blob: f8884c6afb223500bb4902f1ca7e56abf356622b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Timo Kinnunen - Contributions for bug 377373 - [subwords] known limitations with JDT 3.8
* Bug 420953 - [subwords] Constructors that don't match prefix not found
* IBM Corporation - initial API and implementation
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
* Stephan Herrmann - Contribution for
* Bug 400874 - [1.8][compiler] Inference infrastructure should evolve to meet JLS8 18.x (Part G of JSR335 spec)
* Gábor Kövesdán - Contribution for Bug 350000 - [content assist] Include non-prefix matches in auto-complete suggestions
*******************************************************************************/
package org.eclipse.jdt.internal.codeassist;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jdt.core.CompletionContext;
import org.eclipse.jdt.core.CompletionFlags;
import org.eclipse.jdt.core.CompletionProposal;
import org.eclipse.jdt.core.CompletionRequestor;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IAccessRule;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IModuleDescription;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchParticipant;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.SearchRequestor;
import org.eclipse.jdt.internal.codeassist.complete.AssistNodeParentAnnotationArrayInitializer;
import org.eclipse.jdt.internal.codeassist.complete.CompletionJavadoc;
import org.eclipse.jdt.internal.codeassist.complete.CompletionNodeDetector;
import org.eclipse.jdt.internal.codeassist.complete.CompletionNodeFound;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnAnnotationOfType;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnArgumentName;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnBranchStatementLabel;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnClassLiteralAccess;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnExplicitConstructorCall;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnFieldName;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnFieldType;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnImportReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnJavadoc;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnJavadocAllocationExpression;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnJavadocFieldReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnJavadocMessageSend;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnJavadocParamNameReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnJavadocQualifiedTypeReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnJavadocSingleTypeReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnJavadocTag;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnJavadocTypeParamReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnKeyword;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnKeyword3;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnKeywordModuleDeclaration;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnKeywordModuleInfo;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnLocalName;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMarkerAnnotationName;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMemberAccess;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMemberValueName;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMessageSend;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMessageSendName;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMethodName;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMethodReturnType;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnModuleDeclaration;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnModuleReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnPackageReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnPackageVisibilityReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnParameterizedQualifiedTypeReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnProvidesImplementationsQualifiedTypeReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnProvidesImplementationsSingleTypeReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnProvidesInterfacesQualifiedTypeReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnProvidesInterfacesSingleTypeReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnQualifiedAllocationExpression;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnQualifiedNameReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnQualifiedTypeReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnReferenceExpressionName;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnSingleNameReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnSingleTypeReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnStringLiteral;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnUsesQualifiedTypeReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnUsesSingleTypeReference;
import org.eclipse.jdt.internal.codeassist.complete.CompletionParser;
import org.eclipse.jdt.internal.codeassist.complete.CompletionScanner;
import org.eclipse.jdt.internal.codeassist.complete.InvalidCursorLocation;
import org.eclipse.jdt.internal.codeassist.impl.AssistParser;
import org.eclipse.jdt.internal.codeassist.impl.Engine;
import org.eclipse.jdt.internal.codeassist.impl.Keywords;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.ExtraFlags;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.eclipse.jdt.internal.compiler.ast.ArrayReference;
import org.eclipse.jdt.internal.compiler.ast.AssertStatement;
import org.eclipse.jdt.internal.compiler.ast.Assignment;
import org.eclipse.jdt.internal.compiler.ast.BinaryExpression;
import org.eclipse.jdt.internal.compiler.ast.CaseStatement;
import org.eclipse.jdt.internal.compiler.ast.CastExpression;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.ExpressionContext;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.ForStatement;
import org.eclipse.jdt.internal.compiler.ast.IfStatement;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression;
import org.eclipse.jdt.internal.compiler.ast.Javadoc;
import org.eclipse.jdt.internal.compiler.ast.JavadocImplicitTypeReference;
import org.eclipse.jdt.internal.compiler.ast.JavadocQualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.JavadocSingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
import org.eclipse.jdt.internal.compiler.ast.NameReference;
import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
import org.eclipse.jdt.internal.compiler.ast.OperatorExpression;
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
import org.eclipse.jdt.internal.compiler.ast.PackageVisibilityStatement;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ProvidesStatement;
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
import org.eclipse.jdt.internal.compiler.ast.RequiresStatement;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.SuperReference;
import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TryStatement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference;
import org.eclipse.jdt.internal.compiler.ast.UsesStatement;
import org.eclipse.jdt.internal.compiler.ast.WhileStatement;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.env.ISourceType;
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.ImportBinding;
import org.eclipse.jdt.internal.compiler.lookup.InferenceContext18;
import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
import org.eclipse.jdt.internal.compiler.parser.JavadocTagConstants;
import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
import org.eclipse.jdt.internal.compiler.util.ObjectVector;
import org.eclipse.jdt.internal.compiler.util.SimpleSetOfCharArray;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.core.BasicCompilationUnit;
import org.eclipse.jdt.internal.core.BinaryTypeConverter;
import org.eclipse.jdt.internal.core.INamingRequestor;
import org.eclipse.jdt.internal.core.InternalNamingConventions;
import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
import org.eclipse.jdt.internal.core.JavaElementRequestor;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.core.ModuleSourcePathManager;
import org.eclipse.jdt.internal.core.SearchableEnvironment;
import org.eclipse.jdt.internal.core.SourceMethod;
import org.eclipse.jdt.internal.core.SourceMethodElementInfo;
import org.eclipse.jdt.internal.core.SourceType;
import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
import org.eclipse.jdt.internal.core.search.BasicSearchEngine;
import org.eclipse.jdt.internal.core.search.matching.IndexBasedJavaSearchEnvironment;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
import org.eclipse.objectteams.otdt.core.IOTType;
import org.eclipse.objectteams.otdt.core.OTModelManager;
import org.eclipse.objectteams.otdt.core.TypeHelper;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
import org.eclipse.objectteams.otdt.internal.codeassist.CompletionOnFieldAccessSpec;
import org.eclipse.objectteams.otdt.internal.codeassist.CompletionOnMethodSpec;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.AbstractMethodMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CalloutMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.MethodSpec;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.StateHelper;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutScope;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.RoleModel;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.TSuperHelper;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.TypeAnalyzer;
/**
* This class is the entry point for source completions.
* It contains two public APIs used to call CodeAssist on a given source with
* a given environment, assisting position and storage (and possibly options).
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public final class CompletionEngine
extends Engine
implements ISearchRequestor, TypeConstants , TerminalTokens , RelevanceConstants, SuffixConstants {
private static class AcceptedConstructor {
public int modifiers;
public char[] simpleTypeName;
public int parameterCount;
public char[] signature;
public char[][] parameterTypes;
public char[][] parameterNames;
public int typeModifiers;
public char[] packageName;
public int extraFlags;
public int accessibility;
public boolean proposeType = false;
public boolean proposeConstructor = false;
public char[] fullyQualifiedName = null;
public boolean mustBeQualified = false;
public AcceptedConstructor(
int modifiers,
char[] simpleTypeName,
int parameterCount,
char[] signature,
char[][] parameterTypes,
char[][] parameterNames,
int typeModifiers,
char[] packageName,
int extraFlags,
int accessibility) {
this.modifiers = modifiers;
this.simpleTypeName = simpleTypeName;
this.parameterCount = parameterCount;
this.signature = signature;
this.parameterTypes = parameterTypes;
this.parameterNames = parameterNames;
this.typeModifiers = typeModifiers;
this.packageName = packageName;
this.extraFlags = extraFlags;
this.accessibility = accessibility;
}
@Override
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append('{');
buffer.append(this.packageName);
buffer.append(',');
buffer.append(this.simpleTypeName);
buffer.append('}');
return buffer.toString();
}
}
private static class AcceptedType {
public char[] packageName;
public char[] simpleTypeName;
public char[][] enclosingTypeNames;
public int modifiers;
public int accessibility;
public boolean mustBeQualified = false;
public char[] fullyQualifiedName = null;
public char[] qualifiedTypeName = null;
public AcceptedType(
char[] packageName,
char[] simpleTypeName,
char[][] enclosingTypeNames,
int modifiers,
int accessibility) {
this.packageName = packageName;
this.simpleTypeName = simpleTypeName;
this.enclosingTypeNames = enclosingTypeNames;
this.modifiers = modifiers;
this.accessibility = accessibility;
}
@Override
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append('{');
buffer.append(this.packageName);
buffer.append(',');
buffer.append(this.simpleTypeName);
buffer.append(',');
buffer.append(CharOperation.concatWith(this.enclosingTypeNames, '.'));
buffer.append('}');
return buffer.toString();
}
}
public class CompletionProblemFactory extends DefaultProblemFactory {
private int lastErrorStart;
private boolean checkProblems = false;
public boolean hasForbiddenProblems = false;
public boolean hasAllowedProblems = false;
public CompletionProblemFactory(Locale loc) {
super(loc);
}
private CategorizedProblem checkProblem(CategorizedProblem pb,
char[] originatingFileName, int severity, int start) {
int id = pb.getID();
if (CompletionEngine.this.actualCompletionPosition > start
&& this.lastErrorStart < start
&& pb.isError()
&& (id & IProblem.Syntax) == 0
&& (CompletionEngine.this.fileName == null || CharOperation.equals(CompletionEngine.this.fileName, originatingFileName))) {
CompletionEngine.this.problem = pb;
this.lastErrorStart = start;
}
if (this.checkProblems && !this.hasForbiddenProblems) {
switch (id) {
case IProblem.UsingDeprecatedType:
this.hasForbiddenProblems =
CompletionEngine.this.options.checkDeprecation;
break;
case IProblem.NotVisibleType:
this.hasForbiddenProblems =
CompletionEngine.this.options.checkVisibility;
break;
case IProblem.ForbiddenReference:
this.hasForbiddenProblems =
CompletionEngine.this.options.checkForbiddenReference;
break;
case IProblem.DiscouragedReference:
this.hasForbiddenProblems =
CompletionEngine.this.options.checkDiscouragedReference;
break;
default:
if ((severity & ProblemSeverities.Optional) != 0) {
this.hasAllowedProblems = true;
} else {
this.hasForbiddenProblems = true;
}
break;
}
}
return pb;
}
@Override
public CategorizedProblem createProblem(
char[] originatingFileName,
int problemId,
String[] problemArguments,
int elaborationId,
String[] messageArguments,
int severity,
int start,
int end,
int lineNumber,
int columnNumber) {
return checkProblem(
super.createProblem(
originatingFileName,
problemId,
problemArguments,
elaborationId,
messageArguments,
severity,
start,
end,
lineNumber,
columnNumber), originatingFileName, severity, start);
}
@Override
public CategorizedProblem createProblem(
char[] originatingFileName,
int problemId,
String[] problemArguments,
String[] messageArguments,
int severity,
int start,
int end,
int lineNumber,
int columnNumber) {
return checkProblem(
super.createProblem(
originatingFileName,
problemId,
problemArguments,
messageArguments,
severity,
start,
end,
lineNumber,
columnNumber), originatingFileName, severity, start);
}
public void startCheckingProblems() {
this.checkProblems = true;
this.hasForbiddenProblems = false;
this.hasAllowedProblems = false;
}
public void stopCheckingProblems() {
this.checkProblems = false;
}
}
//{ObjectTeams: prefixes for callout-to-field:
private static final char[] SET = "set".toCharArray(); //$NON-NLS-1$
private static final char[] GET = "get".toCharArray(); //$NON-NLS-1$
// SH}
public static char[] createBindingKey(char[] packageName, char[] typeName) {
char[] signature = createTypeSignature(packageName, typeName);
CharOperation.replace(signature, '.', '/');
return signature;
}
public static char[][] createDefaultParameterNames(int length) {
char[][] parameters;
switch (length) {
case 0 :
parameters = new char[length][];
break;
case 1 :
parameters = ARGS1;
break;
case 2 :
parameters = ARGS2;
break;
case 3 :
parameters = ARGS3;
break;
case 4 :
parameters = ARGS4;
break;
default :
parameters = new char[length][];
for (int i = 0; i < length; i++) {
parameters[i] = CharOperation.concat(ARG, String.valueOf(i).toCharArray());
}
break;
}
return parameters;
}
public static char[] createMethodSignature(char[][] parameterPackageNames, char[][] parameterTypeNames, char[] returnTypeSignature) {
char[][] parameterTypeSignature = new char[parameterTypeNames.length][];
for (int i = 0; i < parameterTypeSignature.length; i++) {
parameterTypeSignature[i] =
Signature.createCharArrayTypeSignature(
CharOperation.concat(
parameterPackageNames[i],
CharOperation.replaceOnCopy(parameterTypeNames[i], '.', '$'), '.'), true);
}
return Signature.createMethodSignature(
parameterTypeSignature,
returnTypeSignature);
}
public static char[] createMethodSignature(char[][] parameterPackageNames, char[][] parameterTypeNames, char[] returnPackagename, char[] returnTypeName) {
char[] returnTypeSignature =
returnTypeName == null || returnTypeName.length == 0
? Signature.createCharArrayTypeSignature(VOID, true)
: Signature.createCharArrayTypeSignature(
CharOperation.concat(
returnPackagename,
CharOperation.replaceOnCopy(returnTypeName, '.', '$'), '.'), true);
return createMethodSignature(
parameterPackageNames,
parameterTypeNames,
returnTypeSignature);
}
public static char[] createNonGenericTypeSignature(char[] qualifiedPackageName, char[] qualifiedTypeName) {
return Signature.createCharArrayTypeSignature(
CharOperation.concat(
qualifiedPackageName,
CharOperation.replaceOnCopy(qualifiedTypeName, '.', '$'), '.'), true);
}
public static char[] createTypeSignature(char[] qualifiedPackageName, char[] qualifiedTypeName) {
char[] name = new char[qualifiedTypeName.length];
System.arraycopy(qualifiedTypeName, 0, name, 0, qualifiedTypeName.length);
int depth = 0;
int length = name.length;
for (int i = length -1; i >= 0; i--) {
switch (name[i]) {
case '.':
if (depth == 0 && name[i - 1] != '>') {
name[i] = '$';
}
break;
case '<':
depth--;
break;
case '>':
depth++;
break;
}
}
return Signature.createCharArrayTypeSignature(
CharOperation.concat(
qualifiedPackageName,
name, '.'), true);
}
private static char[] getRequiredTypeSignature(TypeBinding typeBinding) {
char[] result = null;
StringBuffer sig = new StringBuffer(10);
sig.append(typeBinding.signature());
int sigLength = sig.length();
result = new char[sigLength];
sig.getChars(0, sigLength, result, 0);
result = CharOperation.replaceOnCopy(result, '/', '.');
return result;
}
private static char[] getTypeName(TypeReference typeReference) {
char[] typeName = CharOperation.concatWith(typeReference.getTypeName(), '.');
int dims = typeReference.dimensions();
if (dims > 0) {
int length = typeName.length;
int newLength = length + (dims*2);
System.arraycopy(typeName, 0, typeName = new char[newLength], 0, length);
for (int k = length; k < newLength; k += 2) {
typeName[k] = '[';
typeName[k+1] = ']';
}
}
return typeName;
}
private static boolean hasStaticMemberTypes(ReferenceBinding typeBinding, SourceTypeBinding invocationType, CompilationUnitScope unitScope) {
ReferenceBinding[] memberTypes = typeBinding.memberTypes();
int length = memberTypes == null ? 0 : memberTypes.length;
next : for (int i = 0; i < length; i++) {
ReferenceBinding memberType = memberTypes[i];
if (invocationType != null && !memberType.canBeSeenBy(typeBinding, invocationType)) {
continue next;
} else if(invocationType == null && !memberType.canBeSeenBy(unitScope.fPackage)) {
continue next;
}
if ((memberType.modifiers & ClassFileConstants.AccStatic) != 0) {
return true;
}
}
return false;
}
private static boolean hasMemberTypesInEnclosingScope(SourceTypeBinding typeBinding, Scope scope) {
ReferenceBinding[] memberTypes = typeBinding.memberTypes();
int length = memberTypes == null ? 0 : memberTypes.length;
if (length > 0) {
MethodScope methodScope = scope.methodScope();
if (methodScope != null && !methodScope.isStatic) {
ClassScope classScope = typeBinding.scope;
Scope currentScope = scope;
while (currentScope != null) {
if (currentScope == classScope) {
return true;
}
currentScope = currentScope.parent;
}
}
}
return false;
}
public HashtableOfObject typeCache;
public int openedBinaryTypes; // used during InternalCompletionProposal#findConstructorParameterNames()
public static boolean DEBUG = false;
public static boolean PERF = false;
private static final char[] KNOWN_TYPE_WITH_UNKNOWN_CONSTRUCTORS = new char[]{};
private static final char[] KNOWN_TYPE_WITH_KNOWN_CONSTRUCTORS = new char[]{};
private static final char[] ARG = "arg".toCharArray(); //$NON-NLS-1$
private static final char[] ARG0 = "arg0".toCharArray(); //$NON-NLS-1$
private static final char[] ARG1 = "arg1".toCharArray(); //$NON-NLS-1$
private static final char[] ARG2 = "arg2".toCharArray(); //$NON-NLS-1$
private static final char[] ARG3 = "arg3".toCharArray(); //$NON-NLS-1$
private static final char[][] ARGS1 = new char[][]{ARG0};
private static final char[][] ARGS2 = new char[][]{ARG0, ARG1};
private static final char[][] ARGS3 = new char[][]{ARG0, ARG1, ARG2};
private static final char[][] ARGS4 = new char[][]{ARG0, ARG1, ARG2, ARG3};
private final static int CHECK_CANCEL_FREQUENCY = 50;
// temporary constants to quickly disabled polish features if necessary
public final static boolean NO_TYPE_COMPLETION_ON_EMPTY_TOKEN = false;
private final static char[] ERROR_PATTERN = "*error*".toCharArray(); //$NON-NLS-1$
private final static char[] EXCEPTION_PATTERN = "*exception*".toCharArray(); //$NON-NLS-1$
private final static char[] SEMICOLON = new char[] { ';' };
private final static char[] CLASS = "Class".toCharArray(); //$NON-NLS-1$
private final static char[] VOID = "void".toCharArray(); //$NON-NLS-1$
private final static char[] INT = "int".toCharArray(); //$NON-NLS-1$
private final static char[] INT_SIGNATURE = new char[]{Signature.C_INT};
private final static char[] VALUE = "value".toCharArray(); //$NON-NLS-1$
private final static char[] EXTENDS = "extends".toCharArray(); //$NON-NLS-1$
private final static char[] SUPER = "super".toCharArray(); //$NON-NLS-1$
//{ObjectTeams: for <B base R>
private final static char[] BASE = "base".toCharArray(); //$NON-NLS-1$
// SH}
private final static char[] DEFAULT_CONSTRUCTOR_SIGNATURE = "()V".toCharArray(); //$NON-NLS-1$
private final static char[] DOT = ".".toCharArray(); //$NON-NLS-1$
private final static char[] VARARGS = "...".toCharArray(); //$NON-NLS-1$
private final static char[] IMPORT = "import".toCharArray(); //$NON-NLS-1$
private final static char[] STATIC = "static".toCharArray(); //$NON-NLS-1$
private final static char[] ON_DEMAND = ".*".toCharArray(); //$NON-NLS-1$
private final static char[] IMPORT_END = ";\n".toCharArray(); //$NON-NLS-1$
private final static char[] JAVA_LANG_OBJECT_SIGNATURE =
createTypeSignature(CharOperation.concatWith(JAVA_LANG, '.'), OBJECT);
private final static char[] JAVA_LANG_NAME =
CharOperation.concatWith(JAVA_LANG, '.');
private final static int NONE = 0;
private final static int SUPERTYPE = 1;
private final static int SUBTYPE = 2;
int expectedTypesPtr = -1;
TypeBinding[] expectedTypes = new TypeBinding[1];
int expectedTypesFilter;
boolean hasJavaLangObjectAsExpectedType = false;
boolean hasExpectedArrayTypes = false;
boolean hasComputedExpectedArrayTypes = false;
int uninterestingBindingsPtr = -1;
Binding[] uninterestingBindings = new Binding[1];
int forbbidenBindingsPtr = -1;
Binding[] forbbidenBindings = new Binding[1];
int uninterestingBindingsFilter; // only set when completing on an exception type
ImportBinding[] favoriteReferenceBindings;
boolean assistNodeIsClass;
boolean assistNodeIsEnum;
boolean assistNodeIsException;
boolean assistNodeIsInterface;
boolean assistNodeIsAnnotation;
boolean assistNodeIsConstructor;
boolean assistNodeIsSuperType;
boolean assistNodeIsExtendedType;
boolean assistNodeIsInterfaceExcludingAnnotation; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=310423
int assistNodeInJavadoc = 0;
boolean assistNodeCanBeSingleMemberAnnotation = false;
boolean assistNodeIsInsideCase = false; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=195346
boolean assistNodeIsString = false; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=343476
long targetedElement;
//{ObjectTeams:
private AbstractMethodMappingDeclaration currentMethodMapping;
private char seperator= 0; // char that should be inserted before the completion
// searching candidates for callin/callout: are we searching the base class's super?
private static final int SEARCH_SUPER_BASE = 0x1000; // must be larger than CompletionProposal.LAST_KIND
// SH}
WorkingCopyOwner owner;
IProgressMonitor monitor;
IJavaProject javaProject;
ITypeRoot typeRoot;
CompletionParser parser;
CompletionRequestor requestor;
CompletionProblemFactory problemFactory;
ProblemReporter problemReporter;
private INameEnvironment noCacheNameEnvironment;
char[] source;
ModuleDeclaration moduleDeclaration;
boolean skipDefaultPackage = false;
char[] completionToken;
char[] qualifiedCompletionToken;
boolean resolvingImports = false;
boolean resolvingStaticImports = false;
boolean insideQualifiedReference = false;
boolean noProposal = true;
CategorizedProblem problem = null;
char[] fileName = null;
int startPosition, actualCompletionPosition, endPosition, offset;
int tokenStart, tokenEnd;
int javadocTagPosition; // Position of previous tag while completing in javadoc
String sourceLevel;
String complianceLevel;
SimpleSetOfCharArray validPackageNames = new SimpleSetOfCharArray(10);
SimpleSetOfCharArray invalidPackageNames = new SimpleSetOfCharArray(1);
HashtableOfObject knownModules = new HashtableOfObject(10);
HashtableOfObject knownPkgs = new HashtableOfObject(10);
HashtableOfObject knownTypes = new HashtableOfObject(10);
/*
static final char[][] mainDeclarations =
new char[][] {
"package".toCharArray(),
"import".toCharArray(),
"abstract".toCharArray(),
"final".toCharArray(),
"public".toCharArray(),
"class".toCharArray(),
"interface".toCharArray()};
static final char[][] modifiers = // may want field, method, type & member type modifiers
new char[][] {
"abstract".toCharArray(),
"final".toCharArray(),
"native".toCharArray(),
"public".toCharArray(),
"protected".toCharArray(),
"private".toCharArray(),
"static".toCharArray(),
"strictfp".toCharArray(),
"synchronized".toCharArray(),
"transient".toCharArray(),
"volatile".toCharArray()};
*/
static final BaseTypeBinding[] BASE_TYPES = {
TypeBinding.BOOLEAN,
TypeBinding.BYTE,
TypeBinding.CHAR,
TypeBinding.DOUBLE,
TypeBinding.FLOAT,
TypeBinding.INT,
TypeBinding.LONG,
TypeBinding.SHORT,
TypeBinding.VOID
};
static final int BASE_TYPES_LENGTH = BASE_TYPES.length;
static final char[][] BASE_TYPE_NAMES = new char[BASE_TYPES_LENGTH][];
static final int BASE_TYPES_WITHOUT_VOID_LENGTH = BASE_TYPES.length - 1;
static final char[][] BASE_TYPE_NAMES_WITHOUT_VOID = new char[BASE_TYPES_WITHOUT_VOID_LENGTH][];
static {
for (int i=0; i<BASE_TYPES_LENGTH; i++) {
BASE_TYPE_NAMES[i] = BASE_TYPES[i].simpleName;
}
for (int i=0; i<BASE_TYPES_WITHOUT_VOID_LENGTH; i++) {
BASE_TYPE_NAMES_WITHOUT_VOID[i] = BASE_TYPES[i].simpleName;
}
}
static final char[] classField = "class".toCharArray(); //$NON-NLS-1$
static final char[] lengthField = "length".toCharArray(); //$NON-NLS-1$
static final char[] cloneMethod = "clone".toCharArray(); //$NON-NLS-1$
static final char[] THIS = "this".toCharArray(); //$NON-NLS-1$
static final char[] THROWS = "throws".toCharArray(); //$NON-NLS-1$
static InvocationSite FakeInvocationSite = new InvocationSite(){
@Override
public TypeBinding[] genericTypeArguments() { return null; }
@Override
public boolean isSuperAccess(){ return false; }
@Override
public boolean isTypeAccess(){ return false; }
@Override
public void setActualReceiverType(ReferenceBinding receiverType) {/* empty */}
@Override
public void setDepth(int depth){/* empty */}
@Override
public void setFieldIndex(int depth){/* empty */}
@Override
public int sourceEnd() { return 0; }
@Override
public int sourceStart() { return 0; }
@Override
public TypeBinding invocationTargetType() { return null; }
@Override
public boolean receiverIsImplicitThis() { return false; }
@Override
public InferenceContext18 freshInferenceContext(Scope scope) { return null; }
@Override
public ExpressionContext getExpressionContext() { return ExpressionContext.VANILLA_CONTEXT; }
@Override
public boolean isQualifiedSuper() { return false; }
@Override
public boolean checkingPotentialCompatibility() { return false; }
@Override
public void acceptPotentiallyCompatibleMethods(MethodBinding[] methods) {/* ignore */}
};
private int foundTypesCount;
private ObjectVector acceptedTypes;
private int foundConstructorsCount;
private ObjectVector acceptedConstructors;
/**
* The CompletionEngine is responsible for computing source completions.
*
* It requires a searchable name environment, which supports some
* specific search APIs, and a requestor to feed back the results to a UI.
*
* @param nameEnvironment org.eclipse.jdt.internal.codeassist.ISearchableNameEnvironment
* used to resolve type/package references and search for types/packages
* based on partial names.
*
* @param requestor org.eclipse.jdt.internal.codeassist.ICompletionRequestor
* since the engine might produce answers of various forms, the engine
* is associated with a requestor able to accept all possible completions.
*
* @param settings java.util.Map
* set of options used to configure the code assist engine.
*/
public CompletionEngine(
SearchableEnvironment nameEnvironment,
CompletionRequestor requestor,
Map settings,
IJavaProject javaProject,
WorkingCopyOwner owner,
IProgressMonitor monitor) {
super(settings);
this.javaProject = javaProject;
this.requestor = requestor;
this.nameEnvironment = nameEnvironment;
this.typeCache = new HashtableOfObject(5);
this.openedBinaryTypes = 0;
this.sourceLevel = javaProject.getOption(JavaCore.COMPILER_SOURCE, true);
this.complianceLevel = javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true);
this.problemFactory = new CompletionProblemFactory(Locale.getDefault());
this.problemReporter = new ProblemReporter(
DefaultErrorHandlingPolicies.proceedWithAllProblems(),
this.compilerOptions,
this.problemFactory);
this.lookupEnvironment =
new LookupEnvironment(this, this.compilerOptions, this.problemReporter, nameEnvironment);
this.parser =
new CompletionParser(this.problemReporter, this.requestor.isExtendedContextRequired(), monitor);
this.owner = owner;
this.monitor = monitor;
}
@Override
public void accept(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
if (!CharOperation.equals(sourceUnit.getMainTypeName(), TypeConstants.PACKAGE_INFO_NAME)) {
// do not accept package-info.java as a type for completion engine
// because it contains no extra info that will help in completion
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=343865
// Required after the fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=337868
// because now we get a type corresponding to the package-info.java from the java model.
super.accept(sourceUnit, accessRestriction);
}
}
@Override
public void acceptConstructor(
int modifiers,
char[] simpleTypeName,
int parameterCount,
char[] signature,
char[][] parameterTypes,
char[][] parameterNames,
int typeModifiers,
char[] packageName,
int extraFlags,
String path,
AccessRestriction accessRestriction) {
// does not check cancellation for every types to avoid performance loss
if ((this.foundConstructorsCount % (CHECK_CANCEL_FREQUENCY)) == 0) checkCancel();
this.foundConstructorsCount++;
if ((typeModifiers & ClassFileConstants.AccEnum) != 0) return;
if (this.options.checkDeprecation && (typeModifiers & ClassFileConstants.AccDeprecated) != 0) return;
if (this.options.checkVisibility) {
if((typeModifiers & ClassFileConstants.AccPublic) == 0) {
if((typeModifiers & ClassFileConstants.AccPrivate) != 0) return;
if (this.currentPackageName == null) {
initializePackageCache();
}
if(!CharOperation.equals(packageName, this.currentPackageName)) return;
}
}
int accessibility = IAccessRule.K_ACCESSIBLE;
if(accessRestriction != null) {
switch (accessRestriction.getProblemId()) {
case IProblem.ForbiddenReference:
if (this.options.checkForbiddenReference) {
return;
}
accessibility = IAccessRule.K_NON_ACCESSIBLE;
break;
case IProblem.DiscouragedReference:
if (this.options.checkDiscouragedReference) {
return;
}
accessibility = IAccessRule.K_DISCOURAGED;
break;
}
}
if(this.acceptedConstructors == null) {
this.acceptedConstructors = new ObjectVector();
}
this.acceptedConstructors.add(
new AcceptedConstructor(
modifiers,
simpleTypeName,
parameterCount,
signature,
parameterTypes,
parameterNames,
typeModifiers,
packageName,
extraFlags,
accessibility));
}
private void acceptConstructors(Scope scope) {
final boolean DEFER_QUALIFIED_PROPOSALS = false;
this.checkCancel();
if(this.acceptedConstructors == null) return;
int length = this.acceptedConstructors.size();
if(length == 0) return;
HashtableOfObject onDemandFound = new HashtableOfObject();
ArrayList deferredProposals = null;
if (DEFER_QUALIFIED_PROPOSALS) {
deferredProposals = new ArrayList();
}
try {
next : for (int i = 0; i < length; i++) {
// does not check cancellation for every types to avoid performance loss
if ((i % CHECK_CANCEL_FREQUENCY) == 0) checkCancel();
AcceptedConstructor acceptedConstructor = (AcceptedConstructor)this.acceptedConstructors.elementAt(i);
final int typeModifiers = acceptedConstructor.typeModifiers;
final char[] packageName = acceptedConstructor.packageName;
final char[] simpleTypeName = acceptedConstructor.simpleTypeName;
final int modifiers = acceptedConstructor.modifiers;
final int parameterCount = acceptedConstructor.parameterCount;
final char[] signature = acceptedConstructor.signature;
final char[][] parameterTypes = acceptedConstructor.parameterTypes;
final char[][] parameterNames = acceptedConstructor.parameterNames;
final int extraFlags = acceptedConstructor.extraFlags;
final int accessibility = acceptedConstructor.accessibility;
boolean proposeType = hasArrayTypeAsExpectedSuperTypes() || (extraFlags & ExtraFlags.HasNonPrivateStaticMemberTypes) != 0;
char[] fullyQualifiedName = CharOperation.concat(packageName, simpleTypeName, '.');
Object knownTypeKind = this.knownTypes.get(fullyQualifiedName);
if (knownTypeKind != null) {
if (knownTypeKind == KNOWN_TYPE_WITH_KNOWN_CONSTRUCTORS) {
// the type and its constructors are already accepted
continue next;
}
// this type is already accepted
proposeType = false;
} else {
this.knownTypes.put(fullyQualifiedName, KNOWN_TYPE_WITH_UNKNOWN_CONSTRUCTORS);
}
boolean proposeConstructor = true;
if (this.options.checkVisibility) {
if((modifiers & ClassFileConstants.AccPublic) == 0) {
if((modifiers & ClassFileConstants.AccPrivate) != 0) {
if (!proposeType) continue next;
proposeConstructor = false;
} else {
if (this.currentPackageName == null) {
initializePackageCache();
}
if(!CharOperation.equals(packageName, this.currentPackageName)) {
if((typeModifiers & ClassFileConstants.AccAbstract) == 0 ||
(modifiers & ClassFileConstants.AccProtected) == 0) {
if (!proposeType) continue next;
proposeConstructor = false;
}
}
}
}
}
acceptedConstructor.fullyQualifiedName = fullyQualifiedName;
acceptedConstructor.proposeType = proposeType;
acceptedConstructor.proposeConstructor = proposeConstructor;
if(!this.importCachesInitialized) {
initializeImportCaches();
}
for (int j = 0; j < this.importCacheCount; j++) {
char[][] importName = this.importsCache[j];
if(CharOperation.equals(simpleTypeName, importName[0])) {
if (proposeType) {
proposeType(
packageName,
simpleTypeName,
typeModifiers,
accessibility,
simpleTypeName,
fullyQualifiedName,
!CharOperation.equals(fullyQualifiedName, importName[1]),
scope);
}
if (proposeConstructor && !Flags.isEnum(typeModifiers)) {
boolean isQualified = !CharOperation.equals(fullyQualifiedName, importName[1]);
if (!isQualified) {
proposeConstructor(
simpleTypeName,
parameterCount,
signature,
parameterTypes,
parameterNames,
modifiers,
packageName,
typeModifiers,
accessibility,
simpleTypeName,
fullyQualifiedName,
isQualified,
scope,
extraFlags);
} else {
acceptedConstructor.mustBeQualified = true;
if (DEFER_QUALIFIED_PROPOSALS) {
deferredProposals.add(acceptedConstructor);
} else {
proposeConstructor(acceptedConstructor, scope);
}
}
}
continue next;
}
}
if (CharOperation.equals(this.currentPackageName, packageName)) {
if (proposeType) {
proposeType(
packageName,
simpleTypeName,
typeModifiers,
accessibility,
simpleTypeName,
fullyQualifiedName,
false,
scope);
}
if (proposeConstructor && !Flags.isEnum(typeModifiers)) {
proposeConstructor(
simpleTypeName,
parameterCount,
signature,
parameterTypes,
parameterNames,
modifiers,
packageName,
typeModifiers,
accessibility,
simpleTypeName,
fullyQualifiedName,
false,
scope,
extraFlags);
}
continue next;
} else {
char[] fullyQualifiedEnclosingTypeOrPackageName = null;
AcceptedConstructor foundConstructor = null;
if((foundConstructor = (AcceptedConstructor)onDemandFound.get(simpleTypeName)) == null) {
for (int j = 0; j < this.onDemandImportCacheCount; j++) {
ImportBinding importBinding = this.onDemandImportsCache[j];
char[][] importName = importBinding.compoundName;
char[] importFlatName = CharOperation.concatWith(importName, '.');
if(fullyQualifiedEnclosingTypeOrPackageName == null) {
fullyQualifiedEnclosingTypeOrPackageName = packageName;
}
if(CharOperation.equals(fullyQualifiedEnclosingTypeOrPackageName, importFlatName)) {
if(importBinding.isStatic()) {
if((typeModifiers & ClassFileConstants.AccStatic) != 0) {
onDemandFound.put(
simpleTypeName,
acceptedConstructor);
continue next;
}
} else {
onDemandFound.put(
simpleTypeName,
acceptedConstructor);
continue next;
}
}
}
} else if(!foundConstructor.mustBeQualified){
done : for (int j = 0; j < this.onDemandImportCacheCount; j++) {
ImportBinding importBinding = this.onDemandImportsCache[j];
char[][] importName = importBinding.compoundName;
char[] importFlatName = CharOperation.concatWith(importName, '.');
if(fullyQualifiedEnclosingTypeOrPackageName == null) {
fullyQualifiedEnclosingTypeOrPackageName = packageName;
}
if(CharOperation.equals(fullyQualifiedEnclosingTypeOrPackageName, importFlatName)) {
if(importBinding.isStatic()) {
if((typeModifiers & ClassFileConstants.AccStatic) != 0) {
foundConstructor.mustBeQualified = true;
break done;
}
} else {
foundConstructor.mustBeQualified = true;
break done;
}
}
}
}
if (proposeType) {
proposeType(
packageName,
simpleTypeName,
typeModifiers,
accessibility,
simpleTypeName,
fullyQualifiedName,
true,
scope);
}
if (proposeConstructor && !Flags.isEnum(typeModifiers)) {
acceptedConstructor.mustBeQualified = true;
if (DEFER_QUALIFIED_PROPOSALS) {
deferredProposals.add(acceptedConstructor);
} else {
proposeConstructor(acceptedConstructor, scope);
}
}
}
}
char[][] keys = onDemandFound.keyTable;
Object[] values = onDemandFound.valueTable;
int max = keys.length;
for (int i = 0; i < max; i++) {
// does not check cancellation for every types to avoid performance loss
if ((i % CHECK_CANCEL_FREQUENCY) == 0) checkCancel();
if(keys[i] != null) {
AcceptedConstructor value = (AcceptedConstructor) values[i];
if(value != null) {
char[] fullyQualifiedEnclosingTypeOrPackageName = null;
done : for (int j = 0; j < this.onDemandImportCacheCount; j++) {
ImportBinding importBinding = this.onDemandImportsCache[j];
char[][] importName = importBinding.compoundName;
char[] importFlatName = CharOperation.concatWith(importName, '.');
if(fullyQualifiedEnclosingTypeOrPackageName == null) {
fullyQualifiedEnclosingTypeOrPackageName = value.packageName;
}
if(CharOperation.equals(fullyQualifiedEnclosingTypeOrPackageName, importFlatName)) {
if(importBinding.isStatic()) {
if((value.modifiers & ClassFileConstants.AccStatic) != 0) {
value.mustBeQualified = true;
break done;
}
} else {
value.mustBeQualified = true;
break done;
}
}
}
if (value.proposeType) {
proposeType(
value.packageName,
value.simpleTypeName,
value.typeModifiers,
value.accessibility,
value.simpleTypeName,
value.fullyQualifiedName,
value.mustBeQualified,
scope);
}
if (value.proposeConstructor && !Flags.isEnum(value.modifiers)) {
if (!value.mustBeQualified) {
proposeConstructor(
value.simpleTypeName,
value.parameterCount,
value.signature,
value.parameterTypes,
value.parameterNames,
value.modifiers,
value.packageName,
value.typeModifiers,
value.accessibility,
value.simpleTypeName,
value.fullyQualifiedName,
value.mustBeQualified,
scope,
value.extraFlags);
} else {
if (DEFER_QUALIFIED_PROPOSALS) {
deferredProposals.add(value);
} else {
proposeConstructor(value, scope);
}
}
}
}
}
}
if (DEFER_QUALIFIED_PROPOSALS) {
int size = deferredProposals.size();
for (int i = 0; i < size; i++) {
// does not check cancellation for every types to avoid performance loss
if ((i % CHECK_CANCEL_FREQUENCY) == 0) checkCancel();
AcceptedConstructor deferredProposal = (AcceptedConstructor)deferredProposals.get(i);
if (deferredProposal.proposeConstructor) {
proposeConstructor(
deferredProposal.simpleTypeName,
deferredProposal.parameterCount,
deferredProposal.signature,
deferredProposal.parameterTypes,
deferredProposal.parameterNames,
deferredProposal.modifiers,
deferredProposal.packageName,
deferredProposal.typeModifiers,
deferredProposal.accessibility,
deferredProposal.simpleTypeName,
deferredProposal.fullyQualifiedName,
deferredProposal.mustBeQualified,
scope,
deferredProposal.extraFlags);
}
}
}
} finally {
this.acceptedTypes = null; // reset
}
}
/**
* One result of the search consists of a new module.
*
* NOTE - All module names are presented in their readable form:
* Module names are in the form "a.b.c".
* The default module is represented by an empty array.
*/
@Override
public void acceptModule(char[] moduleName) {
if (this.knownModules.containsKey(moduleName)) return;
if (CharOperation.equals(moduleName, this.moduleDeclaration.moduleName)) return;
if (CharOperation.equals(moduleName, CharOperation.NO_CHAR)) return;
this.knownModules.put(moduleName, this);
char[] completion = moduleName;
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(this.qualifiedCompletionToken == null ? this.completionToken : this.qualifiedCompletionToken, moduleName);
relevance += computeRelevanceForQualification(true);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.MODULE_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.MODULE_REF, this.actualCompletionPosition);
proposal.setModuleName(moduleName);
proposal.setDeclarationSignature(moduleName);
proposal.setCompletion(completion);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
@Override
public void acceptPackage(char[] packageName) {
if (this.knownPkgs.containsKey(packageName)) return;
if (!isValidPackageName(packageName)) return;
if (this.skipDefaultPackage &&
CharOperation.equals(packageName, CharOperation.NO_CHAR))
return;
this.knownPkgs.put(packageName, this);
char[] completion;
if(this.resolvingImports) {
if(this.resolvingStaticImports) {
completion = CharOperation.concat(packageName, new char[] { '.' });
} else {
completion = CharOperation.concat(packageName, new char[] { '.', '*', ';' });
}
} else {
completion = packageName;
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(this.qualifiedCompletionToken == null ? this.completionToken : this.qualifiedCompletionToken, packageName);
if(!this.resolvingImports) {
relevance += computeRelevanceForQualification(true);
}
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.PACKAGE_REF, this.actualCompletionPosition);
proposal.setDeclarationSignature(packageName);
proposal.setPackageName(packageName);
proposal.setCompletion(completion);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
@Override
public void acceptType(
char[] packageName,
char[] simpleTypeName,
char[][] enclosingTypeNames,
int modifiers,
AccessRestriction accessRestriction) {
// does not check cancellation for every types to avoid performance loss
if ((this.foundTypesCount % CHECK_CANCEL_FREQUENCY) == 0) checkCancel();
this.foundTypesCount++;
if (this.options.checkDeprecation && (modifiers & ClassFileConstants.AccDeprecated) != 0) return;
if (this.assistNodeIsExtendedType && (modifiers & ClassFileConstants.AccFinal) != 0) return;
if (this.options.checkVisibility) {
if((modifiers & ClassFileConstants.AccPublic) == 0) {
if((modifiers & ClassFileConstants.AccPrivate) != 0) return;
if (this.moduleDeclaration == null) {
char[] currentPackage = CharOperation.concatWith(this.unitScope.fPackage.compoundName, '.');
if(!CharOperation.equals(packageName, currentPackage)) return;
}
}
}
int accessibility = IAccessRule.K_ACCESSIBLE;
if(accessRestriction != null) {
switch (accessRestriction.getProblemId()) {
case IProblem.ForbiddenReference:
if (this.options.checkForbiddenReference) {
return;
}
accessibility = IAccessRule.K_NON_ACCESSIBLE;
break;
case IProblem.DiscouragedReference:
if (this.options.checkDiscouragedReference) {
return;
}
accessibility = IAccessRule.K_DISCOURAGED;
break;
}
}
if (isForbidden(packageName, simpleTypeName, enclosingTypeNames)) {
return;
}
if(this.acceptedTypes == null) {
this.acceptedTypes = new ObjectVector();
}
this.acceptedTypes.add(new AcceptedType(packageName, simpleTypeName, enclosingTypeNames, modifiers, accessibility));
}
private void acceptTypes(Scope scope) {
this.checkCancel();
if(this.acceptedTypes == null) return;
int length = this.acceptedTypes.size();
if(length == 0) return;
HashtableOfObject onDemandFound = new HashtableOfObject();
try {
next : for (int i = 0; i < length; i++) {
// does not check cancellation for every types to avoid performance loss
if ((i % CHECK_CANCEL_FREQUENCY) == 0) checkCancel();
AcceptedType acceptedType = (AcceptedType)this.acceptedTypes.elementAt(i);
char[] packageName = acceptedType.packageName;
char[] simpleTypeName = acceptedType.simpleTypeName;
char[][] enclosingTypeNames = acceptedType.enclosingTypeNames;
int modifiers = acceptedType.modifiers;
int accessibility = acceptedType.accessibility;
char[] typeName;
char[] flatEnclosingTypeNames;
if(enclosingTypeNames == null || enclosingTypeNames.length == 0) {
flatEnclosingTypeNames = null;
typeName = simpleTypeName;
} else {
flatEnclosingTypeNames = CharOperation.concatWith(acceptedType.enclosingTypeNames, '.');
typeName = CharOperation.concat(flatEnclosingTypeNames, simpleTypeName, '.');
}
char[] fullyQualifiedName = CharOperation.concat(packageName, typeName, '.');
if (this.knownTypes.containsKey(fullyQualifiedName)) continue next;
this.knownTypes.put(fullyQualifiedName, KNOWN_TYPE_WITH_UNKNOWN_CONSTRUCTORS);
if (this.resolvingImports) {
if(this.compilerOptions.complianceLevel >= ClassFileConstants.JDK1_4 && packageName.length == 0) {
continue next; // import of default package is forbidden when compliance is 1.4 or higher
}
char[] completionName = this.insideQualifiedReference ? simpleTypeName : fullyQualifiedName;
if(this.resolvingStaticImports) {
if(enclosingTypeNames == null || enclosingTypeNames.length == 0) {
completionName = CharOperation.concat(completionName, new char[] { '.' });
} else if ((modifiers & ClassFileConstants.AccStatic) == 0) {
continue next;
} else {
completionName = CharOperation.concat(completionName, new char[] { ';' });
}
} else {
completionName = CharOperation.concat(completionName, new char[] { ';' });
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal(packageName, fullyQualifiedName);
relevance += computeRelevanceForRestrictions(accessibility);
relevance += computeRelevanceForCaseMatching(this.completionToken, simpleTypeName);
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
createTypeProposal(packageName, typeName, modifiers, accessibility, completionName, relevance);
}
} else {
if(!this.importCachesInitialized) {
initializeImportCaches();
}
for (int j = 0; j < this.importCacheCount; j++) {
char[][] importName = this.importsCache[j];
if(CharOperation.equals(typeName, importName[0])) {
proposeType(
packageName,
simpleTypeName,
modifiers,
accessibility,
typeName,
fullyQualifiedName,
!CharOperation.equals(fullyQualifiedName, importName[1]),
scope);
continue next;
}
}
if ((enclosingTypeNames == null || enclosingTypeNames.length == 0 ) && CharOperation.equals(this.currentPackageName, packageName)) {
proposeType(
packageName,
simpleTypeName,
modifiers,
accessibility,
typeName,
fullyQualifiedName,
false,
scope);
continue next;
} else {
char[] fullyQualifiedEnclosingTypeOrPackageName = null;
AcceptedType foundType = null;
if((foundType = (AcceptedType)onDemandFound.get(simpleTypeName)) == null) {
for (int j = 0; j < this.onDemandImportCacheCount; j++) {
ImportBinding importBinding = this.onDemandImportsCache[j];
char[][] importName = importBinding.compoundName;
char[] importFlatName = CharOperation.concatWith(importName, '.');
if(fullyQualifiedEnclosingTypeOrPackageName == null) {
if(enclosingTypeNames != null && enclosingTypeNames.length != 0) {
fullyQualifiedEnclosingTypeOrPackageName =
CharOperation.concat(
packageName,
flatEnclosingTypeNames,
'.');
} else {
fullyQualifiedEnclosingTypeOrPackageName =
packageName;
}
}
if(CharOperation.equals(fullyQualifiedEnclosingTypeOrPackageName, importFlatName)) {
if(importBinding.isStatic()) {
if((modifiers & ClassFileConstants.AccStatic) != 0) {
acceptedType.qualifiedTypeName = typeName;
acceptedType.fullyQualifiedName = fullyQualifiedName;
onDemandFound.put(
simpleTypeName,
acceptedType);
continue next;
}
} else {
acceptedType.qualifiedTypeName = typeName;
acceptedType.fullyQualifiedName = fullyQualifiedName;
onDemandFound.put(
simpleTypeName,
acceptedType);
continue next;
}
}
}
} else if(!foundType.mustBeQualified){
done : for (int j = 0; j < this.onDemandImportCacheCount; j++) {
ImportBinding importBinding = this.onDemandImportsCache[j];
char[][] importName = importBinding.compoundName;
char[] importFlatName = CharOperation.concatWith(importName, '.');
if(fullyQualifiedEnclosingTypeOrPackageName == null) {
if(enclosingTypeNames != null && enclosingTypeNames.length != 0) {
fullyQualifiedEnclosingTypeOrPackageName =
CharOperation.concat(
packageName,
flatEnclosingTypeNames,
'.');
} else {
fullyQualifiedEnclosingTypeOrPackageName =
packageName;
}
}
if(CharOperation.equals(fullyQualifiedEnclosingTypeOrPackageName, importFlatName)) {
if(importBinding.isStatic()) {
if((modifiers & ClassFileConstants.AccStatic) != 0) {
foundType.mustBeQualified = true;
break done;
}
} else {
foundType.mustBeQualified = true;
break done;
}
}
}
}
proposeType(
packageName,
simpleTypeName,
modifiers,
accessibility,
typeName,
fullyQualifiedName,
true,
scope);
}
}
}
char[][] keys = onDemandFound.keyTable;
Object[] values = onDemandFound.valueTable;
int max = keys.length;
for (int i = 0; i < max; i++) {
if ((i % CHECK_CANCEL_FREQUENCY) == 0) checkCancel();
if(keys[i] != null) {
AcceptedType value = (AcceptedType) values[i];
if(value != null) {
proposeType(
value.packageName,
value.simpleTypeName,
value.modifiers,
value.accessibility,
value.qualifiedTypeName,
value.fullyQualifiedName,
value.mustBeQualified,
scope);
}
}
}
} finally {
this.acceptedTypes = null; // reset
}
}
public void acceptUnresolvedName(char[] name) {
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution(false);
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(this.completionToken, name);
relevance += computeRelevanceForQualification(false);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for local variable
CompletionEngine.this.noProposal = false;
if(!CompletionEngine.this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) {
InternalCompletionProposal proposal = CompletionEngine.this.createProposal(CompletionProposal.LOCAL_VARIABLE_REF, CompletionEngine.this.actualCompletionPosition);
proposal.setSignature(JAVA_LANG_OBJECT_SIGNATURE);
proposal.setPackageName(JAVA_LANG_NAME);
proposal.setTypeName(OBJECT);
proposal.setName(name);
proposal.setCompletion(name);
proposal.setFlags(Flags.AccDefault);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
CompletionEngine.this.requestor.accept(proposal);
if(DEBUG) {
CompletionEngine.this.printDebug(proposal);
}
}
}
private void addExpectedType(TypeBinding type, Scope scope){
if (type == null || !type.isValidBinding() || type == TypeBinding.NULL) return;
// do not add twice the same type
for (int i = 0; i <= this.expectedTypesPtr; i++) {
if (TypeBinding.equalsEquals(this.expectedTypes[i], type)) return;
}
int length = this.expectedTypes.length;
if (++this.expectedTypesPtr >= length)
System.arraycopy(this.expectedTypes, 0, this.expectedTypes = new TypeBinding[length * 2], 0, length);
this.expectedTypes[this.expectedTypesPtr] = type;
if(TypeBinding.equalsEquals(type, scope.getJavaLangObject())) {
this.hasJavaLangObjectAsExpectedType = true;
}
}
private void addForbiddenBindings(Binding binding){
//{ObjectTeams: allow one-time recursion:
addForbiddenBindings(binding, 0);
}
private void addForbiddenBindings(Binding binding, int level){
// SH}
if (binding == null) return;
int length = this.forbbidenBindings.length;
if (++this.forbbidenBindingsPtr >= length)
System.arraycopy(this.forbbidenBindings, 0, this.forbbidenBindings = new Binding[length * 2], 0, length);
this.forbbidenBindings[this.forbbidenBindingsPtr] = binding;
//{ObjectTeams: other role part, too:
if (level == 0 && binding instanceof ReferenceBinding) {
ReferenceBinding type = (ReferenceBinding)binding;
if (type.isRole()) {
RoleModel role = type.roleModel;
ReferenceBinding otherPart = type.isClass() ? role.getInterfacePartBinding() : role.getClassPartBinding();
if (otherPart != null)
addForbiddenBindings(otherPart, 1);
}
}
// SH}
}
private void addUninterestingBindings(Binding binding){
if (binding == null) return;
int length = this.uninterestingBindings.length;
if (++this.uninterestingBindingsPtr >= length)
System.arraycopy(this.uninterestingBindings, 0, this.uninterestingBindings = new Binding[length * 2], 0, length);
this.uninterestingBindings[this.uninterestingBindingsPtr] = binding;
}
// this code is derived from MethodBinding#areParametersCompatibleWith(TypeBinding[])
private final boolean areParametersCompatibleWith(TypeBinding[] parameters, TypeBinding[] arguments, boolean isVarargs) {
int paramLength = parameters.length;
int argLength = arguments.length;
int lastIndex = argLength;
if (isVarargs) {
lastIndex = paramLength - 1;
if (paramLength == argLength) { // accept X[] but not X or X[][]
TypeBinding varArgType = parameters[lastIndex]; // is an ArrayBinding by definition
TypeBinding lastArgument = arguments[lastIndex];
if (TypeBinding.notEquals(varArgType, lastArgument) && !lastArgument.isCompatibleWith(varArgType))
return false;
} else if (paramLength < argLength) { // all remainig argument types must be compatible with the elementsType of varArgType
TypeBinding varArgType = ((ArrayBinding) parameters[lastIndex]).elementsType();
for (int i = lastIndex; i < argLength; i++)
if (TypeBinding.notEquals(varArgType, arguments[i]) && !arguments[i].isCompatibleWith(varArgType))
return false;
} else if (lastIndex != argLength) { // can call foo(int i, X ... x) with foo(1) but NOT foo();
return false;
}
// now compare standard arguments from 0 to lastIndex
} else {
if(paramLength != argLength)
return false;
}
for (int i = 0; i < lastIndex; i++)
if (TypeBinding.notEquals(parameters[i], arguments[i]) && !arguments[i].isCompatibleWith(parameters[i]))
return false;
return true;
}
private void buildContext(
ASTNode astNode,
ASTNode astNodeParent,
CompilationUnitDeclaration compilationUnitDeclaration,
Binding qualifiedBinding,
Scope scope) {
InternalCompletionContext context = new InternalCompletionContext();
if (this.requestor.isExtendedContextRequired()) {
context.setExtendedData(
this.typeRoot,
compilationUnitDeclaration,
this.lookupEnvironment,
scope,
astNode,
astNodeParent,
this.owner,
this.parser);
}
// build expected types context
if (this.expectedTypesPtr > -1) {
int length = this.expectedTypesPtr + 1;
char[][] expTypes = new char[length][];
char[][] expKeys = new char[length][];
for (int i = 0; i < length; i++) {
expTypes[i] = getSignature(this.expectedTypes[i]);
expKeys[i] = this.expectedTypes[i].computeUniqueKey();
}
context.setExpectedTypesSignatures(expTypes);
context.setExpectedTypesKeys(expKeys);
}
context.setOffset(this.actualCompletionPosition + 1 - this.offset);
// Set javadoc info
if (astNode instanceof CompletionOnJavadoc) {
this.assistNodeInJavadoc = ((CompletionOnJavadoc)astNode).getCompletionFlags();
context.setJavadoc(this.assistNodeInJavadoc);
}
if (!(astNode instanceof CompletionOnJavadoc)) {
CompletionScanner scanner = (CompletionScanner)this.parser.scanner;
context.setToken(scanner.completionIdentifier);
context.setTokenRange(
scanner.completedIdentifierStart - this.offset,
scanner.completedIdentifierEnd - this.offset,
scanner.endOfEmptyToken - this.offset);
} else if(astNode instanceof CompletionOnJavadocTag) {
CompletionOnJavadocTag javadocTag = (CompletionOnJavadocTag) astNode;
context.setToken(CharOperation.concat(new char[]{'@'}, javadocTag.token));
context.setTokenRange(
javadocTag.tagSourceStart - this.offset,
javadocTag.tagSourceEnd - this.offset,
((CompletionScanner)this.parser.javadocParser.scanner).endOfEmptyToken - this.offset);
} else {
CompletionScanner scanner = (CompletionScanner)this.parser.javadocParser.scanner;
context.setToken(scanner.completionIdentifier);
context.setTokenRange(
scanner.completedIdentifierStart - this.offset,
scanner.completedIdentifierEnd - this.offset,
scanner.endOfEmptyToken - this.offset);
}
if(astNode instanceof CompletionOnStringLiteral) {
context.setTokenKind(CompletionContext.TOKEN_KIND_STRING_LITERAL);
} else {
context.setTokenKind(CompletionContext.TOKEN_KIND_NAME);
}
buildTokenLocationContext(context, scope, astNode, astNodeParent);
if(DEBUG) {
System.out.println(context.toString());
}
this.requestor.acceptContext(context);
}
private void buildTokenLocationContext(InternalCompletionContext context, Scope scope, ASTNode astNode, ASTNode astNodeParent) {
if (scope == null || context.isInJavadoc()) return;
if (astNode instanceof CompletionOnFieldType) {
CompletionOnFieldType field = (CompletionOnFieldType) astNode;
if (!field.isLocalVariable &&
field.modifiers == ClassFileConstants.AccDefault &&
(field.annotations == null || field.annotations.length == 0)) {
context.setTokenLocation(CompletionContext.TL_MEMBER_START);
}
} else if (astNode instanceof CompletionOnMethodReturnType) {
CompletionOnMethodReturnType method = (CompletionOnMethodReturnType) astNode;
if (method.modifiers == ClassFileConstants.AccDefault &&
(method.annotations == null || method.annotations.length == 0)) {
context.setTokenLocation(CompletionContext.TL_MEMBER_START);
}
} else if (astNode instanceof CompletionOnSingleTypeReference) {
CompletionOnSingleTypeReference completionOnSingleTypeReference = (CompletionOnSingleTypeReference) astNode;
if (completionOnSingleTypeReference.isConstructorType) {
context.setTokenLocation(CompletionContext.TL_CONSTRUCTOR_START);
}
} else if (astNode instanceof CompletionOnQualifiedTypeReference) {
CompletionOnQualifiedTypeReference completionOnQualifiedTypeReference = (CompletionOnQualifiedTypeReference) astNode;
if (completionOnQualifiedTypeReference.isConstructorType){
context.setTokenLocation(CompletionContext.TL_CONSTRUCTOR_START);
}
} else if (astNode instanceof CompletionOnKeyword3 && ((CompletionOnKeyword3) astNode).afterTryOrCatch()) {
context.setTokenLocation(CompletionContext.TL_STATEMENT_START);
} else {
ReferenceContext referenceContext = scope.referenceContext();
if (referenceContext instanceof AbstractMethodDeclaration) {
AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration)referenceContext;
if (methodDeclaration.bodyStart <= astNode.sourceStart &&
astNode.sourceEnd <= methodDeclaration.bodyEnd) {
// completion is inside a method body
if (astNodeParent == null &&
astNode instanceof CompletionOnSingleNameReference &&
!((CompletionOnSingleNameReference)astNode).isPrecededByModifiers) {
context.setTokenLocation(CompletionContext.TL_STATEMENT_START);
}
}
} else if (referenceContext instanceof LambdaExpression) {
LambdaExpression expression = (LambdaExpression)referenceContext;
if (expression.body().sourceStart <= astNode.sourceStart &&
astNode.sourceEnd <= expression.body().sourceEnd) {
// completion is inside a method body
if ((astNodeParent == null || astNodeParent == expression) &&
astNode instanceof CompletionOnSingleNameReference &&
!((CompletionOnSingleNameReference)astNode).isPrecededByModifiers) {
context.setTokenLocation(CompletionContext.TL_STATEMENT_START);
}
}
} else if (referenceContext instanceof TypeDeclaration) {
TypeDeclaration typeDeclaration = (TypeDeclaration) referenceContext;
FieldDeclaration[] fields = typeDeclaration.fields;
if (fields != null) {
done : for (int i = 0; i < fields.length; i++) {
if (fields[i] instanceof Initializer) {
Initializer initializer = (Initializer) fields[i];
if (initializer.block.sourceStart <= astNode.sourceStart &&
astNode.sourceStart < initializer.bodyEnd) {
// completion is inside an initializer
if (astNodeParent == null &&
astNode instanceof CompletionOnSingleNameReference &&
!((CompletionOnSingleNameReference)astNode).isPrecededByModifiers) {
context.setTokenLocation(CompletionContext.TL_STATEMENT_START);
}
break done;
}
}
}
}
}
}
}
void checkCancel() {
if (this.monitor != null && this.monitor.isCanceled()) {
throw new OperationCanceledException();
}
}
private boolean complete(
ASTNode astNode,
ASTNode astNodeParent,
ASTNode enclosingNode,
CompilationUnitDeclaration compilationUnitDeclaration,
Binding qualifiedBinding,
Scope scope,
boolean insideTypeAnnotation) {
setSourceAndTokenRange(astNode.sourceStart, astNode.sourceEnd);
scope = computeForbiddenBindings(astNode, astNodeParent, scope);
computeUninterestingBindings(astNode, astNodeParent, scope);
if(astNodeParent != null) {
if(!isValidParent(astNodeParent, astNode, scope)) return false;
computeExpectedTypes(astNodeParent, astNode, scope);
}
buildContext(astNode, astNodeParent, compilationUnitDeclaration, qualifiedBinding, scope);
if (astNode instanceof CompletionOnMemberAccess && qualifiedBinding instanceof BaseTypeBinding) return true;
if (astNode instanceof CompletionOnFieldType) {
completionOnFieldType(astNode, scope);
} else if (astNode instanceof CompletionOnMethodReturnType) {
completionOnMethodReturnType(astNode, scope);
} else if (astNode instanceof CompletionOnSingleNameReference) {
completionOnSingleNameReference(astNode, astNodeParent, scope, insideTypeAnnotation);
} else if (astNode instanceof CompletionOnProvidesInterfacesQualifiedTypeReference) {
completionOnProvidesInterfacesQualifiedTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
} else if (astNode instanceof CompletionOnProvidesInterfacesSingleTypeReference) {
completionOnProvidesInterfacesSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
} else if (astNode instanceof CompletionOnProvidesImplementationsQualifiedTypeReference) {
completionOnProvidesImplementationsQualifiedTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
} else if (astNode instanceof CompletionOnProvidesImplementationsSingleTypeReference) {
completionOnProvidesImplementationsSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
} else if (astNode instanceof CompletionOnSingleTypeReference) {
completionOnSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
} else if (astNode instanceof CompletionOnQualifiedNameReference) {
completionOnQualifiedNameReference(astNode, enclosingNode, qualifiedBinding, scope, insideTypeAnnotation);
} else if (astNode instanceof CompletionOnQualifiedTypeReference) {
completionOnQualifiedTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
} else if (astNode instanceof CompletionOnMemberAccess) {
completionOnMemberAccess(astNode, enclosingNode, qualifiedBinding, scope, insideTypeAnnotation);
} else if (astNode instanceof CompletionOnMessageSend) {
completionOnMessageSend(astNode, qualifiedBinding, scope);
//{ObjectTeams: complete rhs method spec in a callout or callin:
} else if (astNode instanceof CompletionOnMethodSpec) {
completionOnMethodSpec(astNode, qualifiedBinding, scope);
} else if (astNode instanceof CompletionOnFieldAccessSpec) {
completionOnFieldAccessSpec(astNode, qualifiedBinding, scope);
// SH}
} else if (astNode instanceof CompletionOnExplicitConstructorCall) {
completionOnExplicitConstructorCall(astNode, qualifiedBinding, scope);
} else if (astNode instanceof CompletionOnQualifiedAllocationExpression) {
completionOnQualifiedAllocationExpression(astNode, qualifiedBinding, scope);
} else if (astNode instanceof CompletionOnClassLiteralAccess) {
completionOnClassLiteralAccess(astNode, qualifiedBinding, scope);
} else if (astNode instanceof CompletionOnMethodName) {
completionOnMethodName(astNode, scope);
} else if (astNode instanceof CompletionOnFieldName) {
completionOnFieldName(astNode, scope);
} else if (astNode instanceof CompletionOnLocalName) {
completionOnLocalOrArgumentName(astNode, scope);
} else if (astNode instanceof CompletionOnArgumentName) {
completionOnLocalOrArgumentName(astNode, scope);
} else if (astNode instanceof CompletionOnKeyword) {
completionOnKeyword(astNode);
} else if (astNode instanceof CompletionOnParameterizedQualifiedTypeReference) {
completionOnParameterizedQualifiedTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
} else if (astNode instanceof CompletionOnMarkerAnnotationName) {
completionOnMarkerAnnotationName(astNode, qualifiedBinding, scope);
} else if (astNode instanceof CompletionOnMemberValueName) {
completionOnMemberValueName(astNode, astNodeParent, scope, insideTypeAnnotation);
} else if(astNode instanceof CompletionOnBranchStatementLabel) {
completionOnBranchStatementLabel(astNode);
} else if(astNode instanceof CompletionOnMessageSendName) {
completionOnMessageSendName(astNode, qualifiedBinding, scope);
} else if (astNode instanceof CompletionOnReferenceExpressionName) {
completionOnReferenceExpressionName(astNode, qualifiedBinding, scope);
// Completion on Javadoc nodes
} else if ((astNode.bits & ASTNode.InsideJavadoc) != 0) {
if (astNode instanceof CompletionOnJavadocSingleTypeReference) {
completionOnJavadocSingleTypeReference(astNode, scope);
} else if (astNode instanceof CompletionOnJavadocQualifiedTypeReference) {
completionOnJavadocQualifiedTypeReference(astNode, qualifiedBinding, scope);
} else if (astNode instanceof CompletionOnJavadocFieldReference) {
completionOnJavadocFieldReference(astNode, scope);
} else if (astNode instanceof CompletionOnJavadocMessageSend) {
completionOnJavadocMessageSend(astNode, qualifiedBinding, scope);
} else if (astNode instanceof CompletionOnJavadocAllocationExpression) {
completionOnJavadocAllocationExpression(astNode, qualifiedBinding, scope);
} else if (astNode instanceof CompletionOnJavadocParamNameReference) {
completionOnJavadocParamNameReference(astNode);
} else if (astNode instanceof CompletionOnJavadocTypeParamReference) {
completionOnJavadocTypeParamReference(astNode);
} else if (astNode instanceof CompletionOnJavadocTag) {
completionOnJavadocTag(astNode);
}
}
return true;
}
/**
* Ask the engine to compute a completion at the specified position
* of the given compilation unit.
*
* No return
* completion results are answered through a requestor.
*
* @param sourceUnit org.eclipse.jdt.internal.compiler.env.ICompilationUnit
* the source of the current compilation unit.
*
* @param completionPosition int
* a position in the source where the completion is taking place.
* This position is relative to the source provided.
*/
public void complete(ICompilationUnit sourceUnit, int completionPosition, int pos, ITypeRoot root) {
if(DEBUG) {
System.out.print("COMPLETION IN "); //$NON-NLS-1$
System.out.print(sourceUnit.getFileName());
System.out.print(" AT POSITION "); //$NON-NLS-1$
System.out.println(completionPosition);
System.out.println("COMPLETION - Source :"); //$NON-NLS-1$
System.out.println(sourceUnit.getContents());
}
if (this.monitor != null) this.monitor.beginTask(Messages.engine_completing, IProgressMonitor.UNKNOWN);
this.requestor.beginReporting();
boolean contextAccepted = false;
try {
this.fileName = sourceUnit.getFileName();
this.actualCompletionPosition = completionPosition - 1;
this.offset = pos;
this.typeRoot = root;
this.checkCancel();
// for now until we can change the UI.
CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
CompilationUnitDeclaration parsedUnit = this.parser.dietParse(sourceUnit, result, this.actualCompletionPosition);
// boolean completionNodeFound = false;
if (parsedUnit != null) {
if(DEBUG) {
System.out.println("COMPLETION - Diet AST :"); //$NON-NLS-1$
System.out.println(parsedUnit.toString());
}
if (parsedUnit.isModuleInfo()) {
this.moduleDeclaration = parsedUnit.moduleDeclaration;
if (this.moduleDeclaration == null) return;
if (this.moduleDeclaration instanceof CompletionOnModuleDeclaration) {
contextAccepted = true;
buildContext(parsedUnit.moduleDeclaration, null, parsedUnit, null, null);
//this.requestor.setIgnored(CompletionProposal.MODULE_DECLARATION, false); //TODO: Hack until ui fixes this issue.
if(!this.requestor.isIgnored(CompletionProposal.MODULE_DECLARATION)) {
proposeModuleName(parsedUnit);
}
debugPrintf();
return;
}
if (this.moduleDeclaration instanceof CompletionOnKeywordModuleDeclaration) {
contextAccepted = true;
processModuleKeywordCompletion(parsedUnit, this.moduleDeclaration, (CompletionOnKeyword) this.moduleDeclaration);
return;
}
if (this.moduleDeclaration.exports != null) {
contextAccepted = completeOnPackageVisibilityStatements(contextAccepted, parsedUnit, this.moduleDeclaration.exports);
if (contextAccepted) return;
}
if (this.moduleDeclaration.opens != null) {
contextAccepted = completeOnPackageVisibilityStatements(contextAccepted, parsedUnit, this.moduleDeclaration.opens);
if (contextAccepted) return;
}
RequiresStatement[] moduleRefs = this.moduleDeclaration.requires;
if (moduleRefs != null) {
for (int i = 0, l = moduleRefs.length; i < l; ++i) {
ModuleReference reference = moduleRefs[i].module;
if (reference instanceof CompletionOnModuleReference) {
contextAccepted = true;
buildContext(reference, null, parsedUnit, null, null);
if(!this.requestor.isIgnored(CompletionProposal.MODULE_REF)) {
findModules((CompletionOnModuleReference) reference, false /* targetted */);
}
debugPrintf();
return;
}
}
}
try {
UsesStatement[] uses = this.moduleDeclaration.uses;
if (uses != null) {
for (int i = 0, l = uses.length; i < l; ++i) {
UsesStatement usesStatement = uses[i];
this.parser.enclosingNode = usesStatement;
TypeReference usesReference = usesStatement.serviceInterface;
if (usesReference instanceof CompletionOnUsesSingleTypeReference ||
usesReference instanceof CompletionOnUsesQualifiedTypeReference) {
contextAccepted = checkForCNF(usesReference, parsedUnit, true);
return;
}
}
}
ProvidesStatement[] providesStmts = this.moduleDeclaration.services;
for (int i = 0, l = providesStmts != null ? providesStmts.length : 0; i < l; ++i) {
ProvidesStatement providesStmt = providesStmts[i];
this.parser.enclosingNode = providesStmt;
TypeReference pInterface = providesStmt.serviceInterface;
if (pInterface instanceof CompletionOnProvidesInterfacesSingleTypeReference ||
pInterface instanceof CompletionOnProvidesInterfacesQualifiedTypeReference) {
contextAccepted = checkForCNF(pInterface, parsedUnit, true);
return;
}
TypeReference[] implementations = providesStmt.implementations;
for (int j = 0, k = implementations.length; j < k; ++j) {
TypeReference implementation = implementations[j];
if (implementation instanceof CompletionOnProvidesImplementationsSingleTypeReference ||
implementation instanceof CompletionOnProvidesImplementationsQualifiedTypeReference) {
this.skipDefaultPackage = true;
contextAccepted = checkForCNF(implementation, parsedUnit, false);
return;
} else if (implementation instanceof CompletionOnKeyword) {
contextAccepted = true;
processModuleKeywordCompletion(parsedUnit, implementation, (CompletionOnKeyword) implementation);
}
}
}
} catch (CompletionNodeFound e) {
// completionNodeFound = true;
if (e.astNode != null) {
// if null then we found a problem in the completion node
if(DEBUG) {
System.out.print("COMPLETION - Completion node : "); //$NON-NLS-1$
System.out.println(e.astNode.toString());
if(this.parser.assistNodeParent != null) {
System.out.print("COMPLETION - Parent Node : "); //$NON-NLS-1$
System.out.println(this.parser.assistNodeParent);
}
}
this.lookupEnvironment.unitBeingCompleted = parsedUnit; // better resilient to further error reporting
contextAccepted =
complete(
e.astNode,
this.parser.assistNodeParent,
this.parser.enclosingNode,
parsedUnit,
e.qualifiedBinding,
e.scope,
e.insideTypeAnnotation);
}
} finally {
this.skipDefaultPackage = false;
}
}
// scan the package & import statements first
if (parsedUnit.currentPackage instanceof CompletionOnPackageReference) {
contextAccepted = true;
buildContext(parsedUnit.currentPackage, null, parsedUnit, null, null);
if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
findPackages((CompletionOnPackageReference) parsedUnit.currentPackage);
}
debugPrintf();
return;
}
ImportReference[] imports = parsedUnit.imports;
if (imports != null) {
for (int i = 0, length = imports.length; i < length; i++) {
ImportReference importReference = imports[i];
if (importReference instanceof CompletionOnImportReference) {
//{ObjectTeams: guard with setup/release, rely on Dependencies instead of manually invoking three steps:
try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true))
{
// km(merge) }
this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
if ((this.unitScope = parsedUnit.scope) != null) {
contextAccepted = true;
buildContext(importReference, null, parsedUnit, null, null);
long positions = importReference.sourcePositions[importReference.tokens.length - 1];
setSourceAndTokenRange((int) (positions >>> 32), (int) positions);
char[][] oldTokens = importReference.tokens;
int tokenCount = oldTokens.length;
if (tokenCount == 1) {
findImports((CompletionOnImportReference)importReference, true);
} else if(tokenCount > 1){
this.insideQualifiedReference = true;
char[] lastToken = oldTokens[tokenCount - 1];
char[][] qualifierTokens = CharOperation.subarray(oldTokens, 0, tokenCount - 1);
Binding binding = this.unitScope.getTypeOrPackage(qualifierTokens);
if(binding != null) {
if(binding instanceof PackageBinding) {
findImports((CompletionOnImportReference)importReference, false);
} else {
ReferenceBinding ref = (ReferenceBinding) binding;
if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
findImportsOfMemberTypes(lastToken, ref, importReference.isStatic());
}
if(importReference.isStatic()) {
if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) {
findImportsOfStaticFields(lastToken, ref);
}
if(!this.requestor.isIgnored(CompletionProposal.METHOD_NAME_REFERENCE)) {
findImportsOfStaticMethods(lastToken, ref);
}
}
}
}
}
debugPrintf();
}
//{ObjectTeams:
}
// km(merge) }
return;
} else if(importReference instanceof CompletionOnKeyword) {
contextAccepted = true;
buildContext(importReference, null, parsedUnit, null, null);
if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
setSourceAndTokenRange(importReference.sourceStart, importReference.sourceEnd);
CompletionOnKeyword keyword = (CompletionOnKeyword)importReference;
findKeywords(keyword.getToken(), keyword.getPossibleKeywords(), false, parsedUnit.currentPackage != null);
}
debugPrintf();
return;
}
}
}
// javadoc tag completion in module-info file
contextAccepted = completeJavadocTagInModuleInfo(parsedUnit);
if (parsedUnit.types != null) {
//{ObjectTeams: guard this block by setup/release (don't merge with existing try, since catch still needs the Config):
try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true))
// statements are explicitly requested for the completion position, other statements are not needed
{
// orig:
try {
this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
if ((this.unitScope = parsedUnit.scope) != null) {
this.source = sourceUnit.getContents();
this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
/*
parsedUnit.scope.faultInTypes();
:giro */
Dependencies.ensureState(parsedUnit, ITranslationStates.STATE_METHODS_PARSED-1);
// orig:
parseBlockStatements(parsedUnit, this.actualCompletionPosition);
// :giro
StateHelper.setStateRecursive(parsedUnit, ITranslationStates.STATE_METHODS_PARSED, true);
// orig:
if(DEBUG) {
System.out.println("COMPLETION - AST :"); //$NON-NLS-1$
System.out.println(parsedUnit.toString());
}
// :giro
/* orig:
parsedUnit.resolve();
:giro */
Dependencies.ensureState(parsedUnit, ITranslationStates.STATE_LATE_ELEMENTS_COPIED);
// generateStatements also resolves some, notably parameter mappings as inserted into mapping wrappers.
// orig:
}
} catch (CompletionNodeFound e) {
// OT: Dependencies might drive to CompletionNodeFound already during buildTypeBindings:
if (this.unitScope == null)
this.unitScope = parsedUnit.scope;
// :TO
// completionNodeFound = true;
if (e.astNode != null) {
// if null then we found a problem in the completion node
if(DEBUG) {
System.out.print("COMPLETION - Completion node : "); //$NON-NLS-1$
System.out.println(e.astNode.toString());
if(this.parser.assistNodeParent != null) {
System.out.print("COMPLETION - Parent Node : "); //$NON-NLS-1$
System.out.println(this.parser.assistNodeParent);
}
}
this.lookupEnvironment.unitBeingCompleted = parsedUnit; // better resilient to further error reporting
contextAccepted =
complete(
e.astNode,
this.parser.assistNodeParent,
this.parser.enclosingNode,
parsedUnit,
e.qualifiedBinding,
e.scope,
e.insideTypeAnnotation);
}
}
// :giro
}
// SH}
}
}
if(this.noProposal && this.problem != null) {
if(!contextAccepted) {
contextAccepted = true;
InternalCompletionContext context = new InternalCompletionContext();
context.setOffset(completionPosition - this.offset);
context.setTokenKind(CompletionContext.TOKEN_KIND_UNKNOWN);
if (this.requestor.isExtendedContextRequired()) context.setExtended();
this.requestor.acceptContext(context);
}
this.requestor.completionFailure(this.problem);
if(DEBUG) {
this.printDebug(this.problem);
}
}
/* Ignore package, import, class & interface keywords for now...
if (!completionNodeFound) {
if (parsedUnit == null || parsedUnit.types == null) {
// this is not good enough... can still be trying to define a second type
CompletionScanner scanner = (CompletionScanner) this.parser.scanner;
setSourceRange(scanner.completedIdentifierStart, scanner.completedIdentifierEnd);
findKeywords(scanner.completionIdentifier, mainDeclarations, null);
}
// currently have no way to know if extends/implements are possible keywords
}
*/
} catch (IndexOutOfBoundsException | InvalidCursorLocation | AbortCompilation | CompletionNodeFound e){ // internal failure - bugs 5618
if(DEBUG) {
System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
e.printStackTrace(System.out);
}
} finally {
if(!contextAccepted) {
contextAccepted = true;
InternalCompletionContext context = new InternalCompletionContext();
context.setTokenKind(CompletionContext.TOKEN_KIND_UNKNOWN);
context.setOffset(completionPosition - this.offset);
if (this.requestor.isExtendedContextRequired()) context.setExtended();
this.requestor.acceptContext(context);
}
this.requestor.endReporting();
if (this.monitor != null) this.monitor.done();
reset();
}
}
private boolean completeJavadocTagInModuleInfo(CompilationUnitDeclaration parsedUnit) {
boolean contextAccepted = false;
if (this.parser.assistNodeParent instanceof CompletionJavadoc && parsedUnit.isModuleInfo() ) {
try {
this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
if(this.parser.assistNode instanceof CompletionOnJavadocTag) {
((CompletionOnJavadocTag)this.parser.assistNode).filterPossibleTags(parsedUnit.scope);
}
throw new CompletionNodeFound(this.parser.assistNode, null, parsedUnit.scope);
}
catch (CompletionNodeFound e) {
this.unitScope = parsedUnit.scope;
if (e.astNode != null) {
// if null then we found a problem in the completion node
if(DEBUG) {
System.out.print("COMPLETION - Completion node : "); //$NON-NLS-1$
System.out.println(e.astNode.toString());
if(this.parser.assistNodeParent != null) {
System.out.print("COMPLETION - Parent Node : "); //$NON-NLS-1$
System.out.println(this.parser.assistNodeParent);
}
}
this.lookupEnvironment.unitBeingCompleted = parsedUnit; // better resilient to further error reporting
contextAccepted =
complete(
e.astNode,
this.parser.assistNodeParent,
this.parser.enclosingNode,
parsedUnit,
e.qualifiedBinding,
e.scope,
e.insideTypeAnnotation);
}
}
}
return contextAccepted;
}
private boolean checkForCNF(TypeReference ref, CompilationUnitDeclaration parsedUnit, boolean showAll) {
//{ObjectTeams: protect:
try (Config cfg = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true)) {
// orig:
this.lookupEnvironment.buildTypeBindings(parsedUnit, null);
this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
parsedUnit.resolve();
this.startPosition = ref.sourceStart;
this.endPosition = ref.sourceEnd > ref.sourceStart ? ref.sourceEnd : ref.sourceStart;
if ((this.unitScope = parsedUnit.scope) != null) {
if (showAll) {
char[][] tokens = ref.getTypeName();
char[] typeName = CharOperation.concatWithAll(tokens, '.');
if (typeName.length == 0) {
buildContext(ref, null, parsedUnit, null, null);
this.completionToken = new char[] {'*'};
findTypesAndPackages(this.completionToken, this.unitScope, true, true, new ObjectVector());
return true;
}
}
parsedUnit.scope.faultInTypes();
}
return false; // should not come here - will throw exception
// :giro
}
// SH}
}
private boolean completeOnPackageVisibilityStatements(boolean contextAccepted,
CompilationUnitDeclaration parsedUnit, PackageVisibilityStatement[] pvsStmts) {
try {
this.skipDefaultPackage = true;
for (int i = 0, l = pvsStmts.length; i < l; ++i) {
PackageVisibilityStatement pvs = pvsStmts[i];
if (pvs instanceof CompletionOnKeywordModuleInfo) { // dummy pvs statement
contextAccepted = true;
processModuleKeywordCompletion(parsedUnit, pvs, (CompletionOnKeyword) pvs);
return contextAccepted;
}
if (pvs.pkgRef instanceof CompletionOnPackageVisibilityReference) {
contextAccepted = true;
buildContext(pvs, null, parsedUnit, null, null);
if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
findPackages((CompletionOnPackageVisibilityReference) pvs.pkgRef);
}
debugPrintf();
return contextAccepted;
}
ModuleReference[] targets = pvs.targets;
if (targets == null) continue;
HashSet<String> skipSet = new HashSet<>();
for (int j = 0, lj = targets.length; j < lj; j++) {
ModuleReference target = targets[j];
if (target == null) break;
if (target instanceof CompletionOnModuleReference) {
buildContext(target, null, parsedUnit, null, null);
contextAccepted = true;
if(!this.requestor.isIgnored(CompletionProposal.MODULE_REF)) {
findTargettedModules((CompletionOnModuleReference) target, skipSet);
}
debugPrintf();
return contextAccepted;
} else if (target instanceof CompletionOnKeyword) {
contextAccepted = true;
processModuleKeywordCompletion(parsedUnit, target, (CompletionOnKeyword) target);
} else {
if (target.moduleName != null || target.moduleName == CharOperation.NO_CHAR)
skipSet.add(new String(target.moduleName));
}
}
}
} finally {
this.skipDefaultPackage = false;
}
return contextAccepted;
}
private void debugPrintf() {
if(this.noProposal && this.problem != null) {
this.requestor.completionFailure(this.problem);
if(DEBUG) {
this.printDebug(this.problem);
}
}
}
private void processModuleKeywordCompletion(CompilationUnitDeclaration parsedUnit, ASTNode node, CompletionOnKeyword keyword) {
buildContext(node, null, parsedUnit, null, null);
if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
setSourceAndTokenRange(node.sourceStart, node.sourceEnd);
findKeywords(keyword.getToken(), keyword.getPossibleKeywords(), false, parsedUnit.currentPackage != null);
}
debugPrintf();
}
public void complete(IType type, char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){
if(this.requestor != null){
this.requestor.beginReporting();
}
boolean contextAccepted = false;
IType topLevelType = type;
while(topLevelType.getDeclaringType() != null) {
topLevelType = topLevelType.getDeclaringType();
}
this.fileName = topLevelType.getParent().getElementName().toCharArray();
CompilationResult compilationResult = new CompilationResult(this.fileName, 1, 1, this.compilerOptions.maxProblemsPerUnit);
CompilationUnitDeclaration compilationUnit = null;
try {
// TypeConverter is used instead of SourceTypeConverter because the type
// to convert can be a binary type or a source type
TypeDeclaration typeDeclaration = null;
if (type instanceof SourceType) {
SourceType sourceType = (SourceType) type;
ISourceType info = (ISourceType) sourceType.getElementInfo();
compilationUnit = SourceTypeConverter.buildCompilationUnit(
new ISourceType[] {info},//sourceTypes[0] is always toplevel here
SourceTypeConverter.FIELD_AND_METHOD // need field and methods
| SourceTypeConverter.MEMBER_TYPE, // need member types
// no need for field initialization
this.problemReporter,
compilationResult);
if (compilationUnit != null && compilationUnit.types != null)
typeDeclaration = compilationUnit.types[0];
} else {
compilationUnit = new CompilationUnitDeclaration(this.problemReporter, compilationResult, 0);
typeDeclaration = new BinaryTypeConverter(this.parser.problemReporter(), compilationResult, null/*no need to remember type names*/).buildTypeDeclaration(type, compilationUnit);
}
if(typeDeclaration != null) {
// build AST from snippet
Initializer fakeInitializer = parseSnippeInitializer(snippet, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic);
// merge AST
FieldDeclaration[] oldFields = typeDeclaration.fields;
FieldDeclaration[] newFields = null;
if (oldFields != null) {
newFields = new FieldDeclaration[oldFields.length + 1];
System.arraycopy(oldFields, 0, newFields, 0, oldFields.length);
newFields[oldFields.length] = fakeInitializer;
} else {
newFields = new FieldDeclaration[] {fakeInitializer};
}
typeDeclaration.fields = newFields;
if(DEBUG) {
System.out.println("SNIPPET COMPLETION AST :"); //$NON-NLS-1$
System.out.println(compilationUnit.toString());
}
if (compilationUnit.types != null) {
//{ObjectTeams: guard with setup/release, rely on Dependencies instead of manually invoking three steps:
try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true))
{
//orig:
try {
this.lookupEnvironment.buildTypeBindings(compilationUnit, null /*no access restriction*/);
if ((this.unitScope = compilationUnit.scope) != null) {
this.lookupEnvironment.completeTypeBindings(compilationUnit, true);
//:giro
/* orig:
compilationUnit.scope.faultInTypes();
compilationUnit.resolve();
:giro */
Dependencies.ensureState(compilationUnit, ITranslationStates.STATE_LATE_ELEMENTS_COPIED);
// generateStatements also resolves some, notably parameter mappings as inserted into mapping wrappers.
// orig:
}
} catch (CompletionNodeFound e) {
// completionNodeFound = true;
if (e.astNode != null) {
// if null then we found a problem in the completion node
contextAccepted =
complete(
e.astNode,
this.parser.assistNodeParent,
this.parser.enclosingNode,
compilationUnit,
e.qualifiedBinding,
e.scope,
e.insideTypeAnnotation);
}
}
// :giro
}
// SH}
}
if(this.noProposal && this.problem != null) {
if(!contextAccepted) {
contextAccepted = true;
InternalCompletionContext context = new InternalCompletionContext();
if (this.requestor.isExtendedContextRequired()) context.setExtended();
this.requestor.acceptContext(context);
}
this.requestor.completionFailure(this.problem);
if(DEBUG) {
this.printDebug(this.problem);
}
}
}
} catch (IndexOutOfBoundsException | InvalidCursorLocation | AbortCompilation | CompletionNodeFound e){ // internal failure - bugs 5618 (added with fix of 99629)
if(DEBUG) {
System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
e.printStackTrace(System.out);
}
} catch(JavaModelException e) {
// Do nothing
}
if(!contextAccepted) {
contextAccepted = true;
InternalCompletionContext context = new InternalCompletionContext();
if (this.requestor.isExtendedContextRequired()) context.setExtended();
this.requestor.acceptContext(context);
}
if(this.requestor != null){
this.requestor.endReporting();
}
}
private void completionOnBranchStatementLabel(ASTNode astNode) {
if (!this.requestor.isIgnored(CompletionProposal.LABEL_REF)) {
CompletionOnBranchStatementLabel label = (CompletionOnBranchStatementLabel) astNode;
this.completionToken = label.label;
findLabels(this.completionToken, label.possibleLabels);
}
}
private void completionOnClassLiteralAccess(ASTNode astNode, Binding qualifiedBinding, Scope scope) {
if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) {
CompletionOnClassLiteralAccess access = (CompletionOnClassLiteralAccess) astNode;
setSourceAndTokenRange(access.classStart, access.sourceEnd);
this.completionToken = access.completionIdentifier;
findClassField(
this.completionToken,
(TypeBinding) qualifiedBinding,
scope,
null,
null,
null,
false);
}
}
private void completionOnExplicitConstructorCall(ASTNode astNode, Binding qualifiedBinding, Scope scope) {
if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
setSourceAndTokenRange(astNode.sourceStart, astNode.sourceEnd, false);
CompletionOnExplicitConstructorCall constructorCall = (CompletionOnExplicitConstructorCall) astNode;
TypeBinding[] argTypes = computeTypes(constructorCall.arguments);
findConstructors(
(ReferenceBinding) qualifiedBinding,
argTypes,
scope,
constructorCall,
false,
null,
null,
null,
false);
}
}
private void completionOnFieldName(ASTNode astNode, Scope scope) {
if (!this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) {
CompletionOnFieldName field = (CompletionOnFieldName) astNode;
FieldBinding[] fields = scope.enclosingSourceType().fields();
char[][] excludeNames = new char[fields.length][];
for(int i = 0 ; i < fields.length ; i++){
excludeNames[i] = fields[i].name;
}
this.completionToken = field.realName;
int kind =
(field.modifiers & ClassFileConstants.AccStatic) == 0 ?
InternalNamingConventions.VK_INSTANCE_FIELD :
(field.modifiers & ClassFileConstants.AccFinal) == 0 ?
InternalNamingConventions.VK_STATIC_FIELD :
InternalNamingConventions.VK_STATIC_FINAL_FIELD;
findVariableNames(field.realName, field.type, excludeNames, null, kind);
}
}
private void completionOnFieldType(ASTNode astNode, Scope scope) {
CompletionOnFieldType field = (CompletionOnFieldType) astNode;
CompletionOnSingleTypeReference type = (CompletionOnSingleTypeReference) field.type;
this.completionToken = type.token;
setSourceAndTokenRange(type.sourceStart, type.sourceEnd);
findTypesAndPackages(this.completionToken, scope, true, true, new ObjectVector());
if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
findKeywordsForMember(this.completionToken, field.modifiers, astNode);
}
if (!field.isLocalVariable && field.modifiers == ClassFileConstants.AccDefault) {
SourceTypeBinding enclosingType = scope.enclosingSourceType();
if (!enclosingType.isAnnotationType()) {
if (!this.requestor.isIgnored(CompletionProposal.METHOD_DECLARATION)) {
findMethodDeclarations(
this.completionToken,
enclosingType,
scope,
new ObjectVector(),
null,
null,
null,
false);
}
if (!this.requestor.isIgnored(CompletionProposal.POTENTIAL_METHOD_DECLARATION)) {
proposeNewMethod(this.completionToken, enclosingType);
}
//{ObjectTeams: override-role proposals?
if (!this.requestor.isIgnored(CompletionProposal.OVERRIDE_ROLE_DECLARATION)) {
findOverridableRoles(enclosingType);
}
// SH}
}
}
}
//TODO
private void completionOnJavadocAllocationExpression(ASTNode astNode, Binding qualifiedBinding, Scope scope) {
// setSourceRange(astNode.sourceStart, astNode.sourceEnd, false);
CompletionOnJavadocAllocationExpression allocExpression = (CompletionOnJavadocAllocationExpression) astNode;
this.javadocTagPosition = allocExpression.tagSourceStart;
int rangeStart = astNode.sourceStart;
if (allocExpression.type.isThis()) {
if (allocExpression.completeInText()) {
rangeStart = allocExpression.separatorPosition;
}
} else if (allocExpression.completeInText()) {
rangeStart = allocExpression.type.sourceStart;
}
setSourceAndTokenRange(rangeStart, astNode.sourceEnd, false);
TypeBinding[] argTypes = computeTypes(allocExpression.arguments);
ReferenceBinding ref = (ReferenceBinding) qualifiedBinding;
if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF) && ref.isClass()) {
findConstructors(ref, argTypes, scope, allocExpression, false, null, null, null, false);
}
}
//TODO
private void completionOnJavadocFieldReference(ASTNode astNode, Scope scope) {
this.insideQualifiedReference = true;
CompletionOnJavadocFieldReference fieldRef = (CompletionOnJavadocFieldReference) astNode;
this.completionToken = fieldRef.token;
long completionPosition = fieldRef.nameSourcePosition;
this.javadocTagPosition = fieldRef.tagSourceStart;
if (fieldRef.actualReceiverType != null && fieldRef.actualReceiverType.isValidBinding()) {
ReferenceBinding receiverType = (ReferenceBinding) fieldRef.actualReceiverType;
int rangeStart = (int) (completionPosition >>> 32);
if (fieldRef.receiver.isThis()) {
if (fieldRef.completeInText()) {
rangeStart = fieldRef.separatorPosition;
}
} else if (fieldRef.completeInText()) {
rangeStart = fieldRef.receiver.sourceStart;
}
setSourceAndTokenRange(rangeStart, (int) completionPosition);
if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)
|| !this.requestor.isIgnored(CompletionProposal.JAVADOC_FIELD_REF)) {
findFields(this.completionToken,
receiverType,
scope,
new ObjectVector(),
new ObjectVector(),
false, /*not only static */
fieldRef,
scope,
false,
true,
null,
null,
null,
false,
null,
-1,
-1);
}
if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)
|| !this.requestor.isIgnored(CompletionProposal.JAVADOC_METHOD_REF)) {
findMethods(
this.completionToken,
null,
null,
receiverType,
scope,
new ObjectVector(),
false, /*not only static */
false,
fieldRef,
scope,
false,
false,
true,
null,
null,
null,
false,
null,
-1,
-1);
if (fieldRef.actualReceiverType instanceof ReferenceBinding) {
ReferenceBinding refBinding = (ReferenceBinding)fieldRef.actualReceiverType;
if (this.completionToken == null
|| CharOperation.prefixEquals(this.completionToken, refBinding.sourceName)
|| (this.options.camelCaseMatch && CharOperation.camelCaseMatch(this.completionToken, refBinding.sourceName))) {
findConstructors(refBinding, null, scope, fieldRef, false, null, null, null, false);
}
}
}
}
}
//TODO
private void completionOnJavadocMessageSend(ASTNode astNode, Binding qualifiedBinding, Scope scope) {
CompletionOnJavadocMessageSend messageSend = (CompletionOnJavadocMessageSend) astNode;
TypeBinding[] argTypes = null; //computeTypes(messageSend.arguments);
this.completionToken = messageSend.selector;
this.javadocTagPosition = messageSend.tagSourceStart;
// Set source range
int rangeStart = astNode.sourceStart;
if (messageSend.receiver.isThis()) {
if (messageSend.completeInText()) {
rangeStart = messageSend.separatorPosition;
}
} else if (messageSend.completeInText()) {
rangeStart = messageSend.receiver.sourceStart;
}
setSourceAndTokenRange(rangeStart, astNode.sourceEnd, false);
if (qualifiedBinding == null) {
if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
findImplicitMessageSends(this.completionToken, argTypes, scope, messageSend, scope, new ObjectVector());
}
} else if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
findMethods(
this.completionToken,
null,
argTypes,
(ReferenceBinding) ((ReferenceBinding) qualifiedBinding).capture(scope, messageSend.receiver.sourceStart, messageSend.receiver.sourceEnd),
scope,
new ObjectVector(),
false,
false/* prefix match */,
messageSend,
scope,
false,
messageSend.receiver instanceof SuperReference,
true,
null,
null,
null,
false,
null,
-1,
-1);
}
}
//TODO
private void completionOnJavadocParamNameReference(ASTNode astNode) {
if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_PARAM_REF)) {
CompletionOnJavadocParamNameReference paramRef = (CompletionOnJavadocParamNameReference) astNode;
setSourceAndTokenRange(paramRef.tagSourceStart, paramRef.tagSourceEnd);
findJavadocParamNames(paramRef.token, paramRef.missingParams, false);
findJavadocParamNames(paramRef.token, paramRef.missingTypeParams, true);
}
}
//TODO
private void completionOnJavadocQualifiedTypeReference(ASTNode astNode, Binding qualifiedBinding, Scope scope) {
this.insideQualifiedReference = true;
CompletionOnJavadocQualifiedTypeReference typeRef = (CompletionOnJavadocQualifiedTypeReference) astNode;
this.completionToken = typeRef.completionIdentifier;
long completionPosition = typeRef.sourcePositions[typeRef.tokens.length];
this.javadocTagPosition = typeRef.tagSourceStart;
// get the source positions of the completion identifier
if (qualifiedBinding instanceof ReferenceBinding && !(qualifiedBinding instanceof TypeVariableBinding)) {
if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF) ||
((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF))) {
int rangeStart = typeRef.completeInText() ? typeRef.sourceStart : (int) (completionPosition >>> 32);
setSourceAndTokenRange(rangeStart, (int) completionPosition);
findMemberTypes(
this.completionToken,
(ReferenceBinding) qualifiedBinding,
scope,
scope.enclosingSourceType(),
false,
false,
new ObjectVector(),
null,
null,
null,
false);
}
} else if (qualifiedBinding instanceof PackageBinding) {
setSourceRange(astNode.sourceStart, (int) completionPosition);
int rangeStart = typeRef.completeInText() ? typeRef.sourceStart : (int) (completionPosition >>> 32);
setTokenRange(rangeStart, (int) completionPosition);
// replace to the end of the completion identifier
findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding, scope);
}
}
//TODO
private void completionOnJavadocSingleTypeReference(ASTNode astNode, Scope scope) {
CompletionOnJavadocSingleTypeReference typeRef = (CompletionOnJavadocSingleTypeReference) astNode;
this.completionToken = typeRef.token;
this.javadocTagPosition = typeRef.tagSourceStart;
setSourceAndTokenRange(typeRef.sourceStart, typeRef.sourceEnd);
findTypesAndPackages(
this.completionToken,
scope,
(this.assistNodeInJavadoc & CompletionOnJavadoc.BASE_TYPES) != 0,
false,
new ObjectVector());
}
//TODO
private void completionOnJavadocTag(ASTNode astNode) {
CompletionOnJavadocTag javadocTag = (CompletionOnJavadocTag) astNode;
setSourceAndTokenRange(javadocTag.tagSourceStart, javadocTag.sourceEnd);
findJavadocBlockTags(javadocTag);
findJavadocInlineTags(javadocTag);
}
//TODO
private void completionOnJavadocTypeParamReference(ASTNode astNode) {
if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_PARAM_REF)) {
CompletionOnJavadocTypeParamReference paramRef = (CompletionOnJavadocTypeParamReference) astNode;
setSourceAndTokenRange(paramRef.tagSourceStart, paramRef.tagSourceEnd);
findJavadocParamNames(paramRef.token, paramRef.missingParams, true);
}
}
private void completionOnKeyword(ASTNode astNode) {
if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
CompletionOnKeyword keyword = (CompletionOnKeyword)astNode;
findKeywords(keyword.getToken(), keyword.getPossibleKeywords(), false, false);
}
}
private void completionOnLocalOrArgumentName(ASTNode astNode, Scope scope) {
if (!this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) {
LocalDeclaration variable = (LocalDeclaration) astNode;
int kind;
if (variable instanceof CompletionOnLocalName){
this.completionToken = ((CompletionOnLocalName) variable).realName;
kind = InternalNamingConventions.VK_LOCAL;
} else {
CompletionOnArgumentName arg = (CompletionOnArgumentName) variable;
this.completionToken = arg.realName;
kind = arg.isCatchArgument ? InternalNamingConventions.VK_LOCAL : InternalNamingConventions.VK_PARAMETER;
}
char[][] alreadyDefinedName = computeAlreadyDefinedName((BlockScope)scope, variable);
char[][] forbiddenNames = findVariableFromUnresolvedReference(variable, (BlockScope)scope, alreadyDefinedName);
LocalVariableBinding[] locals = ((BlockScope)scope).locals;
char[][] discouragedNames = new char[locals.length][];
int localCount = 0;
for(int i = 0 ; i < locals.length ; i++){
if (locals[i] != null) {
discouragedNames[localCount++] = locals[i].name;
}
}
System.arraycopy(discouragedNames, 0, discouragedNames = new char[localCount][], 0, localCount);
findVariableNames(this.completionToken, variable.type, discouragedNames, forbiddenNames, kind);
}
}
private void completionOnMarkerAnnotationName(ASTNode astNode, Binding qualifiedBinding, Scope scope) {
CompletionOnMarkerAnnotationName annot = (CompletionOnMarkerAnnotationName) astNode;
// When completion is inside lambda body, the fake type cannot be attached to the lambda.
ReferenceContext referenceContext = scope.parent.referenceContext();
CompletionOnAnnotationOfType fakeType;
if (referenceContext instanceof CompletionOnAnnotationOfType) {
fakeType = (CompletionOnAnnotationOfType) referenceContext;
} else {
fakeType = new CompletionOnAnnotationOfType(CompletionParser.FAKE_TYPE_NAME, scope.referenceCompilationUnit().compilationResult, annot);
}
if (fakeType.annotations[0] == annot) {
// When the completion is inside a method body the annotation cannot be accuratly attached to the correct node by completion recovery.
// So 'targetedElement' is not computed in this case.
if (scope.parent.parent == null || !(scope.parent.parent instanceof MethodScope)) {
this.targetedElement = computeTargetedElement(fakeType);
}
}
this.assistNodeIsAnnotation = true;
if (annot.type instanceof CompletionOnSingleTypeReference) {
CompletionOnSingleTypeReference type = (CompletionOnSingleTypeReference) annot.type;
this.completionToken = type.token;
setSourceAndTokenRange(type.sourceStart, type.sourceEnd);
if (scope.parent.parent != null &&
!(scope.parent.parent instanceof MethodScope) && !fakeType.isParameter) {
if (this.completionToken.length <= Keywords.INTERFACE.length
&& CharOperation.prefixEquals(this.completionToken, Keywords.INTERFACE, false /* ignore case */
)){
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(this.completionToken, Keywords.INTERFACE);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywords
relevance += R_ANNOTATION; // this proposal is most relevant than annotation proposals
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
CompletionProposal proposal = createProposal(CompletionProposal.KEYWORD, this.actualCompletionPosition);
proposal.setName(Keywords.INTERFACE);
proposal.setCompletion(Keywords.INTERFACE);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
}
findTypesAndPackages(this.completionToken, scope, false, false, new ObjectVector());
} else if (annot.type instanceof CompletionOnQualifiedTypeReference) {
this.insideQualifiedReference = true;
CompletionOnQualifiedTypeReference type = (CompletionOnQualifiedTypeReference) annot.type;
this.completionToken = type.completionIdentifier;
long completionPosition = type.sourcePositions[type.tokens.length];
if (qualifiedBinding instanceof PackageBinding) {
setSourceRange(astNode.sourceStart, (int) completionPosition);
setTokenRange((int) (completionPosition >>> 32), (int) completionPosition);
// replace to the end of the completion identifier
findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding, scope);
} else {
setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition);
findMemberTypes(
this.completionToken,
(ReferenceBinding) qualifiedBinding,
scope,
scope.enclosingSourceType(),
false,
false,
new ObjectVector(),
null,
null,
null,
false);
}
}
}
private void completionOnMemberAccess(ASTNode astNode, ASTNode enclosingNode, Binding qualifiedBinding,
Scope scope, boolean insideTypeAnnotation) {
this.insideQualifiedReference = true;
CompletionOnMemberAccess access = (CompletionOnMemberAccess) astNode;
long completionPosition = access.nameSourcePosition;
setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition);
this.completionToken = access.token;
if (qualifiedBinding.problemId() == ProblemReasons.NotFound) {
// complete method members with missing return type
// class X {
// Missing f() {return null;}
// void foo() {
// f().|
// }
// }
if (this.assistNodeInJavadoc == 0 &&
(this.requestor.isAllowingRequiredProposals(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_REF) ||
this.requestor.isAllowingRequiredProposals(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_REF))) {
ProblemMethodBinding problemMethodBinding = (ProblemMethodBinding) qualifiedBinding;
findFieldsAndMethodsFromMissingReturnType(
problemMethodBinding.selector,
problemMethodBinding.parameters,
scope,
access,
insideTypeAnnotation);
}
} else {
if (!access.isInsideAnnotation) {
if (!this.requestor.isIgnored(CompletionProposal.KEYWORD) && !access.isSuperAccess()) {
findKeywords(this.completionToken, new char[][]{Keywords.NEW}, false, false);
}
ObjectVector fieldsFound = new ObjectVector();
ObjectVector methodsFound = new ObjectVector();
boolean superCall = access.receiver instanceof SuperReference;
findFieldsAndMethods(
this.completionToken,
((TypeBinding) qualifiedBinding).capture(scope, access.receiver.sourceStart, access.receiver.sourceEnd),
scope,
fieldsFound,
methodsFound,
access,
scope,
false,
superCall,
null,
null,
null,
false,
null,
-1,
-1);
if (!superCall) {
checkCancel();
findFieldsAndMethodsFromCastedReceiver(
enclosingNode,
qualifiedBinding,
scope,
fieldsFound,
methodsFound,
access,
scope,
access.receiver);
}
}
}
}
private void completionOnMemberValueName(ASTNode astNode, ASTNode astNodeParent, Scope scope,
boolean insideTypeAnnotation) {
CompletionOnMemberValueName memberValuePair = (CompletionOnMemberValueName) astNode;
Annotation annotation = (Annotation) astNodeParent;
this.completionToken = memberValuePair.name;
ReferenceBinding annotationType = (ReferenceBinding)annotation.resolvedType;
if (annotationType != null && annotationType.isAnnotationType()) {
if (!this.requestor.isIgnored(CompletionProposal.ANNOTATION_ATTRIBUTE_REF)) {
findAnnotationAttributes(this.completionToken, annotation.memberValuePairs(), annotationType);
}
if (this.assistNodeCanBeSingleMemberAnnotation) {
if (this.expectedTypesPtr > -1 && this.expectedTypes[0].isAnnotationType()) {
findTypesAndPackages(this.completionToken, scope, false, false, new ObjectVector());
} else {
if (this.expectedTypesPtr > -1) {
this.assistNodeIsEnum = true;
done : for (int i = 0; i <= this.expectedTypesPtr; i++) {
if (!this.expectedTypes[i].isEnum()) {
this.assistNodeIsEnum = false;
break done;
}
}
}
if (scope instanceof BlockScope && !this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) {
char[][] alreadyDefinedName = computeAlreadyDefinedName((BlockScope)scope, FakeInvocationSite);
findUnresolvedReference(
memberValuePair.sourceStart,
memberValuePair.sourceEnd,
(BlockScope)scope,
alreadyDefinedName);
}
findVariablesAndMethods(
this.completionToken,
scope,
FakeInvocationSite,
scope,
insideTypeAnnotation,
true);
// can be the start of a qualified type name
findTypesAndPackages(this.completionToken, scope, false, false, new ObjectVector());
}
}
}
}
private void completionOnMessageSend(ASTNode astNode, Binding qualifiedBinding, Scope scope) {
setSourceAndTokenRange(astNode.sourceStart, astNode.sourceEnd, false);
CompletionOnMessageSend messageSend = (CompletionOnMessageSend) astNode;
TypeBinding[] argTypes = computeTypes(messageSend.arguments);
this.completionToken = messageSend.selector;
if (qualifiedBinding == null) {
if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
ObjectVector methodsFound = new ObjectVector();
findImplicitMessageSends(this.completionToken, argTypes, scope, messageSend, scope, methodsFound);
checkCancel();
findLocalMethodsFromStaticImports(
this.completionToken,
scope,
messageSend,
scope,
true,
methodsFound,
true);
}
} else if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
findMethods(
this.completionToken,
null,
argTypes,
(ReferenceBinding)((ReferenceBinding) qualifiedBinding).capture(scope, messageSend.receiver.sourceStart, messageSend.receiver.sourceEnd),
scope,
new ObjectVector(),
false,
true,
messageSend,
scope,
false,
messageSend.receiver instanceof SuperReference,
false,
null,
null,
null,
false,
null,
-1,
-1);
}
}
private void completionOnMessageSendName(ASTNode astNode, Binding qualifiedBinding, Scope scope) {
if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
CompletionOnMessageSendName messageSend = (CompletionOnMessageSendName) astNode;
this.insideQualifiedReference = true;
this.completionToken = messageSend.selector;
boolean onlyStatic = false;
if (messageSend.receiver instanceof NameReference) {
onlyStatic = ((NameReference)messageSend.receiver).isTypeReference();
} else if (!(messageSend.receiver instanceof MessageSend) &&
!(messageSend.receiver instanceof FieldReference) &&
!(messageSend.receiver.isThis())) {
onlyStatic = true;
}
TypeBinding receiverType = (TypeBinding)qualifiedBinding;
if(receiverType != null && receiverType instanceof ReferenceBinding) {
TypeBinding[] typeArgTypes = computeTypesIfCorrect(messageSend.typeArguments);
if(typeArgTypes != null) {
findMethods(
this.completionToken,
typeArgTypes,
null,
(ReferenceBinding)receiverType.capture(scope, messageSend.receiver.sourceStart, messageSend.receiver.sourceEnd),
scope,
new ObjectVector(),
onlyStatic,
false,
messageSend,
scope,
false,
false,
false,
null,
null,
null,
false,
null,
-1,
-1);
}
}
}
}
private void completionOnReferenceExpressionName(ASTNode astNode, Binding qualifiedBinding, Scope scope) {
if (!this.requestor.isIgnored(CompletionProposal.METHOD_NAME_REFERENCE)) {
CompletionOnReferenceExpressionName referenceExpression = (CompletionOnReferenceExpressionName) astNode;
this.insideQualifiedReference = true;
this.completionToken = referenceExpression.selector;
boolean onlyStatic = false;
TypeBinding receiverType = (TypeBinding) qualifiedBinding;
if (receiverType != null && receiverType instanceof ReferenceBinding) {
setSourceAndTokenRange(referenceExpression.nameSourceStart, referenceExpression.sourceEnd);
if (!(receiverType.isInterface() || this.requestor.isIgnored(CompletionProposal.KEYWORD))) {
this.assistNodeIsConstructor = true;
findKeywords(this.completionToken, new char[][] { Keywords.NEW }, false, false);
}
findMethods(
this.completionToken,
referenceExpression.resolvedTypeArguments,
null,
(ReferenceBinding)receiverType.capture(scope, referenceExpression.sourceStart, referenceExpression.sourceEnd),
scope,
new ObjectVector(),
onlyStatic,
false,
referenceExpression,
scope,
false,
false,
false,
null,
null,
null,
false,
null,
-1,
-1);
}
}
}
private void completionOnMethodName(ASTNode astNode, Scope scope) {
if (!this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) {
CompletionOnMethodName method = (CompletionOnMethodName) astNode;
setSourceAndTokenRange(method.sourceStart, method.selectorEnd);
FieldBinding[] fields = scope.enclosingSourceType().fields();
char[][] excludeNames = new char[fields.length][];
for(int i = 0 ; i < fields.length ; i++){
excludeNames[i] = fields[i].name;
}
this.completionToken = method.selector;
int kind =
(method.modifiers & ClassFileConstants.AccStatic) == 0 ?
InternalNamingConventions.VK_INSTANCE_FIELD :
(method.modifiers & ClassFileConstants.AccFinal) == 0 ?
InternalNamingConventions.VK_STATIC_FIELD :
InternalNamingConventions.VK_STATIC_FINAL_FIELD;
findVariableNames(this.completionToken, method.returnType, excludeNames, null, kind);
}
}
private void completionOnMethodReturnType(ASTNode astNode, Scope scope) {
CompletionOnMethodReturnType method = (CompletionOnMethodReturnType) astNode;
SingleTypeReference type = (CompletionOnSingleTypeReference) method.returnType;
this.completionToken = type.token;
setSourceAndTokenRange(type.sourceStart, type.sourceEnd);
findTypesAndPackages(this.completionToken, scope.parent, true, true, new ObjectVector());
if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
findKeywordsForMember(this.completionToken, method.modifiers, null);
}
if (method.modifiers == ClassFileConstants.AccDefault) {
SourceTypeBinding enclosingType = scope.enclosingSourceType();
if (!enclosingType.isAnnotationType()) {
if (!this.requestor.isIgnored(CompletionProposal.METHOD_DECLARATION)) {
findMethodDeclarations(
this.completionToken,
scope.enclosingSourceType(),
scope,
new ObjectVector(),
null,
null,
null,
false);
}
if (!this.requestor.isIgnored(CompletionProposal.POTENTIAL_METHOD_DECLARATION)) {
proposeNewMethod(this.completionToken, scope.enclosingSourceType());
}
}
}
}
private void completionOnParameterizedQualifiedTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
CompletionOnParameterizedQualifiedTypeReference ref = (CompletionOnParameterizedQualifiedTypeReference) astNode;
this.insideQualifiedReference = true;
this.assistNodeIsClass = ref.isClass();
this.assistNodeIsException = ref.isException();
this.assistNodeIsInterface = ref.isInterface();
this.assistNodeIsSuperType = ref.isSuperType();
this.assistNodeIsExtendedType = assistNodeIsExtendedType(astNode, astNodeParent);
this.assistNodeIsInterfaceExcludingAnnotation = assistNodeIsInterfaceExcludingAnnotation(astNode, astNodeParent);
this.completionToken = ref.completionIdentifier;
long completionPosition = ref.sourcePositions[ref.tokens.length];
setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition);
if (qualifiedBinding.problemId() == ProblemReasons.NotFound ||
(((ReferenceBinding)qualifiedBinding).tagBits & TagBits.HasMissingType) != 0) {
if (this.assistNodeInJavadoc == 0 &&
(this.requestor.isAllowingRequiredProposals(CompletionProposal.TYPE_REF, CompletionProposal.TYPE_REF))) {
if(ref.tokens.length == 1) {
findMemberTypesFromMissingType(
ref,
ref.sourcePositions[0],
scope);
}
}
} else {
ObjectVector typesFound = new ObjectVector();
if (this.assistNodeIsException && astNodeParent instanceof TryStatement) {
findExceptionFromTryStatement(
this.completionToken,
(ReferenceBinding)qualifiedBinding,
scope.enclosingSourceType(),
(BlockScope)scope,
typesFound);
}
checkCancel();
findMemberTypes(
this.completionToken,
(ReferenceBinding) qualifiedBinding,
scope,
scope.enclosingSourceType(),
false,
false,
typesFound,
null,
null,
null,
false);
}
}
}
private boolean assistNodeIsExtendedType(ASTNode astNode, ASTNode astNodeParent) {
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=99399, don't propose final types for extension.
if (astNodeParent == null)
return false;
if (astNodeParent instanceof TypeDeclaration) {
TypeDeclaration typeDeclaration = (TypeDeclaration) astNodeParent;
return (typeDeclaration.superclass == astNode);
} else if (astNodeParent instanceof TypeParameter) {
TypeParameter typeParameter = (TypeParameter) astNodeParent;
return (typeParameter.type == astNode);
} else if (astNodeParent instanceof Wildcard) {
Wildcard wildcard = (Wildcard) astNodeParent;
return (wildcard.bound == astNode && wildcard.kind == Wildcard.EXTENDS);
}
return false;
}
private boolean assistNodeIsInterfaceExcludingAnnotation(ASTNode astNode, ASTNode astNodeParent) {
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=310423, don't propose annotations for implements.
if (astNodeParent == null)
return false;
if (astNodeParent instanceof TypeDeclaration) {
TypeDeclaration typeDeclaration = (TypeDeclaration) astNodeParent;
TypeReference [] superInterfaces = typeDeclaration.superInterfaces;
int length = superInterfaces == null ? 0 : superInterfaces.length;
for (int i = 0; i < length; i++) {
if (superInterfaces[i] == astNode)
return true;
}
}
return false;
}
private boolean assistNodeIsInsideCase(ASTNode astNode, ASTNode astNodeParent) {
// To find whether we're completing inside the case expression in a
// switch case construct (https://bugs.eclipse.org/bugs/show_bug.cgi?id=195346)
if (astNodeParent instanceof SwitchStatement) {
CaseStatement[] cases = ((SwitchStatement) astNodeParent).cases;
for (int i = 0, caseCount = ((SwitchStatement) astNodeParent).caseCount; i < caseCount; i++) {
CompletionNodeDetector detector = new CompletionNodeDetector(astNode, cases[i]);
if (detector.containsCompletionNode()) {
return true;
}
}
}
return false;
}
private void completionOnQualifiedAllocationExpression(ASTNode astNode, Binding qualifiedBinding, Scope scope) {
setSourceAndTokenRange(astNode.sourceStart, astNode.sourceEnd, false);
CompletionOnQualifiedAllocationExpression allocExpression =
(CompletionOnQualifiedAllocationExpression) astNode;
TypeBinding[] argTypes = computeTypes(allocExpression.arguments);
ReferenceBinding ref = (ReferenceBinding) qualifiedBinding;
if (ref.problemId() == ProblemReasons.NotFound) {
findConstructorsFromMissingType(
allocExpression.type,
argTypes,
scope,
allocExpression);
} else {
if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)
&& ref.isClass()
&& !ref.isAbstract()) {
findConstructors(
ref,
argTypes,
scope,
allocExpression,
false,
null,
null,
null,
false);
}
checkCancel();
if (!this.requestor.isIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION)
&& !ref.isFinal()
&& !ref.isEnum()){
findAnonymousType(
ref,
argTypes,
scope,
allocExpression,
null,
null,
null,
false);
}
}
}
private void completionOnQualifiedNameReference(ASTNode astNode, ASTNode enclosingNode, Binding qualifiedBinding,
Scope scope, boolean insideTypeAnnotation) {
this.insideQualifiedReference = true;
CompletionOnQualifiedNameReference ref =
(CompletionOnQualifiedNameReference) astNode;
this.completionToken = ref.completionIdentifier;
long completionPosition = ref.sourcePositions[ref.sourcePositions.length - 1];
if (qualifiedBinding.problemId() == ProblemReasons.NotFound) {
setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition);
// complete field members with missing fields type
// class X {
// Missing f;
// void foo() {
// f.|
// }
// }
if (this.assistNodeInJavadoc == 0 &&
(this.requestor.isAllowingRequiredProposals(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_REF) ||
this.requestor.isAllowingRequiredProposals(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_REF) ||
this.requestor.isAllowingRequiredProposals(CompletionProposal.TYPE_REF, CompletionProposal.TYPE_REF))) {
if(ref.tokens.length == 1) {
boolean foundSomeFields = findFieldsAndMethodsFromMissingFieldType(ref.tokens[0], scope, ref, insideTypeAnnotation);
if (!foundSomeFields) {
checkCancel();
findMembersFromMissingType(
ref.tokens[0],
ref.sourcePositions[0],
null,
scope,
ref,
ref.isInsideAnnotationAttribute);
}
}
}
} else if (qualifiedBinding instanceof VariableBinding) {
setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition);
TypeBinding receiverType = ((VariableBinding) qualifiedBinding).type;
if (receiverType != null && (receiverType.tagBits & TagBits.HasMissingType) == 0) {
ObjectVector fieldsFound = new ObjectVector();
ObjectVector methodsFound = new ObjectVector();
findFieldsAndMethods(
this.completionToken,
receiverType.capture(scope, ref.sourceStart, ref.sourceEnd),
scope,
fieldsFound,
methodsFound,
ref,
scope,
false,
false,
null,
null,
null,
false,
null,
-1,
-1);
checkCancel();
findFieldsAndMethodsFromCastedReceiver(
enclosingNode,
qualifiedBinding,
scope,
fieldsFound,
methodsFound,
ref,
scope,
ref);
} else if (this.assistNodeInJavadoc == 0 &&
(this.requestor.isAllowingRequiredProposals(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_REF) ||
this.requestor.isAllowingRequiredProposals(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_REF))) {
boolean proposeField = !this.requestor.isIgnored(CompletionProposal.FIELD_REF);
boolean proposeMethod = !this.requestor.isIgnored(CompletionProposal.METHOD_REF);
if (proposeField || proposeMethod) {
if(ref.tokens.length == 1) {
if (qualifiedBinding instanceof LocalVariableBinding) {
// complete local variable members with missing variables type
// class X {
// void foo() {
// Missing f;
// f.|
// }
// }
LocalVariableBinding localVariableBinding = (LocalVariableBinding) qualifiedBinding;
findFieldsAndMethodsFromMissingType(
localVariableBinding.declaration.type,
localVariableBinding.declaringScope,
ref,
scope);
} else {
// complete field members with missing fields type
// class X {
// Missing f;
// void foo() {
// f.|
// }
// }
findFieldsAndMethodsFromMissingFieldType(ref.tokens[0], scope, ref, insideTypeAnnotation);
}
}
}
}
} else if (qualifiedBinding instanceof ReferenceBinding && !(qualifiedBinding instanceof TypeVariableBinding)) {
boolean isInsideAnnotationAttribute = ref.isInsideAnnotationAttribute;
ReferenceBinding receiverType = (ReferenceBinding) qualifiedBinding;
setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition);
findMembers(
this.completionToken,
receiverType,
scope,
ref,
isInsideAnnotationAttribute,
null,
null,
null,
false);
} else if (qualifiedBinding instanceof PackageBinding) {
setSourceRange(astNode.sourceStart, (int) completionPosition);
setTokenRange((int) (completionPosition >>> 32), (int) completionPosition);
// replace to the end of the completion identifier
findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding, scope);
}
}
private void completionOnQualifiedTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding,
Scope scope) {
this.insideQualifiedReference = true;
CompletionOnQualifiedTypeReference ref =
(CompletionOnQualifiedTypeReference) astNode;
this.assistNodeIsClass = ref.isClass();
this.assistNodeIsException = ref.isException();
this.assistNodeIsInterface = ref.isInterface();
this.assistNodeIsConstructor = ref.isConstructorType;
this.assistNodeIsSuperType = ref.isSuperType();
this.assistNodeIsExtendedType = assistNodeIsExtendedType(astNode, astNodeParent);
this.assistNodeIsInterfaceExcludingAnnotation = assistNodeIsInterfaceExcludingAnnotation(astNode, astNodeParent);
this.completionToken = ref.completionIdentifier;
long completionPosition = ref.sourcePositions[ref.tokens.length];
// get the source positions of the completion identifier
if (qualifiedBinding.problemId() == ProblemReasons.NotFound) {
setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition);
if (this.assistNodeInJavadoc == 0 &&
(this.requestor.isAllowingRequiredProposals(CompletionProposal.TYPE_REF, CompletionProposal.TYPE_REF))) {
if(ref.tokens.length == 1) {
findMemberTypesFromMissingType(
ref.tokens[0],
ref.sourcePositions[0],
scope);
}
}
} else if (qualifiedBinding instanceof ReferenceBinding && !(qualifiedBinding instanceof TypeVariableBinding)) {
if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition);
ObjectVector typesFound = new ObjectVector();
if (this.assistNodeIsException && astNodeParent instanceof TryStatement) {
findExceptionFromTryStatement(
this.completionToken,
(ReferenceBinding)qualifiedBinding,
scope.enclosingSourceType(),
(BlockScope)scope,
typesFound);
}
checkCancel();
findMemberTypes(
this.completionToken,
(ReferenceBinding) qualifiedBinding,
scope,
scope.enclosingSourceType(),
false,
false,
typesFound,
null,
null,
null,
false);
}
} else if (qualifiedBinding instanceof PackageBinding) {
setSourceRange(astNode.sourceStart, (int) completionPosition);
setTokenRange((int) (completionPosition >>> 32), (int) completionPosition);
// replace to the end of the completion identifier
findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding, scope);
}
}
private void completionOnProvidesInterfacesQualifiedTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
// TODO: Filter the results wrt accessibility and add relevance to the results.
completionOnQualifiedTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
}
private void completionOnProvidesImplementationsQualifiedTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
findImplementations((ProvidesStatement) this.parser.enclosingNode, (TypeReference) astNode);
}
private void completionOnSingleNameReference(ASTNode astNode, ASTNode astNodeParent, Scope scope,
boolean insideTypeAnnotation) {
CompletionOnSingleNameReference singleNameReference = (CompletionOnSingleNameReference) astNode;
this.completionToken = singleNameReference.token;
SwitchStatement switchStatement = astNodeParent instanceof SwitchStatement ? (SwitchStatement) astNodeParent : null;
if (switchStatement != null
&& switchStatement.expression.resolvedType != null
&& switchStatement.expression.resolvedType.isEnum()) {
if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) {
this.assistNodeIsEnum = true;
findEnumConstantsFromSwithStatement(this.completionToken, (SwitchStatement) astNodeParent);
}
} else if (this.expectedTypesPtr > -1 && this.expectedTypes[0].isAnnotationType()) {
findTypesAndPackages(this.completionToken, scope, false, false, new ObjectVector());
if (scope instanceof BlockScope && !this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) {
findVariablesAndMethods(
this.completionToken,
scope,
singleNameReference,
scope,
insideTypeAnnotation,
singleNameReference.isInsideAnnotationAttribute);
}
} else {
if (this.expectedTypesPtr > -1) {
this.assistNodeIsEnum = true;
done : for (int i = 0; i <= this.expectedTypesPtr; i++) {
if (!this.expectedTypes[i].isEnum()) {
this.assistNodeIsEnum = false;
break done;
}
}
}
if (scope instanceof BlockScope && !this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) {
char[][] alreadyDefinedName = computeAlreadyDefinedName((BlockScope)scope, singleNameReference);
findUnresolvedReference(
singleNameReference.sourceStart,
singleNameReference.sourceEnd,
(BlockScope)scope,
alreadyDefinedName);
}
checkCancel();
findVariablesAndMethods(
this.completionToken,
scope,
singleNameReference,
scope,
insideTypeAnnotation,
singleNameReference.isInsideAnnotationAttribute);
//{ObjectTeams: following analyses don't apply to base/tsuper calls:
if (isBaseAccess(singleNameReference) || isTSuperAccess(singleNameReference))
return;
// SH}
checkCancel();
// can be the start of a qualified type name
findTypesAndPackages(this.completionToken, scope, true, false, new ObjectVector());
if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
if (this.completionToken != null && this.completionToken.length != 0) {
findKeywords(this.completionToken, singleNameReference.possibleKeywords, false, false);
} else {
findTrueOrFalseKeywords(singleNameReference.possibleKeywords);
}
}
if (singleNameReference.canBeExplicitConstructor && !this.requestor.isIgnored(CompletionProposal.METHOD_REF)){
if (CharOperation.prefixEquals(this.completionToken, Keywords.THIS, false)) {
ReferenceBinding ref = scope.enclosingSourceType();
findExplicitConstructors(Keywords.THIS, ref, (MethodScope)scope, singleNameReference);
} else if (CharOperation.prefixEquals(this.completionToken, Keywords.SUPER, false)) {
ReferenceBinding ref = scope.enclosingSourceType();
findExplicitConstructors(Keywords.SUPER, ref.superclass(), (MethodScope)scope, singleNameReference);
}
}
}
}
private void completionOnSingleTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
CompletionOnSingleTypeReference singleRef = (CompletionOnSingleTypeReference) astNode;
//{ObjectTeams: support baseclass decapsulation
if (singleRef.getBaseclassDecapsulation().isAllowed())
this.options.checkVisibility = false;
// SH}
this.completionToken = singleRef.token;
this.assistNodeIsClass = singleRef.isClass();
this.assistNodeIsException = singleRef.isException();
this.assistNodeIsInterface = singleRef.isInterface();
this.assistNodeIsConstructor = singleRef.isConstructorType;
this.assistNodeIsSuperType = singleRef.isSuperType();
this.assistNodeIsExtendedType = assistNodeIsExtendedType(astNode, astNodeParent);
this.assistNodeIsInterfaceExcludingAnnotation = assistNodeIsInterfaceExcludingAnnotation(astNode, astNodeParent);
// can be the start of a qualified type name
if (qualifiedBinding == null) {
if (this.completionToken.length == 0 &&
(astNodeParent instanceof ParameterizedSingleTypeReference ||
astNodeParent instanceof ParameterizedQualifiedTypeReference)) {
this.setSourceAndTokenRange(astNode.sourceStart, astNode.sourceStart - 1, false);
findParameterizedType((TypeReference)astNodeParent, scope);
} else {
ObjectVector typesFound = new ObjectVector();
if (this.assistNodeIsException && astNodeParent instanceof TryStatement) {
findExceptionFromTryStatement(
this.completionToken,
null,
scope.enclosingSourceType(),
(BlockScope)scope,
typesFound);
}
checkCancel();
findTypesAndPackages(this.completionToken, scope, this.assistNodeIsConstructor, false, typesFound);
}
} else if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
findMemberTypes(
this.completionToken,
(ReferenceBinding) qualifiedBinding,
scope,
scope.enclosingSourceType(),
false,
false,
false,
false,
!this.assistNodeIsConstructor,
null,
new ObjectVector(),
null,
null,
null,
false);
}
}
private void completionOnProvidesInterfacesSingleTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
completionOnSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
}
private void completionOnProvidesImplementationsSingleTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
findImplementations((ProvidesStatement) this.parser.enclosingNode, (TypeReference) astNode);
// TODO : filter the results - remove packs without a type in impl.
}
private char[][] computeAlreadyDefinedName(
BlockScope scope,
InvocationSite invocationSite) {
ArrayList result = new ArrayList();
boolean staticsOnly = false;
Scope currentScope = scope;
done1 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
switch (currentScope.kind) {
case Scope.METHOD_SCOPE :
// handle the error case inside an explicit constructor call (see MethodScope>>findField)
MethodScope methodScope = (MethodScope) currentScope;
staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall;
//$FALL-THROUGH$
case Scope.BLOCK_SCOPE :
BlockScope blockScope = (BlockScope) currentScope;
next : for (int i = 0, length = blockScope.locals.length; i < length; i++) {
LocalVariableBinding local = blockScope.locals[i];
if (local == null)
break next;
if (local.isSecret())
continue next;
result.add(local.name);
}
break;
case Scope.CLASS_SCOPE :
ClassScope classScope = (ClassScope) currentScope;
SourceTypeBinding enclosingType = classScope.referenceContext.binding;
computeAlreadyDefinedName(
enclosingType,
classScope,
staticsOnly,
invocationSite,
result);
staticsOnly |= enclosingType.isStatic();
break;
case Scope.COMPILATION_UNIT_SCOPE :
break done1;
}
currentScope = currentScope.parent;
}
if (result.size() == 0) return CharOperation.NO_CHAR_CHAR;
return (char[][])result.toArray(new char[result.size()][]);
}
private void computeAlreadyDefinedName(
FieldBinding[] fields,
Scope scope,
boolean onlyStaticFields,
ReferenceBinding receiverType,
InvocationSite invocationSite,
ArrayList result) {
next : for (int f = fields.length; --f >= 0;) {
FieldBinding field = fields[f];
if (field.isSynthetic()) continue next;
if (onlyStaticFields && !field.isStatic()) continue next;
if (!field.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
result.add(field.name);
}
}
private void computeAlreadyDefinedName(
SourceTypeBinding receiverType,
ClassScope scope,
boolean onlyStaticFields,
InvocationSite invocationSite,
ArrayList result) {
ReferenceBinding currentType = receiverType;
ReferenceBinding[] interfacesToVisit = null;
int nextPosition = 0;
do {
ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
if (itsInterfaces != Binding.NO_SUPERINTERFACES) {
if (interfacesToVisit == null) {
interfacesToVisit = itsInterfaces;
nextPosition = interfacesToVisit.length;
} else {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (TypeBinding.equalsEquals(next, interfacesToVisit[b])) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
FieldBinding[] fields = currentType.availableFields();
if(fields != null && fields.length > 0) {
computeAlreadyDefinedName(
fields,
scope,
onlyStaticFields,
receiverType,
invocationSite,
result);
}
currentType = currentType.superclass();
} while ( currentType != null);
if (interfacesToVisit != null) {
for (int i = 0; i < nextPosition; i++) {
ReferenceBinding anInterface = interfacesToVisit[i];
FieldBinding[] fields = anInterface.availableFields();
if(fields != null) {
computeAlreadyDefinedName(
fields,
scope,
onlyStaticFields,
receiverType,
invocationSite,
result);
}
ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
if (itsInterfaces != Binding.NO_SUPERINTERFACES) {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (TypeBinding.equalsEquals(next, interfacesToVisit[b])) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
}
}
int computeBaseRelevance(){
return R_DEFAULT;
}
private void computeExpectedTypes(ASTNode parent, ASTNode node, Scope scope){
// default filter
this.expectedTypesFilter = SUBTYPE;
this.hasJavaLangObjectAsExpectedType = false;
// find types from parent
if(parent instanceof AbstractVariableDeclaration && !(parent instanceof TypeParameter)) {
AbstractVariableDeclaration variable = (AbstractVariableDeclaration)parent;
TypeBinding binding = variable.type.resolvedType;
if(binding != null) {
if(!(variable.initialization instanceof ArrayInitializer)) {
addExpectedType(binding, scope);
} else { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=310747
// If the variable is of type X[], and we're in the initializer
// we should have X as the expected type for the variable initializers.
binding = binding.leafComponentType();
addExpectedType(binding, scope);
}
}
} else if(parent instanceof Assignment) {
TypeBinding binding = ((Assignment)parent).lhs.resolvedType;
if(binding != null) {
addExpectedType(binding, scope);
}
} else if(parent instanceof ReturnStatement) {
if(scope.methodScope().referenceContext instanceof AbstractMethodDeclaration) {
MethodBinding methodBinding = ((AbstractMethodDeclaration) scope.methodScope().referenceContext).binding;
TypeBinding binding = methodBinding == null ? null : methodBinding.returnType;
if(binding != null) {
addExpectedType(binding, scope);
}
} else if (scope.methodScope().referenceContext instanceof LambdaExpression) {
MethodBinding methodBinding = ((LambdaExpression) scope.methodScope().referenceContext).getMethodBinding();
TypeBinding binding = methodBinding == null ? null : methodBinding.returnType;
if (binding != null) {
addExpectedType(binding, scope);
}
}
} else if(parent instanceof CastExpression) {
TypeReference e = ((CastExpression)parent).type;
TypeBinding binding = e.resolvedType;
if(binding != null){
addExpectedType(binding, scope);
this.expectedTypesFilter = SUBTYPE | SUPERTYPE;
}
} else if(parent instanceof MessageSend) {
MessageSend messageSend = (MessageSend) parent;
if(messageSend.actualReceiverType instanceof ReferenceBinding) {
ReferenceBinding binding = (ReferenceBinding)messageSend.actualReceiverType;
boolean isStatic = messageSend.receiver.isTypeReference();
while(binding != null) {
computeExpectedTypesForMessageSend(
binding,
messageSend.selector,
messageSend.arguments,
(ReferenceBinding)messageSend.actualReceiverType,
scope,
messageSend,
isStatic);
computeExpectedTypesForMessageSendForInterface(
binding,
messageSend.selector,
messageSend.arguments,
(ReferenceBinding)messageSend.actualReceiverType,
scope,
messageSend,
isStatic);
binding = binding.superclass();
}
}
} else if(parent instanceof AllocationExpression) {
AllocationExpression allocationExpression = (AllocationExpression) parent;
ReferenceBinding binding = (ReferenceBinding)allocationExpression.type.resolvedType;
if(binding != null) {
computeExpectedTypesForAllocationExpression(
binding,
allocationExpression.arguments,
scope,
allocationExpression);
}
} else if(parent instanceof OperatorExpression) {
int operator = (parent.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT;
if(parent instanceof ConditionalExpression) {
// for future use
} else if(parent instanceof InstanceOfExpression) {
InstanceOfExpression e = (InstanceOfExpression) parent;
TypeBinding binding = e.expression.resolvedType;
if (binding == null) {
if (scope instanceof BlockScope)
binding = e.expression.resolveType((BlockScope) scope);
else if (scope instanceof ClassScope)
binding = e.expression.resolveType((ClassScope) scope);
}
if(binding != null){
addExpectedType(binding, scope);
this.expectedTypesFilter = SUBTYPE | SUPERTYPE;
}
} else if(parent instanceof BinaryExpression) {
BinaryExpression binaryExpression = (BinaryExpression) parent;
switch(operator) {
case OperatorIds.EQUAL_EQUAL :
case OperatorIds.NOT_EQUAL :
// expected type is not relevant in this case
TypeBinding binding = binaryExpression.left.resolvedType;
if (binding != null) {
addExpectedType(binding, scope);
this.expectedTypesFilter = SUBTYPE | SUPERTYPE;
}
break;
case OperatorIds.PLUS :
addExpectedType(TypeBinding.SHORT, scope);
addExpectedType(TypeBinding.INT, scope);
addExpectedType(TypeBinding.LONG, scope);
addExpectedType(TypeBinding.FLOAT, scope);
addExpectedType(TypeBinding.DOUBLE, scope);
addExpectedType(TypeBinding.CHAR, scope);
addExpectedType(TypeBinding.BYTE, scope);
addExpectedType(scope.getJavaLangString(), scope);
break;
case OperatorIds.AND_AND :
case OperatorIds.OR_OR :
case OperatorIds.XOR :
addExpectedType(TypeBinding.BOOLEAN, scope);
break;
default :
addExpectedType(TypeBinding.SHORT, scope);
addExpectedType(TypeBinding.INT, scope);
addExpectedType(TypeBinding.LONG, scope);
addExpectedType(TypeBinding.FLOAT, scope);
addExpectedType(TypeBinding.DOUBLE, scope);
addExpectedType(TypeBinding.CHAR, scope);
addExpectedType(TypeBinding.BYTE, scope);
break;
}
if(operator == OperatorIds.LESS) {
if(binaryExpression.left instanceof SingleNameReference){
SingleNameReference name = (SingleNameReference) binaryExpression.left;
Binding b = scope.getBinding(name.token, Binding.VARIABLE | Binding.TYPE, name, false);
if(b instanceof ReferenceBinding) {
TypeVariableBinding[] typeVariableBindings =((ReferenceBinding)b).typeVariables();
if(typeVariableBindings != null && typeVariableBindings.length > 0) {
addExpectedType(typeVariableBindings[0].firstBound, scope);
}
}
}
}
} else if(parent instanceof UnaryExpression) {
switch(operator) {
case OperatorIds.NOT :
addExpectedType(TypeBinding.BOOLEAN, scope);
break;
case OperatorIds.TWIDDLE :
addExpectedType(TypeBinding.SHORT, scope);
addExpectedType(TypeBinding.INT, scope);
addExpectedType(TypeBinding.LONG, scope);
addExpectedType(TypeBinding.CHAR, scope);
addExpectedType(TypeBinding.BYTE, scope);
break;
case OperatorIds.PLUS :
case OperatorIds.MINUS :
case OperatorIds.PLUS_PLUS :
case OperatorIds.MINUS_MINUS :
addExpectedType(TypeBinding.SHORT, scope);
addExpectedType(TypeBinding.INT, scope);
addExpectedType(TypeBinding.LONG, scope);
addExpectedType(TypeBinding.FLOAT, scope);
addExpectedType(TypeBinding.DOUBLE, scope);
addExpectedType(TypeBinding.CHAR, scope);
addExpectedType(TypeBinding.BYTE, scope);
break;
}
}
} else if(parent instanceof ArrayReference) {
addExpectedType(TypeBinding.SHORT, scope);
addExpectedType(TypeBinding.INT, scope);
addExpectedType(TypeBinding.LONG, scope);
} else if(parent instanceof ParameterizedSingleTypeReference) {
ParameterizedSingleTypeReference ref = (ParameterizedSingleTypeReference) parent;
TypeBinding expected = null;
if (this.parser.enclosingNode instanceof AbstractVariableDeclaration ||
this.parser.enclosingNode instanceof ReturnStatement) {
// completing inside the diamond
if (this.parser.enclosingNode instanceof AbstractVariableDeclaration) {
AbstractVariableDeclaration abstractVariableDeclaration = (AbstractVariableDeclaration) this.parser.enclosingNode;
expected = abstractVariableDeclaration.initialization != null ? abstractVariableDeclaration.initialization.expectedType() : null;
} else {
ReturnStatement returnStatement = (ReturnStatement) this.parser.enclosingNode;
if (returnStatement.expression != null) {
expected = returnStatement.expression.expectedType();
}
}
addExpectedType(expected, scope);
} else {
TypeVariableBinding[] typeVariables = ((ReferenceBinding)ref.resolvedType).typeVariables();
int length = ref.typeArguments == null ? 0 : ref.typeArguments.length;
if(typeVariables != null && typeVariables.length >= length) {
int index = length - 1;
while(index > -1 && ref.typeArguments[index] != node) index--;
TypeBinding bound = typeVariables[index].firstBound;
addExpectedType(bound == null ? scope.getJavaLangObject() : bound, scope);
}
}
} else if(parent instanceof ParameterizedQualifiedTypeReference) {
ParameterizedQualifiedTypeReference ref = (ParameterizedQualifiedTypeReference) parent;
TypeReference[][] arguments = ref.typeArguments;
TypeBinding expected = null;
if (this.parser.enclosingNode instanceof AbstractVariableDeclaration ||
this.parser.enclosingNode instanceof ReturnStatement) {
// completing inside the diamond
if (this.parser.enclosingNode instanceof AbstractVariableDeclaration) {
AbstractVariableDeclaration abstractVariableDeclaration = (AbstractVariableDeclaration) this.parser.enclosingNode;
expected = abstractVariableDeclaration.initialization != null ? abstractVariableDeclaration.initialization.expectedType() : null;
} else {
ReturnStatement returnStatement = (ReturnStatement) this.parser.enclosingNode;
if (returnStatement.expression != null) {
expected = returnStatement.expression.expectedType();
}
}
addExpectedType(expected, scope);
} else {
TypeVariableBinding[] typeVariables = ((ReferenceBinding)ref.resolvedType).typeVariables();
if(typeVariables != null) {
int iLength = arguments == null ? 0 : arguments.length;
done: for (int i = 0; i < iLength; i++) {
int jLength = arguments[i] == null ? 0 : arguments[i].length;
for (int j = 0; j < jLength; j++) {
if(arguments[i][j] == node && typeVariables.length > j) {
TypeBinding bound = typeVariables[j].firstBound;
addExpectedType(bound == null ? scope.getJavaLangObject() : bound, scope);
break done;
}
}
}
}
}
} else if(parent instanceof MemberValuePair) {
MemberValuePair memberValuePair = (MemberValuePair) parent;
if(memberValuePair.binding != null) {
addExpectedType(memberValuePair.binding.returnType.leafComponentType(), scope);
}
} else if (parent instanceof NormalAnnotation) {
NormalAnnotation annotation = (NormalAnnotation) parent;
MemberValuePair[] memberValuePairs = annotation.memberValuePairs();
if(memberValuePairs == null || memberValuePairs.length == 0) {
if(annotation.resolvedType instanceof ReferenceBinding) {
MethodBinding[] methodBindings =
((ReferenceBinding)annotation.resolvedType).availableMethods();
if (methodBindings != null &&
methodBindings.length > 0 &&
CharOperation.equals(methodBindings[0].selector, VALUE)) {
boolean canBeSingleMemberAnnotation = true;
done : for (int i = 1; i < methodBindings.length; i++) {
if((methodBindings[i].modifiers & ClassFileConstants.AccAnnotationDefault) == 0) {
canBeSingleMemberAnnotation = false;
break done;
}
}
if (canBeSingleMemberAnnotation) {
this.assistNodeCanBeSingleMemberAnnotation = canBeSingleMemberAnnotation;
addExpectedType(methodBindings[0].returnType.leafComponentType(), scope);
}
}
}
}
} else if (parent instanceof AssistNodeParentAnnotationArrayInitializer) {
AssistNodeParentAnnotationArrayInitializer parent1 = (AssistNodeParentAnnotationArrayInitializer) parent;
if(parent1.type.resolvedType instanceof ReferenceBinding) {
MethodBinding[] methodBindings =
((ReferenceBinding)parent1.type.resolvedType).availableMethods();
if (methodBindings != null) {
for (MethodBinding methodBinding : methodBindings) {
if(CharOperation.equals(methodBinding.selector, parent1.name)) {
addExpectedType(methodBinding.returnType.leafComponentType(), scope);
break;
}
}
}
}
} else if (parent instanceof TryStatement) {
boolean isException = false;
if (node instanceof CompletionOnSingleTypeReference) {
isException = ((CompletionOnSingleTypeReference)node).isException();
} else if (node instanceof CompletionOnQualifiedTypeReference) {
isException = ((CompletionOnQualifiedTypeReference)node).isException();
} else if (node instanceof CompletionOnParameterizedQualifiedTypeReference) {
isException = ((CompletionOnParameterizedQualifiedTypeReference)node).isException();
}
if (isException) {
ThrownExceptionFinder thrownExceptionFinder = new ThrownExceptionFinder();
thrownExceptionFinder.processThrownExceptions((TryStatement) parent, (BlockScope)scope);
ReferenceBinding[] bindings = thrownExceptionFinder.getThrownUncaughtExceptions();
ReferenceBinding[] alreadyCaughtExceptions = thrownExceptionFinder.getAlreadyCaughtExceptions();
ReferenceBinding[] discouragedExceptions = thrownExceptionFinder.getDiscouragedExceptions();
if (bindings != null && bindings.length > 0) {
for (int i = 0; i < bindings.length; i++) {
addExpectedType(bindings[i], scope);
}
this.expectedTypesFilter = SUPERTYPE;
}
if (alreadyCaughtExceptions != null && alreadyCaughtExceptions.length > 0) {
for (int i = 0; i < alreadyCaughtExceptions.length; i++) {
addForbiddenBindings(alreadyCaughtExceptions[i]);
this.knownTypes.put(CharOperation.concat(alreadyCaughtExceptions[i].qualifiedPackageName(), alreadyCaughtExceptions[i].qualifiedSourceName(), '.'), KNOWN_TYPE_WITH_KNOWN_CONSTRUCTORS);
}
}
if (discouragedExceptions != null && discouragedExceptions.length > 0) {
for (int i = 0; i < discouragedExceptions.length; i++) {
addUninterestingBindings(discouragedExceptions[i]);
// do not insert into known types. We do need these types to come from
// searchAllTypes(..) albeit with lower relevance
}
}
}
} else if (parent instanceof SwitchStatement) {
SwitchStatement switchStatement = (SwitchStatement) parent;
this.assistNodeIsInsideCase = assistNodeIsInsideCase(node, parent);
if (switchStatement.expression != null &&
switchStatement.expression.resolvedType != null) {
if (this.assistNodeIsInsideCase &&
switchStatement.expression.resolvedType.id == TypeIds.T_JavaLangString &&
this.compilerOptions.complianceLevel >= ClassFileConstants.JDK1_7) {
// set the field to true even though the expected types array will contain String as
// expected type to avoid traversing the array in every case later on.
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=343476
this.assistNodeIsString = true;
}
addExpectedType(switchStatement.expression.resolvedType, scope);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=253008, flag boolean as the expected
// type if we are completing inside if(), for (; ;), while() and do while()
} else if (parent instanceof WhileStatement) { // covers both while and do-while loops
addExpectedType(TypeBinding.BOOLEAN, scope);
} else if (parent instanceof IfStatement) {
addExpectedType(TypeBinding.BOOLEAN, scope);
} else if (parent instanceof AssertStatement) {
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=274466
// If the assertExpression is same as the node , then the assistNode is the conditional part of the assert statement
AssertStatement assertStatement = (AssertStatement) parent;
if (assertStatement.assertExpression == node) {
addExpectedType(TypeBinding.BOOLEAN, scope);
}
} else if (parent instanceof ForStatement) { // astNodeParent set to ForStatement only for the condition
addExpectedType(TypeBinding.BOOLEAN, scope);
// Expected types for javadoc
} else if (parent instanceof Javadoc) {
if (scope.kind == Scope.METHOD_SCOPE) {
MethodScope methodScope = (MethodScope) scope;
AbstractMethodDeclaration methodDecl = methodScope.referenceMethod();
if (methodDecl != null && methodDecl.binding != null) {
ReferenceBinding[] exceptions = methodDecl.binding.thrownExceptions;
if (exceptions != null) {
for (int i = 0; i < exceptions.length; i++) {
addExpectedType(exceptions[i], scope);
}
}
}
}
}
if(this.expectedTypesPtr + 1 != this.expectedTypes.length) {
System.arraycopy(this.expectedTypes, 0, this.expectedTypes = new TypeBinding[this.expectedTypesPtr + 1], 0, this.expectedTypesPtr + 1);
}
}
private void computeExpectedTypesForAllocationExpression(
ReferenceBinding binding,
Expression[] arguments,
Scope scope,
InvocationSite invocationSite) {
MethodBinding[] methods = binding.availableMethods();
nextMethod : for (int i = 0; i < methods.length; i++) {
MethodBinding method = methods[i];
if (!method.isConstructor()) continue nextMethod;
if (method.isSynthetic()) continue nextMethod;
if (this.options.checkVisibility && !method.canBeSeenBy(invocationSite, scope)) continue nextMethod;
TypeBinding[] parameters = method.parameters;
if(parameters.length < arguments.length)
continue nextMethod;
int length = arguments.length - 1;
for (int j = 0; j < length; j++) {
Expression argument = arguments[j];
TypeBinding argType = argument.resolvedType;
if(argType != null && !argType.isCompatibleWith(parameters[j]))
continue nextMethod;
}
TypeBinding expectedType = method.parameters[arguments.length - 1];
if(expectedType != null) {
addExpectedType(expectedType, scope);
}
}
}
private void computeExpectedTypesForMessageSend(
ReferenceBinding binding,
char[] selector,
Expression[] arguments,
ReferenceBinding receiverType,
Scope scope,
InvocationSite invocationSite,
boolean isStatic) {
MethodBinding[] methods = binding.availableMethods();
nextMethod : for (int i = 0; i < methods.length; i++) {
MethodBinding method = methods[i];
if (method.isSynthetic()) continue nextMethod;
if (method.isDefaultAbstract()) continue nextMethod;
if (method.isConstructor()) continue nextMethod;
if (isStatic && !method.isStatic()) continue nextMethod;
if (this.options.checkVisibility && !method.canBeSeenBy(receiverType, invocationSite, scope)) continue nextMethod;
if(!CharOperation.equals(method.selector, selector)) continue nextMethod;
TypeBinding[] parameters = method.parameters;
if(parameters.length < arguments.length)
continue nextMethod;
int length = arguments.length - 1;
for (int j = 0; j < length; j++) {
Expression argument = arguments[j];
TypeBinding argType = argument.resolvedType;
if(argType != null && !argType.erasure().isCompatibleWith(parameters[j].erasure()))
continue nextMethod;
}
TypeBinding expectedType = method.parameters[arguments.length - 1];
if(expectedType != null) {
addExpectedType(expectedType, scope);
}
}
}
private void computeExpectedTypesForMessageSendForInterface(
ReferenceBinding binding,
char[] selector,
Expression[] arguments,
ReferenceBinding receiverType,
Scope scope,
InvocationSite invocationSite,
boolean isStatic) {
ReferenceBinding[] itsInterfaces = binding.superInterfaces();
if (itsInterfaces != Binding.NO_SUPERINTERFACES) {
ReferenceBinding[] interfacesToVisit = itsInterfaces;
int nextPosition = interfacesToVisit.length;
for (int i = 0; i < nextPosition; i++) {
ReferenceBinding currentType = interfacesToVisit[i];
computeExpectedTypesForMessageSend(
currentType,
selector,
arguments,
receiverType,
scope,
invocationSite,
isStatic);
if ((itsInterfaces = currentType.superInterfaces()) != Binding.NO_SUPERINTERFACES) {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (TypeBinding.equalsEquals(next, interfacesToVisit[b])) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
}
}
private Scope computeForbiddenBindings(ASTNode astNode, ASTNode astNodeParent, Scope scope) {
if(scope instanceof ClassScope) {
TypeDeclaration typeDeclaration = ((ClassScope)scope).referenceContext;
if(typeDeclaration.superclass == astNode) {
addForbiddenBindings(typeDeclaration.binding);
addForbiddenBindingsForMemberTypes(typeDeclaration);
//{ObjectTeams: role may not extend enclosing!
if (typeDeclaration.binding.isRole()) {
ReferenceBinding currentOuter = typeDeclaration.binding.enclosingType();
while (currentOuter != null) {
addForbiddenBindings(currentOuter);
currentOuter = currentOuter.enclosingType();
}
}
// SH}
return scope.parent;
}
//{ObjectTeams: similar for playedBy:
if(typeDeclaration.baseclass == astNode) {
ReferenceBinding ifcBinding;
RoleModel roleModel = typeDeclaration.getRoleModel();
if ((ifcBinding= roleModel.getInterfacePartBinding()) != null)
addForbiddenBaseclasses(ifcBinding);
else
addForbiddenBaseclasses(typeDeclaration.binding);
ReferenceBinding currentOuter = typeDeclaration.binding.enclosingType();
while (currentOuter != null) {
this.addForbiddenBindings(currentOuter);
currentOuter = currentOuter.enclosingType();
}
return scope.parent;
}
// SH}
TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
int length = superInterfaces == null ? 0 : superInterfaces.length;
int astNodeIndex = -1;
for (int i = 0; i < length; i++) {
if(superInterfaces[i] == astNode) {
addForbiddenBindings(typeDeclaration.binding);
addForbiddenBindingsForMemberTypes(typeDeclaration);
astNodeIndex = i;
break;
}
}
if (astNodeIndex >= 0) {
// Need to loop only up to astNodeIndex as the rest will be undefined.
for (int i = 0; i < astNodeIndex; i++) {
addForbiddenBindings(superInterfaces[i].resolvedType);
}
return scope.parent;
}
}
// else if(scope instanceof MethodScope) {
// MethodScope methodScope = (MethodScope) scope;
// if(methodScope.insideTypeAnnotation) {
// return methodScope.parent.parent;
// }
// }
return scope;
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=270437
private void addForbiddenBindingsForMemberTypes(TypeDeclaration typeDeclaration) {
TypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
int memberTypesLen = memberTypes == null ? 0 : memberTypes.length;
for (int i = 0; i < memberTypesLen; i++) {
addForbiddenBindings(memberTypes[i].binding);
addForbiddenBindingsForMemberTypes(memberTypes[i]);
}
}
private char[] computePrefix(SourceTypeBinding declarationType, SourceTypeBinding invocationType, boolean isStatic){
StringBuffer completion = new StringBuffer(10);
if (isStatic) {
completion.append(declarationType.sourceName());
} else if (TypeBinding.equalsEquals(declarationType, invocationType)) {
completion.append(THIS);
} else {
if (!declarationType.isNestedType()) {
completion.append(declarationType.sourceName());
completion.append('.');
completion.append(THIS);
} else if (!declarationType.isAnonymousType()) {
completion.append(declarationType.sourceName());
completion.append('.');
completion.append(THIS);
}
}
return completion.toString().toCharArray();
}
private int computeRelevanceForAnnotation(){
if(this.assistNodeIsAnnotation) {
return R_ANNOTATION;
}
return 0;
}
private int computeRelevanceForAnnotationTarget(TypeBinding typeBinding){
if (this.assistNodeIsAnnotation &&
(this.targetedElement & TagBits.AnnotationTargetMASK) != 0) {
long target = typeBinding.getAnnotationTagBits() & TagBits.AnnotationTargetMASK;
if(target == 0 || (target & this.targetedElement) != 0) {
return R_TARGET;
}
}
return 0;
}
int computeRelevanceForCaseMatching(char[] token, char[] proposalName){
if(CharOperation.equals(token, proposalName, true)) {
return R_EXACT_NAME + R_CASE;
} else if(CharOperation.equals(token, proposalName, false)) {
return R_EXACT_NAME;
} else if (CharOperation.prefixEquals(token, proposalName, false)) {
if (CharOperation.prefixEquals(token, proposalName, true))
return R_CASE;
} else if (this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, proposalName)){
return R_CAMEL_CASE;
} else if (this.options.substringMatch && CharOperation.substringMatch(token, proposalName)) {
return R_SUBSTRING;
}
return 0;
}
private int computeRelevanceForClass(){
if(this.assistNodeIsClass) {
return R_CLASS;
}
return 0;
}
private int computeRelevanceForConstructor() {
if (this.assistNodeIsConstructor) {
return R_CONSTRUCTOR;
}
return 0;
}
private int computeRelevanceForEnum(){
if(this.assistNodeIsEnum) {
return R_ENUM;
}
return 0;
}
private int computeRelevanceForEnumConstant(TypeBinding proposalType){
if(this.assistNodeIsEnum &&
proposalType != null &&
this.expectedTypes != null) {
for (int i = 0; i <= this.expectedTypesPtr; i++) {
if (proposalType.isEnum() &&
TypeBinding.equalsEquals(proposalType, this.expectedTypes[i])) {
return R_ENUM + R_ENUM_CONSTANT;
}
}
}
return 0;
}
private int computeRelevanceForException(){
if (this.assistNodeIsException) {
return R_EXCEPTION;
}
return 0;
}
private int computeRelevanceForException(char[] proposalName){
if((this.assistNodeIsException || (this.assistNodeInJavadoc & CompletionOnJavadoc.EXCEPTION) != 0 )&&
(CharOperation.match(EXCEPTION_PATTERN, proposalName, false) ||
CharOperation.match(ERROR_PATTERN, proposalName, false))) {
return R_EXCEPTION;
}
return 0;
}
private int computeRelevanceForExpectingType(char[] packageName, char[] typeName){
if(this.expectedTypes != null) {
for (int i = 0; i <= this.expectedTypesPtr; i++) {
if(CharOperation.equals(this.expectedTypes[i].qualifiedPackageName(), packageName) &&
CharOperation.equals(this.expectedTypes[i].qualifiedSourceName(), typeName)) {
return R_EXACT_EXPECTED_TYPE;
}
}
if(this.hasJavaLangObjectAsExpectedType) {
return R_EXPECTED_TYPE;
}
}
return 0;
}
private int computeRelevanceForExpectingType(TypeBinding proposalType){
if(this.expectedTypes != null && proposalType != null) {
int relevance = 0;
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=271296
// If there is at least one expected type, then void proposal types attract a degraded relevance.
if (proposalType == TypeBinding.VOID && this.expectedTypesPtr >=0) {
return R_VOID;
}
for (int i = 0; i <= this.expectedTypesPtr; i++) {
if((this.expectedTypesFilter & SUBTYPE) != 0
&& (proposalType.erasure().isCompatibleWith(this.expectedTypes[i].erasure()))) {
if(CharOperation.equals(this.expectedTypes[i].qualifiedPackageName(), proposalType.qualifiedPackageName()) &&
CharOperation.equals(this.expectedTypes[i].qualifiedSourceName(), proposalType.qualifiedSourceName())) {
return R_EXACT_EXPECTED_TYPE;
}
relevance = R_EXPECTED_TYPE;
}
if((this.expectedTypesFilter & SUPERTYPE) != 0
&& this.expectedTypes[i].isCompatibleWith(proposalType)) {
if(CharOperation.equals(this.expectedTypes[i].qualifiedPackageName(), proposalType.qualifiedPackageName()) &&
CharOperation.equals(this.expectedTypes[i].qualifiedSourceName(), proposalType.qualifiedSourceName())) {
return R_EXACT_EXPECTED_TYPE;
}
relevance = R_EXPECTED_TYPE;
}
// Bug 84720 - [1.5][assist] proposal ranking by return value should consider auto(un)boxing
// Just ensuring that the unitScope is not null, even though it's an unlikely case.
if (this.unitScope != null && this.unitScope.isBoxingCompatibleWith(proposalType, this.expectedTypes[i])) {
relevance = R_EXPECTED_TYPE;
}
}
return relevance;
}
return 0;
}
private int computeRelevanceForInheritance(ReferenceBinding receiverType, ReferenceBinding declaringClass) {
if (TypeBinding.equalsEquals(receiverType, declaringClass)) return R_NON_INHERITED;
return 0;
}
int computeRelevanceForInterestingProposal(){
return computeRelevanceForInterestingProposal(null);
}
private int computeRelevanceForInterestingProposal(Binding binding){
if(this.uninterestingBindings != null) {
for (int i = 0; i <= this.uninterestingBindingsPtr; i++) {
if(this.uninterestingBindings[i] == binding) {
return 0;
}
if((this.uninterestingBindingsFilter & SUBTYPE) != 0) {
if (binding instanceof TypeBinding &&
this.uninterestingBindings[i] instanceof TypeBinding &&
((TypeBinding)binding).isCompatibleWith((TypeBinding)this.uninterestingBindings[i])) {
return 0;
}
}
if ((this.uninterestingBindingsFilter & SUPERTYPE) != 0) {
if (binding instanceof TypeBinding &&
this.uninterestingBindings[i] instanceof TypeBinding &&
((TypeBinding)this.uninterestingBindings[i]).isCompatibleWith((TypeBinding)binding)) {
return 0;
}
}
}
}
return R_INTERESTING;
}
private int computeRelevanceForInterestingProposal(char[] givenPkgName, char[] fullTypeName) {
for (int i = 0; i <= this.uninterestingBindingsPtr; i++) {
if (this.uninterestingBindings[i] instanceof TypeBinding) {
TypeBinding typeBinding = (TypeBinding) this.uninterestingBindings[i];
char[] currPkgName = typeBinding.qualifiedPackageName();
if (CharOperation.equals(givenPkgName, currPkgName)) {
char[] currTypeName = typeBinding.qualifiedSourceName();
if (CharOperation.equals(fullTypeName, currTypeName)) {
return 0;
}
}
}
}
return R_INTERESTING;
}
private int computeRelevanceForInterface(){
if(this.assistNodeIsInterface) {
return R_INTERFACE;
}
return 0;
}
private int computeRelevanceForMissingElements(boolean hasProblems) {
if (!hasProblems) {
return R_NO_PROBLEMS;
}
return 0;
}
int computeRelevanceForQualification(boolean prefixRequired) {
if(!prefixRequired && !this.insideQualifiedReference) {
return R_UNQUALIFIED;
}
if(prefixRequired && this.insideQualifiedReference) {
return R_QUALIFIED;
}
return 0;
}
int computeRelevanceForResolution(){
return computeRelevanceForResolution(true);
}
int computeRelevanceForResolution(boolean isResolved){
if (isResolved) {
return R_RESOLVED;
}
return 0;
}
int computeRelevanceForRestrictions(int accessRuleKind) {
if(accessRuleKind == IAccessRule.K_ACCESSIBLE) {
return R_NON_RESTRICTED;
}
return 0;
}
private int computeRelevanceForStatic(boolean onlyStatic, boolean isStatic) {
if(this.insideQualifiedReference && !onlyStatic && !isStatic) {
return R_NON_STATIC;
}
return 0;
}
private int computeRelevanceForFinal(boolean onlyFinal, boolean isFinal) {
if (onlyFinal && isFinal) {
return R_FINAL;
}
return 0;
}
private int computeRelevanceForSuper(MethodBinding method, Scope scope, InvocationSite site) {
if (site instanceof CompletionOnMemberAccess) {
CompletionOnMemberAccess access = (CompletionOnMemberAccess) site;
if (access.isSuperAccess() && this.parser.assistNodeParent == null) {
ReferenceContext referenceContext = scope.referenceContext();
if (referenceContext instanceof AbstractMethodDeclaration) { // LE is anonymous.
MethodBinding binding = ((AbstractMethodDeclaration) referenceContext).binding;
if (binding != null) {
if (CharOperation.equals(binding.selector, method.selector)) {
if (binding.areParameterErasuresEqual(method)) {
return R_EXACT_NAME + R_METHOD_OVERIDE;
}
return R_EXACT_NAME;
}
}
}
}
}
return 0;
}
private long computeTargetedElement(CompletionOnAnnotationOfType fakeNode) {
ASTNode annotatedElement = fakeNode.potentialAnnotatedNode;
if (annotatedElement instanceof TypeDeclaration) {
TypeDeclaration annotatedTypeDeclaration = (TypeDeclaration) annotatedElement;
if (TypeDeclaration.kind(annotatedTypeDeclaration.modifiers) == TypeDeclaration.ANNOTATION_TYPE_DECL) {
return TagBits.AnnotationForAnnotationType | TagBits.AnnotationForType | TagBits.AnnotationForTypeUse;
}
return TagBits.AnnotationForType | TagBits.AnnotationForTypeUse;
} else if (annotatedElement instanceof FieldDeclaration) {
if (fakeNode.isParameter) {
return TagBits.AnnotationForParameter;
}
return TagBits.AnnotationForField;
} else if (annotatedElement instanceof MethodDeclaration) {
return TagBits.AnnotationForMethod;
} else if (annotatedElement instanceof Argument) {
return TagBits.AnnotationForParameter;
} else if (annotatedElement instanceof ConstructorDeclaration) {
return TagBits.AnnotationForConstructor;
} else if (annotatedElement instanceof LocalDeclaration) {
return TagBits.AnnotationForLocalVariable;
} else if (annotatedElement instanceof ImportReference) {
return TagBits.AnnotationForPackage;
}
return 0;
}
private TypeBinding[] computeTypes(Expression[] arguments) {
if (arguments == null) return null;
int argsLength = arguments.length;
TypeBinding[] argTypes = new TypeBinding[argsLength];
for (int a = argsLength; --a >= 0;) {
argTypes[a] = arguments[a].resolvedType;
}
return argTypes;
}
private TypeBinding[] computeTypesIfCorrect(Expression[] arguments) {
if (arguments == null) return null;
int argsLength = arguments.length;
TypeBinding[] argTypes = new TypeBinding[argsLength];
for (int a = argsLength; --a >= 0;) {
TypeBinding typeBinding = arguments[a].resolvedType;
if(typeBinding == null || !typeBinding.isValidBinding()) return null;
argTypes[a] = typeBinding;
}
return argTypes;
}
private void computeUninterestingBindings(ASTNode astNode, ASTNode parent, Scope scope){
this.uninterestingBindingsFilter = NONE;
if(parent instanceof LocalDeclaration) {
addUninterestingBindings(((LocalDeclaration)parent).binding);
} else if (parent instanceof FieldDeclaration) {
addUninterestingBindings(((FieldDeclaration)parent).binding);
} else if (parent instanceof TryStatement) {
boolean isException = false;
if (astNode instanceof CompletionOnSingleTypeReference) {
isException = ((CompletionOnSingleTypeReference)astNode).isException();
} else if (astNode instanceof CompletionOnQualifiedTypeReference) {
isException = ((CompletionOnQualifiedTypeReference)astNode).isException();
} else if (astNode instanceof CompletionOnParameterizedQualifiedTypeReference) {
isException = ((CompletionOnParameterizedQualifiedTypeReference)astNode).isException();
}
if (isException) {
this.uninterestingBindingsFilter |= SUBTYPE;
// super-types also need to be discouraged if we're in a union type (bug 350652)
Argument[] args = ((TryStatement)parent).catchArguments;
for (int i = 0; i < args.length; i++) {
if (args[i].type instanceof UnionTypeReference) {
CompletionNodeDetector detector = new CompletionNodeDetector(astNode, args[i]);
if (detector.containsCompletionNode()) {
this.uninterestingBindingsFilter |= SUPERTYPE;
break;
}
}
}
}
}
}
private char[] createImportCharArray(char[] importedElement, boolean isStatic, boolean onDemand) {
char[] result = IMPORT;
if (isStatic) {
result = CharOperation.concat(result, STATIC, ' ');
}
result = CharOperation.concat(result, importedElement, ' ');
if (onDemand) {
result = CharOperation.concat(result, ON_DEMAND);
}
return CharOperation.concat(result, IMPORT_END);
}
private void createMethod(MethodBinding method, char[][] parameterPackageNames, char[][] parameterTypeNames, char[][] parameterNames, Scope scope, StringBuffer completion) {
//// Modifiers
// flush uninteresting modifiers
int insertedModifiers = method.modifiers & ~(ClassFileConstants.AccNative | ClassFileConstants.AccAbstract);
if(insertedModifiers != ClassFileConstants.AccDefault){
ASTNode.printModifiers(insertedModifiers, completion);
}
//// Type parameters
TypeVariableBinding[] typeVariableBindings = method.typeVariables;
if(typeVariableBindings != null && typeVariableBindings.length != 0) {
completion.append('<');
for (int i = 0; i < typeVariableBindings.length; i++) {
if(i != 0) {
completion.append(',');
completion.append(' ');
}
createTypeVariable(typeVariableBindings[i], scope, completion);
}
completion.append('>');
completion.append(' ');
}
//// Return type
createType(method.returnType, scope, completion);
completion.append(' ');
//// Selector
completion.append(method.selector);
completion.append('(');
////Parameters
TypeBinding[] parameterTypes = method.parameters;
int length = parameterTypes.length;
for (int i = 0; i < length; i++) {
if(i != 0) {
completion.append(',');
completion.append(' ');
}
createType(parameterTypes[i], scope, completion);
completion.append(' ');
if(parameterNames != null){
completion.append(parameterNames[i]);
} else {
completion.append('%');
}
}
completion.append(')');
//// Exceptions
ReferenceBinding[] exceptions = method.thrownExceptions;
if (exceptions != null && exceptions.length > 0){
completion.append(' ');
completion.append(THROWS);
completion.append(' ');
for(int i = 0; i < exceptions.length ; i++){
if(i != 0) {
completion.append(' ');
completion.append(',');
}
createType(exceptions[i], scope, completion);
}
}
}
protected InternalCompletionProposal createProposal(int kind, int completionOffset) {
InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(kind, completionOffset - this.offset);
proposal.nameLookup = this.nameEnvironment.nameLookup;
proposal.completionEngine = this;
return proposal;
}
private CompletionProposal createRequiredTypeProposal(Binding binding, int start, int end, int relevance) {
InternalCompletionProposal proposal = null;
if (binding instanceof ReferenceBinding) {
ReferenceBinding typeBinding = (ReferenceBinding) binding;
char[] packageName = typeBinding.qualifiedPackageName();
char[] typeName = typeBinding.qualifiedSourceName();
char[] fullyQualifiedName = CharOperation.concat(packageName, typeName, '.');
proposal = createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
proposal.nameLookup = this.nameEnvironment.nameLookup;
proposal.completionEngine = this;
proposal.setDeclarationSignature(packageName);
proposal.setSignature(getRequiredTypeSignature(typeBinding));
proposal.setPackageName(packageName);
proposal.setTypeName(typeName);
proposal.setCompletion(fullyQualifiedName);
proposal.setFlags(typeBinding.modifiers);
proposal.setReplaceRange(start - this.offset, end - this.offset);
proposal.setTokenRange(start - this.offset, end - this.offset);
proposal.setRelevance(relevance);
} else if (binding instanceof PackageBinding) {
PackageBinding packageBinding = (PackageBinding) binding;
char[] packageName = CharOperation.concatWith(packageBinding.compoundName, '.');
proposal = createProposal(CompletionProposal.PACKAGE_REF, this.actualCompletionPosition);
proposal.setDeclarationSignature(packageName);
proposal.setPackageName(packageName);
proposal.setCompletion(packageName);
proposal.setReplaceRange(start - this.offset, end - this.offset);
proposal.setTokenRange(start - this.offset, end - this.offset);
proposal.setRelevance(relevance);
}
return proposal;
}
//{ObjectTeams:
private void createOverrideRoleProposal(ReferenceBinding superTeam, char[] roleName, char[] roleTypeSignature, int modifiers) {
StringBuffer completion = new StringBuffer(10);
createRole(roleName, modifiers, completion);
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(this.completionToken, roleName);
// via analogy:
relevance += R_METHOD_OVERIDE;
if((modifiers & ClassFileConstants.AccAbstract) != 0) relevance += R_ABSTRACT_METHOD;
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.OVERRIDE_ROLE_DECLARATION)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.OVERRIDE_ROLE_DECLARATION, this.actualCompletionPosition);
proposal.setDeclarationSignature(getSignature(superTeam));
proposal.setDeclarationKey(superTeam.computeUniqueKey());
proposal.setSignature(roleTypeSignature);
// proposal.setKey(superRole.getKey().toCharArray()); // FIXME(SH): unused?
proposal.setDeclarationPackageName(superTeam.qualifiedPackageName());
proposal.setDeclarationTypeName(superTeam.qualifiedSourceName());
proposal.setCompletion(completion.toString().toCharArray());
proposal.setName(roleName);
proposal.setFlags(modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
private void createRole(char[] superRoleName, int modifiers, StringBuffer completion) {
//// Modifiers
if(modifiers != ClassFileConstants.AccDefault){
ASTNode.printModifiers(modifiers, completion);
}
//// Keyword
if ((modifiers & ClassFileConstants.AccInterface) != 0)
completion.append("interface "); //$NON-NLS-1$
else
completion.append("class "); //$NON-NLS-1$
//// Name
completion.append(superRoleName);
//// Empty body
completion.append(" {}"); //$NON-NLS-1$
}
// SH}
private void createType(TypeBinding type, Scope scope, StringBuffer completion) {
switch (type.kind()) {
case Binding.BASE_TYPE :
completion.append(type.sourceName());
break;
case Binding.WILDCARD_TYPE :
case Binding.INTERSECTION_TYPE : // TODO (david) need to handle intersection type specifically
WildcardBinding wildcardBinding = (WildcardBinding) type;
completion.append('?');
switch (wildcardBinding.boundKind) {
case Wildcard.EXTENDS:
completion.append(' ');
completion.append(EXTENDS);
completion.append(' ');
createType(wildcardBinding.bound, scope, completion);
if(wildcardBinding.otherBounds != null) {
int length = wildcardBinding.otherBounds.length;
for (int i = 0; i < length; i++) {
completion.append(' ');
completion.append('&');
completion.append(' ');
createType(wildcardBinding.otherBounds[i], scope, completion);
}
}
break;
case Wildcard.SUPER:
completion.append(' ');
completion.append(SUPER);
completion.append(' ');
createType(wildcardBinding.bound, scope, completion);
break;
}
break;
case Binding.ARRAY_TYPE :
createType(type.leafComponentType(), scope, completion);
int dim = type.dimensions();
for (int i = 0; i < dim; i++) {
completion.append('[');
completion.append(']');
}
break;
case Binding.PARAMETERIZED_TYPE :
ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) type;
if (type.isMemberType()) {
createType(parameterizedType.enclosingType(), scope, completion);
completion.append('.');
completion.append(parameterizedType.sourceName);
} else {
completion.append(CharOperation.concatWith(parameterizedType.genericType().compoundName, '.'));
}
if (parameterizedType.arguments != null) {
completion.append('<');
for (int i = 0, length = parameterizedType.arguments.length; i < length; i++) {
if (i != 0) completion.append(',');
createType(parameterizedType.arguments[i], scope, completion);
}
completion.append('>');
}
break;
default :
char[] packageName = type.qualifiedPackageName();
char[] typeName = type.qualifiedSourceName();
if(mustQualifyType(
(ReferenceBinding)type,
packageName,
scope)) {
completion.append(CharOperation.concat(packageName, typeName,'.'));
} else {
completion.append(type.sourceName());
}
break;
}
}
/*
* Create a completion proposal for a member type.
*/
private void createTypeParameterProposal(TypeParameter typeParameter, int relevance) {
char[] completionName = typeParameter.name;
// Create standard type proposal
if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.TYPE_REF, this.actualCompletionPosition - this.offset);
proposal.nameLookup = this.nameEnvironment.nameLookup;
proposal.completionEngine = this;
proposal.setSignature(getSignature(typeParameter.binding));
proposal.setTypeName(completionName);
proposal.setCompletion(completionName);
proposal.setFlags(typeParameter.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
// Create javadoc text proposal if necessary
if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF)) {
char[] javadocCompletion= inlineTagCompletion(completionName, JavadocTagConstants.TAG_LINK);
InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.JAVADOC_TYPE_REF, this.actualCompletionPosition - this.offset);
proposal.nameLookup = this.nameEnvironment.nameLookup;
proposal.completionEngine = this;
proposal.setSignature(getSignature(typeParameter.binding));
proposal.setTypeName(javadocCompletion);
proposal.setCompletion(javadocCompletion);
proposal.setFlags(typeParameter.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance+R_INLINE_TAG);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
/*
* Create a completion proposal for a type.
*/
private void createTypeProposal(char[] packageName, char[] typeName, int modifiers, int accessibility, char[] completionName, int relevance) {
// Create standard type proposal
if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) {
InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.TYPE_REF, this.actualCompletionPosition - this.offset);
proposal.nameLookup = this.nameEnvironment.nameLookup;
proposal.completionEngine = this;
proposal.setDeclarationSignature(packageName);
proposal.setSignature(createNonGenericTypeSignature(packageName, typeName));
proposal.setPackageName(packageName);
proposal.setTypeName(typeName);
proposal.setCompletion(completionName);
proposal.setFlags(modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
proposal.setAccessibility(accessibility);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
// Create javadoc text proposal if necessary
if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF)) {
char[] javadocCompletion= inlineTagCompletion(completionName, JavadocTagConstants.TAG_LINK);
InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.JAVADOC_TYPE_REF, this.actualCompletionPosition - this.offset);
proposal.nameLookup = this.nameEnvironment.nameLookup;
proposal.completionEngine = this;
proposal.setDeclarationSignature(packageName);
proposal.setSignature(createNonGenericTypeSignature(packageName, typeName));
proposal.setPackageName(packageName);
proposal.setTypeName(typeName);
proposal.setCompletion(javadocCompletion);
proposal.setFlags(modifiers);
int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition;
proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance+R_INLINE_TAG);
proposal.setAccessibility(accessibility);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
/*
* Create a completion proposal for a member type.
*/
private void createTypeProposal(
ReferenceBinding refBinding,
char[] typeName,
int accessibility,
char[] completionName,
int relevance,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems) {
// Create standard type proposal
if(!this.isIgnored(CompletionProposal.TYPE_REF, missingElements != null) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) {
InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.TYPE_REF, this.actualCompletionPosition - this.offset);
proposal.nameLookup = this.nameEnvironment.nameLookup;
proposal.completionEngine = this;
proposal.setDeclarationSignature(refBinding.qualifiedPackageName());
proposal.setSignature(getCompletedTypeSignature(refBinding));
proposal.setPackageName(refBinding.qualifiedPackageName());
proposal.setTypeName(typeName);
if (missingElements != null) {
CompletionProposal[] subProposals = new CompletionProposal[missingElements.length];
for (int i = 0; i < missingElements.length; i++) {
subProposals[i] =
createRequiredTypeProposal(
missingElements[i],
missingElementsStarts[i],
missingElementsEnds[i],
relevance);
}
proposal.setRequiredProposals(subProposals);
}
proposal.setCompletion(completionName);
proposal.setFlags(refBinding.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
// Create javadoc text proposal if necessary
if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF)) {
char[] javadocCompletion= inlineTagCompletion(completionName, JavadocTagConstants.TAG_LINK);
InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.JAVADOC_TYPE_REF, this.actualCompletionPosition - this.offset);
proposal.nameLookup = this.nameEnvironment.nameLookup;
proposal.completionEngine = this;
proposal.setDeclarationSignature(refBinding.qualifiedPackageName());
proposal.setSignature(getCompletedTypeSignature(refBinding));
proposal.setPackageName(refBinding.qualifiedPackageName());
proposal.setTypeName(typeName);
proposal.setCompletion(javadocCompletion);
proposal.setFlags(refBinding.modifiers);
int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition;
proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance+R_INLINE_TAG);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
private void createTypeVariable(TypeVariableBinding typeVariable, Scope scope, StringBuffer completion) {
completion.append(typeVariable.sourceName);
//{ObjectTeams:
if (typeVariable.roletype != null && TypeBinding.equalsEquals(typeVariable.firstBound, typeVariable.roletype)) {
completion.append(' ');
completion.append(BASE);
completion.append(' ');
createType(typeVariable.roletype, scope, completion);
}
// SH}
if (typeVariable.superclass != null && TypeBinding.equalsEquals(typeVariable.firstBound, typeVariable.superclass)) {
completion.append(' ');
completion.append(EXTENDS);
completion.append(' ');
createType(typeVariable.superclass, scope, completion);
}
if (typeVariable.superInterfaces != null && typeVariable.superInterfaces != Binding.NO_SUPERINTERFACES) {
if (TypeBinding.notEquals(typeVariable.firstBound, typeVariable.superclass)) {
completion.append(' ');
completion.append(EXTENDS);
completion.append(' ');
}
for (int i = 0, length = typeVariable.superInterfaces.length; i < length; i++) {
if (i > 0 || TypeBinding.equalsEquals(typeVariable.firstBound, typeVariable.superclass)) {
completion.append(' ');
completion.append(EXTENDS);
completion.append(' ');
}
createType(typeVariable.superInterfaces[i], scope, completion);
}
}
}
private void createVargsType(TypeBinding type, Scope scope, StringBuffer completion) {
if (type.isArrayType()) {
createType(type.leafComponentType(), scope, completion);
int dim = type.dimensions() - 1;
for (int i = 0; i < dim; i++) {
completion.append('[');
completion.append(']');
}
completion.append(VARARGS);
} else {
createType(type, scope, completion);
}
}
private void findAnnotationAttributes(char[] token, MemberValuePair[] attributesFound, ReferenceBinding annotation) {
MethodBinding[] methods = annotation.availableMethods();
nextAttribute: for (int i = 0; i < methods.length; i++) {
MethodBinding method = methods[i];
if(isFailedMatch(token, method.selector)) continue nextAttribute;
int length = attributesFound == null ? 0 : attributesFound.length;
for (int j = 0; j < length; j++) {
if(CharOperation.equals(method.selector, attributesFound[j].name, false)) continue nextAttribute;
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal(method);
relevance += computeRelevanceForCaseMatching(token, method.selector);
relevance += computeRelevanceForQualification(false);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.ANNOTATION_ATTRIBUTE_REF)) {
CompletionProposal proposal = createProposal(CompletionProposal.ANNOTATION_ATTRIBUTE_REF, this.actualCompletionPosition);
proposal.setDeclarationSignature(getSignature(method.declaringClass));
proposal.setSignature(getSignature(method.returnType));
proposal.setName(method.selector);
// add "=" to completion since it will always be needed
char[] completion= method.selector;
if (JavaCore.INSERT.equals(this.javaProject.getOption(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATOR, true))) {
completion= CharOperation.concat(completion, new char[] {' '});
}
completion= CharOperation.concat(completion, new char[] {'='});
if (JavaCore.INSERT.equals(this.javaProject.getOption(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATOR, true))) {
completion= CharOperation.concat(completion, new char[] {' '});
}
proposal.setCompletion(completion);
proposal.setFlags(method.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
}
void findAnonymousType(
ReferenceBinding currentType,
TypeBinding[] argTypes,
Scope scope,
InvocationSite invocationSite,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems) {
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal(currentType);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
if (missingElements != null) {
relevance += computeRelevanceForMissingElements(missingElementsHaveProblems);
}
//{ObjectTeams: other parts of completion prefer role interfaces, but here we need to go back to the role class:
if (currentType.isSynthInterface()) {
currentType = currentType.roleModel.getClassPartBinding();
if (currentType == null) return;
}
// SH}
findAnonymousType(
currentType,
argTypes,
scope,
invocationSite,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
true,
false,
relevance);
}
private void findAnonymousType(
ReferenceBinding currentType,
TypeBinding[] argTypes,
Scope scope,
InvocationSite invocationSite,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems,
boolean exactMatch,
boolean isQualified,
int relevance) {
//{ObjectTeams: other parts of completion prefer role interfaces, but here we need to go back to the role class:
if (currentType.isSynthInterface()) {
currentType = currentType.roleModel.getClassPartBinding();
if (currentType == null) return;
}
// SH}
if (currentType.isInterface()) {
char[] completion = CharOperation.NO_CHAR;
char[] typeCompletion = null;
if (!exactMatch) {
typeCompletion =
isQualified ?
CharOperation.concat(currentType.qualifiedPackageName(), currentType.qualifiedSourceName(), '.') :
currentType.sourceName();
if (this.source != null
&& this.source.length > this.endPosition
&& this.source[this.endPosition] == '(') {
completion = CharOperation.NO_CHAR;
} else {
completion = new char[] { '(', ')' };
}
}
this.noProposal = false;
if (!exactMatch) {
if(!isIgnored(CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)) {
char[] packageName = currentType.isLocalType() ? null : currentType.qualifiedPackageName();
char[] typeName = currentType.qualifiedSourceName();
InternalCompletionProposal proposal = createProposal(CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION, this.actualCompletionPosition);
proposal.setDeclarationSignature(getSignature(currentType));
proposal.setDeclarationKey(currentType.computeUniqueKey());
proposal.setSignature(
createMethodSignature(
CharOperation.NO_CHAR_CHAR,
CharOperation.NO_CHAR_CHAR,
CharOperation.NO_CHAR,
CharOperation.NO_CHAR));
//proposal.setOriginalSignature(null);
//proposal.setUniqueKey(null);
proposal.setDeclarationPackageName(packageName);
proposal.setDeclarationTypeName(typeName);
//proposal.setParameterPackageNames(null);
//proposal.setParameterTypeNames(null);
//proposal.setPackageName(null);
//proposal.setTypeName(null);
proposal.setName(currentType.sourceName());
InternalCompletionProposal typeProposal = createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
typeProposal.nameLookup = this.nameEnvironment.nameLookup;
typeProposal.completionEngine = this;
typeProposal.setDeclarationSignature(packageName);
typeProposal.setSignature(getRequiredTypeSignature(currentType));
typeProposal.setPackageName(packageName);
typeProposal.setTypeName(typeName);
typeProposal.setCompletion(typeCompletion);
typeProposal.setFlags(currentType.modifiers);
typeProposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
typeProposal.setTokenRange(this.startPosition - this.offset, this.endPosition - this.offset);
typeProposal.setRelevance(relevance);
proposal.setRequiredProposals( new CompletionProposal[]{typeProposal});
proposal.setCompletion(completion);
proposal.setFlags(Flags.AccPublic);
proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
} else {
if(!isIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, missingElements != null)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, this.actualCompletionPosition);
proposal.setDeclarationSignature(getSignature(currentType));
proposal.setDeclarationKey(currentType.computeUniqueKey());
proposal.setSignature(
createMethodSignature(
CharOperation.NO_CHAR_CHAR,
CharOperation.NO_CHAR_CHAR,
CharOperation.NO_CHAR,
CharOperation.NO_CHAR));
//proposal.setOriginalSignature(null);
//proposal.setUniqueKey(null);
proposal.setDeclarationPackageName(currentType.qualifiedPackageName());
proposal.setDeclarationTypeName(currentType.qualifiedSourceName());
//proposal.setParameterPackageNames(null);
//proposal.setParameterTypeNames(null);
//proposal.setPackageName(null);
//proposal.setTypeName(null);
if (missingElements != null) {
CompletionProposal[] subProposals = new CompletionProposal[missingElements.length];
for (int i = 0; i < missingElements.length; i++) {
subProposals[i] =
createRequiredTypeProposal(
missingElements[i],
missingElementsStarts[i],
missingElementsEnds[i],
relevance);
}
proposal.setRequiredProposals(subProposals);
}
proposal.setCompletion(completion);
proposal.setFlags(Flags.AccPublic);
proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenEnd - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
} else {
findConstructors(
currentType,
argTypes,
scope,
invocationSite,
true,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
exactMatch,
isQualified,
relevance);
}
}
private void findClassField(
char[] token,
TypeBinding receiverType,
Scope scope,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems) {
if (token == null) return;
if (token.length <= classField.length
&& CharOperation.prefixEquals(token, classField, false /* ignore case */
)) {
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(token, classField);
relevance += computeRelevanceForExpectingType(scope.getJavaLangClass());
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); //no access restriction for class field
relevance += R_NON_INHERITED;
if (missingElements != null) {
relevance += computeRelevanceForMissingElements(missingElementsHaveProblems);
}
this.noProposal = false;
if(!isIgnored(CompletionProposal.FIELD_REF, missingElements != null)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
//proposal.setDeclarationSignature(null);
char[] signature =
createNonGenericTypeSignature(
CharOperation.concatWith(JAVA_LANG, '.'),
CLASS);
if (this.compilerOptions.sourceLevel > ClassFileConstants.JDK1_4) {
// add type argument
char[] typeArgument = getTypeSignature(receiverType);
int oldLength = signature.length;
int argumentLength = typeArgument.length;
int newLength = oldLength + argumentLength + 2;
System.arraycopy(signature, 0, signature = new char[newLength], 0, oldLength - 1);
signature[oldLength - 1] = '<';
System.arraycopy(typeArgument, 0, signature, oldLength , argumentLength);
signature[newLength - 2] = '>';
signature[newLength - 1] = ';';
}
proposal.setSignature(signature);
//proposal.setDeclarationPackageName(null);
//proposal.setDeclarationTypeName(null);
proposal.setPackageName(CharOperation.concatWith(JAVA_LANG, '.'));
proposal.setTypeName(CLASS);
proposal.setName(classField);
if (missingElements != null) {
CompletionProposal[] subProposals = new CompletionProposal[missingElements.length];
for (int i = 0; i < missingElements.length; i++) {
subProposals[i] =
createRequiredTypeProposal(
missingElements[i],
missingElementsStarts[i],
missingElementsEnds[i],
relevance);
}
proposal.setRequiredProposals(subProposals);
}
proposal.setCompletion(classField);
proposal.setFlags(Flags.AccStatic | Flags.AccPublic);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
}
void findConstructors(
ReferenceBinding currentType,
TypeBinding[] argTypes,
Scope scope,
InvocationSite invocationSite,
boolean forAnonymousType,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems) {
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
if (missingElements != null) {
relevance += computeRelevanceForMissingElements(missingElementsHaveProblems);
}
findConstructors(
currentType,
argTypes,
scope,
invocationSite,
forAnonymousType,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
true,
false,
relevance);
}
private void findConstructorsFromMissingType(
TypeReference typeRef,
final TypeBinding[] argTypes,
final Scope scope,
final InvocationSite invocationSite) {
MissingTypesGuesser missingTypesConverter = new MissingTypesGuesser(this);
MissingTypesGuesser.GuessedTypeRequestor substitutionRequestor =
new MissingTypesGuesser.GuessedTypeRequestor() {
@Override
public void accept(
TypeBinding guessedType,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean hasProblems) {
if (guessedType instanceof ReferenceBinding) {
ReferenceBinding ref = (ReferenceBinding) guessedType;
if (!isIgnored(CompletionProposal.METHOD_REF, missingElements != null)
&& ref.isClass()
&& !ref.isAbstract()) {
findConstructors(
ref,
argTypes,
scope,
invocationSite,
false,
missingElements,
missingElementsStarts,
missingElementsEnds,
hasProblems);
}
checkCancel();
if (!isIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, missingElements != null)
&& !ref.isFinal()
&& !ref.isEnum()){
findAnonymousType(
ref,
argTypes,
scope,
invocationSite,
missingElements,
missingElementsStarts,
missingElementsEnds,
hasProblems);
}
}
}
};
missingTypesConverter.guess(typeRef, scope, substitutionRequestor);
}
private void findConstructors(
ReferenceBinding currentType,
TypeBinding[] argTypes,
Scope scope,
InvocationSite invocationSite,
boolean forAnonymousType,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems,
boolean exactMatch,
boolean isQualified,
int relevance) {
// No visibility checks can be performed without the scope & invocationSite
MethodBinding[] methods = null;
if (currentType instanceof ParameterizedTypeBinding && invocationSite instanceof CompletionOnQualifiedAllocationExpression) {
CompletionOnQualifiedAllocationExpression alloc = (CompletionOnQualifiedAllocationExpression) invocationSite;
if ((alloc.bits & ASTNode.IsDiamond) != 0) {
// inference failed. So don't substitute type arguments. Just return the unsubstituted methods
// and let the user decide what to substitute.
ParameterizedTypeBinding binding = (ParameterizedTypeBinding) currentType;
ReferenceBinding originalGenericType = binding.genericType();
if (originalGenericType != null)
methods = originalGenericType.methods();
} else {
methods = currentType.availableMethods();
}
} else {
methods = currentType.availableMethods();
}
if(methods != null) {
int minArgLength = argTypes == null ? 0 : argTypes.length;
next : for (int f = methods.length; --f >= 0;) {
MethodBinding constructor = methods[f];
if (constructor.isConstructor()) {
if (constructor.isSynthetic()) continue next;
if (this.options.checkDeprecation &&
constructor.isViewedAsDeprecated() &&
!scope.isDefinedInSameUnit(constructor.declaringClass))
continue next;
if (this.options.checkVisibility
&& !constructor.canBeSeenBy(invocationSite, scope)) {
if(!forAnonymousType || !constructor.isProtected())
continue next;
}
TypeBinding[] parameters = constructor.parameters;
int paramLength = parameters.length;
if (minArgLength > paramLength)
continue next;
for (int a = minArgLength; --a >= 0;)
if (argTypes[a] != null) { // can be null if it could not be resolved properly
if (!argTypes[a].isCompatibleWith(constructor.parameters[a]))
continue next;
}
char[][] parameterPackageNames = new char[paramLength][];
char[][] parameterTypeNames = new char[paramLength][];
for (int i = 0; i < paramLength; i++) {
TypeBinding type = parameters[i];
parameterPackageNames[i] = type.qualifiedPackageName();
parameterTypeNames[i] = type.qualifiedSourceName();
}
char[][] parameterNames = findMethodParameterNames(constructor,parameterTypeNames);
char[] completion = CharOperation.NO_CHAR;
if(forAnonymousType){
char[] typeCompletion = null;
if (!exactMatch) {
typeCompletion =
isQualified ?
CharOperation.concat(currentType.qualifiedPackageName(), currentType.qualifiedSourceName(), '.') :
currentType.sourceName();
if (this.source != null
&& this.source.length > this.endPosition
&& this.source[this.endPosition] == '(') {
completion = CharOperation.NO_CHAR;
} else {
completion = new char[] { '(', ')' };
}
}
this.noProposal = false;
if (!exactMatch) {
if(!isIgnored(CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)) {
char[] packageName = currentType.isLocalType() ? null : currentType.qualifiedPackageName();
char[] typeName = currentType.qualifiedSourceName();
InternalCompletionProposal proposal = createProposal(CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION, this.actualCompletionPosition);
proposal.setBinding(constructor);
proposal.setDeclarationSignature(getSignature(currentType));
proposal.setDeclarationKey(currentType.computeUniqueKey());
proposal.setSignature(getSignature(constructor));
MethodBinding original = constructor.original();
if(original != constructor) {
proposal.setOriginalSignature(getSignature(original));
}
proposal.setKey(constructor.computeUniqueKey());
proposal.setDeclarationPackageName(packageName);
proposal.setDeclarationTypeName(typeName);
proposal.setParameterPackageNames(parameterPackageNames);
proposal.setParameterTypeNames(parameterTypeNames);
//proposal.setPackageName(null);
//proposal.setTypeName(null);
proposal.setName(currentType.sourceName());
InternalCompletionProposal typeProposal = createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
typeProposal.nameLookup = this.nameEnvironment.nameLookup;
typeProposal.completionEngine = this;
typeProposal.setDeclarationSignature(packageName);
typeProposal.setSignature(getRequiredTypeSignature(currentType));
typeProposal.setPackageName(packageName);
typeProposal.setTypeName(typeName);
typeProposal.setCompletion(typeCompletion);
typeProposal.setFlags(currentType.modifiers);
typeProposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
typeProposal.setTokenRange(this.startPosition - this.offset, this.endPosition - this.offset);
typeProposal.setRelevance(relevance);
proposal.setRequiredProposals( new CompletionProposal[]{typeProposal});
proposal.setCompletion(completion);
proposal.setFlags(constructor.modifiers);
proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
if(parameterNames != null) proposal.setParameterNames(parameterNames);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
} else {
if(!isIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, missingElements != null)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, this.actualCompletionPosition);
proposal.setDeclarationSignature(getSignature(currentType));
proposal.setDeclarationKey(currentType.computeUniqueKey());
proposal.setSignature(getSignature(constructor));
MethodBinding original = constructor.original();
if(original != constructor) {
proposal.setOriginalSignature(getSignature(original));
}
proposal.setKey(constructor.computeUniqueKey());
proposal.setDeclarationPackageName(currentType.qualifiedPackageName());
proposal.setDeclarationTypeName(currentType.qualifiedSourceName());
proposal.setParameterPackageNames(parameterPackageNames);
proposal.setParameterTypeNames(parameterTypeNames);
//proposal.setPackageName(null);
//proposal.setTypeName(null);
if (missingElements != null) {
CompletionProposal[] subProposals = new CompletionProposal[missingElements.length];
for (int i = 0; i < missingElements.length; i++) {
subProposals[i] =
createRequiredTypeProposal(
missingElements[i],
missingElementsStarts[i],
missingElementsEnds[i],
relevance);
}
proposal.setRequiredProposals(subProposals);
}
proposal.setCompletion(completion);
proposal.setFlags(constructor.modifiers);
proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenEnd - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
if(parameterNames != null) proposal.setParameterNames(parameterNames);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
} else {
char[] typeCompletion = null;
// Special case for completion in javadoc
if (this.assistNodeInJavadoc > 0) {
Expression receiver = null;
char[] selector = null;
if (invocationSite instanceof CompletionOnJavadocAllocationExpression) {
CompletionOnJavadocAllocationExpression alloc = (CompletionOnJavadocAllocationExpression) invocationSite;
receiver = alloc.type;
} else if (invocationSite instanceof CompletionOnJavadocFieldReference) {
CompletionOnJavadocFieldReference fieldRef = (CompletionOnJavadocFieldReference) invocationSite;
receiver = fieldRef.receiver;
}
if (receiver != null) {
StringBuffer javadocCompletion = new StringBuffer();
if (receiver.isThis()) {
selector = (((JavadocImplicitTypeReference)receiver).token);
if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) {
javadocCompletion.append('#');
}
} else if (receiver instanceof JavadocSingleTypeReference) {
JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) receiver;
selector = typeRef.token;
if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) {
javadocCompletion.append(typeRef.token);
javadocCompletion.append('#');
}
} else if (receiver instanceof JavadocQualifiedTypeReference) {
JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) receiver;
selector = typeRef.tokens[typeRef.tokens.length-1];
if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) {
javadocCompletion.append(CharOperation.concatWith(typeRef.tokens, '.'));
javadocCompletion.append('#');
}
}
// Append parameters types
javadocCompletion.append(selector);
javadocCompletion.append('(');
if (constructor.parameters != null) {
boolean isVarargs = constructor.isVarargs();
for (int p=0, ln=constructor.parameters.length; p<ln; p++) {
if (p>0) javadocCompletion.append(", "); //$NON-NLS-1$
TypeBinding argTypeBinding = constructor.parameters[p];
if (isVarargs && p == ln - 1) {
createVargsType(argTypeBinding.erasure(), scope, javadocCompletion);
} else {
createType(argTypeBinding.erasure(), scope, javadocCompletion);
}
}
}
javadocCompletion.append(')');
completion = javadocCompletion.toString().toCharArray();
}
} else {
if (!exactMatch) {
typeCompletion =
isQualified ?
CharOperation.concat(currentType.qualifiedPackageName(), currentType.qualifiedSourceName(), '.') :
currentType.sourceName();
if (this.source != null
&& this.source.length > this.endPosition
&& this.source[this.endPosition] == '(') {
completion = CharOperation.NO_CHAR;
} else {
completion = new char[] { '(', ')' };
}
}
}
// Create standard proposal
this.noProposal = false;
if (!exactMatch) {
if(!isIgnored(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)) {
char[] packageName = currentType.isLocalType() ? null : currentType.qualifiedPackageName();
char[] typeName = currentType.qualifiedSourceName();
int constructorRelevance = relevance + computeRelevanceForConstructor();
InternalCompletionProposal proposal = createProposal(CompletionProposal.CONSTRUCTOR_INVOCATION, this.actualCompletionPosition);
proposal.setBinding(constructor);
proposal.setDeclarationSignature(getSignature(currentType));
proposal.setSignature(getSignature(constructor));
MethodBinding original = constructor.original();
if(original != constructor) {
proposal.setOriginalSignature(getSignature(original));
}
proposal.setDeclarationPackageName(packageName);
proposal.setDeclarationTypeName(typeName);
proposal.setParameterPackageNames(parameterPackageNames);
proposal.setParameterTypeNames(parameterTypeNames);
//proposal.setPackageName(null);
//proposal.setTypeName(null);
proposal.setName(currentType.sourceName());
InternalCompletionProposal typeProposal = createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
typeProposal.nameLookup = this.nameEnvironment.nameLookup;
typeProposal.completionEngine = this;
typeProposal.setDeclarationSignature(packageName);
typeProposal.setSignature(getRequiredTypeSignature(currentType));
typeProposal.setPackageName(packageName);
typeProposal.setTypeName(typeName);
typeProposal.setCompletion(typeCompletion);
typeProposal.setFlags(currentType.modifiers);
typeProposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
typeProposal.setTokenRange(this.startPosition - this.offset, this.endPosition - this.offset);
typeProposal.setRelevance(constructorRelevance);
proposal.setRequiredProposals( new CompletionProposal[]{typeProposal});
proposal.setIsContructor(true);
proposal.setCompletion(completion);
proposal.setFlags(constructor.modifiers);
proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(constructorRelevance);
if(parameterNames != null) proposal.setParameterNames(parameterNames);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
} else {
if(!isIgnored(CompletionProposal.METHOD_REF, missingElements != null) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
proposal.setBinding(constructor);
proposal.setDeclarationSignature(getSignature(currentType));
proposal.setSignature(getSignature(constructor));
MethodBinding original = constructor.original();
if(original != constructor) {
proposal.setOriginalSignature(getSignature(original));
}
proposal.setDeclarationPackageName(currentType.qualifiedPackageName());
proposal.setDeclarationTypeName(currentType.qualifiedSourceName());
proposal.setParameterPackageNames(parameterPackageNames);
proposal.setParameterTypeNames(parameterTypeNames);
//proposal.setPackageName(null);
//proposal.setTypeName(null);
proposal.setName(currentType.sourceName());
if (missingElements != null) {
CompletionProposal[] subProposals = new CompletionProposal[missingElements.length];
for (int i = 0; i < missingElements.length; i++) {
subProposals[i] =
createRequiredTypeProposal(
missingElements[i],
missingElementsStarts[i],
missingElementsEnds[i],
relevance);
}
proposal.setRequiredProposals(subProposals);
}
proposal.setIsContructor(true);
proposal.setCompletion(completion);
proposal.setFlags(constructor.modifiers);
int start = (this.assistNodeInJavadoc > 0) ? this.startPosition : this.endPosition;
proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
if(parameterNames != null) proposal.setParameterNames(parameterNames);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_METHOD_REF)) {
char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK);
InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_METHOD_REF, this.actualCompletionPosition);
proposal.setBinding(constructor);
proposal.setDeclarationSignature(getSignature(currentType));
proposal.setSignature(getSignature(constructor));
MethodBinding original = constructor.original();
if(original != constructor) {
proposal.setOriginalSignature(getSignature(original));
}
proposal.setDeclarationPackageName(currentType.qualifiedPackageName());
proposal.setDeclarationTypeName(currentType.qualifiedSourceName());
proposal.setParameterPackageNames(parameterPackageNames);
proposal.setParameterTypeNames(parameterTypeNames);
//proposal.setPackageName(null);
//proposal.setTypeName(null);
proposal.setName(currentType.sourceName());
proposal.setIsContructor(true);
proposal.setCompletion(javadocCompletion);
proposal.setFlags(constructor.modifiers);
int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition;
proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance+R_INLINE_TAG);
if(parameterNames != null) proposal.setParameterNames(parameterNames);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
}
}
}
}
}
private char[] getResolvedSignature(char[][] parameterTypes, char[] fullyQualifiedTypeName, int parameterCount, Scope scope) {
char[][] cn = CharOperation.splitOn('.', fullyQualifiedTypeName);
TypeReference ref;
if (cn.length == 1) {
ref = new SingleTypeReference(cn[0], 0);
} else {
ref = new QualifiedTypeReference(cn,new long[cn.length]);
}
TypeBinding guessedType = null;
INameEnvironment oldNameEnvironment = this.lookupEnvironment.nameEnvironment;
this.lookupEnvironment.nameEnvironment = getNoCacheNameEnvironment();
try {
switch (scope.kind) {
case Scope.METHOD_SCOPE :
case Scope.BLOCK_SCOPE :
guessedType = ref.resolveType((BlockScope)scope);
break;
case Scope.CLASS_SCOPE :
guessedType = ref.resolveType((ClassScope)scope);
break;
}
if (guessedType != null && guessedType.isValidBinding()) {
// the erasure must be used because guessedType can be a RawTypeBinding (https://bugs.eclipse.org/bugs/show_bug.cgi?id=276890)
guessedType = guessedType.erasure();
if (guessedType instanceof SourceTypeBinding) {
SourceTypeBinding refBinding = (SourceTypeBinding) guessedType;
if (refBinding.scope == null || refBinding.scope.referenceContext == null) return null;
TypeDeclaration typeDeclaration = refBinding.scope.referenceContext;
AbstractMethodDeclaration[] methods = typeDeclaration.methods;
next : for (int i = 0; i < methods.length; i++) {
AbstractMethodDeclaration method = methods[i];
if (!method.isConstructor()) continue next;
Argument[] arguments = method.arguments;
int argumentsLength = arguments == null ? 0 : arguments.length;
if (parameterCount != argumentsLength) continue next;
for (int j = 0; j < argumentsLength; j++) {
char[] argumentTypeName = getTypeName(arguments[j].type);
if (!CharOperation.equals(argumentTypeName, parameterTypes[j])) {
continue next;
}
}
refBinding.resolveTypesFor(method.binding); // force resolution
if (method.binding == null) continue next;
return getSignature(method.binding);
}
}
}
} finally {
this.lookupEnvironment.nameEnvironment = oldNameEnvironment;
}
return null;
}
private void findConstructorsOrAnonymousTypes(
ReferenceBinding currentType,
Scope scope,
InvocationSite invocationSite,
boolean isQualified,
int relevance) {
//{ObjectTeams: other parts of completion prefer role interfaces, but here we need to go back to the role class:
if (currentType.isSynthInterface()) {
currentType = currentType.roleModel.getClassPartBinding();
if (currentType == null) return;
}
// SH}
if (!isIgnored(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)
&& currentType.isClass()
&& !currentType.isAbstract()) {
findConstructors(
currentType,
null,
scope,
invocationSite,
false,
null,
null,
null,
false,
false,
isQualified,
relevance);
}
//{ObjectTeams: no anonymous classes from roles:
if (currentType.isRole())
return;
// SH}
// This code is disabled because there is too much proposals when constructors and anonymous are proposed
if (!isIgnored(CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)
&& !currentType.isFinal()
&& (currentType.isInterface() || (currentType.isClass() && currentType.isAbstract()))){
findAnonymousType(
currentType,
null,
scope,
invocationSite,
null,
null,
null,
false,
false,
isQualified,
relevance);
}
}
private char[][] findEnclosingTypeNames(Scope scope){
char[][] excludedNames = new char[10][];
int excludedNameCount = 0;
Scope currentScope = scope;
while(currentScope != null) {
switch (currentScope.kind) {
case Scope.CLASS_SCOPE :
ClassScope classScope = (ClassScope) currentScope;
TypeDeclaration typeDeclaration = classScope.referenceContext;
if(excludedNameCount == excludedNames.length) {
System.arraycopy(excludedNames, 0, excludedNames = new char[excludedNameCount * 2][], 0, excludedNameCount);
}
excludedNames[excludedNameCount++] = typeDeclaration.name;
TypeParameter[] classTypeParameters = typeDeclaration.typeParameters;
if(classTypeParameters != null) {
for (int i = 0; i < classTypeParameters.length; i++) {
TypeParameter typeParameter = classTypeParameters[i];
if(excludedNameCount == excludedNames.length) {
System.arraycopy(excludedNames, 0, excludedNames = new char[excludedNameCount * 2][], 0, excludedNameCount);
}
excludedNames[excludedNameCount++] = typeParameter.name;
}
}
break;
case Scope.METHOD_SCOPE :
MethodScope methodScope = (MethodScope) currentScope;
if(methodScope.referenceContext instanceof AbstractMethodDeclaration) {
TypeParameter[] methodTypeParameters = ((AbstractMethodDeclaration)methodScope.referenceContext).typeParameters();
if(methodTypeParameters != null) {
for (int i = 0; i < methodTypeParameters.length; i++) {
TypeParameter typeParameter = methodTypeParameters[i];
if(excludedNameCount == excludedNames.length) {
System.arraycopy(excludedNames, 0, excludedNames = new char[excludedNameCount * 2][], 0, excludedNameCount);
}
excludedNames[excludedNameCount++] = typeParameter.name;
}
}
}
break;
}
currentScope = currentScope.parent;
}
if(excludedNameCount == 0) {
return CharOperation.NO_CHAR_CHAR;
}
System.arraycopy(excludedNames, 0, excludedNames = new char[excludedNameCount][], 0, excludedNameCount);
return excludedNames;
}
private void findEnumConstants(
char[] enumConstantName,
ReferenceBinding enumType,
Scope invocationScope,
ObjectVector fieldsFound,
char[][] alreadyUsedConstants,
int alreadyUsedConstantCount,
boolean needQualification) {
FieldBinding[] fields = enumType.fields();
int enumConstantLength = enumConstantName.length;
next : for (int f = fields.length; --f >= 0;) {
FieldBinding field = fields[f];
if (field.isSynthetic()) continue next;
if ((field.modifiers & Flags.AccEnum) == 0) continue next;
if (enumConstantLength > field.name.length) continue next;
if (isFailedMatch(enumConstantName, field.name)) continue next;
char[] fieldName = field.name;
for (int i = 0; i < alreadyUsedConstantCount; i++) {
if(CharOperation.equals(alreadyUsedConstants[i], fieldName)) continue next;
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal(field);
relevance += computeRelevanceForCaseMatching(enumConstantName, field.name);
relevance += computeRelevanceForExpectingType(field.type);
relevance += computeRelevanceForEnumConstant(field.type);
relevance += computeRelevanceForQualification(needQualification);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
this.noProposal = false;
if (!needQualification) {
char[] completion = fieldName;
if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
proposal.setBinding(field);
proposal.setDeclarationSignature(getSignature(field.declaringClass));
proposal.setSignature(getSignature(field.type));
proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
proposal.setPackageName(field.type.qualifiedPackageName());
proposal.setTypeName(field.type.qualifiedSourceName());
proposal.setName(field.name);
proposal.setCompletion(completion);
proposal.setFlags(field.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
} else {
TypeBinding visibleType = invocationScope.getType(field.type.sourceName());
boolean needImport = visibleType == null || !visibleType.isValidBinding();
char[] completion = CharOperation.concat(field.type.sourceName(), field.name, '.');
if (!needImport) {
if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
proposal.setDeclarationSignature(getSignature(field.declaringClass));
proposal.setSignature(getSignature(field.type));
proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
proposal.setPackageName(field.type.qualifiedPackageName());
proposal.setTypeName(field.type.qualifiedSourceName());
proposal.setName(field.name);
proposal.setCompletion(completion);
proposal.setFlags(field.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
} else {
if (!this.isIgnored(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_IMPORT)) {
CompilationUnitDeclaration cu = this.unitScope.referenceContext;
int importStart = cu.types[0].declarationSourceStart;
int importEnd = importStart;
ReferenceBinding fieldType = (ReferenceBinding)field.type;
InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
proposal.setBinding(field);
proposal.setDeclarationSignature(getSignature(field.declaringClass));
proposal.setSignature(getSignature(field.type));
proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
proposal.setPackageName(field.type.qualifiedPackageName());
proposal.setTypeName(field.type.qualifiedSourceName());
proposal.setName(field.name);
proposal.setCompletion(completion);
proposal.setFlags(field.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
char[] typeImportCompletion = createImportCharArray(CharOperation.concatWith(fieldType.compoundName, '.'), false, false);
InternalCompletionProposal typeImportProposal = createProposal(CompletionProposal.TYPE_IMPORT, this.actualCompletionPosition);
typeImportProposal.nameLookup = this.nameEnvironment.nameLookup;
typeImportProposal.completionEngine = this;
char[] packageName = fieldType.qualifiedPackageName();
typeImportProposal.setDeclarationSignature(packageName);
typeImportProposal.setSignature(getSignature(fieldType));
typeImportProposal.setPackageName(packageName);
typeImportProposal.setTypeName(fieldType.qualifiedSourceName());
typeImportProposal.setCompletion(typeImportCompletion);
typeImportProposal.setFlags(fieldType.modifiers);
typeImportProposal.setAdditionalFlags(CompletionFlags.Default);
typeImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset);
typeImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset);
typeImportProposal.setRelevance(relevance);
proposal.setRequiredProposals(new CompletionProposal[]{typeImportProposal});
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
}
}
}
private void findEnumConstantsFromExpectedTypes(
char[] token,
Scope invocationScope,
ObjectVector fieldsFound) {
int length = this.expectedTypesPtr + 1;
for (int i = 0; i < length; i++) {
if (this.expectedTypes[i].isEnum()) {
findEnumConstants(
token,
(ReferenceBinding)this.expectedTypes[i],
invocationScope,
fieldsFound,
CharOperation.NO_CHAR_CHAR,
0,
true);
}
}
}
private void findEnumConstantsFromSwithStatement(char[] enumConstantName, SwitchStatement switchStatement) {
TypeBinding expressionType = switchStatement.expression.resolvedType;
if(expressionType != null && expressionType.isEnum()) {
ReferenceBinding enumType = (ReferenceBinding) expressionType;
CaseStatement[] cases = switchStatement.cases;
char[][] alreadyUsedConstants = new char[switchStatement.caseCount][];
int alreadyUsedConstantCount = 0;
for (int i = 0; i < switchStatement.caseCount; i++) {
Expression caseExpression = cases[i].constantExpression;
if((caseExpression instanceof SingleNameReference)
&& (caseExpression.resolvedType != null && caseExpression.resolvedType.isEnum())) {
alreadyUsedConstants[alreadyUsedConstantCount++] = ((SingleNameReference)cases[i].constantExpression).token;
}
}
findEnumConstants(
enumConstantName,
enumType,
null /* doesn't need invocation scope */,
new ObjectVector(),
alreadyUsedConstants,
alreadyUsedConstantCount,
false);
}
}
private void findExceptionFromTryStatement(
char[] typeName,
ReferenceBinding exceptionType,
ReferenceBinding receiverType,
SourceTypeBinding invocationType,
BlockScope scope,
ObjectVector typesFound,
boolean searchSuperClasses) {
if (searchSuperClasses) {
ReferenceBinding javaLangThrowable = scope.getJavaLangThrowable();
if (TypeBinding.notEquals(exceptionType, javaLangThrowable)) {
ReferenceBinding superClass = exceptionType.superclass();
while(superClass != null && TypeBinding.notEquals(superClass, javaLangThrowable)) {
findExceptionFromTryStatement(typeName, superClass, receiverType, invocationType, scope, typesFound, false);
superClass = superClass.superclass();
}
}
}
if (typeName.length > exceptionType.sourceName.length)
return;
if (isFailedMatch(typeName, exceptionType.sourceName))
return;
if (this.options.checkDeprecation &&
exceptionType.isViewedAsDeprecated() &&
!scope.isDefinedInSameUnit(exceptionType))
return;
if (this.options.checkVisibility) {
if (invocationType != null) {
if (receiverType != null) {
if (!exceptionType.canBeSeenBy(receiverType, invocationType)) return;
} else {
if (!exceptionType.canBeSeenBy(exceptionType, invocationType)) return;
}
} else if(!exceptionType.canBeSeenBy(this.unitScope.fPackage)) {
return;
}
}
if (isForbidden(exceptionType)) return;
for (int j = typesFound.size; --j >= 0;) {
ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j);
if (TypeBinding.equalsEquals(exceptionType, otherType))
return;
if (CharOperation.equals(exceptionType.sourceName, otherType.sourceName, true)) {
if (exceptionType.enclosingType().isSuperclassOf(otherType.enclosingType()))
return;
if (otherType.enclosingType().isInterface())
if (exceptionType.enclosingType()
.implementsInterface(otherType.enclosingType(), true))
return;
if (exceptionType.enclosingType().isInterface())
if (otherType.enclosingType()
.implementsInterface(exceptionType.enclosingType(), true))
return;
}
}
typesFound.add(exceptionType);
char[] completionName = exceptionType.sourceName();
boolean isQualified = false;
if(!this.insideQualifiedReference) {
isQualified = true;
char[] memberPackageName = exceptionType.qualifiedPackageName();
char[] memberTypeName = exceptionType.sourceName();
char[] memberEnclosingTypeNames = null;
ReferenceBinding enclosingType = exceptionType.enclosingType();
if (enclosingType != null) {
memberEnclosingTypeNames = exceptionType.enclosingType().qualifiedSourceName();
}
Scope currentScope = scope;
done : while (currentScope != null) { // done when a COMPILATION_UNIT_SCOPE is found
switch (currentScope.kind) {
case Scope.METHOD_SCOPE :
case Scope.BLOCK_SCOPE :
BlockScope blockScope = (BlockScope) currentScope;
for (int j = 0, length = blockScope.subscopeCount; j < length; j++) {
if (blockScope.subscopes[j] instanceof ClassScope) {
SourceTypeBinding localType =
((ClassScope) blockScope.subscopes[j]).referenceContext.binding;
if (TypeBinding.equalsEquals(localType, exceptionType)) {
isQualified = false;
break done;
}
}
}
break;
case Scope.CLASS_SCOPE :
SourceTypeBinding type = ((ClassScope)currentScope).referenceContext.binding;
ReferenceBinding[] memberTypes = type.memberTypes();
if (memberTypes != null) {
for (int j = 0; j < memberTypes.length; j++) {
if (TypeBinding.equalsEquals(memberTypes[j], exceptionType)) {
isQualified = false;
break done;
}
}
}
break;
case Scope.COMPILATION_UNIT_SCOPE :
SourceTypeBinding[] types = ((CompilationUnitScope)currentScope).topLevelTypes;
if (types != null) {
for (int j = 0; j < types.length; j++) {
if (TypeBinding.equalsEquals(types[j], exceptionType)) {
isQualified = false;
break done;
}
}
}
break done;
}
currentScope = currentScope.parent;
}
if (isQualified && mustQualifyType(memberPackageName, memberTypeName, memberEnclosingTypeNames, exceptionType.modifiers)) {
if (memberPackageName == null || memberPackageName.length == 0)
if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
return; // ignore types from the default package from outside it
} else {
isQualified = false;
}
if (isQualified) {
completionName =
CharOperation.concat(
memberPackageName,
CharOperation.concat(
memberEnclosingTypeNames,
memberTypeName,
'.'),
'.');
}
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal(exceptionType);
relevance += computeRelevanceForCaseMatching(typeName, exceptionType.sourceName);
relevance += computeRelevanceForExpectingType(exceptionType);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
if(!this.insideQualifiedReference) {
relevance += computeRelevanceForQualification(isQualified);
}
relevance += computeRelevanceForClass();
relevance += computeRelevanceForException();
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
createTypeProposal(
exceptionType,
exceptionType.qualifiedSourceName(),
IAccessRule.K_ACCESSIBLE,
completionName,
relevance,
null,
null,
null,
false);
}
}
private void findExceptionFromTryStatement(
char[] typeName,
ReferenceBinding receiverType,
SourceTypeBinding invocationType,
BlockScope scope,
ObjectVector typesFound) {
for (int i = 0; i <= this.expectedTypesPtr; i++) {
ReferenceBinding exceptionType = (ReferenceBinding)this.expectedTypes[i];
findExceptionFromTryStatement(typeName, exceptionType, receiverType, invocationType, scope, typesFound, true);
}
}
private void findExplicitConstructors(
char[] name,
ReferenceBinding currentType,
MethodScope scope,
InvocationSite invocationSite) {
ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration)scope.referenceContext;
MethodBinding enclosingConstructor = constructorDeclaration.binding;
// No visibility checks can be performed without the scope & invocationSite
MethodBinding[] methods = currentType.availableMethods();
if(methods != null) {
next : for (int f = methods.length; --f >= 0;) {
MethodBinding constructor = methods[f];
if (constructor != enclosingConstructor && constructor.isConstructor()) {
if (constructor.isSynthetic()) continue next;
if (this.options.checkDeprecation &&
constructor.isViewedAsDeprecated() &&
!scope.isDefinedInSameUnit(constructor.declaringClass))
continue next;
if (this.options.checkVisibility
&& !constructor.canBeSeenBy(invocationSite, scope)) continue next;
TypeBinding[] parameters = constructor.parameters;
int paramLength = parameters.length;
char[][] parameterPackageNames = new char[paramLength][];
char[][] parameterTypeNames = new char[paramLength][];
for (int i = 0; i < paramLength; i++) {
TypeBinding type = parameters[i];
parameterPackageNames[i] = type.qualifiedPackageName();
parameterTypeNames[i] = type.qualifiedSourceName();
}
char[][] parameterNames = findMethodParameterNames(constructor,parameterTypeNames);
char[] completion = CharOperation.NO_CHAR;
if (this.source != null
&& this.source.length > this.endPosition
&& this.source[this.endPosition] == '(')
completion = name;
else
completion = CharOperation.concat(name, new char[] { '(', ')' });
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(this.completionToken, name);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
proposal.setBinding(constructor);
proposal.setDeclarationSignature(getSignature(currentType));
proposal.setSignature(getSignature(constructor));
MethodBinding original = constructor.original();
if(original != constructor) {
proposal.setOriginalSignature(getSignature(original));
}
proposal.setDeclarationPackageName(currentType.qualifiedPackageName());
proposal.setDeclarationTypeName(currentType.qualifiedSourceName());
proposal.setParameterPackageNames(parameterPackageNames);
proposal.setParameterTypeNames(parameterTypeNames);
//proposal.setPackageName(null);
//proposal.setTypeName(null);
proposal.setName(name);
proposal.setIsContructor(true);
proposal.setCompletion(completion);
proposal.setFlags(constructor.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
if(parameterNames != null) proposal.setParameterNames(parameterNames);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
}
}
}
// Helper method for findFields(char[], ReferenceBinding, Scope, ObjectVector, boolean)
private void findFields(
char[] fieldName,
FieldBinding[] fields,
Scope scope,
ObjectVector fieldsFound,
ObjectVector localsFound,
boolean onlyStaticFields,
//{ObjectTeams: field or callout-to-field?
int kind,
TypeBinding expectedType, // use as strict filter if non-null
// SH}
ReferenceBinding receiverType,
InvocationSite invocationSite,
Scope invocationScope,
boolean implicitCall,
boolean canBePrefixed,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems,
char[] castedReceiver,
int receiverStart,
int receiverEnd) {
ObjectVector newFieldsFound = new ObjectVector();
// if the proposal is being asked inside a field's initialization, we'll record its id
int fieldBeingCompletedId = -1;
boolean isFieldBeingCompletedStatic = false;
for (int f = fields.length; --f >=0;) {
FieldBinding field = fields[f];
FieldDeclaration fieldDeclaration = field.sourceField();
// We maybe asking for a proposal inside this field's initialization. So record its id
ASTNode astNode = this.parser.assistNode;
if (fieldDeclaration != null && fieldDeclaration.initialization != null && astNode != null) {
if (CharOperation.equals(this.fileName, field.declaringClass.getFileName()) && fieldDeclaration.initialization.sourceEnd > 0) {
if (fieldDeclaration.initialization.sourceStart <= astNode.sourceStart &&
astNode.sourceEnd <= fieldDeclaration.initialization.sourceEnd) {
// completion is inside a field initializer
fieldBeingCompletedId = field.id;
isFieldBeingCompletedStatic = field.isStatic();
break;
}
} else { // The sourceEnd may not yet be set
CompletionNodeDetector detector = new CompletionNodeDetector(astNode, fieldDeclaration.initialization);
if (detector.containsCompletionNode()) { // completion is inside a field initializer
fieldBeingCompletedId = field.id;
isFieldBeingCompletedStatic = field.isStatic();
break;
}
}
}
}
// Inherited fields which are hidden by subclasses are filtered out
// No visibility checks can be performed without the scope & invocationSite
//{ObjectTeams:
if (isBaseAccess(invocationSite) || isTSuperAccess(invocationSite))
return; // no "base.field", "tsuper.field" ever;
// decode additional flag:
boolean isSearchingSuperBase = (kind >= SEARCH_SUPER_BASE);
kind &= ~SEARCH_SUPER_BASE;
//SH}
int fieldLength = fieldName.length;
next : for (int f = fields.length; --f >= 0;) {
FieldBinding field = fields[f];
// Content assist invoked inside some field's initialization.
// bug 310427 and 325481
if (fieldBeingCompletedId >= 0 && field.id >= fieldBeingCompletedId) {
// Don't propose field which is being declared currently
// Don't propose fields declared after the current field declaration statement
// Though, if field is static or completion happens in Javadoc, then it can be still be proposed
if (this.assistNodeInJavadoc == 0) {
if (!field.isStatic()) {
continue next;
} else if (isFieldBeingCompletedStatic) {
// static fields can't be proposed before they are actually declared if the
// field currently being declared is also static
continue next;
}
}
}
//{ObjectTeams: filter out generated fields
if (!canBeCompleted(field.name)) continue next;
//carp}
if (field.isSynthetic()) continue next;
if (onlyStaticFields && !field.isStatic()) continue next;
if (fieldLength > field.name.length) continue next;
if (isFailedMatch(fieldName, field.name)) continue next;
if (this.options.checkDeprecation &&
field.isViewedAsDeprecated() &&
!scope.isDefinedInSameUnit(field.declaringClass))
continue next;
//{ObjectTeams: ignore visibility for callout-to-field, except when searching superbase:
if (isSearchingSuperBase && field.isPrivate()) continue next;
if (kind == CompletionProposal.FIELD_REF)
// SH}
if (this.options.checkVisibility
&& !field.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
// don't propose non constant fields or strings (1.6 or below) in case expression
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=195346
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=343342
if (this.assistNodeIsInsideCase) {
if (field.isFinal()) {
if (this.assistNodeIsString){
if (field.type == null || field.type.id != TypeIds.T_JavaLangString)
continue next;
} else if (!(field.type instanceof BaseTypeBinding))
continue next;
} else {
continue next; // non-constants not allowed in case.
}
}
//{ObjectTeams: additional check if method spec type already known:
if (expectedType != null && TypeBinding.notEquals(expectedType, field.type)) continue next;
// SH}
boolean prefixRequired = false;
for (int i = fieldsFound.size; --i >= 0;) {
Object[] other = (Object[])fieldsFound.elementAt(i);
FieldBinding otherField = (FieldBinding) other[0];
ReferenceBinding otherReceiverType = (ReferenceBinding) other[1];
if (field == otherField && TypeBinding.equalsEquals(receiverType, otherReceiverType))
continue next;
if (CharOperation.equals(field.name, otherField.name, true)) {
if (field.declaringClass.isSuperclassOf(otherField.declaringClass))
continue next;
if (otherField.declaringClass.isInterface()) {
if (TypeBinding.equalsEquals(field.declaringClass, scope.getJavaLangObject()))
continue next;
if (field.declaringClass.implementsInterface(otherField.declaringClass, true))
continue next;
}
if (field.declaringClass.isInterface())
if (otherField.declaringClass.implementsInterface(field.declaringClass, true))
continue next;
if(canBePrefixed) {
prefixRequired = true;
} else {
continue next;
}
}
}
for (int l = localsFound.size; --l >= 0;) {
LocalVariableBinding local = (LocalVariableBinding) localsFound.elementAt(l);
if (CharOperation.equals(field.name, local.name, true)) {
SourceTypeBinding declarationType = scope.enclosingSourceType();
if (declarationType.isAnonymousType() && TypeBinding.notEquals(declarationType, invocationScope.enclosingSourceType())) {
continue next;
}
if(canBePrefixed) {
prefixRequired = true;
} else {
continue next;
}
break;
}
}
newFieldsFound.add(new Object[]{field, receiverType});
char[] completion = field.name;
if(prefixRequired || this.options.forceImplicitQualification){
char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), field.isStatic());
completion = CharOperation.concat(prefix,completion,'.');
}
//{ObjectTeams: callout-to-field:
boolean isOverride = false;
TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
switch (kind) {
case CompletionProposal.OT_CALLOUT_SET:
argumentTypes = new TypeBinding[] { field.type };
//$FALL-THROUGH$
case CompletionProposal.OT_CALLOUT_GET:
char[] methodName = getCalloutToFieldName(kind, field.name);
MethodBinding method = TypeAnalyzer.findMethod(scope, scope.enclosingReceiverType(), methodName, argumentTypes);
if (method != null && method.isValidBinding())
isOverride = true;
completion = createCalloutToField(kind, isOverride, field, scope);
break;
case CompletionProposal.OT_FIELD_SPEC:
// FieldType fieldName;
completion = prependType(field.type, scope, completion);
if (this.seperator != 0)
completion= CharOperation.concat(this.seperator, completion, ';');
else
completion = CharOperation.append(completion, ';');
}
// SH}
if (castedReceiver != null) {
completion = CharOperation.concat(castedReceiver, completion);
}
// Special case for javadoc completion
if (this.assistNodeInJavadoc > 0) {
if (invocationSite instanceof CompletionOnJavadocFieldReference) {
CompletionOnJavadocFieldReference fieldRef = (CompletionOnJavadocFieldReference) invocationSite;
if (fieldRef.receiver.isThis()) {
if (fieldRef.completeInText()) {
completion = CharOperation.concat(new char[] { '#' }, field.name);
}
} else if (fieldRef.completeInText()) {
if (fieldRef.receiver instanceof JavadocSingleTypeReference) {
JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) fieldRef.receiver;
completion = CharOperation.concat(typeRef.token, field.name, '#');
} else if (fieldRef.receiver instanceof JavadocQualifiedTypeReference) {
JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) fieldRef.receiver;
completion = CharOperation.concat(CharOperation.concatWith(typeRef.tokens, '.'), field.name, '#');
}
}
}
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal(field);
relevance += computeRelevanceForCaseMatching(fieldName, field.name);
relevance += computeRelevanceForExpectingType(field.type);
relevance += computeRelevanceForEnumConstant(field.type);
relevance += computeRelevanceForStatic(onlyStaticFields, field.isStatic());
relevance += computeRelevanceForFinal(this.assistNodeIsInsideCase, field.isFinal());
relevance += computeRelevanceForQualification(prefixRequired);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
if (onlyStaticFields && this.insideQualifiedReference) {
relevance += computeRelevanceForInheritance(receiverType, field.declaringClass);
}
if (missingElements != null) {
relevance += computeRelevanceForMissingElements(missingElementsHaveProblems);
}
this.noProposal = false;
if (castedReceiver == null) {
// Standard proposal
//{ObjectTeams: respect 'kind'
/* orig:
if (!this.isIgnored(CompletionProposal.FIELD_REF, missingElements != null) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
:giro */
if (!this.isIgnored(kind, missingElements != null) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) {
InternalCompletionProposal proposal = createProposal(kind, this.actualCompletionPosition);
// SH}
proposal.setBinding(field);
proposal.setDeclarationSignature(getSignature(field.declaringClass));
proposal.setSignature(getSignature(field.type));
proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
proposal.setPackageName(field.type.qualifiedPackageName());
proposal.setTypeName(field.type.qualifiedSourceName());
proposal.setName(field.name);
//{ObjectTeams: role signature for callout-to-field:
if ( kind == CompletionProposal.OT_CALLOUT_GET
|| kind == CompletionProposal.OT_CALLOUT_SET)
{
proposal.setSignature(getCalloutToFieldSignature(kind, field.type));
proposal.setName(getCalloutToFieldName(kind, field.name));
}
// SH}
if (missingElements != null) {
CompletionProposal[] subProposals = new CompletionProposal[missingElements.length];
for (int i = 0; i < missingElements.length; i++) {
subProposals[i] =
createRequiredTypeProposal(
missingElements[i],
missingElementsStarts[i],
missingElementsEnds[i],
relevance);
}
proposal.setRequiredProposals(subProposals);
}
proposal.setCompletion(completion);
proposal.setFlags(field.modifiers);
//{ObjectTeams: mark callout-to-field in flags as needed by the CompletionAdaptor:
if ( kind == CompletionProposal.OT_CALLOUT_GET
|| kind == CompletionProposal.OT_CALLOUT_SET)
proposal.setAdditionalFlags(isOverride ? TerminalTokens.TokenNameCALLOUT_OVERRIDE : TerminalTokens.TokenNameBINDOUT); // pass down for label computation: callout
// SH}
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
// Javadoc completions
if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_FIELD_REF)) {
char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK);
InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_FIELD_REF, this.actualCompletionPosition);
proposal.setBinding(field);
proposal.setDeclarationSignature(getSignature(field.declaringClass));
proposal.setSignature(getSignature(field.type));
proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
proposal.setPackageName(field.type.qualifiedPackageName());
proposal.setTypeName(field.type.qualifiedSourceName());
proposal.setName(field.name);
proposal.setCompletion(javadocCompletion);
proposal.setFlags(field.modifiers);
int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition;
proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance+R_INLINE_TAG);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
// Javadoc value completion for static fields
if (field.isStatic() && !this.requestor.isIgnored(CompletionProposal.JAVADOC_VALUE_REF)) {
javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_VALUE);
InternalCompletionProposal valueProposal = createProposal(CompletionProposal.JAVADOC_VALUE_REF, this.actualCompletionPosition);
valueProposal.setDeclarationSignature(getSignature(field.declaringClass));
valueProposal.setSignature(getSignature(field.type));
valueProposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
valueProposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
valueProposal.setPackageName(field.type.qualifiedPackageName());
valueProposal.setTypeName(field.type.qualifiedSourceName());
valueProposal.setName(field.name);
valueProposal.setCompletion(javadocCompletion);
valueProposal.setFlags(field.modifiers);
valueProposal.setReplaceRange(start - this.offset, this.endPosition - this.offset);
valueProposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
valueProposal.setRelevance(relevance+R_VALUE_TAG);
this.requestor.accept(valueProposal);
if(DEBUG) {
this.printDebug(valueProposal);
}
}
}
} else {
if(!this.isIgnored(CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER, missingElements != null)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER, this.actualCompletionPosition);
proposal.setBinding(field);
proposal.setDeclarationSignature(getSignature(field.declaringClass));
proposal.setSignature(getSignature(field.type));
proposal.setReceiverSignature(getSignature(receiverType));
proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
proposal.setPackageName(field.type.qualifiedPackageName());
proposal.setTypeName(field.type.qualifiedSourceName());
proposal.setName(field.name);
if (missingElements != null) {
CompletionProposal[] subProposals = new CompletionProposal[missingElements.length];
for (int i = 0; i < missingElements.length; i++) {
subProposals[i] =
createRequiredTypeProposal(
missingElements[i],
missingElementsStarts[i],
missingElementsEnds[i],
relevance);
}
proposal.setRequiredProposals(subProposals);
}
proposal.setCompletion(completion);
proposal.setFlags(field.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setReceiverRange(receiverStart - this.offset, receiverEnd - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
}
fieldsFound.addAll(newFieldsFound);
}
private void findFields(
char[] fieldName,
ReferenceBinding receiverType,
Scope scope,
ObjectVector fieldsFound,
ObjectVector localsFound,
boolean onlyStaticFields,
InvocationSite invocationSite,
Scope invocationScope,
boolean implicitCall,
boolean canBePrefixed,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems,
char[] castedReceiver,
int receiverStart,
int receiverEnd) {
//{ObjectTeams: delegate to method with extended signature:
this.findFields(fieldName, receiverType, scope, fieldsFound, localsFound, onlyStaticFields,
CompletionProposal.FIELD_REF, null,
invocationSite, invocationScope, implicitCall, canBePrefixed,
missingElements, missingElementsStarts, missingElementsEnds, missingElementsHaveProblems,
castedReceiver, receiverStart, receiverEnd);
}
private void findFields(
char[] fieldName,
ReferenceBinding receiverType,
Scope scope,
ObjectVector fieldsFound,
ObjectVector localsFound,
boolean onlyStaticFields,
//OT: regular ref or via callout-to-field?
int kind,
TypeBinding expectedType, // use as a strict filter if non-null
//:TO
InvocationSite invocationSite,
Scope invocationScope,
boolean implicitCall,
boolean canBePrefixed,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems,
char[] castedReceiver,
int receiverStart,
int receiverEnd) {
//SH}
boolean notInJavadoc = this.assistNodeInJavadoc == 0;
if (fieldName == null && notInJavadoc)
return;
ReferenceBinding currentType = receiverType;
ReferenceBinding[] interfacesToVisit = null;
int nextPosition = 0;
do {
ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
if (notInJavadoc && itsInterfaces != Binding.NO_SUPERINTERFACES) {
if (interfacesToVisit == null) {
interfacesToVisit = itsInterfaces;
nextPosition = interfacesToVisit.length;
} else {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (TypeBinding.equalsEquals(next, interfacesToVisit[b])) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
FieldBinding[] fields = currentType.availableFields();
if(fields != null && fields.length > 0) {
findFields(
fieldName,
fields,
scope,
fieldsFound,
localsFound,
onlyStaticFields,
//{ObjectTeams: additional args (pass-through)
kind,
expectedType,
// SH}
receiverType,
invocationSite,
invocationScope,
implicitCall,
canBePrefixed,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
castedReceiver,
receiverStart,
receiverEnd);
}
currentType = currentType.superclass();
} while (notInJavadoc && currentType != null);
//{ObjectTeams: accessing base field via inferred c-t-f?
boolean inferredCalloutAllowed = implicitCall;
if (!implicitCall && invocationSite instanceof CompletionOnMemberAccess)
inferredCalloutAllowed = ((CompletionOnMemberAccess)invocationSite).receiver.isThis();
ReferenceBinding baseclass = receiverType.baseclass();
if (notInJavadoc && inferredCalloutAllowed && baseclass != null) {
FieldBinding[] fields = baseclass.availableFields();
if(fields != null && fields.length > 0) {
boolean checkVis = this.options.checkVisibility;
try {
this.options.checkVisibility = false;
findFields(
fieldName,
fields,
scope,
fieldsFound,
localsFound,
onlyStaticFields,
//OT: additional args (pass-through)
kind,
expectedType,
//:TO
receiverType,
invocationSite,
invocationScope,
implicitCall,
canBePrefixed,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
castedReceiver,
receiverStart,
receiverEnd);
} finally {
this.options.checkVisibility = checkVis;
}
}
}
// SH}
if (notInJavadoc && interfacesToVisit != null) {
for (int i = 0; i < nextPosition; i++) {
ReferenceBinding anInterface = interfacesToVisit[i];
FieldBinding[] fields = anInterface.availableFields();
if(fields != null) {
findFields(
fieldName,
fields,
scope,
fieldsFound,
localsFound,
onlyStaticFields,
//{ObjectTeams: additional arg (pass-through)
kind,
expectedType,
// SH}
receiverType,
invocationSite,
invocationScope,
implicitCall,
canBePrefixed,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
castedReceiver,
receiverStart,
receiverEnd);
}
ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
if (itsInterfaces != Binding.NO_SUPERINTERFACES) {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (TypeBinding.equalsEquals(next, interfacesToVisit[b])) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
}
}
protected void findFieldsAndMethods(
char[] token,
TypeBinding receiverType,
Scope scope,
ObjectVector fieldsFound,
ObjectVector methodsFound,
InvocationSite invocationSite,
Scope invocationScope,
boolean implicitCall,
boolean superCall,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems,
char[] castedReceiver,
int receiverStart,
int receiverEnd) {
if (token == null)
return;
if (receiverType.isBaseType())
return; // nothing else is possible with base types
boolean proposeField =
castedReceiver == null ?
!this.isIgnored(CompletionProposal.FIELD_REF, missingElements != null) :
!this.isIgnored(CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER, missingElements != null) ;
boolean proposeMethod =
castedReceiver == null ?
!this.isIgnored(CompletionProposal.METHOD_REF, missingElements != null) :
!this.isIgnored(CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER, missingElements != null);
if (receiverType.isArrayType()) {
if (proposeField
&& token.length <= lengthField.length
&& CharOperation.prefixEquals(token, lengthField, false /* ignore case */
)) {
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(token,lengthField);
relevance += computeRelevanceForExpectingType(TypeBinding.INT);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for length field
if (missingElements != null) {
relevance += computeRelevanceForMissingElements(missingElementsHaveProblems);
}
this.noProposal = false;
if (castedReceiver == null) {
if(!isIgnored(CompletionProposal.FIELD_REF, missingElements != null)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
proposal.setDeclarationSignature(getSignature(receiverType));
proposal.setSignature(INT_SIGNATURE);
proposal.setTypeName(INT);
proposal.setName(lengthField);
if (missingElements != null) {
CompletionProposal[] subProposals = new CompletionProposal[missingElements.length];
for (int i = 0; i < missingElements.length; i++) {
subProposals[i] =
createRequiredTypeProposal(
missingElements[i],
missingElementsStarts[i],
missingElementsEnds[i],
relevance);
}
proposal.setRequiredProposals(subProposals);
}
proposal.setCompletion(lengthField);
proposal.setFlags(Flags.AccPublic);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
} else {
char[] completion = CharOperation.concat(castedReceiver, lengthField);
if(!this.isIgnored(CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER, missingElements != null)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER, this.actualCompletionPosition);
proposal.setDeclarationSignature(getSignature(receiverType));
proposal.setSignature(INT_SIGNATURE);
proposal.setReceiverSignature(getSignature(receiverType));
proposal.setTypeName(INT);
proposal.setName(lengthField);
if (missingElements != null) {
CompletionProposal[] subProposals = new CompletionProposal[missingElements.length];
for (int i = 0; i < missingElements.length; i++) {
subProposals[i] =
createRequiredTypeProposal(
missingElements[i],
missingElementsStarts[i],
missingElementsEnds[i],
relevance);
}
proposal.setRequiredProposals(subProposals);
}
proposal.setCompletion(completion);
proposal.setFlags(Flags.AccPublic);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setReceiverRange(receiverStart - this.offset, receiverEnd - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
}
if (proposeMethod
&& token.length <= cloneMethod.length
&& CharOperation.prefixEquals(token, cloneMethod, false /* ignore case */)
) {
ReferenceBinding objectRef = scope.getJavaLangObject();
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(token, cloneMethod);
relevance += computeRelevanceForExpectingType(objectRef);
relevance += computeRelevanceForStatic(false, false);
relevance += computeRelevanceForQualification(false);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for clone() method
if (missingElements != null) {
relevance += computeRelevanceForMissingElements(missingElementsHaveProblems);
}
char[] completion;
if (this.source != null
&& this.source.length > this.endPosition
&& this.source[this.endPosition] == '(') {
completion = cloneMethod;
} else {
completion = CharOperation.concat(cloneMethod, new char[] { '(', ')' });
}
if (castedReceiver != null) {
completion = CharOperation.concat(castedReceiver, completion);
}
this.noProposal = false;
if (castedReceiver == null) {
if (!this.isIgnored(CompletionProposal.METHOD_REF, missingElements != null)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
proposal.setDeclarationSignature(getSignature(receiverType));
proposal.setSignature(
this.compilerOptions.sourceLevel > ClassFileConstants.JDK1_4 && receiverType.isArrayType() ?
createMethodSignature(
CharOperation.NO_CHAR_CHAR,
CharOperation.NO_CHAR_CHAR,
getSignature(receiverType)) :
createMethodSignature(
CharOperation.NO_CHAR_CHAR,
CharOperation.NO_CHAR_CHAR,
CharOperation.concatWith(JAVA_LANG, '.'),
OBJECT));
//proposal.setOriginalSignature(null);
//proposal.setDeclarationPackageName(null);
//proposal.setDeclarationTypeName(null);
//proposal.setParameterPackageNames(null);
//proposal.setParameterTypeNames(null);
proposal.setPackageName(CharOperation.concatWith(JAVA_LANG, '.'));
proposal.setTypeName(OBJECT);
proposal.setName(cloneMethod);
if (missingElements != null) {
CompletionProposal[] subProposals = new CompletionProposal[missingElements.length];
for (int i = 0; i < missingElements.length; i++) {
subProposals[i] =
createRequiredTypeProposal(
missingElements[i],
missingElementsStarts[i],
missingElementsEnds[i],
relevance);
}
proposal.setRequiredProposals(subProposals);
}
proposal.setCompletion(completion);
proposal.setFlags(Flags.AccPublic);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
methodsFound.add(new Object[]{objectRef.getMethods(cloneMethod)[0], objectRef});
} else {
if(!this.isIgnored(CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER, missingElements != null)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER, this.actualCompletionPosition);
proposal.setDeclarationSignature(getSignature(receiverType));
proposal.setSignature(
this.compilerOptions.sourceLevel > ClassFileConstants.JDK1_4 && receiverType.isArrayType() ?
createMethodSignature(
CharOperation.NO_CHAR_CHAR,
CharOperation.NO_CHAR_CHAR,
getSignature(receiverType)) :
createMethodSignature(
CharOperation.NO_CHAR_CHAR,
CharOperation.NO_CHAR_CHAR,
CharOperation.concatWith(JAVA_LANG, '.'),
OBJECT));
proposal.setReceiverSignature(getSignature(receiverType));
proposal.setPackageName(CharOperation.concatWith(JAVA_LANG, '.'));
proposal.setTypeName(OBJECT);
proposal.setName(cloneMethod);
if (missingElements != null) {
CompletionProposal[] subProposals = new CompletionProposal[missingElements.length];
for (int i = 0; i < missingElements.length; i++) {
subProposals[i] =
createRequiredTypeProposal(
missingElements[i],
missingElementsStarts[i],
missingElementsEnds[i],
relevance);
}
proposal.setRequiredProposals(subProposals);
}
proposal.setCompletion(completion);
proposal.setFlags(Flags.AccPublic);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setReceiverRange(receiverStart - this.offset, receiverEnd - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
}
//{ObjectTeams: no object super type for array of confined:
if (TypeAnalyzer.isConfined(receiverType.leafComponentType()))
return;
// SH}
receiverType = scope.getJavaLangObject();
}
checkCancel();
if(proposeField) {
findFields(
token,
(ReferenceBinding) receiverType,
scope,
fieldsFound,
new ObjectVector(),
false,
invocationSite,
invocationScope,
implicitCall,
false,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
castedReceiver,
receiverStart,
receiverEnd);
}
if(proposeMethod) {
findMethods(
token,
null,
null,
(ReferenceBinding) receiverType,
scope,
methodsFound,
false,
false,
invocationSite,
invocationScope,
implicitCall,
superCall,
false,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
castedReceiver,
receiverStart,
receiverEnd);
}
}
protected void findFieldsAndMethodsFromAnotherReceiver(
char[] token,
TypeReference receiverType,
Scope scope,
ObjectVector fieldsFound,
ObjectVector methodsFound,
InvocationSite invocationSite,
Scope invocationScope,
boolean implicitCall,
boolean superCall,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems,
char[][] receiverName,
int receiverStart,
int receiverEnd) {
if (receiverType.resolvedType == null) return;
TypeBinding receiverTypeBinding = receiverType.resolvedType;
char[] castedReceiver = null;
char[] castedTypeChars = CharOperation.concatWith(receiverType.getTypeName(), '.');
if(this.source != null) {
int memberRefStart = this.startPosition;
char[] receiverChars = CharOperation.subarray(this.source, receiverStart, receiverEnd);
char[] dotChars = CharOperation.subarray(this.source, receiverEnd, memberRefStart);
castedReceiver =
CharOperation.concat(
CharOperation.concat(
'(',
CharOperation.concat(
CharOperation.concat('(', castedTypeChars, ')'),
receiverChars),
')'),
dotChars);
} else {
castedReceiver =
CharOperation.concat(
CharOperation.concat(
'(',
CharOperation.concat(
CharOperation.concat('(', castedTypeChars, ')'),
CharOperation.concatWith(receiverName, '.')),
')'),
DOT);
}
if (castedReceiver == null) return;
int oldStartPosition = this.startPosition;
this.startPosition = receiverStart;
findFieldsAndMethods(
token,
receiverTypeBinding,
scope,
fieldsFound,
methodsFound,
invocationSite,
invocationScope,
implicitCall,
superCall,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
castedReceiver,
receiverStart,
receiverEnd);
this.startPosition = oldStartPosition;
}
private void findFieldsAndMethodsFromCastedReceiver(
ASTNode enclosingNode,
Binding qualifiedBinding,
Scope scope,
ObjectVector fieldsFound,
ObjectVector methodsFound,
InvocationSite invocationSite,
Scope invocationScope,
Expression receiver) {
if (enclosingNode == null || !(enclosingNode instanceof IfStatement)) return;
IfStatement ifStatement = (IfStatement)enclosingNode;
while (true) {
if (!(ifStatement.condition instanceof InstanceOfExpression)) return;
InstanceOfExpression instanceOfExpression = (InstanceOfExpression) ifStatement.condition;
TypeReference instanceOfType = instanceOfExpression.type;
if (instanceOfType.resolvedType == null) return;
boolean findFromAnotherReceiver = false;
char[][] receiverName = null;
int receiverStart = -1;
int receiverEnd = -1;
if (receiver instanceof QualifiedNameReference) {
QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) receiver;
receiverName = qualifiedNameReference.tokens;
if (receiverName.length != 1) return;
receiverStart = (int) (qualifiedNameReference.sourcePositions[0] >>> 32);
receiverEnd = (int) qualifiedNameReference.sourcePositions[qualifiedNameReference.tokens.length - 1] + 1;
// if (local instanceof X) local.|
// if (field instanceof X) field.|
if (instanceOfExpression.expression instanceof SingleNameReference &&
((SingleNameReference)instanceOfExpression.expression).binding == qualifiedBinding &&
(qualifiedBinding instanceof LocalVariableBinding || qualifiedBinding instanceof FieldBinding)) {
findFromAnotherReceiver = true;
}
// if (this.field instanceof X) field.|
if (instanceOfExpression.expression instanceof FieldReference) {
FieldReference fieldReference = (FieldReference)instanceOfExpression.expression;
if (fieldReference.receiver instanceof ThisReference &&
qualifiedBinding instanceof FieldBinding &&
fieldReference.binding == qualifiedBinding) {
findFromAnotherReceiver = true;
}
}
} else if (receiver instanceof FieldReference) {
FieldReference fieldReference1 = (FieldReference) receiver;
receiverStart = fieldReference1.sourceStart;
receiverEnd = fieldReference1.sourceEnd + 1;
if (fieldReference1.receiver instanceof ThisReference) {
receiverName = new char[][] {THIS, fieldReference1.token};
// if (field instanceof X) this.field.|
if (instanceOfExpression.expression instanceof SingleNameReference &&
((SingleNameReference)instanceOfExpression.expression).binding == fieldReference1.binding) {
findFromAnotherReceiver = true;
}
// if (this.field instanceof X) this.field.|
if (instanceOfExpression.expression instanceof FieldReference) {
FieldReference fieldReference2 = (FieldReference)instanceOfExpression.expression;
if (fieldReference2.receiver instanceof ThisReference &&
fieldReference2.binding == fieldReference1.binding) {
findFromAnotherReceiver = true;
}
}
}
}
if (findFromAnotherReceiver) {
TypeBinding receiverTypeBinding = instanceOfType.resolvedType;
char[] castedReceiver = null;
char[] castedTypeChars = CharOperation.concatWith(instanceOfType.getTypeName(), '.');
if(this.source != null) {
int memberRefStart = this.startPosition;
char[] receiverChars = CharOperation.subarray(this.source, receiverStart, receiverEnd);
char[] dotChars = CharOperation.subarray(this.source, receiverEnd, memberRefStart);
castedReceiver =
CharOperation.concat(
CharOperation.concat(
'(',
CharOperation.concat(
CharOperation.concat('(', castedTypeChars, ')'),
receiverChars),
')'),
dotChars);
} else {
castedReceiver =
CharOperation.concat(
CharOperation.concat(
'(',
CharOperation.concat(
CharOperation.concat('(', castedTypeChars, ')'),
CharOperation.concatWith(receiverName, '.')),
')'),
DOT);
}
if (castedReceiver == null) return;
int oldStartPosition = this.startPosition;
this.startPosition = receiverStart;
findFieldsAndMethods(
this.completionToken,
receiverTypeBinding,
scope,
fieldsFound,
methodsFound,
invocationSite,
invocationScope,
false,
false,
null,
null,
null,
false,
castedReceiver,
receiverStart,
receiverEnd);
this.startPosition = oldStartPosition;
}
// traverse the enclosing node to find the instanceof expression corresponding
// to the completion node (if any)
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=304006
if (ifStatement.thenStatement instanceof IfStatement) {
ifStatement = (IfStatement) ifStatement.thenStatement;
} else {
break;
}
}
}
private void findFieldsAndMethodsFromFavorites(
char[] token,
Scope scope,
InvocationSite invocationSite,
Scope invocationScope,
ObjectVector localsFound,
ObjectVector fieldsFound,
ObjectVector methodsFound) {
ObjectVector methodsFoundFromFavorites = new ObjectVector();
ImportBinding[] favoriteBindings = getFavoriteReferenceBindings(invocationScope);
if (favoriteBindings != null && favoriteBindings.length > 0) {
for (int i = 0; i < favoriteBindings.length; i++) {
ImportBinding favoriteBinding = favoriteBindings[i];
switch (favoriteBinding.resolvedImport.kind()) {
case Binding.FIELD:
FieldBinding fieldBinding = (FieldBinding) favoriteBinding.resolvedImport;
findFieldsFromFavorites(
token,
new FieldBinding[]{fieldBinding},
scope,
fieldsFound,
localsFound,
fieldBinding.declaringClass,
invocationSite,
invocationScope);
break;
case Binding.METHOD:
MethodBinding methodBinding = (MethodBinding) favoriteBinding.resolvedImport;
MethodBinding[] methods = methodBinding.declaringClass.availableMethods();
long range;
if ((range = ReferenceBinding.binarySearch(methodBinding.selector, methods)) >= 0) {
int start = (int) range, end = (int) (range >> 32);
int length = end - start + 1;
System.arraycopy(methods, start, methods = new MethodBinding[length], 0, length);
} else {
methods = Binding.NO_METHODS;
}
findLocalMethodsFromFavorites(
token,
methods,
scope,
methodsFound,
methodsFoundFromFavorites,
methodBinding.declaringClass,
invocationSite,
invocationScope);
break;
case Binding.TYPE:
ReferenceBinding referenceBinding = (ReferenceBinding) favoriteBinding.resolvedImport;
if(favoriteBinding.onDemand) {
findFieldsFromFavorites(
token,
referenceBinding.availableFields(),
scope,
fieldsFound,
localsFound,
referenceBinding,
invocationSite,
invocationScope);
findLocalMethodsFromFavorites(
token,
referenceBinding.availableMethods(),
scope,
methodsFound,
methodsFoundFromFavorites,
referenceBinding,
invocationSite,
invocationScope);
}
break;
}
}
}
methodsFound.addAll(methodsFoundFromFavorites);
}
private boolean findFieldsAndMethodsFromMissingFieldType(
char[] token,
Scope scope,
InvocationSite invocationSite,
boolean insideTypeAnnotation) {
boolean foundSomeFields = false;
Scope currentScope = scope;
done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
switch (currentScope.kind) {
case Scope.CLASS_SCOPE :
ClassScope classScope = (ClassScope) currentScope;
if(!insideTypeAnnotation) {
FieldDeclaration[] fields = classScope.referenceContext.fields;
int fieldsCount = fields == null ? 0 : fields.length;
for (int i = 0; i < fieldsCount; i++) {
FieldDeclaration fieldDeclaration = fields[i];
if (CharOperation.equals(fieldDeclaration.name, token)) {
FieldBinding fieldBinding = fieldDeclaration.binding;
if (fieldBinding == null || fieldBinding.type == null || (fieldBinding.type.tagBits & TagBits.HasMissingType) != 0) {
foundSomeFields = true;
findFieldsAndMethodsFromMissingType(
fieldDeclaration.type,
currentScope,
invocationSite,
scope);
}
break done;
}
}
}
insideTypeAnnotation = false;
break;
case Scope.COMPILATION_UNIT_SCOPE :
break done;
}
currentScope = currentScope.parent;
}
return foundSomeFields;
}
private void findFieldsAndMethodsFromMissingReturnType(
char[] token,
TypeBinding[] arguments,
Scope scope,
InvocationSite invocationSite,
boolean insideTypeAnnotation) {
Scope currentScope = scope;
done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
switch (currentScope.kind) {
case Scope.CLASS_SCOPE :
ClassScope classScope = (ClassScope) currentScope;
if(!insideTypeAnnotation) {
AbstractMethodDeclaration[] methods = classScope.referenceContext.methods;
int methodsCount = methods == null ? 0 : methods.length;
for (int i = 0; i < methodsCount; i++) {
AbstractMethodDeclaration methodDeclaration = methods[i];
if (methodDeclaration instanceof MethodDeclaration &&
CharOperation.equals(methodDeclaration.selector, token)) {
MethodDeclaration method = (MethodDeclaration) methodDeclaration;
MethodBinding methodBinding = method.binding;
if (methodBinding == null || methodBinding.returnType == null || (methodBinding.returnType.tagBits & TagBits.HasMissingType) != 0) {
Argument[] parameters = method.arguments;
int parametersLength = parameters == null ? 0 : parameters.length;
int argumentsLength = arguments == null ? 0 : arguments.length;
if (parametersLength == 0) {
if (argumentsLength == 0) {
findFieldsAndMethodsFromMissingType(
method.returnType,
currentScope,
invocationSite,
scope);
break done;
}
} else {
TypeBinding[] parametersBindings;
if (methodBinding == null) { // since no binding, extra types from type references
parametersBindings = new TypeBinding[parametersLength];
for (int j = 0; j < parametersLength; j++) {
TypeBinding parameterType = parameters[j].type.resolvedType;
if (!parameterType.isValidBinding() && parameterType.closestMatch() != null) {
parameterType = parameterType.closestMatch();
}
parametersBindings[j] = parameterType;
}
} else {
parametersBindings = methodBinding.parameters;
}
if(areParametersCompatibleWith(parametersBindings, arguments, parameters[parametersLength - 1].isVarArgs())) {
findFieldsAndMethodsFromMissingType(
method.returnType,
currentScope,
invocationSite,
scope);
break done;
}
}
}
}
}
}
insideTypeAnnotation = false;
break;
case Scope.COMPILATION_UNIT_SCOPE :
break done;
}
currentScope = currentScope.parent;
}
}
private void findFieldsAndMethodsFromMissingType(
TypeReference typeRef,
final Scope scope,
final InvocationSite invocationSite,
final Scope invocationScope) {
MissingTypesGuesser missingTypesConverter = new MissingTypesGuesser(this);
MissingTypesGuesser.GuessedTypeRequestor substitutionRequestor =
new MissingTypesGuesser.GuessedTypeRequestor() {
@Override
public void accept(
TypeBinding guessedType,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean hasProblems) {
findFieldsAndMethods(
CompletionEngine.this.completionToken,
guessedType,
scope,
new ObjectVector(),
new ObjectVector(),
invocationSite,
invocationScope,
false,
false,
missingElements,
missingElementsStarts,
missingElementsEnds,
hasProblems,
null,
-1,
-1);
}
};
missingTypesConverter.guess(typeRef, scope, substitutionRequestor);
}
private void findFieldsAndMethodsFromStaticImports(
char[] token,
Scope scope,
InvocationSite invocationSite,
Scope invocationScope,
boolean exactMatch,
boolean insideAnnotationAttribute,
ObjectVector localsFound,
ObjectVector fieldsFound,
ObjectVector methodsFound,
boolean proposeField,
boolean proposeMethod) {
// search in static import
ImportBinding[] importBindings = scope.compilationUnitScope().imports;
for (int i = 0; i < importBindings.length; i++) {
ImportBinding importBinding = importBindings[i];
if(importBinding.isValidBinding() && importBinding.isStatic()) {
Binding binding = importBinding.resolvedImport;
if(binding != null && binding.isValidBinding()) {
if(importBinding.onDemand) {
if((binding.kind() & Binding.TYPE) != 0) {
if(proposeField) {
findFields(
token,
(ReferenceBinding)binding,
scope,
fieldsFound,
localsFound,
true,
invocationSite,
invocationScope,
true,
false,
null,
null,
null,
false,
null,
-1,
-1);
}
if(proposeMethod && !insideAnnotationAttribute) {
findMethods(
token,
null,
null,
(ReferenceBinding)binding,
scope,
methodsFound,
true,
exactMatch,
invocationSite,
invocationScope,
true,
false,
false,
null,
null,
null,
false,
null,
-1,
-1);
}
}
} else {
if ((binding.kind() & Binding.FIELD) != 0) {
if(proposeField) {
findFields(
token,
new FieldBinding[]{(FieldBinding)binding},
scope,
fieldsFound,
localsFound,
true,
//{ObjectTeams: normal behavior:
CompletionProposal.FIELD_REF,
null, // expected type
// SH}
((FieldBinding)binding).declaringClass,
invocationSite,
invocationScope,
true,
false,
null,
null,
null,
false,
null,
-1,
-1);
}
} else if ((binding.kind() & Binding.METHOD) != 0) {
if(proposeMethod && !insideAnnotationAttribute) {
MethodBinding methodBinding = (MethodBinding)binding;
if ((exactMatch && CharOperation.equals(token, methodBinding.selector)) ||
!exactMatch && CharOperation.prefixEquals(token, methodBinding.selector, false) ||
(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, methodBinding.selector))) {
findLocalMethodsFromStaticImports(
token,
methodBinding.declaringClass.getMethods(methodBinding.selector),
scope,
exactMatch,
methodsFound,
methodBinding.declaringClass,
invocationSite);
}
}
}
}
}
}
}
}
private void findFieldsFromFavorites(
char[] fieldName,
FieldBinding[] fields,
Scope scope,
ObjectVector fieldsFound,
ObjectVector localsFound,
ReferenceBinding receiverType,
InvocationSite invocationSite,
Scope invocationScope) {
char[] typeName = CharOperation.concatWith(receiverType.compoundName, '.');
int fieldLength = fieldName.length;
next : for (int f = fields.length; --f >= 0;) {
FieldBinding field = fields[f];
if (field.isSynthetic()) continue next;
// only static fields must be proposed
if (!field.isStatic()) continue next;
if (fieldLength > field.name.length) continue next;
if (isFailedMatch(fieldName, field.name)) continue next;
if (this.options.checkDeprecation &&
field.isViewedAsDeprecated() &&
!scope.isDefinedInSameUnit(field.declaringClass))
continue next;
if (this.options.checkVisibility
&& !field.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
for (int i = fieldsFound.size; --i >= 0;) {
Object[] other = (Object[])fieldsFound.elementAt(i);
FieldBinding otherField = (FieldBinding) other[0];
if (field == otherField) continue next;
}
fieldsFound.add(new Object[]{field, receiverType});
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal(field);
relevance += computeRelevanceForCaseMatching(fieldName, field.name);
relevance += computeRelevanceForExpectingType(field.type);
relevance += computeRelevanceForEnumConstant(field.type);
relevance += computeRelevanceForStatic(true, true);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
CompilationUnitDeclaration cu = this.unitScope.referenceContext;
int importStart = cu.types[0].declarationSourceStart;
int importEnd = importStart;
this.noProposal = false;
if (this.compilerOptions.complianceLevel < ClassFileConstants.JDK1_5 ||
!this.options.suggestStaticImport) {
if (!this.isIgnored(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_IMPORT)) {
char[] completion = CharOperation.concat(receiverType.sourceName, field.name, '.');
InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
proposal.setBinding(field);
proposal.setDeclarationSignature(getSignature(field.declaringClass));
proposal.setSignature(getSignature(field.type));
proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
proposal.setPackageName(field.type.qualifiedPackageName());
proposal.setTypeName(field.type.qualifiedSourceName());
proposal.setName(field.name);
proposal.setCompletion(completion);
proposal.setFlags(field.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
char[] typeImportCompletion = createImportCharArray(typeName, false, false);
InternalCompletionProposal typeImportProposal = createProposal(CompletionProposal.TYPE_IMPORT, this.actualCompletionPosition);
typeImportProposal.nameLookup = this.nameEnvironment.nameLookup;
typeImportProposal.completionEngine = this;
char[] packageName = receiverType.qualifiedPackageName();
typeImportProposal.setDeclarationSignature(packageName);
typeImportProposal.setSignature(getSignature(receiverType));
typeImportProposal.setPackageName(packageName);
typeImportProposal.setTypeName(receiverType.qualifiedSourceName());
typeImportProposal.setCompletion(typeImportCompletion);
typeImportProposal.setFlags(receiverType.modifiers);
typeImportProposal.setAdditionalFlags(CompletionFlags.Default);
typeImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset);
typeImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset);
typeImportProposal.setRelevance(relevance);
proposal.setRequiredProposals(new CompletionProposal[]{typeImportProposal});
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
} else {
if (!this.isIgnored(CompletionProposal.FIELD_REF, CompletionProposal.FIELD_IMPORT)) {
char[] completion = field.name;
InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
proposal.setBinding(field);
proposal.setDeclarationSignature(getSignature(field.declaringClass));
proposal.setSignature(getSignature(field.type));
proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
proposal.setPackageName(field.type.qualifiedPackageName());
proposal.setTypeName(field.type.qualifiedSourceName());
proposal.setName(field.name);
proposal.setCompletion(completion);
proposal.setFlags(field.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
char[] fieldImportCompletion = createImportCharArray(CharOperation.concat(typeName, field.name, '.'), true, false);
InternalCompletionProposal fieldImportProposal = createProposal(CompletionProposal.FIELD_IMPORT, this.actualCompletionPosition);
fieldImportProposal.setDeclarationSignature(getSignature(field.declaringClass));
fieldImportProposal.setSignature(getSignature(field.type));
fieldImportProposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
fieldImportProposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
fieldImportProposal.setPackageName(field.type.qualifiedPackageName());
fieldImportProposal.setTypeName(field.type.qualifiedSourceName());
fieldImportProposal.setName(field.name);
fieldImportProposal.setCompletion(fieldImportCompletion);
fieldImportProposal.setFlags(field.modifiers);
fieldImportProposal.setAdditionalFlags(CompletionFlags.StaticImport);
fieldImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset);
fieldImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset);
fieldImportProposal.setRelevance(relevance);
proposal.setRequiredProposals(new CompletionProposal[]{fieldImportProposal});
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
}
}
private void findImplicitMessageSends(
char[] token,
TypeBinding[] argTypes,
Scope scope,
InvocationSite invocationSite,
Scope invocationScope,
ObjectVector methodsFound) {
if (token == null)
return;
boolean staticsOnly = false;
// need to know if we're in a static context (or inside a constructor)
done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
switch (scope.kind) {
case Scope.METHOD_SCOPE :
// handle the error case inside an explicit constructor call (see MethodScope>>findField)
MethodScope methodScope = (MethodScope) scope;
staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall;
break;
case Scope.CLASS_SCOPE :
ClassScope classScope = (ClassScope) scope;
SourceTypeBinding enclosingType = classScope.referenceContext.binding;
findMethods(
token,
null,
argTypes,
enclosingType,
classScope,
methodsFound,
staticsOnly,
true,
invocationSite,
invocationScope,
true,
false,
true,
null,
null,
null,
false,
null,
-1,
-1);
staticsOnly |= enclosingType.isStatic();
break;
case Scope.COMPILATION_UNIT_SCOPE :
break done;
}
scope = scope.parent;
}
}
private void findImports(CompletionOnImportReference importReference, boolean findMembers) {
char[][] tokens = importReference.tokens;
char[] importName = CharOperation.concatWith(tokens, '.');
if (importName.length == 0)
return;
char[] lastToken = tokens[tokens.length - 1];
if(lastToken != null && lastToken.length == 0)
importName = CharOperation.concat(importName, new char[]{'.'});
this.resolvingImports = true;
this.resolvingStaticImports = importReference.isStatic();
this.completionToken = lastToken;
this.qualifiedCompletionToken = importName;
// want to replace the existing .*;
if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
int oldStart = this.startPosition;
int oldEnd = this.endPosition;
setSourceRange(
importReference.sourceStart,
importReference.declarationSourceEnd);
try {
this.nameEnvironment.findPackages(importName, this, this.javaProject.getAllPackageFragmentRoots(), true);
} catch (JavaModelException e) {
// silent
}
setSourceRange(
oldStart,
oldEnd - 1,
false);
}
if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
this.foundTypesCount = 0;
this.nameEnvironment.findTypes(
importName,
findMembers,
this.options.camelCaseMatch,
IJavaSearchConstants.TYPE,
this,
this.monitor);
acceptTypes(null);
}
}
private void findImportsOfMemberTypes(char[] typeName, ReferenceBinding ref, boolean onlyStatic) {
ReferenceBinding[] memberTypes = ref.memberTypes();
int typeLength = typeName.length;
next : for (int m = memberTypes.length; --m >= 0;) {
ReferenceBinding memberType = memberTypes[m];
// if (!wantClasses && memberType.isClass()) continue next;
// if (!wantInterfaces && memberType.isInterface()) continue next;
if (onlyStatic && !memberType.isStatic())
continue next;
if (typeLength > memberType.sourceName.length)
continue next;
if (isFailedMatch(typeName, memberType.sourceName))
continue next;
if (this.options.checkDeprecation && memberType.isViewedAsDeprecated()) continue next;
if (this.options.checkVisibility
&& !memberType.canBeSeenBy(this.unitScope.fPackage))
continue next;
char[] completionName = CharOperation.concat(memberType.sourceName, SEMICOLON);
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(typeName, memberType.sourceName);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
if (memberType.isClass()) {
relevance += computeRelevanceForClass();
} else if(memberType.isEnum()) {
relevance += computeRelevanceForEnum();
} else if (memberType.isInterface()) {
relevance += computeRelevanceForInterface();
}
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
createTypeProposal(
memberType,
memberType.qualifiedSourceName(),
IAccessRule.K_ACCESSIBLE,
completionName,
relevance,
null,
null,
null,
false);
}
}
}
private void findImportsOfStaticFields(char[] fieldName, ReferenceBinding ref) {
FieldBinding[] fields = ref.availableFields();
int fieldLength = fieldName.length;
next : for (int m = fields.length; --m >= 0;) {
FieldBinding field = fields[m];
if (fieldLength > field.name.length)
continue next;
if (field.isSynthetic())
continue next;
if (!field.isStatic())
continue next;
if (isFailedMatch(fieldName, field.name))
continue next;
if (this.options.checkDeprecation && field.isViewedAsDeprecated()) continue next;
if (this.options.checkVisibility
&& !field.canBeSeenBy(this.unitScope.fPackage))
continue next;
char[] completionName = CharOperation.concat(field.name, SEMICOLON);
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(fieldName, field.name);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
proposal.setBinding(field);
proposal.setDeclarationSignature(getSignature(field.declaringClass));
proposal.setSignature(getSignature(field.type));
proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
proposal.setPackageName(field.type.qualifiedPackageName());
proposal.setTypeName(field.type.qualifiedSourceName());
proposal.setName(field.name);
proposal.setCompletion(completionName);
proposal.setFlags(field.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
}
private void findImportsOfStaticMethods(char[] methodName, ReferenceBinding ref) {
MethodBinding[] methods = ref.availableMethods();
int methodLength = methodName.length;
next : for (int m = methods.length; --m >= 0;) {
MethodBinding method = methods[m];
if (method.isSynthetic()) continue next;
if (method.isDefaultAbstract()) continue next;
if (method.isConstructor()) continue next;
if (!method.isStatic()) continue next;
if (this.options.checkDeprecation && method.isViewedAsDeprecated()) continue next;
if (this.options.checkVisibility
&& !method.canBeSeenBy(this.unitScope.fPackage)) continue next;
if (methodLength > method.selector.length)
continue next;
if (isFailedMatch(methodName, method.selector))
continue next;
int length = method.parameters.length;
char[][] parameterPackageNames = new char[length][];
char[][] parameterTypeNames = new char[length][];
for (int i = 0; i < length; i++) {
TypeBinding type = method.original().parameters[i];
parameterPackageNames[i] = type.qualifiedPackageName();
parameterTypeNames[i] = type.qualifiedSourceName();
}
char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames);
char[] completionName = CharOperation.concat(method.selector, SEMICOLON);
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(methodName, method.selector);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.METHOD_NAME_REFERENCE)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_NAME_REFERENCE, this.actualCompletionPosition);
proposal.setDeclarationSignature(getSignature(method.declaringClass));
proposal.setSignature(getSignature(method));
proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
proposal.setParameterPackageNames(parameterPackageNames);
proposal.setParameterTypeNames(parameterTypeNames);
proposal.setPackageName(method.returnType.qualifiedPackageName());
proposal.setTypeName(method.returnType.qualifiedSourceName());
proposal.setName(method.selector);
proposal.setCompletion(completionName);
proposal.setFlags(method.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
if(parameterNames != null) proposal.setParameterNames(parameterNames);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
}
private void findInterfacesMethodDeclarations(
char[] selector,
ReferenceBinding receiverType,
ReferenceBinding[] itsInterfaces,
Scope scope,
ObjectVector methodsFound,
Binding[] missingElements,
int[] missingElementssStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems) {
if (selector == null)
return;
if (itsInterfaces != Binding.NO_SUPERINTERFACES) {
ReferenceBinding[] interfacesToVisit = itsInterfaces;
int nextPosition = interfacesToVisit.length;
for (int i = 0; i < nextPosition; i++) {
ReferenceBinding currentType = interfacesToVisit[i];
MethodBinding[] methods = currentType.availableMethods();
if(methods != null) {
findLocalMethodDeclarations(
selector,
methods,
scope,
methodsFound,
false,
//{ObjectTeams: new param
CompletionProposal.METHOD_DECLARATION,
// SH}
receiverType);
}
itsInterfaces = currentType.superInterfaces();
if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (TypeBinding.equalsEquals(next, interfacesToVisit[b])) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
}
}
private void findInterfacesMethods(
char[] selector,
TypeBinding[] typeArgTypes,
TypeBinding[] argTypes,
ReferenceBinding receiverType,
ReferenceBinding[] itsInterfaces,
Scope scope,
ObjectVector methodsFound,
boolean onlyStaticMethods,
boolean exactMatch,
InvocationSite invocationSite,
Scope invocationScope,
boolean implicitCall,
boolean superCall,
boolean canBePrefixed,
Binding[] missingElements,
int[] missingElementssStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems,
char[] castedReceiver,
int receiverStart,
int receiverEnd) {
if (selector == null)
return;
if (itsInterfaces != Binding.NO_SUPERINTERFACES) {
ReferenceBinding[] interfacesToVisit = itsInterfaces;
int nextPosition = interfacesToVisit.length;
for (int i = 0; i < nextPosition; i++) {
ReferenceBinding currentType = interfacesToVisit[i];
MethodBinding[] methods = currentType.availableMethods();
if(methods != null) {
findLocalMethods(
selector,
typeArgTypes,
argTypes,
methods,
scope,
methodsFound,
onlyStaticMethods,
exactMatch,
//{ObjectTeams: new params (normal behavior):
CompletionProposal.METHOD_REF,
null, // expected type
// SH}
receiverType,
invocationSite,
invocationScope,
implicitCall,
superCall,
canBePrefixed,
missingElements,
missingElementssStarts,
missingElementsEnds,
missingElementsHaveProblems,
castedReceiver,
receiverStart,
receiverEnd);
}
itsInterfaces = currentType.superInterfaces();
if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (TypeBinding.equalsEquals(next, interfacesToVisit[b])) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
}
}
/*
* Find javadoc block tags for a given completion javadoc tag node
*/
private void findJavadocBlockTags(CompletionOnJavadocTag javadocTag) {
char[][] possibleTags = javadocTag.getPossibleBlockTags();
if (possibleTags == null) return;
int length = possibleTags.length;
for (int i=0; i<length; i++) {
int relevance = computeBaseRelevance();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors
this.noProposal = false;
if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_BLOCK_TAG)) {
char[] possibleTag = possibleTags[i];
InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_BLOCK_TAG, this.actualCompletionPosition);
proposal.setName(possibleTag);
int tagLength = possibleTag.length;
char[] completion = new char[1+tagLength];
completion[0] = '@';
System.arraycopy(possibleTag, 0, completion, 1, tagLength);
proposal.setCompletion(completion);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if (DEBUG) {
this.printDebug(proposal);
}
}
}
}
/*
* Find javadoc inline tags for a given completion javadoc tag node
*/
private void findJavadocInlineTags(CompletionOnJavadocTag javadocTag) {
char[][] possibleTags = javadocTag.getPossibleInlineTags();
if (possibleTags == null) return;
int length = possibleTags.length;
for (int i=0; i<length; i++) {
int relevance = computeBaseRelevance();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors
this.noProposal = false;
if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_INLINE_TAG)) {
char[] possibleTag = possibleTags[i];
InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_INLINE_TAG, this.actualCompletionPosition);
proposal.setName(possibleTag);
int tagLength = possibleTag.length;
// boolean inlineTagStarted = javadocTag.completeInlineTagStarted();
char[] completion = new char[2+tagLength+1];
completion[0] = '{';
completion[1] = '@';
System.arraycopy(possibleTag, 0, completion, 2, tagLength);
// do not add space at end of inline tag (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=121026)
//completion[tagLength+2] = ' ';
completion[tagLength+2] = '}';
proposal.setCompletion(completion);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if (DEBUG) {
this.printDebug(proposal);
}
}
}
}
/*
* Find javadoc parameter names.
*/
private void findJavadocParamNames(char[] token, char[][] missingParams, boolean isTypeParam) {
if (missingParams == null) return;
// Get relevance
int relevance = computeBaseRelevance();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for param name
if (!isTypeParam) relevance += R_INTERESTING;
// Propose missing param
int length = missingParams.length;
relevance += length;
for (int i=0; i<length; i++) {
char[] argName = missingParams[i];
if (token == null || CharOperation.prefixEquals(token, argName)) {
this.noProposal = false;
if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_PARAM_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_PARAM_REF, this.actualCompletionPosition);
proposal.setName(argName);
char[] completion = isTypeParam ? CharOperation.concat('<', argName, '>') : argName;
proposal.setCompletion(completion);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(--relevance);
this.requestor.accept(proposal);
if (DEBUG) {
this.printDebug(proposal);
}
}
}
}
}
// what about onDemand types? Ignore them since it does not happen!
// import p1.p2.A.*;
private void findKeywords(char[] keyword, char[][] choices, boolean staticFieldsAndMethodOnly, boolean ignorePackageKeyword) {
if(choices == null || choices.length == 0) return;
int length = keyword.length;
for (int i = 0; i < choices.length; i++)
if (length <= choices[i].length && (CharOperation.prefixEquals(keyword, choices[i], false /* ignore case */)
|| (this.options.substringMatch && CharOperation.substringMatch(keyword, choices[i])))) {
if (ignorePackageKeyword && CharOperation.equals(choices[i], Keywords.PACKAGE))
continue;
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(keyword, choices[i]);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywords
if (staticFieldsAndMethodOnly && this.insideQualifiedReference) relevance += R_NON_INHERITED;
if(CharOperation.equals(choices[i], Keywords.TRUE) || CharOperation.equals(choices[i], Keywords.FALSE)) {
relevance += computeRelevanceForExpectingType(TypeBinding.BOOLEAN);
relevance += computeRelevanceForQualification(false);
}
if (CharOperation.equals(choices[i], Keywords.NEW)) {
relevance += computeRelevanceForConstructor();
}
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.KEYWORD, this.actualCompletionPosition);
proposal.setName(choices[i]);
proposal.setCompletion(choices[i]);
proposal.setReplaceRange((this.startPosition < 0) ? 0 : this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange((this.tokenStart < 0) ? 0 : this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
}
private void findKeywordsForMember(char[] token, int modifiers, ASTNode astNode) {
char[][] keywords = new char[Keywords.COUNT][];
int count = 0;
// visibility
if((modifiers & ClassFileConstants.AccPrivate) == 0
&& (modifiers & ClassFileConstants.AccProtected) == 0
&& (modifiers & ClassFileConstants.AccPublic) == 0) {
keywords[count++] = Keywords.PROTECTED;
keywords[count++] = Keywords.PUBLIC;
if((modifiers & ClassFileConstants.AccAbstract) == 0) {
keywords[count++] = Keywords.PRIVATE;
}
}
if (astNode instanceof CompletionOnFieldType &&
this.compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8) {
FieldBinding astNodeBinding = ((CompletionOnFieldType) astNode).binding;
ReferenceBinding declaringClass = astNodeBinding != null ? astNodeBinding.declaringClass : null;
if (declaringClass != null && declaringClass.isInterface() && !declaringClass.isAnnotationType())
keywords[count++] = Keywords.DEFAULT;
}
if((modifiers & ClassFileConstants.AccAbstract) == 0) {
// abtract
if((modifiers & ~(ExtraCompilerModifiers.AccVisibilityMASK | ClassFileConstants.AccStatic)) == 0) {
keywords[count++] = Keywords.ABSTRACT;
}
// final
if((modifiers & ClassFileConstants.AccFinal) == 0) {
keywords[count++] = Keywords.FINAL;
}
// static
if((modifiers & ClassFileConstants.AccStatic) == 0) {
keywords[count++] = Keywords.STATIC;
}
boolean canBeField = true;
boolean canBeMethod = true;
boolean canBeType = true;
if((modifiers & ClassFileConstants.AccNative) != 0
|| (modifiers & ClassFileConstants.AccStrictfp) != 0
|| (modifiers & ClassFileConstants.AccSynchronized) != 0) {
canBeField = false;
canBeType = false;
}
if((modifiers & ClassFileConstants.AccTransient) != 0
|| (modifiers & ClassFileConstants.AccVolatile) != 0) {
canBeMethod = false;
canBeType = false;
}
if(canBeField) {
// transient
if((modifiers & ClassFileConstants.AccTransient) == 0) {
keywords[count++] = Keywords.TRANSIENT;
}
// volatile
if((modifiers & ClassFileConstants.AccVolatile) == 0) {
keywords[count++] = Keywords.VOLATILE;
}
}
if(canBeMethod) {
// native
if((modifiers & ClassFileConstants.AccNative) == 0) {
keywords[count++] = Keywords.NATIVE;
}
// strictfp
if((modifiers & ClassFileConstants.AccStrictfp) == 0) {
keywords[count++] = Keywords.STRICTFP;
}
// synchronized
if((modifiers & ClassFileConstants.AccSynchronized) == 0) {
keywords[count++] = Keywords.SYNCHRONIZED;
}
//{ObjectTeams: OT specific modifier "callin"
if((modifiers & ExtraCompilerModifiers.AccCallin) == 0) {
keywords[count++] = Keywords.CALLIN;
}
// gbr}
}
if(canBeType) {
//{ObjectTeams: OT specific modifier
if((modifiers & ExtraCompilerModifiers.AccTeam) == 0) {
keywords[count++] = Keywords.TEAM;
}
//gbr}
keywords[count++] = Keywords.CLASS;
keywords[count++] = Keywords.INTERFACE;
if((modifiers & ClassFileConstants.AccFinal) == 0) {
keywords[count++] = Keywords.ENUM;
}
}
} else {
// class
//{ObjectTeams: OT specific modifier
if((modifiers & ExtraCompilerModifiers.AccTeam) == 0) {
keywords[count++] = Keywords.TEAM;
}
//gbr}
keywords[count++] = Keywords.CLASS;
keywords[count++] = Keywords.INTERFACE;
}
System.arraycopy(keywords, 0, keywords = new char[count][], 0, count);
findKeywords(token, keywords, false, false);
}
private void findLabels(char[] label, char[][] choices) {
if(choices == null || choices.length == 0) return;
int length = label.length;
for (int i = 0; i < choices.length; i++) {
if (length <= choices[i].length
&& CharOperation.prefixEquals(label, choices[i], false /* ignore case */
)){
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(label, choices[i]);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.LABEL_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.LABEL_REF, this.actualCompletionPosition);
proposal.setName(choices[i]);
proposal.setCompletion(choices[i]);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
}
}
// Helper method for findMethods(char[], MethodBinding[], Scope, ObjectVector, boolean, boolean, boolean, TypeBinding)
private void findLocalMethodDeclarations(
char[] methodName,
MethodBinding[] methods,
Scope scope,
ObjectVector methodsFound,
// boolean noVoidReturnType, how do you know?
boolean exactMatch,
//{ObjectTeams: new arg: method or callout?
int kind,
// SH}
ReferenceBinding receiverType) {
//{ObjectTeams: decode additional flag:
boolean isSearchingSuperBase = (kind >= SEARCH_SUPER_BASE);
kind &= ~SEARCH_SUPER_BASE;
// SH}
ObjectVector newMethodsFound = new ObjectVector();
// Inherited methods which are hidden by subclasses are filtered out
// No visibility checks can be performed without the scope & invocationSite
int methodLength = methodName.length;
next : for (int f = methods.length; --f >= 0;) {
MethodBinding method = methods[f];
//{ObjectTeams: filter out not-completable methods
if (!canBeCompleted(method.selector)) continue next;
if (TSuperHelper.isTSuper(method)) continue next;
//carp}
if (method.isSynthetic()) continue next;
if (method.isDefaultAbstract()) continue next;
if (method.isConstructor()) continue next;
if (method.isFinal()) {
newMethodsFound.add(method);
continue next;
}
if (this.options.checkDeprecation &&
method.isViewedAsDeprecated() &&
!scope.isDefinedInSameUnit(method.declaringClass))
continue next;
// if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next;
//{ObjectTeams: callout may refer to static method:
if (kind == CompletionProposal.METHOD_DECLARATION)
// SH}
if(method.isStatic()) continue next;
//{ObjectTeams: callout don't respect visibility, except when searching superbase:
if (isSearchingSuperBase && method.isPrivate()) continue next;
if (kind == CompletionProposal.METHOD_DECLARATION)
// SH}
if (!method.canBeSeenBy(receiverType, FakeInvocationSite , scope)) continue next;
if (exactMatch) {
if (!CharOperation.equals(methodName, method.selector, false /* ignore case */
))
continue next;
} else {
if (methodLength > method.selector.length)
continue next;
if (isFailedMatch(methodName, method.selector))
continue next;
}
//{ObjectTeams: different methods may produce different completion kinds
int curKind = kind;
// SH}
for (int i = methodsFound.size; --i >= 0;) {
MethodBinding otherMethod = (MethodBinding) methodsFound.elementAt(i);
//{ObjectTeams: callout override can refer to same methods on both sides:
if (kind != CompletionProposal.OT_CALLOUT_DECLARATION)
// SH}
if (method == otherMethod)
continue next;
if (CharOperation.equals(method.selector, otherMethod.selector, true)
&& this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) {
//{ObjectTeams: callout (override)? (the ui expands callout to a choice of any method binding)
if (curKind != CompletionProposal.METHOD_DECLARATION) {
if (otherMethod.declaringClass.isCompatibleWith(method.declaringClass)
&& !receiverType.isCompatibleWith(method.declaringClass))
continue next; // comparing two base methods.
if (MethodModel.isAbstract(otherMethod)) {
curKind = CompletionProposal.OT_CALLOUT_DECLARATION;
} else {
if( TypeBinding.equalsEquals(otherMethod.declaringClass, receiverType)
&& otherMethod.copyInheritanceSrc == null)
curKind = CompletionProposal.OT_CALLIN_DECLARATION; // no overriding of local methods, only callin allowed
else
curKind = CompletionProposal.OT_CALLOUT_OVERRIDE_DECLARATION;
}
break;
}
// SH}
continue next;
}
}
newMethodsFound.add(method);
int length = method.parameters.length;
char[][] parameterPackageNames = new char[length][];
char[][] parameterFullTypeNames = new char[length][];
for (int i = 0; i < length; i++) {
TypeBinding type = method.parameters[i];
parameterPackageNames[i] = type.qualifiedPackageName();
parameterFullTypeNames[i] = type.qualifiedSourceName();
}
char[][] parameterNames = findMethodParameterNames(method, parameterFullTypeNames);
if(method.typeVariables != null && method.typeVariables.length > 0) {
char[][] excludedNames = findEnclosingTypeNames(scope);
char[][] substituedParameterNames = substituteMethodTypeParameterNames(method.typeVariables, excludedNames);
if(substituedParameterNames != null) {
method = new ParameterizedMethodBinding(
method.declaringClass,
method,
substituedParameterNames,
scope.environment());
}
}
StringBuffer completion = new StringBuffer(10);
if (!exactMatch) {
//{ObjectTeams: callout?
if (curKind != CompletionProposal.METHOD_DECLARATION)
createMethodBinding(method, parameterPackageNames, parameterFullTypeNames, parameterNames, curKind, scope, completion);
else
// SH}
createMethod(method, parameterPackageNames, parameterFullTypeNames, parameterNames, scope, completion);
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(methodName, method.selector);
relevance += R_METHOD_OVERIDE;
//{ObjectTeams: abstractness of ifc-part methods:
/* orig:
if(method.isAbstract()) relevance += R_ABSTRACT_METHOD;
:giro */
if(MethodModel.isAbstract(method)) relevance += R_ABSTRACT_METHOD;
// SH}
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.METHOD_DECLARATION)) {
//{ObjectTeams: different kinds:
/*orig:
InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_DECLARATION, this.actualCompletionPosition);
*/
InternalCompletionProposal proposal = createProposal(curKind, this.actualCompletionPosition);
// SH}
proposal.setBinding(method);
proposal.setDeclarationSignature(getSignature(method.declaringClass));
proposal.setDeclarationKey(method.declaringClass.computeUniqueKey());
proposal.setSignature(getSignature(method));
MethodBinding original = method.original();
if(original != method) {
proposal.setOriginalSignature(getSignature(original));
}
proposal.setKey(method.computeUniqueKey());
proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
proposal.setParameterPackageNames(parameterPackageNames);
proposal.setParameterTypeNames(parameterFullTypeNames);
proposal.setPackageName(method.returnType.qualifiedPackageName());
proposal.setTypeName(method.returnType.qualifiedSourceName());
proposal.setCompletion(completion.toString().toCharArray());
proposal.setName(method.selector);
proposal.setFlags(method.modifiers);
//{ObjectTeams: callout?
switch (curKind) {
case CompletionProposal.OT_CALLOUT_OVERRIDE_DECLARATION:
proposal.setAdditionalFlags(TerminalTokens.TokenNameCALLOUT_OVERRIDE); break;
case CompletionProposal.OT_CALLOUT_DECLARATION:
proposal.setAdditionalFlags(TerminalTokens.TokenNameBINDOUT); break;
}
// SH}
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
if(parameterNames != null) proposal.setParameterNames(parameterNames);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
methodsFound.addAll(newMethodsFound);
}
// Helper method for findMethods(char[], TypeBinding[], ReferenceBinding, Scope, ObjectVector, boolean, boolean, boolean)
private void findLocalMethods(
char[] methodName,
TypeBinding[] typeArgTypes,
TypeBinding[] argTypes,
MethodBinding[] methods,
Scope scope,
ObjectVector methodsFound,
boolean onlyStaticMethods,
boolean exactMatch,
//{ObjectTeams: callin/out RHS?
int kind,
TypeBinding expectedType, //use as a strict filter if non-null
// SH}
ReferenceBinding receiverType,
InvocationSite invocationSite,
Scope invocationScope,
boolean implicitCall,
boolean superCall,
boolean canBePrefixed,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems,
char[] castedReceiver,
int receiverStart,
int receiverEnd) {
boolean completionOnReferenceExpressionName = invocationSite instanceof ReferenceExpression;
ObjectVector newMethodsFound = new ObjectVector();
// Inherited methods which are hidden by subclasses are filtered out
// No visibility checks can be performed without the scope & invocationSite
int methodLength = methodName.length;
int minTypeArgLength = typeArgTypes == null ? 0 : typeArgTypes.length;
int minArgLength = argTypes == null ? 0 : argTypes.length;
next : for (int f = methods.length; --f >= 0;) {
MethodBinding method = methods[f];
//{ObjectTeams: filter out not-completable methods
if (!canBeCompleted(method.selector)) continue next;
if (TSuperHelper.isTSuper(method)) continue next;
//carp}
if (method.isSynthetic()) continue next;
if (method.isDefaultAbstract()) continue next;
if (method.isConstructor()) continue next;
if (this.options.checkDeprecation &&
method.isViewedAsDeprecated() &&
!scope.isDefinedInSameUnit(method.declaringClass))
continue next;
//TODO (david) perhaps the relevance of a void method must be lesser than other methods
//if (expectedTypesPtr > -1 && method.returnType == BaseTypes.VoidBinding) continue next;
if (onlyStaticMethods && !method.isStatic()) continue next;
if (this.options.checkVisibility
//{ObjectTeams: invocationSite can be null (method spec, which don't check visib any way ;-):
&& invocationSite != null
// SH}
&& !method.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
//{ObjectTeams: additional check if method spec type already known:
if (expectedType != null && TypeBinding.notEquals(expectedType, method.returnType)) continue next;
// SH}
if(superCall && method.isAbstract()) {
methodsFound.add(new Object[]{method, receiverType});
continue next;
}
if (exactMatch) {
if (!CharOperation.equals(methodName, method.selector, false /* ignore case */)) {
continue next;
}
} else {
if (methodLength > method.selector.length) continue next;
if (isFailedMatch(methodName, method.selector)) {
continue next;
}
}
if (minTypeArgLength != 0 && minTypeArgLength != method.typeVariables.length)
continue next;
if (minTypeArgLength != 0) {
method = scope.environment().createParameterizedGenericMethod(method, typeArgTypes);
}
if (minArgLength > method.parameters.length)
continue next;
for (int a = minArgLength; --a >= 0;){
if (argTypes[a] != null) { // can be null if it could not be resolved properly
if (!argTypes[a].isCompatibleWith(method.parameters[a])) {
continue next;
}
}
}
//{ObjectTeams:
if (isBaseAccess(invocationSite) || isTSuperAccess(invocationSite)) {
MethodScope methodScope = invocationScope.methodScope();
if (methodScope != null) {
MethodBinding enclosingMethod = methodScope.referenceMethod().binding;
if (enclosingMethod != method) {
AbstractMethodDeclaration ifcMethod = methodScope.referenceMethod().interfacePartMethod;
if (ifcMethod == null || ifcMethod.binding != method) {
continue next;
}
}
}
} else if (method.isCallin()) {
continue next;
}
if (method.copyInheritanceSrc != null)
method = method.copyInheritanceSrc;
//SH}
boolean prefixRequired = false;
for (int i = methodsFound.size; --i >= 0;) {
Object[] other = (Object[]) methodsFound.elementAt(i);
MethodBinding otherMethod = (MethodBinding) other[0];
ReferenceBinding otherReceiverType = (ReferenceBinding) other[1];
if (method == otherMethod && TypeBinding.equalsEquals(receiverType, otherReceiverType))
continue next;
if (CharOperation.equals(method.selector, otherMethod.selector, true)) {
if (TypeBinding.equalsEquals(receiverType, otherReceiverType)) {
if (this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) {
if (!superCall || !otherMethod.declaringClass.isInterface()) {
continue next;
}
}
} else {
if (this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) {
if(receiverType.isAnonymousType()) continue next;
if(!superCall) {
if(!canBePrefixed) continue next;
prefixRequired = true;
}
}
}
}
}
newMethodsFound.add(new Object[]{method, receiverType});
ReferenceBinding superTypeWithSameErasure = (ReferenceBinding)receiverType.findSuperTypeOriginatingFrom(method.declaringClass);
//{ObjectTeams: some types don't have a super type
if (superTypeWithSameErasure != null)
// SH}
if (TypeBinding.notEquals(method.declaringClass, superTypeWithSameErasure)) {
MethodBinding[] otherMethods = superTypeWithSameErasure.getMethods(method.selector);
for (int i = 0; i < otherMethods.length; i++) {
if(otherMethods[i].original() == method.original()) {
method = otherMethods[i];
}
}
}
//{ObjectTeams: retrench callin:
/* orig:
int length = method.parameters.length;
:giro */
int length = method.getSourceParamLength();
int parameterOffset = method.parameters.length - length;
// SH}
char[][] parameterPackageNames = new char[length][];
char[][] parameterTypeNames = new char[length][];
//{ObjectTeams: offset
/* orig:
for (int i = 0; i < length; i++) {
:giro */
for (int i = parameterOffset; i < length; i++) {
// SH}
TypeBinding type = method.original().parameters[i];
parameterPackageNames[i] = type.qualifiedPackageName();
parameterTypeNames[i] = type.qualifiedSourceName();
}
//{ObjectTeams: offset:
/* orig:
char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames);
:giro */
char[][] parameterNames = findMethodParameterNames(method,parameterOffset,parameterTypeNames);
// SH}
char[] completion = CharOperation.NO_CHAR;
int previousStartPosition = this.startPosition;
int previousTokenStart = this.tokenStart;
// Special case for completion in javadoc
if (this.assistNodeInJavadoc > 0) {
Expression receiver = null;
if (invocationSite instanceof CompletionOnJavadocMessageSend) {
CompletionOnJavadocMessageSend msg = (CompletionOnJavadocMessageSend) invocationSite;
receiver = msg.receiver;
} else if (invocationSite instanceof CompletionOnJavadocFieldReference) {
CompletionOnJavadocFieldReference fieldRef = (CompletionOnJavadocFieldReference) invocationSite;
receiver = fieldRef.receiver;
}
if (receiver != null) {
StringBuffer javadocCompletion = new StringBuffer();
if (receiver.isThis()) {
if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) {
javadocCompletion.append('#');
}
} else if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) {
if (receiver instanceof JavadocSingleTypeReference) {
JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) receiver;
javadocCompletion.append(typeRef.token);
javadocCompletion.append('#');
} else if (receiver instanceof JavadocQualifiedTypeReference) {
JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) receiver;
completion = CharOperation.concat(CharOperation.concatWith(typeRef.tokens, '.'), method.selector, '#');
for (int t=0,nt =typeRef.tokens.length; t<nt; t++) {
if (t>0) javadocCompletion.append('.');
javadocCompletion.append(typeRef.tokens[t]);
}
javadocCompletion.append('#');
}
}
javadocCompletion.append(method.selector);
// Append parameters types
javadocCompletion.append('(');
if (method.parameters != null) {
boolean isVarargs = method.isVarargs();
for (int p=0, ln=method.parameters.length; p<ln; p++) {
if (p>0) javadocCompletion.append(", "); //$NON-NLS-1$
TypeBinding argTypeBinding = method.parameters[p];
if (isVarargs && p == ln - 1) {
createVargsType(argTypeBinding.erasure(), scope, javadocCompletion);
} else {
createType(argTypeBinding.erasure(), scope,javadocCompletion);
}
}
}
javadocCompletion.append(')');
completion = javadocCompletion.toString().toCharArray();
}
} else {
// nothing to insert - do not want to replace the existing selector & arguments
if (!exactMatch) {
if (completionOnReferenceExpressionName)
completion = method.selector;
else if (this.source != null
&& this.source.length > this.endPosition
&& this.source[this.endPosition] == '(')
completion = method.selector;
else
completion = CharOperation.concat(method.selector, new char[] { '(', ')' });
if (castedReceiver != null) {
completion = CharOperation.concat(castedReceiver, completion);
}
} else {
if(prefixRequired && (this.source != null)) {
completion = CharOperation.subarray(this.source, this.startPosition, this.endPosition);
} else {
this.startPosition = this.endPosition;
}
this.tokenStart = this.tokenEnd;
}
if(prefixRequired || this.options.forceImplicitQualification){
char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), method.isStatic());
completion = CharOperation.concat(prefix,completion,'.');
}
//{ObjectTeams: RHS method spec?
if (kind == CompletionProposal.OT_METHOD_SPEC) {
// Note that unlike OT_FIELD_SPEC the return type would appear twice, if included unconditionally.
// Seemingly, the curserLocation is set differently in both cases.
if (expectedType == null) // else type is already present
completion = prependType(method.returnType, scope, completion);
completion = CharOperation.append(completion, ';');
}
// SH}
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(methodName, method.selector);
relevance += computeRelevanceForExpectingType(method.returnType);
relevance += computeRelevanceForEnumConstant(method.returnType);
relevance += computeRelevanceForStatic(onlyStaticMethods, method.isStatic());
relevance += computeRelevanceForQualification(prefixRequired);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
if (onlyStaticMethods && this.insideQualifiedReference) {
relevance += computeRelevanceForInheritance(receiverType, method.declaringClass);
}
if (missingElements != null) {
relevance += computeRelevanceForMissingElements(missingElementsHaveProblems);
}
relevance += computeRelevanceForSuper(method, scope, invocationSite);
this.noProposal = false;
if (castedReceiver == null) {
// Standard proposal
if(!this.isIgnored(CompletionProposal.METHOD_REF, missingElements != null) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) {
//{ObjectTeams: invocationSite==null signals completion on method spec short:
/* orig:
InternalCompletionProposal proposal = createProposal(completionOnReferenceExpressionName ? CompletionProposal.METHOD_NAME_REFERENCE : CompletionProposal.METHOD_REF, this.actualCompletionPosition);
:giro */
if (kind == CompletionProposal.OT_METHOD_SPEC) {
if (invocationSite == null)
// method-spec short: chop off empty param list:
completion = CharOperation.replace(completion, "()".toCharArray(), new char[0]); //$NON-NLS-1$
} else {
kind = completionOnReferenceExpressionName ? CompletionProposal.METHOD_NAME_REFERENCE : CompletionProposal.METHOD_REF;
}
InternalCompletionProposal proposal = createProposal(kind, this.actualCompletionPosition);
// SH}
proposal.setBinding(method);
proposal.setDeclarationSignature(getSignature(method.declaringClass));
proposal.setSignature(getSignature(method));
MethodBinding original = method.original();
if(original != method) {
proposal.setOriginalSignature(getSignature(original));
}
proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
proposal.setParameterPackageNames(parameterPackageNames);
proposal.setParameterTypeNames(parameterTypeNames);
proposal.setPackageName(method.returnType.qualifiedPackageName());
proposal.setTypeName(method.returnType.qualifiedSourceName());
proposal.setName(method.selector);
if (missingElements != null) {
CompletionProposal[] subProposals = new CompletionProposal[missingElements.length];
for (int i = 0; i < missingElements.length; i++) {
subProposals[i] =
createRequiredTypeProposal(
missingElements[i],
missingElementsStarts[i],
missingElementsEnds[i],
relevance);
}
proposal.setRequiredProposals(subProposals);
}
proposal.setCompletion(completion);
proposal.setFlags(method.modifiers);
//{ObjectTeams: encode kind of method mapping:
if (this.currentMethodMapping != null) {
if (this.currentMethodMapping.isCallin()) {
proposal.setAdditionalFlags(((CallinMappingDeclaration)this.currentMethodMapping).callinModifier); // pass down for label computation.
} else {
boolean isOverride = ((CalloutMappingDeclaration)this.currentMethodMapping).isCalloutOverride();
proposal.setAdditionalFlags(isOverride ? TerminalTokens.TokenNameCALLOUT_OVERRIDE : TerminalTokens.TokenNameBINDOUT); // pass down for label computation: callout
}
}
// SH}
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
if(parameterNames != null) proposal.setParameterNames(parameterNames);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
// Javadoc proposal
if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_METHOD_REF)) {
char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK);
InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_METHOD_REF, this.actualCompletionPosition);
proposal.setBinding(method);
proposal.setDeclarationSignature(getSignature(method.declaringClass));
proposal.setSignature(getSignature(method));
MethodBinding original = method.original();
if(original != method) {
proposal.setOriginalSignature(getSignature(original));
}
proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
proposal.setParameterPackageNames(parameterPackageNames);
proposal.setParameterTypeNames(parameterTypeNames);
proposal.setPackageName(method.returnType.qualifiedPackageName());
proposal.setTypeName(method.returnType.qualifiedSourceName());
proposal.setName(method.selector);
proposal.setCompletion(javadocCompletion);
proposal.setFlags(method.modifiers);
int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition;
proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance+R_INLINE_TAG);
if(parameterNames != null) proposal.setParameterNames(parameterNames);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
} else {
if(!this.isIgnored(CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER, missingElements != null)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER, this.actualCompletionPosition);
proposal.setBinding(method);
proposal.setDeclarationSignature(getSignature(method.declaringClass));
proposal.setSignature(getSignature(method));
MethodBinding original = method.original();
if(original != method) {
proposal.setOriginalSignature(getSignature(original));
}
proposal.setReceiverSignature(getSignature(receiverType));
proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
proposal.setParameterPackageNames(parameterPackageNames);
proposal.setParameterTypeNames(parameterTypeNames);
proposal.setPackageName(method.returnType.qualifiedPackageName());
proposal.setTypeName(method.returnType.qualifiedSourceName());
proposal.setName(method.selector);
if (missingElements != null) {
CompletionProposal[] subProposals = new CompletionProposal[missingElements.length];
for (int i = 0; i < missingElements.length; i++) {
subProposals[i] =
createRequiredTypeProposal(
missingElements[i],
missingElementsStarts[i],
missingElementsEnds[i],
relevance);
}
proposal.setRequiredProposals(subProposals);
}
proposal.setCompletion(completion);
proposal.setFlags(method.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setReceiverRange(receiverStart - this.offset, receiverEnd - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
if(parameterNames != null) proposal.setParameterNames(parameterNames);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
this.startPosition = previousStartPosition;
this.tokenStart = previousTokenStart;
}
methodsFound.addAll(newMethodsFound);
}
private void findLocalMethodsFromFavorites(
char[] methodName,
MethodBinding[] methods,
Scope scope,
ObjectVector methodsFound,
ObjectVector methodsFoundFromFavorites,
ReferenceBinding receiverType,
InvocationSite invocationSite,
Scope invocationScope) {
char[] typeName = CharOperation.concatWith(receiverType.compoundName, '.');
int methodLength = methodName.length;
next : for (int f = methods.length; --f >= 0;) {
MethodBinding method = methods[f];
if (method.isSynthetic()) continue next;
if (method.isDefaultAbstract()) continue next;
if (method.isConstructor()) continue next;
if (this.options.checkDeprecation &&
method.isViewedAsDeprecated() &&
!scope.isDefinedInSameUnit(method.declaringClass))
continue next;
if (!method.isStatic()) continue next;
if (this.options.checkVisibility
&& !method.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
if (methodLength > method.selector.length) continue next;
if (isFailedMatch(methodName, method.selector)) {
continue next;
}
for (int i = methodsFoundFromFavorites.size; --i >= 0;) {
Object[] other = (Object[]) methodsFoundFromFavorites.elementAt(i);
MethodBinding otherMethod = (MethodBinding) other[0];
if (method == otherMethod) continue next;
if (CharOperation.equals(method.selector, otherMethod.selector, true)) {
if (TypeBinding.equalsEquals(otherMethod.declaringClass, method.declaringClass) &&
this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) {
continue next;
}
}
}
for (int i = methodsFound.size; --i >= 0;) {
Object[] other = (Object[]) methodsFound.elementAt(i);
MethodBinding otherMethod = (MethodBinding) other[0];
if (method == otherMethod) continue next;
if (CharOperation.equals(method.selector, otherMethod.selector, true)) {
if (this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) {
continue next;
}
}
}
boolean proposeStaticImport = !(this.compilerOptions.complianceLevel < ClassFileConstants.JDK1_5) &&
this.options.suggestStaticImport;
boolean isAlreadyImported = false;
if (!proposeStaticImport) {
if(!this.importCachesInitialized) {
initializeImportCaches();
}
for (int j = 0; j < this.importCacheCount; j++) {
char[][] importName = this.importsCache[j];
if(CharOperation.equals(receiverType.sourceName, importName[0])) {
if (!CharOperation.equals(typeName, importName[1])) {
continue next;
} else {
isAlreadyImported = true;
}
}
}
}
methodsFoundFromFavorites.add(new Object[]{method, receiverType});
ReferenceBinding superTypeWithSameErasure = (ReferenceBinding)receiverType.findSuperTypeOriginatingFrom(method.declaringClass);
if (TypeBinding.notEquals(method.declaringClass, superTypeWithSameErasure)) {
MethodBinding[] otherMethods = superTypeWithSameErasure.getMethods(method.selector);
for (int i = 0; i < otherMethods.length; i++) {
if(otherMethods[i].original() == method.original()) {
method = otherMethods[i];
}
}
}
int length = method.parameters.length;
char[][] parameterPackageNames = new char[length][];
char[][] parameterTypeNames = new char[length][];
for (int i = 0; i < length; i++) {
TypeBinding type = method.original().parameters[i];
parameterPackageNames[i] = type.qualifiedPackageName();
parameterTypeNames[i] = type.qualifiedSourceName();
}
char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames);
char[] completion = CharOperation.NO_CHAR;
int previousStartPosition = this.startPosition;
int previousTokenStart = this.tokenStart;
if (this.source != null
&& this.source.length > this.endPosition
&& this.source[this.endPosition] == '(') {
completion = method.selector;
} else {
completion = CharOperation.concat(method.selector, new char[] { '(', ')' });
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(methodName, method.selector);
relevance += computeRelevanceForExpectingType(method.returnType);
relevance += computeRelevanceForEnumConstant(method.returnType);
relevance += computeRelevanceForStatic(true, method.isStatic());
relevance += computeRelevanceForQualification(true);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
CompilationUnitDeclaration cu = this.unitScope.referenceContext;
int importStart = cu.types[0].declarationSourceStart;
int importEnd = importStart;
this.noProposal = false;
if (!proposeStaticImport) {
if (isAlreadyImported) {
if (!isIgnored(CompletionProposal.METHOD_REF)) {
completion = CharOperation.concat(receiverType.sourceName, completion, '.');
InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
proposal.setBinding(method);
proposal.setDeclarationSignature(getSignature(method.declaringClass));
proposal.setSignature(getSignature(method));
MethodBinding original = method.original();
if(original != method) {
proposal.setOriginalSignature(getSignature(original));
}
proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
proposal.setParameterPackageNames(parameterPackageNames);
proposal.setParameterTypeNames(parameterTypeNames);
proposal.setPackageName(method.returnType.qualifiedPackageName());
proposal.setTypeName(method.returnType.qualifiedSourceName());
proposal.setName(method.selector);
proposal.setCompletion(completion);
proposal.setFlags(method.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
if(parameterNames != null) proposal.setParameterNames(parameterNames);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
} else if (!this.isIgnored(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_IMPORT)) {
completion = CharOperation.concat(receiverType.sourceName, completion, '.');
InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
proposal.setBinding(method);
proposal.setDeclarationSignature(getSignature(method.declaringClass));
proposal.setSignature(getSignature(method));
MethodBinding original = method.original();
if(original != method) {
proposal.setOriginalSignature(getSignature(original));
}
proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
proposal.setParameterPackageNames(parameterPackageNames);
proposal.setParameterTypeNames(parameterTypeNames);
proposal.setPackageName(method.returnType.qualifiedPackageName());
proposal.setTypeName(method.returnType.qualifiedSourceName());
proposal.setName(method.selector);
proposal.setCompletion(completion);
proposal.setFlags(method.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
if(parameterNames != null) proposal.setParameterNames(parameterNames);
char[] typeImportCompletion = createImportCharArray(typeName, false, false);
InternalCompletionProposal typeImportProposal = createProposal(CompletionProposal.TYPE_IMPORT, this.actualCompletionPosition);
typeImportProposal.nameLookup = this.nameEnvironment.nameLookup;
typeImportProposal.completionEngine = this;
char[] packageName = receiverType.qualifiedPackageName();
typeImportProposal.setDeclarationSignature(packageName);
typeImportProposal.setSignature(getSignature(receiverType));
typeImportProposal.setPackageName(packageName);
typeImportProposal.setTypeName(receiverType.qualifiedSourceName());
typeImportProposal.setCompletion(typeImportCompletion);
typeImportProposal.setFlags(receiverType.modifiers);
typeImportProposal.setAdditionalFlags(CompletionFlags.Default);
typeImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset);
typeImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset);
typeImportProposal.setRelevance(relevance);
proposal.setRequiredProposals(new CompletionProposal[]{typeImportProposal});
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
} else {
if (!this.isIgnored(CompletionProposal.METHOD_REF, CompletionProposal.METHOD_IMPORT)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
proposal.setBinding(method);
proposal.setDeclarationSignature(getSignature(method.declaringClass));
proposal.setSignature(getSignature(method));
MethodBinding original = method.original();
if(original != method) {
proposal.setOriginalSignature(getSignature(original));
}
proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
proposal.setParameterPackageNames(parameterPackageNames);
proposal.setParameterTypeNames(parameterTypeNames);
proposal.setPackageName(method.returnType.qualifiedPackageName());
proposal.setTypeName(method.returnType.qualifiedSourceName());
proposal.setName(method.selector);
proposal.setCompletion(completion);
proposal.setFlags(method.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
if(parameterNames != null) proposal.setParameterNames(parameterNames);
char[] methodImportCompletion = createImportCharArray(CharOperation.concat(typeName, method.selector, '.'), true, false);
InternalCompletionProposal methodImportProposal = createProposal(CompletionProposal.METHOD_IMPORT, this.actualCompletionPosition);
methodImportProposal.setDeclarationSignature(getSignature(method.declaringClass));
methodImportProposal.setSignature(getSignature(method));
if(original != method) {
proposal.setOriginalSignature(getSignature(original));
}
methodImportProposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
methodImportProposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
methodImportProposal.setParameterPackageNames(parameterPackageNames);
methodImportProposal.setParameterTypeNames(parameterTypeNames);
methodImportProposal.setPackageName(method.returnType.qualifiedPackageName());
methodImportProposal.setTypeName(method.returnType.qualifiedSourceName());
methodImportProposal.setName(method.selector);
methodImportProposal.setCompletion(methodImportCompletion);
methodImportProposal.setFlags(method.modifiers);
methodImportProposal.setAdditionalFlags(CompletionFlags.StaticImport);
methodImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset);
methodImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset);
methodImportProposal.setRelevance(relevance);
if(parameterNames != null) methodImportProposal.setParameterNames(parameterNames);
proposal.setRequiredProposals(new CompletionProposal[]{methodImportProposal});
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
this.startPosition = previousStartPosition;
this.tokenStart = previousTokenStart;
}
}
/**
* Helper method for findMethods(char[], TypeBinding[], ReferenceBinding, Scope, ObjectVector, boolean, boolean, boolean)
* Note that the method doesn't do a comparison of the method names and expects the client to handle the same.
*
* @methodName method as entered by the user, the one to completed
* @param methods a resultant array of MethodBinding, whose names should match methodName. The calling client must ensure that this check is handled.
*/
private void findLocalMethodsFromStaticImports(
char[] methodName,
MethodBinding[] methods,
Scope scope,
boolean exactMatch,
ObjectVector methodsFound,
ReferenceBinding receiverType,
InvocationSite invocationSite) {
ObjectVector newMethodsFound = new ObjectVector();
next : for (int f = methods.length; --f >= 0;) {
MethodBinding method = methods[f];
if (method.isSynthetic()) continue next;
if (method.isDefaultAbstract()) continue next;
if (method.isConstructor()) continue next;
if (!method.isStatic()) continue next;
if (this.options.checkDeprecation &&
method.isViewedAsDeprecated() &&
!scope.isDefinedInSameUnit(method.declaringClass))
continue next;
if (this.options.checkVisibility
&& !method.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
for (int i = methodsFound.size; --i >= 0;) {
Object[] other = (Object[]) methodsFound.elementAt(i);
MethodBinding otherMethod = (MethodBinding) other[0];
ReferenceBinding otherReceiverType = (ReferenceBinding) other[1];
if (method == otherMethod && TypeBinding.equalsEquals(receiverType, otherReceiverType))
continue next;
if (CharOperation.equals(method.selector, otherMethod.selector, true)) {
if (this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) {
continue next;
}
}
}
newMethodsFound.add(new Object[]{method, receiverType});
int length = method.parameters.length;
char[][] parameterPackageNames = new char[length][];
char[][] parameterTypeNames = new char[length][];
for (int i = 0; i < length; i++) {
TypeBinding type = method.original().parameters[i];
parameterPackageNames[i] = type.qualifiedPackageName();
parameterTypeNames[i] = type.qualifiedSourceName();
}
char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames);
char[] completion = CharOperation.NO_CHAR;
int previousStartPosition = this.startPosition;
int previousTokenStart = this.tokenStart;
if (!exactMatch) {
if (this.source != null
&& this.source.length > this.endPosition
&& this.source[this.endPosition] == '(') {
completion = method.selector;
} else {
completion = CharOperation.concat(method.selector, new char[] { '(', ')' });
}
} else {
this.startPosition = this.endPosition;
this.tokenStart = this.tokenEnd;
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(methodName, method.selector);
relevance += computeRelevanceForExpectingType(method.returnType);
relevance += computeRelevanceForEnumConstant(method.returnType);
relevance += computeRelevanceForStatic(true, method.isStatic());
relevance += computeRelevanceForQualification(false);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
proposal.setBinding(method);
proposal.setDeclarationSignature(getSignature(method.declaringClass));
proposal.setSignature(getSignature(method));
MethodBinding original = method.original();
if(original != method) {
proposal.setOriginalSignature(getSignature(original));
}
proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
proposal.setParameterPackageNames(parameterPackageNames);
proposal.setParameterTypeNames(parameterTypeNames);
proposal.setPackageName(method.returnType.qualifiedPackageName());
proposal.setTypeName(method.returnType.qualifiedSourceName());
proposal.setName(method.selector);
proposal.setCompletion(completion);
proposal.setFlags(method.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
if(parameterNames != null) proposal.setParameterNames(parameterNames);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
this.startPosition = previousStartPosition;
this.tokenStart = previousTokenStart;
}
methodsFound.addAll(newMethodsFound);
}
private void findLocalMethodsFromStaticImports(
char[] token,
Scope scope,
InvocationSite invocationSite,
Scope invocationScope,
boolean exactMatch,
ObjectVector methodsFound,
boolean proposeMethod) {
findFieldsAndMethodsFromStaticImports(
token,
scope,
invocationSite,
invocationScope,
exactMatch,
false,
new ObjectVector(),
new ObjectVector(),
methodsFound,
false,
proposeMethod);
}
protected void findMembers(
char[] token,
ReferenceBinding receiverType,
Scope scope,
InvocationSite invocationSite,
boolean isInsideAnnotationAttribute,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems) {
if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
findMemberTypes(
token,
receiverType,
scope,
scope.enclosingSourceType(),
false,
true,
new ObjectVector(),
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems);
}
if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) {
findClassField(
token,
receiverType,
scope,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems);
}
MethodScope methodScope = null;
if (!isInsideAnnotationAttribute &&
!this.requestor.isIgnored(CompletionProposal.KEYWORD) &&
((scope instanceof MethodScope && !((MethodScope)scope).isStatic)
|| ((methodScope = scope.enclosingMethodScope()) != null && !methodScope.isStatic))) {
if (token.length >= 0) {
boolean isInterface = false;
if (receiverType != null) {
isInterface = receiverType.isInterface();
}
if (!isInterface) {
findKeywords(token, new char[][] { Keywords.THIS, Keywords.SUPER }, true, false);
} else {
boolean isEqual = false;
char[] enclosingSourceName = null;
if(scope.enclosingSourceType() != null)
enclosingSourceName = scope.enclosingSourceType().sourceName;
char[] receiverSourceName = null;
if (receiverType != null) {
receiverSourceName = receiverType.sourceName;
}
if( enclosingSourceName !=null & receiverSourceName !=null)
isEqual = Arrays.equals(enclosingSourceName, receiverSourceName);
if(isEqual) {
findKeywords(token, new char[][] { Keywords.THIS }, true, false);
} else {
// Check if the enclosing source implements this interface then show super
if (scope.enclosingSourceType() != null) {
SourceTypeBinding src = scope.enclosingSourceType();
ReferenceBinding[] superInterfaces = src.superInterfaces();
boolean implemented = false;
for (ReferenceBinding referenceBinding : superInterfaces) {
if (Arrays.equals(referenceBinding.sourceName, receiverSourceName)) {
implemented = true;
break;
}
}
if (implemented) {
findKeywords(token, new char[][] { Keywords.SUPER }, true, false);
}
}
}
}
}
}
if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) {
findFields(
token,
receiverType,
scope,
new ObjectVector(),
new ObjectVector(),
true,
invocationSite,
scope,
false,
false,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
null,
-1,
-1);
}
if (!isInsideAnnotationAttribute && !this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
findMethods(
token,
null,
null,
receiverType,
scope,
new ObjectVector(),
true,
false,
invocationSite,
scope,
false,
false,
false,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
null,
-1,
-1);
}
}
private void findMembersFromMissingType(
final char[] token,
final long pos,
TypeBinding resolveType,
final Scope scope,
final InvocationSite invocationSite,
final boolean isInsideAnnotationAttribute) {
MissingTypesGuesser missingTypesConverter = new MissingTypesGuesser(this);
MissingTypesGuesser.GuessedTypeRequestor substitutionRequestor =
new MissingTypesGuesser.GuessedTypeRequestor() {
@Override
public void accept(
TypeBinding guessedType,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean hasProblems) {
if (guessedType instanceof ReferenceBinding) {
findMembers(
CompletionEngine.this.completionToken,
(ReferenceBinding)guessedType,
scope,
invocationSite,
isInsideAnnotationAttribute,
missingElements,
missingElementsStarts,
missingElementsEnds,
hasProblems);
}
}
};
SingleTypeReference typeRef = new SingleTypeReference(token, pos);
typeRef.resolvedType = new ProblemReferenceBinding(new char[][]{ token }, null, ProblemReasons.NotFound);
missingTypesConverter.guess(typeRef, scope, substitutionRequestor);
}
private void findMemberTypes(
char[] typeName,
ReferenceBinding receiverType,
Scope scope,
SourceTypeBinding typeInvocation,
boolean staticOnly,
boolean staticFieldsAndMethodOnly,
boolean fromStaticImport,
boolean checkQualification,
boolean proposeAllMemberTypes,
SourceTypeBinding typeToIgnore,
ObjectVector typesFound,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems) {
ReferenceBinding currentType = receiverType;
if (typeName == null)
return;
if (this.insideQualifiedReference
|| typeName.length == 0) { // do not search up the hierarchy
findMemberTypes(
typeName,
currentType.memberTypes(),
typesFound,
receiverType,
typeInvocation,
staticOnly,
staticFieldsAndMethodOnly,
fromStaticImport,
checkQualification,
scope,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems);
return;
}
ReferenceBinding[] interfacesToVisit = null;
int nextPosition = 0;
do {
ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
if (interfacesToVisit == null) {
interfacesToVisit = itsInterfaces;
nextPosition = interfacesToVisit.length;
} else {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (TypeBinding.equalsEquals(next, interfacesToVisit[b])) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
findMemberTypes(
typeName,
currentType.memberTypes(),
typesFound,
receiverType,
typeInvocation,
staticOnly,
staticFieldsAndMethodOnly,
fromStaticImport,
checkQualification,
scope,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems);
currentType = currentType.superclass();
} while (currentType != null);
if(proposeAllMemberTypes) {
ReferenceBinding[] memberTypes = receiverType.memberTypes();
for (int i = 0; i < memberTypes.length; i++) {
if(TypeBinding.notEquals(memberTypes[i], typeToIgnore)) {
findSubMemberTypes(
typeName,
memberTypes[i],
scope,
typeInvocation,
staticOnly,
staticFieldsAndMethodOnly,
fromStaticImport,
typesFound);
}
}
}
if (interfacesToVisit != null) {
for (int i = 0; i < nextPosition; i++) {
ReferenceBinding anInterface = interfacesToVisit[i];
findMemberTypes(
typeName,
anInterface.memberTypes(),
typesFound,
receiverType,
typeInvocation,
staticOnly,
staticFieldsAndMethodOnly,
fromStaticImport,
checkQualification,
scope,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems);
ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (TypeBinding.equalsEquals(next, interfacesToVisit[b])) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
}
}
protected void findMemberTypes(
char[] typeName,
ReferenceBinding receiverType,
Scope scope,
SourceTypeBinding typeInvocation,
boolean staticOnly,
boolean staticFieldsAndMethodOnly,
ObjectVector typesFound,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems) {
findMemberTypes(
typeName,
receiverType,
scope,
typeInvocation,
staticOnly,
staticFieldsAndMethodOnly,
false,
false,
false,
null,
typesFound,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems);
}
// Helper method for findMemberTypes(char[], ReferenceBinding, Scope)
private void findMemberTypes(
char[] typeName,
ReferenceBinding[] memberTypes,
ObjectVector typesFound,
ReferenceBinding receiverType,
SourceTypeBinding invocationType,
boolean staticOnly,
boolean staticFieldsAndMethodOnly,
boolean fromStaticImport,
boolean checkQualification,
Scope scope,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems) {
// Inherited member types which are hidden by subclasses are filtered out
// No visibility checks can be performed without the scope & invocationSite
int typeLength = typeName.length;
next : for (int m = memberTypes.length; --m >= 0;) {
ReferenceBinding memberType = memberTypes[m];
// if (!wantClasses && memberType.isClass()) continue next;
// if (!wantInterfaces && memberType.isInterface()) continue next;
if (staticOnly && !memberType.isStatic()) continue next;
if (isForbidden(memberType)) continue next;
if (typeLength > memberType.sourceName.length)
continue next;
if (isFailedMatch(typeName, memberType.sourceName))
continue next;
//{ObjectTeams: don't surface __OT__ names:
if (!canTypeBeCompleted(memberType.sourceName))
continue next;
// after @role expect role files only.
if ((this.assistNodeInJavadoc & CompletionOnJavadoc.ROLE) != 0) {
RoleModel roleModel = memberType.roleModel;
if (roleModel == null || !roleModel.isRoleFile())
continue next;
}
// SH}
if (this.options.checkDeprecation &&
memberType.isViewedAsDeprecated() &&
!scope.isDefinedInSameUnit(memberType))
continue next;
if (this.options.checkVisibility) {
if (invocationType != null && !memberType.canBeSeenBy(receiverType, invocationType)) {
continue next;
} else if(invocationType == null && !memberType.canBeSeenBy(this.unitScope.fPackage)) {
continue next;
}
}
if (this.insideQualifiedReference &&
receiverType.isParameterizedType() &&
memberType.isStatic()) {
continue next;
}
for (int i = typesFound.size; --i >= 0;) {
ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(i);
if (TypeBinding.equalsEquals(memberType, otherType))
continue next;
if (CharOperation.equals(memberType.sourceName, otherType.sourceName, true)
&& otherType.isNestedType()) {
if (memberType.enclosingType().isSuperclassOf(otherType.enclosingType()))
continue next;
if (otherType.enclosingType().isInterface())
if (memberType.enclosingType()
.implementsInterface(otherType.enclosingType(), true))
continue next;
if (memberType.enclosingType().isInterface())
if (otherType.enclosingType()
.implementsInterface(memberType.enclosingType(), true))
continue next;
}
}
typesFound.add(memberType);
if (this.assistNodeIsExtendedType && memberType.isFinal()) continue next;
if (this.assistNodeIsInterfaceExcludingAnnotation && memberType.isAnnotationType()) continue next;
if(!this.insideQualifiedReference) {
if(this.assistNodeIsClass || this.assistNodeIsException) {
//{ObjectTeams: different determination of class/interface for roles:
/* orig:
if(!memberType.isClass()) continue next;
:giro */
if(!RoleModel.isClass(memberType)) continue next;
// SH}
} else if(this.assistNodeIsInterface) {
//{ObjectTeams: different determination of class/interface for roles:
/* orig:
if(!memberType.isInterface() && !memberType.isAnnotationType()) continue next;
:giro */
if(!RoleModel.isInterface(memberType) && !memberType.isAnnotationType()) continue next;
// SH}
} else if (this.assistNodeIsAnnotation) {
if(!memberType.isAnnotationType()) continue next;
}
}
char[] completionName = memberType.sourceName();
boolean isQualified = false;
if(checkQualification && !fromStaticImport) {
char[] memberPackageName = memberType.qualifiedPackageName();
char[] memberTypeName = memberType.sourceName();
char[] memberEnclosingTypeNames = memberType.enclosingType().qualifiedSourceName();
if (mustQualifyType(memberPackageName, memberTypeName, memberEnclosingTypeNames, memberType.modifiers)) {
if (memberPackageName == null || memberPackageName.length == 0)
if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
break next; // ignore types from the default package from outside it
isQualified = true;
completionName =
CharOperation.concat(
memberPackageName,
CharOperation.concat(
memberEnclosingTypeNames,
memberTypeName,
'.'),
'.');
}
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal(memberType);
relevance += computeRelevanceForCaseMatching(typeName, memberType.sourceName);
relevance += computeRelevanceForExpectingType(memberType);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
if(!this.insideQualifiedReference) {
relevance += computeRelevanceForQualification(isQualified);
}
if (staticFieldsAndMethodOnly && this.insideQualifiedReference) relevance += R_NON_INHERITED; // This criterion doesn't concern types and is added to be balanced with field and method relevance.
if (memberType.isAnnotationType()) {
relevance += computeRelevanceForAnnotation();
relevance += computeRelevanceForAnnotationTarget(memberType);
} else if (memberType.isClass()) {
relevance += computeRelevanceForClass();
relevance += computeRelevanceForException(memberType.sourceName);
} else if(memberType.isEnum()) {
relevance += computeRelevanceForEnum();
} else if(memberType.isInterface()) {
relevance += computeRelevanceForInterface();
}
if (missingElements != null) {
relevance += computeRelevanceForMissingElements(missingElementsHaveProblems);
}
boolean allowingLongComputationProposals = isAllowingLongComputationProposals();
this.noProposal = false;
if (!this.assistNodeIsConstructor ||
!allowingLongComputationProposals ||
hasStaticMemberTypes(memberType, invocationType, this.unitScope) ||
(memberType instanceof SourceTypeBinding && hasMemberTypesInEnclosingScope((SourceTypeBinding)memberType, scope)) ||
hasArrayTypeAsExpectedSuperTypes()) {
createTypeProposal(
memberType,
memberType.qualifiedSourceName(),
IAccessRule.K_ACCESSIBLE,
completionName,
relevance,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems);
}
if (this.assistNodeIsConstructor && allowingLongComputationProposals) {
findConstructorsOrAnonymousTypes(
memberType,
scope,
FakeInvocationSite,
isQualified,
relevance);
}
}
}
private void findMemberTypesFromMissingType(
char[] typeName,
final long pos,
final Scope scope) {
MissingTypesGuesser missingTypesConverter = new MissingTypesGuesser(this);
MissingTypesGuesser.GuessedTypeRequestor substitutionRequestor =
new MissingTypesGuesser.GuessedTypeRequestor() {
@Override
public void accept(
TypeBinding guessedType,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean hasProblems) {
if (guessedType instanceof ReferenceBinding) {
findMemberTypes(
CompletionEngine.this.completionToken,
(ReferenceBinding)guessedType,
scope,
scope.enclosingSourceType(),
false,
false,
new ObjectVector(),
missingElements,
missingElementsStarts,
missingElementsEnds,
hasProblems);
}
}
};
SingleTypeReference typeRef = new SingleTypeReference(typeName, pos);
typeRef.resolvedType = new ProblemReferenceBinding(new char[][]{ typeName }, null, ProblemReasons.NotFound);
missingTypesConverter.guess(typeRef, scope, substitutionRequestor);
}
private void findMemberTypesFromMissingType(
TypeReference typeRef,
final long pos,
final Scope scope) {
MissingTypesGuesser missingTypesConverter = new MissingTypesGuesser(this);
MissingTypesGuesser.GuessedTypeRequestor substitutionRequestor =
new MissingTypesGuesser.GuessedTypeRequestor() {
@Override
public void accept(
TypeBinding guessedType,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean hasProblems) {
if (guessedType instanceof ReferenceBinding) {
findMemberTypes(
CompletionEngine.this.completionToken,
(ReferenceBinding)guessedType,
scope,
scope.enclosingSourceType(),
false,
false,
new ObjectVector(),
missingElements,
missingElementsStarts,
missingElementsEnds,
hasProblems);
}
}
};
missingTypesConverter.guess(typeRef, scope, substitutionRequestor);
}
private void findMethodDeclarations(
char[] selector,
ReferenceBinding receiverType,
Scope scope,
ObjectVector methodsFound,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems) {
if (selector == null) {
return;
}
MethodBinding[] receiverTypeMethods = receiverType.availableMethods();
if (receiverTypeMethods != null){
for (int i = 0; i < receiverTypeMethods.length; i++) {
if(!receiverTypeMethods[i].isDefaultAbstract()) {
//{ObjectTeams: filter out not-completable methods (including copy inherited versions):
if (canBeCompleted(receiverTypeMethods[i]))
//carp}
methodsFound.add(receiverTypeMethods[i]);
}
}
}
ReferenceBinding currentType = receiverType;
findInterfacesMethodDeclarations(
selector,
receiverType,
currentType.superInterfaces(),
scope,
methodsFound,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems);
if (receiverType.isInterface()) {
currentType = scope.getJavaLangObject();
} else {
currentType = receiverType.superclass();
}
boolean hasPotentialDefaultAbstractMethods = true;
boolean java8Plus = this.compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8;
while (currentType != null) {
MethodBinding[] methods = currentType.availableMethods();
if (methods != null) {
findLocalMethodDeclarations(
selector,
methods,
scope,
methodsFound,
false,
//{ObjectTeams: new param (normal behavior, callout declarations are handled by findMethods)
CompletionProposal.METHOD_DECLARATION,
// SH}
receiverType);
}
if (hasPotentialDefaultAbstractMethods && (java8Plus ||
(currentType.isAbstract() ||
currentType.isTypeVariable() ||
currentType.isIntersectionType() ||
currentType.isEnum()))){
ReferenceBinding[] superInterfaces = currentType.superInterfaces();
findInterfacesMethodDeclarations(
selector,
receiverType,
superInterfaces,
scope,
methodsFound,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems);
} else {
hasPotentialDefaultAbstractMethods = false;
}
currentType = currentType.superclass();
}
//{ObjectTeams: inferred callout declarations?
if (receiverType.isDirectRole()) {
inferCalloutDeclarations(selector,
receiverType,
scope,
methodsFound,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems);
}
// SH}
}
private char[][] findMethodParameterNames(MethodBinding method, char[][] parameterTypeNames){
//{ObjectTeams: added arg offset:
return findMethodParameterNames(method, /*parameterOffset*/0, parameterTypeNames);
}
private char[][] findMethodParameterNames(MethodBinding method, int parameterOffset, char[][] parameterTypeNames){
// SH}
TypeBinding erasure = method.declaringClass.erasure();
if(!(erasure instanceof ReferenceBinding)) return null;
char[][] parameterNames = null;
int length = parameterTypeNames.length;
if (length == 0){
return CharOperation.NO_CHAR_CHAR;
}
// look into the corresponding unit if it is available
if (erasure instanceof SourceTypeBinding){
SourceTypeBinding sourceType = (SourceTypeBinding) erasure;
if (sourceType.scope != null){
TypeDeclaration parsedType;
if ((parsedType = sourceType.scope.referenceContext) != null){
AbstractMethodDeclaration methodDecl = parsedType.declarationOf(method.original());
if (methodDecl != null){
Argument[] arguments = methodDecl.arguments;
parameterNames = new char[length][];
for(int i = 0 ; i < length ; i++){
//{ObjectTeams:
/* orig:
parameterNames[i] = arguments[i].name;
:giro */
parameterNames[i] = stripOTPrefix(arguments[i+parameterOffset].name);
// carp+SH}
}
}
}
}
}
// look into the model
if(parameterNames == null){
ReferenceBinding bindingType = (ReferenceBinding)erasure;
char[] compoundName = CharOperation.concatWith(bindingType.compoundName, '.');
Object type = this.typeCache.get(compoundName);
ISourceType sourceType = null;
if(type != null) {
if(type instanceof ISourceType) {
sourceType = (ISourceType) type;
}
} else {
NameEnvironmentAnswer answer = this.nameEnvironment.findTypeInModules(bindingType.compoundName, this.unitScope.module());
if(answer != null && answer.isSourceType()) {
sourceType = answer.getSourceTypes()[0];
this.typeCache.put(compoundName, sourceType);
}
}
if(sourceType != null) {
IType typeHandle = ((SourceTypeElementInfo) sourceType).getHandle();
String[] parameterTypeSignatures = new String[length];
for (int i = 0; i < length; i++) {
parameterTypeSignatures[i] = Signature.createTypeSignature(parameterTypeNames[i], false);
}
IMethod searchedMethod = typeHandle.getMethod(String.valueOf(method.selector), parameterTypeSignatures);
IMethod[] foundMethods = typeHandle.findMethods(searchedMethod);
if(foundMethods != null) {
int len = foundMethods.length;
if(len == 1) {
try {
SourceMethod sourceMethod = (SourceMethod) foundMethods[0];
parameterNames = ((SourceMethodElementInfo) sourceMethod.getElementInfo()).getArgumentNames();
} catch (JavaModelException e) {
// method doesn't exist: ignore
}
}
}
}
}
return parameterNames;
}
private void findMethods(
char[] selector,
TypeBinding[] typeArgTypes,
TypeBinding[] argTypes,
ReferenceBinding receiverType,
Scope scope,
ObjectVector methodsFound,
boolean onlyStaticMethods,
boolean exactMatch,
InvocationSite invocationSite,
Scope invocationScope,
boolean implicitCall,
boolean superCall,
boolean canBePrefixed,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems,
char[] castedReceiver,
int receiverStart,
int receiverEnd) {
//{ObjectTeams: delegate to method with extended signature:
findMethods(selector, typeArgTypes, argTypes, receiverType, scope, methodsFound,
onlyStaticMethods, exactMatch,
CompletionProposal.METHOD_REF, null,
invocationSite, invocationScope, implicitCall, superCall, canBePrefixed,
missingElements, missingElementsStarts, missingElementsEnds, missingElementsHaveProblems,
castedReceiver, receiverStart, receiverEnd);
}
private void findMethods(
char[] selector,
TypeBinding[] typeArgTypes,
TypeBinding[] argTypes,
ReferenceBinding receiverType,
Scope scope,
ObjectVector methodsFound,
boolean onlyStaticMethods,
boolean exactMatch,
//OT: RHS of callout/in (CompletionProposal.OT_METHOD_SPEC)
int kind,
TypeBinding expectedType, // use as a strict filter if non-null
//:TO
InvocationSite invocationSite,
Scope invocationScope,
boolean implicitCall,
boolean superCall,
boolean canBePrefixed,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems,
char[] castedReceiver,
int receiverStart,
int receiverEnd) {
// SH}
boolean notInJavadoc = this.assistNodeInJavadoc == 0;
if (selector == null && notInJavadoc) {
return;
}
if (this.assistNodeIsInsideCase)
return; // no methods should be proposed inside case expression
ReferenceBinding currentType = receiverType;
if (notInJavadoc) {
if (receiverType.isInterface()) {
findInterfacesMethods(
selector,
typeArgTypes,
argTypes,
receiverType,
new ReferenceBinding[]{currentType},
scope,
methodsFound,
onlyStaticMethods,
exactMatch,
invocationSite,
invocationScope,
implicitCall,
superCall,
canBePrefixed,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
castedReceiver,
receiverStart,
receiverEnd);
//{ObjectTeams: no super type Object for confined interfaces:
if (TypeAnalyzer.isConfined(currentType))
return;
// SH}
currentType = scope.getJavaLangObject();
}
}
boolean hasPotentialDefaultAbstractMethods = true;
boolean java8Plus = this.compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8;
while (currentType != null) {
//{ObjectTeams: don't let availableMethods() look in the interface part!
currentType = currentType.getRealClass();
// SH}
MethodBinding[] methods = currentType.availableMethods();
if (methods != null) {
findLocalMethods(
selector,
typeArgTypes,
argTypes,
methods,
scope,
methodsFound,
onlyStaticMethods,
exactMatch,
//{ObjectTeams: new args, pass through:
kind,
expectedType,
// SH}
receiverType,
invocationSite,
invocationScope,
implicitCall,
superCall,
canBePrefixed,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
castedReceiver,
receiverStart,
receiverEnd);
}
/* Searching of superinterfaces for candidate proposal methods can be skipped if current type is concrete, but only for source levels below 1.8.
For 1.8 even a concrete type's superinterfaces should be searched as they could have default methods which are not implemented by the concrete
type.
*/
if (hasPotentialDefaultAbstractMethods &&
(java8Plus || (currentType.isAbstract() || currentType.isTypeVariable() || currentType.isIntersectionType() || currentType.isEnum()))) {
ReferenceBinding[] superInterfaces = currentType.superInterfaces();
if (superInterfaces != null && currentType.isIntersectionType()) {
for (int i = 0; i < superInterfaces.length; i++) {
superInterfaces[i] = (ReferenceBinding)superInterfaces[i].capture(invocationScope, invocationSite.sourceStart(), invocationSite.sourceEnd());
}
}
findInterfacesMethods(
selector,
typeArgTypes,
argTypes,
receiverType,
superInterfaces,
scope,
methodsFound,
onlyStaticMethods,
exactMatch,
invocationSite,
invocationScope,
implicitCall,
superCall,
canBePrefixed,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
castedReceiver,
receiverStart,
receiverEnd);
} else {
if (!java8Plus)
hasPotentialDefaultAbstractMethods = false;
}
currentType = currentType.superclass();
}
//{ObjectTeams: inferred callout-calls?
if (receiverType.isDirectRole()) {
inferCallouts(selector,
typeArgTypes,
argTypes,
receiverType,
scope,
methodsFound,
onlyStaticMethods,
exactMatch,
kind,
expectedType,
invocationSite,
invocationScope,
implicitCall,
superCall,
canBePrefixed,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
castedReceiver,
receiverStart,
receiverEnd);
}
// SH}
}
private void findNestedTypes(
char[] typeName,
SourceTypeBinding currentType,
Scope scope,
boolean proposeAllMemberTypes,
ObjectVector typesFound) {
if (typeName == null)
return;
int typeLength = typeName.length;
SourceTypeBinding nextTypeToIgnore = null;
while (scope != null) { // done when a COMPILATION_UNIT_SCOPE is found
switch (scope.kind) {
case Scope.METHOD_SCOPE :
case Scope.BLOCK_SCOPE :
BlockScope blockScope = (BlockScope) scope;
next : for (int i = 0, length = blockScope.subscopeCount; i < length; i++) {
if (blockScope.subscopes[i] instanceof ClassScope) {
SourceTypeBinding localType =
((ClassScope) blockScope.subscopes[i]).referenceContext.binding;
if (!localType.isAnonymousType()) {
if (isForbidden(localType))
continue next;
if (typeLength > localType.sourceName.length)
continue next;
if (isFailedMatch(typeName, localType.sourceName))
continue next;
for (int j = typesFound.size; --j >= 0;) {
ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j);
if (TypeBinding.equalsEquals(localType, otherType))
continue next;
}
if (this.assistNodeIsExtendedType && localType.isFinal()) continue next;
if (this.assistNodeIsInterfaceExcludingAnnotation && localType.isAnnotationType()) continue next;
if(this.assistNodeIsClass) {
if(!localType.isClass()) continue next;
} else if(this.assistNodeIsInterface) {
if(!localType.isInterface() && !localType.isAnnotationType()) continue next;
} else if (this.assistNodeIsAnnotation) {
if(!localType.isAnnotationType()) continue next;
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal(localType);
relevance += computeRelevanceForCaseMatching(typeName, localType.sourceName);
relevance += computeRelevanceForExpectingType(localType);
relevance += computeRelevanceForException(localType.sourceName);
relevance += computeRelevanceForClass();
relevance += computeRelevanceForQualification(false);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for nested type
relevance += computeRelevanceForAnnotationTarget(localType);
boolean allowingLongComputationProposals = isAllowingLongComputationProposals();
if (!this.assistNodeIsConstructor || !allowingLongComputationProposals || hasArrayTypeAsExpectedSuperTypes()) {
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
createTypeProposal(
localType,
localType.sourceName,
IAccessRule.K_ACCESSIBLE,
localType.sourceName,
relevance,
null,
null,
null,
false);
}
}
if (this.assistNodeIsConstructor && allowingLongComputationProposals) {
findConstructorsOrAnonymousTypes(
localType,
blockScope,
FakeInvocationSite,
false,
relevance);
}
}
}
}
break;
case Scope.CLASS_SCOPE :
SourceTypeBinding enclosingSourceType = scope.enclosingSourceType();
findMemberTypes(
typeName,
enclosingSourceType,
scope,
currentType,
false,
false,
false,
false,
proposeAllMemberTypes,
nextTypeToIgnore,
typesFound,
null,
null,
null,
false);
nextTypeToIgnore = enclosingSourceType;
if (typeLength == 0)
return; // do not search outside the class scope if no prefix was provided
break;
case Scope.COMPILATION_UNIT_SCOPE :
return;
}
scope = scope.parent;
}
}
//{ObjectTeams: propose to override a role from the super team
private void findOverridableRoles(SourceTypeBinding enclosingType) {
if (!enclosingType.isTeam())
return;
ReferenceBinding superTeam = enclosingType.superclass();
if (!superTeam.isTeam())
return;
Set<String> knownRoles = new HashSet<String>();
// pre-load existing roles:
for (ReferenceBinding existingRole : enclosingType.memberTypes())
if (existingRole.roleModel != null && !existingRole.roleModel.isPurelyCopied()) // null if member is enum
knownRoles.add(String.valueOf(existingRole.internalName()));
// search direct super team:
findOverridableRolesFrom(superTeam, knownRoles);
// search tsuper-teams:
if (enclosingType.isRole())
for (ReferenceBinding tsuperTeam : enclosingType.roleModel.getTSuperRoleBindings())
findOverridableRolesFrom(tsuperTeam, knownRoles);
}
private void findOverridableRolesFrom(ReferenceBinding superTeam, Set<String> knownRoles)
{
int nameLength = this.completionToken.length;
ReferenceBinding[] superRoles = superTeam.memberTypes();
// inline roles:
for (int i = 0; i < superRoles.length; i++)
checkOverridableRole(superTeam, knownRoles, superRoles[i], nameLength);
// secondary types like the super team are inserted into compilation using the
// SourceTypeConverter, which doesn't know about role files.
// Thus we use the search engine (via IOTType.getRoleTypes) to find role files:
try {
IType superType = this.javaProject.findType(String.valueOf(superTeam.readableName()));
IOTType superTeamType = OTModelManager.getOTElement(superType);
if (superTeamType != null)
for (IType type : superTeamType.getRoleTypes(IOTType.ROLEFILE))
checkOverridableRole(superTeam, knownRoles, type, nameLength);
} catch (JavaModelException e) {
// ignore
}
}
private void checkOverridableRole(ReferenceBinding superTeam,
Set<String> knownRoles,
ReferenceBinding superRole,
int nameLength)
{
if (!superRole.isInterface())
return;
if (TypeAnalyzer.isTopConfined(superRole)) // can't override Confined/IConfined
return;
if (TSuperHelper.isMarkerInterface(superRole)) // invisible type
return;
char[] superRoleName = superRole.sourceName;
if (CharOperation.equals(superRoleName, IOTConstants.ILOWERABLE)) // not interesting to override
return;
if (this.completionToken.length > 0) {
if (this.completionToken.length > superRoleName.length)
return;
if (!CharOperation.prefixEquals(this.completionToken, superRoleName, false/* ignore case */)
&& !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(this.completionToken, superRoleName)))
return;
}
String roleName = String.valueOf(superRoleName);
if (!knownRoles.add(roleName))
return;
ReferenceBinding classPart = superRole.roleModel.getClassPartBinding();
int modifiers = classPart != null ? classPart.modifiers : superRole.modifiers;
createOverrideRoleProposal(superTeam, superRoleName, getSignature(superRole), modifiers);
}
// similar to above, version for IType:
private void checkOverridableRole(ReferenceBinding superTeam,
Set<String> knownRoles,
IType superRole,
int nameLength) throws JavaModelException
{
// don't check for interface, java model has no role-splitting
if (TypeHelper.isConfined(superRole)) // can't override Confined/IConfined
return;
if (TypeHelper.isMarkerInterface(superRole)) // invisible type
return;
char[] superRoleName = superRole.getElementName().toCharArray();
if (CharOperation.equals(superRoleName, IOTConstants.ILOWERABLE)) // not interesting to override
return;
if (this.completionToken.length > 0) {
if (this.completionToken.length > superRoleName.length)
return;
if (!CharOperation.prefixEquals(this.completionToken, superRoleName, false/* ignore case */)
&& !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(this.completionToken, superRoleName)))
return;
}
String roleName = String.valueOf(superRoleName);
if (!knownRoles.add(roleName))
return;
char[] roleTypeSignature = Signature.createTypeSignature(superRole.getFullyQualifiedName(), true/*resolved*/).toCharArray();
createOverrideRoleProposal(superTeam, superRoleName, roleTypeSignature, superRole.getFlags());
}
// SH}
private void proposeModuleName(CompilationUnitDeclaration parsedUnit) {
String projectName = this.javaProject.getElementName();
char[] moduleName = projectName.toCharArray();
if (moduleName.length > 0) {// do not propose invalid names
if (!Character.isJavaIdentifierStart(moduleName[0])) return;
for (char c : moduleName) {
if (!Character.isJavaIdentifierPart(c) && c != '.') return;
}
}
this.completionToken = CharOperation.concatWith(this.moduleDeclaration.tokens, '.');
setSourceRange(this.moduleDeclaration.sourceStart, this.moduleDeclaration.bodyStart);
if (this.completionToken.length > 0 && !CharOperation.prefixEquals(this.completionToken, moduleName)) return;
InternalCompletionProposal proposal = createProposal(CompletionProposal.MODULE_DECLARATION, this.actualCompletionPosition);
proposal.setName(moduleName);
proposal.setDeclarationSignature(moduleName);
proposal.setCompletion(moduleName);
proposal.setReplaceRange((this.startPosition < 0) ? 0 : this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange((this.tokenStart < 0) ? 0 : this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(R_MODULE_DECLARATION);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
private HashSet<String> getAllJarModuleNames(IJavaProject javaProject2) {
HashSet<String> modules = new HashSet<>();
try {
for (IPackageFragmentRoot root : javaProject2.getAllPackageFragmentRoots()) {
if (root instanceof JarPackageFragmentRoot) {
IModuleDescription desc = root.getModuleDescription();
desc = desc == null ? ((JarPackageFragmentRoot) root).getAutomaticModuleDescription() : desc;
String name = desc != null ? desc.getElementName() : null;
if (name != null && name.length() > 0)
modules.add(name);
}
}
} catch (JavaModelException e) {
// do nothing
}
return modules;
}
private void findTargettedModules(char[] prefix, HashSet<String> skipSet) {
HashSet<String> probableModules = new HashSet<>();
ModuleSourcePathManager mManager = JavaModelManager.getModulePathManager();
JavaElementRequestor javaElementRequestor = new JavaElementRequestor();
try {
mManager.seekModule(this.completionToken, true, javaElementRequestor);
IModuleDescription[] modules = javaElementRequestor.getModules();
for (IModuleDescription module : modules) {
String name = module.getElementName();
if (name == null || name.equals("")) //$NON-NLS-1$
continue;
probableModules.add(name);
}
} catch (JavaModelException e) {
// TODO ignore for now
}
probableModules.addAll(getAllJarModuleNames(this.javaProject));
if (prefix != CharOperation.ALL_PREFIX && prefix != null && prefix.length > 0) {
probableModules.removeIf(e -> isFailedMatch(prefix, e.toCharArray()));
}
for (String s : probableModules) {
if (!skipSet.contains(s))
this.acceptModule(s.toCharArray());
}
}
private void findTargettedModules(CompletionOnModuleReference moduleReference, HashSet<String> skipSet) {
setCompletionToken(moduleReference.tokens, moduleReference.sourceStart, moduleReference.sourceEnd, moduleReference.sourcePositions);
findTargettedModules(CharOperation.toLowerCase(this.completionToken), skipSet);
}
private void setCompletionToken(char[][] tokens, int sourceStart, int sourceEnd, long[] sourcePositions, boolean without) {
this.completionToken = without ? CharOperation.concatWith(tokens, '.') : CharOperation.concatWithAll(tokens, '.');
if (this.completionToken.length == 0)
this.completionToken = CharOperation.ALL_PREFIX;
setSourceRange(sourceStart, sourceEnd);
long completionPosition = sourcePositions[sourcePositions.length - 1];
setTokenRange((int) (completionPosition >>> 32), (int) completionPosition);
}
private void setCompletionToken(char[][] tokens, int sourceStart, int sourceEnd, long[] sourcePositions) {
setCompletionToken(tokens, sourceStart, sourceEnd, sourcePositions, tokens.length > 0 && tokens[tokens.length - 1].length > 0);
}
private void findModules(CompletionOnModuleReference moduleReference, boolean targetted) {
setCompletionToken(moduleReference.tokens, moduleReference.sourceStart, moduleReference.sourceEnd, moduleReference.sourcePositions);
findTargettedModules(moduleReference, new HashSet<>()); // empty skipSet passed
this.nameEnvironment.findModules(CharOperation.toLowerCase(this.completionToken), this, targetted ? this.javaProject : null);
}
private void findPackages(CompletionOnPackageVisibilityReference reference) {
setCompletionToken(reference.tokens, reference.sourceStart, reference.sourceEnd, reference.sourcePositions, false);
findPackagesInCurrentModule();
}
private void findPackagesInCurrentModule() {
try {
IPackageFragmentRoot[] moduleRoots = SearchableEnvironment.getOwnedPackageFragmentRoots(this.javaProject);
this.nameEnvironment.findPackages(CharOperation.toLowerCase(this.completionToken), this, moduleRoots, false);
} catch (JavaModelException e) {
// silent
}
}
private void findPackages(CompletionOnPackageReference packageStatement) {
this.completionToken = CharOperation.concatWithAll(packageStatement.tokens, '.');
if (this.completionToken.length == 0)
return;
setSourceRange(packageStatement.sourceStart, packageStatement.sourceEnd);
long completionPosition = packageStatement.sourcePositions[packageStatement.sourcePositions.length - 1];
setTokenRange((int) (completionPosition >>> 32), (int) completionPosition);
try {
this.nameEnvironment.findPackages(CharOperation.toLowerCase(this.completionToken), this, this.javaProject.getAllPackageFragmentRoots(), true);
} catch (JavaModelException e) {
// silent
}
}
private void findParameterizedType(TypeReference ref, Scope scope) {
ReferenceBinding refBinding = (ReferenceBinding) ref.resolvedType;
if(refBinding != null) {
if (this.options.checkDeprecation &&
refBinding.isViewedAsDeprecated() &&
!scope.isDefinedInSameUnit(refBinding))
return;
int accessibility = IAccessRule.K_ACCESSIBLE;
if(refBinding.hasRestrictedAccess()) {
AccessRestriction accessRestriction = this.lookupEnvironment.getAccessRestriction(refBinding);
if(accessRestriction != null) {
switch (accessRestriction.getProblemId()) {
case IProblem.ForbiddenReference:
if (this.options.checkForbiddenReference) {
return;
}
accessibility = IAccessRule.K_NON_ACCESSIBLE;
break;
case IProblem.DiscouragedReference:
if (this.options.checkDiscouragedReference) {
return;
}
accessibility = IAccessRule.K_DISCOURAGED;
break;
}
}
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(refBinding.sourceName, refBinding.sourceName);
relevance += computeRelevanceForExpectingType(refBinding);
relevance += computeRelevanceForQualification(false);
relevance += computeRelevanceForRestrictions(accessibility); // no access restriction for type in the current unit
if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
createTypeProposal(
refBinding,
refBinding.qualifiedSourceName(),
IAccessRule.K_ACCESSIBLE,
CharOperation.NO_CHAR,
relevance,
null,
null,
null,
false);
}
}
}
private void findSubMemberTypes(
char[] typeName,
ReferenceBinding receiverType,
Scope scope,
SourceTypeBinding typeInvocation,
boolean staticOnly,
boolean staticFieldsAndMethodOnly,
boolean fromStaticImport,
ObjectVector typesFound) {
ReferenceBinding currentType = receiverType;
if (typeName == null)
return;
if (this.assistNodeIsSuperType && !this.insideQualifiedReference && isForbidden(currentType)) return; // we're trying to find a supertype
findMemberTypes(
typeName,
currentType.memberTypes(),
typesFound,
receiverType,
typeInvocation,
staticOnly,
staticFieldsAndMethodOnly,
fromStaticImport,
true,
scope,
null,
null,
null,
false);
ReferenceBinding[] memberTypes = receiverType.memberTypes();
next : for (int i = 0; i < memberTypes.length; i++) {
if (this.options.checkVisibility) {
if (typeInvocation != null && !memberTypes[i].canBeSeenBy(receiverType, typeInvocation)) {
continue next;
} else if(typeInvocation == null && !memberTypes[i].canBeSeenBy(this.unitScope.fPackage)) {
continue next;
}
}
findSubMemberTypes(
typeName,
memberTypes[i],
scope,
typeInvocation,
staticOnly,
staticFieldsAndMethodOnly,
fromStaticImport,
typesFound);
}
}
private void findTrueOrFalseKeywords(char[][] choices) {
if(choices == null || choices.length == 0) return;
if(this.expectedTypesPtr != 0 || TypeBinding.notEquals(this.expectedTypes[0], TypeBinding.BOOLEAN)) return;
for (int i = 0; i < choices.length; i++) {
if (CharOperation.equals(choices[i], Keywords.TRUE) ||
CharOperation.equals(choices[i], Keywords.FALSE)
){
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(CharOperation.NO_CHAR, choices[i]);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors
relevance += computeRelevanceForExpectingType(TypeBinding.BOOLEAN);
relevance += computeRelevanceForQualification(false);
relevance += R_TRUE_OR_FALSE;
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.KEYWORD, this.actualCompletionPosition);
proposal.setName(choices[i]);
proposal.setCompletion(choices[i]);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
}
}
private void findTypeParameters(char[] token, Scope scope) {
if (this.compilerOptions.sourceLevel < ClassFileConstants.JDK1_5) return;
TypeParameter[] typeParameters = null;
while (scope != null) { // done when a COMPILATION_UNIT_SCOPE is found
typeParameters = null;
switch (scope.kind) {
case Scope.METHOD_SCOPE :
MethodScope methodScope = (MethodScope) scope;
if(methodScope.referenceContext instanceof MethodDeclaration) {
MethodDeclaration methodDeclaration = (MethodDeclaration) methodScope.referenceContext;
typeParameters = methodDeclaration.typeParameters;
} else if(methodScope.referenceContext instanceof ConstructorDeclaration) {
ConstructorDeclaration methodDeclaration = (ConstructorDeclaration) methodScope.referenceContext;
typeParameters = methodDeclaration.typeParameters;
}
break;
case Scope.CLASS_SCOPE :
ClassScope classScope = (ClassScope) scope;
typeParameters = classScope.referenceContext.typeParameters;
break;
case Scope.COMPILATION_UNIT_SCOPE :
return;
}
if(typeParameters != null) {
for (int i = 0; i < typeParameters.length; i++) {
int typeLength = token.length;
TypeParameter typeParameter = typeParameters[i];
if(typeParameter.binding == null) continue;
if (typeLength > typeParameter.name.length) continue;
if (isFailedMatch(token, typeParameter.name)) continue;
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(token, typeParameter.name);
relevance += computeRelevanceForExpectingType(typeParameter.type == null ? null :typeParameter.type.resolvedType);
relevance += computeRelevanceForQualification(false);
relevance += computeRelevanceForException(typeParameter.name);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction fot type parameter
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
createTypeParameterProposal(typeParameter, relevance);
}
}
}
scope = scope.parent;
}
}
private void findTypesAndPackages(char[] token, Scope scope, boolean proposeBaseTypes, boolean proposeVoidType, ObjectVector typesFound) {
if (token == null)
return;
boolean allowingLongComputationProposals = isAllowingLongComputationProposals();
boolean proposeType =
!this.requestor.isIgnored(CompletionProposal.TYPE_REF) ||
((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF));
boolean proposeAllMemberTypes = !this.assistNodeIsConstructor;
boolean proposeConstructor =
allowingLongComputationProposals &&
this.assistNodeIsConstructor &&
(!isIgnored(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF) ||
!isIgnored(CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF));
if ((proposeType || proposeConstructor) && scope.enclosingSourceType() != null) {
checkCancel();
findNestedTypes(token, scope.enclosingSourceType(), scope, proposeAllMemberTypes, typesFound);
if(!this.assistNodeIsInterface &&
!this.assistNodeIsConstructor &&
!this.assistNodeIsAnnotation &&
this.assistNodeInJavadoc == 0) {
checkCancel();
// don't propose type parameters if the completion is a constructor ('new |')
findTypeParameters(token, scope);
}
}
//{ObjectTeams: for @role tags nested types was all we care for:
if ((this.assistNodeInJavadoc & CompletionOnJavadoc.ROLE) != 0)
return;
// similar for the role side in a lifting type declaration:
if (this.parser.assistNode instanceof CompletionOnSingleTypeReference
&& ((CompletionOnSingleTypeReference)this.parser.assistNode).isLiftingRoleType)
return;
// SH}
boolean isEmptyPrefix = token.length == 0;
if ((proposeType || proposeConstructor) && this.unitScope != null) {
ReferenceBinding outerInvocationType = scope.enclosingSourceType();
if(outerInvocationType != null) {
ReferenceBinding temp = outerInvocationType.enclosingType();
while(temp != null) {
outerInvocationType = temp;
temp = temp.enclosingType();
}
}
int typeLength = token.length;
SourceTypeBinding[] types = this.unitScope.topLevelTypes;
next : for (int i = 0, length = types.length; i < length; i++) {
checkCancel();
SourceTypeBinding sourceType = types[i];
if(isForbidden(sourceType)) continue next;
if(proposeAllMemberTypes &&
TypeBinding.notEquals(sourceType, outerInvocationType)) {
findSubMemberTypes(
token,
sourceType,
scope,
scope.enclosingSourceType(),
false,
false,
false,
typesFound);
}
if (sourceType.sourceName == CompletionParser.FAKE_TYPE_NAME) continue next;
if (sourceType.sourceName == TypeConstants.PACKAGE_INFO_NAME) continue next;
if (typeLength > sourceType.sourceName.length) continue next;
if (isFailedMatch(token, sourceType.sourceName)) continue next;
if (this.assistNodeIsAnnotation && !hasPossibleAnnotationTarget(sourceType, scope)) {
continue next;
}
for (int j = typesFound.size; --j >= 0;) {
ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j);
if (TypeBinding.equalsEquals(sourceType, otherType)) continue next;
}
typesFound.add(sourceType);
if (this.assistNodeIsExtendedType && sourceType.isFinal()) continue next;
if (this.assistNodeIsInterfaceExcludingAnnotation && sourceType.isAnnotationType()) continue next;
if(this.assistNodeIsClass) {
if(!sourceType.isClass()) continue next;
} else if(this.assistNodeIsInterface) {
if(!sourceType.isInterface() && !sourceType.isAnnotationType()) continue next;
} else if (this.assistNodeIsAnnotation) {
if(!sourceType.isAnnotationType()) continue next;
} else if (this.assistNodeIsException) {
if (!sourceType.isClass()) continue next;
if (isEmptyPrefix) {
if (sourceType.findSuperTypeOriginatingFrom(TypeIds.T_JavaLangThrowable, true) == null) {
continue next;
}
}
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal(sourceType);
relevance += computeRelevanceForCaseMatching(token, sourceType.sourceName);
relevance += computeRelevanceForExpectingType(sourceType);
relevance += computeRelevanceForQualification(false);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for type in the current unit
if (sourceType.isAnnotationType()) {
relevance += computeRelevanceForAnnotation();
relevance += computeRelevanceForAnnotationTarget(sourceType);
} else if (sourceType.isInterface()) {
relevance += computeRelevanceForInterface();
} else if(sourceType.isClass()){
relevance += computeRelevanceForClass();
relevance += computeRelevanceForException(sourceType.sourceName);
}
this.noProposal = false;
if(proposeType &&
(!this.assistNodeIsConstructor ||
!allowingLongComputationProposals ||
hasStaticMemberTypes(sourceType, null, this.unitScope) ||
hasMemberTypesInEnclosingScope(sourceType, scope)) ||
hasArrayTypeAsExpectedSuperTypes()) {
char[] typeName = sourceType.sourceName();
createTypeProposal(
sourceType,
typeName,
IAccessRule.K_ACCESSIBLE,
typeName,
relevance,
null,
null,
null,
false);
}
if (proposeConstructor) {
findConstructorsOrAnonymousTypes(
sourceType,
scope,
FakeInvocationSite,
false,
relevance);
}
}
}
if (proposeConstructor && !isEmptyPrefix) {
checkCancel();
findTypesFromImports(token, scope, proposeType, typesFound);
} else if(proposeType) {
checkCancel();
findTypesFromStaticImports(token, scope, proposeAllMemberTypes, typesFound);
}
if (proposeConstructor) {
checkCancel();
findTypesFromExpectedTypes(token, scope, typesFound, proposeType, proposeConstructor);
}
if (isEmptyPrefix && !this.assistNodeIsAnnotation) {
if (!proposeConstructor) {
findTypesFromExpectedTypes(token, scope, typesFound, proposeType, proposeConstructor);
}
} else {
if(!isEmptyPrefix && !this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
if (this.assistNodeInJavadoc == 0 || (this.assistNodeInJavadoc & CompletionOnJavadoc.BASE_TYPES) != 0) {
if (proposeBaseTypes) {
if (proposeVoidType) {
findKeywords(token, BASE_TYPE_NAMES, false, false);
} else {
findKeywords(token, BASE_TYPE_NAMES_WITHOUT_VOID, false, false);
}
}
}
}
if (proposeConstructor) {
int l = typesFound.size();
for (int i = 0; i < l; i++) {
ReferenceBinding typeFound = (ReferenceBinding) typesFound.elementAt(i);
char[] fullyQualifiedTypeName =
CharOperation.concat(
typeFound.qualifiedPackageName(),
typeFound.qualifiedSourceName(),
'.');
this.knownTypes.put(fullyQualifiedTypeName, KNOWN_TYPE_WITH_KNOWN_CONSTRUCTORS);
}
checkCancel();
this.foundConstructorsCount = 0;
this.nameEnvironment.findConstructorDeclarations(
token,
this.options.camelCaseMatch,
this,
this.monitor);
acceptConstructors(scope);
} else if (proposeType) {
int l = typesFound.size();
for (int i = 0; i < l; i++) {
ReferenceBinding typeFound = (ReferenceBinding) typesFound.elementAt(i);
char[] fullyQualifiedTypeName =
CharOperation.concat(
typeFound.qualifiedPackageName(),
typeFound.qualifiedSourceName(),
'.');
this.knownTypes.put(fullyQualifiedTypeName, KNOWN_TYPE_WITH_KNOWN_CONSTRUCTORS);
}
int searchFor = IJavaSearchConstants.TYPE;
if(this.assistNodeIsClass || this.assistNodeIsException) {
searchFor = IJavaSearchConstants.CLASS;
} else if (this.assistNodeIsInterfaceExcludingAnnotation) {
searchFor = IJavaSearchConstants.INTERFACE;
} else if(this.assistNodeIsInterface) {
searchFor = IJavaSearchConstants.INTERFACE_AND_ANNOTATION;
} else if(this.assistNodeIsEnum) {
searchFor = IJavaSearchConstants.ENUM;
} else if(this.assistNodeIsAnnotation) {
searchFor = IJavaSearchConstants.ANNOTATION_TYPE;
}
checkCancel();
this.foundTypesCount = 0;
this.nameEnvironment.findTypes(
token,
proposeAllMemberTypes,
this.options.camelCaseMatch,
searchFor,
this,
this.monitor);
acceptTypes(scope);
}
if(!isEmptyPrefix && !this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
checkCancel();
this.nameEnvironment.findPackages(token, this);
}
}
}
private void findTypesAndSubpackages(
char[] token,
PackageBinding packageBinding,
Scope scope) {
boolean allowingLongComputationProposals = isAllowingLongComputationProposals();
boolean proposeType =
!this.requestor.isIgnored(CompletionProposal.TYPE_REF) ||
((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF));
boolean proposeConstructor =
allowingLongComputationProposals &&
this.assistNodeIsConstructor &&
(!isIgnored(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF) ||
!isIgnored(CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF));
char[] qualifiedName =
CharOperation.concatWith(packageBinding.compoundName, token, '.');
if (token == null || token.length == 0) {
int length = qualifiedName.length;
System.arraycopy(
qualifiedName,
0,
qualifiedName = new char[length + 1],
0,
length);
qualifiedName[length] = '.';
}
this.qualifiedCompletionToken = qualifiedName;
if ((proposeType || proposeConstructor) && this.unitScope != null) {
int typeLength = qualifiedName.length;
SourceTypeBinding[] types = this.unitScope.topLevelTypes;
for (int i = 0, length = types.length; i < length; i++) {
checkCancel();
SourceTypeBinding sourceType = types[i];
if (isForbidden(sourceType)) continue;
if (this.assistNodeIsClass && sourceType.isInterface()) continue;
if (this.assistNodeIsInterface && sourceType.isClass()) continue;
char[] qualifiedSourceTypeName = CharOperation.concatWith(sourceType.compoundName, '.');
if (sourceType.sourceName == CompletionParser.FAKE_TYPE_NAME) continue;
if (sourceType.sourceName == TypeConstants.PACKAGE_INFO_NAME) continue;
if (typeLength > qualifiedSourceTypeName.length) continue;
if (!(packageBinding == sourceType.getPackage())) continue;
if (!CharOperation.prefixEquals(qualifiedName, qualifiedSourceTypeName, false)
&& !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, sourceType.sourceName))) continue;
if (this.options.checkDeprecation &&
sourceType.isViewedAsDeprecated() &&
!scope.isDefinedInSameUnit(sourceType))
continue;
if (this.assistNodeIsExtendedType && sourceType.isFinal()) continue;
if (this.assistNodeIsInterfaceExcludingAnnotation && sourceType.isAnnotationType()) continue;
int accessibility = IAccessRule.K_ACCESSIBLE;
if(sourceType.hasRestrictedAccess()) {
AccessRestriction accessRestriction = this.lookupEnvironment.getAccessRestriction(sourceType);
if(accessRestriction != null) {
switch (accessRestriction.getProblemId()) {
case IProblem.ForbiddenReference:
if (this.options.checkForbiddenReference) {
continue;
}
accessibility = IAccessRule.K_NON_ACCESSIBLE;
break;
case IProblem.DiscouragedReference:
if (this.options.checkDiscouragedReference) {
continue;
}
accessibility = IAccessRule.K_DISCOURAGED;
break;
}
}
}
this.knownTypes.put(CharOperation.concat(sourceType.qualifiedPackageName(), sourceType.sourceName(), '.'), KNOWN_TYPE_WITH_KNOWN_CONSTRUCTORS);
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal(sourceType);
relevance += computeRelevanceForCaseMatching(qualifiedName, qualifiedSourceTypeName);
relevance += computeRelevanceForExpectingType(sourceType);
relevance += computeRelevanceForQualification(false);
relevance += computeRelevanceForRestrictions(accessibility);
if (sourceType.isAnnotationType()) {
relevance += computeRelevanceForAnnotation();
} else if (sourceType.isInterface()) {
relevance += computeRelevanceForInterface();
} else if (sourceType.isClass()) {
relevance += computeRelevanceForClass();
relevance += computeRelevanceForException(sourceType.sourceName);
}
this.noProposal = false;
if(proposeType &&
(!this.assistNodeIsConstructor ||
!allowingLongComputationProposals ||
hasStaticMemberTypes(sourceType, null, this.unitScope) ||
hasMemberTypesInEnclosingScope(sourceType, scope)) ||
hasArrayTypeAsExpectedSuperTypes()) {
char[] typeName = sourceType.sourceName();
createTypeProposal(
sourceType,
typeName,
IAccessRule.K_ACCESSIBLE,
typeName,
relevance,
null,
null,
null,
false);
}
if (proposeConstructor) {
findConstructorsOrAnonymousTypes(
sourceType,
scope,
FakeInvocationSite,
false,
relevance);
}
}
}
if (proposeConstructor) {
checkCancel();
this.foundConstructorsCount = 0;
this.nameEnvironment.findConstructorDeclarations(
qualifiedName,
this.options.camelCaseMatch,
this,
this.monitor);
acceptConstructors(scope);
} if(proposeType) {
int searchFor = IJavaSearchConstants.TYPE;
if(this.assistNodeIsClass) {
searchFor = IJavaSearchConstants.CLASS;
} else if (this.assistNodeIsInterfaceExcludingAnnotation) {
searchFor = IJavaSearchConstants.INTERFACE;
} else if(this.assistNodeIsInterface) {
searchFor = IJavaSearchConstants.INTERFACE_AND_ANNOTATION;
} else if(this.assistNodeIsEnum) {
searchFor = IJavaSearchConstants.ENUM;
} else if(this.assistNodeIsAnnotation) {
searchFor = IJavaSearchConstants.ANNOTATION_TYPE;
}
checkCancel();
this.foundTypesCount = 0;
this.nameEnvironment.findTypes(
qualifiedName,
false,
this.options.camelCaseMatch,
searchFor,
this,
this.monitor);
acceptTypes(scope);
}
if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
this.nameEnvironment.findPackages(qualifiedName, this);
}
}
private void findTypesFromExpectedTypes(char[] token, Scope scope, ObjectVector typesFound, boolean proposeType, boolean proposeConstructor) {
if(this.expectedTypesPtr > -1) {
boolean allowingLongComputationProposals = isAllowingLongComputationProposals();
int typeLength = token == null ? 0 : token.length;
next : for (int i = 0; i <= this.expectedTypesPtr; i++) {
checkCancel();
if(this.expectedTypes[i] instanceof ReferenceBinding) {
ReferenceBinding refBinding = (ReferenceBinding)this.expectedTypes[i];
if (typeLength > 0) {
if (typeLength > refBinding.sourceName.length) continue next;
if (isFailedMatch(token, refBinding.sourceName)) continue next;
}
if(refBinding.isTypeVariable() && this.assistNodeIsConstructor) {
// don't propose type variable if the completion is a constructor ('new |')
continue next;
}
if (this.options.checkDeprecation &&
refBinding.isViewedAsDeprecated() &&
!scope.isDefinedInSameUnit(refBinding))
continue next;
int accessibility = IAccessRule.K_ACCESSIBLE;
if(refBinding.hasRestrictedAccess()) {
AccessRestriction accessRestriction = this.lookupEnvironment.getAccessRestriction(refBinding);
if(accessRestriction != null) {
switch (accessRestriction.getProblemId()) {
case IProblem.ForbiddenReference:
if (this.options.checkForbiddenReference) {
continue next;
}
accessibility = IAccessRule.K_NON_ACCESSIBLE;
break;
case IProblem.DiscouragedReference:
if (this.options.checkDiscouragedReference) {
continue next;
}
accessibility = IAccessRule.K_DISCOURAGED;
break;
}
}
}
if(isForbidden(refBinding)) continue next;
for (int j = 0; j < typesFound.size(); j++) {
ReferenceBinding typeFound = (ReferenceBinding)typesFound.elementAt(j);
if (TypeBinding.equalsEquals(typeFound, refBinding.erasure())) {
continue next;
}
}
typesFound.add(refBinding);
boolean inSameUnit = this.unitScope.isDefinedInSameUnit(refBinding);
// top level types of the current unit are already proposed.
if(!inSameUnit || (inSameUnit && refBinding.isMemberType())) {
char[] packageName = refBinding.qualifiedPackageName();
char[] typeName = refBinding.sourceName();
char[] completionName = typeName;
boolean isQualified = false;
if (!this.insideQualifiedReference && !refBinding.isMemberType()) {
if (mustQualifyType(packageName, typeName, null, refBinding.modifiers)) {
if (packageName == null || packageName.length == 0)
if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
continue next; // ignore types from the default package from outside it
completionName = CharOperation.concat(packageName, typeName, '.');
isQualified = true;
}
}
if (this.assistNodeIsExtendedType && refBinding.isFinal()) continue next;
if (this.assistNodeIsInterfaceExcludingAnnotation && refBinding.isAnnotationType()) continue next;
if(this.assistNodeIsClass) {
if(!refBinding.isClass()) continue next;
} else if(this.assistNodeIsInterface) {
if(!refBinding.isInterface() && !refBinding.isAnnotationType()) continue next;
} else if (this.assistNodeIsAnnotation) {
if(!refBinding.isAnnotationType()) continue next;
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal(refBinding);
relevance += computeRelevanceForCaseMatching(token, typeName);
relevance += computeRelevanceForExpectingType(refBinding);
relevance += computeRelevanceForQualification(isQualified);
relevance += computeRelevanceForRestrictions(accessibility);
if(refBinding.isClass()) {
relevance += computeRelevanceForClass();
relevance += computeRelevanceForException(typeName);
} else if(refBinding.isEnum()) {
relevance += computeRelevanceForEnum();
} else if(refBinding.isInterface()) {
relevance += computeRelevanceForInterface();
}
if (proposeType &&
(!this.assistNodeIsConstructor ||
!allowingLongComputationProposals ||
hasStaticMemberTypes(refBinding, scope.enclosingSourceType() ,this.unitScope)) ||
hasArrayTypeAsExpectedSuperTypes()) {
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
proposal.setDeclarationSignature(packageName);
proposal.setSignature(getSignature(refBinding));
proposal.setPackageName(packageName);
proposal.setTypeName(typeName);
proposal.setCompletion(completionName);
proposal.setFlags(refBinding.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
proposal.setAccessibility(accessibility);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
if (proposeConstructor) {
findConstructorsOrAnonymousTypes(
refBinding,
scope,
FakeInvocationSite,
isQualified,
relevance);
}
}
}
}
}
}
private void findTypesFromImports(char[] token, Scope scope, boolean proposeType, ObjectVector typesFound) {
ImportBinding[] importBindings = scope.compilationUnitScope().imports;
next : for (int i = 0; i < importBindings.length; i++) {
ImportBinding importBinding = importBindings[i];
if(importBinding.isValidBinding()) {
Binding binding = importBinding.resolvedImport;
if(binding != null && binding.isValidBinding()) {
if(importBinding.onDemand) {
if (importBinding.isStatic()) {
if((binding.kind() & Binding.TYPE) != 0) {
this.findMemberTypes(
token,
(ReferenceBinding) binding,
scope,
scope.enclosingSourceType(),
true,
false,
true,
true,
false,
null,
typesFound,
null,
null,
null,
false);
}
}
} else {
if ((binding.kind() & Binding.TYPE) != 0) {
ReferenceBinding typeBinding = (ReferenceBinding) binding;
int typeLength = token.length;
if (!typeBinding.isStatic()) continue next;
if (typeLength > typeBinding.sourceName.length) continue next;
if (isFailedMatch(token, typeBinding.sourceName)) continue next;
int accessibility = IAccessRule.K_ACCESSIBLE;
if(typeBinding.hasRestrictedAccess()) {
AccessRestriction accessRestriction = this.lookupEnvironment.getAccessRestriction(typeBinding);
if(accessRestriction != null) {
switch (accessRestriction.getProblemId()) {
case IProblem.ForbiddenReference:
if (this.options.checkForbiddenReference) {
continue next;
}
accessibility = IAccessRule.K_NON_ACCESSIBLE;
break;
case IProblem.DiscouragedReference:
if (this.options.checkDiscouragedReference) {
continue next;
}
accessibility = IAccessRule.K_DISCOURAGED;
break;
}
}
}
if (typesFound.contains(typeBinding)) continue next;
typesFound.add(typeBinding);
if (this.assistNodeIsExtendedType && typeBinding.isFinal()) continue;
if (this.assistNodeIsInterfaceExcludingAnnotation && typeBinding.isAnnotationType()) continue;
if(this.assistNodeIsClass) {
if(!typeBinding.isClass()) continue;
} else if(this.assistNodeIsInterface) {
if(!typeBinding.isInterface() && !typeBinding.isAnnotationType()) continue;
} else if (this.assistNodeIsAnnotation) {
if(!typeBinding.isAnnotationType()) continue;
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal(typeBinding);
relevance += computeRelevanceForCaseMatching(token, typeBinding.sourceName);
relevance += computeRelevanceForExpectingType(typeBinding);
relevance += computeRelevanceForQualification(false);
relevance += computeRelevanceForRestrictions(accessibility);
if (typeBinding.isAnnotationType()) {
relevance += computeRelevanceForAnnotation();
relevance += computeRelevanceForAnnotationTarget(typeBinding);
} else if (typeBinding.isInterface()) {
relevance += computeRelevanceForInterface();
} else if(typeBinding.isClass()){
relevance += computeRelevanceForClass();
relevance += computeRelevanceForException(typeBinding.sourceName);
}
if (proposeType &&
(hasStaticMemberTypes(typeBinding, scope.enclosingSourceType(), this.unitScope) || hasArrayTypeAsExpectedSuperTypes())) {
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
proposal.setDeclarationSignature(typeBinding.qualifiedPackageName());
proposal.setSignature(getSignature(typeBinding));
proposal.setPackageName(typeBinding.qualifiedPackageName());
proposal.setTypeName(typeBinding.qualifiedSourceName());
proposal.setCompletion(typeBinding.sourceName());
proposal.setFlags(typeBinding.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
findConstructorsOrAnonymousTypes(
typeBinding,
scope,
FakeInvocationSite,
false,
relevance);
}
}
}
}
}
}
private void findTypesFromStaticImports(char[] token, Scope scope, boolean proposeAllMemberTypes, ObjectVector typesFound) {
ImportBinding[] importBindings = scope.compilationUnitScope().imports;
if (importBindings == null) return;
for (int i = 0; i < importBindings.length; i++) {
ImportBinding importBinding = importBindings[i];
if(importBinding.isValidBinding() && importBinding.isStatic()) {
Binding binding = importBinding.resolvedImport;
if(binding != null && binding.isValidBinding()) {
if(importBinding.onDemand) {
if((binding.kind() & Binding.TYPE) != 0) {
this.findMemberTypes(
token,
(ReferenceBinding) binding,
scope,
scope.enclosingSourceType(),
true,
false,
true,
true,
proposeAllMemberTypes,
null,
typesFound,
null,
null,
null,
false);
}
} else {
if ((binding.kind() & Binding.TYPE) != 0) {
ReferenceBinding typeBinding = (ReferenceBinding) binding;
int typeLength = token.length;
if (!typeBinding.isStatic()) continue;
if (typeLength > typeBinding.sourceName.length) continue;
if (isFailedMatch(token, typeBinding.sourceName)) continue;
if (typesFound.contains(typeBinding)) continue;
typesFound.add(typeBinding);
if (this.assistNodeIsExtendedType && typeBinding.isFinal()) continue;
if (this.assistNodeIsInterfaceExcludingAnnotation && typeBinding.isAnnotationType()) continue;
if(this.assistNodeIsClass || this.assistNodeIsException) {
if(!typeBinding.isClass()) continue;
} else if(this.assistNodeIsInterface) {
if(!typeBinding.isInterface() && !typeBinding.isAnnotationType()) continue;
} else if (this.assistNodeIsAnnotation) {
if(!typeBinding.isAnnotationType()) continue;
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal(typeBinding);
relevance += computeRelevanceForCaseMatching(token, typeBinding.sourceName);
relevance += computeRelevanceForExpectingType(typeBinding);
relevance += computeRelevanceForQualification(false);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
if (typeBinding.isClass()) {
relevance += computeRelevanceForClass();
relevance += computeRelevanceForException(typeBinding.sourceName);
} else if(typeBinding.isEnum()) {
relevance += computeRelevanceForEnum();
} else if(typeBinding.isInterface()) {
relevance += computeRelevanceForInterface();
}
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
proposal.setDeclarationSignature(typeBinding.qualifiedPackageName());
proposal.setSignature(getSignature(typeBinding));
proposal.setPackageName(typeBinding.qualifiedPackageName());
proposal.setTypeName(typeBinding.qualifiedSourceName());
proposal.setCompletion(typeBinding.sourceName());
proposal.setFlags(typeBinding.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
}
}
}
}
}
private void findUnresolvedReference(int completedNameStart, int completedNameEnd, BlockScope scope, char[][] discouragedNames) {
char[][] foundNames = findUnresolvedReferenceBefore(completedNameStart - 1, completedNameEnd, scope, discouragedNames);
if (foundNames != null && foundNames.length > 1) {
int discouragedNamesLength = discouragedNames.length;
int foundNamesLength = foundNames.length;
int newLength = discouragedNamesLength + foundNamesLength;
System.arraycopy(discouragedNames, 0, discouragedNames = new char[newLength][], 0, discouragedNamesLength);
System.arraycopy(foundNames, 0, discouragedNames, discouragedNamesLength, foundNamesLength);
}
findUnresolvedReferenceAfter(completedNameEnd + 1, scope, discouragedNames);
}
private char[][] findUnresolvedReferenceAfter(int from, BlockScope scope, final char[][] discouragedNames) {
final ArrayList proposedNames = new ArrayList();
UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor nameRequestor =
new UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor() {
@Override
public void acceptName(char[] name) {
CompletionEngine.this.acceptUnresolvedName(name);
proposedNames.add(name);
}
};
ReferenceContext referenceContext = scope.referenceContext();
if (referenceContext instanceof AbstractMethodDeclaration) {
AbstractMethodDeclaration md = (AbstractMethodDeclaration)referenceContext;
UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this);
nameFinder.findAfter(
this.completionToken,
md.scope,
md.scope.classScope(),
from,
md.bodyEnd,
discouragedNames,
nameRequestor);
} else if (referenceContext instanceof LambdaExpression) {
LambdaExpression expression = (LambdaExpression) referenceContext;
UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this);
nameFinder.findAfter(
this.completionToken,
expression.scope,
expression.scope.classScope(),
from,
expression.body().sourceEnd,
discouragedNames,
nameRequestor);
} else if (referenceContext instanceof TypeDeclaration) {
TypeDeclaration typeDeclaration = (TypeDeclaration) referenceContext;
FieldDeclaration[] fields = typeDeclaration.fields;
if (fields != null) {
done : for (int i = 0; i < fields.length; i++) {
if (fields[i] instanceof Initializer) {
Initializer initializer = (Initializer) fields[i];
if (initializer.block.sourceStart <= from &&
from < initializer.bodyEnd) {
UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this);
nameFinder.findAfter(
this.completionToken,
typeDeclaration.scope,
typeDeclaration.scope,
from,
initializer.bodyEnd,
discouragedNames,
nameRequestor);
break done;
}
}
}
}
}
int proposedNamesCount = proposedNames.size();
if (proposedNamesCount > 0) {
return (char[][])proposedNames.toArray(new char[proposedNamesCount][]);
}
return null;
}
private char[][] findUnresolvedReferenceBefore(int recordTo, int parseTo, BlockScope scope, final char[][] discouragedNames) {
final ArrayList proposedNames = new ArrayList();
UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor nameRequestor =
new UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor() {
@Override
public void acceptName(char[] name) {
CompletionEngine.this.acceptUnresolvedName(name);
proposedNames.add(name);
}
};
BlockScope upperScope = scope;
while (upperScope.enclosingMethodScope() != null) {
upperScope = upperScope.enclosingMethodScope();
}
ReferenceContext referenceContext = upperScope.referenceContext();
if (referenceContext instanceof AbstractMethodDeclaration) {
AbstractMethodDeclaration md = (AbstractMethodDeclaration)referenceContext;
UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this);
nameFinder.findBefore(
this.completionToken,
md.scope,
md.scope.classScope(),
md.bodyStart,
recordTo,
parseTo,
discouragedNames,
nameRequestor);
} else if (referenceContext instanceof TypeDeclaration) {
TypeDeclaration typeDeclaration = (TypeDeclaration) referenceContext;
done : {
FieldDeclaration[] fields = typeDeclaration.fields;
if (fields != null) {
for (int i = 0; i < fields.length; i++) {
if (fields[i] instanceof Initializer) {
Initializer initializer = (Initializer) fields[i];
if (initializer.block.sourceStart <= recordTo &&
recordTo < initializer.bodyEnd) {
UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this);
nameFinder.findBefore(
this.completionToken,
typeDeclaration.scope,
typeDeclaration.scope,
initializer.block.sourceStart,
recordTo,
parseTo,
discouragedNames,
nameRequestor);
break done;
}
}
}
}
}
}
int proposedNamesCount = proposedNames.size();
if (proposedNamesCount > 0) {
return (char[][])proposedNames.toArray(new char[proposedNamesCount][]);
}
return null;
}
private void findImplementations(ProvidesStatement providesStmt, TypeReference reference ) {
char[][] tokens = reference.getTypeName();
char[] typeName = CharOperation.concatWithAll(tokens, '.');
if (typeName.length == 0) {
this.completionToken = CharOperation.ALL_PREFIX;
} else if (reference instanceof CompletionOnProvidesImplementationsQualifiedTypeReference) {
CompletionOnQualifiedTypeReference qReference = (CompletionOnQualifiedTypeReference) reference;
if (qReference.completionIdentifier != null) {
this.completionToken = CharOperation.concatAll(typeName, qReference.completionIdentifier, '.');
}
} else {
char[] lastToken = tokens[tokens.length - 1];
this.completionToken = lastToken != null && lastToken.length == 0 ?
CharOperation.concat(typeName, new char[]{'.'}) :lastToken;
}
setSourceRange(reference.sourceStart, reference.sourceEnd);
findImplementations(this.completionToken, this.unitScope, providesStmt, -1);
}
private void findImplementations(char[] token, Scope scope, ProvidesStatement providesStmt, int stmtIndex) {
TypeReference theInterface = providesStmt.serviceInterface;
if (token == null) return;
char[][] theInterfaceType = null;
if (theInterface.resolvedType != null && theInterface.resolvedType.isValidBinding()) {
char[] readableName = theInterface.resolvedType.readableName();
if (readableName != null)
theInterfaceType = CharOperation.splitOn('.', readableName);
}
theInterfaceType = theInterfaceType == null ? theInterface.getTypeName() : theInterfaceType;
if (theInterfaceType == null) return;
SearchPattern pattern = null;
NameEnvironmentAnswer answer = this.nameEnvironment.findTypeInModules(theInterfaceType, scope.module());
if (answer != null ) {
if (answer.isSourceType()) {
IType typeHandle = ((SourceTypeElementInfo) answer.getSourceTypes()[0]).getHandle();
try {
ArrayList<IType> allTypes = new ArrayList<IType>();
ITypeHierarchy newTypeHierarchy = typeHandle.newTypeHierarchy(this.javaProject, null);
IType[] implementingClasses = newTypeHierarchy.getImplementingClasses(typeHandle);
for (IType iClass : implementingClasses) {
getAllTypesInHierarchy(newTypeHierarchy,iClass,allTypes);
}
for (IType iType : allTypes) {
String pkg = iType.getPackageFragment().getElementName();
String name = iType.getElementName();
if ( CharOperation.ALL_PREFIX != this.completionToken) {
if(!CharOperation.prefixEquals(this.completionToken, name.toCharArray(), false))
if(!CharOperation.prefixEquals(this.completionToken, pkg.toCharArray(), false))
continue;
}
this.acceptType(pkg.toCharArray(), name.toCharArray(), CharOperation.NO_CHAR_CHAR, iType.getFlags(), null);
acceptTypes(scope);
}
if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
checkCancel();
findPackagesInCurrentModule();
}
return;
} catch (JavaModelException e) {
//
}
} else if (answer.isBinaryType()) {
String typeName = new String(CharOperation.replaceOnCopy(answer.getBinaryType().getName(), '/', '.'));
pattern = SearchPattern.createPattern(typeName,
IJavaSearchConstants.CLASS_AND_INTERFACE,
IJavaSearchConstants.IMPLEMENTORS, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE);
}
}
if (pattern == null) return;
IJavaSearchScope searchScope = BasicSearchEngine.createJavaSearchScope(new IJavaElement[] {this.javaProject});
class ImplSearchRequestor extends SearchRequestor {
String prefix;
LinkedHashSet<String> filter;
public List<IType> types = new ArrayList<>();
public ImplSearchRequestor(char[] prefixToken, LinkedHashSet<String> filter) {
this.prefix = (prefixToken == CharOperation.ALL_PREFIX) ? null : new String(prefixToken);
this.filter = filter;
}
@Override
public void acceptSearchMatch(SearchMatch match) throws CoreException {
// checkCancel();
IJavaElement element = ((IJavaElement) match.getElement());
if (element.getElementType() == IJavaElement.TYPE) {
IType type = (IType) element;
if (this.prefix != null) {
String fullTypeName = type.getPackageFragment().getElementName();
if (fullTypeName != null) {
fullTypeName = fullTypeName.concat(".").concat(type.getElementName()); //$NON-NLS-1$
} else {
fullTypeName = type.getElementName();
}
if (this.filter.contains(fullTypeName)) return;
if (!(fullTypeName.startsWith(this.prefix) || type.getElementName().startsWith(this.prefix)))
return;
}
this.types.add(type);
}
}
}
try {
LinkedHashSet<String> existingImpl = new LinkedHashSet<>();
char[][] theInterfaceName = theInterface.getTypeName();
// filter out existing implementations of the same interfaces
for (int i = 0, l = this.moduleDeclaration.servicesCount; i < l; ++i) {
if (i == stmtIndex) continue;
ProvidesStatement prevProvides = this.moduleDeclaration.services[i];
if (!CharOperation.equals(theInterfaceName, prevProvides.serviceInterface.getTypeName())) continue;
TypeReference[] prevImpls = prevProvides.implementations;
for (TypeReference prevImpl : prevImpls) {
char[][] typeName = prevImpl.getTypeName();
if (typeName == CharOperation.NO_CHAR_CHAR) continue;
existingImpl.add(CharOperation.toString(typeName));
}
}
// use search infrastructure - faster than using model
ImplSearchRequestor searchRequestor = new ImplSearchRequestor(this.completionToken, existingImpl);
new SearchEngine(this.owner == null ? null : JavaModelManager.getJavaModelManager().getWorkingCopies(this.owner, true/*add primary WCs*/)).search(
pattern,
new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()},
searchScope,
searchRequestor,
null
);
for (IType type : searchRequestor.types) {
String pkg = type.getPackageFragment().getElementName();
String name = type.getElementName();
this.acceptType(pkg.toCharArray(), name.toCharArray(), CharOperation.NO_CHAR_CHAR, type.getFlags(), null);
acceptTypes(scope);
}
} catch (CoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
checkCancel();
findPackagesInCurrentModule();
}
}
private void getAllTypesInHierarchy(ITypeHierarchy newTypeHierarchy, IType iClass, ArrayList<IType> allTypes) {
allTypes.add(iClass);
IType[] subclasses = newTypeHierarchy.getSubclasses(iClass);
for (IType iType2 : subclasses) {
getAllTypesInHierarchy(newTypeHierarchy,iType2,allTypes);
}
}
private char[][] findVariableFromUnresolvedReference(LocalDeclaration variable, BlockScope scope, final char[][] discouragedNames) {
final TypeReference type = variable.type;
if(type != null &&
type.resolvedType != null &&
type.resolvedType.problemId() == ProblemReasons.NoError){
final ArrayList proposedNames = new ArrayList();
UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor nameRequestor =
new UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor() {
@Override
public void acceptName(char[] name) {
int relevance = computeBaseRelevance();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(CompletionEngine.this.completionToken, name);
relevance += R_NAME_FIRST_PREFIX;
relevance += R_NAME_FIRST_SUFFIX;
relevance += R_NAME_LESS_NEW_CHARACTERS;
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for variable name
// accept result
CompletionEngine.this.noProposal = false;
if(!CompletionEngine.this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) {
InternalCompletionProposal proposal = CompletionEngine.this.createProposal(CompletionProposal.VARIABLE_DECLARATION, CompletionEngine.this.actualCompletionPosition);
proposal.setSignature(getSignature(type.resolvedType));
proposal.setPackageName(type.resolvedType.qualifiedPackageName());
proposal.setTypeName(type.resolvedType.qualifiedSourceName());
proposal.setName(name);
proposal.setCompletion(name);
//proposal.setFlags(Flags.AccDefault);
proposal.setReplaceRange(CompletionEngine.this.startPosition - CompletionEngine.this.offset, CompletionEngine.this.endPosition - CompletionEngine.this.offset);
proposal.setTokenRange(CompletionEngine.this.tokenStart - CompletionEngine.this.offset, CompletionEngine.this.tokenEnd - CompletionEngine.this.offset);
proposal.setRelevance(relevance);
CompletionEngine.this.requestor.accept(proposal);
if(DEBUG) {
CompletionEngine.this.printDebug(proposal);
}
}
proposedNames.add(name);
}
};
ReferenceContext referenceContext = scope.referenceContext();
if (referenceContext instanceof AbstractMethodDeclaration) {
AbstractMethodDeclaration md = (AbstractMethodDeclaration)referenceContext;
UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this);
nameFinder.find(
this.completionToken,
md,
variable.declarationSourceEnd + 1,
discouragedNames,
nameRequestor);
} else if (referenceContext instanceof TypeDeclaration) {
TypeDeclaration typeDeclaration = (TypeDeclaration) referenceContext;
FieldDeclaration[] fields = typeDeclaration.fields;
if (fields != null) {
done : for (int i = 0; i < fields.length; i++) {
if (fields[i] instanceof Initializer) {
Initializer initializer = (Initializer) fields[i];
if (initializer.bodyStart <= variable.sourceStart &&
variable.sourceStart < initializer.bodyEnd) {
UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this);
nameFinder.find(
this.completionToken,
initializer,
typeDeclaration.scope,
variable.declarationSourceEnd + 1,
discouragedNames,
nameRequestor);
break done;
}
}
}
}
}
int proposedNamesCount = proposedNames.size();
if (proposedNamesCount > 0) {
return (char[][])proposedNames.toArray(new char[proposedNamesCount][]);
}
}
return null;
}
private void findVariableName(
char[] token,
char[] qualifiedPackageName,
char[] qualifiedSourceName,
char[] sourceName,
final TypeBinding typeBinding,
char[][] discouragedNames,
final char[][] forbiddenNames,
boolean forCollection,
int dim,
int kind){
if(sourceName == null || sourceName.length == 0)
return;
//{ObjectTeams: filter out non-completable variables
// if (!canBeCompleted(token))
// return;
//carp}
// compute variable name for non base type
final char[] displayName;
if (!forCollection) {
if (dim > 0){
int l = qualifiedSourceName.length;
displayName = new char[l+(2*dim)];
System.arraycopy(qualifiedSourceName, 0, displayName, 0, l);
for(int i = 0; i < dim; i++){
displayName[l+(i*2)] = '[';
displayName[l+(i*2)+1] = ']';
}
} else {
displayName = qualifiedSourceName;
}
} else {
displayName = typeBinding.qualifiedSourceName();
}
final char[] t = token;
final char[] q = qualifiedPackageName;
INamingRequestor namingRequestor = new INamingRequestor() {
void accept(char[] name, int prefixAndSuffixRelevance, int reusedCharacters){
int l = forbiddenNames == null ? 0 : forbiddenNames.length;
for (int i = 0; i < l; i++) {
if (CharOperation.equals(forbiddenNames[i], name, false)) return;
}
if (CharOperation.prefixEquals(t, name, false)) {
int relevance = computeBaseRelevance();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(t, name);
relevance += prefixAndSuffixRelevance;
if(reusedCharacters > 0) relevance += R_NAME_LESS_NEW_CHARACTERS;
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for variable name
// accept result
CompletionEngine.this.noProposal = false;
if(!CompletionEngine.this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) {
InternalCompletionProposal proposal = CompletionEngine.this.createProposal(CompletionProposal.VARIABLE_DECLARATION, CompletionEngine.this.actualCompletionPosition);
proposal.setSignature(getSignature(typeBinding));
proposal.setPackageName(q);
proposal.setTypeName(displayName);
proposal.setName(name);
proposal.setCompletion(name);
//proposal.setFlags(Flags.AccDefault);
proposal.setReplaceRange(CompletionEngine.this.startPosition - CompletionEngine.this.offset, CompletionEngine.this.endPosition - CompletionEngine.this.offset);
proposal.setTokenRange(CompletionEngine.this.tokenStart - CompletionEngine.this.offset, CompletionEngine.this.tokenEnd - CompletionEngine.this.offset);
proposal.setRelevance(relevance);
CompletionEngine.this.requestor.accept(proposal);
if(DEBUG) {
CompletionEngine.this.printDebug(proposal);
}
}
}
}
@Override
public void acceptNameWithoutPrefixAndSuffix(char[] name,int reusedCharacters) {
accept(name, 0, reusedCharacters);
}
@Override
public void acceptNameWithPrefix(char[] name, boolean isFirstPrefix, int reusedCharacters) {
accept(name, isFirstPrefix ? R_NAME_FIRST_PREFIX : R_NAME_PREFIX, reusedCharacters);
}
@Override
public void acceptNameWithPrefixAndSuffix(char[] name, boolean isFirstPrefix, boolean isFirstSuffix, int reusedCharacters) {
accept(
name,
(isFirstPrefix ? R_NAME_FIRST_PREFIX : R_NAME_PREFIX) + (isFirstSuffix ? R_NAME_FIRST_SUFFIX : R_NAME_SUFFIX),
reusedCharacters);
}
@Override
public void acceptNameWithSuffix(char[] name, boolean isFirstSuffix, int reusedCharacters) {
accept(name, isFirstSuffix ? R_NAME_FIRST_SUFFIX : R_NAME_SUFFIX, reusedCharacters);
}
};
InternalNamingConventions.suggestVariableNames(
kind,
InternalNamingConventions.BK_SIMPLE_TYPE_NAME,
qualifiedSourceName,
this.javaProject,
dim,
token,
discouragedNames,
true,
namingRequestor);
}
// Helper method for private void findVariableNames(char[] name, TypeReference type )
private void findVariableName(
char[] token,
char[] qualifiedPackageName,
char[] qualifiedSourceName,
char[] sourceName,
final TypeBinding typeBinding,
char[][] discouragedNames,
final char[][] forbiddenNames,
int dim,
int kind){
findVariableName(
token,
qualifiedPackageName,
qualifiedSourceName,
sourceName,
typeBinding,
discouragedNames,
forbiddenNames,
false,
dim,
kind);
}
private void findVariableNameForCollection(
char[] token,
char[] qualifiedPackageName,
char[] qualifiedSourceName,
char[] sourceName,
final TypeBinding typeBinding,
char[][] discouragedNames,
final char[][] forbiddenNames,
int kind){
findVariableName(
token,
qualifiedPackageName,
qualifiedSourceName,
sourceName,
typeBinding,
discouragedNames,
forbiddenNames,
false,
1,
kind);
}
private void findVariableNames(char[] name, TypeReference type , char[][] discouragedNames, char[][] forbiddenNames, int kind){
if(type != null &&
type.resolvedType != null) {
TypeBinding tb = type.resolvedType;
if (tb.problemId() == ProblemReasons.NoError &&
TypeBinding.notEquals(tb, Scope.getBaseType(VOID))) {
findVariableName(
name,
tb.leafComponentType().qualifiedPackageName(),
tb.leafComponentType().qualifiedSourceName(),
tb.leafComponentType().sourceName(),
tb,
discouragedNames,
forbiddenNames,
type.dimensions(),
kind);
if (tb.isParameterizedType() &&
tb.findSuperTypeOriginatingFrom(TypeIds.T_JavaUtilCollection, false) != null) {
ParameterizedTypeBinding ptb = ((ParameterizedTypeBinding) tb);
TypeBinding[] arguments = ptb.arguments;
if (arguments != null && arguments.length == 1) {
TypeBinding argument = arguments[0];
findVariableNameForCollection(
name,
argument.leafComponentType().qualifiedPackageName(),
argument.leafComponentType().qualifiedSourceName(),
argument.leafComponentType().sourceName(),
tb,
discouragedNames,
forbiddenNames,
kind);
}
}
}
}
}
private void findVariablesAndMethods(
char[] token,
Scope scope,
InvocationSite invocationSite,
Scope invocationScope,
boolean insideTypeAnnotation,
boolean insideAnnotationAttribute) {
if (token == null)
return;
// Should local variables hide fields from the receiver type or any of its enclosing types?
// we know its an implicit field/method access... see BlockScope getBinding/getImplicitMethod
boolean staticsOnly = false;
// need to know if we're in a static context (or inside a constructor)
int tokenLength = token.length;
ObjectVector localsFound = new ObjectVector();
ObjectVector fieldsFound = new ObjectVector();
ObjectVector methodsFound = new ObjectVector();
Scope currentScope = scope;
if (!this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) {
done1 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
switch (currentScope.kind) {
case Scope.METHOD_SCOPE :
// handle the error case inside an explicit constructor call (see MethodScope>>findField)
MethodScope methodScope = (MethodScope) currentScope;
staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall;
//$FALL-THROUGH$
case Scope.BLOCK_SCOPE :
BlockScope blockScope = (BlockScope) currentScope;
next : for (int i = 0, length = blockScope.locals.length; i < length; i++) {
//{ObjectTeams:
if (isBaseAccess(invocationSite) || isTSuperAccess(invocationSite))
break next; // no "base.local", "tsuper.local" ever;
// SH}
LocalVariableBinding local = blockScope.locals[i];
if (local == null)
break next;
if (tokenLength > local.name.length)
continue next;
if (isFailedMatch(token, local.name))
continue next;
//{ObjectTeams: filter out generated variables
if (!canBeCompleted(local.name)) continue next;
// carp}
if (local.isSecret())
continue next;
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=328674
if (local.declaration.initialization != null && !local.declaration.type.isTypeNameVar(null)) {
// proposal being asked inside field's initialization. Don't propose this field.
continue next;
}
// don't propose non constant variables or strings (1.6 or below) in case expression
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=195346
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=343342
if (this.assistNodeIsInsideCase) {
if (local.isFinal()) {
if (this.assistNodeIsString){
if (local.type == null || local.type.id != TypeIds.T_JavaLangString)
continue next;
} else if (!(local.type instanceof BaseTypeBinding))
continue next;
} else {
continue next; // non-constants not allowed in case.
}
}
int ptr = this.uninterestingBindingsPtr;
// Cases where the binding is uninteresting eg. for completion occurring inside a local var
// declaration, the local var binding is uninteresting and shouldn't be proposed.
while (ptr >= 0) {
if (this.uninterestingBindings[ptr] == local) {
continue next;
}
ptr--;
}
for (int f = 0; f < localsFound.size; f++) {
LocalVariableBinding otherLocal =
(LocalVariableBinding) localsFound.elementAt(f);
if (CharOperation.equals(otherLocal.name, local.name, true))
continue next;
}
localsFound.add(local);
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal(local);
relevance += computeRelevanceForCaseMatching(token, local.name);
relevance += computeRelevanceForExpectingType(local.type);
relevance += computeRelevanceForEnumConstant(local.type);
relevance += computeRelevanceForQualification(false);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for local variable
relevance += computeRelevanceForFinal(this.assistNodeIsInsideCase, local.isFinal());
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.LOCAL_VARIABLE_REF, this.actualCompletionPosition);
proposal.setSignature(
local.type == null
? createTypeSignature(
CharOperation.NO_CHAR,
local.declaration.type.toString().toCharArray())
: getSignature(local.type));
if(local.type == null) {
//proposal.setPackageName(null);
proposal.setTypeName(local.declaration.type.toString().toCharArray());
} else {
proposal.setPackageName(local.type.qualifiedPackageName());
proposal.setTypeName(local.type.qualifiedSourceName());
}
proposal.setName(local.name);
proposal.setCompletion(local.name);
proposal.setFlags(local.modifiers);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
break;
case Scope.COMPILATION_UNIT_SCOPE :
break done1;
}
currentScope = currentScope.parent;
}
}
checkCancel();
boolean proposeField = !this.requestor.isIgnored(CompletionProposal.FIELD_REF);
boolean proposeMethod = !this.requestor.isIgnored(CompletionProposal.METHOD_REF);
staticsOnly = false;
currentScope = scope;
if(proposeField || proposeMethod) {
done2 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
switch (currentScope.kind) {
case Scope.METHOD_SCOPE :
// handle the error case inside an explicit constructor call (see MethodScope>>findField)
MethodScope methodScope = (MethodScope) currentScope;
staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall;
break;
case Scope.CLASS_SCOPE :
ClassScope classScope = (ClassScope) currentScope;
SourceTypeBinding enclosingType = classScope.referenceContext.binding;
/* if (tokenLength == 0) { // only search inside the type itself if no prefix was provided
findFields(token, enclosingType.fields(), classScope, fieldsFound, staticsOnly);
findMethods(token, enclosingType.methods(), classScope, methodsFound, staticsOnly, false);
break done;
} else { */
if(!insideTypeAnnotation) {
if(proposeField) {
findFields(
token,
enclosingType,
classScope,
fieldsFound,
localsFound,
staticsOnly,
invocationSite,
invocationScope,
true,
true,
null,
null,
null,
false,
null,
-1,
-1);
}
if(proposeMethod && !insideAnnotationAttribute) {
findMethods(
token,
null,
null,
enclosingType,
classScope,
methodsFound,
staticsOnly,
false,
invocationSite,
invocationScope,
true,
false,
true,
null,
null,
null,
false,
null,
-1,
-1);
}
}
staticsOnly |= enclosingType.isStatic();
insideTypeAnnotation = false;
// }
break;
case Scope.COMPILATION_UNIT_SCOPE :
break done2;
}
currentScope = currentScope.parent;
}
checkCancel();
findFieldsAndMethodsFromStaticImports(
token,
scope,
invocationSite,
invocationScope,
false,
insideAnnotationAttribute,
localsFound,
fieldsFound,
methodsFound,
proposeField,
proposeMethod);
if (this.assistNodeInJavadoc == 0) {
checkCancel();
// search in favorites import
findFieldsAndMethodsFromFavorites(
token,
scope,
invocationSite,
invocationScope,
localsFound,
fieldsFound,
methodsFound);
}
checkCancel();
findEnumConstantsFromExpectedTypes(
token,
invocationScope,
fieldsFound);
}
}
private char[] getCompletedTypeSignature(ReferenceBinding referenceBinding) {
char[] result = null;
StringBuffer sig = new StringBuffer(10);
if (!referenceBinding.isMemberType()) {
char[] typeSig = referenceBinding.genericTypeSignature();
sig.append(typeSig, 0, typeSig.length);
} else if (!this.insideQualifiedReference) {
if (referenceBinding.isStatic()) {
char[] typeSig = referenceBinding.signature();
sig.append(typeSig, 0, typeSig.length-1); // copy all but trailing semicolon
TypeVariableBinding[] typeVariables = referenceBinding.typeVariables();
if (typeVariables != Binding.NO_TYPE_VARIABLES) {
sig.append(Signature.C_GENERIC_START);
for (int i = 0, length = typeVariables.length; i < length; i++) {
sig.append(typeVariables[i].genericTypeSignature());
}
sig.append(Signature.C_GENERIC_END);
}
sig.append(Signature.C_SEMICOLON);
} else {
char[] typeSig = referenceBinding.genericTypeSignature();
sig.append(typeSig, 0, typeSig.length);
}
} else {
ReferenceBinding enclosingType = referenceBinding.enclosingType();
if (enclosingType.isParameterizedType()) {
char[] typeSig = referenceBinding.genericTypeSignature();
sig.append(typeSig, 0, typeSig.length-1);
TypeVariableBinding[] typeVariables = referenceBinding.typeVariables();
if (typeVariables != Binding.NO_TYPE_VARIABLES) {
sig.append(Signature.C_GENERIC_START);
for (int i = 0, length = typeVariables.length; i < length; i++) {
sig.append(typeVariables[i].genericTypeSignature());
}
sig.append(Signature.C_GENERIC_END);
}
} else {
char[] typeSig = referenceBinding.signature();
sig.append(typeSig, 0, typeSig.length-1); // copy all but trailing semicolon
if (referenceBinding.isStatic()) {
TypeVariableBinding[] typeVariables = referenceBinding.typeVariables();
if (typeVariables != Binding.NO_TYPE_VARIABLES) {
sig.append(Signature.C_GENERIC_START);
for (int i = 0, length = typeVariables.length; i < length; i++) {
sig.append(typeVariables[i].genericTypeSignature());
}
sig.append(Signature.C_GENERIC_END);
}
}
}
sig.append(Signature.C_SEMICOLON);
}
int sigLength = sig.length();
result = new char[sigLength];
sig.getChars(0, sigLength, result, 0);
result = CharOperation.replaceOnCopy(result, '/', Signature.C_DOT);
return result;
}
private ImportBinding[] getFavoriteReferenceBindings(Scope scope) {
if (this.favoriteReferenceBindings != null) return this.favoriteReferenceBindings;
String[] favoriteReferences = this.requestor.getFavoriteReferences();
if (favoriteReferences == null || favoriteReferences.length == 0) return null;
ImportBinding[] resolvedImports = new ImportBinding[favoriteReferences.length];
int count = 0;
next : for (int i = 0; i < favoriteReferences.length; i++) {
String favoriteReference = favoriteReferences[i];
int length;
if (favoriteReference == null || (length = favoriteReference.length()) == 0) continue next;
boolean onDemand = favoriteReference.charAt(length - 1) == '*';
char[][] compoundName = CharOperation.splitOn('.', favoriteReference.toCharArray());
if (onDemand) {
compoundName = CharOperation.subarray(compoundName, 0, compoundName.length - 1);
}
// remove duplicate and conflicting
for (int j = 0; j < count; j++) {
ImportReference f = resolvedImports[j].reference;
if (CharOperation.equals(f.tokens, compoundName)) continue next;
if (!onDemand && ((f.bits & ASTNode.OnDemand) == 0)) {
if (CharOperation.equals(f.tokens[f.tokens.length - 1], compoundName[compoundName.length - 1]))
continue next;
}
}
boolean isStatic = true;
ImportReference importReference =
new ImportReference(
compoundName,
new long[compoundName.length],
onDemand,
isStatic ? ClassFileConstants.AccStatic : ClassFileConstants.AccDefault);
Binding importBinding = this.unitScope.findImport(compoundName, isStatic, onDemand);
if (!importBinding.isValidBinding()) {
continue next;
}
if (importBinding instanceof PackageBinding) {
continue next;
}
resolvedImports[count++] =
new ImportBinding(compoundName, onDemand, importBinding, importReference);
}
if (resolvedImports.length > count)
System.arraycopy(resolvedImports, 0, resolvedImports = new ImportBinding[count], 0, count);
return this.favoriteReferenceBindings = resolvedImports;
}
private INameEnvironment getNoCacheNameEnvironment() {
if (this.noCacheNameEnvironment == null) {
JavaModelManager.getJavaModelManager().cacheZipFiles(this);
this.noCacheNameEnvironment = IndexBasedJavaSearchEnvironment.create(Collections.singletonList(this.javaProject), this.owner == null ? null : JavaModelManager.getJavaModelManager().getWorkingCopies(this.owner, true/*add primary WCs*/));
}
return this.noCacheNameEnvironment;
}
@Override
public AssistParser getParser() {
return this.parser;
}
protected boolean hasArrayTypeAsExpectedSuperTypes() {
if ((this.expectedTypesFilter & ~SUBTYPE) != 0) return false;
if (!this.hasComputedExpectedArrayTypes) {
if(this.expectedTypes != null) {
done : for (int i = 0; i <= this.expectedTypesPtr; i++) {
if(this.expectedTypes[i].isArrayType()) {
this.hasExpectedArrayTypes = true;
break done;
}
}
}
this.hasComputedExpectedArrayTypes = true;
}
return this.hasExpectedArrayTypes;
}
protected boolean hasPossibleAnnotationTarget(TypeBinding typeBinding, Scope scope) {
if (this.targetedElement == TagBits.AnnotationForPackage) {
long target = typeBinding.getAnnotationTagBits() & TagBits.AnnotationTargetMASK;
if(target != 0 && (target & TagBits.AnnotationForPackage) == 0) {
return false;
}
} else if (this.targetedElement == TagBits.AnnotationForModule) {
long target = typeBinding.getAnnotationTagBits() & TagBits.AnnotationTargetMASK;
if(target != 0 && (target & TagBits.AnnotationForModule) == 0) {
return false;
}
} else if ((this.targetedElement & (TagBits.AnnotationForType | TagBits.AnnotationForTypeUse)) != 0) {
if (scope.parent != null &&
scope.parent.parent != null &&
scope.parent.referenceContext() instanceof CompletionOnAnnotationOfType &&
scope.parent.parent instanceof CompilationUnitScope) {
long target = typeBinding.getAnnotationTagBits() & TagBits.AnnotationTargetMASK;
if ((this.targetedElement & TagBits.AnnotationForAnnotationType) != 0) {
if(target != 0 && (target &(TagBits.AnnotationForType | TagBits.AnnotationForAnnotationType | TagBits.AnnotationForTypeUse)) == 0) {
return false;
}
} else {
if (target != 0 && (target & (TagBits.AnnotationForType | TagBits.AnnotationForTypeUse)) == 0) {
return false;
}
}
}
}
return true;
}
/**
* Returns completion string inserted inside a specified inline tag.
* @param completionName
* @return char[] Completion text inclunding specified inline tag
*/
private char[] inlineTagCompletion(char[] completionName, char[] inlineTag) {
int tagLength= inlineTag.length;
int completionLength = completionName.length;
int inlineLength = 2+tagLength+1+completionLength+1;
char[] inlineCompletion = new char[inlineLength];
inlineCompletion[0] = '{';
inlineCompletion[1] = '@';
System.arraycopy(inlineTag, 0, inlineCompletion, 2, tagLength);
inlineCompletion[tagLength+2] = ' ';
System.arraycopy(completionName, 0, inlineCompletion, tagLength+3, completionLength);
// do not add space at end of inline tag (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=121026)
//inlineCompletion[inlineLength-2] = ' ';
inlineCompletion[inlineLength-1] = '}';
return inlineCompletion;
}
private boolean isAllowingLongComputationProposals() {
return this.monitor != null;
}
/**
* Checks whether name matches the token according to the current
* code completion settings (substring match, camel case match etc.)
* and sets whether the current match is a suffix proposal.
*
* @param token the token that is tested
* @param name the name to match
* @return <code>true</code> if the token does not match,
* <code>false</code> otherwise
*/
private boolean isFailedMatch(char[] token, char[] name) {
if ((this.options.substringMatch && CharOperation.substringMatch(token, name))
|| (this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, name))
|| CharOperation.prefixEquals(token, name, false)) {
return false;
}
return true;
}
private boolean isForbidden(ReferenceBinding binding) {
for (int i = 0; i <= this.forbbidenBindingsPtr; i++) {
if(this.forbbidenBindings[i] == binding) {
return true;
}
}
if (!isValidPackageName(binding.qualifiedPackageName())) {
return true;
}
return false;
}
private boolean isForbidden(char[] givenPkgName, char[] givenTypeName, char[][] enclosingTypeNames) {
// CharOperation.concatWith() handles the cases where input args are null/empty
char[] fullTypeName = CharOperation.concatWith(enclosingTypeNames, givenTypeName, '.');
for (int i = 0; i <= this.forbbidenBindingsPtr; i++) {
if (this.forbbidenBindings[i] instanceof TypeBinding) {
TypeBinding typeBinding = (TypeBinding) this.forbbidenBindings[i];
char[] currPkgName = typeBinding.qualifiedPackageName();
if (CharOperation.equals(givenPkgName, currPkgName)) {
char[] currTypeName = typeBinding.qualifiedSourceName();
if (CharOperation.equals(fullTypeName, currTypeName)) {
return true;
}
}
}
}
if (!isValidPackageName(givenPkgName)) {
return true;
}
return false;
}
private boolean isIgnored(int kind) {
return this.requestor.isIgnored(kind);
}
boolean isIgnored(int kind, boolean missingTypes) {
return this.requestor.isIgnored(kind) ||
(missingTypes && !this.requestor.isAllowingRequiredProposals(kind, CompletionProposal.TYPE_REF));
}
private boolean isIgnored(int kind, int requiredProposalKind) {
return this.requestor.isIgnored(kind) ||
!this.requestor.isAllowingRequiredProposals(kind, requiredProposalKind);
}
private boolean isValidPackageName(char[] packageName) {
if (this.validPackageNames.includes(packageName)) {
return true;
}
if (this.invalidPackageNames.includes(packageName)) {
return false;
}
char[][] names = CharOperation.splitOn('.', packageName);
for (int i = 0, length = names.length; i < length; i++) {
if (!Util.isValidFolderNameForPackage(new String(names[i]), this.sourceLevel, this.complianceLevel)) {
this.invalidPackageNames.add(packageName);
return false;
}
}
this.validPackageNames.add(packageName);
return true;
}
private boolean isValidParent(ASTNode parent, ASTNode node, Scope scope){
if(parent instanceof ParameterizedSingleTypeReference) {
ParameterizedSingleTypeReference ref = (ParameterizedSingleTypeReference) parent;
if (ref.resolvedType == null) {
return false;
}
TypeVariableBinding[] typeVariables = ((ReferenceBinding)ref.resolvedType).typeVariables();
int length = ref.typeArguments == null ? 0 : ref.typeArguments.length;
int nodeIndex = -1;
for(int i = length - 1 ; i > -1 ; i--) {
if(node == ref.typeArguments[i]) {
nodeIndex = i;
break;
}
}
if(nodeIndex > -1 && (typeVariables == null || typeVariables.length < nodeIndex + 1)) {
TypeBinding[] typeBindings = new TypeBinding[nodeIndex + 1];
for(int i = 0; i < nodeIndex; i++) {
typeBindings[i] = ref.typeArguments[i].resolvedType;
}
typeBindings[nodeIndex] = scope.getJavaLangObject();
if(typeVariables == null || typeVariables.length == 0) {
scope.problemReporter().nonGenericTypeCannotBeParameterized(0, ref, ref.resolvedType, typeBindings);
} else {
scope.problemReporter().incorrectArityForParameterizedType(ref, ref.resolvedType, typeBindings);
}
return false;
}
} else if(parent instanceof ParameterizedQualifiedTypeReference) {
ParameterizedQualifiedTypeReference ref = (ParameterizedQualifiedTypeReference) parent;
TypeVariableBinding[] typeVariables = ((ReferenceBinding)ref.resolvedType).typeVariables();
TypeReference[][] arguments = ref.typeArguments;
int iLength = arguments == null ? 0 : arguments.length;
for (int i = 0; i < iLength; i++) {
int jLength = arguments[i] == null ? 0 : arguments[i].length;
for (int j = 0; j < jLength; j++) {
if(arguments[i][j] == node && (typeVariables == null || typeVariables.length <= j)) {
TypeBinding[] typeBindings = new TypeBinding[j + 1];
for(int k = 0; k < j; k++) {
typeBindings[k] = ref.typeArguments[i][k].resolvedType;
}
typeBindings[j] = scope.getJavaLangObject();
if(typeVariables == null || typeVariables.length == 0) {
scope.problemReporter().nonGenericTypeCannotBeParameterized(0, ref, ref.resolvedType, typeBindings);
} else {
scope.problemReporter().incorrectArityForParameterizedType(ref, ref.resolvedType, typeBindings);
}
return false;
}
}
}
}
return true;
}
private boolean mustQualifyType(ReferenceBinding type, char[] packageName, Scope scope) {
if(!mustQualifyType(
packageName,
type.sourceName(),
type.isMemberType() ? type.enclosingType().qualifiedSourceName() : null,
type.modifiers)) {
return false;
}
ReferenceBinding enclosingType = scope.enclosingSourceType();
while (enclosingType != null) {
ReferenceBinding currentType = enclosingType;
while (currentType != null) {
ReferenceBinding[] memberTypes = currentType.memberTypes();
if(memberTypes != null) {
for (int i = 0; i < memberTypes.length; i++) {
if (CharOperation.equals(memberTypes[i].sourceName, type.sourceName()) &&
memberTypes[i].canBeSeenBy(scope)) {
return TypeBinding.notEquals(memberTypes[i], type);
}
}
}
currentType = currentType.superclass();
}
enclosingType = enclosingType.enclosingType();
}
return true;
}
private Initializer parseSnippeInitializer(char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){
StringBuffer prefix = new StringBuffer();
prefix.append("public class FakeType {\n "); //$NON-NLS-1$
if(isStatic) {
prefix.append("static "); //$NON-NLS-1$
}
prefix.append("{\n"); //$NON-NLS-1$
for (int i = 0; i < localVariableTypeNames.length; i++) {
ASTNode.printModifiers(localVariableModifiers[i], prefix);
prefix.append(' ');
prefix.append(localVariableTypeNames[i]);
prefix.append(' ');
prefix.append(localVariableNames[i]);
prefix.append(';');
}
char[] fakeSource = CharOperation.concat(prefix.toString().toCharArray(), snippet, "}}".toCharArray());//$NON-NLS-1$
this.offset = prefix.length();
String encoding = this.compilerOptions.defaultEncoding;
@SuppressWarnings("deprecation")
BasicCompilationUnit fakeUnit = new BasicCompilationUnit(
fakeSource,
null,
"FakeType.java", //$NON-NLS-1$
encoding);
this.actualCompletionPosition = prefix.length() + position - 1;
CompilationResult fakeResult = new CompilationResult(fakeUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
CompilationUnitDeclaration fakeAST = this.parser.dietParse(fakeUnit, fakeResult, this.actualCompletionPosition);
parseBlockStatements(fakeAST, this.actualCompletionPosition);
return (Initializer)fakeAST.types[0].fields[0];
}
protected void printDebug(CategorizedProblem error) {
if(CompletionEngine.DEBUG) {
System.out.print("COMPLETION - completionFailure("); //$NON-NLS-1$
System.out.print(error);
System.out.println(")"); //$NON-NLS-1$
}
}
protected void printDebug(CompletionProposal proposal){
StringBuffer buffer = new StringBuffer();
printDebug(proposal, 0, buffer);
System.out.println(buffer.toString());
}
private void printDebug(CompletionProposal proposal, int tab, StringBuffer buffer){
printDebugTab(tab, buffer);
buffer.append("COMPLETION - "); //$NON-NLS-1$
switch(proposal.getKind()) {
case CompletionProposal.ANONYMOUS_CLASS_DECLARATION :
buffer.append("ANONYMOUS_CLASS_DECLARATION"); //$NON-NLS-1$
break;
case CompletionProposal.FIELD_REF :
buffer.append("FIELD_REF"); //$NON-NLS-1$
break;
case CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER :
buffer.append("FIELD_REF_WITH_CASTED_RECEIVER"); //$NON-NLS-1$
break;
case CompletionProposal.KEYWORD :
buffer.append("KEYWORD"); //$NON-NLS-1$
break;
case CompletionProposal.LABEL_REF :
buffer.append("LABEL_REF"); //$NON-NLS-1$
break;
case CompletionProposal.LOCAL_VARIABLE_REF :
buffer.append("LOCAL_VARIABLE_REF"); //$NON-NLS-1$
break;
case CompletionProposal.METHOD_DECLARATION :
buffer.append("METHOD_DECLARATION"); //$NON-NLS-1$
break;
case CompletionProposal.METHOD_REF :
buffer.append("METHOD_REF"); //$NON-NLS-1$
break;
case CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER :
buffer.append("METHOD_REF_WITH_CASTED_RECEIVER"); //$NON-NLS-1$
break;
case CompletionProposal.MODULE_DECLARATION :
buffer.append("MODULE_DECLARATION"); //$NON-NLS-1$
break;
case CompletionProposal.MODULE_REF :
buffer.append("MODULE_REF"); //$NON-NLS-1$
break;
case CompletionProposal.PACKAGE_REF :
buffer.append("PACKAGE_REF"); //$NON-NLS-1$
break;
case CompletionProposal.TYPE_REF :
buffer.append("TYPE_REF"); //$NON-NLS-1$
break;
case CompletionProposal.VARIABLE_DECLARATION :
buffer.append("VARIABLE_DECLARATION"); //$NON-NLS-1$
break;
case CompletionProposal.POTENTIAL_METHOD_DECLARATION :
buffer.append("POTENTIAL_METHOD_DECLARATION"); //$NON-NLS-1$
break;
case CompletionProposal.METHOD_NAME_REFERENCE :
buffer.append("METHOD_NAME_REFERENCE"); //$NON-NLS-1$
break;
case CompletionProposal.ANNOTATION_ATTRIBUTE_REF :
buffer.append("ANNOTATION_ATTRIBUT_REF"); //$NON-NLS-1$
break;
case CompletionProposal.FIELD_IMPORT :
buffer.append("FIELD_IMPORT"); //$NON-NLS-1$
break;
case CompletionProposal.METHOD_IMPORT :
buffer.append("METHOD_IMPORT"); //$NON-NLS-1$
break;
case CompletionProposal.TYPE_IMPORT :
buffer.append("TYPE_IMPORT"); //$NON-NLS-1$
break;
case CompletionProposal.CONSTRUCTOR_INVOCATION :
buffer.append("CONSTRUCTOR_INVOCATION"); //$NON-NLS-1$
break;
case CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION :
buffer.append("ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION"); //$NON-NLS-1$
break;
default :
buffer.append("PROPOSAL"); //$NON-NLS-1$
break;
}
buffer.append("{\n");//$NON-NLS-1$
printDebugTab(tab, buffer);
buffer.append("\tCompletion[").append(proposal.getCompletion() == null ? "null".toCharArray() : proposal.getCompletion()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
printDebugTab(tab, buffer);
buffer.append("\tDeclarationSignature[").append(proposal.getDeclarationSignature() == null ? "null".toCharArray() : proposal.getDeclarationSignature()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
printDebugTab(tab, buffer);
buffer.append("\tDeclarationKey[").append(proposal.getDeclarationKey() == null ? "null".toCharArray() : proposal.getDeclarationKey()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
printDebugTab(tab, buffer);
buffer.append("\tSignature[").append(proposal.getSignature() == null ? "null".toCharArray() : proposal.getSignature()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
printDebugTab(tab, buffer);
buffer.append("\tKey[").append(proposal.getKey() == null ? "null".toCharArray() : proposal.getKey()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
printDebugTab(tab, buffer);
buffer.append("\tName[").append(proposal.getName() == null ? "null".toCharArray() : proposal.getName()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
printDebugTab(tab, buffer);
buffer.append("\tFlags[");//$NON-NLS-1$
int flags = proposal.getFlags();
buffer.append(Flags.toString(flags));
if((flags & Flags.AccInterface) != 0) buffer.append("interface ");//$NON-NLS-1$
if((flags & Flags.AccEnum) != 0) buffer.append("enum ");//$NON-NLS-1$
buffer.append("]\n"); //$NON-NLS-1$
CompletionProposal[] proposals = proposal.getRequiredProposals();
if(proposals != null) {
printDebugTab(tab, buffer);
buffer.append("\tRequiredProposals[");//$NON-NLS-1$
for (int i = 0; i < proposals.length; i++) {
buffer.append("\n"); //$NON-NLS-1$
printDebug(proposals[i], tab + 2, buffer);
}
printDebugTab(tab, buffer);
buffer.append("\n\t]\n"); //$NON-NLS-1$
}
printDebugTab(tab, buffer);
buffer.append("\tCompletionLocation[").append(proposal.getCompletionLocation()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$
int start = proposal.getReplaceStart();
int end = proposal.getReplaceEnd();
printDebugTab(tab, buffer);
buffer.append("\tReplaceStart[").append(start).append("]"); //$NON-NLS-1$ //$NON-NLS-2$
buffer.append("-ReplaceEnd[").append(end).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$
start = proposal.getTokenStart();
end = proposal.getTokenEnd();
printDebugTab(tab, buffer);
buffer.append("\tTokenStart[").append(start).append("]"); //$NON-NLS-1$ //$NON-NLS-2$
buffer.append("-TokenEnd[").append(end).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$
if (this.source != null) {
printDebugTab(tab, buffer);
buffer.append("\tReplacedText[").append(this.source, start, end-start).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$
}
printDebugTab(tab, buffer);
buffer.append("\tTokenStart[").append(proposal.getTokenStart()).append("]"); //$NON-NLS-1$ //$NON-NLS-2$
buffer.append("-TokenEnd[").append(proposal.getTokenEnd()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$
printDebugTab(tab, buffer);
buffer.append("\tRelevance[").append(proposal.getRelevance()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$
printDebugTab(tab, buffer);
buffer.append("}\n");//$NON-NLS-1$
}
private void printDebugTab(int tab, StringBuffer buffer) {
for (int i = 0; i < tab; i++) {
buffer.append('\t');
}
}
private void proposeConstructor(AcceptedConstructor deferredProposal, Scope scope) {
if (deferredProposal.proposeConstructor) {
proposeConstructor(
deferredProposal.simpleTypeName,
deferredProposal.parameterCount,
deferredProposal.signature,
deferredProposal.parameterTypes,
deferredProposal.parameterNames,
deferredProposal.modifiers,
deferredProposal.packageName,
deferredProposal.typeModifiers,
deferredProposal.accessibility,
deferredProposal.simpleTypeName,
deferredProposal.fullyQualifiedName,
deferredProposal.mustBeQualified,
scope,
deferredProposal.extraFlags);
}
}
private void proposeConstructor(
char[] simpleTypeName,
int parameterCount,
char[] signature,
char[][] parameterTypes,
char[][] parameterNames,
int modifiers,
char[] packageName,
int typeModifiers,
int accessibility,
char[] typeName,
char[] fullyQualifiedName,
boolean isQualified,
Scope scope,
int extraFlags) {
char[] typeCompletion = fullyQualifiedName;
if(isQualified) {
if (packageName == null || packageName.length == 0)
if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
return; // ignore types from the default package from outside it
} else {
typeCompletion = simpleTypeName;
}
ReferenceBinding typeBinding = this.lookupEnvironment.getType(CharOperation.splitOn('.', fullyQualifiedName));
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForRestrictions(accessibility);
relevance += computeRelevanceForCaseMatching(this.completionToken, simpleTypeName);
relevance += computeRelevanceForExpectingType(typeBinding);
relevance += computeRelevanceForQualification(isQualified);
relevance += computeRelevanceForConstructor();
boolean isInterface = false;
int kind = typeModifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation);
switch (kind) {
case ClassFileConstants.AccAnnotation:
case ClassFileConstants.AccAnnotation | ClassFileConstants.AccInterface:
relevance += computeRelevanceForAnnotation();
relevance += computeRelevanceForInterface();
isInterface = true;
break;
case ClassFileConstants.AccEnum:
relevance += computeRelevanceForEnum();
break;
case ClassFileConstants.AccInterface:
relevance += computeRelevanceForInterface();
isInterface = true;
break;
default:
relevance += computeRelevanceForClass();
relevance += computeRelevanceForException(simpleTypeName);
break;
}
char[] completion;
if (this.source != null
&& this.source.length > this.endPosition
&& this.source[this.endPosition] == '(') {
completion = CharOperation.NO_CHAR;
} else {
completion = new char[] { '(', ')' };
}
InternalCompletionProposal typeProposal = createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
typeProposal.nameLookup = this.nameEnvironment.nameLookup;
typeProposal.completionEngine = this;
typeProposal.setDeclarationSignature(packageName);
typeProposal.setSignature(createNonGenericTypeSignature(packageName, typeName));
typeProposal.setPackageName(packageName);
typeProposal.setTypeName(typeName);
typeProposal.setCompletion(typeCompletion);
typeProposal.setFlags(typeModifiers);
typeProposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
typeProposal.setTokenRange(this.startPosition - this.offset, this.endPosition - this.offset);
typeProposal.setRelevance(relevance);
switch (parameterCount) {
case -1: // default constructor
int flags = Flags.AccPublic;
if (Flags.isDeprecated(typeModifiers)) {
flags |= Flags.AccDeprecated;
}
if (isInterface || (typeModifiers & ClassFileConstants.AccAbstract) != 0) {
this.noProposal = false;
//{ObjectTeams: no anonymous roles:
if ((typeModifiers & ExtraCompilerModifiers.AccRole) != 0) {
break;
}
// SH}
if(!isIgnored(CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION, this.actualCompletionPosition);
proposal.setDeclarationSignature(createNonGenericTypeSignature(packageName, typeName));
proposal.setDeclarationKey(createBindingKey(packageName, typeName));
proposal.setSignature(DEFAULT_CONSTRUCTOR_SIGNATURE);
proposal.setDeclarationPackageName(packageName);
proposal.setDeclarationTypeName(typeName);
proposal.setParameterPackageNames(CharOperation.NO_CHAR_CHAR);
proposal.setParameterTypeNames(CharOperation.NO_CHAR_CHAR);
proposal.setParameterNames(CharOperation.NO_CHAR_CHAR);
proposal.setName(simpleTypeName);
proposal.setRequiredProposals(new CompletionProposal[]{typeProposal});
proposal.setIsContructor(true);
proposal.setCompletion(completion);
proposal.setFlags(flags);
proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
} else {
this.noProposal = false;
if(!isIgnored(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.CONSTRUCTOR_INVOCATION, this.actualCompletionPosition);
proposal.setDeclarationSignature(createNonGenericTypeSignature(packageName, typeName));
proposal.setSignature(DEFAULT_CONSTRUCTOR_SIGNATURE);
proposal.setDeclarationPackageName(packageName);
proposal.setDeclarationTypeName(typeName);
proposal.setParameterPackageNames(CharOperation.NO_CHAR_CHAR);
proposal.setParameterTypeNames(CharOperation.NO_CHAR_CHAR);
proposal.setParameterNames(CharOperation.NO_CHAR_CHAR);
proposal.setName(simpleTypeName);
proposal.setRequiredProposals(new CompletionProposal[]{typeProposal});
proposal.setIsContructor(true);
proposal.setCompletion(completion);
proposal.setFlags(flags);
proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
break;
case 0: // constructor with no parameter
if ((typeModifiers & ClassFileConstants.AccAbstract) != 0) {
//{ObjectTeams: no anonymous roles:
if ((typeModifiers & ExtraCompilerModifiers.AccRole) != 0) {
break;
}
// SH}
this.noProposal = false;
if(!isIgnored(CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION, this.actualCompletionPosition);
proposal.setDeclarationSignature(createNonGenericTypeSignature(packageName, typeName));
proposal.setDeclarationKey(createBindingKey(packageName, typeName));
proposal.setSignature(DEFAULT_CONSTRUCTOR_SIGNATURE);
proposal.setDeclarationPackageName(packageName);
proposal.setDeclarationTypeName(typeName);
proposal.setParameterPackageNames(CharOperation.NO_CHAR_CHAR);
proposal.setParameterTypeNames(CharOperation.NO_CHAR_CHAR);
proposal.setParameterNames(CharOperation.NO_CHAR_CHAR);
proposal.setName(simpleTypeName);
proposal.setRequiredProposals(new CompletionProposal[]{typeProposal});
proposal.setIsContructor(true);
proposal.setCompletion(completion);
proposal.setFlags(modifiers);
proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
} else {
this.noProposal = false;
if(!isIgnored(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.CONSTRUCTOR_INVOCATION, this.actualCompletionPosition);
proposal.setDeclarationSignature(createNonGenericTypeSignature(packageName, typeName));
proposal.setSignature(DEFAULT_CONSTRUCTOR_SIGNATURE);
proposal.setDeclarationPackageName(packageName);
proposal.setDeclarationTypeName(typeName);
proposal.setParameterPackageNames(CharOperation.NO_CHAR_CHAR);
proposal.setParameterTypeNames(CharOperation.NO_CHAR_CHAR);
proposal.setParameterNames(CharOperation.NO_CHAR_CHAR);
proposal.setName(simpleTypeName);
proposal.setRequiredProposals(new CompletionProposal[]{typeProposal});
proposal.setIsContructor(true);
proposal.setCompletion(completion);
proposal.setFlags(modifiers);
proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
break;
default: // constructor with parameter
if (signature == null) {
// resolve type to found parameter types
signature = getResolvedSignature(parameterTypes, fullyQualifiedName, parameterCount, scope);
if (signature == null) return;
} else {
signature = CharOperation.replaceOnCopy(signature, '/', '.');
}
int parameterNamesLength = parameterNames == null ? 0 : parameterNames.length;
if (parameterCount != parameterNamesLength) {
parameterNames = null;
}
if ((typeModifiers & ClassFileConstants.AccAbstract) != 0) {
this.noProposal = false;
if(!isIgnored(CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION, this.actualCompletionPosition);
proposal.setDeclarationSignature(createNonGenericTypeSignature(packageName, typeName));
proposal.setDeclarationKey(createBindingKey(packageName, typeName));
proposal.setSignature(signature);
proposal.setDeclarationPackageName(packageName);
proposal.setDeclarationTypeName(typeName);
proposal.setParameterPackageNames(CharOperation.NO_CHAR_CHAR);
proposal.setParameterTypeNames(CharOperation.NO_CHAR_CHAR);
if (parameterNames != null) {
proposal.setParameterNames(parameterNames);
} else {
proposal.setHasNoParameterNamesFromIndex(true);
}
proposal.setName(simpleTypeName);
proposal.setRequiredProposals(new CompletionProposal[]{typeProposal});
proposal.setIsContructor(true);
proposal.setCompletion(completion);
proposal.setFlags(modifiers);
proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
} else {
this.noProposal = false;
if(!isIgnored(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)) {
InternalCompletionProposal proposal = createProposal(CompletionProposal.CONSTRUCTOR_INVOCATION, this.actualCompletionPosition);
proposal.setDeclarationSignature(createNonGenericTypeSignature(packageName, typeName));
proposal.setSignature(signature);
proposal.setDeclarationPackageName(packageName);
proposal.setDeclarationTypeName(typeName);
proposal.setParameterPackageNames(CharOperation.NO_CHAR_CHAR);
proposal.setParameterTypeNames(CharOperation.NO_CHAR_CHAR);
if (parameterNames != null) {
proposal.setParameterNames(parameterNames);
} else {
proposal.setHasNoParameterNamesFromIndex(true);
}
proposal.setName(simpleTypeName);
proposal.setRequiredProposals(new CompletionProposal[]{typeProposal});
proposal.setIsContructor(true);
proposal.setCompletion(completion);
proposal.setFlags(modifiers);
proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
break;
}
}
private void proposeNewMethod(char[] token, ReferenceBinding reference) {
if(!this.requestor.isIgnored(CompletionProposal.POTENTIAL_METHOD_DECLARATION)) {
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for new method
InternalCompletionProposal proposal = createProposal(CompletionProposal.POTENTIAL_METHOD_DECLARATION, this.actualCompletionPosition);
proposal.setDeclarationSignature(getSignature(reference));
proposal.setSignature(
createMethodSignature(
CharOperation.NO_CHAR_CHAR,
CharOperation.NO_CHAR_CHAR,
CharOperation.NO_CHAR,
VOID));
proposal.setDeclarationPackageName(reference.qualifiedPackageName());
proposal.setDeclarationTypeName(reference.qualifiedSourceName());
//proposal.setPackageName(null);
proposal.setTypeName(VOID);
proposal.setName(token);
//proposal.setParameterPackageNames(null);
//proposal.setParameterTypeNames(null);
//proposal.setPackageName(null);
proposal.setCompletion(token);
proposal.setFlags(Flags.AccPublic);
proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
proposal.setRelevance(relevance);
this.requestor.accept(proposal);
if(DEBUG) {
this.printDebug(proposal);
}
}
}
private void proposeType(
char[] packageName,
char[] simpleTypeName,
int modifiers,
int accessibility,
char[] typeName,
char[] fullyQualifiedName,
boolean isQualified,
Scope scope) {
char[] completionName = fullyQualifiedName;
if(isQualified) {
if (packageName == null || packageName.length == 0)
if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
return; // ignore types from the default package from outside it
} else {
completionName = simpleTypeName;
}
TypeBinding guessedType = null;
if ((modifiers & ClassFileConstants.AccAnnotation) != 0 &&
this.assistNodeIsAnnotation &&
(this.targetedElement & TagBits.AnnotationTargetMASK) != 0) {
char[][] cn = CharOperation.splitOn('.', fullyQualifiedName);
TypeReference ref;
if (cn.length == 1) {
ref = new SingleTypeReference(simpleTypeName, 0);
} else {
ref = new QualifiedTypeReference(cn,new long[cn.length]);
}
switch (scope.kind) {
case Scope.METHOD_SCOPE :
case Scope.BLOCK_SCOPE :
guessedType = ref.resolveType((BlockScope)scope);
break;
case Scope.CLASS_SCOPE :
guessedType = ref.resolveType((ClassScope)scope);
break;
}
if (guessedType == null || !guessedType.isValidBinding()) return;
if (!hasPossibleAnnotationTarget(guessedType, scope)) return;
}
int relevance = computeBaseRelevance();
relevance += computeRelevanceForResolution();
relevance += computeRelevanceForInterestingProposal(packageName, fullyQualifiedName);
relevance += computeRelevanceForRestrictions(accessibility);
relevance += computeRelevanceForCaseMatching(this.completionToken, simpleTypeName);
relevance += computeRelevanceForExpectingType(packageName, simpleTypeName);
relevance += computeRelevanceForQualification(isQualified);
int kind = modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation);
switch (kind) {
case ClassFileConstants.AccAnnotation:
case ClassFileConstants.AccAnnotation | ClassFileConstants.AccInterface:
relevance += computeRelevanceForAnnotation();
if (guessedType != null) relevance += computeRelevanceForAnnotationTarget(guessedType);
relevance += computeRelevanceForInterface();
break;
case ClassFileConstants.AccEnum:
relevance += computeRelevanceForEnum();
break;
case ClassFileConstants.AccInterface:
relevance += computeRelevanceForInterface();
break;
default:
relevance += computeRelevanceForClass();
relevance += computeRelevanceForException(simpleTypeName);
break;
}
this.noProposal = false;
if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
createTypeProposal(packageName, typeName, modifiers, accessibility, completionName, relevance);
}
}
protected void reset() {
super.reset(false);
this.validPackageNames = new SimpleSetOfCharArray(10);
this.invalidPackageNames = new SimpleSetOfCharArray(1);
this.knownModules = new HashtableOfObject(10);
this.knownPkgs = new HashtableOfObject(10);
this.knownTypes = new HashtableOfObject(10);
if (this.noCacheNameEnvironment != null) {
this.noCacheNameEnvironment.cleanup();
this.noCacheNameEnvironment = null;
JavaModelManager.getJavaModelManager().flushZipFiles(this);
}
}
private void setSourceAndTokenRange(int start, int end) {
this.setSourceAndTokenRange(start, end, true);
}
private void setSourceAndTokenRange(int start, int end, boolean emptyTokenAdjstment) {
this.setSourceRange(start, end, emptyTokenAdjstment);
this.setTokenRange(start, end, emptyTokenAdjstment);
}
private void setSourceRange(int start, int end) {
this.setSourceRange(start, end, true);
}
private void setSourceRange(int start, int end, boolean emptyTokenAdjstment) {
this.startPosition = start;
if(emptyTokenAdjstment) {
int endOfEmptyToken = ((CompletionScanner)this.parser.scanner).endOfEmptyToken;
this.endPosition = endOfEmptyToken > end ? endOfEmptyToken + 1 : end + 1;
} else {
this.endPosition = end + 1;
}
}
private void setTokenRange(int start, int end) {
this.setTokenRange(start, end, true);
}
private void setTokenRange(int start, int end, boolean emptyTokenAdjstment) {
this.tokenStart = start;
if(emptyTokenAdjstment) {
int endOfEmptyToken = ((CompletionScanner)this.parser.scanner).endOfEmptyToken;
this.tokenEnd = endOfEmptyToken > end ? endOfEmptyToken + 1 : end + 1;
} else {
this.tokenEnd = end + 1;
}
}
private char[] substituteMethodTypeParameterName(char firstName, char startChar, char endChar, char[][] excludedNames, char[][] otherParameterNames) {
char name = firstName;
next : while (true) {
for (int i = 0 ; i < excludedNames.length ; i++){
if(excludedNames[i].length == 1 && ScannerHelper.toLowerCase(excludedNames[i][0]) == ScannerHelper.toLowerCase(name)) {
name++;
if(name > endChar)
name = startChar;
if(name == firstName)
return substituteMethodTypeParameterName(new char[]{firstName}, excludedNames, otherParameterNames);
continue next;
}
}
for (int i = 0; i < otherParameterNames.length; i++) {
if(otherParameterNames[i].length == 1 && ScannerHelper.toLowerCase(otherParameterNames[i][0]) == ScannerHelper.toLowerCase(name)) {
name++;
if(name > endChar)
name = startChar;
if(name == firstName)
return substituteMethodTypeParameterName(new char[]{firstName}, excludedNames, otherParameterNames);
continue next;
}
}
break next;
}
return new char[]{name};
}
private char[] substituteMethodTypeParameterName(char[] firstName, char[][] excludedNames, char[][] otherParameterNames) {
char[] name = firstName;
int count = 2;
next : while(true) {
for(int k = 0 ; k < excludedNames.length ; k++){
if(CharOperation.equals(name, excludedNames[k], false)) {
name = CharOperation.concat(firstName, String.valueOf(count++).toCharArray());
continue next;
}
}
for (int i = 0; i < otherParameterNames.length; i++) {
if(CharOperation.equals(name, otherParameterNames[i], false)) {
name = CharOperation.concat(firstName, String.valueOf(count++).toCharArray());
continue next;
}
}
break next;
}
return name;
}
private char[][] substituteMethodTypeParameterNames(TypeVariableBinding[] typeVariables, char[][] excludedNames) {
char[][] substituedParameterNames = new char[typeVariables.length][];
for (int i = 0; i < substituedParameterNames.length; i++) {
substituedParameterNames[i] = typeVariables[i].sourceName;
}
boolean foundConflicts = false;
nextTypeParameter : for (int i = 0; i < typeVariables.length; i++) {
TypeVariableBinding typeVariableBinding = typeVariables[i];
char[] methodParameterName = typeVariableBinding.sourceName;
for (int j = 0; j < excludedNames.length; j++) {
char[] typeParameterName = excludedNames[j];
if(CharOperation.equals(typeParameterName, methodParameterName, false)) {
char[] substitution;
if(methodParameterName.length == 1) {
if(ScannerHelper.isUpperCase(methodParameterName[0])) {
substitution = substituteMethodTypeParameterName(methodParameterName[0], 'A', 'Z', excludedNames, substituedParameterNames);
} else {
substitution = substituteMethodTypeParameterName(methodParameterName[0], 'a', 'z', excludedNames, substituedParameterNames);
}
} else {
substitution = substituteMethodTypeParameterName(methodParameterName, excludedNames, substituedParameterNames);
}
substituedParameterNames[i] = substitution;
foundConflicts = true;
continue nextTypeParameter;
}
}
}
if(foundConflicts) return substituedParameterNames;
return null;
}
//{ObjectTeams: added methods:
// helper for base.foo, tsuper.foo
private boolean isBaseAccess(InvocationSite invocationSite) {
if (invocationSite instanceof CompletionOnSingleNameReference)
return ((CompletionOnSingleNameReference)invocationSite).isBaseAccess;
if (invocationSite instanceof CompletionOnMemberAccess)
return ((CompletionOnMemberAccess)invocationSite).isBaseAccess;
return false;
}
private boolean isTSuperAccess(InvocationSite invocationSite) {
if (invocationSite instanceof CompletionOnSingleNameReference)
return ((CompletionOnSingleNameReference)invocationSite).isTSuperAccess;
return false;
}
private boolean canBeCompleted(char[] name) {
return !CharOperation.prefixEquals(IOTConstants.OT_DOLLAR_NAME, name);
}
// also filter out copy inherited versions:
private boolean canBeCompleted(MethodBinding method) {
return canBeCompleted(method.selector)
&& !TSuperHelper.isTSuper(method)
&& (method.copyInheritanceSrc == null);
}
// filter out __OT__ resp. _OT$
private boolean canTypeBeCompleted(char[] name) {
return !CharOperation.prefixEquals(IOTConstants.OT_DELIM_NAME, name);
}
private char[] stripOTPrefix(char[] name) {
if (CharOperation.prefixEquals(IOTConstants.OT_DOLLAR_NAME, name))
return CharOperation.subarray(name, IOTConstants.OT_DOLLAR_LEN, -1);
return name;
}
// helper for computeForbiddenBindings
private void addForbiddenBaseclasses (ReferenceBinding roleType) {
if (!roleType.isRole())
return;
// no siblings (members of direct enclosing team):
ReferenceBinding currentEnclosing= roleType.enclosingType();
for (ReferenceBinding member : currentEnclosing.memberTypes()) {
addForbiddenBindings(member); // shallow!
this.knownTypes.put(CharOperation.concat(member.qualifiedPackageName(), member.qualifiedSourceName(), '.'), this);
}
// no enclosing/super-paths
while (currentEnclosing != null) {
ReferenceBinding currentSuper= currentEnclosing;
do {
addAll(currentSuper);
currentSuper= currentSuper.superclass();
} while (currentSuper.isTeam());
currentEnclosing= currentEnclosing.enclosingType();
}
}
private void addAll(ReferenceBinding typeBinding) {
addForbiddenBindings(typeBinding);
this.knownTypes.put(CharOperation.concat(typeBinding.qualifiedPackageName(), typeBinding.qualifiedSourceName(), '.'), this);
if (typeBinding.isTeam())
for (ReferenceBinding member : typeBinding.memberTypes())
addAll(member);
}
private void completionOnMethodSpec(ASTNode astNode, Binding qualifiedBinding, Scope scope) {
setSourceAndTokenRange(astNode.sourceStart, astNode.sourceEnd, false);
CompletionOnMethodSpec methodSpec = (CompletionOnMethodSpec) astNode;
this.completionToken = methodSpec.selector;
final int start = methodSpec.sourceStart;
final int end = methodSpec.sourceEnd;
if (qualifiedBinding == null) {
// no base class? can't proceed
} else if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
TypeBinding returnType = null;
if (methodSpec.returnType != null)
returnType = methodSpec.returnType.resolvedType;
// soft filter: inspect the role method for expected return type:
AbstractMethodMappingDeclaration mapping = null;
if (scope instanceof CallinCalloutScope)
mapping = (AbstractMethodMappingDeclaration)scope.referenceContext();
if (mapping != null) {
this.expectedTypesFilter = SUBTYPE;
TypeReference returnTypeRef = mapping.roleMethodSpec.returnType;
if (returnTypeRef != null && returnTypeRef.resolvedType != TypeBinding.VOID)
addExpectedType(returnTypeRef.resolvedType, scope);
}
// treating MethodSpec(long) like a call, we need a fake InvocationSite:
InvocationSite site = null;
if (methodSpec.hasSignature)
site = FakeInvocationSite;
try {
this.currentMethodMapping = mapping;
findMethods(
this.completionToken,
null, // no type args (TODO(GENERIC))
null, // parameters (completing before parameters are entered)
(ReferenceBinding) qualifiedBinding, // receiver is the baseclass
scope,
new ObjectVector(),
false,
false, // no exact match
CompletionProposal.OT_METHOD_SPEC,
returnType,
site,
scope,
false,
false, // not a super reference
true,
null,
null,
null,
false,
null,
-1,
-1);
// also check callout to field right at "rm -> get|" or "rm -> set|"
if (methodSpec.selector.length == 3) {
char[] selector= methodSpec.selector;
int fieldAccessKind= 0;
if (CharOperation.prefixEquals(GET, selector))
fieldAccessKind= TerminalTokens.TokenNameget;
else if (CharOperation.prefixEquals(SET, selector))
fieldAccessKind= TerminalTokens.TokenNameset;
if (fieldAccessKind != 0) {
this.startPosition += 3;
this.seperator= ' ';
selector= mapping.roleMethodSpec.selector;
if (selector.length > 3) {
selector= CharOperation.subarray(selector, 3, -1);
selector[0]= Character.toLowerCase(selector[0]);
this.completionToken= selector;
}
boolean hasSignature= mapping.hasSignature;
TypeBinding fieldType= null;
if (hasSignature) {
if (fieldAccessKind == TerminalTokens.TokenNameget)
fieldType= mapping.roleMethodSpec.resolvedType();
else {
TypeBinding[] parameters= mapping.roleMethodSpec.parameters;
if (parameters != null && parameters.length == 1)
fieldType= parameters[0];
}
}
completeCalloutToField((ReferenceBinding) qualifiedBinding, scope, start, end,
fieldAccessKind, hasSignature, fieldType);
}
}
} finally {
this.currentMethodMapping = null;
this.seperator= 0;
}
}
}
private void completionOnFieldAccessSpec(ASTNode astNode, Binding qualifiedBinding, Scope scope) {
setSourceAndTokenRange(astNode.sourceStart, astNode.sourceEnd, false);
CompletionOnFieldAccessSpec fieldSpec = (CompletionOnFieldAccessSpec) astNode;
this.completionToken = fieldSpec.selector;
if (fieldSpec.selector.length == 0) {
MethodSpec roleMeth= ((AbstractMethodMappingDeclaration)scope.referenceContext()).roleMethodSpec;
char[] selector= roleMeth.selector;
if ( selector.length > 3
&& ( CharOperation.prefixEquals(GET, selector)
|| CharOperation.prefixEquals(SET, selector)))
{
selector= CharOperation.subarray(selector, 3, -1);
selector[0]= Character.toLowerCase(selector[0]);
this.completionToken= selector;
}
}
final int start = fieldSpec.sourceStart;
final int end = fieldSpec.sourceEnd;
if (qualifiedBinding == null) {
// no base class? can't proceed
} else if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
int fieldAccessKind = fieldSpec.calloutModifier;
boolean hasSignature = fieldSpec.hasSignature;
TypeBinding fieldType = null;
// strict filter: type name already typed in:
if (fieldSpec.returnType != null)
fieldType = fieldSpec.returnType.resolvedType;
completeCalloutToField((ReferenceBinding) qualifiedBinding, scope, start, end,
fieldAccessKind, hasSignature, fieldType);
}
}
// search for fields for callout-to-field
private void completeCalloutToField(ReferenceBinding baseclassBinding, Scope scope,
final int start, final int end,
int fieldAccessKind, boolean hasSignature, TypeBinding fieldType)
{
AbstractMethodMappingDeclaration callout = null;
if (scope instanceof CallinCalloutScope)
callout = (AbstractMethodMappingDeclaration)scope.referenceContext();
if (callout != null) {
// soft filter: inspect the role method for expected field type:
this.expectedTypesFilter = SUBTYPE;
if (fieldAccessKind == TerminalTokens.TokenNameset) {
TypeBinding[] parameters = callout.roleMethodSpec.parameters;
if (parameters != null && parameters.length == 1)
addExpectedType(parameters[0], scope);
} else if (fieldAccessKind == TerminalTokens.TokenNameget) {
TypeReference returnType = callout.roleMethodSpec.returnType;
if (returnType != null)
addExpectedType(returnType.resolvedType, scope);
}
}
// treating FieldAccessSpec(long) like a field access, we need a fake InvocationSite:
InvocationSite site = null;
if (hasSignature)
site = FakeInvocationSite;
ObjectVector fieldsFound = new ObjectVector();
findFields(
this.completionToken,
baseclassBinding,
scope,
fieldsFound,
new ObjectVector(),
false, /*only static*/
CompletionProposal.OT_FIELD_SPEC,
fieldType,
site,
scope,
true, /*implicitCall*/
false, /*canBePrefixed*/
null,
null,
null,
false,
null,
-1,
-1);
if (this.completionToken != null && this.completionToken.length > 0) {
// repeat search w/o a selector this time:
this.completionToken= new char[0];
findFields(
this.completionToken,
baseclassBinding,
scope,
fieldsFound,
new ObjectVector(),
false, /*only static*/
CompletionProposal.OT_FIELD_SPEC,
fieldType,
site,
scope,
true, /*implicitCall*/
false, /*canBePrefixed*/
null,
null,
null,
false,
null,
-1,
-1);
}
}
// add callout-bound fields to fieldsFound.
private void addExistingCalloutToFields(ReferenceBinding receiverType, ReferenceBinding baseclass, char[] selector, ObjectVector fieldsFound) {
TypeDeclaration roleType = receiverType.roleModel.getAst();
if (roleType != null) {
AbstractMethodMappingDeclaration[] callinCallouts = roleType.callinCallouts;
if (callinCallouts != null) {
for (AbstractMethodMappingDeclaration callinCallout : callinCallouts) {
// note: callouts are not resolved, have to analyze manually:
if(!callinCallout.ignoreFurtherInvestigation && callinCallout.isCallout())
{
CalloutMappingDeclaration callout = (CalloutMappingDeclaration)callinCallout;
if (callout.isCalloutToField())
{
char[] rmSelector = callout.roleMethodSpec.selector;
if (CharOperation.prefixEquals(selector, rmSelector))
{
char[] fieldName = callout.baseMethodSpec.selector;
FieldBinding field = baseclass.getField(fieldName, false);
if (field != null)
fieldsFound.add(new Object[]{field, receiverType});
}
}
}
}
}
}
}
// callout (OT_COPY_PASTE: largely copied from createMethod())
private void createMethodBinding(MethodBinding method,
char[][] parameterPackageNames,
char[][] parameterTypeNames,
char[][] parameterNames,
int kind, // OT_CALLOUT_DECLARATION or OT_CALLOUT_OVERRIDE_DECLARATION or OT_CALLIN_DECLARATION
Scope scope,
StringBuffer completion)
{
//// NO Modifiers
//// Type parameters
TypeVariableBinding[] typeVariableBindings = method.typeVariables;
if(typeVariableBindings != null && typeVariableBindings.length != 0) {
completion.append('<');
for (int i = 0; i < typeVariableBindings.length; i++) {
if(i != 0) {
completion.append(',');
completion.append(' ');
}
createTypeVariable(typeVariableBindings[i], scope, completion);
}
completion.append('>');
completion.append(' ');
}
//// Return type
createType(method.returnType, scope, completion);
completion.append(' ');
//// Selector
completion.append(method.selector);
completion.append('(');
////Parameters
TypeBinding[] parameterTypes = method.parameters;
int length = parameterTypes.length;
for (int i = 0; i < length; i++) {
if(i != 0) {
completion.append(',');
completion.append(' ');
}
createType(parameterTypes[i], scope, completion);
completion.append(' ');
if(parameterNames != null){
completion.append(parameterNames[i]);
} else {
completion.append('%');
}
}
completion.append(')');
//// NO Exceptions
if (method.thrownExceptions != Binding.NO_EXCEPTIONS)
completion.append("/*thrown exceptions*/"); //$NON-NLS-1$
// store lhs:
String methodSpec = completion.toString();
// callout/callin token:
switch (kind) {
case CompletionProposal.OT_CALLOUT_OVERRIDE_DECLARATION:
completion.append(" => "); break; //$NON-NLS-1$
case CompletionProposal.OT_CALLOUT_DECLARATION:
completion.append(" -> "); break; //$NON-NLS-1$
case CompletionProposal.OT_CALLIN_DECLARATION:
completion.append(" <- before "); break; //$NON-NLS-1$
}
// rhs is the same as lhs ;-)
completion.append(methodSpec);
completion.append(';');
}
private char[] createCalloutToField(int kind, boolean isOverride, FieldBinding field, Scope scope) {
StringBuffer completion = new StringBuffer();
char[] methodName = getCalloutToFieldName(kind, field.name);
if (kind == CompletionProposal.OT_CALLOUT_GET) {
// role method spec:
// return type
createType(field.type, scope, completion);
// selector
completion.append(' ');
completion.append(methodName);
// params + constant part
if (isOverride)
completion.append("() => get "); //$NON-NLS-1$
else
completion.append("() -> get "); //$NON-NLS-1$
} else {
// return type
completion.append("void "); //$NON-NLS-1$
// selector
completion.append(methodName);
// params
completion.append('(');
createType(field.type, scope, completion);
completion.append(' ');
completion.append(field.name);
// constant part.
if (isOverride)
completion.append(") => set "); //$NON-NLS-1$
else
completion.append(") -> set "); //$NON-NLS-1$
}
// field spec:
createType(field.type, scope, completion);
completion.append(' ');
completion.append(field.name);
completion.append(';');
char[] result = new char[completion.length()];
completion.getChars(0, result.length, result, 0);
return result;
}
private void inferCallouts(
char[] selector,
TypeBinding[] typeArgTypes,
TypeBinding[] argTypes,
ReferenceBinding receiverType,
Scope scope,
ObjectVector methodsFound,
boolean onlyStaticMethods,
boolean exactMatch,
int kind,
TypeBinding expectedType,
InvocationSite invocationSite,
Scope invocationScope,
boolean implicitCall,
boolean superCall,
boolean canBePrefixed,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems,
char[] castedReceiver,
int receiverStart,
int receiverEnd)
{
ReferenceBinding baseclass = receiverType.baseclass();
boolean inferredCalloutAllowed = implicitCall;
if (!implicitCall && invocationSite instanceof CompletionOnMemberAccess)
inferredCalloutAllowed = ((CompletionOnMemberAccess)invocationSite).receiver.isThis();
if (baseclass != null && inferredCalloutAllowed) {
boolean checkVis = this.options.checkVisibility;
try {
this.options.checkVisibility = false;
findMethods(
selector,
typeArgTypes,
argTypes,
baseclass,
scope,
methodsFound,
onlyStaticMethods,
exactMatch,
kind,
expectedType,
invocationSite,
invocationScope,
implicitCall,
superCall,
canBePrefixed,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
castedReceiver,
receiverStart,
receiverEnd);
} finally {
this.options.checkVisibility = checkVis;
}
}
}
private void inferCalloutDeclarations(
char[] selector,
ReferenceBinding receiverType,
Scope scope,
ObjectVector methodsFound,
Binding[] missingElements,
int[] missingElementsStarts,
int[] missingElementsEnds,
boolean missingElementsHaveProblems)
{
ReferenceBinding baseclass = receiverType.baseclass();
// prepare for callout-to-field:
ObjectVector fieldsFound = new ObjectVector();
// record existing callout-to-field:
if (baseclass != null)
addExistingCalloutToFields(receiverType, baseclass, selector, fieldsFound);
int calloutToFieldKind = -1;
char[] fieldName = null;
if (CharOperation.prefixEquals(GET, selector))
calloutToFieldKind = CompletionProposal.OT_CALLOUT_GET;
else if (CharOperation.prefixEquals(SET, selector))
calloutToFieldKind = CompletionProposal.OT_CALLOUT_SET;
if (calloutToFieldKind > -1) {
fieldName = CharOperation.subarray(selector, 3, -1);
if (fieldName.length > 0)
fieldName[0] = Character.toLowerCase(fieldName[0]);
}
int superBaseFlag= 0;
while (baseclass != null) {
MethodBinding[] basemethods = baseclass.availableMethods();
if (basemethods != null) {
findLocalMethodDeclarations(
selector,
basemethods,
scope,
methodsFound,
false, // no exactMatch
CompletionProposal.OT_CALLOUT_DECLARATION+superBaseFlag,
receiverType);
}
if (calloutToFieldKind > -1) {
FieldBinding[] fields = baseclass.availableFields();
if (fields != null) {
findFields(
fieldName,
fields,
scope,
fieldsFound,
new ObjectVector(),
false, /* only static fields */
calloutToFieldKind+superBaseFlag,
null, // expected type
baseclass,
null,
null,
false, // implicitCall
false /*canBePrefixed*/,
missingElements,
missingElementsStarts,
missingElementsEnds,
missingElementsHaveProblems,
null, // castedReceiver
-1, // receiverStart
-1); // receiverEnd
}
}
baseclass = baseclass.superclass();
// don't propose privates from base class's super:
superBaseFlag= SEARCH_SUPER_BASE;
}
methodsFound.addAll(fieldsFound);
}
// support callout-to-field:
private char[] getCalloutToFieldName(int kind, char[] name) {
char[] methodName = new char[name.length+3];
System.arraycopy(name, 0, methodName, 3, name.length);
methodName[0] = (kind == CompletionProposal.OT_CALLOUT_GET) ? 'g' : 's';
methodName[1] = 'e';
methodName[2] = 't';
methodName[3] = Character.toUpperCase(methodName[3]);
return methodName;
}
private char[] getCalloutToFieldSignature(int kind, TypeBinding type) {
char[] typeSig = getSignature(type);
if (kind == CompletionProposal.OT_CALLOUT_GET)
return CharOperation.concat("()".toCharArray(), typeSig); //$NON-NLS-1$
return CharOperation.concat(new char[]{'('}, typeSig, ")V".toCharArray()); //$NON-NLS-1$
}
// prepend the type to a RHS method spec:
private char[] prependType(TypeBinding type, Scope scope, char[] completion) {
if (this.currentMethodMapping != null) {
if (!this.currentMethodMapping.hasSignature)
return completion; // unmodified for short version
}
StringBuffer buf = new StringBuffer();
createType(type, scope, buf);
char[] chars = new char[buf.length()];
buf.getChars(0, buf.length(), chars, 0);
completion = CharOperation.concat(chars, completion, ' ');
return completion;
}
// SH}
}