4545import org .eclipse .jdt .core .IField ;
4646import org .eclipse .jdt .core .IJavaElement ;
4747import org .eclipse .jdt .core .IJavaProject ;
48+ import org .eclipse .jdt .core .IMember ;
4849import org .eclipse .jdt .core .IMemberValuePair ;
4950import org .eclipse .jdt .core .IMethod ;
5051import org .eclipse .jdt .core .IModuleDescription ;
9596import org .eclipse .jdt .core .dom .MethodInvocation ;
9697import org .eclipse .jdt .core .dom .MethodRef ;
9798import org .eclipse .jdt .core .dom .Modifier ;
98- import org .eclipse .jdt .core .dom .Modifier .ModifierKeyword ;
9999import org .eclipse .jdt .core .dom .ModuleDeclaration ;
100100import org .eclipse .jdt .core .dom .Name ;
101101import org .eclipse .jdt .core .dom .NormalAnnotation ;
129129import org .eclipse .jdt .core .dom .VariableDeclarationExpression ;
130130import org .eclipse .jdt .core .dom .VariableDeclarationFragment ;
131131import org .eclipse .jdt .core .dom .VariableDeclarationStatement ;
132+ import org .eclipse .jdt .core .dom .Modifier .ModifierKeyword ;
132133import org .eclipse .jdt .core .formatter .DefaultCodeFormatterConstants ;
133134import org .eclipse .jdt .core .search .IJavaSearchConstants ;
134135import org .eclipse .jdt .core .search .SearchEngine ;
135136import org .eclipse .jdt .core .search .SearchPattern ;
137+ import org .eclipse .jdt .core .search .TypeNameMatch ;
136138import org .eclipse .jdt .core .search .TypeNameMatchRequestor ;
137139import org .eclipse .jdt .internal .codeassist .impl .AssistOptions ;
138140import org .eclipse .jdt .internal .codeassist .impl .Keywords ;
@@ -562,8 +564,13 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
562564 Expression fieldAccessExpr = fieldAccess .getExpression ();
563565 ITypeBinding fieldAccessType = fieldAccessExpr .resolveTypeBinding ();
564566 if (fieldAccessType != null ) {
565- processMembers (fieldAccess , fieldAccessExpr .resolveTypeBinding (), specificCompletionBindings , false );
566- publishFromScope (specificCompletionBindings );
567+ if (!fieldAccessType .isRecovered ()) {
568+ processMembers (fieldAccess , fieldAccessExpr .resolveTypeBinding (), specificCompletionBindings , false );
569+ publishFromScope (specificCompletionBindings );
570+ } else if (fieldAccessExpr instanceof MethodInvocation method &&
571+ this .unit .findDeclaringNode (method .resolveMethodBinding ()) instanceof MethodDeclaration decl ) {
572+ completeMissingType (decl .getReturnType2 ());
573+ }
567574 } else if (DOMCompletionUtil .findParent (fieldAccessExpr , new int []{ ASTNode .METHOD_INVOCATION }) == null ) {
568575 String packageName = "" ; //$NON-NLS-1$
569576 if (fieldAccess .getExpression () instanceof FieldAccess parentFieldAccess
@@ -989,6 +996,26 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
989996 }
990997 } else if (qualifiedNameBinding instanceof IVariableBinding variableBinding ) {
991998 ITypeBinding typeBinding = variableBinding .getType ();
999+ if (typeBinding == null && unit .findDeclaringNode (variableBinding ) instanceof VariableDeclaration decl ) {
1000+ Type type = null ;
1001+ if (decl instanceof SingleVariableDeclaration single ) {
1002+ type = single .getType ();
1003+ } else if (decl instanceof VariableDeclarationFragment fragment ) {
1004+ if (fragment .getParent () instanceof FieldDeclaration field ) {
1005+ type = field .getType ();
1006+ } else if (fragment .getParent () instanceof VariableDeclarationExpression expr ) {
1007+ type = expr .getType ();
1008+ } else if (fragment .getParent () instanceof VariableDeclarationStatement stmt ) {
1009+ type = stmt .getType ();
1010+ }
1011+ }
1012+ if (type != null ) {
1013+ typeBinding = type .resolveBinding ();
1014+ }
1015+ if (typeBinding == null || typeBinding .isRecovered ()) {
1016+ completeMissingType (type );
1017+ }
1018+ }
9921019 processMembers (qualifiedName , typeBinding , specificCompletionBindings , false );
9931020 publishFromScope (specificCompletionBindings );
9941021 suggestDefaultCompletions = false ;
@@ -1519,6 +1546,8 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
15191546 }
15201547
15211548 checkCancelled ();
1549+ } catch (JavaModelException e ) {
1550+ ILog .get ().error (e .getMessage (), e );
15221551 } finally {
15231552 this .requestor .endReporting ();
15241553 if (this .monitor != null ) {
@@ -1547,6 +1576,27 @@ private boolean isTypeInVariableDeclaration(ASTNode context) {
15471576 return false ;
15481577 }
15491578
1579+ private void completeMissingType (Type type ) throws JavaModelException {
1580+ if (type instanceof ParameterizedType parameterized ) {
1581+ type = parameterized .getType ();
1582+ }
1583+ final Type finalType = type ;
1584+ var scope = SearchEngine .createJavaSearchScope (new IJavaElement [] { this .javaProject });
1585+ new SearchEngine (this .workingCopyOwner ).searchAllTypeNames (null , SearchPattern .R_PREFIX_MATCH , type .toString ().toCharArray (), SearchPattern .R_EXACT_MATCH , IJavaSearchConstants .TYPE , scope , new TypeNameMatchRequestor () {
1586+ @ Override
1587+ public void acceptTypeNameMatch (TypeNameMatch match ) {
1588+ processMembers (match .getType ()).stream ()
1589+ .map (member -> {
1590+ CompletionProposal typeProposal = toProposal (match .getType ());
1591+ typeProposal .setReplaceRange (finalType .getStartPosition (), finalType .getStartPosition () + finalType .getLength ());
1592+ typeProposal .setRelevance (member .getRelevance ());
1593+ member .setRequiredProposals (new CompletionProposal [] { typeProposal });
1594+ return member ;
1595+ }).forEach (DOMCompletionEngine .this .requestor ::accept );
1596+ }
1597+ }, IJavaSearchConstants .WAIT_UNTIL_READY_TO_SEARCH , monitor );
1598+ }
1599+
15501600 private void suggestSuperConstructors () {
15511601 if (this .requestor .isIgnored (CompletionProposal .METHOD_REF ) || this .requestor .isIgnored (CompletionProposal .CONSTRUCTOR_INVOCATION )) {
15521602 return ;
@@ -2443,6 +2493,21 @@ private void processMembers(ITypeBinding typeBinding, Bindings scope,
24432493 }
24442494 }
24452495
2496+ private List <CompletionProposal > processMembers (IType type ) {
2497+ IJavaElement [] children ;
2498+ try {
2499+ children = type .getChildren ();
2500+ } catch (JavaModelException ex ) {
2501+ ILog .get ().error (ex .getMessage (), ex );
2502+ children = new IJavaElement [0 ];
2503+ }
2504+ return Arrays .stream (children )
2505+ .filter (element -> element .getElementType () == IJavaElement .FIELD || element .getElementType () == IJavaElement .METHOD )
2506+ .filter (this ::isVisible )
2507+ .map (this ::toProposal )
2508+ .toList ();
2509+ }
2510+
24462511 private String getSignature (IMethodBinding method ) {
24472512 return method .getName () + '(' +
24482513 Arrays .stream (method .getParameterTypes ()).map (ITypeBinding ::getName ).collect (Collectors .joining ("," ))
@@ -2904,7 +2969,7 @@ private CompletionProposal toProposal(IType type) {
29042969 if (packageDecl != null ) {
29052970 packageName = packageDecl .getName ().toString ();
29062971 }
2907- if (!packageName .equals (type .getPackageFragment ().getElementName ())) {
2972+ if (!packageName .equals (type .getPackageFragment ().getElementName ()) && ! new String ( res . getCompletion ()). equals ( type . getFullyQualifiedName ()) ) {
29082973 // propose importing the type
29092974 res .setRequiredProposals (new CompletionProposal [] { toImportProposal (simpleName , signature , type .getPackageFragment ().getElementName ().toCharArray ()) });
29102975 }
@@ -2931,7 +2996,58 @@ private CompletionProposal toSuperConstructorProposal(IMethodBinding superConstr
29312996
29322997 return res ;
29332998 }
2934-
2999+
3000+ private CompletionProposal toProposal (IJavaElement element ) {
3001+ if (element instanceof IType type ) {
3002+ return toProposal (type );
3003+ }
3004+ DOMInternalCompletionProposal res = null ;
3005+ IType parentType = (IType )element .getAncestor (IJavaElement .TYPE );
3006+ if (element instanceof IField field ) {
3007+ res = createProposal (CompletionProposal .FIELD_REF );
3008+ res .setName (field .getElementName ().toCharArray ());
3009+ res .setCompletion (field .getElementName ().toCharArray ());
3010+ setRange (res );
3011+ res .setRelevance (RelevanceConstants .R_DEFAULT +
3012+ RelevanceConstants .R_RESOLVED +
3013+ RelevanceConstants .R_INTERESTING +
3014+ RelevanceConstants .R_NON_RESTRICTED );
3015+ }
3016+ if (element instanceof IMethod method ) {
3017+ res = createProposal (CompletionProposal .METHOD_REF );
3018+ try {
3019+ res .setSignature (method .getSignature ().toCharArray ());
3020+ res .setParameterNames (Arrays .stream (method .getParameterNames ()).map (String ::toCharArray ).toArray (char [][]::new ));
3021+ res .setParameterTypeNames (Arrays .stream (method .getParameterTypes ()).map (String ::toCharArray ).toArray (char [][]::new ));
3022+ } catch (JavaModelException ex ) {
3023+ ILog .get ().error (ex .getMessage (), ex );
3024+ }
3025+ res .setName (method .getElementName ().toCharArray ());
3026+ res .setCompletion ((method .getElementName () + "()" ).toCharArray ());
3027+ setRange (res );
3028+ res .setRelevance (RelevanceConstants .R_DEFAULT +
3029+ RelevanceConstants .R_RESOLVED +
3030+ RelevanceConstants .R_INTERESTING +
3031+ RelevanceConstants .R_CASE +
3032+ RelevanceConstants .R_NON_STATIC +
3033+ RelevanceConstants .R_NON_RESTRICTED +
3034+ RelevanceConstants .R_NO_PROBLEMS );
3035+ }
3036+ if (res != null ) {
3037+ if (element instanceof IMember member ) {
3038+ try {
3039+ res .setFlags (member .getFlags ());
3040+ } catch (JavaModelException ex ) {
3041+ ILog .get ().error (ex .getMessage (), ex );
3042+ }
3043+ }
3044+ res .setDeclarationSignature (SignatureUtils .createSignature (parentType ).toCharArray ());
3045+ res .setDeclarationTypeName (parentType .getFullyQualifiedName ().toCharArray ());
3046+ res .setDeclarationPackageName (element .getAncestor (IJavaElement .PACKAGE_FRAGMENT ).getElementName ().toCharArray ());
3047+ }
3048+ return res ;
3049+ }
3050+
29353051 private CompletionProposal toNewMethodProposal (ITypeBinding parentType , String newMethodName ) {
29363052 DOMInternalCompletionProposal res = createProposal (CompletionProposal .POTENTIAL_METHOD_DECLARATION );
29373053 res .setDeclarationSignature (DOMCompletionEngineBuilder .getSignature (parentType ));
@@ -3682,6 +3798,51 @@ private boolean isVisible(IBinding binding) {
36823798 return declaringClass .getPackage ().isEqualTo (DOMCompletionUtil .findParentTypeDeclaration (this .toComplete ).resolveBinding ().getPackage ());
36833799 }
36843800
3801+ private boolean isVisible (IJavaElement element ) {
3802+ if (element == null ) {
3803+ return false ;
3804+ }
3805+ int flags ;
3806+ try {
3807+ flags = element instanceof IType type ? type .getFlags () :
3808+ element instanceof IMethod method ? method .getFlags () :
3809+ element instanceof IField field ? field .getFlags () :
3810+ 0 ;
3811+ } catch (JavaModelException ex ) {
3812+ ILog .get ().error (ex .getMessage (), ex );
3813+ flags = 0 ;
3814+ }
3815+ if (element instanceof IType type ) {
3816+ if (Modifier .isPublic (flags )) {
3817+ return true ;
3818+ }
3819+ if (Modifier .isPrivate (flags )) {
3820+ return type .equals (this .toComplete );
3821+ }
3822+ if (Modifier .isProtected (flags )) {
3823+ // TODO
3824+ }
3825+ return Objects .equals (type .getPackageFragment ().getElementName (), this .unit .getPackage ().getName ().toString ());
3826+ } else {
3827+ IType type = element instanceof IMethod method ? method .getDeclaringType () :
3828+ element instanceof IField field ? field .getDeclaringType () :
3829+ null ;
3830+ if (!isVisible (type )) {
3831+ return false ;
3832+ }
3833+ if (Modifier .isPublic (flags )) {
3834+ return true ;
3835+ }
3836+ if (Modifier .isPrivate (flags )) {
3837+ return type .equals (this .toComplete );
3838+ }
3839+ if (Modifier .isProtected (flags )) {
3840+ // TODO
3841+ }
3842+ return Objects .equals (type .getPackageFragment ().getElementName (), this .unit .getPackage ().getName ().toString ());
3843+ }
3844+ }
3845+
36853846 private ITypeBinding getDeclaringClass (IBinding binding ) {
36863847 return binding instanceof ITypeBinding typeBinding ? typeBinding :
36873848 binding instanceof IMethodBinding methodBinding ? methodBinding .getDeclaringClass () :
0 commit comments