From 6a9559c3c9e478e65cbca63c57f836d317f103dc Mon Sep 17 00:00:00 2001 From: David Thompson Date: Fri, 17 Jan 2025 13:50:09 -0500 Subject: [PATCH] [WIP] reuse a cached AST if available Signed-off-by: David Thompson --- .../core/dom/DOMCompletionEngineProvider.java | 4 +-- .../javac/completion/DOMCompletionEngine.java | 25 +++++++++++++------ .../internal/codeassist/CompletionEngine.java | 6 ++++- .../codeassist}/ICompletionEngine.java | 7 +++--- .../ICompletionEngineProvider.java | 5 +++- .../jdt/internal/core/CompilationUnit.java | 19 ++++++++------ .../CompletionEngineProviderDiscovery.java | 2 +- .../eclipse/jdt/internal/core/Openable.java | 4 ++- 8 files changed, 48 insertions(+), 24 deletions(-) rename org.eclipse.jdt.core/codeassist/org/eclipse/jdt/{core => internal/codeassist}/ICompletionEngine.java (80%) rename org.eclipse.jdt.core/codeassist/org/eclipse/jdt/{core => internal/codeassist}/ICompletionEngineProvider.java (88%) diff --git a/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/core/dom/DOMCompletionEngineProvider.java b/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/core/dom/DOMCompletionEngineProvider.java index 595904cc35a..5125b0dd9c2 100644 --- a/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/core/dom/DOMCompletionEngineProvider.java +++ b/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/core/dom/DOMCompletionEngineProvider.java @@ -14,10 +14,10 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.CompletionRequestor; -import org.eclipse.jdt.core.ICompletionEngine; -import org.eclipse.jdt.core.ICompletionEngineProvider; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.WorkingCopyOwner; +import org.eclipse.jdt.internal.codeassist.ICompletionEngine; +import org.eclipse.jdt.internal.codeassist.ICompletionEngineProvider; import org.eclipse.jdt.internal.core.SearchableEnvironment; import org.eclipse.jdt.internal.javac.completion.DOMCompletionEngine; diff --git a/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/completion/DOMCompletionEngine.java b/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/completion/DOMCompletionEngine.java index a3a664d1199..9abeb2f99a1 100644 --- a/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/completion/DOMCompletionEngine.java +++ b/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/completion/DOMCompletionEngine.java @@ -41,7 +41,6 @@ import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.IAnnotation; import org.eclipse.jdt.core.ICompilationUnit; -import org.eclipse.jdt.core.ICompletionEngine; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; @@ -93,7 +92,6 @@ import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.MethodRef; import org.eclipse.jdt.core.dom.Modifier; -import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword; import org.eclipse.jdt.core.dom.ModuleDeclaration; import org.eclipse.jdt.core.dom.Name; import org.eclipse.jdt.core.dom.NameQualifiedType; @@ -125,6 +123,7 @@ import org.eclipse.jdt.core.dom.VariableDeclaration; import org.eclipse.jdt.core.dom.VariableDeclarationFragment; import org.eclipse.jdt.core.dom.VariableDeclarationStatement; +import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword; import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants; import org.eclipse.jdt.core.search.IJavaSearchConstants; import org.eclipse.jdt.core.search.SearchEngine; @@ -133,6 +132,7 @@ import org.eclipse.jdt.internal.codeassist.CompletionEngine; import org.eclipse.jdt.internal.codeassist.DOMCodeSelector; import org.eclipse.jdt.internal.codeassist.ExpectedTypes; +import org.eclipse.jdt.internal.codeassist.ICompletionEngine; import org.eclipse.jdt.internal.codeassist.InternalCompletionProposal; import org.eclipse.jdt.internal.codeassist.RelevanceConstants; import org.eclipse.jdt.internal.codeassist.impl.AssistOptions; @@ -424,29 +424,40 @@ private static CompilationUnit getCompletionAST(char[] content, char[] unitName, } @Override - public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit, int completionPosition, int ignored, ITypeRoot root) { + public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit, int completionPosition, ITypeRoot root) { if (this.monitor != null) { this.monitor.beginTask(Messages.engine_completing, IProgressMonitor.UNKNOWN); } this.requestor.beginReporting(); - + this.modelUnit = root; if (modelUnit != null) { try { this.textContent = new String(this.modelUnit.getBuffer().getCharacters()); } catch (JavaModelException e) { + this.textContent = new String(sourceUnit.getContents()); ILog.get().error("unable to access buffer for completion", e); //$NON-NLS-1$ } this.offset = completionPosition; - this.unit = getCompletionAST(this.modelUnit, root.getJavaProject(), this.workingCopyOwner, completionPosition); + if (modelUnit instanceof org.eclipse.jdt.internal.core.CompilationUnit modelCU) { + try { + this.unit = modelCU.getOrBuildAST(this.workingCopyOwner, completionPosition); + } catch (JavaModelException e) { + // do nothing + } + } + if (this.unit == null) { + this.unit = getCompletionAST(this.modelUnit, root.getJavaProject(), this.workingCopyOwner, completionPosition); + } if (this.unit == null) { return; } } else { - // uh oh this.textContent = new String(sourceUnit.getContents()); this.offset = completionPosition; - this.unit = getCompletionAST(sourceUnit.getContents(), sourceUnit.getFileName(), this.javaProject, this.workingCopyOwner, completionPosition); + if (this.unit == null) { + this.unit = getCompletionAST(sourceUnit.getContents(), sourceUnit.getFileName(), this.javaProject, this.workingCopyOwner, completionPosition); + } } diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java index 368143c5ffb..6e392586790 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java @@ -1938,6 +1938,11 @@ private boolean complete( return true; } + @Override + public void complete(ICompilationUnit sourceUnit, int completionPosition, ITypeRoot root) { + complete(sourceUnit, completionPosition, 0, root); + } + /** * Ask the engine to compute a completion at the specified position * of the given compilation unit. @@ -1952,7 +1957,6 @@ private boolean complete( * a position in the source where the completion is taking place. * This position is relative to the source provided. */ - @Override public void complete(ICompilationUnit sourceUnit, int completionPosition, int pos, ITypeRoot root) { if(DEBUG) { diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/core/ICompletionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ICompletionEngine.java similarity index 80% rename from org.eclipse.jdt.core/codeassist/org/eclipse/jdt/core/ICompletionEngine.java rename to org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ICompletionEngine.java index b91c4068a02..4be66995a0e 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/core/ICompletionEngine.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ICompletionEngine.java @@ -8,8 +8,9 @@ * * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -package org.eclipse.jdt.core; +package org.eclipse.jdt.internal.codeassist; +import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; /** @@ -21,10 +22,10 @@ public interface ICompletionEngine { * Provide completion items based on the given source unit and completion position to the configured requestor. * * @param sourceUnit the compilation unit for which completion was triggered + * @param ast the AST of the compilation unit to use for completion. can be null, in which case the completion engine is expected to build it * @param completionPosition the position that completion was triggered at - * @param pos should always be 0, don't set it to anything else * @param root the type root for which completion was triggered */ - public void complete(ICompilationUnit sourceUnit, int completionPosition, int pos, ITypeRoot root); + public void complete(ICompilationUnit sourceUnit, int completionPosition, ITypeRoot root); } diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/core/ICompletionEngineProvider.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ICompletionEngineProvider.java similarity index 88% rename from org.eclipse.jdt.core/codeassist/org/eclipse/jdt/core/ICompletionEngineProvider.java rename to org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ICompletionEngineProvider.java index f3085b63ae2..0c114f2e335 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/core/ICompletionEngineProvider.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ICompletionEngineProvider.java @@ -8,10 +8,13 @@ * * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -package org.eclipse.jdt.core; +package org.eclipse.jdt.internal.codeassist; import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.core.CompletionRequestor; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.WorkingCopyOwner; import org.eclipse.jdt.internal.core.SearchableEnvironment; /** diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java index 45d367433a9..3192fab812b 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java @@ -448,14 +448,10 @@ public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyO @Override public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner workingCopyOwner, IProgressMonitor monitor) throws JavaModelException { - codeComplete( - this, + + codeComplete(this, isWorkingCopy() ? (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) getOriginalElement() : this, - offset, - requestor, - workingCopyOwner, - this, - monitor); + offset, requestor, workingCopyOwner, this, monitor); } /** @@ -477,12 +473,14 @@ public IJavaElement[] codeSelect(int offset, int length, WorkingCopyOwner workin } } -public org.eclipse.jdt.core.dom.CompilationUnit getOrBuildAST(WorkingCopyOwner workingCopyOwner) throws JavaModelException { +public org.eclipse.jdt.core.dom.CompilationUnit getOrBuildAST(WorkingCopyOwner workingCopyOwner, int focalPosition) throws JavaModelException { if (this.ast != null) { return this.ast; } Map options = getOptions(true); ASTParser parser = ASTParser.newParser(new AST(options).apiLevel()); // go through AST constructor to convert options to apiLevel + // but we should probably instead just use the latest Java version + // supported by the compiler parser.setWorkingCopyOwner(workingCopyOwner); parser.setSource(this); // greedily enable everything assuming the AST will be used extensively for edition @@ -490,7 +488,12 @@ public org.eclipse.jdt.core.dom.CompilationUnit getOrBuildAST(WorkingCopyOwner w parser.setStatementsRecovery(true); parser.setBindingsRecovery(true); parser.setCompilerOptions(options); + parser.setFocalPosition(focalPosition); if (parser.createAST(null) instanceof org.eclipse.jdt.core.dom.CompilationUnit newAST) { + if (focalPosition >= 0) { + // do not store + return newAST; + } this.ast = newAST; } return this.ast; diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompletionEngineProviderDiscovery.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompletionEngineProviderDiscovery.java index 677be0fc8ef..aebeae887c4 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompletionEngineProviderDiscovery.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompletionEngineProviderDiscovery.java @@ -17,9 +17,9 @@ import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.Platform; -import org.eclipse.jdt.core.ICompletionEngineProvider; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.internal.codeassist.CompletionEngine; +import org.eclipse.jdt.internal.codeassist.ICompletionEngineProvider; class CompletionEngineProviderDiscovery { private static final String SELECTED_SYSPROP = "ICompletionEngineProvider"; //$NON-NLS-1$ diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java index 4bc25a2c931..072321ceb2f 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java @@ -24,6 +24,8 @@ import org.eclipse.core.runtime.PerformanceStats; import org.eclipse.jdt.core.*; import org.eclipse.jdt.internal.codeassist.CompletionEngine; +import org.eclipse.jdt.internal.codeassist.ICompletionEngine; +import org.eclipse.jdt.internal.codeassist.ICompletionEngineProvider; import org.eclipse.jdt.internal.codeassist.SelectionEngine; import org.eclipse.jdt.internal.compiler.env.IElementInfo; import org.eclipse.jdt.internal.core.util.Util; @@ -134,7 +136,7 @@ protected void codeComplete( // code complete ICompletionEngineProvider completionEngineProvider = CompletionEngineProviderDiscovery.getInstance(); ICompletionEngine completionEngine = completionEngineProvider.getCompletionEngine(environment, requestor, project.getOptions(true), project, owner, monitor); - completionEngine.complete(cu, position, 0, typeRoot); + completionEngine.complete(cu, position, typeRoot); if(performanceStats != null) { performanceStats.endRun();