Skip to content

Commit d49a773

Browse files
datho7561Rob Stryker
authored andcommitted
Filter types based on access level
- suggest types in more cases (do not shut off type name completion if there are no expected types) - do not suggest types when completing type arguments for a non-generic type (or if there are eg. 2 params and 3 args) - do not suggest types from the default package in classes not in the default package - do not suggest private inner classes - only suggest package private classes when in the same package - only suggest protected inner classes when the class the cursor is in inherits from the class containing the protected inner class Signed-off-by: David Thompson <[email protected]>
1 parent 1867ad7 commit d49a773

File tree

1 file changed

+77
-5
lines changed

1 file changed

+77
-5
lines changed

org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/codeassist/DOMCompletionEngine.java

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
import org.eclipse.jdt.core.dom.NormalAnnotation;
100100
import org.eclipse.jdt.core.dom.NumberLiteral;
101101
import org.eclipse.jdt.core.dom.PackageDeclaration;
102+
import org.eclipse.jdt.core.dom.ParameterizedType;
102103
import org.eclipse.jdt.core.dom.PrefixExpression;
103104
import org.eclipse.jdt.core.dom.PrimitiveType;
104105
import org.eclipse.jdt.core.dom.QualifiedName;
@@ -858,7 +859,10 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
858859
}
859860
if (context instanceof QualifiedName qualifiedName) {
860861
ImportDeclaration importDecl = (ImportDeclaration)DOMCompletionUtil.findParent(context, new int[] { ASTNode.IMPORT_DECLARATION });
861-
if (importDecl != null) {
862+
if (isParameterInNonParameterizedType(context)) {
863+
// do not complete
864+
suggestDefaultCompletions = false;
865+
} else if (importDecl != null) {
862866
if(importDecl.getAST().apiLevel() >= AST.JLS23
863867
&& this.javaProject.getOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, true).equals(JavaCore.ENABLED)
864868
&& importDecl.modifiers().stream().anyMatch(node -> node instanceof Modifier modifier && modifier.getKeyword() == ModifierKeyword.MODULE_KEYWORD)) {
@@ -1405,6 +1409,9 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
14051409
}
14061410
}
14071411
}
1412+
if (isParameterInNonParameterizedType(context)) {
1413+
suggestDefaultCompletions = false;
1414+
}
14081415

14091416
// check for accessible bindings to potentially turn into completions.
14101417
// currently, this is always run, even when not using the default completion,
@@ -1438,14 +1445,24 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
14381445
}
14391446
publishFromScope(defaultCompletionBindings);
14401447
if (!completeAfter.isBlank()) {
1448+
String currentPackage = this.unit.getPackage() == null ? "" : this.unit.getPackage().getName().toString();
1449+
AbstractTypeDeclaration typeDecl = DOMCompletionUtil.findParentTypeDeclaration(context);
1450+
ITypeBinding currentTypeBinding = typeDecl == null ? null : typeDecl.resolveBinding();
14411451
final int typeMatchRule = this.toComplete.getParent() instanceof Annotation
14421452
? IJavaSearchConstants.ANNOTATION_TYPE
14431453
: IJavaSearchConstants.TYPE;
1444-
if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)
1445-
&& (completionContext.getExpectedTypesSignatures() != null || extendsOrImplementsInfo != null)) {
1454+
if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
14461455
findTypes(completeAfter, typeMatchRule, null)
1456+
.filter(type -> filterTypeBasedOnAccess(type, currentPackage, currentTypeBinding))
14471457
.filter(type -> {
1448-
return defaultCompletionBindings.all().map(typeBinding -> typeBinding.getJavaElement()).noneMatch(elt -> type.equals(elt));
1458+
for (var scrapedBinding : defaultCompletionBindings.all().toList()) {
1459+
if (scrapedBinding instanceof ITypeBinding scrapedTypeBinding) {
1460+
if (type.equals(scrapedTypeBinding.getJavaElement()) || type.getKey().equals(scrapedTypeBinding.getKey())) {
1461+
return false;
1462+
}
1463+
}
1464+
}
1465+
return true;
14491466
})
14501467
.filter(type -> this.pattern.matchesName(this.prefix.toCharArray(),
14511468
type.getElementName().toCharArray()))
@@ -1470,6 +1487,58 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
14701487
}
14711488
}
14721489

1490+
/**
1491+
* Returns true if the given type can be accessed from the given context
1492+
*
1493+
* @param type the type that you're trying to access
1494+
* @param currentPackage the package that you're in
1495+
* @param currentTypeBinding the binding of the type that you're currently in, can be null
1496+
* @return true if the given type can be accessed from the given context
1497+
*/
1498+
private boolean filterTypeBasedOnAccess(IType type, String currentPackage, ITypeBinding currentTypeBinding) {
1499+
String typePackage = type.getAncestor(IJavaElement.PACKAGE_FRAGMENT).getElementName();
1500+
// can only access classes in the default package from the default package
1501+
if (!currentPackage.isEmpty() && typePackage.isEmpty()) {
1502+
return false;
1503+
}
1504+
try {
1505+
int flags = type.getFlags();
1506+
if ((flags & (Flags.AccPublic | Flags.AccPrivate | Flags.AccProtected)) == 0) {
1507+
return currentPackage.equals(typePackage);
1508+
}
1509+
if ((flags & Flags.AccPublic) != 0) {
1510+
return true;
1511+
}
1512+
if ((flags & Flags.AccProtected) != 0) {
1513+
// protected means `type` is an inner class
1514+
if (currentTypeBinding == null) {
1515+
return false;
1516+
}
1517+
return findInSupers(currentTypeBinding, ((IType)type.getParent()).getKey());
1518+
}
1519+
// private inner class
1520+
return false;
1521+
} catch (JavaModelException e) {
1522+
return true;
1523+
}
1524+
}
1525+
1526+
private boolean isParameterInNonParameterizedType(ASTNode context) {
1527+
if (DOMCompletionUtil.findParent(context, new int[] { ASTNode.PARAMETERIZED_TYPE }) != null) {
1528+
ASTNode cursor1 = context;
1529+
ASTNode cursor2 = context.getParent();
1530+
while (!(cursor2 instanceof ParameterizedType paramType)) {
1531+
cursor1 = cursor2;
1532+
cursor2 = cursor2.getParent();
1533+
}
1534+
ITypeBinding paramTypeBinding = paramType.resolveBinding().getTypeDeclaration();
1535+
if (paramTypeBinding.getTypeParameters().length <= paramType.typeArguments().indexOf(cursor1)) {
1536+
return true;
1537+
}
1538+
}
1539+
return false;
1540+
}
1541+
14731542
private void suggestAccessibleConstructorsForType(ITypeBinding typeBinding) {
14741543
ITypeBinding parentTypeBinding = DOMCompletionUtil.findParentTypeDeclaration(this.toComplete).resolveBinding();
14751544
Stream.of(typeBinding.getDeclaredMethods()) //
@@ -1825,9 +1894,12 @@ private void suggestTypesInPackage(String packageName) {
18251894
if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
18261895
List<IType> foundTypes = findTypes(this.prefix, packageName).toList();
18271896
ExtendsOrImplementsInfo extendsOrImplementsInfo = isInExtendsOrImplements(this.toComplete);
1897+
String currentPackage = this.unit.getPackage() == null ? "" : this.unit.getPackage().getName().toString();
1898+
AbstractTypeDeclaration typeDecl = DOMCompletionUtil.findParentTypeDeclaration(this.toComplete);
1899+
ITypeBinding currentTypeBinding = typeDecl == null ? null : typeDecl.resolveBinding();
18281900
for (IType foundType : foundTypes) {
18291901
if (this.pattern.matchesName(this.prefix.toCharArray(), foundType.getElementName().toCharArray())) {
1830-
if (filterBasedOnExtendsOrImplementsInfo(foundType, extendsOrImplementsInfo)) {
1902+
if (filterBasedOnExtendsOrImplementsInfo(foundType, extendsOrImplementsInfo) && filterTypeBasedOnAccess(foundType, currentPackage, currentTypeBinding)) {
18311903
this.requestor.accept(this.toProposal(foundType));
18321904
}
18331905
}

0 commit comments

Comments
 (0)