|
110 | 110 | import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword; |
111 | 111 | import org.eclipse.jdt.core.dom.ModuleDeclaration; |
112 | 112 | import org.eclipse.jdt.core.dom.Name; |
| 113 | +import org.eclipse.jdt.core.dom.NodeFinder; |
113 | 114 | import org.eclipse.jdt.core.dom.NormalAnnotation; |
114 | 115 | import org.eclipse.jdt.core.dom.NumberLiteral; |
115 | 116 | import org.eclipse.jdt.core.dom.PackageDeclaration; |
|
156 | 157 | import org.eclipse.jdt.core.search.TypeNameMatchRequestor; |
157 | 158 | import org.eclipse.jdt.internal.codeassist.impl.AssistOptions; |
158 | 159 | import org.eclipse.jdt.internal.codeassist.impl.Keywords; |
| 160 | +import org.eclipse.jdt.internal.codeassist.impl.RestrictedIdentifiers; |
159 | 161 | import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; |
160 | 162 | import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner; |
161 | 163 | import org.eclipse.jdt.internal.core.JarPackageFragmentRoot; |
@@ -646,6 +648,8 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour |
646 | 648 | } |
647 | 649 | } else if (this.toComplete instanceof QualifiedName && this.toComplete.getParent() instanceof TagElement tagElement) { |
648 | 650 | context = tagElement; |
| 651 | + } else if (this.toComplete instanceof Modifier && this.toComplete.getParent() instanceof ImportDeclaration) { |
| 652 | + context = this.toComplete.getParent(); |
649 | 653 | } |
650 | 654 | this.prefix = token == null ? new String() : new String(token); |
651 | 655 | if (this.toComplete instanceof MethodInvocation methodInvocation && this.offset == (methodInvocation.getName().getStartPosition() + methodInvocation.getName().getLength()) + 1) { |
@@ -792,9 +796,7 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour |
792 | 796 | // } |
793 | 797 | ITypeBinding typeDeclBinding = typeDecl.resolveBinding(); |
794 | 798 | findOverridableMethods(typeDeclBinding, this.javaProject, context); |
795 | | - if (!isFailedMatch(this.prefix.toCharArray(), Keywords.CLASS)) { |
796 | | - this.requestor.accept(createKeywordProposal(Keywords.CLASS, this.toComplete.getStartPosition(), this.offset)); |
797 | | - } |
| 799 | + suggestClassDeclarationLikeKeywords(); |
798 | 800 | suggestTypeKeywords(true); |
799 | 801 | suggestModifierKeywords(fieldDeclaration.getModifiers()); |
800 | 802 | if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { |
@@ -1563,19 +1565,39 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour |
1563 | 1565 | } |
1564 | 1566 | } |
1565 | 1567 | } |
1566 | | - if (context instanceof ImportDeclaration) { |
| 1568 | + if (context instanceof ImportDeclaration importDeclaration) { |
1567 | 1569 | if (context.getAST().apiLevel() >= AST.JLS23 |
1568 | | - && this.javaProject.getOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, true).equals(JavaCore.ENABLED)) { |
| 1570 | + && this.javaProject.getOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, true).equals(JavaCore.ENABLED) |
| 1571 | + && Modifier.isModule(importDeclaration.getModifiers())) { |
1569 | 1572 | findModules(this.qualifiedPrefix.toCharArray(), this.javaProject, this.assistOptions, Collections.emptySet()); |
1570 | 1573 | suggestDefaultCompletions = false; |
1571 | 1574 | } |
1572 | 1575 | } |
1573 | | - if (context instanceof CompilationUnit unit && |
1574 | | - CharOperation.prefixEquals(completionContext.getToken(), Keywords.PACKAGE) && |
1575 | | - unit.getPackage() == null && |
1576 | | - this.offset <= ((Collection<ASTNode>)unit.imports()).stream().mapToInt(ASTNode::getStartPosition).filter(n -> n >= 0).min().orElse(Integer.MAX_VALUE) && |
1577 | | - this.offset <= ((Collection<ASTNode>)unit.types()).stream().mapToInt(ASTNode::getStartPosition).filter(n -> n >= 0).min().orElse(Integer.MAX_VALUE)) { |
1578 | | - this.requestor.accept(createKeywordProposal(Keywords.PACKAGE, completionContext.getTokenStart(), completionContext.getTokenEnd())); |
| 1576 | + if (context instanceof CompilationUnit unit) { |
| 1577 | + if (CharOperation.prefixEquals(completionContext.getToken(), Keywords.PACKAGE) && |
| 1578 | + unit.getPackage() == null && |
| 1579 | + this.offset <= ((Collection<ASTNode>)unit.imports()).stream().mapToInt(ASTNode::getStartPosition).filter(n -> n >= 0).min().orElse(Integer.MAX_VALUE) && |
| 1580 | + this.offset <= ((Collection<ASTNode>)unit.types()).stream().mapToInt(ASTNode::getStartPosition).filter(n -> n >= 0).min().orElse(Integer.MAX_VALUE)) { |
| 1581 | + this.requestor.accept(createKeywordProposal(Keywords.PACKAGE, completionContext.getTokenStart(), completionContext.getTokenEnd())); |
| 1582 | + } |
| 1583 | + if (CharOperation.prefixEquals(completionContext.getToken(), Keywords.IMPORT) |
| 1584 | + && (unit.getPackage() == null |
| 1585 | + || this.offset >= unit.getPackage().getStartPosition() + unit.getPackage().getLength()) |
| 1586 | + && (unit.types().isEmpty() || this.offset < ((ASTNode)unit.types().get(0)).getStartPosition())) { |
| 1587 | + if (unit.imports().isEmpty()) { |
| 1588 | + this.requestor.accept(createKeywordProposal(Keywords.IMPORT, -1, -1)); |
| 1589 | + } else { |
| 1590 | + for (int i = unit.imports().size() - 1; i >= 0; i--) { |
| 1591 | + ImportDeclaration importDeclaration = (ImportDeclaration)unit.imports().get(i); |
| 1592 | + if (this.offset > importDeclaration.getStartPosition() + importDeclaration.getLength()) { |
| 1593 | + if ((importDeclaration.getFlags() & ASTNode.MALFORMED) == 0) { |
| 1594 | + this.requestor.accept(createKeywordProposal(Keywords.IMPORT, -1, -1)); |
| 1595 | + } |
| 1596 | + break; |
| 1597 | + } |
| 1598 | + } |
| 1599 | + } |
| 1600 | + } |
1579 | 1601 | } |
1580 | 1602 | if (context instanceof MethodRef methodRef) { |
1581 | 1603 | JavadocMethodReferenceParseState state = JavadocMethodReferenceParseState.BEFORE_IDENTIFIER; |
@@ -1879,9 +1901,7 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour |
1879 | 1901 | } |
1880 | 1902 |
|
1881 | 1903 | suggestModifierKeywords(existingModifiers); |
1882 | | - if (!this.isFailedMatch(this.prefix.toCharArray(), Keywords.CLASS)) { |
1883 | | - this.requestor.accept(createKeywordProposal(Keywords.CLASS, -1, -1)); |
1884 | | - } |
| 1904 | + suggestClassDeclarationLikeKeywords(); |
1885 | 1905 | } |
1886 | 1906 | suggestDefaultCompletions = false; |
1887 | 1907 | } |
@@ -2051,6 +2071,23 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour |
2051 | 2071 | } |
2052 | 2072 | } |
2053 | 2073 | } |
| 2074 | + |
| 2075 | + private void suggestClassDeclarationLikeKeywords() { |
| 2076 | + if (!this.isFailedMatch(this.prefix.toCharArray(), Keywords.CLASS)) { |
| 2077 | + this.requestor.accept(createKeywordProposal(Keywords.CLASS, -1, -1)); |
| 2078 | + } |
| 2079 | + if (!this.isFailedMatch(this.prefix.toCharArray(), Keywords.INTERFACE)) { |
| 2080 | + this.requestor.accept(createKeywordProposal(Keywords.INTERFACE, -1, -1)); |
| 2081 | + } |
| 2082 | + if (!this.isFailedMatch(this.prefix.toCharArray(), Keywords.ENUM)) { |
| 2083 | + this.requestor.accept(createKeywordProposal(Keywords.ENUM, -1, -1)); |
| 2084 | + } |
| 2085 | + if (this.unit.getAST().apiLevel() >= AST.JLS14) { |
| 2086 | + if (!this.isFailedMatch(this.prefix.toCharArray(), RestrictedIdentifiers.RECORD)) { |
| 2087 | + this.requestor.accept(createKeywordProposal(RestrictedIdentifiers.RECORD, -1, -1)); |
| 2088 | + } |
| 2089 | + } |
| 2090 | + } |
2054 | 2091 |
|
2055 | 2092 | private void suggestUndeclaredVariableNames(ITypeBinding typeBinding, Set<String> alreadySuggested) { |
2056 | 2093 | ASTNode pastCursor = this.toComplete; |
@@ -2981,7 +3018,22 @@ private void statementLikeKeywords() { |
2981 | 3018 | } |
2982 | 3019 | keywords.add(Keywords.SUPER); |
2983 | 3020 | keywords.add(Keywords.NEW); |
2984 | | - |
| 3021 | + |
| 3022 | + { |
| 3023 | + // instanceof must be preceeded by an expression |
| 3024 | + int instanceofCursor = this.toComplete.getStartPosition(); |
| 3025 | + while (instanceofCursor > 0 && Character.isWhitespace(this.textContent.charAt(instanceofCursor - 1))) { |
| 3026 | + instanceofCursor--; |
| 3027 | + } |
| 3028 | + ASTNode preceedingNode = NodeFinder.perform(this.unit, instanceofCursor, 0); |
| 3029 | + while (preceedingNode != null && !(preceedingNode instanceof Expression)) { |
| 3030 | + preceedingNode = preceedingNode.getParent(); |
| 3031 | + } |
| 3032 | + if (preceedingNode != null) { |
| 3033 | + keywords.add(Keywords.INSTANCEOF); |
| 3034 | + } |
| 3035 | + } |
| 3036 | + |
2985 | 3037 | if (!this.expectedTypes.getExpectedTypes().isEmpty()) { |
2986 | 3038 | keywords.add(Keywords.NULL); |
2987 | 3039 | } |
@@ -3097,8 +3149,17 @@ private void suggestPackages(ASTNode context) { |
3097 | 3149 | context = context.getParent(); |
3098 | 3150 | } |
3099 | 3151 | String prefix = context instanceof Name name ? name.toString() : this.prefix; |
3100 | | - if (prefix != null && !prefix.isBlank()) { |
3101 | | - this.nameEnvironment.findPackages(prefix.toCharArray(), this.nestedEngine); |
| 3152 | + if (prefix != null) { |
| 3153 | + prefix = prefix.replace(FAKE_IDENTIFIER, ""); |
| 3154 | + if (!prefix.isBlank()) { |
| 3155 | + // IMO we should provide our own ISearchRequestor so that we don't have to mess with CompletionEngine internal state |
| 3156 | + // but this hack should hopefully fix the range |
| 3157 | + if (context instanceof Name name) { |
| 3158 | + this.nestedEngine.startPosition = name.getStartPosition(); |
| 3159 | + this.nestedEngine.endPosition = name.getStartPosition() + name.getLength(); |
| 3160 | + } |
| 3161 | + this.nameEnvironment.findPackages(prefix.toCharArray(), this.nestedEngine); |
| 3162 | + } |
3102 | 3163 | } |
3103 | 3164 | } |
3104 | 3165 |
|
|
0 commit comments