| /******************************************************************************* |
| * Copyright (c) 2000, 2018 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.core; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| |
| import org.eclipse.jdt.core.Flags; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IField; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IMethod; |
| import org.eclipse.jdt.core.IModuleDescription; |
| import org.eclipse.jdt.core.IPackageFragment; |
| import org.eclipse.jdt.core.ISourceRange; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.ITypeParameter; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.Signature; |
| import org.eclipse.jdt.core.compiler.*; |
| import org.eclipse.jdt.internal.codeassist.ISelectionRequestor; |
| import org.eclipse.jdt.internal.codeassist.SelectionEngine; |
| import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; |
| import org.eclipse.jdt.internal.compiler.ast.LambdaExpression; |
| import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; |
| import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; |
| import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; |
| import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; |
| import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; |
| import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; |
| import org.eclipse.jdt.internal.compiler.lookup.MethodScope; |
| import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; |
| import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; |
| import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; |
| import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; |
| import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; |
| import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; |
| import org.eclipse.jdt.internal.core.NameLookup.Answer; |
| import org.eclipse.jdt.internal.core.util.HandleFactory; |
| import org.eclipse.jdt.internal.core.util.Util; |
| |
| /** |
| * Implementation of <code>ISelectionRequestor</code> to assist with |
| * code resolve in a compilation unit. Translates names to elements. |
| */ |
| @SuppressWarnings({"rawtypes", "unchecked"}) |
| public class SelectionRequestor implements ISelectionRequestor { |
| /* |
| * The name lookup facility used to resolve packages |
| */ |
| protected NameLookup nameLookup; |
| |
| /* |
| * The compilation unit or class file we are resolving in |
| */ |
| protected Openable openable; |
| |
| /* |
| * The collection of resolved elements. |
| */ |
| protected IJavaElement[] elements = JavaElement.NO_ELEMENTS; |
| protected int elementIndex = -1; |
| |
| protected HandleFactory handleFactory = new HandleFactory(); |
| |
| /** |
| * Creates a selection requestor that uses that given |
| * name lookup facility to resolve names. |
| * |
| * Fix for 1FVXGDK |
| */ |
| public SelectionRequestor(NameLookup nameLookup, Openable openable) { |
| super(); |
| this.nameLookup = nameLookup; |
| this.openable = openable; |
| } |
| private void acceptBinaryMethod( |
| IType type, |
| IMethod method, |
| char[] uniqueKey, |
| boolean isConstructor) { |
| try { |
| if(!isConstructor || ((JavaElement)method).getClassFile().getBuffer() == null) { |
| if (uniqueKey != null) { |
| ResolvedBinaryMethod resolvedMethod = new ResolvedBinaryMethod( |
| (JavaElement)method.getParent(), |
| method.getElementName(), |
| method.getParameterTypes(), |
| new String(uniqueKey)); |
| resolvedMethod.occurrenceCount = method.getOccurrenceCount(); |
| method = resolvedMethod; |
| } |
| |
| addElement(method); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept method("); //$NON-NLS-1$ |
| System.out.print(method.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } else { |
| ISourceRange range = method.getSourceRange(); |
| if (range.getOffset() != -1 && range.getLength() != 0 ) { |
| if (uniqueKey != null) { |
| ResolvedBinaryMethod resolvedMethod = new ResolvedBinaryMethod( |
| (JavaElement)method.getParent(), |
| method.getElementName(), |
| method.getParameterTypes(), |
| new String(uniqueKey)); |
| resolvedMethod.occurrenceCount = method.getOccurrenceCount(); |
| method = resolvedMethod; |
| } |
| addElement(method); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept method("); //$NON-NLS-1$ |
| System.out.print(method.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } else { |
| // no range was actually found, but a method was originally given -> default constructor |
| addElement(type); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept type("); //$NON-NLS-1$ |
| System.out.print(type.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } |
| } |
| } catch (JavaModelException e) { |
| // an exception occurs, return nothing |
| } |
| } |
| /** |
| * Resolve the binary method |
| * |
| * fix for 1FWFT6Q |
| */ |
| protected void acceptBinaryMethod( |
| IType type, |
| char[] selector, |
| char[][] parameterPackageNames, |
| char[][] parameterTypeNames, |
| String[] parameterSignatures, |
| char[][] typeParameterNames, |
| char[][][] typeParameterBoundNames, |
| char[] uniqueKey, |
| boolean isConstructor) { |
| IMethod method= type.getMethod(new String(selector), parameterSignatures); |
| |
| if (method.exists()) { |
| if (typeParameterNames != null && typeParameterNames.length != 0) { |
| IMethod[] methods = type.findMethods(method); |
| if (methods != null && methods.length > 1) { |
| for (int i = 0; i < methods.length; i++) { |
| if (areTypeParametersCompatible(methods[i], typeParameterNames, typeParameterBoundNames)) { |
| acceptBinaryMethod(type, method, uniqueKey, isConstructor); |
| } |
| } |
| return; |
| } |
| } |
| acceptBinaryMethod(type, method, uniqueKey, isConstructor); |
| } |
| } |
| @Override |
| public void acceptModule(char[] moduleName, char[] uniqueKey, int start, int end) { |
| IModuleDescription module = resolveModule(moduleName); |
| addElement(module); |
| } |
| /** |
| * Resolve the type. |
| */ |
| public void acceptType(char[] packageName, char[] typeName, int modifiers, boolean isDeclaration, char[] uniqueKey, int start, int end) { |
| int acceptFlags = 0; |
| int kind = modifiers & (ClassFileConstants.AccInterface|ClassFileConstants.AccEnum|ClassFileConstants.AccAnnotation); |
| switch (kind) { |
| case ClassFileConstants.AccAnnotation: |
| case ClassFileConstants.AccAnnotation|ClassFileConstants.AccInterface: |
| acceptFlags = NameLookup.ACCEPT_ANNOTATIONS; |
| break; |
| case ClassFileConstants.AccEnum: |
| acceptFlags = NameLookup.ACCEPT_ENUMS; |
| break; |
| case ClassFileConstants.AccInterface: |
| acceptFlags = NameLookup.ACCEPT_INTERFACES; |
| break; |
| default: |
| acceptFlags = NameLookup.ACCEPT_CLASSES; |
| break; |
| } |
| IType type = null; |
| if(isDeclaration) { |
| type = resolveTypeByLocation(packageName, typeName, acceptFlags, start, end); |
| } else { |
| type = resolveType(packageName, typeName, acceptFlags); |
| if(type != null ) { |
| String key = uniqueKey == null ? type.getKey() : new String(uniqueKey); |
| if(type.isBinary()) { |
| ResolvedBinaryType resolvedType = new ResolvedBinaryType((JavaElement)type.getParent(), type.getElementName(), key); |
| resolvedType.occurrenceCount = type.getOccurrenceCount(); |
| type = resolvedType; |
| } else { |
| ResolvedSourceType resolvedType = new ResolvedSourceType((JavaElement)type.getParent(), type.getElementName(), key); |
| resolvedType.occurrenceCount = type.getOccurrenceCount(); |
| type = resolvedType; |
| } |
| } |
| } |
| |
| if (type != null) { |
| addElement(type); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept type("); //$NON-NLS-1$ |
| System.out.print(type.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } |
| } |
| /** |
| * Resolve the type. |
| */ |
| public void acceptType(IType type) { |
| String key = type.getKey(); |
| if(type.isBinary()) { |
| ResolvedBinaryType resolvedType = new ResolvedBinaryType((JavaElement)type.getParent(), type.getElementName(), key); |
| resolvedType.occurrenceCount = type.getOccurrenceCount(); |
| type = resolvedType; |
| } else { |
| ResolvedSourceType resolvedType = new ResolvedSourceType((JavaElement)type.getParent(), type.getElementName(), key); |
| resolvedType.occurrenceCount = type.getOccurrenceCount(); |
| type = resolvedType; |
| } |
| |
| addElement(type); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept type("); //$NON-NLS-1$ |
| System.out.print(type.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } |
| /** |
| * @see ISelectionRequestor#acceptError |
| */ |
| public void acceptError(CategorizedProblem error) { |
| // do nothing |
| } |
| /** |
| * Resolve the field. |
| */ |
| public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, boolean isDeclaration, char[] uniqueKey, int start, int end) { |
| if(isDeclaration) { |
| IType type= resolveTypeByLocation(declaringTypePackageName, declaringTypeName, |
| NameLookup.ACCEPT_ALL, |
| start, end); |
| if(type != null) { |
| try { |
| IField[] fields = type.getFields(); |
| for (int i = 0; i < fields.length; i++) { |
| IField field = fields[i]; |
| ISourceRange range = field.getNameRange(); |
| if(range.getOffset() <= start |
| && range.getOffset() + range.getLength() >= end |
| && field.getElementName().equals(new String(name))) { |
| addElement(fields[i]); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept field("); //$NON-NLS-1$ |
| System.out.print(field.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| return; // only one method is possible |
| } |
| } |
| } catch (JavaModelException e) { |
| return; |
| } |
| } |
| } else { |
| IType type= resolveType(declaringTypePackageName, declaringTypeName, NameLookup.ACCEPT_ALL); |
| if (type != null) { |
| IField field= type.getField(new String(name)); |
| if (field.exists()) { |
| if (uniqueKey != null) { |
| if(field.isBinary()) { |
| ResolvedBinaryField resolvedField = new ResolvedBinaryField( |
| (JavaElement)field.getParent(), |
| field.getElementName(), |
| new String(uniqueKey)); |
| resolvedField.occurrenceCount = field.getOccurrenceCount(); |
| field = resolvedField; |
| } else { |
| ResolvedSourceField resolvedField = new ResolvedSourceField( |
| (JavaElement)field.getParent(), |
| field.getElementName(), |
| new String(uniqueKey)); |
| resolvedField.occurrenceCount = field.getOccurrenceCount(); |
| field = resolvedField; |
| } |
| } |
| addElement(field); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept field("); //$NON-NLS-1$ |
| System.out.print(field.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } |
| } |
| } |
| } |
| public void acceptLocalField(FieldBinding fieldBinding) { |
| IJavaElement res; |
| if(fieldBinding.declaringClass instanceof ParameterizedTypeBinding) { |
| LocalTypeBinding localTypeBinding = (LocalTypeBinding)((ParameterizedTypeBinding)fieldBinding.declaringClass).genericType(); |
| res = findLocalElement(localTypeBinding.sourceStart()); |
| } else { |
| SourceTypeBinding typeBinding = (SourceTypeBinding)fieldBinding.declaringClass; |
| res = findLocalElement(typeBinding.sourceStart()); |
| } |
| if (res != null && res.getElementType() == IJavaElement.TYPE) { |
| IType type = (IType) res; |
| IField field= type.getField(new String(fieldBinding.name)); |
| if (field.exists()) { |
| char[] uniqueKey = fieldBinding.computeUniqueKey(); |
| if(field.isBinary()) { |
| ResolvedBinaryField resolvedField = new ResolvedBinaryField( |
| (JavaElement)field.getParent(), |
| field.getElementName(), |
| new String(uniqueKey)); |
| resolvedField.occurrenceCount = field.getOccurrenceCount(); |
| field = resolvedField; |
| } else { |
| ResolvedSourceField resolvedField = new ResolvedSourceField( |
| (JavaElement)field.getParent(), |
| field.getElementName(), |
| new String(uniqueKey)); |
| resolvedField.occurrenceCount = field.getOccurrenceCount(); |
| field = resolvedField; |
| } |
| addElement(field); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept field("); //$NON-NLS-1$ |
| System.out.print(field.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } |
| } |
| } |
| public void acceptLocalMethod(MethodBinding methodBinding) { |
| IJavaElement res = findLocalElement(methodBinding.original().sourceStart()); |
| if(res != null) { |
| if(res.getElementType() == IJavaElement.METHOD) { |
| IMethod method = (IMethod) res; |
| |
| char[] uniqueKey = methodBinding.computeUniqueKey(); |
| if(method.isBinary()) { |
| ResolvedBinaryMethod resolvedRes = new ResolvedBinaryMethod( |
| (JavaElement)res.getParent(), |
| method.getElementName(), |
| method.getParameterTypes(), |
| new String(uniqueKey)); |
| resolvedRes.occurrenceCount = method.getOccurrenceCount(); |
| res = resolvedRes; |
| } else { |
| ResolvedSourceMethod resolvedRes = new ResolvedSourceMethod( |
| (JavaElement)res.getParent(), |
| method.getElementName(), |
| method.getParameterTypes(), |
| new String(uniqueKey)); |
| resolvedRes.occurrenceCount = method.getOccurrenceCount(); |
| res = resolvedRes; |
| } |
| addElement(res); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept method("); //$NON-NLS-1$ |
| System.out.print(res.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } else if(methodBinding.selector == TypeConstants.INIT && res.getElementType() == IJavaElement.TYPE) { |
| // it's a default constructor |
| res = ((JavaElement)res).resolved(methodBinding.declaringClass); |
| addElement(res); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept type("); //$NON-NLS-1$ |
| System.out.print(res.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } |
| } |
| } |
| public void acceptLocalType(TypeBinding typeBinding) { |
| IJavaElement res = null; |
| if(typeBinding instanceof ParameterizedTypeBinding) { |
| LocalTypeBinding localTypeBinding = (LocalTypeBinding)((ParameterizedTypeBinding)typeBinding).genericType(); |
| res = findLocalElement(localTypeBinding.sourceStart()); |
| } else if(typeBinding instanceof SourceTypeBinding) { |
| res = findLocalElement(((SourceTypeBinding)typeBinding).sourceStart()); |
| } |
| if(res != null && res.getElementType() == IJavaElement.TYPE) { |
| res = ((JavaElement)res).resolved(typeBinding); |
| addElement(res); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept type("); //$NON-NLS-1$ |
| System.out.print(res.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } |
| } |
| public void acceptLocalTypeParameter(TypeVariableBinding typeVariableBinding) { |
| IJavaElement res; |
| if(typeVariableBinding.declaringElement instanceof ParameterizedTypeBinding) { |
| LocalTypeBinding localTypeBinding = (LocalTypeBinding)((ParameterizedTypeBinding)typeVariableBinding.declaringElement).genericType(); |
| res = findLocalElement(localTypeBinding.sourceStart()); |
| } else { |
| SourceTypeBinding typeBinding = (SourceTypeBinding)typeVariableBinding.declaringElement; |
| res = findLocalElement(typeBinding.sourceStart()); |
| } |
| if (res != null && res.getElementType() == IJavaElement.TYPE) { |
| IType type = (IType) res; |
| ITypeParameter typeParameter = type.getTypeParameter(new String(typeVariableBinding.sourceName)); |
| if (typeParameter.exists()) { |
| addElement(typeParameter); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept type parameter("); //$NON-NLS-1$ |
| System.out.print(typeParameter.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } |
| } |
| } |
| public void acceptLocalMethodTypeParameter(TypeVariableBinding typeVariableBinding) { |
| MethodBinding methodBinding = (MethodBinding)typeVariableBinding.declaringElement; |
| IJavaElement res = findLocalElement(methodBinding.sourceStart()); |
| if(res != null && res.getElementType() == IJavaElement.METHOD) { |
| IMethod method = (IMethod) res; |
| |
| ITypeParameter typeParameter = method.getTypeParameter(new String(typeVariableBinding.sourceName)); |
| if (typeParameter.exists()) { |
| addElement(typeParameter); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept type parameter("); //$NON-NLS-1$ |
| System.out.print(typeParameter.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } |
| } |
| } |
| public void acceptLocalVariable(LocalVariableBinding binding, org.eclipse.jdt.internal.compiler.env.ICompilationUnit unit) { |
| LocalDeclaration local = binding.declaration; |
| IJavaElement parent = null; |
| if (binding.declaringScope.isLambdaSubscope() && unit instanceof ICompilationUnit) { |
| HashSet existingElements = new HashSet(); |
| HashMap knownScopes = new HashMap(); |
| parent = this.handleFactory.createElement(binding.declaringScope, local.sourceStart, (ICompilationUnit) unit, existingElements, knownScopes); |
| } else { |
| parent = findLocalElement(local.sourceStart, binding.declaringScope.methodScope()); // findLocalElement() cannot find local variable |
| } |
| LocalVariable localVar = null; |
| if(parent != null) { |
| String typeSig = null; |
| if (local.type == null || local.type.isTypeNameVar(binding.declaringScope)) { |
| typeSig = Signature.createTypeSignature(binding.type.signableName(), true);// : Util.typeSignature(local.type) |
| } else { |
| typeSig = Util.typeSignature(local.type); |
| } |
| localVar = new LocalVariable( |
| (JavaElement)parent, |
| new String(local.name), |
| local.declarationSourceStart, |
| local.declarationSourceEnd, |
| local.sourceStart, |
| local.sourceEnd, |
| typeSig, |
| local.annotations, |
| local.modifiers, |
| local.getKind() == AbstractVariableDeclaration.PARAMETER); |
| } |
| if (localVar != null) { |
| addElement(localVar); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept local variable("); //$NON-NLS-1$ |
| System.out.print(localVar.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } |
| } |
| /** |
| * Resolve the method |
| */ |
| public void acceptMethod( |
| char[] declaringTypePackageName, |
| char[] declaringTypeName, |
| String enclosingDeclaringTypeSignature, |
| char[] selector, |
| char[][] parameterPackageNames, |
| char[][] parameterTypeNames, |
| String[] parameterSignatures, |
| char[][] typeParameterNames, |
| char[][][] typeParameterBoundNames, |
| boolean isConstructor, |
| boolean isDeclaration, |
| char[] uniqueKey, |
| int start, |
| int end) { |
| IJavaElement[] previousElement = this.elements; |
| int previousElementIndex = this.elementIndex; |
| this.elements = JavaElement.NO_ELEMENTS; |
| this.elementIndex = -1; |
| |
| if(isDeclaration) { |
| IType type = resolveTypeByLocation(declaringTypePackageName, declaringTypeName, |
| NameLookup.ACCEPT_ALL, |
| start, end); |
| |
| if(type != null) { |
| acceptMethodDeclaration(type, selector, start, end); |
| } |
| } else { |
| IType type = resolveType(declaringTypePackageName, declaringTypeName, |
| NameLookup.ACCEPT_ALL); |
| // fix for 1FWFT6Q |
| if (type != null) { |
| if (type.isBinary()) { |
| |
| // need to add a paramater for constructor in binary type |
| IType declaringDeclaringType = type.getDeclaringType(); |
| |
| boolean isStatic = false; |
| try { |
| isStatic = Flags.isStatic(type.getFlags()); |
| } catch (JavaModelException e) { |
| // isStatic == false |
| } |
| |
| if(declaringDeclaringType != null && isConstructor && !isStatic) { |
| int length = parameterPackageNames.length; |
| System.arraycopy(parameterPackageNames, 0, parameterPackageNames = new char[length+1][], 1, length); |
| System.arraycopy(parameterTypeNames, 0, parameterTypeNames = new char[length+1][], 1, length); |
| System.arraycopy(parameterSignatures, 0, parameterSignatures = new String[length+1], 1, length); |
| |
| parameterPackageNames[0] = declaringDeclaringType.getPackageFragment().getElementName().toCharArray(); |
| parameterTypeNames[0] = declaringDeclaringType.getTypeQualifiedName().toCharArray(); |
| parameterSignatures[0] = Signature.getTypeErasure(enclosingDeclaringTypeSignature); |
| } |
| |
| acceptBinaryMethod(type, selector, parameterPackageNames, parameterTypeNames, parameterSignatures, typeParameterNames, typeParameterBoundNames, uniqueKey, isConstructor); |
| } else { |
| acceptSourceMethod(type, selector, parameterPackageNames, parameterTypeNames, parameterSignatures, typeParameterNames, typeParameterBoundNames, uniqueKey); |
| } |
| } |
| } |
| |
| if(previousElementIndex > -1) { |
| int elementsLength = this.elementIndex + previousElementIndex + 2; |
| if(elementsLength > this.elements.length) { |
| System.arraycopy(this.elements, 0, this.elements = new IJavaElement[elementsLength * 2 + 1], 0, this.elementIndex + 1); |
| } |
| System.arraycopy(previousElement, 0, this.elements, this.elementIndex + 1, previousElementIndex + 1); |
| this.elementIndex += previousElementIndex + 1; |
| } |
| } |
| /** |
| * Resolve the package |
| */ |
| public void acceptPackage(char[] packageName) { |
| IPackageFragment[] pkgs = this.nameLookup.findPackageFragments(new String(packageName), false); |
| if (pkgs != null) { |
| for (int i = 0, length = pkgs.length; i < length; i++) { |
| addElement(pkgs[i]); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept package("); //$NON-NLS-1$ |
| System.out.print(pkgs[i].toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } |
| } |
| } |
| /** |
| * Resolve the source method |
| * |
| * fix for 1FWFT6Q |
| */ |
| protected void acceptSourceMethod( |
| IType type, |
| char[] selector, |
| char[][] parameterPackageNames, |
| char[][] parameterTypeNames, |
| String[] parameterSignatures, |
| char[][] typeParameterNames, |
| char[][][] typeParameterBoundNames, |
| char[] uniqueKey) { |
| |
| String name = new String(selector); |
| IMethod[] methods = null; |
| try { |
| methods = type.getMethods(); |
| for (int i = 0; i < methods.length; i++) { |
| if (methods[i].getElementName().equals(name) |
| && methods[i].getParameterTypes().length == parameterTypeNames.length) { |
| IMethod method = methods[i]; |
| if (uniqueKey != null) { |
| ResolvedSourceMethod resolvedMethod = new ResolvedSourceMethod( |
| (JavaElement)method.getParent(), |
| method.getElementName(), |
| method.getParameterTypes(), |
| new String(uniqueKey)); |
| resolvedMethod.occurrenceCount = method.getOccurrenceCount(); |
| method = resolvedMethod; |
| } |
| addElement(method); |
| } |
| } |
| } catch (JavaModelException e) { |
| return; |
| } |
| |
| // if no matches, nothing to report |
| if (this.elementIndex == -1) { |
| // no match was actually found, but a method was originally given -> default constructor |
| addElement(type); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept type("); //$NON-NLS-1$ |
| System.out.print(type.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| return; |
| } |
| |
| // if there is only one match, we've got it |
| if (this.elementIndex == 0) { |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept method("); //$NON-NLS-1$ |
| System.out.print(this.elements[0].toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| return; |
| } |
| |
| // more than one match - must match simple parameter types |
| IJavaElement[] matches = this.elements; |
| int matchesIndex = this.elementIndex; |
| this.elements = JavaElement.NO_ELEMENTS; |
| this.elementIndex = -1; |
| for (int i = 0; i <= matchesIndex; i++) { |
| IMethod method= (IMethod)matches[i]; |
| String[] signatures = method.getParameterTypes(); |
| boolean match= true; |
| for (int p = 0; p < signatures.length; p++) { |
| String simpleName= Signature.getSimpleName(Signature.toString(Signature.getTypeErasure(signatures[p]))); |
| char[] simpleParameterName = CharOperation.lastSegment(parameterTypeNames[p], '.'); |
| if (!simpleName.equals(new String(simpleParameterName))) { |
| match = false; |
| break; |
| } |
| } |
| |
| if (match && !areTypeParametersCompatible(method, typeParameterNames, typeParameterBoundNames)) { |
| match = false; |
| } |
| |
| if (match) { |
| addElement(method); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept method("); //$NON-NLS-1$ |
| System.out.print(method.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| } |
| protected void acceptMethodDeclaration(IType type, char[] selector, int start, int end) { |
| String name = new String(selector); |
| IMethod[] methods = null; |
| try { |
| methods = type.getMethods(); |
| for (int i = 0; i < methods.length; i++) { |
| ISourceRange range = methods[i].getNameRange(); |
| if(range.getOffset() <= start |
| && range.getOffset() + range.getLength() >= end |
| && methods[i].getElementName().equals(name)) { |
| addElement(methods[i]); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept method("); //$NON-NLS-1$ |
| System.out.print(this.elements[0].toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| return; // only one method is possible |
| } |
| } |
| } catch (JavaModelException e) { |
| return; |
| } |
| |
| // no match was actually found |
| addElement(type); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept type("); //$NON-NLS-1$ |
| System.out.print(type.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| return; |
| } |
| public void acceptTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] typeParameterName, boolean isDeclaration, int start, int end) { |
| IType type; |
| if(isDeclaration) { |
| type = resolveTypeByLocation(declaringTypePackageName, declaringTypeName, |
| NameLookup.ACCEPT_ALL, |
| start, end); |
| } else { |
| type = resolveType(declaringTypePackageName, declaringTypeName, |
| NameLookup.ACCEPT_ALL); |
| } |
| |
| if(type != null) { |
| ITypeParameter typeParameter = type.getTypeParameter(new String(typeParameterName)); |
| if(typeParameter == null) { |
| addElement(type); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept type("); //$NON-NLS-1$ |
| System.out.print(type.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } else { |
| addElement(typeParameter); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept type parameter("); //$NON-NLS-1$ |
| System.out.print(typeParameter.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } |
| } |
| } |
| public void acceptMethodTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector,int selectorStart, int selectorEnd, char[] typeParameterName, boolean isDeclaration, int start, int end) { |
| IType type = resolveTypeByLocation(declaringTypePackageName, declaringTypeName, |
| NameLookup.ACCEPT_ALL, |
| selectorStart, selectorEnd); |
| |
| if(type != null) { |
| IMethod method = null; |
| |
| String name = new String(selector); |
| IMethod[] methods = null; |
| |
| try { |
| methods = type.getMethods(); |
| done : for (int i = 0; i < methods.length; i++) { |
| ISourceRange range = methods[i].getNameRange(); |
| if(range.getOffset() >= selectorStart |
| && range.getOffset() + range.getLength() <= selectorEnd |
| && methods[i].getElementName().equals(name)) { |
| method = methods[i]; |
| break done; |
| } |
| } |
| } catch (JavaModelException e) { |
| //nothing to do |
| } |
| |
| if(method == null) { |
| addElement(type); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept type("); //$NON-NLS-1$ |
| System.out.print(type.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } else { |
| ITypeParameter typeParameter = method.getTypeParameter(new String(typeParameterName)); |
| if(typeParameter == null) { |
| addElement(method); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept method("); //$NON-NLS-1$ |
| System.out.print(method.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } else { |
| addElement(typeParameter); |
| if(SelectionEngine.DEBUG){ |
| System.out.print("SELECTION - accept method type parameter("); //$NON-NLS-1$ |
| System.out.print(typeParameter.toString()); |
| System.out.println(")"); //$NON-NLS-1$ |
| } |
| } |
| } |
| } |
| } |
| /* |
| * Adds the given element to the list of resolved elements. |
| */ |
| protected void addElement(IJavaElement element) { |
| int elementLength = this.elementIndex + 1; |
| |
| for (int i = 0; i < elementLength; i++) { |
| if (this.elements[i].equals(element)) { |
| return; |
| } |
| } |
| |
| if (elementLength == this.elements.length) { |
| System.arraycopy(this.elements, 0, this.elements = new IJavaElement[(elementLength*2) + 1], 0, elementLength); |
| } |
| this.elements[++this.elementIndex] = element; |
| } |
| private boolean areTypeParametersCompatible(IMethod method, char[][] typeParameterNames, char[][][] typeParameterBoundNames) { |
| try { |
| ITypeParameter[] typeParameters = method.getTypeParameters(); |
| int length1 = typeParameters == null ? 0 : typeParameters.length; |
| int length2 = typeParameterNames == null ? 0 : typeParameterNames.length; |
| if (length1 != length2) { |
| return false; |
| } else { |
| for (int j = 0; j < length1; j++) { |
| ITypeParameter typeParameter = typeParameters[j]; |
| String typeParameterName = typeParameter.getElementName(); |
| if (!typeParameterName.equals(new String(typeParameterNames[j]))) { |
| return false; |
| } |
| |
| String[] bounds = typeParameter.getBounds(); |
| int boundCount = typeParameterBoundNames[j] == null ? 0 : typeParameterBoundNames[j].length; |
| |
| if (bounds.length != boundCount) { |
| return false; |
| } else { |
| for (int k = 0; k < boundCount; k++) { |
| String simpleName = Signature.getSimpleName(bounds[k]); |
| int index = simpleName.indexOf('<'); |
| if (index != -1) { |
| simpleName = simpleName.substring(0, index); |
| } |
| if (!simpleName.equals(new String(typeParameterBoundNames[j][k]))) { |
| return false; |
| } |
| } |
| } |
| } |
| } |
| } catch (JavaModelException e) { |
| return false; |
| } |
| return true; |
| } |
| /* |
| * findLocalElement() cannot find local variable |
| */ |
| protected IJavaElement findLocalElement(int pos) { |
| IJavaElement res = null; |
| if(this.openable instanceof ICompilationUnit) { |
| ICompilationUnit cu = (ICompilationUnit) this.openable; |
| try { |
| res = cu.getElementAt(pos); |
| } catch (JavaModelException e) { |
| // do nothing |
| } |
| } else if (this.openable instanceof ClassFile) { |
| ClassFile cf = (ClassFile) this.openable; |
| try { |
| res = cf.getElementAtConsideringSibling(pos); |
| } catch (JavaModelException e) { |
| // do nothing |
| } |
| } |
| return res; |
| } |
| /* |
| * findLocalElement() cannot find lambdas. |
| */ |
| protected IJavaElement findLocalElement(int pos, MethodScope scope) { |
| if (scope != null && scope.isLambdaScope()) { |
| IJavaElement parent = findLocalElement(pos, scope.enclosingMethodScope()); |
| LambdaExpression expression = (LambdaExpression) scope.originalReferenceContext(); |
| if (expression != null && expression.resolvedType != null && expression.resolvedType.isValidBinding()) { |
| org.eclipse.jdt.internal.core.LambdaExpression lambdaElement = LambdaFactory.createLambdaExpression((JavaElement) parent, expression); |
| return lambdaElement.getMethod(); |
| } |
| return parent; |
| } |
| return findLocalElement(pos); |
| } |
| |
| /** |
| * This method returns an IMethod element from the given method and declaring type bindings. However, |
| * unlike {@link Util#findMethod(IType, char[], String[], boolean)} , this does not require an IType to get |
| * the IMethod element. |
| * @param method the given method binding |
| * @param signatures the type signatures of the method arguments |
| * @param declaringClass the binding of the method's declaring class |
| * @return an IMethod corresponding to the method binding given, or null if none is found. |
| */ |
| public IJavaElement findMethodFromBinding(MethodBinding method, String[] signatures, ReferenceBinding declaringClass) { |
| IType foundType = this.resolveType(declaringClass.qualifiedPackageName(), declaringClass.qualifiedSourceName(), NameLookup.ACCEPT_CLASSES & NameLookup.ACCEPT_INTERFACES); |
| if (foundType != null) { |
| if (foundType instanceof BinaryType) { |
| try { |
| return Util.findMethod(foundType, method.selector, signatures, method.isConstructor()); |
| } catch (JavaModelException e) { |
| return null; |
| } |
| } else { |
| return foundType.getMethod(new String(method.selector), signatures); |
| } |
| } |
| return null; |
| } |
| /** |
| * Returns the resolved elements. |
| */ |
| public IJavaElement[] getElements() { |
| int elementLength = this.elementIndex + 1; |
| if (this.elements.length != elementLength) { |
| System.arraycopy(this.elements, 0, this.elements = new IJavaElement[elementLength], 0, elementLength); |
| } |
| return this.elements; |
| } |
| protected IModuleDescription resolveModule(char[] moduleName) { |
| Answer answer = this.nameLookup.findModule(moduleName); |
| if (answer != null) { |
| return answer.module; |
| } |
| return null; |
| } |
| /** |
| * Resolve the type |
| */ |
| protected IType resolveType(char[] packageName, char[] typeName, int acceptFlags) { |
| |
| IType type= null; |
| |
| if (this.openable instanceof CompilationUnit && ((CompilationUnit)this.openable).isWorkingCopy()) { |
| CompilationUnit wc = (CompilationUnit) this.openable; |
| try { |
| if(((packageName == null || packageName.length == 0) && wc.getPackageDeclarations().length == 0) || |
| (!(packageName == null || packageName.length == 0) && wc.getPackageDeclaration(new String(packageName)).exists())) { |
| |
| char[][] compoundName = CharOperation.splitOn('.', typeName); |
| if(compoundName.length > 0) { |
| type = wc.getType(new String(compoundName[0])); |
| for (int i = 1, length = compoundName.length; i < length; i++) { |
| type = type.getType(new String(compoundName[i])); |
| } |
| } |
| |
| if(type != null && !type.exists()) { |
| type = null; |
| } |
| } |
| }catch (JavaModelException e) { |
| // type is null |
| } |
| } |
| |
| if(type == null) { |
| IPackageFragment[] pkgs = this.nameLookup.findPackageFragments( |
| (packageName == null || packageName.length == 0) ? IPackageFragment.DEFAULT_PACKAGE_NAME : new String(packageName), |
| false); |
| // iterate type lookup in each package fragment |
| for (int i = 0, length = pkgs == null ? 0 : pkgs.length; i < length; i++) { |
| type= this.nameLookup.findType(new String(typeName), pkgs[i], false, acceptFlags, false, true/*consider secondary types*/); |
| if (type != null) break; |
| } |
| if (type == null) { |
| String pName= IPackageFragment.DEFAULT_PACKAGE_NAME; |
| if (packageName != null) { |
| pName = new String(packageName); |
| } |
| if (this.openable != null && this.openable.getParent().getElementName().equals(pName)) { |
| // look inside the type in which we are resolving in |
| String tName= new String(typeName); |
| tName = tName.replace('.','$'); |
| IType[] allTypes= null; |
| try { |
| ArrayList list = this.openable.getChildrenOfType(IJavaElement.TYPE); |
| allTypes = new IType[list.size()]; |
| list.toArray(allTypes); |
| } catch (JavaModelException e) { |
| return null; |
| } |
| for (int i= 0; i < allTypes.length; i++) { |
| if (allTypes[i].getTypeQualifiedName().equals(tName)) { |
| return allTypes[i]; |
| } |
| } |
| } |
| } |
| } |
| return type; |
| } |
| protected IType resolveTypeByLocation(char[] packageName, char[] typeName, int acceptFlags, int start, int end) { |
| |
| IType type= null; |
| |
| // TODO (david) post 3.0 should remove isOpen check, and investigate reusing ICompilationUnit#getElementAt. may need to optimize #getElementAt to remove recursions |
| if (this.openable instanceof CompilationUnit && ((CompilationUnit)this.openable).isOpen()) { |
| CompilationUnit wc = (CompilationUnit) this.openable; |
| try { |
| if(((packageName == null || packageName.length == 0) && wc.getPackageDeclarations().length == 0) || |
| (!(packageName == null || packageName.length == 0) && wc.getPackageDeclaration(new String(packageName)).exists())) { |
| |
| char[][] compoundName = CharOperation.splitOn('.', typeName); |
| if(compoundName.length > 0) { |
| |
| IType[] tTypes = wc.getTypes(); |
| int i = 0; |
| int depth = 0; |
| done : while(i < tTypes.length) { |
| ISourceRange range = tTypes[i].getSourceRange(); |
| if(range.getOffset() <= start |
| && range.getOffset() + range.getLength() >= end |
| && tTypes[i].getElementName().equals(new String(compoundName[depth]))) { |
| if(depth == compoundName.length - 1) { |
| type = tTypes[i]; |
| break done; |
| } |
| tTypes = tTypes[i].getTypes(); |
| i = 0; |
| depth++; |
| continue done; |
| } |
| i++; |
| } |
| } |
| |
| if(type != null && !type.exists()) { |
| type = null; |
| } |
| } |
| }catch (JavaModelException e) { |
| // type is null |
| } |
| } |
| |
| if(type == null) { |
| IPackageFragment[] pkgs = this.nameLookup.findPackageFragments( |
| (packageName == null || packageName.length == 0) ? IPackageFragment.DEFAULT_PACKAGE_NAME : new String(packageName), |
| false); |
| // iterate type lookup in each package fragment |
| for (int i = 0, length = pkgs == null ? 0 : pkgs.length; i < length; i++) { |
| type= this.nameLookup.findType(new String(typeName), pkgs[i], false, acceptFlags, false, true/*consider secondary types*/); |
| if (type != null) break; |
| } |
| if (type == null) { |
| String pName= IPackageFragment.DEFAULT_PACKAGE_NAME; |
| if (packageName != null) { |
| pName = new String(packageName); |
| } |
| if (this.openable != null && this.openable.getParent().getElementName().equals(pName)) { |
| // look inside the type in which we are resolving in |
| String tName= new String(typeName); |
| tName = tName.replace('.','$'); |
| IType[] allTypes= null; |
| try { |
| ArrayList list = this.openable.getChildrenOfType(IJavaElement.TYPE); |
| allTypes = new IType[list.size()]; |
| list.toArray(allTypes); |
| } catch (JavaModelException e) { |
| return null; |
| } |
| for (int i= 0; i < allTypes.length; i++) { |
| if (allTypes[i].getTypeQualifiedName().equals(tName)) { |
| return allTypes[i]; |
| } |
| } |
| } |
| } |
| } |
| return type; |
| } |
| } |