Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.eclipse.jdt.internal.core.search.indexing.BinaryIndexer Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2000, 2015 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.search.indexing;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.search.SearchDocument;
import org.eclipse.jdt.internal.compiler.ExtraFlags;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
import org.eclipse.jdt.internal.compiler.classfmt.FieldInfo;
import org.eclipse.jdt.internal.compiler.classfmt.MethodInfo;
import org.eclipse.jdt.internal.compiler.env.ClassSignature;
import org.eclipse.jdt.internal.compiler.env.EnumConstantSignature;
import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
import org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair;
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.core.util.Util;
public class BinaryIndexer extends AbstractIndexer implements SuffixConstants {
private static final char[] BYTE = "byte".toCharArray(); //$NON-NLS-1$
private static final char[] CHAR = "char".toCharArray(); //$NON-NLS-1$
private static final char[] DOUBLE = "double".toCharArray(); //$NON-NLS-1$
private static final char[] FLOAT = "float".toCharArray(); //$NON-NLS-1$
private static final char[] INT = "int".toCharArray(); //$NON-NLS-1$
private static final char[] LONG = "long".toCharArray(); //$NON-NLS-1$
private static final char[] SHORT = "short".toCharArray(); //$NON-NLS-1$
private static final char[] BOOLEAN = "boolean".toCharArray(); //$NON-NLS-1$
private static final char[] VOID = "void".toCharArray(); //$NON-NLS-1$
private static final char[] INIT = "".toCharArray(); //$NON-NLS-1$
public BinaryIndexer(SearchDocument document) {
super(document);
}
private void addBinaryStandardAnnotations(long annotationTagBits) {
if ((annotationTagBits & TagBits.AllStandardAnnotationsMask) == 0) {
return;
}
if ((annotationTagBits & TagBits.AnnotationTargetMASK) != 0) {
char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_TARGET;
addAnnotationTypeReference(compoundName[compoundName.length-1]);
addBinaryTargetAnnotation(annotationTagBits);
}
if ((annotationTagBits & TagBits.AnnotationRetentionMASK) != 0) {
char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_RETENTION;
addAnnotationTypeReference(compoundName[compoundName.length-1]);
addBinaryRetentionAnnotation(annotationTagBits);
}
if ((annotationTagBits & TagBits.AnnotationDeprecated) != 0) {
char[][] compoundName = TypeConstants.JAVA_LANG_DEPRECATED;
addAnnotationTypeReference(compoundName[compoundName.length-1]);
}
if ((annotationTagBits & TagBits.AnnotationDocumented) != 0) {
char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_DOCUMENTED;
addAnnotationTypeReference(compoundName[compoundName.length-1]);
}
if ((annotationTagBits & TagBits.AnnotationInherited) != 0) {
char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_INHERITED;
addAnnotationTypeReference(compoundName[compoundName.length-1]);
}
if ((annotationTagBits & TagBits.AnnotationOverride) != 0) {
char[][] compoundName = TypeConstants.JAVA_LANG_OVERRIDE;
addAnnotationTypeReference(compoundName[compoundName.length-1]);
}
if ((annotationTagBits & TagBits.AnnotationSuppressWarnings) != 0) {
char[][] compoundName = TypeConstants.JAVA_LANG_SUPPRESSWARNINGS;
addAnnotationTypeReference(compoundName[compoundName.length-1]);
}
if ((annotationTagBits & TagBits.AnnotationSafeVarargs) != 0) {
char[][] compoundName = TypeConstants.JAVA_LANG_SAFEVARARGS;
addAnnotationTypeReference(compoundName[compoundName.length-1]);
}
if ((annotationTagBits & TagBits.AnnotationPolymorphicSignature) != 0) {
char[][] compoundName =
TypeConstants.JAVA_LANG_INVOKE_METHODHANDLE_$_POLYMORPHICSIGNATURE;
addAnnotationTypeReference(compoundName[compoundName.length-1]);
}
}
private void addBinaryTargetAnnotation(long bits) {
char[][] compoundName = null;
if ((bits & TagBits.AnnotationForAnnotationType) != 0) {
compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
addTypeReference(compoundName[compoundName.length-1]);
addFieldReference(TypeConstants.UPPER_ANNOTATION_TYPE);
}
if ((bits & TagBits.AnnotationForConstructor) != 0) {
if (compoundName == null) {
compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
addTypeReference(compoundName[compoundName.length-1]);
}
addFieldReference(TypeConstants.UPPER_CONSTRUCTOR);
}
if ((bits & TagBits.AnnotationForField) != 0) {
if (compoundName == null) {
compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
addTypeReference(compoundName[compoundName.length-1]);
}
addFieldReference(TypeConstants.UPPER_FIELD);
}
if ((bits & TagBits.AnnotationForLocalVariable) != 0) {
if (compoundName == null) {
compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
addTypeReference(compoundName[compoundName.length-1]);
}
addFieldReference(TypeConstants.UPPER_LOCAL_VARIABLE);
}
if ((bits & TagBits.AnnotationForMethod) != 0) {
if (compoundName == null) {
compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
addTypeReference(compoundName[compoundName.length-1]);
}
addFieldReference(TypeConstants.UPPER_METHOD);
}
if ((bits & TagBits.AnnotationForPackage) != 0) {
if (compoundName == null) {
compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
addTypeReference(compoundName[compoundName.length-1]);
}
addFieldReference(TypeConstants.UPPER_PACKAGE);
}
if ((bits & TagBits.AnnotationForParameter) != 0) {
if (compoundName == null) {
compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
addTypeReference(compoundName[compoundName.length-1]);
}
addFieldReference(TypeConstants.UPPER_PARAMETER);
}
if ((bits & TagBits.AnnotationForType) != 0) {
if (compoundName == null) {
compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
addTypeReference(compoundName[compoundName.length-1]);
}
addFieldReference(TypeConstants.TYPE);
}
}
private void addBinaryRetentionAnnotation(long bits) {
char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_RETENTIONPOLICY;
addTypeReference(compoundName[compoundName.length-1]);
if ((bits & TagBits.AnnotationRuntimeRetention) == TagBits.AnnotationRuntimeRetention) {
addFieldReference(TypeConstants.UPPER_RUNTIME);
} else if ((bits & TagBits.AnnotationClassRetention) != 0) {
addFieldReference(TypeConstants.UPPER_CLASS);
} else if ((bits & TagBits.AnnotationSourceRetention) != 0) {
addFieldReference(TypeConstants.UPPER_SOURCE);
}
}
private void addBinaryAnnotation(IBinaryAnnotation annotation) {
addAnnotationTypeReference(replace('/', '.', Signature.toCharArray(annotation.getTypeName())));
IBinaryElementValuePair[] valuePairs = annotation.getElementValuePairs();
if (valuePairs != null) {
for (int j=0, vpLength=valuePairs.length; j 2 && typeName[length - 2] == '$') {
switch (typeName[length - 1]) {
case '0' :
case '1' :
case '2' :
case '3' :
case '4' :
case '5' :
case '6' :
case '7' :
case '8' :
case '9' :
return; // skip local type names
}
}
// consider that A$B is a member type: so replace '$' with '.'
// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=40116)
typeName = CharOperation.replaceOnCopy(typeName, '$', '.'); // copy it so the original is not modified
super.addTypeReference(typeName);
}
/**
* For example:
* - int foo(String[]) is ([Ljava/lang/String;)I => java.lang.String[] in a char[][]
* - void foo(int) is (I)V ==> int
*/
private void convertToArrayType(char[][] parameterTypes, int counter, int arrayDim) {
int length = parameterTypes[counter].length;
char[] arrayType = new char[length + arrayDim*2];
System.arraycopy(parameterTypes[counter], 0, arrayType, 0, length);
for (int i = 0; i < arrayDim; i++) {
arrayType[length + (i * 2)] = '[';
arrayType[length + (i * 2) + 1] = ']';
}
parameterTypes[counter] = arrayType;
}
/**
* For example:
* - int foo(String[]) is ([Ljava/lang/String;)I => java.lang.String[] in a char[][]
* - void foo(int) is (I)V ==> int
*/
private char[] convertToArrayType(char[] typeName, int arrayDim) {
int length = typeName.length;
char[] arrayType = new char[length + arrayDim*2];
System.arraycopy(typeName, 0, arrayType, 0, length);
for (int i = 0; i < arrayDim; i++) {
arrayType[length + (i * 2)] = '[';
arrayType[length + (i * 2) + 1] = ']';
}
return arrayType;
}
private char[] decodeFieldType(char[] signature) throws ClassFormatException {
if (signature == null) return null;
int arrayDim = 0;
for (int i = 0, max = signature.length; i < max; i++) {
switch(signature[i]) {
case 'B':
if (arrayDim > 0)
return convertToArrayType(BYTE, arrayDim);
return BYTE;
case 'C':
if (arrayDim > 0)
return convertToArrayType(CHAR, arrayDim);
return CHAR;
case 'D':
if (arrayDim > 0)
return convertToArrayType(DOUBLE, arrayDim);
return DOUBLE;
case 'F':
if (arrayDim > 0)
return convertToArrayType(FLOAT, arrayDim);
return FLOAT;
case 'I':
if (arrayDim > 0)
return convertToArrayType(INT, arrayDim);
return INT;
case 'J':
if (arrayDim > 0)
return convertToArrayType(LONG, arrayDim);
return LONG;
case 'L':
int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
if (arrayDim > 0) {
return convertToArrayType(replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon)), arrayDim);
}
return replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon));
case 'S':
if (arrayDim > 0)
return convertToArrayType(SHORT, arrayDim);
return SHORT;
case 'Z':
if (arrayDim > 0)
return convertToArrayType(BOOLEAN, arrayDim);
return BOOLEAN;
case 'V':
return VOID;
case '[':
arrayDim++;
break;
default:
throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
}
}
return null;
}
/**
* For example:
* - int foo(String[]) is ([Ljava/lang/String;)I => java.lang.String[] in a char[][]
* - void foo(int) is (I)V ==> int
*/
private char[][] decodeParameterTypes(char[] signature, boolean firstIsSynthetic) throws ClassFormatException {
if (signature == null) return null;
int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
if (indexOfClosingParen == 1) {
// there is no parameter
return null;
}
if (indexOfClosingParen == -1) {
throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
}
char[][] parameterTypes = new char[3][];
int parameterTypesCounter = 0;
int arrayDim = 0;
for (int i = 1; i < indexOfClosingParen; i++) {
if (parameterTypesCounter == parameterTypes.length) {
// resize
System.arraycopy(parameterTypes, 0, (parameterTypes = new char[parameterTypesCounter * 2][]), 0, parameterTypesCounter);
}
switch(signature[i]) {
case 'B':
parameterTypes[parameterTypesCounter++] = BYTE;
if (arrayDim > 0)
convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
arrayDim = 0;
break;
case 'C':
parameterTypes[parameterTypesCounter++] = CHAR;
if (arrayDim > 0)
convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
arrayDim = 0;
break;
case 'D':
parameterTypes[parameterTypesCounter++] = DOUBLE;
if (arrayDim > 0)
convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
arrayDim = 0;
break;
case 'F':
parameterTypes[parameterTypesCounter++] = FLOAT;
if (arrayDim > 0)
convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
arrayDim = 0;
break;
case 'I':
parameterTypes[parameterTypesCounter++] = INT;
if (arrayDim > 0)
convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
arrayDim = 0;
break;
case 'J':
parameterTypes[parameterTypesCounter++] = LONG;
if (arrayDim > 0)
convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
arrayDim = 0;
break;
case 'L':
int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
if (firstIsSynthetic && parameterTypesCounter == 0) {
// skip first synthetic parameter
firstIsSynthetic = false;
} else {
parameterTypes[parameterTypesCounter++] = replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon));
if (arrayDim > 0)
convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
}
i = indexOfSemiColon;
arrayDim = 0;
break;
case 'S':
parameterTypes[parameterTypesCounter++] = SHORT;
if (arrayDim > 0)
convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
arrayDim = 0;
break;
case 'Z':
parameterTypes[parameterTypesCounter++] = BOOLEAN;
if (arrayDim > 0)
convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
arrayDim = 0;
break;
case '[':
arrayDim++;
break;
default:
throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
}
}
if (parameterTypes.length != parameterTypesCounter) {
System.arraycopy(parameterTypes, 0, parameterTypes = new char[parameterTypesCounter][], 0, parameterTypesCounter);
}
return parameterTypes;
}
private char[] decodeReturnType(char[] signature) throws ClassFormatException {
if (signature == null) return null;
int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
if (indexOfClosingParen == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
int arrayDim = 0;
for (int i = indexOfClosingParen + 1, max = signature.length; i < max; i++) {
switch(signature[i]) {
case 'B':
if (arrayDim > 0)
return convertToArrayType(BYTE, arrayDim);
return BYTE;
case 'C':
if (arrayDim > 0)
return convertToArrayType(CHAR, arrayDim);
return CHAR;
case 'D':
if (arrayDim > 0)
return convertToArrayType(DOUBLE, arrayDim);
return DOUBLE;
case 'F':
if (arrayDim > 0)
return convertToArrayType(FLOAT, arrayDim);
return FLOAT;
case 'I':
if (arrayDim > 0)
return convertToArrayType(INT, arrayDim);
return INT;
case 'J':
if (arrayDim > 0)
return convertToArrayType(LONG, arrayDim);
return LONG;
case 'L':
int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
if (arrayDim > 0) {
return convertToArrayType(replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon)), arrayDim);
}
return replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon));
case 'S':
if (arrayDim > 0)
return convertToArrayType(SHORT, arrayDim);
return SHORT;
case 'Z':
if (arrayDim > 0)
return convertToArrayType(BOOLEAN, arrayDim);
return BOOLEAN;
case 'V':
return VOID;
case '[':
arrayDim++;
break;
default:
throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
}
}
return null;
}
private int extractArgCount(char[] signature, char[] className) throws ClassFormatException {
int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
if (indexOfClosingParen == 1) {
// there is no parameter
return 0;
}
if (indexOfClosingParen == -1) {
throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
}
int parameterTypesCounter = 0;
for (int i = 1; i < indexOfClosingParen; i++) {
switch(signature[i]) {
case 'B':
case 'C':
case 'D':
case 'F':
case 'I':
case 'J':
case 'S':
case 'Z':
parameterTypesCounter++;
break;
case 'L':
int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
// verify if first parameter is synthetic
if (className != null && parameterTypesCounter == 0) {
char[] classSignature = Signature.createCharArrayTypeSignature(className, true);
int length = indexOfSemiColon-i+1;
if (classSignature.length > (length+1)) {
// synthetic means that parameter type has same signature than given class
for (int j=i, k=0; j 0 && name[0] == '[')
break; // skip over array references
name = replace('/', '.', name); // so that it looks like java.lang.String
addTypeReference(name);
// also add a simple reference on each segment of the qualification (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=24741)
char[][] qualification = CharOperation.splitOn('.', name);
for (int j = 0, length = qualification.length; j < length; j++) {
addNameReference(qualification[j]);
}
break;
}
}
}
private char[] extractType(int[] constantPoolOffsets, ClassFileReader reader, int index) {
int constantPoolIndex = reader.u2At(constantPoolOffsets[index] + 3);
int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[constantPoolIndex] + 3)];
return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
}
public void indexDocument() {
try {
final byte[] contents = this.document.getByteContents();
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=107124
// contents can potentially be null if a IOException occurs while retrieving the contents
if (contents == null) return;
final String path = this.document.getPath();
ClassFileReader reader = new ClassFileReader(contents, path == null ? null : path.toCharArray());
// first add type references
char[] className = replace('/', '.', reader.getName()); // looks like java/lang/String
// need to extract the package name and the simple name
int packageNameIndex = CharOperation.lastIndexOf('.', className);
char[] packageName = null;
char[] name = null;
if (packageNameIndex >= 0) {
packageName = CharOperation.subarray(className, 0, packageNameIndex);
name = CharOperation.subarray(className, packageNameIndex + 1, className.length);
} else {
packageName = CharOperation.NO_CHAR;
name = className;
}
char[] enclosingTypeName = null;
boolean isNestedType = reader.isNestedType();
if (isNestedType) {
if (reader.isAnonymous()) {
name = CharOperation.NO_CHAR;
} else {
name = reader.getInnerSourceName();
}
if (reader.isLocal() || reader.isAnonymous()) {
// set specific ['0'] value for local and anonymous to be able to filter them
enclosingTypeName = ONE_ZERO;
} else {
char[] fullEnclosingName = reader.getEnclosingTypeName();
int nameLength = fullEnclosingName.length - packageNameIndex - 1;
if (nameLength <= 0) {
// See PR 1GIR345: ITPJCORE:ALL - Indexer: NegativeArraySizeException
return;
}
enclosingTypeName = new char[nameLength];
System.arraycopy(fullEnclosingName, packageNameIndex + 1, enclosingTypeName, 0, nameLength);
}
}
// type parameters
char[][] typeParameterSignatures = null;
char[] genericSignature = reader.getGenericSignature();
if (genericSignature != null) {
CharOperation.replace(genericSignature, '/', '.');
typeParameterSignatures = Signature.getTypeParameters(genericSignature);
}
// eliminate invalid innerclasses (1G4KCF7)
if (name == null) return;
char[][] superinterfaces = replace('/', '.', reader.getInterfaceNames());
char[][] enclosingTypeNames = enclosingTypeName == null ? null : new char[][] {enclosingTypeName};
int modifiers = reader.getModifiers();
switch (TypeDeclaration.kind(modifiers)) {
case TypeDeclaration.CLASS_DECL :
char[] superclass = replace('/', '.', reader.getSuperclassName());
addClassDeclaration(modifiers, packageName, name, enclosingTypeNames, superclass, superinterfaces, typeParameterSignatures, false);
break;
case TypeDeclaration.INTERFACE_DECL :
addInterfaceDeclaration(modifiers, packageName, name, enclosingTypeNames, superinterfaces, typeParameterSignatures, false);
break;
case TypeDeclaration.ENUM_DECL :
superclass = replace('/', '.', reader.getSuperclassName());
addEnumDeclaration(modifiers, packageName, name, enclosingTypeNames, superclass, superinterfaces, false);
break;
case TypeDeclaration.ANNOTATION_TYPE_DECL :
addAnnotationTypeDeclaration(modifiers, packageName, name, enclosingTypeNames, false);
break;
}
// Look for references in class annotations
IBinaryAnnotation[] annotations = reader.getAnnotations();
if (annotations != null) {
for (int a=0, length=annotations.length; a 0) {
addMethodDeclaration(
name,
null,
selector,
parameterTypes == null ? 0 : parameterTypes.length,
signature,
parameterTypes,
method.getArgumentNames(),
returnType,
method.getModifiers(),
packageName,
modifiers,
exceptionTypes,
extraFlags);
}
}
}
// look for references in method annotations
annotations = method.getAnnotations();
if (annotations != null) {
for (int a=0, length=annotations.length; a