@@ -4812,8 +4812,184 @@ private boolean staticOnly() {
48124812 return false ;
48134813 }
48144814
4815- private CompletionProposal toProposal (TypeNameMatch typeNameMatch ) {
4816- return toProposal (typeNameMatch .getType (), typeNameMatch .getAccessibility (), typeNameMatch .getModifiers ());
4815+ /// In this method, we avoid retrieving the IType, because most of IType methods require re-parsing the source
4816+ private CompletionProposal toProposal (TypeNameMatch type ) {
4817+ DOMInternalCompletionProposal res = createProposal (CompletionProposal .TYPE_REF );
4818+ char [] simpleName = type .getSimpleTypeName ().toCharArray ();
4819+ char [] signature = Signature .createTypeSignature (type .getFullyQualifiedName (), true ).toCharArray ();
4820+ res .setSignature (signature );
4821+ res .setDeclarationSignature (type .getPackageName ().toCharArray ());
4822+
4823+ // set completion, considering nested types
4824+ StringBuilder completion = new StringBuilder ();
4825+ if (completionContext .getCurrentTypeBinding () != null
4826+ && completionContext .getCurrentTypeBinding ().getJavaElement () != null
4827+ && type .getFullyQualifiedName ().equals (((IType )completionContext .getCurrentTypeBinding ().getJavaElement ()).getFullyQualifiedName ())) {
4828+ completion .insert (0 , type .getSimpleTypeName ());
4829+ } else {
4830+ completion .insert (0 , type .getFullyQualifiedName ());
4831+ // ASTNode currentName = this.toComplete instanceof QualifiedName qn && FAKE_IDENTIFIER.equals(qn.getName().toString()) ? qn.getName() : this.toComplete instanceof Name ? this.toComplete : null;
4832+ // while (cursor instanceof IType currentType && (completion.isEmpty() || currentName == null || (!Objects.equals(currentName.toString(), currentType.getElementName()) && !Objects.equals(currentName.toString(), currentType.getFullyQualifiedName())))) {
4833+ // if (!completion.isEmpty()) {
4834+ // completion.insert(0, '.');
4835+ // }
4836+ // completion.insert(0, cursor.getElementName());
4837+ // cursor = cursor.getParent();
4838+ // if (currentName != null && currentName.getLocationInParent() == QualifiedName.NAME_PROPERTY) {
4839+ // currentName = ((QualifiedName)currentName.getParent()).getQualifier();
4840+ // } else {
4841+ // currentName = null;
4842+ // }
4843+ // }
4844+ }
4845+
4846+ boolean isMember = false ;
4847+ // try {
4848+ // isMember = type.isMember();
4849+ // } catch (JavaModelException e) {
4850+ // // do nothing
4851+ // }
4852+ Javadoc javadoc = (Javadoc ) DOMCompletionUtils .findParent (this .toComplete , new int [] { ASTNode .JAVADOC });
4853+ ASTNode parentTypeDeclaration = DOMCompletionUtils .findParentTypeDeclaration (this .toComplete );
4854+ if (parentTypeDeclaration != null || javadoc != null ) {
4855+ String fullTypeName = type .getFullyQualifiedName ();
4856+ boolean inImports = ((List <ImportDeclaration >)this .unit .imports ()).stream ().anyMatch (improt -> fullTypeName .equals (improt .getName ().toString ()));
4857+ boolean isInJavaLang = type .getFullyQualifiedName ().startsWith ("java.lang." ) && !type .getFullyQualifiedName ().substring ("java.lang." .length ()).contains ("." );
4858+ IPackageBinding currentPackageBinding = completionContext .getCurrentTypeBinding () == null ? null : completionContext .getCurrentTypeBinding ().getPackage ();
4859+ // TODO: what about qualified references to inner classes?
4860+ if (!type .getPackageName ().isEmpty () && (currentPackageBinding == null
4861+ || (this .qualifiedPrefix .startsWith (type .getPackageName ()) && javadoc != null )
4862+ || ((!type .getPackageName ().equals (currentPackageBinding .getName ()) || (isMember && this .qualifiedPrefix .equals (this .prefix ) && !type .getFullyQualifiedName ().equals (this .modelUnit )))
4863+ && !type .getPackageName ().equals ("java.lang" ))) && !inImports && !isInJavaLang ) { //$NON-NLS-1$
4864+ completion .insert (0 , '.' );
4865+ completion .insert (0 , type .getPackageName ());
4866+ }
4867+ } else {
4868+ // in imports list
4869+ int lastOffset = this .toComplete .getStartPosition () + this .toComplete .getLength ();
4870+ if (lastOffset >= this .textContent .length () || this .textContent .charAt (lastOffset ) != ';' ) {
4871+ completion .append (';' );
4872+ }
4873+ }
4874+ res .setCompletion (completion .toString ().toCharArray ());
4875+
4876+ if (this .toComplete instanceof FieldAccess || this .prefix .isEmpty ()) {
4877+ res .setReplaceRange (this .offset , this .offset );
4878+ } else if (this .completionContext .isInJavadoc ()) {
4879+ if (this .qualifiedPrefix .equals (this .prefix )) {
4880+ setRange (res );
4881+ } else {
4882+ setQualifiedRange (res );
4883+ }
4884+ } else if (this .toComplete instanceof MarkerAnnotation ) {
4885+ res .setReplaceRange (this .toComplete .getStartPosition () + 1 , this .toComplete .getStartPosition () + this .toComplete .getLength ());
4886+ } else if (this .toComplete instanceof SimpleName currentName && FAKE_IDENTIFIER .equals (currentName .toString ())) {
4887+ res .setReplaceRange (this .offset , this .offset );
4888+ } else if (this .toComplete instanceof SimpleName ) {
4889+ res .setReplaceRange (this .toComplete .getStartPosition (), this .toComplete .getStartPosition () + this .toComplete .getLength ());
4890+ } else if (this .toComplete instanceof ThisExpression thisExpression
4891+ && thisExpression .getQualifier () != null
4892+ && this .offset > (thisExpression .getQualifier ().getStartPosition () + thisExpression .getQualifier ().getLength ())) {
4893+ setRange (res );
4894+ } else if (this .toComplete instanceof MethodRefParameter || this .toComplete instanceof MethodRef || this .toComplete instanceof TextElement ){
4895+ if (this .qualifiedPrefix .equals (this .prefix )) {
4896+ setRange (res );
4897+ } else {
4898+ setQualifiedRange (res );
4899+ }
4900+ } else {
4901+ res .setReplaceRange (this .toComplete .getStartPosition (), this .offset );
4902+ }
4903+ res .setFlags (type .getModifiers ());
4904+ if (this .toComplete instanceof SimpleName ) {
4905+ res .setTokenRange (this .toComplete .getStartPosition (), this .toComplete .getStartPosition () + this .toComplete .getLength ());
4906+ } else if (this .toComplete instanceof MarkerAnnotation ) {
4907+ res .setTokenRange (this .offset , this .offset );
4908+ } else {
4909+ setTokenRange (res );
4910+ }
4911+ boolean nodeInImports = DOMCompletionUtils .findParent (this .toComplete , new int [] { ASTNode .IMPORT_DECLARATION }) != null ;
4912+
4913+ boolean fromCurrentCU = ((List <AbstractTypeDeclaration >)this .unit .types ()).stream ().map (decl -> decl .resolveBinding ().getQualifiedName ()).anyMatch (qualified -> type .getFullyQualifiedName ().equals (qualified ));
4914+ boolean inSamePackage = false ;
4915+ boolean typeIsImported = ((List <ImportDeclaration >)this .unit .imports ()).stream ().anyMatch (importDecl -> {
4916+ return importDecl .getName ().toString ().equals (type .getFullyQualifiedName ());
4917+ });
4918+ PackageDeclaration packageDeclaration = this .unit .getPackage ();
4919+ if (packageDeclaration != null ) {
4920+ inSamePackage = packageDeclaration .getName ().toString ().equals (type .getPackageName ());
4921+ } else {
4922+ inSamePackage = type .getPackageName ().isEmpty ();
4923+ }
4924+ boolean isExceptionExpected = DOMCompletionUtils .findParent (this .toComplete , new int [] { ASTNode .CATCH_CLAUSE }) != null //
4925+ || (DOMCompletionUtils .findParent (this .toComplete , new int [] { ASTNode .TAG_ELEMENT }) instanceof TagElement te && TagElement .TAG_THROWS .equals (te .getTagName ()));
4926+ int relevance = RelevanceConstants .R_DEFAULT ;
4927+ relevance += RelevanceConstants .R_RESOLVED ;
4928+ // relevance += RelevanceUtils.computeRelevanceForInteresting(type, expectedTypes);
4929+ relevance += RelevanceUtils .computeRelevanceForRestrictions (type .getAccessibility (), this .settings );
4930+ // relevance += (isExceptionExpected && DOMCompletionUtils.findInSupers(type, "Ljava/lang/Exception;", this.workingCopyOwner, this.typeHierarchyCache) ? RelevanceConstants.R_EXCEPTION : 0);
4931+ // relevance += RelevanceUtils.computeRelevanceForInheritance(this.qualifyingType, type);
4932+ relevance += RelevanceUtils .computeRelevanceForQualification (!"java.lang" .equals (type .getPackageName ()) && !nodeInImports && !fromCurrentCU && !inSamePackage && !typeIsImported , this .prefix , this .qualifiedPrefix );
4933+ if (type .getFullyQualifiedName ().startsWith ("java." )
4934+ && !(DOMCompletionUtils .findParent (this .toComplete , new int [] { ASTNode .CATCH_CLAUSE }) != null && this .prefix .isEmpty ())) {
4935+ relevance += RelevanceConstants .R_JAVA_LIBRARY ;
4936+ }
4937+ // sometimes subclasses and superclasses are considered, sometimes they aren't
4938+ // relevance += (isExceptionExpected ? RelevanceUtils.computeRelevanceForExpectingType(type, expectedTypes, this.workingCopyOwner, this.typeHierarchyCache) : RelevanceUtils.simpleComputeRelevanceForExpectingType(type, expectedTypes));
4939+ relevance += RelevanceUtils .computeRelevanceForCaseMatching (this .prefix .toCharArray (), simpleName , this .assistOptions );
4940+ try {
4941+ if ((type .getModifiers () & Flags .AccAnnotation ) != 0 ) {
4942+ ASTNode current = this .toComplete ;
4943+ while (current instanceof Name ) {
4944+ current = current .getParent ();
4945+ }
4946+ if (current instanceof Annotation annotation ) {
4947+ relevance += RelevanceConstants .R_ANNOTATION ;
4948+ IAnnotation targetAnnotation = null ; //type.getAnnotation(Target.class.getName());
4949+ if (targetAnnotation == null || !targetAnnotation .exists ()) {
4950+ // On Javadoc for @Target: "If a Target meta-annotation is not present on an annotation type declaration,
4951+ // the declared type may be used on any program element."
4952+ relevance += RelevanceConstants .R_TARGET ;
4953+ } else {
4954+ var memberValuePairs = targetAnnotation .getMemberValuePairs ();
4955+ if (memberValuePairs != null ) {
4956+ if (Stream .of (memberValuePairs )
4957+ .filter (memberValue -> "value" .equals (memberValue .getMemberName ()))
4958+ .map (IMemberValuePair ::getValue )
4959+ .anyMatch (target -> matchHostType (annotation .getParent (), target ))) {
4960+ relevance += RelevanceConstants .R_TARGET ;
4961+ }
4962+ }
4963+ }
4964+ }
4965+ }
4966+ } catch (JavaModelException ex ) {
4967+ ILog .get ().warn (ex .getMessage (), ex );
4968+ }
4969+ if (isInExtendsOrImplements (this .toComplete ) != null ) {
4970+ if ((type .getModifiers () & Flags .AccAnnotation ) != 0 ) {
4971+ relevance += RelevanceConstants .R_ANNOTATION ;
4972+ }
4973+ if ((type .getModifiers () & Flags .AccInterface ) != 0 ) {
4974+ relevance += RelevanceConstants .R_INTERFACE ;
4975+ } else {
4976+ relevance += RelevanceConstants .R_CLASS ;
4977+ }
4978+ }
4979+ res .setRelevance (relevance );
4980+ if (parentTypeDeclaration != null ) {
4981+ String packageName = "" ; //$NON-NLS-1$
4982+ PackageDeclaration packageDecl = this .unit .getPackage ();
4983+ if (packageDecl != null ) {
4984+ packageName = packageDecl .getName ().toString ();
4985+ }
4986+ if (!packageName .equals (type .getPackageName ()) && !new String (res .getCompletion ()).equals (type .getFullyQualifiedName ())) {
4987+ // propose importing the type
4988+ res .setRequiredProposals (new CompletionProposal [] { toImportProposal (simpleName , signature , type .getPackageName ().toCharArray ()) });
4989+ }
4990+ }
4991+ return res ;
4992+
48174993 }
48184994
48194995 private CompletionProposal toProposal (IType type , int access ) {
@@ -4965,7 +5141,7 @@ private CompletionProposal toProposal(IType type, int access, int modifiers) {
49655141 relevance += (isExceptionExpected ? RelevanceUtils .computeRelevanceForExpectingType (type , expectedTypes , this .workingCopyOwner , this .typeHierarchyCache ) : RelevanceUtils .simpleComputeRelevanceForExpectingType (type , expectedTypes ));
49665142 relevance += RelevanceUtils .computeRelevanceForCaseMatching (this .prefix .toCharArray (), simpleName , this .assistOptions );
49675143 try {
4968- if (type .isAnnotation () ) {
5144+ if (( type .getFlags () & Flags . AccAnnotation ) != 0 ) {
49695145 ASTNode current = this .toComplete ;
49705146 while (current instanceof Name ) {
49715147 current = current .getParent ();
0 commit comments