*** empty log message ***
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
index fe8b2e0..88d37bc 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
@@ -1,1003 +1,1002 @@
-package org.eclipse.jdt.internal.codeassist;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import java.util.Locale;
-
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.env.*;
-
-import org.eclipse.jdt.internal.codeassist.impl.*;
-import org.eclipse.jdt.internal.codeassist.complete.*;
-
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.parser.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.compiler.util.*;
-import org.eclipse.jdt.internal.compiler.impl.*;
-
-/**
- * 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).
- */
-public final class CompletionEngine extends Engine implements ISearchRequestor, TypeConstants {
- CompletionParser parser;
- ISearchableNameEnvironment nameEnvironment;
- ICompletionRequestor requestor;
-
- CompilationUnitScope unitScope;
- char[] source;
- boolean resolvingImports = false;
- boolean insideQualifiedReference = false;
- int startPosition, endPosition;
- HashtableOfObject knownPkgs = 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 char[][] baseTypes =
- new char[][] {
- "boolean"/*nonNLS*/.toCharArray(),
- "byte"/*nonNLS*/.toCharArray(),
- "char"/*nonNLS*/.toCharArray(),
- "double"/*nonNLS*/.toCharArray(),
- "float"/*nonNLS*/.toCharArray(),
- "int"/*nonNLS*/.toCharArray(),
- "long"/*nonNLS*/.toCharArray(),
- "short"/*nonNLS*/.toCharArray(),
- "void"/*nonNLS*/.toCharArray()};
-
- static final char[] classField = "class"/*nonNLS*/.toCharArray();
- static final char[] lengthField = "length"/*nonNLS*/.toCharArray();
-/**
- * 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 environment com.ibm.codeassist.java.api.ISearchableNameEnvironment
- * used to resolve type/package references and search for types/packages
- * based on partial names.
- *
- * @param requestor com.ibm.codeassist.java.api.ICompletionRequestor
- * since the engine might produce answers of various forms, the engine
- * is associated with a requestor able to accept all possible completions.
- *
- * @param options com.ibm.compiler.java.api.ConfigurableOptions
- * set of options used to configure the code assist engine.
- */
-
-public CompletionEngine(
- ISearchableNameEnvironment nameEnvironment, ICompletionRequestor requestor, ConfigurableOption[] settings) {
-
- this.requestor = requestor;
- this.nameEnvironment = nameEnvironment;
-
- CompilerOptions options = new CompilerOptions(settings);
- ProblemReporter problemReporter =
- new ProblemReporter(
- DefaultErrorHandlingPolicies.proceedWithAllProblems(),
- options,
- new DefaultProblemFactory(Locale.getDefault())) {
- public void record(IProblem problem, CompilationResult unitResult) {
- if (problem.getID() != ProblemIrritants.UnmatchedBracket) {
- unitResult.record(problem);
- CompletionEngine.this.requestor.acceptError(problem);
- }
- }
- };
-
- this.parser = new CompletionParser(problemReporter);
- this.lookupEnvironment = new LookupEnvironment(this, options, problemReporter, nameEnvironment);
-}
-/**
- * One result of the search consists of a new class.
- *
- * NOTE - All package and type names are presented in their readable form:
- * Package names are in the form "a.b.c".
- * Nested type names are in the qualified form "A.M".
- * The default package is represented by an empty array.
- */
-public void acceptClass(char[] packageName, char[] className, int modifiers) {
- char[] completionName = CharOperation.concat(packageName, className, '.');
- if (resolvingImports) {
- completionName = CharOperation.concat(completionName, new char[] {';'});
- } else if (!insideQualifiedReference) {
- if (mustQualifyType(CharOperation.splitOn('.', packageName), completionName)) {
- if (packageName == null || packageName.length == 0)
- if (unitScope != null && unitScope.fPackage.compoundName != NoCharChar)
- return; // ignore types from the default package from outside it
- } else {
- completionName = className;
- }
- }
-
- requestor.acceptClass(
- packageName,
- className,
- completionName,
- modifiers,
- startPosition,
- endPosition);
-}
-/**
- * One result of the search consists of a new interface.
- *
- * NOTE - All package and type names are presented in their readable form:
- * Package names are in the form "a.b.c".
- * Nested type names are in the qualified form "A.I".
- * The default package is represented by an empty array.
- */
-public void acceptInterface(char[] packageName, char[] interfaceName, int modifiers) {
- char[] completionName = CharOperation.concat(packageName, interfaceName, '.');
- if (resolvingImports) {
- completionName = CharOperation.concat(completionName, new char[] {';'});
- } else if (!insideQualifiedReference) {
- if (mustQualifyType(CharOperation.splitOn('.', packageName), completionName)) {
- if (packageName == null || packageName.length == 0)
- if (unitScope != null && unitScope.fPackage.compoundName != NoCharChar)
- return; // ignore types from the default package from outside it
- } else {
- completionName = interfaceName;
- }
- }
-
- requestor.acceptInterface(
- packageName,
- interfaceName,
- completionName,
- modifiers,
- startPosition,
- endPosition);
-}
-/**
- * One result of the search consists of a new package.
- *
- * NOTE - All package names are presented in their readable form:
- * Package names are in the form "a.b.c".
- * The default package is represented by an empty array.
- */
-public void acceptPackage(char[] packageName) {
- if (this.knownPkgs.containsKey(packageName)) return;
- this.knownPkgs.put(packageName, this);
- requestor.acceptPackage(
- packageName,
- resolvingImports ? CharOperation.concat(packageName, new char[] {'.', '*', ';'}) : packageName,
- startPosition,
- endPosition);
-}
-/**
- * One result of the search consists of a new type.
- *
- * NOTE - All package and type names are presented in their readable form:
- * Package names are in the form "a.b.c".
- * Nested type names are in the qualified form "A.M".
- * The default package is represented by an empty array.
- */
-public void acceptType(char[] packageName, char[] typeName) {
- char[] completionName = CharOperation.concat(packageName, typeName, '.');
- if (resolvingImports) {
- completionName = CharOperation.concat(completionName, new char[] {';'});
- } else if (!insideQualifiedReference) {
- if (mustQualifyType(CharOperation.splitOn('.', packageName), completionName)) {
- if (packageName == null || packageName.length == 0)
- if (unitScope != null && unitScope.fPackage.compoundName != NoCharChar)
- return; // ignore types from the default package from outside it
- } else {
- completionName = typeName;
- }
- }
-
- requestor.acceptType(
- packageName,
- typeName,
- completionName,
- startPosition,
- endPosition);
-}
-private void complete(AstNode astNode, Binding qualifiedBinding, Scope scope) {
- setSourceRange(astNode.sourceStart, astNode.sourceEnd); // defaults... some nodes will change these
-
- if (astNode instanceof CompletionOnFieldType) {
- CompletionOnSingleTypeReference type =
- (CompletionOnSingleTypeReference) ((CompletionOnFieldType) astNode).type;
- char[] token = type.token;
- setSourceRange(type.sourceStart, type.sourceEnd);
-// findKeywords(token, modifiers, scope); // could be the start of a field, method or member type
- findTypesAndPackages(token, scope);
- } else if (astNode instanceof CompletionOnSingleNameReference) {
- char[] token = ((CompletionOnSingleNameReference) astNode).token;
- findVariablesAndMethods(token, scope);
- findTypesAndPackages(token, scope); // can be the start of a qualified type name
- } else if (astNode instanceof CompletionOnSingleTypeReference) {
- char[] token = ((CompletionOnSingleTypeReference) astNode).token;
- if (qualifiedBinding == null)
- findTypesAndPackages(token, scope); // can be the start of a qualified type name
- else
- findMemberTypes(token, (ReferenceBinding) qualifiedBinding, scope);
- } else if (astNode instanceof CompletionOnQualifiedNameReference) {
- insideQualifiedReference = true;
- CompletionOnQualifiedNameReference ref = (CompletionOnQualifiedNameReference) astNode;
- char[] token = ref.completionIdentifier;
- long completionPosition = ref.sourcePositions[ref.sourcePositions.length - 1];
- if (qualifiedBinding instanceof VariableBinding) {
- setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
- TypeBinding receiverType = ((VariableBinding) qualifiedBinding).type;
- if (receiverType != null)
- findFieldsAndMethods(token, receiverType, scope);
- } else if (qualifiedBinding instanceof ReferenceBinding) {
- ReferenceBinding receiverType = (ReferenceBinding) qualifiedBinding;
- setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
- findMemberTypes(token, receiverType, scope);
- findClassField(token, (TypeBinding) qualifiedBinding);
- findFields(token, receiverType, scope, new ObjectVector(), true);
- findMethods(token, null, receiverType, scope, new ObjectVector(), true, false);
- } else if (qualifiedBinding instanceof PackageBinding) {
- setSourceRange(astNode.sourceStart, (int) completionPosition); // replace to the end of the completion identifier
- findTypesAndSubpackages(token, (PackageBinding) qualifiedBinding);
- }
- } else if (astNode instanceof CompletionOnQualifiedTypeReference) {
- insideQualifiedReference = true;
- CompletionOnQualifiedTypeReference ref = (CompletionOnQualifiedTypeReference) astNode;
- char[] token = ref.completionIdentifier;
- long completionPosition = ref.sourcePositions[ref.tokens.length]; // get the source positions of the completion identifier
- if (qualifiedBinding instanceof ReferenceBinding) {
- setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
- findMemberTypes(token, (ReferenceBinding) qualifiedBinding, scope);
- } else if (qualifiedBinding instanceof PackageBinding) {
- setSourceRange(astNode.sourceStart, (int) completionPosition); // replace to the end of the completion identifier
- findTypesAndSubpackages(token, (PackageBinding) qualifiedBinding);
- }
- } else if (astNode instanceof CompletionOnMemberAccess) {
- CompletionOnMemberAccess access = (CompletionOnMemberAccess) astNode;
- long completionPosition = access.nameSourcePosition;
- setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
- findFieldsAndMethods(access.token, (TypeBinding) qualifiedBinding, scope);
- } else if (astNode instanceof CompletionOnMessageSend) {
- CompletionOnMessageSend messageSend = (CompletionOnMessageSend) astNode;
- TypeBinding[] argTypes = computeTypes(messageSend.arguments, (BlockScope) scope);
- if (qualifiedBinding == null)
- findMessageSends(messageSend.selector, argTypes, scope);
- else
- findMethods(messageSend.selector, argTypes, (ReferenceBinding) qualifiedBinding, scope, new ObjectVector(), false, true);
- } else if (astNode instanceof CompletionOnExplicitConstructorCall) {
- CompletionOnExplicitConstructorCall constructorCall = (CompletionOnExplicitConstructorCall) astNode;
- TypeBinding[] argTypes = computeTypes(constructorCall.arguments, (BlockScope) scope);
- findConstructors((ReferenceBinding) qualifiedBinding, argTypes, scope);
- } else if (astNode instanceof CompletionOnQualifiedAllocationExpression) {
- CompletionOnQualifiedAllocationExpression allocExpression = (CompletionOnQualifiedAllocationExpression) astNode;
- TypeBinding[] argTypes = computeTypes(allocExpression.arguments, (BlockScope) scope);
- findConstructors((ReferenceBinding) qualifiedBinding, argTypes, scope);
- } else if (astNode instanceof CompletionOnClassLiteralAccess) {
- char[] token = ((CompletionOnClassLiteralAccess) astNode).completionIdentifier;
- findClassField(token, (TypeBinding) qualifiedBinding);
- }
-}
-/**
- * Ask the engine to compute a completion at the specified position
- * of the given compilation unit.
- *
- * @return void
- * completion results are answered through a requestor.
- *
- * @param unit com.ibm.compiler.java.api.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) {
- try {
- int actualCompletionPosition = completionPosition - 1; // for now until we can change the UI.
- CompilationResult result = new CompilationResult(sourceUnit, 1, 1);
- CompilationUnitDeclaration parsedUnit = parser.dietParse(sourceUnit, result, actualCompletionPosition);
-
-// boolean completionNodeFound = false;
- if (parsedUnit != null) {
- // scan the package & import statements first
- if (parsedUnit.currentPackage instanceof CompletionOnPackageReference) {
- findPackages((CompletionOnPackageReference) parsedUnit.currentPackage);
- 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) {
- findImports((CompletionOnImportReference) importReference);
- return;
- }
- }
- }
-
- if (parsedUnit.types != null) {
- try {
- lookupEnvironment.buildTypeBindings(parsedUnit);
- if ((unitScope = parsedUnit.scope) != null) {
- source = sourceUnit.getContents();
- lookupEnvironment.completeTypeBindings(parsedUnit, true);
- parsedUnit.scope.faultInTypes();
- parseMethod(parsedUnit, actualCompletionPosition);
- parsedUnit.resolve();
- }
- } catch (CompletionNodeFound e) {
-// completionNodeFound = true;
- if (e.astNode != null) // if null then we found a problem in the completion node
- complete(e.astNode, e.qualifiedBinding, e.scope);
- }
- }
- }
-
-/* 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) 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 e) { // work-around internal failure - 1GEMF6D
- } catch (InvalidCursorLocation e) { // may eventually report a usefull error
- } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
- } finally {
- reset();
- }
-}
-private TypeBinding[] computeTypes(Expression[] arguments, BlockScope scope) {
- if (arguments == null) return null;
-
- int argsLength = arguments.length;
- TypeBinding[] argTypes = new TypeBinding[argsLength];
- for (int a = argsLength; --a >= 0;)
- argTypes[a] = arguments[a].resolveType(scope);
- return argTypes;
-}
-private void findClassField(char[] token, TypeBinding receiverType) {
- if (token == null) return;
-
- if (token.length <= classField.length && CharOperation.prefixEquals(token, classField, false /* ignore case */))
- requestor.acceptField(
- NoChar,
- NoChar,
- classField,
- NoChar,
- NoChar,
- classField,
- CompilerModifiers.AccStatic | CompilerModifiers.AccPublic,
- startPosition,
- endPosition);
-}
-private void findConstructors(ReferenceBinding currentType, TypeBinding[] argTypes, Scope scope) {
- // No visibility checks can be performed without the scope & invocationSite
- MethodBinding[] methods = currentType.methods();
- int minArgLength = argTypes == null ? 0 : argTypes.length;
- next : for (int f = methods.length; --f >= 0;) {
- MethodBinding constructor = methods[f];
- if (constructor.isConstructor()) {
- 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 (!scope.areTypesCompatible(argTypes[a], 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[] completion = TypeConstants.NoChar; // nothing to insert - do not want to replace the existing selector & arguments
- if (source == null || source.length <= endPosition || source[endPosition] != ')')
- completion = new char[] {')'};
- requestor.acceptMethod(
- currentType.qualifiedPackageName(),
- currentType.qualifiedSourceName(),
- currentType.sourceName(),
- parameterPackageNames,
- parameterTypeNames,
- TypeConstants.NoChar,
- TypeConstants.NoChar,
- completion,
- constructor.modifiers,
- endPosition,
- endPosition);
- }
- }
-}
-// Helper method for findFields(char[], ReferenceBinding, Scope, ObjectVector, boolean)
-
-private void findFields(
- char[] fieldName,
- FieldBinding[] fields,
- Scope scope,
- ObjectVector fieldsFound,
- boolean onlyStaticFields) {
-
- // Inherited fields which are hidden by subclasses are filtered out
- // No visibility checks can be performed without the scope & invocationSite
-
- int fieldLength = fieldName.length;
- next : for (int f = fields.length; --f >= 0;) {
- FieldBinding field = fields[f];
- if (onlyStaticFields && !field.isStatic()) continue next;
- if (fieldLength > field.name.length) continue next;
- if (!CharOperation.prefixEquals(fieldName, field.name, false /* ignore case */)) continue next;
-
- for (int i = fieldsFound.size; --i >= 0;) {
- FieldBinding otherField = (FieldBinding) fieldsFound.elementAt(i);
- if (field == otherField) continue next;
- if (CharOperation.equals(field.name, otherField.name, true)) {
- if (field.declaringClass.isSuperclassOf(otherField.declaringClass)) continue next;
- if (otherField.declaringClass.isInterface())
- if (field.declaringClass.implementsInterface(otherField.declaringClass, true)) continue next;
- }
- }
-
- fieldsFound.add(field);
- requestor.acceptField(
- field.declaringClass.qualifiedPackageName(),
- field.declaringClass.qualifiedSourceName(),
- field.name,
- field.type.qualifiedPackageName(),
- field.type.qualifiedSourceName(),
- field.name, // may include some qualification to resolve ambiguities
- field.modifiers,
- startPosition,
- endPosition);
- }
-}
-private void findFields(
- char[] fieldName,
- ReferenceBinding receiverType,
- Scope scope,
- ObjectVector fieldsFound,
- boolean onlyStaticFields) {
-
- if (fieldName == null) return;
-
- ReferenceBinding currentType = receiverType;
- ReferenceBinding[][] interfacesToVisit = null;
- int lastPosition = -1;
- do {
- ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
- if (itsInterfaces != NoSuperInterfaces) {
- if (interfacesToVisit == null)
- interfacesToVisit = new ReferenceBinding[5][];
- if (++lastPosition == interfacesToVisit.length)
- System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
- interfacesToVisit[lastPosition] = itsInterfaces;
- }
-
- findFields(fieldName, currentType.fields(), scope, fieldsFound, onlyStaticFields);
- currentType = currentType.superclass();
- } while (currentType != null);
-
- if (interfacesToVisit != null) {
- for (int i = 0; i <= lastPosition; i++) {
- ReferenceBinding[] interfaces = interfacesToVisit[i];
- for (int j = 0, length = interfaces.length; j < length; j++) {
- ReferenceBinding anInterface = interfaces[j];
- if ((anInterface.tagBits & TagBits.InterfaceVisited) == 0) { // if interface as not already been visited
- anInterface.tagBits |= TagBits.InterfaceVisited;
-
- findFields(fieldName, anInterface.fields(), scope, fieldsFound, onlyStaticFields);
-
- ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
- if (itsInterfaces != NoSuperInterfaces) {
- if (++lastPosition == interfacesToVisit.length)
- System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
- interfacesToVisit[lastPosition] = itsInterfaces;
- }
- }
- }
- }
-
- // bit reinitialization
- for (int i = 0; i <= lastPosition; i++) {
- ReferenceBinding[] interfaces = interfacesToVisit[i];
- for (int j = 0, length = interfaces.length; j < length; j++)
- interfaces[j].tagBits &= ~TagBits.InterfaceVisited;
- }
- }
-}
-private void findFieldsAndMethods(char[] token, TypeBinding receiverType, Scope scope) {
- if (token == null) return;
-
- if (receiverType.isBaseType()) return; // nothing else is possible with base types
- if (receiverType.isArrayType()) {
- if (token.length <= lengthField.length && CharOperation.prefixEquals(token, lengthField, false /* ignore case */))
- requestor.acceptField(
- NoChar,
- NoChar,
- lengthField,
- NoChar,
- NoChar,
- lengthField,
- CompilerModifiers.AccPublic,
- startPosition,
- endPosition);
-
- receiverType = scope.getJavaLangObject();
- }
-
- findFields(token, (ReferenceBinding) receiverType, scope, new ObjectVector(), false);
- findMethods(token, null, (ReferenceBinding) receiverType, scope, new ObjectVector(), false, false);
-}
-private void findImports(CompletionOnImportReference importReference) {
- char[] importName = CharOperation.concatWith(importReference.tokens, '.');
- if (importName.length == 0) return;
- resolvingImports = true;
- setSourceRange(importReference.sourceStart, importReference.declarationSourceEnd); // want to replace the existing .*;
- nameEnvironment.findPackages(importName, this);
- nameEnvironment.findTypes(importName, this);
-}
-// what about onDemand types? Ignore them since it does not happen!
-// import p1.p2.A.*;
-private void findKeywords(char[] keyword, char[][] choices, Scope scope) {
- int length = keyword.length;
- if (length > 0)
- for (int i = 0; i < choices.length; i++)
- if (length <= choices[i].length && CharOperation.prefixEquals(keyword, choices[i], false /* ignore case */))
- requestor.acceptKeyword(choices[i], startPosition, endPosition);
-}
-// Helper method for findMemberTypes(char[], ReferenceBinding, Scope)
-
-private void findMemberTypes(char[] typeName, ReferenceBinding[] memberTypes, ObjectVector typesFound) {
-
- // 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 (typeLength > memberType.sourceName.length) continue next;
- if (!CharOperation.prefixEquals(typeName, memberType.sourceName, false /* ignore case */)) continue next;
-
- for (int i = typesFound.size; --i >= 0;) {
- ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(i);
- if (memberType == otherType) continue next;
- if (CharOperation.equals(memberType.sourceName, otherType.sourceName, true)) {
- if (memberType.enclosingType().isSuperclassOf(otherType.enclosingType())) continue next;
- if (otherType.enclosingType().isInterface())
- if (memberType.enclosingType().implementsInterface(otherType.enclosingType(), true)) continue next;
- }
- }
-
- typesFound.add(memberType);
- if (memberType.isClass())
- requestor.acceptClass(
- memberType.qualifiedPackageName(),
- memberType.qualifiedSourceName(),
- memberType.sourceName(),
- memberType.modifiers,
- startPosition,
- endPosition);
- else
- requestor.acceptInterface(
- memberType.qualifiedPackageName(),
- memberType.qualifiedSourceName(),
- memberType.sourceName(),
- memberType.modifiers,
- startPosition,
- endPosition);
- }
-}
-private void findMemberTypes(char[] typeName, ReferenceBinding currentType, Scope scope) {
- if (typeName == null) return;
- if (currentType.superInterfaces() == null) return; // we're trying to find a supertype
-
- ObjectVector typesFound = new ObjectVector();
- if (insideQualifiedReference || typeName.length == 0) { // do not search up the hierarchy
- findMemberTypes(typeName, currentType.memberTypes(), typesFound);
- return;
- }
-
- ReferenceBinding[][] interfacesToVisit = null;
- int lastPosition = -1;
- do {
- ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
- if (itsInterfaces != NoSuperInterfaces) {
- if (interfacesToVisit == null)
- interfacesToVisit = new ReferenceBinding[5][];
- if (++lastPosition == interfacesToVisit.length)
- System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
- interfacesToVisit[lastPosition] = itsInterfaces;
- }
-
- findMemberTypes(typeName, currentType.memberTypes(), typesFound);
- currentType = currentType.superclass();
- } while (currentType != null);
-
- if (interfacesToVisit != null) {
- for (int i = 0; i <= lastPosition; i++) {
- ReferenceBinding[] interfaces = interfacesToVisit[i];
- for (int j = 0, length = interfaces.length; j < length; j++) {
- ReferenceBinding anInterface = interfaces[j];
- if ((anInterface.tagBits & TagBits.InterfaceVisited) == 0) { // if interface as not already been visited
- anInterface.tagBits |= TagBits.InterfaceVisited;
-
- findMemberTypes(typeName, anInterface.memberTypes(), typesFound);
-
- ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
- if (itsInterfaces != NoSuperInterfaces) {
- if (++lastPosition == interfacesToVisit.length)
- System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
- interfacesToVisit[lastPosition] = itsInterfaces;
- }
- }
- }
- }
-
- // bit reinitialization
- for (int i = 0; i <= lastPosition; i++) {
- ReferenceBinding[] interfaces = interfacesToVisit[i];
- for (int j = 0, length = interfaces.length; j < length; j++)
- interfaces[j].tagBits &= ~TagBits.InterfaceVisited;
- }
- }
-}
-private void findMessageSends(char[] token, TypeBinding[] argTypes, Scope scope) {
- if (token == null) return;
-
- boolean staticsOnly = false; // need to know if we're in a static context (or inside a constructor)
- int tokenLength = token.length;
- ObjectVector methodsFound = new ObjectVector();
- 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, argTypes, enclosingType, classScope, methodsFound, staticsOnly, true);
- staticsOnly |= enclosingType.isStatic();
- break;
- case Scope.COMPILATION_UNIT_SCOPE :
- break done;
- }
- scope = scope.parent;
- }
-}
-// Helper method for findMethods(char[], TypeBinding[], ReferenceBinding, Scope, ObjectVector, boolean, boolean)
-
-private void findMethods(
- char[] methodName,
- TypeBinding[] argTypes,
- MethodBinding[] methods,
- Scope scope,
- ObjectVector methodsFound,
-// boolean noVoidReturnType, how do you know?
- boolean onlyStaticMethods,
- boolean exactMatch) {
-
- // 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 minArgLength = argTypes == null ? 0 : argTypes.length;
- next : for (int f = methods.length; --f >= 0;) {
- MethodBinding method = methods[f];
- if (method.isConstructor()) continue next;
-// if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next;
- if (onlyStaticMethods && !method.isStatic()) continue next;
- if (exactMatch) {
- if (!CharOperation.equals(methodName, method.selector, false /* ignore case */)) continue next;
- } else {
- if (methodLength > method.selector.length) continue next;
- if (!CharOperation.prefixEquals(methodName, method.selector, false /* ignore case */)) continue next;
- }
- 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 (!scope.areTypesCompatible(argTypes[a], method.parameters[a])) continue next;
-
- for (int i = methodsFound.size; --i >= 0;) {
- MethodBinding otherMethod = (MethodBinding) methodsFound.elementAt(i);
- if (method == otherMethod) continue next;
- if (CharOperation.equals(method.selector, otherMethod.selector, true) && method.areParametersEqual(otherMethod)) {
- if (method.declaringClass.isSuperclassOf(otherMethod.declaringClass)) continue next;
- if (otherMethod.declaringClass.isInterface())
- if (method.declaringClass.implementsInterface(otherMethod.declaringClass, true)) continue next;
- }
- }
-
- methodsFound.add(method);
- 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.parameters[i];
- parameterPackageNames[i] = type.qualifiedPackageName();
- parameterTypeNames[i] = type.qualifiedSourceName();
- }
- char[] completion = TypeConstants.NoChar; // nothing to insert - do not want to replace the existing selector & arguments
- if (!exactMatch) {
- if (source != null && source.length > endPosition && source[endPosition] == '(')
- completion = method.selector;
- else
- completion = CharOperation.concat(method.selector, new char[] {'(', ')'});
- }
- requestor.acceptMethod(
- method.declaringClass.qualifiedPackageName(),
- method.declaringClass.qualifiedSourceName(),
- method.selector,
- parameterPackageNames,
- parameterTypeNames,
- method.returnType.qualifiedPackageName(),
- method.returnType.qualifiedSourceName(),
- completion,
- method.modifiers,
- startPosition,
- endPosition);
- }
-}
-private void findMethods(
- char[] selector,
- TypeBinding[] argTypes,
- ReferenceBinding receiverType,
- Scope scope,
- ObjectVector methodsFound,
- boolean onlyStaticMethods,
- boolean exactMatch) {
-
- if (selector == null) return;
-
- ReferenceBinding currentType = receiverType;
- if (currentType.isInterface()) {
- findMethods(selector, argTypes, currentType.methods(), scope, methodsFound, onlyStaticMethods, exactMatch);
-
- ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
- if (itsInterfaces != NoSuperInterfaces) {
- ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
- int lastPosition = 0;
- interfacesToVisit[lastPosition] = itsInterfaces;
-
- for (int i = 0; i <= lastPosition; i++) {
- ReferenceBinding[] interfaces = interfacesToVisit[i];
- for (int j = 0, length = interfaces.length; j < length; j++) {
- currentType = interfaces[j];
- if ((currentType.tagBits & TagBits.InterfaceVisited) == 0) { // if interface as not already been visited
- currentType.tagBits |= TagBits.InterfaceVisited;
-
- findMethods(selector, argTypes, currentType.methods(), scope, methodsFound, onlyStaticMethods, exactMatch);
-
- itsInterfaces = currentType.superInterfaces();
- if (itsInterfaces != NoSuperInterfaces) {
- if (++lastPosition == interfacesToVisit.length)
- System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
- interfacesToVisit[lastPosition] = itsInterfaces;
- }
- }
- }
- }
-
- // bit reinitialization
- for (int i = 0; i <= lastPosition; i++) {
- ReferenceBinding[] interfaces = interfacesToVisit[i];
- for (int j = 0, length = interfaces.length; j < length; j++)
- interfaces[j].tagBits &= ~TagBits.InterfaceVisited;
- }
- }
- currentType = scope.getJavaLangObject();
- }
-
- while (currentType != null) {
- findMethods(selector, argTypes, currentType.methods(), scope, methodsFound, onlyStaticMethods, exactMatch);
- currentType = currentType.superclass();
- }
-}
-private void findNestedTypes(char[] typeName, ReferenceBinding currentType, Scope scope) {
- if (typeName == null) return;
-
- int typeLength = typeName.length;
- 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.scopeIndex; i < length; i++) {
- if (blockScope.subscopes[i] instanceof ClassScope) {
- SourceTypeBinding localType = ((ClassScope) blockScope.subscopes[i]).referenceContext.binding;
- if (!localType.isAnonymousType()) {
- if (typeLength > localType.sourceName.length) continue next;
- if (!CharOperation.prefixEquals(typeName, localType.sourceName, false /* ignore case */)) continue next;
-
- requestor.acceptClass(
- localType.qualifiedPackageName(),
- localType.sourceName,
- localType.sourceName,
- localType.modifiers,
- startPosition,
- endPosition);
- }
- }
- }
- break;
- case Scope.CLASS_SCOPE :
- findMemberTypes(typeName, scope.enclosingSourceType(), scope);
- 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;
- }
-}
-private void findPackages(CompletionOnPackageReference packageStatement) {
- char[] packageName = CharOperation.concatWith(packageStatement.tokens, '.');
- if (packageName.length == 0) return;
-
- setSourceRange(packageStatement.sourceStart, packageStatement.sourceEnd);
- nameEnvironment.findPackages(CharOperation.toLowerCase(packageName), this);
-}
-private void findTypesAndPackages(char[] token, Scope scope) {
- if (token == null) return;
-
- if (scope.enclosingSourceType() != null)
- findNestedTypes(token, scope.enclosingSourceType(), scope);
-
- if (unitScope != null) {
- int typeLength = token.length;
- SourceTypeBinding[] types = unitScope.topLevelTypes;
- for (int i = 0, length = types.length; i < length; i++) {
- SourceTypeBinding sourceType = types[i];
- if (typeLength > sourceType.sourceName.length) continue;
- if (!CharOperation.prefixEquals(token, sourceType.sourceName, false /* ignore case */)) continue;
-
- requestor.acceptType(
- sourceType.qualifiedPackageName(),
- sourceType.sourceName(),
- sourceType.sourceName(),
- startPosition,
- endPosition);
- }
- }
-
- if (token.length == 0) return;
- findKeywords(token, baseTypes, scope);
- nameEnvironment.findTypes(token, this);
- nameEnvironment.findPackages(token, this);
-}
-private void findTypesAndSubpackages(char[] token, PackageBinding packageBinding) {
- 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] = '.';
- }
- nameEnvironment.findTypes(qualifiedName, this);
- nameEnvironment.findPackages(qualifiedName, this);
-}
-private void findVariablesAndMethods(char[] token, Scope scope) {
- 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)
- char[][] found = null;
- int lastPosition = -1;
- int tokenLength = token.length;
- ObjectVector fieldsFound = new ObjectVector();
- ObjectVector methodsFound = new ObjectVector();
- 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;
- case Scope.BLOCK_SCOPE :
- BlockScope blockScope = (BlockScope) scope;
- next : for (int i = 0, length = blockScope.locals.length; i < length; i++) {
- LocalVariableBinding local = blockScope.locals[i];
- if (local == null) break next;
- if (tokenLength > local.name.length) continue next;
- if (!CharOperation.prefixEquals(token, local.name, false /* ignore case */)) continue next;
- if (local.isSecret()) continue next;
-
- if (found == null) {
- found = new char[5][];
- } else {
- for (int f = 0; f < found.length; f++) {
- char[] name = found[f];
- if (name == null) break;
- if (CharOperation.equals(name, local.name, false /* ignore case */)) continue next;
- }
- }
- if (++lastPosition == found.length)
- System.arraycopy(found, 0, found = new char[lastPosition * 2][], 0, lastPosition);
- found[lastPosition] = local.name;
-
- requestor.acceptLocalVariable(
- local.name,
- NoChar,
- local.type == null ? local.declaration.type.toString().toCharArray() : local.type.qualifiedSourceName(),
- local.modifiers,
- startPosition,
- endPosition);
- }
- break;
- case Scope.CLASS_SCOPE :
- ClassScope classScope = (ClassScope) scope;
- 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 { */
- findFields(token, enclosingType, classScope, fieldsFound, staticsOnly);
- findMethods(token, null, enclosingType, classScope, methodsFound, staticsOnly, false);
- staticsOnly |= enclosingType.isStatic();
-// }
- break;
- case Scope.COMPILATION_UNIT_SCOPE :
- break done;
- }
- scope = scope.parent;
- }
-}
-public AssistParser getParser(){
- return parser;
-}
-private boolean mustQualifyType(char[][] packageName, char[] readableTypeName) {
- // If there are no types defined into the current CU yet.
- if (unitScope == null)
- return true;
- if (CharOperation.equals(unitScope.fPackage.compoundName, packageName))
- return false;
-
- ImportBinding[] imports = unitScope.imports;
- for (int i = 0, length = imports.length; i < length; i++) {
- if (imports[i].onDemand) {
- if (CharOperation.equals(imports[i].compoundName, packageName))
- return false; // how do you match p1.p2.A.* ?
- } else if (CharOperation.equals(imports[i].readableName(), readableTypeName)) {
- return false;
- }
- }
- return true;
-}
-protected void reset() {
- super.reset();
- this.knownPkgs = new HashtableOfObject(10);
-}
-private void setSourceRange(int start, int end) {
- this.startPosition = start;
- this.endPosition = end + 1; // Add 1 for now
-}
-}
+package org.eclipse.jdt.internal.codeassist;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import java.util.Locale;
+
+import org.eclipse.jdt.internal.compiler.*;
+import org.eclipse.jdt.internal.compiler.env.*;
+
+import org.eclipse.jdt.internal.codeassist.impl.*;
+import org.eclipse.jdt.internal.codeassist.complete.*;
+
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.compiler.util.*;
+import org.eclipse.jdt.internal.compiler.impl.*;
+
+/**
+ * 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).
+ */
+public final class CompletionEngine extends Engine implements ISearchRequestor, TypeConstants {
+ CompletionParser parser;
+ ISearchableNameEnvironment nameEnvironment;
+ ICompletionRequestor requestor;
+
+ CompilationUnitScope unitScope;
+ char[] source;
+ boolean resolvingImports = false;
+ boolean insideQualifiedReference = false;
+ int startPosition, endPosition;
+ HashtableOfObject knownPkgs = 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 char[][] baseTypes =
+ new char[][] {
+ "boolean"/*nonNLS*/.toCharArray(),
+ "byte"/*nonNLS*/.toCharArray(),
+ "char"/*nonNLS*/.toCharArray(),
+ "double"/*nonNLS*/.toCharArray(),
+ "float"/*nonNLS*/.toCharArray(),
+ "int"/*nonNLS*/.toCharArray(),
+ "long"/*nonNLS*/.toCharArray(),
+ "short"/*nonNLS*/.toCharArray(),
+ "void"/*nonNLS*/.toCharArray()};
+
+ static final char[] classField = "class"/*nonNLS*/.toCharArray();
+ static final char[] lengthField = "length"/*nonNLS*/.toCharArray();
+/**
+ * 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 environment com.ibm.codeassist.java.api.ISearchableNameEnvironment
+ * used to resolve type/package references and search for types/packages
+ * based on partial names.
+ *
+ * @param requestor com.ibm.codeassist.java.api.ICompletionRequestor
+ * since the engine might produce answers of various forms, the engine
+ * is associated with a requestor able to accept all possible completions.
+ *
+ * @param options com.ibm.compiler.java.api.ConfigurableOptions
+ * set of options used to configure the code assist engine.
+ */
+
+public CompletionEngine(
+ ISearchableNameEnvironment nameEnvironment, ICompletionRequestor requestor, ConfigurableOption[] settings) {
+
+ this.requestor = requestor;
+ this.nameEnvironment = nameEnvironment;
+
+ CompilerOptions options = new CompilerOptions(settings);
+ ProblemReporter problemReporter =
+ new ProblemReporter(
+ DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+ options,
+ new DefaultProblemFactory(Locale.getDefault())) {
+ public void record(IProblem problem, CompilationResult unitResult) {
+ if (problem.getID() != ProblemIrritants.UnmatchedBracket) {
+ unitResult.record(problem);
+ CompletionEngine.this.requestor.acceptError(problem);
+ }
+ }
+ };
+
+ this.parser = new CompletionParser(problemReporter);
+ this.lookupEnvironment = new LookupEnvironment(this, options, problemReporter, nameEnvironment);
+}
+/**
+ * One result of the search consists of a new class.
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * Nested type names are in the qualified form "A.M".
+ * The default package is represented by an empty array.
+ */
+public void acceptClass(char[] packageName, char[] className, int modifiers) {
+ char[] completionName = CharOperation.concat(packageName, className, '.');
+ if (resolvingImports) {
+ completionName = CharOperation.concat(completionName, new char[] {';'});
+ } else if (!insideQualifiedReference) {
+ if (mustQualifyType(CharOperation.splitOn('.', packageName), completionName)) {
+ if (packageName == null || packageName.length == 0)
+ if (unitScope != null && unitScope.fPackage.compoundName != NoCharChar)
+ return; // ignore types from the default package from outside it
+ } else {
+ completionName = className;
+ }
+ }
+
+ requestor.acceptClass(
+ packageName,
+ className,
+ completionName,
+ modifiers,
+ startPosition,
+ endPosition);
+}
+/**
+ * One result of the search consists of a new interface.
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * Nested type names are in the qualified form "A.I".
+ * The default package is represented by an empty array.
+ */
+public void acceptInterface(char[] packageName, char[] interfaceName, int modifiers) {
+ char[] completionName = CharOperation.concat(packageName, interfaceName, '.');
+ if (resolvingImports) {
+ completionName = CharOperation.concat(completionName, new char[] {';'});
+ } else if (!insideQualifiedReference) {
+ if (mustQualifyType(CharOperation.splitOn('.', packageName), completionName)) {
+ if (packageName == null || packageName.length == 0)
+ if (unitScope != null && unitScope.fPackage.compoundName != NoCharChar)
+ return; // ignore types from the default package from outside it
+ } else {
+ completionName = interfaceName;
+ }
+ }
+
+ requestor.acceptInterface(
+ packageName,
+ interfaceName,
+ completionName,
+ modifiers,
+ startPosition,
+ endPosition);
+}
+/**
+ * One result of the search consists of a new package.
+ *
+ * NOTE - All package names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * The default package is represented by an empty array.
+ */
+public void acceptPackage(char[] packageName) {
+ if (this.knownPkgs.containsKey(packageName)) return;
+ this.knownPkgs.put(packageName, this);
+ requestor.acceptPackage(
+ packageName,
+ resolvingImports ? CharOperation.concat(packageName, new char[] {'.', '*', ';'}) : packageName,
+ startPosition,
+ endPosition);
+}
+/**
+ * One result of the search consists of a new type.
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * Nested type names are in the qualified form "A.M".
+ * The default package is represented by an empty array.
+ */
+public void acceptType(char[] packageName, char[] typeName) {
+ char[] completionName = CharOperation.concat(packageName, typeName, '.');
+ if (resolvingImports) {
+ completionName = CharOperation.concat(completionName, new char[] {';'});
+ } else if (!insideQualifiedReference) {
+ if (mustQualifyType(CharOperation.splitOn('.', packageName), completionName)) {
+ if (packageName == null || packageName.length == 0)
+ if (unitScope != null && unitScope.fPackage.compoundName != NoCharChar)
+ return; // ignore types from the default package from outside it
+ } else {
+ completionName = typeName;
+ }
+ }
+
+ requestor.acceptType(
+ packageName,
+ typeName,
+ completionName,
+ startPosition,
+ endPosition);
+}
+private void complete(AstNode astNode, Binding qualifiedBinding, Scope scope) {
+ setSourceRange(astNode.sourceStart, astNode.sourceEnd); // defaults... some nodes will change these
+
+ if (astNode instanceof CompletionOnFieldType) {
+ CompletionOnSingleTypeReference type =
+ (CompletionOnSingleTypeReference) ((CompletionOnFieldType) astNode).type;
+ char[] token = type.token;
+ setSourceRange(type.sourceStart, type.sourceEnd);
+// findKeywords(token, modifiers, scope); // could be the start of a field, method or member type
+ findTypesAndPackages(token, scope);
+ } else if (astNode instanceof CompletionOnSingleNameReference) {
+ char[] token = ((CompletionOnSingleNameReference) astNode).token;
+ findVariablesAndMethods(token, scope);
+ findTypesAndPackages(token, scope); // can be the start of a qualified type name
+ } else if (astNode instanceof CompletionOnSingleTypeReference) {
+ char[] token = ((CompletionOnSingleTypeReference) astNode).token;
+ if (qualifiedBinding == null)
+ findTypesAndPackages(token, scope); // can be the start of a qualified type name
+ else
+ findMemberTypes(token, (ReferenceBinding) qualifiedBinding, scope);
+ } else if (astNode instanceof CompletionOnQualifiedNameReference) {
+ insideQualifiedReference = true;
+ CompletionOnQualifiedNameReference ref = (CompletionOnQualifiedNameReference) astNode;
+ char[] token = ref.completionIdentifier;
+ long completionPosition = ref.sourcePositions[ref.sourcePositions.length - 1];
+ if (qualifiedBinding instanceof VariableBinding) {
+ setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+ TypeBinding receiverType = ((VariableBinding) qualifiedBinding).type;
+ if (receiverType != null)
+ findFieldsAndMethods(token, receiverType, scope);
+ } else if (qualifiedBinding instanceof ReferenceBinding) {
+ ReferenceBinding receiverType = (ReferenceBinding) qualifiedBinding;
+ setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+ findMemberTypes(token, receiverType, scope);
+ findClassField(token, (TypeBinding) qualifiedBinding);
+ findFields(token, receiverType, scope, new ObjectVector(), true);
+ findMethods(token, null, receiverType, scope, new ObjectVector(), true, false);
+ } else if (qualifiedBinding instanceof PackageBinding) {
+ setSourceRange(astNode.sourceStart, (int) completionPosition); // replace to the end of the completion identifier
+ findTypesAndSubpackages(token, (PackageBinding) qualifiedBinding);
+ }
+ } else if (astNode instanceof CompletionOnQualifiedTypeReference) {
+ insideQualifiedReference = true;
+ CompletionOnQualifiedTypeReference ref = (CompletionOnQualifiedTypeReference) astNode;
+ char[] token = ref.completionIdentifier;
+ long completionPosition = ref.sourcePositions[ref.tokens.length]; // get the source positions of the completion identifier
+ if (qualifiedBinding instanceof ReferenceBinding) {
+ setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+ findMemberTypes(token, (ReferenceBinding) qualifiedBinding, scope);
+ } else if (qualifiedBinding instanceof PackageBinding) {
+ setSourceRange(astNode.sourceStart, (int) completionPosition); // replace to the end of the completion identifier
+ findTypesAndSubpackages(token, (PackageBinding) qualifiedBinding);
+ }
+ } else if (astNode instanceof CompletionOnMemberAccess) {
+ CompletionOnMemberAccess access = (CompletionOnMemberAccess) astNode;
+ long completionPosition = access.nameSourcePosition;
+ setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+ findFieldsAndMethods(access.token, (TypeBinding) qualifiedBinding, scope);
+ } else if (astNode instanceof CompletionOnMessageSend) {
+ CompletionOnMessageSend messageSend = (CompletionOnMessageSend) astNode;
+ TypeBinding[] argTypes = computeTypes(messageSend.arguments, (BlockScope) scope);
+ if (qualifiedBinding == null)
+ findMessageSends(messageSend.selector, argTypes, scope);
+ else
+ findMethods(messageSend.selector, argTypes, (ReferenceBinding) qualifiedBinding, scope, new ObjectVector(), false, true);
+ } else if (astNode instanceof CompletionOnExplicitConstructorCall) {
+ CompletionOnExplicitConstructorCall constructorCall = (CompletionOnExplicitConstructorCall) astNode;
+ TypeBinding[] argTypes = computeTypes(constructorCall.arguments, (BlockScope) scope);
+ findConstructors((ReferenceBinding) qualifiedBinding, argTypes, scope);
+ } else if (astNode instanceof CompletionOnQualifiedAllocationExpression) {
+ CompletionOnQualifiedAllocationExpression allocExpression = (CompletionOnQualifiedAllocationExpression) astNode;
+ TypeBinding[] argTypes = computeTypes(allocExpression.arguments, (BlockScope) scope);
+ findConstructors((ReferenceBinding) qualifiedBinding, argTypes, scope);
+ } else if (astNode instanceof CompletionOnClassLiteralAccess) {
+ char[] token = ((CompletionOnClassLiteralAccess) astNode).completionIdentifier;
+ findClassField(token, (TypeBinding) qualifiedBinding);
+ }
+}
+/**
+ * Ask the engine to compute a completion at the specified position
+ * of the given compilation unit.
+ *
+ * @return void
+ * completion results are answered through a requestor.
+ *
+ * @param unit com.ibm.compiler.java.api.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) {
+ try {
+ int actualCompletionPosition = completionPosition - 1; // for now until we can change the UI.
+ CompilationResult result = new CompilationResult(sourceUnit, 1, 1);
+ CompilationUnitDeclaration parsedUnit = parser.dietParse(sourceUnit, result, actualCompletionPosition);
+
+// boolean completionNodeFound = false;
+ if (parsedUnit != null) {
+ // scan the package & import statements first
+ if (parsedUnit.currentPackage instanceof CompletionOnPackageReference) {
+ findPackages((CompletionOnPackageReference) parsedUnit.currentPackage);
+ 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) {
+ findImports((CompletionOnImportReference) importReference);
+ return;
+ }
+ }
+ }
+
+ if (parsedUnit.types != null) {
+ try {
+ lookupEnvironment.buildTypeBindings(parsedUnit);
+ if ((unitScope = parsedUnit.scope) != null) {
+ source = sourceUnit.getContents();
+ lookupEnvironment.completeTypeBindings(parsedUnit, true);
+ parsedUnit.scope.faultInTypes();
+ parseMethod(parsedUnit, actualCompletionPosition);
+ parsedUnit.resolve();
+ }
+ } catch (CompletionNodeFound e) {
+// completionNodeFound = true;
+ if (e.astNode != null) // if null then we found a problem in the completion node
+ complete(e.astNode, e.qualifiedBinding, e.scope);
+ }
+ }
+ }
+
+/* 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) 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 e) { // work-around internal failure - 1GEMF6D
+ } catch (InvalidCursorLocation e) { // may eventually report a usefull error
+ } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
+ } finally {
+ reset();
+ }
+}
+private TypeBinding[] computeTypes(Expression[] arguments, BlockScope scope) {
+ if (arguments == null) return null;
+
+ int argsLength = arguments.length;
+ TypeBinding[] argTypes = new TypeBinding[argsLength];
+ for (int a = argsLength; --a >= 0;)
+ argTypes[a] = arguments[a].resolveType(scope);
+ return argTypes;
+}
+private void findClassField(char[] token, TypeBinding receiverType) {
+ if (token == null) return;
+
+ if (token.length <= classField.length && CharOperation.prefixEquals(token, classField, false /* ignore case */))
+ requestor.acceptField(
+ NoChar,
+ NoChar,
+ classField,
+ NoChar,
+ NoChar,
+ classField,
+ CompilerModifiers.AccStatic | CompilerModifiers.AccPublic,
+ startPosition,
+ endPosition);
+}
+private void findConstructors(ReferenceBinding currentType, TypeBinding[] argTypes, Scope scope) {
+ // No visibility checks can be performed without the scope & invocationSite
+ MethodBinding[] methods = currentType.methods();
+ int minArgLength = argTypes == null ? 0 : argTypes.length;
+ next : for (int f = methods.length; --f >= 0;) {
+ MethodBinding constructor = methods[f];
+ if (constructor.isConstructor()) {
+ 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 (!scope.areTypesCompatible(argTypes[a], 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[] completion = TypeConstants.NoChar; // nothing to insert - do not want to replace the existing selector & arguments
+ if (source == null || source.length <= endPosition || source[endPosition] != ')')
+ completion = new char[] {')'};
+ requestor.acceptMethod(
+ currentType.qualifiedPackageName(),
+ currentType.qualifiedSourceName(),
+ currentType.sourceName(),
+ parameterPackageNames,
+ parameterTypeNames,
+ TypeConstants.NoChar,
+ TypeConstants.NoChar,
+ completion,
+ constructor.modifiers,
+ endPosition,
+ endPosition);
+ }
+ }
+}
+// Helper method for findFields(char[], ReferenceBinding, Scope, ObjectVector, boolean)
+
+private void findFields(
+ char[] fieldName,
+ FieldBinding[] fields,
+ Scope scope,
+ ObjectVector fieldsFound,
+ boolean onlyStaticFields) {
+
+ // Inherited fields which are hidden by subclasses are filtered out
+ // No visibility checks can be performed without the scope & invocationSite
+
+ int fieldLength = fieldName.length;
+ next : for (int f = fields.length; --f >= 0;) {
+ FieldBinding field = fields[f];
+ if (onlyStaticFields && !field.isStatic()) continue next;
+ if (fieldLength > field.name.length) continue next;
+ if (!CharOperation.prefixEquals(fieldName, field.name, false /* ignore case */)) continue next;
+
+ for (int i = fieldsFound.size; --i >= 0;) {
+ FieldBinding otherField = (FieldBinding) fieldsFound.elementAt(i);
+ if (field == otherField) continue next;
+ if (CharOperation.equals(field.name, otherField.name, true)) {
+ if (field.declaringClass.isSuperclassOf(otherField.declaringClass)) continue next;
+ if (otherField.declaringClass.isInterface())
+ if (field.declaringClass.implementsInterface(otherField.declaringClass, true)) continue next;
+ }
+ }
+
+ fieldsFound.add(field);
+ requestor.acceptField(
+ field.declaringClass.qualifiedPackageName(),
+ field.declaringClass.qualifiedSourceName(),
+ field.name,
+ field.type.qualifiedPackageName(),
+ field.type.qualifiedSourceName(),
+ field.name, // may include some qualification to resolve ambiguities
+ field.modifiers,
+ startPosition,
+ endPosition);
+ }
+}
+private void findFields(
+ char[] fieldName,
+ ReferenceBinding receiverType,
+ Scope scope,
+ ObjectVector fieldsFound,
+ boolean onlyStaticFields) {
+
+ if (fieldName == null) return;
+
+ ReferenceBinding currentType = receiverType;
+ ReferenceBinding[][] interfacesToVisit = null;
+ int lastPosition = -1;
+ do {
+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+ if (itsInterfaces != NoSuperInterfaces) {
+ if (interfacesToVisit == null)
+ interfacesToVisit = new ReferenceBinding[5][];
+ if (++lastPosition == interfacesToVisit.length)
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+ interfacesToVisit[lastPosition] = itsInterfaces;
+ }
+
+ findFields(fieldName, currentType.fields(), scope, fieldsFound, onlyStaticFields);
+ currentType = currentType.superclass();
+ } while (currentType != null);
+
+ if (interfacesToVisit != null) {
+ for (int i = 0; i <= lastPosition; i++) {
+ ReferenceBinding[] interfaces = interfacesToVisit[i];
+ for (int j = 0, length = interfaces.length; j < length; j++) {
+ ReferenceBinding anInterface = interfaces[j];
+ if ((anInterface.tagBits & TagBits.InterfaceVisited) == 0) { // if interface as not already been visited
+ anInterface.tagBits |= TagBits.InterfaceVisited;
+
+ findFields(fieldName, anInterface.fields(), scope, fieldsFound, onlyStaticFields);
+
+ ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
+ if (itsInterfaces != NoSuperInterfaces) {
+ if (++lastPosition == interfacesToVisit.length)
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+ interfacesToVisit[lastPosition] = itsInterfaces;
+ }
+ }
+ }
+ }
+
+ // bit reinitialization
+ for (int i = 0; i <= lastPosition; i++) {
+ ReferenceBinding[] interfaces = interfacesToVisit[i];
+ for (int j = 0, length = interfaces.length; j < length; j++)
+ interfaces[j].tagBits &= ~TagBits.InterfaceVisited;
+ }
+ }
+}
+private void findFieldsAndMethods(char[] token, TypeBinding receiverType, Scope scope) {
+ if (token == null) return;
+
+ if (receiverType.isBaseType()) return; // nothing else is possible with base types
+ if (receiverType.isArrayType()) {
+ if (token.length <= lengthField.length && CharOperation.prefixEquals(token, lengthField, false /* ignore case */))
+ requestor.acceptField(
+ NoChar,
+ NoChar,
+ lengthField,
+ NoChar,
+ NoChar,
+ lengthField,
+ CompilerModifiers.AccPublic,
+ startPosition,
+ endPosition);
+
+ receiverType = scope.getJavaLangObject();
+ }
+
+ findFields(token, (ReferenceBinding) receiverType, scope, new ObjectVector(), false);
+ findMethods(token, null, (ReferenceBinding) receiverType, scope, new ObjectVector(), false, false);
+}
+private void findImports(CompletionOnImportReference importReference) {
+ char[] importName = CharOperation.concatWith(importReference.tokens, '.');
+ if (importName.length == 0) return;
+ resolvingImports = true;
+ setSourceRange(importReference.sourceStart, importReference.declarationSourceEnd); // want to replace the existing .*;
+ nameEnvironment.findPackages(importName, this);
+ nameEnvironment.findTypes(importName, this);
+}
+// what about onDemand types? Ignore them since it does not happen!
+// import p1.p2.A.*;
+private void findKeywords(char[] keyword, char[][] choices, Scope scope) {
+ int length = keyword.length;
+ if (length > 0)
+ for (int i = 0; i < choices.length; i++)
+ if (length <= choices[i].length && CharOperation.prefixEquals(keyword, choices[i], false /* ignore case */))
+ requestor.acceptKeyword(choices[i], startPosition, endPosition);
+}
+// Helper method for findMemberTypes(char[], ReferenceBinding, Scope)
+
+private void findMemberTypes(char[] typeName, ReferenceBinding[] memberTypes, ObjectVector typesFound) {
+
+ // 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 (typeLength > memberType.sourceName.length) continue next;
+ if (!CharOperation.prefixEquals(typeName, memberType.sourceName, false /* ignore case */)) continue next;
+
+ for (int i = typesFound.size; --i >= 0;) {
+ ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(i);
+ if (memberType == otherType) continue next;
+ if (CharOperation.equals(memberType.sourceName, otherType.sourceName, true)) {
+ if (memberType.enclosingType().isSuperclassOf(otherType.enclosingType())) continue next;
+ if (otherType.enclosingType().isInterface())
+ if (memberType.enclosingType().implementsInterface(otherType.enclosingType(), true)) continue next;
+ }
+ }
+
+ typesFound.add(memberType);
+ if (memberType.isClass())
+ requestor.acceptClass(
+ memberType.qualifiedPackageName(),
+ memberType.qualifiedSourceName(),
+ memberType.sourceName(),
+ memberType.modifiers,
+ startPosition,
+ endPosition);
+ else
+ requestor.acceptInterface(
+ memberType.qualifiedPackageName(),
+ memberType.qualifiedSourceName(),
+ memberType.sourceName(),
+ memberType.modifiers,
+ startPosition,
+ endPosition);
+ }
+}
+private void findMemberTypes(char[] typeName, ReferenceBinding currentType, Scope scope) {
+ if (typeName == null) return;
+ if (currentType.superInterfaces() == null) return; // we're trying to find a supertype
+
+ ObjectVector typesFound = new ObjectVector();
+ if (insideQualifiedReference || typeName.length == 0) { // do not search up the hierarchy
+ findMemberTypes(typeName, currentType.memberTypes(), typesFound);
+ return;
+ }
+
+ ReferenceBinding[][] interfacesToVisit = null;
+ int lastPosition = -1;
+ do {
+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+ if (itsInterfaces != NoSuperInterfaces) {
+ if (interfacesToVisit == null)
+ interfacesToVisit = new ReferenceBinding[5][];
+ if (++lastPosition == interfacesToVisit.length)
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+ interfacesToVisit[lastPosition] = itsInterfaces;
+ }
+
+ findMemberTypes(typeName, currentType.memberTypes(), typesFound);
+ currentType = currentType.superclass();
+ } while (currentType != null);
+
+ if (interfacesToVisit != null) {
+ for (int i = 0; i <= lastPosition; i++) {
+ ReferenceBinding[] interfaces = interfacesToVisit[i];
+ for (int j = 0, length = interfaces.length; j < length; j++) {
+ ReferenceBinding anInterface = interfaces[j];
+ if ((anInterface.tagBits & TagBits.InterfaceVisited) == 0) { // if interface as not already been visited
+ anInterface.tagBits |= TagBits.InterfaceVisited;
+
+ findMemberTypes(typeName, anInterface.memberTypes(), typesFound);
+
+ ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
+ if (itsInterfaces != NoSuperInterfaces) {
+ if (++lastPosition == interfacesToVisit.length)
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+ interfacesToVisit[lastPosition] = itsInterfaces;
+ }
+ }
+ }
+ }
+
+ // bit reinitialization
+ for (int i = 0; i <= lastPosition; i++) {
+ ReferenceBinding[] interfaces = interfacesToVisit[i];
+ for (int j = 0, length = interfaces.length; j < length; j++)
+ interfaces[j].tagBits &= ~TagBits.InterfaceVisited;
+ }
+ }
+}
+private void findMessageSends(char[] token, TypeBinding[] argTypes, Scope scope) {
+ if (token == null) return;
+
+ boolean staticsOnly = false; // need to know if we're in a static context (or inside a constructor)
+ int tokenLength = token.length;
+ ObjectVector methodsFound = new ObjectVector();
+ 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, argTypes, enclosingType, classScope, methodsFound, staticsOnly, true);
+ staticsOnly |= enclosingType.isStatic();
+ break;
+ case Scope.COMPILATION_UNIT_SCOPE :
+ break done;
+ }
+ scope = scope.parent;
+ }
+}
+// Helper method for findMethods(char[], TypeBinding[], ReferenceBinding, Scope, ObjectVector, boolean, boolean)
+
+private void findMethods(
+ char[] methodName,
+ TypeBinding[] argTypes,
+ MethodBinding[] methods,
+ Scope scope,
+ ObjectVector methodsFound,
+// boolean noVoidReturnType, how do you know?
+ boolean onlyStaticMethods,
+ boolean exactMatch) {
+
+ // 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 minArgLength = argTypes == null ? 0 : argTypes.length;
+ next : for (int f = methods.length; --f >= 0;) {
+ MethodBinding method = methods[f];
+ if (method.isConstructor()) continue next;
+// if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next;
+ if (onlyStaticMethods && !method.isStatic()) continue next;
+ if (exactMatch) {
+ if (!CharOperation.equals(methodName, method.selector, false /* ignore case */)) continue next;
+ } else {
+ if (methodLength > method.selector.length) continue next;
+ if (!CharOperation.prefixEquals(methodName, method.selector, false /* ignore case */)) continue next;
+ }
+ 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 (!scope.areTypesCompatible(argTypes[a], method.parameters[a])) continue next;
+
+ for (int i = methodsFound.size; --i >= 0;) {
+ MethodBinding otherMethod = (MethodBinding) methodsFound.elementAt(i);
+ if (method == otherMethod) continue next;
+ if (CharOperation.equals(method.selector, otherMethod.selector, true) && method.areParametersEqual(otherMethod)) {
+ if (method.declaringClass.isSuperclassOf(otherMethod.declaringClass)) continue next;
+ if (otherMethod.declaringClass.isInterface())
+ if (method.declaringClass.implementsInterface(otherMethod.declaringClass, true)) continue next;
+ }
+ }
+
+ methodsFound.add(method);
+ 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.parameters[i];
+ parameterPackageNames[i] = type.qualifiedPackageName();
+ parameterTypeNames[i] = type.qualifiedSourceName();
+ }
+ char[] completion = TypeConstants.NoChar; // nothing to insert - do not want to replace the existing selector & arguments
+ if (!exactMatch) {
+ if (source != null && source.length > endPosition && source[endPosition] == '(')
+ completion = method.selector;
+ else
+ completion = CharOperation.concat(method.selector, new char[] {'(', ')'});
+ }
+ requestor.acceptMethod(
+ method.declaringClass.qualifiedPackageName(),
+ method.declaringClass.qualifiedSourceName(),
+ method.selector,
+ parameterPackageNames,
+ parameterTypeNames,
+ method.returnType.qualifiedPackageName(),
+ method.returnType.qualifiedSourceName(),
+ completion,
+ method.modifiers,
+ startPosition,
+ endPosition);
+ }
+}
+private void findMethods(
+ char[] selector,
+ TypeBinding[] argTypes,
+ ReferenceBinding receiverType,
+ Scope scope,
+ ObjectVector methodsFound,
+ boolean onlyStaticMethods,
+ boolean exactMatch) {
+
+ if (selector == null) return;
+
+ ReferenceBinding currentType = receiverType;
+ if (currentType.isInterface()) {
+ findMethods(selector, argTypes, currentType.methods(), scope, methodsFound, onlyStaticMethods, exactMatch);
+
+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+ if (itsInterfaces != NoSuperInterfaces) {
+ ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
+ int lastPosition = 0;
+ interfacesToVisit[lastPosition] = itsInterfaces;
+
+ for (int i = 0; i <= lastPosition; i++) {
+ ReferenceBinding[] interfaces = interfacesToVisit[i];
+ for (int j = 0, length = interfaces.length; j < length; j++) {
+ currentType = interfaces[j];
+ if ((currentType.tagBits & TagBits.InterfaceVisited) == 0) { // if interface as not already been visited
+ currentType.tagBits |= TagBits.InterfaceVisited;
+
+ findMethods(selector, argTypes, currentType.methods(), scope, methodsFound, onlyStaticMethods, exactMatch);
+
+ itsInterfaces = currentType.superInterfaces();
+ if (itsInterfaces != NoSuperInterfaces) {
+ if (++lastPosition == interfacesToVisit.length)
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+ interfacesToVisit[lastPosition] = itsInterfaces;
+ }
+ }
+ }
+ }
+
+ // bit reinitialization
+ for (int i = 0; i <= lastPosition; i++) {
+ ReferenceBinding[] interfaces = interfacesToVisit[i];
+ for (int j = 0, length = interfaces.length; j < length; j++)
+ interfaces[j].tagBits &= ~TagBits.InterfaceVisited;
+ }
+ }
+ currentType = scope.getJavaLangObject();
+ }
+
+ while (currentType != null) {
+ findMethods(selector, argTypes, currentType.methods(), scope, methodsFound, onlyStaticMethods, exactMatch);
+ currentType = currentType.superclass();
+ }
+}
+private void findNestedTypes(char[] typeName, ReferenceBinding currentType, Scope scope) {
+ if (typeName == null) return;
+
+ int typeLength = typeName.length;
+ 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.scopeIndex; i < length; i++) {
+ if (blockScope.subscopes[i] instanceof ClassScope) {
+ SourceTypeBinding localType = ((ClassScope) blockScope.subscopes[i]).referenceContext.binding;
+ if (!localType.isAnonymousType()) {
+ if (typeLength > localType.sourceName.length) continue next;
+ if (!CharOperation.prefixEquals(typeName, localType.sourceName, false /* ignore case */)) continue next;
+
+ requestor.acceptClass(
+ localType.qualifiedPackageName(),
+ localType.sourceName,
+ localType.sourceName,
+ localType.modifiers,
+ startPosition,
+ endPosition);
+ }
+ }
+ }
+ break;
+ case Scope.CLASS_SCOPE :
+ findMemberTypes(typeName, scope.enclosingSourceType(), scope);
+ 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;
+ }
+}
+private void findPackages(CompletionOnPackageReference packageStatement) {
+ char[] packageName = CharOperation.concatWith(packageStatement.tokens, '.');
+ if (packageName.length == 0) return;
+
+ setSourceRange(packageStatement.sourceStart, packageStatement.sourceEnd);
+ nameEnvironment.findPackages(CharOperation.toLowerCase(packageName), this);
+}
+private void findTypesAndPackages(char[] token, Scope scope) {
+ if (token == null) return;
+
+ if (scope.enclosingSourceType() != null)
+ findNestedTypes(token, scope.enclosingSourceType(), scope);
+
+ if (unitScope != null) {
+ int typeLength = token.length;
+ SourceTypeBinding[] types = unitScope.topLevelTypes;
+ for (int i = 0, length = types.length; i < length; i++) {
+ SourceTypeBinding sourceType = types[i];
+ if (typeLength > sourceType.sourceName.length) continue;
+ if (!CharOperation.prefixEquals(token, sourceType.sourceName, false /* ignore case */)) continue;
+
+ requestor.acceptType(
+ sourceType.qualifiedPackageName(),
+ sourceType.sourceName(),
+ sourceType.sourceName(),
+ startPosition,
+ endPosition);
+ }
+ }
+
+ if (token.length == 0) return;
+ findKeywords(token, baseTypes, scope);
+ nameEnvironment.findTypes(token, this);
+ nameEnvironment.findPackages(token, this);
+}
+private void findTypesAndSubpackages(char[] token, PackageBinding packageBinding) {
+ 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] = '.';
+ }
+ nameEnvironment.findTypes(qualifiedName, this);
+ nameEnvironment.findPackages(qualifiedName, this);
+}
+private void findVariablesAndMethods(char[] token, Scope scope) {
+ 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)
+ char[][] found = null;
+ int lastPosition = -1;
+ int tokenLength = token.length;
+ ObjectVector fieldsFound = new ObjectVector();
+ ObjectVector methodsFound = new ObjectVector();
+ 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;
+ case Scope.BLOCK_SCOPE :
+ BlockScope blockScope = (BlockScope) scope;
+ next : for (int i = 0, length = blockScope.locals.length; i < length; i++) {
+ LocalVariableBinding local = blockScope.locals[i];
+ if (local == null) break next;
+ if (tokenLength > local.name.length) continue next;
+ if (!CharOperation.prefixEquals(token, local.name, false /* ignore case */)) continue next;
+ if (local.isSecret()) continue next;
+
+ if (found == null) {
+ found = new char[5][];
+ } else {
+ for (int f = 0; f < found.length; f++) {
+ char[] name = found[f];
+ if (name == null) break;
+ if (CharOperation.equals(name, local.name, false /* ignore case */)) continue next;
+ }
+ }
+ if (++lastPosition == found.length)
+ System.arraycopy(found, 0, found = new char[lastPosition * 2][], 0, lastPosition);
+ found[lastPosition] = local.name;
+
+ requestor.acceptLocalVariable(
+ local.name,
+ NoChar,
+ local.type == null ? local.declaration.type.toString().toCharArray() : local.type.qualifiedSourceName(),
+ local.modifiers,
+ startPosition,
+ endPosition);
+ }
+ break;
+ case Scope.CLASS_SCOPE :
+ ClassScope classScope = (ClassScope) scope;
+ 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 { */
+ findFields(token, enclosingType, classScope, fieldsFound, staticsOnly);
+ findMethods(token, null, enclosingType, classScope, methodsFound, staticsOnly, false);
+ staticsOnly |= enclosingType.isStatic();
+// }
+ break;
+ case Scope.COMPILATION_UNIT_SCOPE :
+ break done;
+ }
+ scope = scope.parent;
+ }
+}
+public AssistParser getParser(){
+ return parser;
+}
+private boolean mustQualifyType(char[][] packageName, char[] readableTypeName) {
+ // If there are no types defined into the current CU yet.
+ if (unitScope == null)
+ return true;
+ if (CharOperation.equals(unitScope.fPackage.compoundName, packageName))
+ return false;
+
+ ImportBinding[] imports = unitScope.imports;
+ for (int i = 0, length = imports.length; i < length; i++) {
+ if (imports[i].onDemand) {
+ if (CharOperation.equals(imports[i].compoundName, packageName))
+ return false; // how do you match p1.p2.A.* ?
+ } else if (CharOperation.equals(imports[i].readableName(), readableTypeName)) {
+ return false;
+ }
+ }
+ return true;
+}
+protected void reset() {
+ super.reset();
+ this.knownPkgs = new HashtableOfObject(10);
+}
+private void setSourceRange(int start, int end) {
+ this.startPosition = start;
+ this.endPosition = end + 1; // Add 1 for now
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java b/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java
index 46432c4..7351fac 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java
@@ -1,51 +1,50 @@
-package org.eclipse.jdt.internal.codeassist;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.codeassist.*;
-
-/**
- * This is the internal requestor passed to the searchable name environment
- * so as to process the multiple search results as they are discovered.
- *
- * It is used to allow the code assist engine to add some more information
- * to the raw name environment results before answering them to the UI.
- */
-public interface ISearchRequestor {
-/**
- * One result of the search consists of a new class.
- *
- * NOTE - All package and type names are presented in their readable form:
- * Package names are in the form "a.b.c".
- * Nested type names are in the qualified form "A.M".
- * The default package is represented by an empty array.
- */
-public void acceptClass(char[] packageName, char[] typeName, int modifiers);
-/**
- * One result of the search consists of a new interface.
- *
- * NOTE - All package and type names are presented in their readable form:
- * Package names are in the form "a.b.c".
- * Nested type names are in the qualified form "A.I".
- * The default package is represented by an empty array.
- */
-public void acceptInterface(char[] packageName, char[] typeName, int modifiers);
-/**
- * One result of the search consists of a new package.
- *
- * NOTE - All package names are presented in their readable form:
- * Package names are in the form "a.b.c".
- * The default package is represented by an empty array.
- */
-public void acceptPackage(char[] packageName);
-/**
- * One result of the search consists of a new type.
- *
- * NOTE - All package and type names are presented in their readable form:
- * Package names are in the form "a.b.c".
- * Nested type names are in the qualified form "A.M".
- * The default package is represented by an empty array.
- */
-public void acceptType(char[] packageName, char[] typeName);
-}
+package org.eclipse.jdt.internal.codeassist;
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+/**
+ * This is the internal requestor passed to the searchable name environment
+ * so as to process the multiple search results as they are discovered.
+ *
+ * It is used to allow the code assist engine to add some more information
+ * to the raw name environment results before answering them to the UI.
+ */
+public interface ISearchRequestor {
+/**
+ * One result of the search consists of a new class.
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * Nested type names are in the qualified form "A.M".
+ * The default package is represented by an empty array.
+ */
+public void acceptClass(char[] packageName, char[] typeName, int modifiers);
+/**
+ * One result of the search consists of a new interface.
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * Nested type names are in the qualified form "A.I".
+ * The default package is represented by an empty array.
+ */
+public void acceptInterface(char[] packageName, char[] typeName, int modifiers);
+/**
+ * One result of the search consists of a new package.
+ *
+ * NOTE - All package names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * The default package is represented by an empty array.
+ */
+public void acceptPackage(char[] packageName);
+/**
+ * One result of the search consists of a new type.
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * Nested type names are in the qualified form "A.M".
+ * The default package is represented by an empty array.
+ */
+public void acceptType(char[] packageName, char[] typeName);
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeFound.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeFound.java
index f83e65c..dcb2bd7 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeFound.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeFound.java
@@ -1,28 +1,26 @@
-package org.eclipse.jdt.internal.codeassist.complete;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.env.*;
-
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class CompletionNodeFound extends RuntimeException {
- public AstNode astNode;
- public Binding qualifiedBinding;
- public Scope scope;
-public CompletionNodeFound() {
- this(null, null, null); // we found a problem in the completion node
-}
-public CompletionNodeFound(AstNode astNode, Binding qualifiedBinding, Scope scope) {
- this.astNode = astNode;
- this.qualifiedBinding = qualifiedBinding;
- this.scope = scope;
-}
-public CompletionNodeFound(AstNode astNode, Scope scope) {
- this(astNode, null, scope);
-}
-}
+package org.eclipse.jdt.internal.codeassist.complete;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class CompletionNodeFound extends RuntimeException {
+ public AstNode astNode;
+ public Binding qualifiedBinding;
+ public Scope scope;
+public CompletionNodeFound() {
+ this(null, null, null); // we found a problem in the completion node
+}
+public CompletionNodeFound(AstNode astNode, Binding qualifiedBinding, Scope scope) {
+ this.astNode = astNode;
+ this.qualifiedBinding = qualifiedBinding;
+ this.scope = scope;
+}
+public CompletionNodeFound(AstNode astNode, Scope scope) {
+ this(astNode, null, scope);
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java
index 6b14d5a..8b7a785 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java
@@ -1,41 +1,40 @@
-package org.eclipse.jdt.internal.codeassist.complete;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
-
-/*
- * Completion node build by the parser in any case it was intending to
- * reduce an exception type reference containing the completion identifier.
- * e.g.
- *
- * class X {
- * void foo() {
- * try {
- * bar();
- * } catch (IOExc[cursor] e) {
- * }
- * }
- * }
- *
- * ---> class X {
- * void foo() {
- * try {
- * bar();
- * } catch (<CompleteOnException:IOExc> e) {
- * }
- * }
- * }
- *
- * The source range of the completion node denotes the source range
- * which should be replaced by the completion.
- */
-public class CompletionOnExceptionReference extends CompletionOnSingleTypeReference {
-public CompletionOnExceptionReference(char[] source, long pos) {
- super(source, pos);
-}
-public String toStringExpression(int tab) {
- return "<CompleteOnException:"/*nonNLS*/ + new String(token) + ">"/*nonNLS*/;
-}
-}
+package org.eclipse.jdt.internal.codeassist.complete;
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an exception type reference containing the completion identifier.
+ * e.g.
+ *
+ * class X {
+ * void foo() {
+ * try {
+ * bar();
+ * } catch (IOExc[cursor] e) {
+ * }
+ * }
+ * }
+ *
+ * ---> class X {
+ * void foo() {
+ * try {
+ * bar();
+ * } catch (<CompleteOnException:IOExc> e) {
+ * }
+ * }
+ * }
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+public class CompletionOnExceptionReference extends CompletionOnSingleTypeReference {
+public CompletionOnExceptionReference(char[] source, long pos) {
+ super(source, pos);
+}
+public String toStringExpression(int tab) {
+ return "<CompleteOnException:"/*nonNLS*/ + new String(token) + ">"/*nonNLS*/;
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java
index 4d02d45..aa522e5 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java
@@ -1,50 +1,49 @@
-package org.eclipse.jdt.internal.codeassist.complete;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
-
-/*
- * Completion node build by the parser in any case it was intending to
- * reduce an exception type reference containing the completion identifier
- * as part of a qualified name.
- * e.g.
- *
- * class X {
- * void foo() {
- * try {
- * bar();
- * } catch (java.io.IOExc[cursor] e) {
- * }
- * }
- * }
- *
- * ---> class X {
- * void foo() {
- * try {
- * bar();
- * } catch (<CompleteOnException:java.io.IOExc> e) {
- * }
- * }
- * }
- *
- * The source range of the completion node denotes the source range
- * which should be replaced by the completion.
- */
-public class CompletionOnQualifiedExceptionReference extends CompletionOnQualifiedTypeReference {
-public CompletionOnQualifiedExceptionReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
- super(previousIdentifiers, completionIdentifier, positions);
-}
-public String toStringExpression(int tab) {
-
- StringBuffer buffer = new StringBuffer();
- buffer. append("<CompleteOnException:"/*nonNLS*/);
- for (int i = 0; i < tokens.length; i++) {
- buffer.append(tokens[i]);
- buffer.append("."/*nonNLS*/);
- }
- buffer.append(completionIdentifier).append(">"/*nonNLS*/);
- return buffer.toString();
-}
-}
+package org.eclipse.jdt.internal.codeassist.complete;
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an exception type reference containing the completion identifier
+ * as part of a qualified name.
+ * e.g.
+ *
+ * class X {
+ * void foo() {
+ * try {
+ * bar();
+ * } catch (java.io.IOExc[cursor] e) {
+ * }
+ * }
+ * }
+ *
+ * ---> class X {
+ * void foo() {
+ * try {
+ * bar();
+ * } catch (<CompleteOnException:java.io.IOExc> e) {
+ * }
+ * }
+ * }
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+public class CompletionOnQualifiedExceptionReference extends CompletionOnQualifiedTypeReference {
+public CompletionOnQualifiedExceptionReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
+ super(previousIdentifiers, completionIdentifier, positions);
+}
+public String toStringExpression(int tab) {
+
+ StringBuffer buffer = new StringBuffer();
+ buffer. append("<CompleteOnException:"/*nonNLS*/);
+ for (int i = 0; i < tokens.length; i++) {
+ buffer.append(tokens[i]);
+ buffer.append("."/*nonNLS*/);
+ }
+ buffer.append(completionIdentifier).append(">"/*nonNLS*/);
+ return buffer.toString();
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
index 62a3b91..768e766 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
@@ -1,1106 +1,1097 @@
-package org.eclipse.jdt.internal.codeassist.complete;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-/*
- * Parser able to build specific completion parse nodes, given a cursorLocation.
- *
- * Cursor location denotes the position of the last character behind which completion
- * got requested:
- * -1 means completion at the very beginning of the source
- * 0 means completion behind the first character
- * n means completion behind the n-th character
- */
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.env.*;
-
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.parser.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.codeassist.impl.*;
-
-public class CompletionParser extends AssistParser {
-
- /* public fields */
-
- public int cursorLocation;
- public char[][] labels; // the visible labels up to the cursor location
-
-
- /* the following fields are internal flags */
-
- boolean betweenNewAndLeftBraket; // whether we are between the keyword 'new' and the following left braket, ie. '[', '(' or '{'
- boolean betweenCatchAndRightParen; // whether we are between the keyword 'catch' and the following ')'
- boolean completionBehindDot; // true when completion identifier immediately follows a dot
-
- // the stacks of types and qualifiers for invocations (ie. method invocations, allocation expressions and
- // explicit constructor invocations). They use the same stack pointer as the selector stack (ie. invocationPtr)
- // the invocation type stack contains one of the invocation type constants below
- // the qualifier stack contains pointers to the expression stack or -1 if there is no qualifier
- // (a qualifier is the expression that qualifies a 'new', a 'super' constructor or a 'this' constructor
- // or it is the receiver of a message send)
- int[] invocationTypeStack = new int[StackIncrement];
- int[] qualifierStack = new int[StackIncrement];
-
- // invocation type constants
- static final int EXPLICIT_RECEIVER = 0;
- static final int NO_RECEIVER = -1;
- static final int SUPER_RECEIVER = -2;
- static final int NAME_RECEIVER = -3;
- static final int ALLOCATION = -4;
- static final int QUALIFIED_ALLOCATION = -5;
-
- // the type of the current invocation (one of the invocation type constants)
- int invocationType;
-
- // a pointer in the expression stack to the qualifier of a invocation
- int qualifier;
-
- // a stack of label counters
- // a new counter is pushed on the stack each time when a method (or a constructor) is entered,
- // it is poped when the method (or constructor) is exited,
- // it is incremented when a new label is defined
- int labelCounterPtr;
- int[] labelCounterStack = new int[StackIncrement];
-
- // a stack of invocationPtr: contains the first invocationPtr of a block
- // the current invocationPtr+1 is pushed when a block is entered
- // it is poped when a block is exited
- int blockInvocationPtr;
- int[] blockInvocationStack = new int[StackIncrement];
-public CompletionParser(ProblemReporter problemReporter) {
- super(problemReporter);
-}
-public char[] assistIdentifier(){
- return ((CompletionScanner)scanner).completionIdentifier;
-}
-protected void attachOrphanCompletionNode(){
- if (this.isOrphanCompletionNode) {
- AstNode orphan = this.assistNode;
- this.isOrphanCompletionNode = false;
-
- /* if in context of a type, then persists the identifier into a fake field return type */
- if (currentElement instanceof RecoveredType){
- RecoveredType recoveredType = (RecoveredType)currentElement;
- /* filter out cases where scanner is still inside type header */
- if (recoveredType.foundOpeningBrace) {
- /* generate a pseudo field with a completion on type reference */
- if (orphan instanceof TypeReference){
- currentElement = currentElement.add(
- new CompletionOnFieldType((TypeReference)orphan), 0);
- return;
- }
- }
- }
- /* if in context of a method, persists if inside arguments as a type */
- if (currentElement instanceof RecoveredMethod){
- RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
- /* only consider if inside method header */
- if (!recoveredMethod.foundOpeningBrace) {
- //if (rParenPos < lParenPos){ // inside arguments
- if (orphan instanceof TypeReference){
- currentElement = currentElement.parent.add(
- new CompletionOnFieldType((TypeReference)orphan), 0);
- return;
- }
- }
- }
-
- // add the completion node to the method declaration or constructor declaration
- if (orphan instanceof Statement) {
- /* check for completion at the beginning of method body
- behind an invalid signature
- */
- RecoveredMethod method = currentElement.enclosingMethod();
- if (method != null){
- AbstractMethodDeclaration methodDecl = method.methodDeclaration;
- if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
- && (scanner.searchLineNumber(orphan.sourceStart) == scanner.searchLineNumber(methodDecl.sourceEnd))){
- return;
- }
- }
- // add the completion node as a statement to the list of block statements
- currentElement = currentElement.add((Statement)orphan, 0);
- return;
- }
- }
-
- // the following code applies only in methods, constructors or initializers
- if ((!this.inMethodStack[this.inMethodPtr] && !this.inInitializerStack[this.inInitializerPtr])) {
- return;
- }
-
- // push top expression on ast stack if it contains the completion node
- Expression expression;
- if (this.expressionPtr > -1 && containsCompletionNode(expression = this.expressionStack[this.expressionPtr])) {
- /* check for completion at the beginning of method body
- behind an invalid signature
- */
- RecoveredMethod method = currentElement.enclosingMethod();
- if (method != null){
- AbstractMethodDeclaration methodDecl = method.methodDeclaration;
- if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
- && (scanner.searchLineNumber(expression.sourceStart) == scanner.searchLineNumber(methodDecl.sourceEnd))){
- return;
- }
- }
- if (expression instanceof AllocationExpression) {
- // keep the context if it is an allocation expression
- Statement statement = (Statement)wrapWithExplicitConstructorCallIfNeeded(expression);
- currentElement = currentElement.add(statement, 0);
- } else {
- Statement statement = (Statement)wrapWithExplicitConstructorCallIfNeeded(this.assistNode);
- currentElement = currentElement.add(statement, 0);
- }
- }
-}
-public int bodyEnd(AbstractMethodDeclaration method){
- return cursorLocation;
-}
-public int bodyEnd(Initializer initializer){
- return cursorLocation;
-}
-/**
- * Checks if the completion is on the exception type of a catch clause.
- * Returns whether we found a completion node.
- */
-private boolean checkCatchClause() {
- if (this.betweenCatchAndRightParen && this.identifierPtr > -1) {
- // NB: if the cursor is on the variable, then it has been reduced (so identifierPtr is -1),
- // thus this can only be a completion on the type of the catch clause
- this.assistNode = getTypeReference(0);
- this.lastCheckPoint = this.assistNode.sourceEnd + 1;
- this.isOrphanCompletionNode = true;
- return true;
- }
- return false;
-}
-/**
- * Checks if the completion is on the type following a 'new'.
- * Returns whether we found a completion node.
- */
-private boolean checkClassInstanceCreation() {
- if (this.betweenNewAndLeftBraket) {
- // completion on type inside an allocation expression
- TypeReference type = getTypeReference(0);
- this.assistNode = type;
- this.lastCheckPoint = type.sourceEnd + 1;
- if (this.invocationType == ALLOCATION) {
- // non qualified allocation expression: attach it later
- this.isOrphanCompletionNode = true;
- } else {
- // qualified allocation expression
- QualifiedAllocationExpression allocExpr = new QualifiedAllocationExpression();
- allocExpr.type = type;
- allocExpr.enclosingInstance = this.expressionStack[this.qualifier];
- allocExpr.sourceStart = this.intStack[this.intPtr--];
- allocExpr.sourceEnd = type.sourceEnd;
- this.expressionStack[this.qualifier] = allocExpr; // attach it now (it replaces the qualifier expression)
- this.isOrphanCompletionNode = false;
- }
- return true;
- }
- return false;
-}
-/**
- * Checks if the completion is on the dot following an array type,
- * a primitive type or an primitive array type.
- * Returns whether we found a completion node.
- */
-private boolean checkClassLiteralAccess() {
- if (this.identifierLengthPtr >= 1 && this.previousToken == TokenNameDOT) { // (NB: the top id length is 1 and it is for the completion identifier)
- int length;
- // if the penultimate id length is negative,
- // the completion is after a primitive type or a primitive array type
- if ((length = this.identifierLengthStack[this.identifierLengthPtr-1]) < 0) {
- // build the primitive type node
- int dim = this.isAfterArrayType() ? this.intStack[this.intPtr--] : 0;
- SingleTypeReference typeRef = (SingleTypeReference)TypeReference.baseTypeReference(-length, dim);
- typeRef.sourceStart = this.intStack[this.intPtr--];
- //typeRef.sourceEnd = typeRef.sourceStart + typeRef.token.length; // NB: It's ok to use the length of the token since it doesn't contain any unicode
-
- // find the completion identifier and its source positions
- char[] source = identifierStack[identifierPtr];
- long pos = this.identifierPositionStack[this.identifierPtr--];
- this.identifierLengthPtr--; // it can only be a simple identifier (so its length is one)
-
- // build the completion on class literal access node
- CompletionOnClassLiteralAccess access = new CompletionOnClassLiteralAccess(pos, typeRef);
- access.completionIdentifier = source;
- this.identifierLengthPtr--; // pop the length that was used to say it is a primitive type
- this.assistNode = access;
- this.isOrphanCompletionNode = true;
- return true;
- }
-
- // if the completion is after a regular array type
- if (isAfterArrayType()) {
- // find the completion identifier and its source positions
- char[] source = identifierStack[identifierPtr];
- long pos = this.identifierPositionStack[this.identifierPtr--];
- this.identifierLengthPtr--; // it can only be a simple identifier (so its length is one)
-
- // get the type reference
- TypeReference typeRef = getTypeReference(this.intPtr--);
-
- // build the completion on class literal access node
- CompletionOnClassLiteralAccess access = new CompletionOnClassLiteralAccess(pos, typeRef);
- access.completionIdentifier = source;
- this.assistNode = access;
- this.isOrphanCompletionNode = true;
- return true;
- }
-
- }
- return false;
-}
-/**
- * Checks if the completion is inside a method invocation or a constructor invocation.
- * Returns whether we found a completion node.
- */
-private boolean checkInvocation() {
- Expression topExpression = this.expressionPtr >= 0 ?
- this.expressionStack[this.expressionPtr] :
- null;
- boolean isEmptyNameCompletion = false;
- boolean isEmptyAssistIdentifier = false;
- int startInvocationPtr = this.blockInvocationPtr >= 0 ? this.blockInvocationStack[this.blockInvocationPtr] : 0;
- if (this.invocationPtr >= startInvocationPtr
- && ((isEmptyNameCompletion = topExpression == this.assistNode && this.isEmptyNameCompletion()) // eg. it is something like "this.fred([cursor]" but it is not something like "this.fred(1 + [cursor]"
- || (isEmptyAssistIdentifier = this.indexOfAssistIdentifier() >= 0 && this.identifierStack[this.identifierPtr].length == 0))) { // eg. it is something like "this.fred(1 [cursor]"
-
- // pop empty name completion
- if (isEmptyNameCompletion) {
- this.expressionPtr--;
- this.expressionLengthStack[this.expressionLengthPtr]--;
- } else if (isEmptyAssistIdentifier) {
- this.identifierPtr--;
- this.identifierLengthPtr--;
- }
-
- // find receiver and qualifier
- int invocationType = this.invocationTypeStack[this.invocationPtr];
- int qualifierExprPtr = this.qualifierStack[this.invocationPtr];
-
- // find arguments
- int numArgs = this.expressionPtr - qualifierExprPtr;
- int argStart = qualifierExprPtr + 1;
- Expression[] arguments = null;
- if (numArgs > 0) {
- // remember the arguments
- arguments = new Expression[numArgs];
- System.arraycopy(this.expressionStack, argStart, arguments, 0, numArgs);
-
- // consume the expression arguments
- this.expressionPtr -= numArgs;
- int count = numArgs;
- while (count > 0) {
- count -= this.expressionLengthStack[this.expressionLengthPtr--];
- }
- }
-
- // build ast node
- if (invocationType != ALLOCATION && invocationType != QUALIFIED_ALLOCATION) {
- // creates completion on message send
- CompletionOnMessageSend messageSend = new CompletionOnMessageSend();
- messageSend.arguments = arguments;
- switch (invocationType) {
- case NO_RECEIVER:
- // implicit this
- messageSend.receiver = ThisReference.ThisImplicit;
- break;
- case NAME_RECEIVER:
- // remove selector
- this.identifierPtr--;
- this.identifierLengthStack[this.identifierLengthPtr]--;
- // consume the receiver
- messageSend.receiver = this.getUnspecifiedReference();
- break;
- case SUPER_RECEIVER:
- messageSend.receiver = SuperReference.Super;
- break;
- case EXPLICIT_RECEIVER:
- messageSend.receiver = this.expressionStack[qualifierExprPtr];
- }
-
- // set selector
- messageSend.selector = this.identifierStack[this.selectorStack[this.invocationPtr]];
- // remove selector
- if (this.identifierLengthPtr >=0 && this.identifierLengthStack[this.identifierLengthPtr] == 1) {
- this.identifierPtr--;
- this.identifierLengthPtr--;
- }
-
- // no source is going to be replaced
- messageSend.sourceStart = this.cursorLocation + 1;
- messageSend.sourceEnd = this.cursorLocation;
-
- // remember the message send as an orphan completion node
- this.assistNode = messageSend;
- this.lastCheckPoint = messageSend.sourceEnd + 1;
- this.isOrphanCompletionNode = true;
- return true;
- } else {
- int selectorPtr = this.selectorStack[this.invocationPtr];
- if (selectorPtr == THIS_CONSTRUCTOR || selectorPtr == SUPER_CONSTRUCTOR) {
- // creates an explicit constructor call
- CompletionOnExplicitConstructorCall call = new CompletionOnExplicitConstructorCall(
- (selectorPtr == THIS_CONSTRUCTOR) ? ExplicitConstructorCall.This : ExplicitConstructorCall.Super);
- call.arguments = arguments;
- if (invocationType == QUALIFIED_ALLOCATION) {
- call.qualification = this.expressionStack[qualifierExprPtr];
- }
-
- // no source is going to be replaced
- call.sourceStart = this.cursorLocation + 1;
- call.sourceEnd = this.cursorLocation;
-
- // remember the explicit constructor call as an orphan completion node
- this.assistNode = call;
- this.lastCheckPoint = call.sourceEnd + 1;
- this.isOrphanCompletionNode = true;
- return true;
- } else {
- // creates an allocation expression
- CompletionOnQualifiedAllocationExpression allocExpr = new CompletionOnQualifiedAllocationExpression();
- allocExpr.arguments = arguments;
- allocExpr.type = super.getTypeReference(0); // we don't want a completion node here, so call super
- if (invocationType == QUALIFIED_ALLOCATION) {
- allocExpr.enclosingInstance = this.expressionStack[qualifierExprPtr];
- }
- // no source is going to be replaced
- allocExpr.sourceStart = this.cursorLocation + 1;
- allocExpr.sourceEnd = this.cursorLocation;
-
- // remember the allocation expression as an orphan completion node
- this.assistNode = allocExpr;
- this.lastCheckPoint = allocExpr.sourceEnd + 1;
- this.isOrphanCompletionNode = true;
- return true;
- }
- }
- }
- return false;
-}
-/**
- * Checks if the completion is on a member access (ie. in an identifier following a dot).
- * Returns whether we found a completion node.
- */
-private boolean checkMemberAccess() {
- if (this.previousToken == TokenNameDOT && this.qualifier > -1 && this.expressionPtr == this.qualifier) {
- // the receiver is an expression
- pushCompletionOnMemberAccessOnExpressionStack(false);
- return true;
- }
- return false;
-}
-/**
- * Checks if the completion is on a name reference.
- * Returns whether we found a completion node.
- */
-private boolean checkNameCompletion() {
- /*
- We didn't find any other completion, but the completion identifier is on the identifier stack,
- so it can only be a completion on name.
- Note that we allow the completion on a name even if nothing is expected (eg. foo() b[cursor] would
- be a completion on 'b'). This policy gives more to the user than he/she would expect, but this
- simplifies the problem. To fix this, the recovery must be changed to work at a 'statement' granularity
- instead of at the 'expression' granularity as it does right now.
- */
-
- // NB: at this point the completion identifier is on the identifier stack
- this.assistNode = getUnspecifiedReferenceOptimized();
- this.lastCheckPoint = this.assistNode.sourceEnd + 1;
- this.isOrphanCompletionNode = true;
- return true;
-}
-/**
- * Checks if the completion is in the context of a method and on the type of one of its arguments
- * Returns whether we found a completion node.
- */
-private boolean checkRecoveredMethod() {
- if (currentElement instanceof RecoveredMethod){
- /* check if current awaiting identifier is the completion identifier */
- if (this.indexOfAssistIdentifier() < 0) return false;
-
- /* check if on line with an error already - to avoid completing inside
- illegal type names e.g. int[<cursor> */
- if (lastErrorEndPosition <= cursorLocation+1
- && scanner.searchLineNumber(lastErrorEndPosition)
- == scanner.searchLineNumber(((CompletionScanner)scanner).completedIdentifierStart)){
- return false;
- }
- RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
- /* only consider if inside method header */
- if (!recoveredMethod.foundOpeningBrace
- && lastIgnoredToken == -1) {
- //if (rParenPos < lParenPos){ // inside arguments
- this.assistNode = this.getTypeReference(0);
- this.lastCheckPoint = this.assistNode.sourceEnd + 1;
- this.isOrphanCompletionNode = true;
- return true;
- }
- }
- return false;
-}
-/**
- * Checks if the completion is in the context of a type and on a type reference in this type.
- * Persists the identifier into a fake field return type
- * Returns whether we found a completion node.
- */
-private boolean checkRecoveredType() {
- if (currentElement instanceof RecoveredType){
- /* check if current awaiting identifier is the completion identifier */
- if (this.indexOfAssistIdentifier() < 0) return false;
-
- /* check if on line with an error already - to avoid completing inside
- illegal type names e.g. int[<cursor> */
- if ((lastErrorEndPosition <= cursorLocation+1)
- && scanner.searchLineNumber(lastErrorEndPosition)
- == scanner.searchLineNumber(((CompletionScanner)scanner).completedIdentifierStart)){
- return false;
- }
- RecoveredType recoveredType = (RecoveredType)currentElement;
- /* filter out cases where scanner is still inside type header */
- if (recoveredType.foundOpeningBrace) {
- this.assistNode = this.getTypeReference(0);
- this.lastCheckPoint = this.assistNode.sourceEnd + 1;
- this.isOrphanCompletionNode = true;
- return true;
- }
- }
- return false;
-}
-/*
- * Check whether about to shift beyond the completion token.
- * If so, depending on the context, a special node might need to be created
- * and attached to the existing recovered structure so as to be remember in the
- * resulting parsed structure.
- */
-public void completionIdentifierCheck(){
-
- if (checkRecoveredType()) return;
- if (checkRecoveredMethod()) return;
-
- // if not in a method in non diet mode and if not inside a field initializer, only record references attached to types
- if (!(this.inMethodStack[this.inMethodPtr] && !this.diet)
- && !insideFieldInitializer()) return;
-
- /*
- In some cases, the completion identifier may not have yet been consumed,
- e.g. int.[cursor]
- This is because the grammar does not allow any (empty) identifier to follow
- a base type. We thus have to manually force the identifier to be consumed
- (i.e. pushed).
- */
- if (assistIdentifier() == null && this.currentToken == TokenNameIdentifier) { // Test below copied from CompletionScanner.getCurrentIdentifierSource()
- if (cursorLocation < this.scanner.startPosition && this.scanner.currentPosition == this.scanner.startPosition){ // fake empty identifier got issued
- this.pushIdentifier();
- } else if (cursorLocation+1 >= this.scanner.startPosition && cursorLocation < this.scanner.currentPosition){
- this.pushIdentifier();
- }
- }
-
- // check for different scenarii
- try {
- // no need to go further if we found a non empty completion node
- // (we still need to store labels though)
- if (this.assistNode != null) {
- // however inside an invocation, the completion identifier may already have been consumed into an empty name
- // completion, so this check should be before we check that we are at the cursor location
- if (!isEmptyNameCompletion() || checkInvocation()) return;
- }
-
- // no need to check further if we are not at the cursor location
- if (this.indexOfAssistIdentifier() < 0) return;
-
- if (checkClassInstanceCreation()) return;
- if (checkCatchClause()) return;
- if (checkMemberAccess()) return;
- if (checkClassLiteralAccess()) return;
-
- // if the completion was not on an empty name, it can still be inside an invocation (eg. this.fred("abc"[cursor])
- // (NB: Put this check before checkNameCompletion() because the selector of the invocation can be on the identifier stack)
- if (checkInvocation()) return;
-
- if (checkNameCompletion()) return;
- } finally {
- storeLabelsIfNeeded();
- }
-}
-protected void consumeCaseLabel() {
- Expression caseExpression = this.expressionStack[this.expressionPtr];
- if (caseExpression instanceof SingleNameReference || caseExpression instanceof QualifiedNameReference) {
- // label counter was wrongly incremented in consumeToken
- if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]--;
- }
- super.consumeCaseLabel();
-}
-protected void consumeConditionalExpression(int op) {
- Expression valueIfTrue = this.expressionStack[this.expressionPtr - 1];
- if (valueIfTrue instanceof SingleNameReference || valueIfTrue instanceof QualifiedNameReference) {
- // label counter was wrongly incremented in consumeToken
- if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]--;
- }
- super.consumeConditionalExpression(op);
-}
-protected void consumeConstructorBody() {
- super.consumeConstructorBody();
- this.labelCounterPtr--;
-}
-protected void consumeConstructorHeaderName() {
-
- int index;
-
- /* no need to take action if not inside assist identifiers */
- if ((index = indexOfAssistIdentifier()) < 0) {
- super.consumeConstructorHeaderName();
- return;
- }
-
- /* force to start recovering in order to get fake field behavior */
- if (currentElement == null){
- this.hasReportedError = true; // do not report any error
- }
- this.restartRecovery = true;
-}
-/*
- * Copy of code from superclass with the following change:
- * If the cursor location is on the field access, then create a
- * CompletionOnMemberAccess instead.
- */
-protected void consumeFieldAccess(boolean isSuperAccess) {
- // FieldAccess ::= Primary '.' 'Identifier'
- // FieldAccess ::= 'super' '.' 'Identifier'
-
- // potential receiver is being poped, so reset potential receiver
- this.invocationType = NO_RECEIVER;
-
- if (this.indexOfAssistIdentifier() < 0) {
- super.consumeFieldAccess(isSuperAccess);
- } else {
- this.pushCompletionOnMemberAccessOnExpressionStack(isSuperAccess);
- }
-}
-protected void consumeMethodBody() {
- super.consumeMethodBody();
- this.labelCounterPtr--;
-}
-protected void consumeNestedMethod() {
- super.consumeNestedMethod();
- this.pushNewLabelCounter();
-}
-protected void consumeStatementLabel() {
- super.consumeStatementLabel();
- if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]--;
-}
-protected void consumeToken(int token) {
- int previous = this.previousToken;
- int previousIdentifierPtr = this.previousIdentifierPtr;
- super.consumeToken(token);
-
- // if in field initializer (directly or not), on the completion identifier and not in recovery mode yet
- // then position end of file at cursor location (so that we have the same behavior as
- // in method bodies)
- if (token == TokenNameIdentifier
- && this.identifierStack[this.identifierPtr] == assistIdentifier()
- && this.currentElement == null
- && this.insideFieldInitializer()) {
- this.scanner.eofPosition = cursorLocation+1;
- }
-
- // if in a method or if in a field initializer
- if (this.inMethodStack[this.inMethodPtr] || this.inInitializerStack[this.inInitializerPtr]) {
- switch (token) {
- case TokenNameDOT:
- switch (previous) {
- case TokenNamethis: // eg. this[.]fred()
- this.invocationType = EXPLICIT_RECEIVER;
- break;
- case TokenNamesuper: // eg. super[.]fred()
- this.invocationType = SUPER_RECEIVER;
- break;
- case TokenNameIdentifier: // eg. bar[.]fred()
- if (!this.betweenNewAndLeftBraket) { // eg. not new z.y[.]X()
- if (this.identifierPtr != previousIdentifierPtr) { // if identifier has been consumed, eg. this.x[.]fred()
- this.invocationType = EXPLICIT_RECEIVER;
- } else {
- this.invocationType = NAME_RECEIVER;
- }
- }
- break;
- }
- break;
- case TokenNameIdentifier:
- if (previous == TokenNameDOT) { // eg. foo().[fred]()
- // if current identifier is the empty completion one
- if (identifierStack[identifierPtr] == CompletionScanner.EmptyCompletionIdentifier){
- this.completionBehindDot = true;
- }
- if (this.invocationType != SUPER_RECEIVER // eg. not super.[fred]()
- && this.invocationType != NAME_RECEIVER // eg. not bar.[fred]()
- && this.invocationType != ALLOCATION // eg. not new foo.[Bar]()
- && this.invocationType != QUALIFIED_ALLOCATION) { // eg. not fred().new foo.[Bar]()
-
- this.invocationType = EXPLICIT_RECEIVER;
- this.qualifier = this.expressionPtr;
- }
- }
- break;
- case TokenNamenew:
- this.betweenNewAndLeftBraket = true;
- this.qualifier = this.expressionPtr; // NB: even if there is no qualification, set it to the expression ptr so that the number of arguments are correctly computed
- if (previous == TokenNameDOT) { // eg. fred().[new] X()
- this.invocationType = QUALIFIED_ALLOCATION;
- } else { // eg. [new] X()
- this.invocationType = ALLOCATION;
- }
- break;
- case TokenNamethis:
- if (previous == TokenNameDOT) { // eg. fred().[this]()
- this.invocationType = QUALIFIED_ALLOCATION;
- this.qualifier = this.expressionPtr;
- }
- break;
- case TokenNamesuper:
- if (previous == TokenNameDOT) { // eg. fred().[super]()
- this.invocationType = QUALIFIED_ALLOCATION;
- this.qualifier = this.expressionPtr;
- }
- break;
- case TokenNamecatch:
- this.betweenCatchAndRightParen = true;
- break;
- case TokenNameLPAREN:
- this.betweenNewAndLeftBraket = false;
- if (this.invocationType == NO_RECEIVER || this.invocationType == NAME_RECEIVER) {
- this.qualifier = this.expressionPtr; // remenber the last expression so that arguments are correctly computed
- }
- switch (previous) {
- case TokenNameIdentifier: // eg. fred[(]) or foo.fred[(])
- this.pushOnInvocationStacks(this.invocationType, this.qualifier);
- this.invocationType = NO_RECEIVER;
- break;
- case TokenNamethis: // explicit constructor invocation, eg. this[(]1, 2)
- this.pushOnInvocationStacks(
- (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION,
- this.qualifier);
- this.invocationType = NO_RECEIVER;
- break;
- case TokenNamesuper: // explicit constructor invocation, eg. super[(]1, 2)
- this.pushOnInvocationStacks(
- (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION,
- this.qualifier);
- this.invocationType = NO_RECEIVER;
- break;
- }
- break;
- case TokenNameLBRACE:
- this.betweenNewAndLeftBraket = false;
- this.pushBlockInvocationPtr();
- break;
- case TokenNameLBRACKET:
- this.betweenNewAndLeftBraket = false;
- break;
- case TokenNameRBRACE:
- if (this.blockInvocationPtr >= 0) this.blockInvocationPtr--;
- break;
- case TokenNameRPAREN:
- this.betweenCatchAndRightParen = false;
- break;
- case TokenNameCOLON:
- if (previous == TokenNameIdentifier) {
- if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]++;
- }
- break;
- }
- }
-}
-/**
- * Return whether the given ast node contains the completion node.
- */
-private boolean containsCompletionNode(AstNode ast) {
- if (this.assistNode == null || ast instanceof Literal) {
- return false;
- }
- if (this.assistNode == ast) {
- return true;
- }
- if (ast instanceof Reference || ast instanceof TypeReference) {
- return ast == this.assistNode;
- }
- if (ast instanceof Assignment) {
- Assignment assign = (Assignment)ast;
- return containsCompletionNode(assign.lhs) || containsCompletionNode(assign.expression);
- }
- if (ast instanceof UnaryExpression) {
- UnaryExpression unary = (UnaryExpression)ast;
- return containsCompletionNode(unary.expression);
- }
- if (ast instanceof BinaryExpression) {
- BinaryExpression binary = (BinaryExpression)ast;
- return containsCompletionNode(binary.left) || containsCompletionNode(binary.right);
- }
- if (ast instanceof InstanceOfExpression) {
- InstanceOfExpression instanceOfExpr = (InstanceOfExpression)ast;
- return containsCompletionNode(instanceOfExpr.expression) || containsCompletionNode(instanceOfExpr.type);
- }
- if (ast instanceof ConditionalExpression) {
- ConditionalExpression conditional = (ConditionalExpression)ast;
- return containsCompletionNode(conditional.condition) || containsCompletionNode(conditional.valueIfTrue) || containsCompletionNode(conditional.valueIfFalse);
- }
- if (ast instanceof AllocationExpression) {
- AllocationExpression alloc = (AllocationExpression)ast;
- return containsCompletionNode(alloc.type);
- }
- if (ast instanceof CastExpression) {
- CastExpression cast = (CastExpression)ast;
- return containsCompletionNode(cast.expression) || containsCompletionNode(cast.type);
- }
- if (ast instanceof ExplicitConstructorCall) {
- ExplicitConstructorCall call = (ExplicitConstructorCall)ast;
- Expression[] arguments = call.arguments;
- if (arguments != null) {
- for (int i = 0; i < arguments.length; i++) {
- if (containsCompletionNode(arguments[i])) {
- return true;
- }
- }
- return false;
- }
- }
- return false;
-}
-public ImportReference createAssistImportReference(char[][] tokens, long[] positions){
- return new CompletionOnImportReference(tokens, positions);
-}
-public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){
- return new CompletionOnPackageReference(tokens, positions);
-}
-public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] name, long[] positions){
- return new CompletionOnQualifiedNameReference(
- previousIdentifiers,
- name,
- positions);
-}
-public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] name, long[] positions){
- return this.betweenCatchAndRightParen // check for exception scenario
- ? new CompletionOnQualifiedExceptionReference(
- previousIdentifiers,
- name,
- positions)
- : new CompletionOnQualifiedTypeReference(
- previousIdentifiers,
- name,
- positions);
-}
-public NameReference createSingleAssistNameReference(char[] name, long position) {
- return new CompletionOnSingleNameReference(name, position);
-}
-public TypeReference createSingleAssistTypeReference(char[] name, long position) {
- return this.betweenCatchAndRightParen // check for exception scenario
- ? new CompletionOnExceptionReference(name, position)
- : new CompletionOnSingleTypeReference(name, position);
-}
-public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLocation) {
-
- this.cursorLocation = cursorLocation;
- CompletionScanner completionScanner = (CompletionScanner)this.scanner;
- completionScanner.completionIdentifier = null;
- completionScanner.cursorLocation = cursorLocation;
- return this.dietParse(sourceUnit, compilationResult);
-}
-/*
- * Flush parser/scanner state regarding to code assist
- */
-public void flushAssistState() {
-
- super.flushAssistState();
- this.isOrphanCompletionNode = false;
- this.setAssistIdentifier(null);
- CompletionScanner completionScanner = (CompletionScanner)this.scanner;
- completionScanner.completedIdentifierStart = 0;
- completionScanner.completedIdentifierEnd = -1;
-}
-protected NameReference getUnspecifiedReferenceOptimized() {
- if (this.identifierLengthStack[this.identifierLengthPtr] > 1) { // reducing a qualified name
- // potential receiver is being poped, so reset potential receiver
- this.invocationType = NO_RECEIVER;
- }
- return super.getUnspecifiedReferenceOptimized();
-}
-/**
- * Return whether the given ast node has information interresting for code completion.
- */
-private boolean hasCompletionInformation(AstNode ast) {
- return (
- ast instanceof AbstractMethodDeclaration ||
- ast instanceof AbstractVariableDeclaration ||
- ast instanceof LabeledStatement ||
- ast instanceof TypeDeclaration);
-}
-public void initialize() {
- super.initialize();
- this.initializeForBlockStatements();
- this.labelCounterPtr = -1;
-}
-/*
- * Initializes the state of the parser that is about to go for BlockStatements.
- */
-private void initializeForBlockStatements() {
- this.previousToken = -1;
- this.previousIdentifierPtr = -1;
- this.completionBehindDot = false;
- this.betweenNewAndLeftBraket = false;
- this.betweenCatchAndRightParen = false;
- this.invocationType = NO_RECEIVER;
- this.qualifier = -1;
- this.blockInvocationPtr = -1;
-}
-public void initializeScanner(){
- this.scanner = new CompletionScanner();
-}
-/**
- * Returns whether we are directly or indirectly inside a field initializer.
- */
-private boolean insideFieldInitializer() {
- for (int i = this.inInitializerPtr; i >= 0; i--) {
- if (this.inInitializerStack[i]) {
- return true;
- }
- }
- return false;
-}
-/**
- * Returns whether the completion is just after an array type
- * eg. String[].[cursor]
- */
-private boolean isAfterArrayType() {
- // TBD: The following relies on the fact that array dimensions are small: it says that if the
- // top of the intStack is less than 11, then it must be a dimension
- // (smallest position of array type in a compilation unit is 11 as in "class X{Y[]")
- int dim = 0;
- if ((this.intPtr > -1) && (this.intStack[this.intPtr] < 11)) {
- return true;
- }
- return false;
-}
-private boolean isEmptyNameCompletion() {
- return
- this.assistNode != null &&
- this.assistNode instanceof CompletionOnSingleNameReference &&
- (((CompletionOnSingleNameReference)this.assistNode).token.length == 0);
-}
-public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLocation) {
-
- this.cursorLocation = cursorLocation;
- CompletionScanner completionScanner = (CompletionScanner)this.scanner;
- completionScanner.completionIdentifier = null;
- completionScanner.cursorLocation = cursorLocation;
- return this.parse(sourceUnit, compilationResult);
-}
-/*
- * Prepares the state of the parser to go for BlockStatements.
- */
-protected void prepareForBlockStatements() {
- super.prepareForBlockStatements();
- this.initializeForBlockStatements();
-}
-protected void pushBlockInvocationPtr() {
- try {
- this.blockInvocationStack[++this.blockInvocationPtr] = this.invocationPtr+1;
- } catch (IndexOutOfBoundsException e) {
- int oldStackLength = this.blockInvocationStack.length;
- int[] oldStack = this.labelCounterStack;
- this.blockInvocationStack = new int[oldStackLength + StackIncrement];
- System.arraycopy(oldStack, 0, this.blockInvocationStack, 0, oldStackLength);
- this.blockInvocationStack[this.blockInvocationPtr] = this.invocationPtr+1;
- }
-}
-/**
- * Creates a completion on member access node and push it
- * on the expression stack.
- */
-private void pushCompletionOnMemberAccessOnExpressionStack(boolean isSuperAccess) {
- char[] source = identifierStack[identifierPtr];
- long pos = identifierPositionStack[identifierPtr--];
- CompletionOnMemberAccess fr = new CompletionOnMemberAccess(source, pos);
- this.assistNode = fr;
- this.lastCheckPoint = fr.sourceEnd + 1;
- identifierLengthPtr--;
- if (isSuperAccess) { //considerates the fieldReference beginning at the 'super' ....
- fr.sourceStart = intStack[intPtr--];
- fr.receiver = new SuperReference(fr.sourceStart, endPosition);
- pushOnExpressionStack(fr);
- } else { //optimize push/pop
- if ((fr.receiver = expressionStack[expressionPtr]).isThis()) { //fieldreference begins at the this
- fr.sourceStart = fr.receiver.sourceStart;
- }
- expressionStack[expressionPtr] = fr;
- }
-}
-protected void pushNewLabelCounter() {
- try {
- this.labelCounterStack[++this.labelCounterPtr] = 0;
- } catch (IndexOutOfBoundsException e) {
- int oldStackLength = this.labelCounterStack.length;
- int[] oldStack = this.labelCounterStack;
- this.labelCounterStack = new int[oldStackLength + StackIncrement];
- System.arraycopy(oldStack, 0, this.labelCounterStack, 0, oldStackLength);
- this.labelCounterStack[this.labelCounterPtr] = 0;
- }
-}
-/**
- * Pushes the given invocation type (one of the invocation type constants) on the invocation type stack,
- * and the given qualifier (an expression pointer to the expression stack) on the qualifier stack.
- */
-protected void pushOnInvocationStacks(int invocationType, int qualifierExprPtr) {
- // NB: invocationPtr has already been incremented by a call to pushOnSelectorStack()
- try {
- this.invocationTypeStack[this.invocationPtr] = invocationType;
- this.qualifierStack[this.invocationPtr] = qualifierExprPtr;
- } catch (IndexOutOfBoundsException e) {
- int oldStackLength = this.invocationTypeStack.length;
- int oldInvocationTypeStack[] = this.invocationTypeStack;
- int oldQualifierStack[] = this.qualifierStack;
- this.invocationTypeStack = new int[oldStackLength + StackIncrement];
- this.qualifierStack = new int[oldStackLength + StackIncrement];
- System.arraycopy(oldInvocationTypeStack, 0, this.invocationTypeStack, 0, oldStackLength);
- System.arraycopy(oldQualifierStack, 0, this.qualifierStack, 0, oldStackLength);
- this.invocationTypeStack[this.invocationPtr] = invocationType;
- this.qualifierStack[this.invocationPtr] = qualifierExprPtr;
- }
-}
-public void recordCompletionOnReference(){
-
- if (currentElement instanceof RecoveredType){
- RecoveredType recoveredType = (RecoveredType)currentElement;
-
- /* filter out cases where scanner is still inside type header */
- if (!recoveredType.foundOpeningBrace) return;
-
- /* generate a pseudo field with a completion on type reference */
- currentElement.add(
- new CompletionOnFieldType(this.getTypeReference(0)), 0);
- return;
- }
- if (!diet) return; // only record references attached to types
-
-}
-protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
-
- /* Intercept error state on EOF inside method bodies, due to
- cursor location being used as an EOF position.
- */
- if (!diet && currentToken == TokenNameEOF) return;
- super.reportSyntaxError(act, currentKind, stateStackTop);
-}
-/*
- * Reset internal state after completion is over
- */
-
-public void reset() {
- super.reset();
- this.cursorLocation = 0;
-}
-/*
- * Reset internal state after completion is over
- */
-
-public void resetAfterCompletion() {
- this.cursorLocation = 0;
- this.flushAssistState();
-}
-/*
- * Reset context so as to resume to regular parse loop
- * If unable to reset for resuming, answers false.
- *
- * Move checkpoint location, reset internal stacks and
- * decide which grammar goal is activated.
- */
-protected boolean resumeAfterRecovery() {
-
- if (this.assistNode != null) {
- // if an assist node has been found and a recovered element exists,
- // mark enclosing blocks as to be preserved
- if (this.currentElement != null) {
- currentElement.preserveEnclosingBlocks();
- }
- /* if reached [eof] inside method body, but still inside nested type,
- or inside a field initializer, should continue in diet mode until
- the end of the method body or compilation unit */
- if ((scanner.eofPosition == cursorLocation+1)
- && (!(referenceContext instanceof CompilationUnitDeclaration)
- || insideFieldInitializer())) {
-
- /* disabled since does not handle possible field/message refs, i.e. Obj[ASSIST HERE]ect.registerNatives()
- // consume extra tokens which were part of the qualified reference
- // so that the replaced source comprises them as well
- if (this.assistNode instanceof NameReference){
- int oldEof = scanner.eofPosition;
- scanner.eofPosition = currentElement.topElement().sourceEnd()+1;
- scanner.currentPosition = this.cursorLocation+1;
- int token = -1;
- try {
- do {
- // first token might not have to be a dot
- if (token >= 0 || !this.completionBehindDot){
- if ((token = scanner.getNextToken()) != TokenNameDOT) break;
- }
- if ((token = scanner.getNextToken()) != TokenNameIdentifier) break;
- this.assistNode.sourceEnd = scanner.currentPosition - 1;
- } while (token != TokenNameEOF);
- } catch (InvalidInputException e){
- } finally {
- scanner.eofPosition = oldEof;
- }
- }
- */
- /* restart in diet mode for finding sibling constructs */
- if (currentElement.enclosingType() != null){
- lastCheckPoint = this.assistNode.sourceEnd+1;
- scanner.eofPosition = currentElement.topElement().sourceEnd()+1;
- } else {
- this.resetStacks();
- return false;
- }
- }
- }
- return super.resumeAfterRecovery();
-}
-public void setAssistIdentifier(char[] assistIdent){
- ((CompletionScanner)scanner).completionIdentifier = assistIdent;
-}
-/**
- * Stores the labels left on the identifier stack if they have not been stored yet.
- */
-private void storeLabelsIfNeeded() {
- int counter = this.labelCounterPtr >= 0 ? this.labelCounterStack[this.labelCounterPtr] : 0;
- if (this.labels == null && this.identifierPtr >= 0) {
- this.labels = new char[counter][];
- System.arraycopy(this.identifierStack, this.identifierPtr - counter + 1, this.labels, 0, counter);
- }
- this.identifierPtr -= counter;
- this.identifierLengthPtr -= counter; // labels have not been concatenated yet
-}
-/*
- * Update recovery state based on current parser/scanner state
- */
-protected void updateRecoveryState() {
-
- /* expose parser state to recovery state */
- currentElement.updateFromParserState();
-
- /* may be able to retrieve completionNode as an orphan, and then attach it */
- this.completionIdentifierCheck();
- this.attachOrphanCompletionNode();
-
- /* check and update recovered state based on current token,
- this action is also performed when shifting token after recovery
- got activated once.
- */
- this.recoveryTokenCheck();
-}
-}
+package org.eclipse.jdt.internal.codeassist.complete;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+/*
+ * Parser able to build specific completion parse nodes, given a cursorLocation.
+ *
+ * Cursor location denotes the position of the last character behind which completion
+ * got requested:
+ * -1 means completion at the very beginning of the source
+ * 0 means completion behind the first character
+ * n means completion behind the n-th character
+ */
+import org.eclipse.jdt.internal.compiler.*;
+import org.eclipse.jdt.internal.compiler.env.*;
+
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.parser.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.codeassist.impl.*;
+
+public class CompletionParser extends AssistParser {
+
+ /* public fields */
+
+ public int cursorLocation;
+ public char[][] labels; // the visible labels up to the cursor location
+
+
+ /* the following fields are internal flags */
+
+ boolean betweenNewAndLeftBraket; // whether we are between the keyword 'new' and the following left braket, ie. '[', '(' or '{'
+ boolean betweenCatchAndRightParen; // whether we are between the keyword 'catch' and the following ')'
+ boolean completionBehindDot; // true when completion identifier immediately follows a dot
+
+ // the stacks of types and qualifiers for invocations (ie. method invocations, allocation expressions and
+ // explicit constructor invocations). They use the same stack pointer as the selector stack (ie. invocationPtr)
+ // the invocation type stack contains one of the invocation type constants below
+ // the qualifier stack contains pointers to the expression stack or -1 if there is no qualifier
+ // (a qualifier is the expression that qualifies a 'new', a 'super' constructor or a 'this' constructor
+ // or it is the receiver of a message send)
+ int[] invocationTypeStack = new int[StackIncrement];
+ int[] qualifierStack = new int[StackIncrement];
+
+ // invocation type constants
+ static final int EXPLICIT_RECEIVER = 0;
+ static final int NO_RECEIVER = -1;
+ static final int SUPER_RECEIVER = -2;
+ static final int NAME_RECEIVER = -3;
+ static final int ALLOCATION = -4;
+ static final int QUALIFIED_ALLOCATION = -5;
+
+ // the type of the current invocation (one of the invocation type constants)
+ int invocationType;
+
+ // a pointer in the expression stack to the qualifier of a invocation
+ int qualifier;
+
+ // a stack of label counters
+ // a new counter is pushed on the stack each time when a method (or a constructor) is entered,
+ // it is poped when the method (or constructor) is exited,
+ // it is incremented when a new label is defined
+ int labelCounterPtr;
+ int[] labelCounterStack = new int[StackIncrement];
+
+ // a stack of invocationPtr: contains the first invocationPtr of a block
+ // the current invocationPtr+1 is pushed when a block is entered
+ // it is poped when a block is exited
+ int blockInvocationPtr;
+ int[] blockInvocationStack = new int[StackIncrement];
+public CompletionParser(ProblemReporter problemReporter) {
+ super(problemReporter);
+}
+public char[] assistIdentifier(){
+ return ((CompletionScanner)scanner).completionIdentifier;
+}
+protected void attachOrphanCompletionNode(){
+ if (this.isOrphanCompletionNode) {
+ AstNode orphan = this.assistNode;
+ this.isOrphanCompletionNode = false;
+
+ /* if in context of a type, then persists the identifier into a fake field return type */
+ if (currentElement instanceof RecoveredType){
+ RecoveredType recoveredType = (RecoveredType)currentElement;
+ /* filter out cases where scanner is still inside type header */
+ if (recoveredType.foundOpeningBrace) {
+ /* generate a pseudo field with a completion on type reference */
+ if (orphan instanceof TypeReference){
+ currentElement = currentElement.add(
+ new CompletionOnFieldType((TypeReference)orphan), 0);
+ return;
+ }
+ }
+ }
+ /* if in context of a method, persists if inside arguments as a type */
+ if (currentElement instanceof RecoveredMethod){
+ RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
+ /* only consider if inside method header */
+ if (!recoveredMethod.foundOpeningBrace) {
+ //if (rParenPos < lParenPos){ // inside arguments
+ if (orphan instanceof TypeReference){
+ currentElement = currentElement.parent.add(
+ new CompletionOnFieldType((TypeReference)orphan), 0);
+ return;
+ }
+ }
+ }
+
+ // add the completion node to the method declaration or constructor declaration
+ if (orphan instanceof Statement) {
+ /* check for completion at the beginning of method body
+ behind an invalid signature
+ */
+ RecoveredMethod method = currentElement.enclosingMethod();
+ if (method != null){
+ AbstractMethodDeclaration methodDecl = method.methodDeclaration;
+ if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
+ && (scanner.searchLineNumber(orphan.sourceStart) == scanner.searchLineNumber(methodDecl.sourceEnd))){
+ return;
+ }
+ }
+ // add the completion node as a statement to the list of block statements
+ currentElement = currentElement.add((Statement)orphan, 0);
+ return;
+ }
+ }
+
+ // the following code applies only in methods, constructors or initializers
+ if ((!this.inMethodStack[this.inMethodPtr] && !this.inInitializerStack[this.inInitializerPtr])) {
+ return;
+ }
+
+ // push top expression on ast stack if it contains the completion node
+ Expression expression;
+ if (this.expressionPtr > -1 && containsCompletionNode(expression = this.expressionStack[this.expressionPtr])) {
+ /* check for completion at the beginning of method body
+ behind an invalid signature
+ */
+ RecoveredMethod method = currentElement.enclosingMethod();
+ if (method != null){
+ AbstractMethodDeclaration methodDecl = method.methodDeclaration;
+ if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
+ && (scanner.searchLineNumber(expression.sourceStart) == scanner.searchLineNumber(methodDecl.sourceEnd))){
+ return;
+ }
+ }
+ if (expression instanceof AllocationExpression) {
+ // keep the context if it is an allocation expression
+ Statement statement = (Statement)wrapWithExplicitConstructorCallIfNeeded(expression);
+ currentElement = currentElement.add(statement, 0);
+ } else {
+ Statement statement = (Statement)wrapWithExplicitConstructorCallIfNeeded(this.assistNode);
+ currentElement = currentElement.add(statement, 0);
+ }
+ }
+}
+public int bodyEnd(AbstractMethodDeclaration method){
+ return cursorLocation;
+}
+public int bodyEnd(Initializer initializer){
+ return cursorLocation;
+}
+/**
+ * Checks if the completion is on the exception type of a catch clause.
+ * Returns whether we found a completion node.
+ */
+private boolean checkCatchClause() {
+ if (this.betweenCatchAndRightParen && this.identifierPtr > -1) {
+ // NB: if the cursor is on the variable, then it has been reduced (so identifierPtr is -1),
+ // thus this can only be a completion on the type of the catch clause
+ this.assistNode = getTypeReference(0);
+ this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+ return false;
+}
+/**
+ * Checks if the completion is on the type following a 'new'.
+ * Returns whether we found a completion node.
+ */
+private boolean checkClassInstanceCreation() {
+ if (this.betweenNewAndLeftBraket) {
+ // completion on type inside an allocation expression
+ TypeReference type = getTypeReference(0);
+ this.assistNode = type;
+ this.lastCheckPoint = type.sourceEnd + 1;
+ if (this.invocationType == ALLOCATION) {
+ // non qualified allocation expression: attach it later
+ this.isOrphanCompletionNode = true;
+ } else {
+ // qualified allocation expression
+ QualifiedAllocationExpression allocExpr = new QualifiedAllocationExpression();
+ allocExpr.type = type;
+ allocExpr.enclosingInstance = this.expressionStack[this.qualifier];
+ allocExpr.sourceStart = this.intStack[this.intPtr--];
+ allocExpr.sourceEnd = type.sourceEnd;
+ this.expressionStack[this.qualifier] = allocExpr; // attach it now (it replaces the qualifier expression)
+ this.isOrphanCompletionNode = false;
+ }
+ return true;
+ }
+ return false;
+}
+/**
+ * Checks if the completion is on the dot following an array type,
+ * a primitive type or an primitive array type.
+ * Returns whether we found a completion node.
+ */
+private boolean checkClassLiteralAccess() {
+ if (this.identifierLengthPtr >= 1 && this.previousToken == TokenNameDOT) { // (NB: the top id length is 1 and it is for the completion identifier)
+ int length;
+ // if the penultimate id length is negative,
+ // the completion is after a primitive type or a primitive array type
+ if ((length = this.identifierLengthStack[this.identifierLengthPtr-1]) < 0) {
+ // build the primitive type node
+ int dim = this.isAfterArrayType() ? this.intStack[this.intPtr--] : 0;
+ SingleTypeReference typeRef = (SingleTypeReference)TypeReference.baseTypeReference(-length, dim);
+ typeRef.sourceStart = this.intStack[this.intPtr--];
+ //typeRef.sourceEnd = typeRef.sourceStart + typeRef.token.length; // NB: It's ok to use the length of the token since it doesn't contain any unicode
+
+ // find the completion identifier and its source positions
+ char[] source = identifierStack[identifierPtr];
+ long pos = this.identifierPositionStack[this.identifierPtr--];
+ this.identifierLengthPtr--; // it can only be a simple identifier (so its length is one)
+
+ // build the completion on class literal access node
+ CompletionOnClassLiteralAccess access = new CompletionOnClassLiteralAccess(pos, typeRef);
+ access.completionIdentifier = source;
+ this.identifierLengthPtr--; // pop the length that was used to say it is a primitive type
+ this.assistNode = access;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+
+ // if the completion is after a regular array type
+ if (isAfterArrayType()) {
+ // find the completion identifier and its source positions
+ char[] source = identifierStack[identifierPtr];
+ long pos = this.identifierPositionStack[this.identifierPtr--];
+ this.identifierLengthPtr--; // it can only be a simple identifier (so its length is one)
+
+ // get the type reference
+ TypeReference typeRef = getTypeReference(this.intPtr--);
+
+ // build the completion on class literal access node
+ CompletionOnClassLiteralAccess access = new CompletionOnClassLiteralAccess(pos, typeRef);
+ access.completionIdentifier = source;
+ this.assistNode = access;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+
+ }
+ return false;
+}
+/**
+ * Checks if the completion is inside a method invocation or a constructor invocation.
+ * Returns whether we found a completion node.
+ */
+private boolean checkInvocation() {
+ Expression topExpression = this.expressionPtr >= 0 ?
+ this.expressionStack[this.expressionPtr] :
+ null;
+ boolean isEmptyNameCompletion = false;
+ boolean isEmptyAssistIdentifier = false;
+ int startInvocationPtr = this.blockInvocationPtr >= 0 ? this.blockInvocationStack[this.blockInvocationPtr] : 0;
+ if (this.invocationPtr >= startInvocationPtr
+ && ((isEmptyNameCompletion = topExpression == this.assistNode && this.isEmptyNameCompletion()) // eg. it is something like "this.fred([cursor]" but it is not something like "this.fred(1 + [cursor]"
+ || (isEmptyAssistIdentifier = this.indexOfAssistIdentifier() >= 0 && this.identifierStack[this.identifierPtr].length == 0))) { // eg. it is something like "this.fred(1 [cursor]"
+
+ // pop empty name completion
+ if (isEmptyNameCompletion) {
+ this.expressionPtr--;
+ this.expressionLengthStack[this.expressionLengthPtr]--;
+ } else if (isEmptyAssistIdentifier) {
+ this.identifierPtr--;
+ this.identifierLengthPtr--;
+ }
+
+ // find receiver and qualifier
+ int invocationType = this.invocationTypeStack[this.invocationPtr];
+ int qualifierExprPtr = this.qualifierStack[this.invocationPtr];
+
+ // find arguments
+ int numArgs = this.expressionPtr - qualifierExprPtr;
+ int argStart = qualifierExprPtr + 1;
+ Expression[] arguments = null;
+ if (numArgs > 0) {
+ // remember the arguments
+ arguments = new Expression[numArgs];
+ System.arraycopy(this.expressionStack, argStart, arguments, 0, numArgs);
+
+ // consume the expression arguments
+ this.expressionPtr -= numArgs;
+ int count = numArgs;
+ while (count > 0) {
+ count -= this.expressionLengthStack[this.expressionLengthPtr--];
+ }
+ }
+
+ // build ast node
+ if (invocationType != ALLOCATION && invocationType != QUALIFIED_ALLOCATION) {
+ // creates completion on message send
+ CompletionOnMessageSend messageSend = new CompletionOnMessageSend();
+ messageSend.arguments = arguments;
+ switch (invocationType) {
+ case NO_RECEIVER:
+ // implicit this
+ messageSend.receiver = ThisReference.ThisImplicit;
+ break;
+ case NAME_RECEIVER:
+ // remove selector
+ this.identifierPtr--;
+ this.identifierLengthStack[this.identifierLengthPtr]--;
+ // consume the receiver
+ messageSend.receiver = this.getUnspecifiedReference();
+ break;
+ case SUPER_RECEIVER:
+ messageSend.receiver = SuperReference.Super;
+ break;
+ case EXPLICIT_RECEIVER:
+ messageSend.receiver = this.expressionStack[qualifierExprPtr];
+ }
+
+ // set selector
+ messageSend.selector = this.identifierStack[this.selectorStack[this.invocationPtr]];
+ // remove selector
+ if (this.identifierLengthPtr >=0 && this.identifierLengthStack[this.identifierLengthPtr] == 1) {
+ this.identifierPtr--;
+ this.identifierLengthPtr--;
+ }
+
+ // no source is going to be replaced
+ messageSend.sourceStart = this.cursorLocation + 1;
+ messageSend.sourceEnd = this.cursorLocation;
+
+ // remember the message send as an orphan completion node
+ this.assistNode = messageSend;
+ this.lastCheckPoint = messageSend.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ } else {
+ int selectorPtr = this.selectorStack[this.invocationPtr];
+ if (selectorPtr == THIS_CONSTRUCTOR || selectorPtr == SUPER_CONSTRUCTOR) {
+ // creates an explicit constructor call
+ CompletionOnExplicitConstructorCall call = new CompletionOnExplicitConstructorCall(
+ (selectorPtr == THIS_CONSTRUCTOR) ? ExplicitConstructorCall.This : ExplicitConstructorCall.Super);
+ call.arguments = arguments;
+ if (invocationType == QUALIFIED_ALLOCATION) {
+ call.qualification = this.expressionStack[qualifierExprPtr];
+ }
+
+ // no source is going to be replaced
+ call.sourceStart = this.cursorLocation + 1;
+ call.sourceEnd = this.cursorLocation;
+
+ // remember the explicit constructor call as an orphan completion node
+ this.assistNode = call;
+ this.lastCheckPoint = call.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ } else {
+ // creates an allocation expression
+ CompletionOnQualifiedAllocationExpression allocExpr = new CompletionOnQualifiedAllocationExpression();
+ allocExpr.arguments = arguments;
+ allocExpr.type = super.getTypeReference(0); // we don't want a completion node here, so call super
+ if (invocationType == QUALIFIED_ALLOCATION) {
+ allocExpr.enclosingInstance = this.expressionStack[qualifierExprPtr];
+ }
+ // no source is going to be replaced
+ allocExpr.sourceStart = this.cursorLocation + 1;
+ allocExpr.sourceEnd = this.cursorLocation;
+
+ // remember the allocation expression as an orphan completion node
+ this.assistNode = allocExpr;
+ this.lastCheckPoint = allocExpr.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+/**
+ * Checks if the completion is on a member access (ie. in an identifier following a dot).
+ * Returns whether we found a completion node.
+ */
+private boolean checkMemberAccess() {
+ if (this.previousToken == TokenNameDOT && this.qualifier > -1 && this.expressionPtr == this.qualifier) {
+ // the receiver is an expression
+ pushCompletionOnMemberAccessOnExpressionStack(false);
+ return true;
+ }
+ return false;
+}
+/**
+ * Checks if the completion is on a name reference.
+ * Returns whether we found a completion node.
+ */
+private boolean checkNameCompletion() {
+ /*
+ We didn't find any other completion, but the completion identifier is on the identifier stack,
+ so it can only be a completion on name.
+ Note that we allow the completion on a name even if nothing is expected (eg. foo() b[cursor] would
+ be a completion on 'b'). This policy gives more to the user than he/she would expect, but this
+ simplifies the problem. To fix this, the recovery must be changed to work at a 'statement' granularity
+ instead of at the 'expression' granularity as it does right now.
+ */
+
+ // NB: at this point the completion identifier is on the identifier stack
+ this.assistNode = getUnspecifiedReferenceOptimized();
+ this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+}
+/**
+ * Checks if the completion is in the context of a method and on the type of one of its arguments
+ * Returns whether we found a completion node.
+ */
+private boolean checkRecoveredMethod() {
+ if (currentElement instanceof RecoveredMethod){
+ /* check if current awaiting identifier is the completion identifier */
+ if (this.indexOfAssistIdentifier() < 0) return false;
+
+ /* check if on line with an error already - to avoid completing inside
+ illegal type names e.g. int[<cursor> */
+ if (lastErrorEndPosition <= cursorLocation+1
+ && scanner.searchLineNumber(lastErrorEndPosition)
+ == scanner.searchLineNumber(((CompletionScanner)scanner).completedIdentifierStart)){
+ return false;
+ }
+ RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
+ /* only consider if inside method header */
+ if (!recoveredMethod.foundOpeningBrace
+ && lastIgnoredToken == -1) {
+ //if (rParenPos < lParenPos){ // inside arguments
+ this.assistNode = this.getTypeReference(0);
+ this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+ }
+ return false;
+}
+/**
+ * Checks if the completion is in the context of a type and on a type reference in this type.
+ * Persists the identifier into a fake field return type
+ * Returns whether we found a completion node.
+ */
+private boolean checkRecoveredType() {
+ if (currentElement instanceof RecoveredType){
+ /* check if current awaiting identifier is the completion identifier */
+ if (this.indexOfAssistIdentifier() < 0) return false;
+
+ /* check if on line with an error already - to avoid completing inside
+ illegal type names e.g. int[<cursor> */
+ if ((lastErrorEndPosition <= cursorLocation+1)
+ && scanner.searchLineNumber(lastErrorEndPosition)
+ == scanner.searchLineNumber(((CompletionScanner)scanner).completedIdentifierStart)){
+ return false;
+ }
+ RecoveredType recoveredType = (RecoveredType)currentElement;
+ /* filter out cases where scanner is still inside type header */
+ if (recoveredType.foundOpeningBrace) {
+ this.assistNode = this.getTypeReference(0);
+ this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+ }
+ return false;
+}
+/*
+ * Check whether about to shift beyond the completion token.
+ * If so, depending on the context, a special node might need to be created
+ * and attached to the existing recovered structure so as to be remember in the
+ * resulting parsed structure.
+ */
+public void completionIdentifierCheck(){
+
+ if (checkRecoveredType()) return;
+ if (checkRecoveredMethod()) return;
+
+ // if not in a method in non diet mode and if not inside a field initializer, only record references attached to types
+ if (!(this.inMethodStack[this.inMethodPtr] && !this.diet)
+ && !insideFieldInitializer()) return;
+
+ /*
+ In some cases, the completion identifier may not have yet been consumed,
+ e.g. int.[cursor]
+ This is because the grammar does not allow any (empty) identifier to follow
+ a base type. We thus have to manually force the identifier to be consumed
+ (i.e. pushed).
+ */
+ if (assistIdentifier() == null && this.currentToken == TokenNameIdentifier) { // Test below copied from CompletionScanner.getCurrentIdentifierSource()
+ if (cursorLocation < this.scanner.startPosition && this.scanner.currentPosition == this.scanner.startPosition){ // fake empty identifier got issued
+ this.pushIdentifier();
+ } else if (cursorLocation+1 >= this.scanner.startPosition && cursorLocation < this.scanner.currentPosition){
+ this.pushIdentifier();
+ }
+ }
+
+ // check for different scenarii
+ try {
+ // no need to go further if we found a non empty completion node
+ // (we still need to store labels though)
+ if (this.assistNode != null) {
+ // however inside an invocation, the completion identifier may already have been consumed into an empty name
+ // completion, so this check should be before we check that we are at the cursor location
+ if (!isEmptyNameCompletion() || checkInvocation()) return;
+ }
+
+ // no need to check further if we are not at the cursor location
+ if (this.indexOfAssistIdentifier() < 0) return;
+
+ if (checkClassInstanceCreation()) return;
+ if (checkCatchClause()) return;
+ if (checkMemberAccess()) return;
+ if (checkClassLiteralAccess()) return;
+
+ // if the completion was not on an empty name, it can still be inside an invocation (eg. this.fred("abc"[cursor])
+ // (NB: Put this check before checkNameCompletion() because the selector of the invocation can be on the identifier stack)
+ if (checkInvocation()) return;
+
+ if (checkNameCompletion()) return;
+ } finally {
+ storeLabelsIfNeeded();
+ }
+}
+protected void consumeCaseLabel() {
+ Expression caseExpression = this.expressionStack[this.expressionPtr];
+ if (caseExpression instanceof SingleNameReference || caseExpression instanceof QualifiedNameReference) {
+ // label counter was wrongly incremented in consumeToken
+ if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]--;
+ }
+ super.consumeCaseLabel();
+}
+protected void consumeConditionalExpression(int op) {
+ Expression valueIfTrue = this.expressionStack[this.expressionPtr - 1];
+ if (valueIfTrue instanceof SingleNameReference || valueIfTrue instanceof QualifiedNameReference) {
+ // label counter was wrongly incremented in consumeToken
+ if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]--;
+ }
+ super.consumeConditionalExpression(op);
+}
+protected void consumeConstructorBody() {
+ super.consumeConstructorBody();
+ this.labelCounterPtr--;
+}
+protected void consumeConstructorHeaderName() {
+
+ int index;
+
+ /* no need to take action if not inside assist identifiers */
+ if ((index = indexOfAssistIdentifier()) < 0) {
+ super.consumeConstructorHeaderName();
+ return;
+ }
+
+ /* force to start recovering in order to get fake field behavior */
+ if (currentElement == null){
+ this.hasReportedError = true; // do not report any error
+ }
+ this.restartRecovery = true;
+}
+/*
+ * Copy of code from superclass with the following change:
+ * If the cursor location is on the field access, then create a
+ * CompletionOnMemberAccess instead.
+ */
+protected void consumeFieldAccess(boolean isSuperAccess) {
+ // FieldAccess ::= Primary '.' 'Identifier'
+ // FieldAccess ::= 'super' '.' 'Identifier'
+
+ // potential receiver is being poped, so reset potential receiver
+ this.invocationType = NO_RECEIVER;
+
+ if (this.indexOfAssistIdentifier() < 0) {
+ super.consumeFieldAccess(isSuperAccess);
+ } else {
+ this.pushCompletionOnMemberAccessOnExpressionStack(isSuperAccess);
+ }
+}
+protected void consumeMethodBody() {
+ super.consumeMethodBody();
+ this.labelCounterPtr--;
+}
+protected void consumeNestedMethod() {
+ super.consumeNestedMethod();
+ this.pushNewLabelCounter();
+}
+protected void consumeStatementLabel() {
+ super.consumeStatementLabel();
+ if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]--;
+}
+protected void consumeToken(int token) {
+ int previous = this.previousToken;
+ int previousIdentifierPtr = this.previousIdentifierPtr;
+ super.consumeToken(token);
+
+ // if in field initializer (directly or not), on the completion identifier and not in recovery mode yet
+ // then position end of file at cursor location (so that we have the same behavior as
+ // in method bodies)
+ if (token == TokenNameIdentifier
+ && this.identifierStack[this.identifierPtr] == assistIdentifier()
+ && this.currentElement == null
+ && this.insideFieldInitializer()) {
+ this.scanner.eofPosition = cursorLocation+1;
+ }
+
+ // if in a method or if in a field initializer
+ if (this.inMethodStack[this.inMethodPtr] || this.inInitializerStack[this.inInitializerPtr]) {
+ switch (token) {
+ case TokenNameDOT:
+ switch (previous) {
+ case TokenNamethis: // eg. this[.]fred()
+ this.invocationType = EXPLICIT_RECEIVER;
+ break;
+ case TokenNamesuper: // eg. super[.]fred()
+ this.invocationType = SUPER_RECEIVER;
+ break;
+ case TokenNameIdentifier: // eg. bar[.]fred()
+ if (!this.betweenNewAndLeftBraket) { // eg. not new z.y[.]X()
+ if (this.identifierPtr != previousIdentifierPtr) { // if identifier has been consumed, eg. this.x[.]fred()
+ this.invocationType = EXPLICIT_RECEIVER;
+ } else {
+ this.invocationType = NAME_RECEIVER;
+ }
+ }
+ break;
+ }
+ break;
+ case TokenNameIdentifier:
+ if (previous == TokenNameDOT) { // eg. foo().[fred]()
+ // if current identifier is the empty completion one
+ if (identifierStack[identifierPtr] == CompletionScanner.EmptyCompletionIdentifier){
+ this.completionBehindDot = true;
+ }
+ if (this.invocationType != SUPER_RECEIVER // eg. not super.[fred]()
+ && this.invocationType != NAME_RECEIVER // eg. not bar.[fred]()
+ && this.invocationType != ALLOCATION // eg. not new foo.[Bar]()
+ && this.invocationType != QUALIFIED_ALLOCATION) { // eg. not fred().new foo.[Bar]()
+
+ this.invocationType = EXPLICIT_RECEIVER;
+ this.qualifier = this.expressionPtr;
+ }
+ }
+ break;
+ case TokenNamenew:
+ this.betweenNewAndLeftBraket = true;
+ this.qualifier = this.expressionPtr; // NB: even if there is no qualification, set it to the expression ptr so that the number of arguments are correctly computed
+ if (previous == TokenNameDOT) { // eg. fred().[new] X()
+ this.invocationType = QUALIFIED_ALLOCATION;
+ } else { // eg. [new] X()
+ this.invocationType = ALLOCATION;
+ }
+ break;
+ case TokenNamethis:
+ if (previous == TokenNameDOT) { // eg. fred().[this]()
+ this.invocationType = QUALIFIED_ALLOCATION;
+ this.qualifier = this.expressionPtr;
+ }
+ break;
+ case TokenNamesuper:
+ if (previous == TokenNameDOT) { // eg. fred().[super]()
+ this.invocationType = QUALIFIED_ALLOCATION;
+ this.qualifier = this.expressionPtr;
+ }
+ break;
+ case TokenNamecatch:
+ this.betweenCatchAndRightParen = true;
+ break;
+ case TokenNameLPAREN:
+ this.betweenNewAndLeftBraket = false;
+ if (this.invocationType == NO_RECEIVER || this.invocationType == NAME_RECEIVER) {
+ this.qualifier = this.expressionPtr; // remenber the last expression so that arguments are correctly computed
+ }
+ switch (previous) {
+ case TokenNameIdentifier: // eg. fred[(]) or foo.fred[(])
+ this.pushOnInvocationStacks(this.invocationType, this.qualifier);
+ this.invocationType = NO_RECEIVER;
+ break;
+ case TokenNamethis: // explicit constructor invocation, eg. this[(]1, 2)
+ this.pushOnInvocationStacks(
+ (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION,
+ this.qualifier);
+ this.invocationType = NO_RECEIVER;
+ break;
+ case TokenNamesuper: // explicit constructor invocation, eg. super[(]1, 2)
+ this.pushOnInvocationStacks(
+ (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION,
+ this.qualifier);
+ this.invocationType = NO_RECEIVER;
+ break;
+ }
+ break;
+ case TokenNameLBRACE:
+ this.betweenNewAndLeftBraket = false;
+ this.pushBlockInvocationPtr();
+ break;
+ case TokenNameLBRACKET:
+ this.betweenNewAndLeftBraket = false;
+ break;
+ case TokenNameRBRACE:
+ if (this.blockInvocationPtr >= 0) this.blockInvocationPtr--;
+ break;
+ case TokenNameRPAREN:
+ this.betweenCatchAndRightParen = false;
+ break;
+ case TokenNameCOLON:
+ if (previous == TokenNameIdentifier) {
+ if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]++;
+ }
+ break;
+ }
+ }
+}
+/**
+ * Return whether the given ast node contains the completion node.
+ */
+private boolean containsCompletionNode(AstNode ast) {
+ if (this.assistNode == null || ast instanceof Literal) {
+ return false;
+ }
+ if (this.assistNode == ast) {
+ return true;
+ }
+ if (ast instanceof Reference || ast instanceof TypeReference) {
+ return ast == this.assistNode;
+ }
+ if (ast instanceof Assignment) {
+ Assignment assign = (Assignment)ast;
+ return containsCompletionNode(assign.lhs) || containsCompletionNode(assign.expression);
+ }
+ if (ast instanceof UnaryExpression) {
+ UnaryExpression unary = (UnaryExpression)ast;
+ return containsCompletionNode(unary.expression);
+ }
+ if (ast instanceof BinaryExpression) {
+ BinaryExpression binary = (BinaryExpression)ast;
+ return containsCompletionNode(binary.left) || containsCompletionNode(binary.right);
+ }
+ if (ast instanceof InstanceOfExpression) {
+ InstanceOfExpression instanceOfExpr = (InstanceOfExpression)ast;
+ return containsCompletionNode(instanceOfExpr.expression) || containsCompletionNode(instanceOfExpr.type);
+ }
+ if (ast instanceof ConditionalExpression) {
+ ConditionalExpression conditional = (ConditionalExpression)ast;
+ return containsCompletionNode(conditional.condition) || containsCompletionNode(conditional.valueIfTrue) || containsCompletionNode(conditional.valueIfFalse);
+ }
+ if (ast instanceof AllocationExpression) {
+ AllocationExpression alloc = (AllocationExpression)ast;
+ return containsCompletionNode(alloc.type);
+ }
+ if (ast instanceof CastExpression) {
+ CastExpression cast = (CastExpression)ast;
+ return containsCompletionNode(cast.expression) || containsCompletionNode(cast.type);
+ }
+ if (ast instanceof ExplicitConstructorCall) {
+ ExplicitConstructorCall call = (ExplicitConstructorCall)ast;
+ Expression[] arguments = call.arguments;
+ if (arguments != null) {
+ for (int i = 0; i < arguments.length; i++) {
+ if (containsCompletionNode(arguments[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+ return false;
+}
+public ImportReference createAssistImportReference(char[][] tokens, long[] positions){
+ return new CompletionOnImportReference(tokens, positions);
+}
+public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){
+ return new CompletionOnPackageReference(tokens, positions);
+}
+public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] name, long[] positions){
+ return new CompletionOnQualifiedNameReference(
+ previousIdentifiers,
+ name,
+ positions);
+}
+public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] name, long[] positions){
+ return this.betweenCatchAndRightParen // check for exception scenario
+ ? new CompletionOnQualifiedExceptionReference(
+ previousIdentifiers,
+ name,
+ positions)
+ : new CompletionOnQualifiedTypeReference(
+ previousIdentifiers,
+ name,
+ positions);
+}
+public NameReference createSingleAssistNameReference(char[] name, long position) {
+ return new CompletionOnSingleNameReference(name, position);
+}
+public TypeReference createSingleAssistTypeReference(char[] name, long position) {
+ return this.betweenCatchAndRightParen // check for exception scenario
+ ? new CompletionOnExceptionReference(name, position)
+ : new CompletionOnSingleTypeReference(name, position);
+}
+public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLocation) {
+
+ this.cursorLocation = cursorLocation;
+ CompletionScanner completionScanner = (CompletionScanner)this.scanner;
+ completionScanner.completionIdentifier = null;
+ completionScanner.cursorLocation = cursorLocation;
+ return this.dietParse(sourceUnit, compilationResult);
+}
+/*
+ * Flush parser/scanner state regarding to code assist
+ */
+public void flushAssistState() {
+
+ super.flushAssistState();
+ this.isOrphanCompletionNode = false;
+ this.setAssistIdentifier(null);
+ CompletionScanner completionScanner = (CompletionScanner)this.scanner;
+ completionScanner.completedIdentifierStart = 0;
+ completionScanner.completedIdentifierEnd = -1;
+}
+protected NameReference getUnspecifiedReferenceOptimized() {
+ if (this.identifierLengthStack[this.identifierLengthPtr] > 1) { // reducing a qualified name
+ // potential receiver is being poped, so reset potential receiver
+ this.invocationType = NO_RECEIVER;
+ }
+ return super.getUnspecifiedReferenceOptimized();
+}
+
+public void initialize() {
+ super.initialize();
+ this.initializeForBlockStatements();
+ this.labelCounterPtr = -1;
+}
+/*
+ * Initializes the state of the parser that is about to go for BlockStatements.
+ */
+private void initializeForBlockStatements() {
+ this.previousToken = -1;
+ this.previousIdentifierPtr = -1;
+ this.completionBehindDot = false;
+ this.betweenNewAndLeftBraket = false;
+ this.betweenCatchAndRightParen = false;
+ this.invocationType = NO_RECEIVER;
+ this.qualifier = -1;
+ this.blockInvocationPtr = -1;
+}
+public void initializeScanner(){
+ this.scanner = new CompletionScanner();
+}
+/**
+ * Returns whether we are directly or indirectly inside a field initializer.
+ */
+private boolean insideFieldInitializer() {
+ for (int i = this.inInitializerPtr; i >= 0; i--) {
+ if (this.inInitializerStack[i]) {
+ return true;
+ }
+ }
+ return false;
+}
+/**
+ * Returns whether the completion is just after an array type
+ * eg. String[].[cursor]
+ */
+private boolean isAfterArrayType() {
+ // TBD: The following relies on the fact that array dimensions are small: it says that if the
+ // top of the intStack is less than 11, then it must be a dimension
+ // (smallest position of array type in a compilation unit is 11 as in "class X{Y[]")
+ int dim = 0;
+ if ((this.intPtr > -1) && (this.intStack[this.intPtr] < 11)) {
+ return true;
+ }
+ return false;
+}
+private boolean isEmptyNameCompletion() {
+ return
+ this.assistNode != null &&
+ this.assistNode instanceof CompletionOnSingleNameReference &&
+ (((CompletionOnSingleNameReference)this.assistNode).token.length == 0);
+}
+public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLocation) {
+
+ this.cursorLocation = cursorLocation;
+ CompletionScanner completionScanner = (CompletionScanner)this.scanner;
+ completionScanner.completionIdentifier = null;
+ completionScanner.cursorLocation = cursorLocation;
+ return this.parse(sourceUnit, compilationResult);
+}
+/*
+ * Prepares the state of the parser to go for BlockStatements.
+ */
+protected void prepareForBlockStatements() {
+ super.prepareForBlockStatements();
+ this.initializeForBlockStatements();
+}
+protected void pushBlockInvocationPtr() {
+ try {
+ this.blockInvocationStack[++this.blockInvocationPtr] = this.invocationPtr+1;
+ } catch (IndexOutOfBoundsException e) {
+ int oldStackLength = this.blockInvocationStack.length;
+ int[] oldStack = this.labelCounterStack;
+ this.blockInvocationStack = new int[oldStackLength + StackIncrement];
+ System.arraycopy(oldStack, 0, this.blockInvocationStack, 0, oldStackLength);
+ this.blockInvocationStack[this.blockInvocationPtr] = this.invocationPtr+1;
+ }
+}
+/**
+ * Creates a completion on member access node and push it
+ * on the expression stack.
+ */
+private void pushCompletionOnMemberAccessOnExpressionStack(boolean isSuperAccess) {
+ char[] source = identifierStack[identifierPtr];
+ long pos = identifierPositionStack[identifierPtr--];
+ CompletionOnMemberAccess fr = new CompletionOnMemberAccess(source, pos);
+ this.assistNode = fr;
+ this.lastCheckPoint = fr.sourceEnd + 1;
+ identifierLengthPtr--;
+ if (isSuperAccess) { //considerates the fieldReference beginning at the 'super' ....
+ fr.sourceStart = intStack[intPtr--];
+ fr.receiver = new SuperReference(fr.sourceStart, endPosition);
+ pushOnExpressionStack(fr);
+ } else { //optimize push/pop
+ if ((fr.receiver = expressionStack[expressionPtr]).isThis()) { //fieldreference begins at the this
+ fr.sourceStart = fr.receiver.sourceStart;
+ }
+ expressionStack[expressionPtr] = fr;
+ }
+}
+protected void pushNewLabelCounter() {
+ try {
+ this.labelCounterStack[++this.labelCounterPtr] = 0;
+ } catch (IndexOutOfBoundsException e) {
+ int oldStackLength = this.labelCounterStack.length;
+ int[] oldStack = this.labelCounterStack;
+ this.labelCounterStack = new int[oldStackLength + StackIncrement];
+ System.arraycopy(oldStack, 0, this.labelCounterStack, 0, oldStackLength);
+ this.labelCounterStack[this.labelCounterPtr] = 0;
+ }
+}
+/**
+ * Pushes the given invocation type (one of the invocation type constants) on the invocation type stack,
+ * and the given qualifier (an expression pointer to the expression stack) on the qualifier stack.
+ */
+protected void pushOnInvocationStacks(int invocationType, int qualifierExprPtr) {
+ // NB: invocationPtr has already been incremented by a call to pushOnSelectorStack()
+ try {
+ this.invocationTypeStack[this.invocationPtr] = invocationType;
+ this.qualifierStack[this.invocationPtr] = qualifierExprPtr;
+ } catch (IndexOutOfBoundsException e) {
+ int oldStackLength = this.invocationTypeStack.length;
+ int oldInvocationTypeStack[] = this.invocationTypeStack;
+ int oldQualifierStack[] = this.qualifierStack;
+ this.invocationTypeStack = new int[oldStackLength + StackIncrement];
+ this.qualifierStack = new int[oldStackLength + StackIncrement];
+ System.arraycopy(oldInvocationTypeStack, 0, this.invocationTypeStack, 0, oldStackLength);
+ System.arraycopy(oldQualifierStack, 0, this.qualifierStack, 0, oldStackLength);
+ this.invocationTypeStack[this.invocationPtr] = invocationType;
+ this.qualifierStack[this.invocationPtr] = qualifierExprPtr;
+ }
+}
+public void recordCompletionOnReference(){
+
+ if (currentElement instanceof RecoveredType){
+ RecoveredType recoveredType = (RecoveredType)currentElement;
+
+ /* filter out cases where scanner is still inside type header */
+ if (!recoveredType.foundOpeningBrace) return;
+
+ /* generate a pseudo field with a completion on type reference */
+ currentElement.add(
+ new CompletionOnFieldType(this.getTypeReference(0)), 0);
+ return;
+ }
+ if (!diet) return; // only record references attached to types
+
+}
+protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
+
+ /* Intercept error state on EOF inside method bodies, due to
+ cursor location being used as an EOF position.
+ */
+ if (!diet && currentToken == TokenNameEOF) return;
+ super.reportSyntaxError(act, currentKind, stateStackTop);
+}
+/*
+ * Reset internal state after completion is over
+ */
+
+public void reset() {
+ super.reset();
+ this.cursorLocation = 0;
+}
+/*
+ * Reset internal state after completion is over
+ */
+
+public void resetAfterCompletion() {
+ this.cursorLocation = 0;
+ this.flushAssistState();
+}
+/*
+ * Reset context so as to resume to regular parse loop
+ * If unable to reset for resuming, answers false.
+ *
+ * Move checkpoint location, reset internal stacks and
+ * decide which grammar goal is activated.
+ */
+protected boolean resumeAfterRecovery() {
+
+ if (this.assistNode != null) {
+ // if an assist node has been found and a recovered element exists,
+ // mark enclosing blocks as to be preserved
+ if (this.currentElement != null) {
+ currentElement.preserveEnclosingBlocks();
+ }
+ /* if reached [eof] inside method body, but still inside nested type,
+ or inside a field initializer, should continue in diet mode until
+ the end of the method body or compilation unit */
+ if ((scanner.eofPosition == cursorLocation+1)
+ && (!(referenceContext instanceof CompilationUnitDeclaration)
+ || insideFieldInitializer())) {
+
+ /* disabled since does not handle possible field/message refs, i.e. Obj[ASSIST HERE]ect.registerNatives()
+ // consume extra tokens which were part of the qualified reference
+ // so that the replaced source comprises them as well
+ if (this.assistNode instanceof NameReference){
+ int oldEof = scanner.eofPosition;
+ scanner.eofPosition = currentElement.topElement().sourceEnd()+1;
+ scanner.currentPosition = this.cursorLocation+1;
+ int token = -1;
+ try {
+ do {
+ // first token might not have to be a dot
+ if (token >= 0 || !this.completionBehindDot){
+ if ((token = scanner.getNextToken()) != TokenNameDOT) break;
+ }
+ if ((token = scanner.getNextToken()) != TokenNameIdentifier) break;
+ this.assistNode.sourceEnd = scanner.currentPosition - 1;
+ } while (token != TokenNameEOF);
+ } catch (InvalidInputException e){
+ } finally {
+ scanner.eofPosition = oldEof;
+ }
+ }
+ */
+ /* restart in diet mode for finding sibling constructs */
+ if (currentElement.enclosingType() != null){
+ lastCheckPoint = this.assistNode.sourceEnd+1;
+ scanner.eofPosition = currentElement.topElement().sourceEnd()+1;
+ } else {
+ this.resetStacks();
+ return false;
+ }
+ }
+ }
+ return super.resumeAfterRecovery();
+}
+public void setAssistIdentifier(char[] assistIdent){
+ ((CompletionScanner)scanner).completionIdentifier = assistIdent;
+}
+/**
+ * Stores the labels left on the identifier stack if they have not been stored yet.
+ */
+private void storeLabelsIfNeeded() {
+ int counter = this.labelCounterPtr >= 0 ? this.labelCounterStack[this.labelCounterPtr] : 0;
+ if (this.labels == null && this.identifierPtr >= 0) {
+ this.labels = new char[counter][];
+ System.arraycopy(this.identifierStack, this.identifierPtr - counter + 1, this.labels, 0, counter);
+ }
+ this.identifierPtr -= counter;
+ this.identifierLengthPtr -= counter; // labels have not been concatenated yet
+}
+/*
+ * Update recovery state based on current parser/scanner state
+ */
+protected void updateRecoveryState() {
+
+ /* expose parser state to recovery state */
+ currentElement.updateFromParserState();
+
+ /* may be able to retrieve completionNode as an orphan, and then attach it */
+ this.completionIdentifierCheck();
+ this.attachOrphanCompletionNode();
+
+ /* check and update recovered state based on current token,
+ this action is also performed when shifting token after recovery
+ got activated once.
+ */
+ this.recoveryTokenCheck();
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/InvalidCursorLocation.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/InvalidCursorLocation.java
index 543d318..72c987d 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/InvalidCursorLocation.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/InvalidCursorLocation.java
@@ -1,25 +1,24 @@
-package org.eclipse.jdt.internal.codeassist.complete;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.codeassist.impl.Engine;
-
-/**
- * Thrown whenever cursor location is not inside a consistent token
- * i.e. inside a string, number, unicode, comments etc...
- */
-public class InvalidCursorLocation extends RuntimeException {
-
- public String irritant;
-
- /* Possible irritants */
- public static final String NO_COMPLETION_INSIDE_UNICODE = "No Completion Inside Unicode"/*nonNLS*/;
- public static final String NO_COMPLETION_INSIDE_COMMENT = "No Completion Inside Comment"/*nonNLS*/;
- public static final String NO_COMPLETION_INSIDE_STRING = "No Completion Inside String"/*nonNLS*/;
- public static final String NO_COMPLETION_INSIDE_NUMBER = "No Completion Inside Number"/*nonNLS*/;
-
-public InvalidCursorLocation(String irritant){
- this.irritant = irritant;
-}
-}
+package org.eclipse.jdt.internal.codeassist.complete;
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+/**
+ * Thrown whenever cursor location is not inside a consistent token
+ * i.e. inside a string, number, unicode, comments etc...
+ */
+public class InvalidCursorLocation extends RuntimeException {
+
+ public String irritant;
+
+ /* Possible irritants */
+ public static final String NO_COMPLETION_INSIDE_UNICODE = "No Completion Inside Unicode"/*nonNLS*/;
+ public static final String NO_COMPLETION_INSIDE_COMMENT = "No Completion Inside Comment"/*nonNLS*/;
+ public static final String NO_COMPLETION_INSIDE_STRING = "No Completion Inside String"/*nonNLS*/;
+ public static final String NO_COMPLETION_INSIDE_NUMBER = "No Completion Inside Number"/*nonNLS*/;
+
+public InvalidCursorLocation(String irritant){
+ this.irritant = irritant;
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionNodeFound.java b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionNodeFound.java
index 6a98923..fbf2169 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionNodeFound.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionNodeFound.java
@@ -1,21 +1,17 @@
-package org.eclipse.jdt.internal.codeassist.select;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.env.*;
-
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class SelectionNodeFound extends RuntimeException {
- public Binding binding;
-public SelectionNodeFound() {
- this(null); // we found a problem in the selection node
-}
-public SelectionNodeFound(Binding binding) {
- this.binding = binding;
-}
-}
+package org.eclipse.jdt.internal.codeassist.select;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class SelectionNodeFound extends RuntimeException {
+ public Binding binding;
+public SelectionNodeFound() {
+ this(null); // we found a problem in the selection node
+}
+public SelectionNodeFound(Binding binding) {
+ this.binding = binding;
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedSuperReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedSuperReference.java
index d4c9138..3ebc0f3 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedSuperReference.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedSuperReference.java
@@ -1,53 +1,52 @@
-package org.eclipse.jdt.internal.codeassist.select;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-/*
- * Selection node build by the parser in any case it was intending to
- * reduce a qualified super reference containing the assist identifier.
- * e.g.
- *
- * class X extends Z {
- * class Y {
- * void foo() {
- * X.[start]super[end].bar();
- * }
- * }
- * }
- *
- * ---> class X {
- * class Y {
- * void foo() {
- * <SelectOnQualifiedSuper:X.super>
- * }
- * }
- * }
- *
- */
-
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.util.CharOperation;
-
-public class SelectionOnQualifiedSuperReference extends QualifiedSuperReference {
-public SelectionOnQualifiedSuperReference(TypeReference name, int pos, int sourceEnd) {
- super(name, pos, sourceEnd);
-}
-public TypeBinding resolveType(BlockScope scope) {
- TypeBinding binding = super.resolveType(scope);
-
- if (binding == null || !binding.isValidBinding())
- throw new SelectionNodeFound();
- else
- throw new SelectionNodeFound(binding);
-}
-public String toStringExpression(){
-
- StringBuffer buffer = new StringBuffer("<SelectOnQualifiedSuper:"/*nonNLS*/);
- buffer.append(super.toStringExpression());
- buffer.append(">"/*nonNLS*/);
- return buffer.toString();
-}
-}
+package org.eclipse.jdt.internal.codeassist.select;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a qualified super reference containing the assist identifier.
+ * e.g.
+ *
+ * class X extends Z {
+ * class Y {
+ * void foo() {
+ * X.[start]super[end].bar();
+ * }
+ * }
+ * }
+ *
+ * ---> class X {
+ * class Y {
+ * void foo() {
+ * <SelectOnQualifiedSuper:X.super>
+ * }
+ * }
+ * }
+ *
+ */
+
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class SelectionOnQualifiedSuperReference extends QualifiedSuperReference {
+public SelectionOnQualifiedSuperReference(TypeReference name, int pos, int sourceEnd) {
+ super(name, pos, sourceEnd);
+}
+public TypeBinding resolveType(BlockScope scope) {
+ TypeBinding binding = super.resolveType(scope);
+
+ if (binding == null || !binding.isValidBinding())
+ throw new SelectionNodeFound();
+ else
+ throw new SelectionNodeFound(binding);
+}
+public String toStringExpression(){
+
+ StringBuffer buffer = new StringBuffer("<SelectOnQualifiedSuper:"/*nonNLS*/);
+ buffer.append(super.toStringExpression());
+ buffer.append(">"/*nonNLS*/);
+ return buffer.toString();
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSuperReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSuperReference.java
index ea6450a..d6dd52c 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSuperReference.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSuperReference.java
@@ -1,52 +1,51 @@
-package org.eclipse.jdt.internal.codeassist.select;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-/*
- * Selection node build by the parser in any case it was intending to
- * reduce a super reference containing the assist identifier.
- * e.g.
- *
- * class X extends Z {
- * class Y {
- * void foo() {
- * [start]super[end].bar();
- * }
- * }
- * }
- *
- * ---> class X {
- * class Y {
- * void foo() {
- * <SelectOnQualifiedSuper:super>
- * }
- * }
- * }
- *
- */
-
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.util.CharOperation;
-
-public class SelectionOnSuperReference extends SuperReference {
-
-public SelectionOnSuperReference(int pos, int sourceEnd) {
- super(pos, sourceEnd);
-}
-public TypeBinding resolveType(BlockScope scope) {
- TypeBinding binding = super.resolveType(scope);
-
- if (binding == null || !binding.isValidBinding())
- throw new SelectionNodeFound();
- else
- throw new SelectionNodeFound(binding);
-}
-public String toStringExpression(){
-
- return "<SelectOnSuper:"/*nonNLS*/+super.toStringExpression()+">"/*nonNLS*/;
-
-}
-}
+package org.eclipse.jdt.internal.codeassist.select;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a super reference containing the assist identifier.
+ * e.g.
+ *
+ * class X extends Z {
+ * class Y {
+ * void foo() {
+ * [start]super[end].bar();
+ * }
+ * }
+ * }
+ *
+ * ---> class X {
+ * class Y {
+ * void foo() {
+ * <SelectOnQualifiedSuper:super>
+ * }
+ * }
+ * }
+ *
+ */
+
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class SelectionOnSuperReference extends SuperReference {
+
+public SelectionOnSuperReference(int pos, int sourceEnd) {
+ super(pos, sourceEnd);
+}
+public TypeBinding resolveType(BlockScope scope) {
+ TypeBinding binding = super.resolveType(scope);
+
+ if (binding == null || !binding.isValidBinding())
+ throw new SelectionNodeFound();
+ else
+ throw new SelectionNodeFound(binding);
+}
+public String toStringExpression(){
+
+ return "<SelectOnSuper:"/*nonNLS*/+super.toStringExpression()+">"/*nonNLS*/;
+
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
index 2752e8d..6224b2c 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
@@ -1,497 +1,496 @@
-package org.eclipse.jdt.internal.codeassist.select;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-/*
- * Parser able to build specific completion parse nodes, given a cursorLocation.
- *
- * Cursor location denotes the position of the last character behind which completion
- * got requested:
- * -1 means completion at the very beginning of the source
- * 0 means completion behind the first character
- * n means completion behind the n-th character
- */
-
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.env.*;
-
-import org.eclipse.jdt.internal.codeassist.impl.*;
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.parser.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.compiler.util.CharOperation;
-
-public class SelectionParser extends AssistParser {
-
- /* public fields */
-
- public int selectionStart, selectionEnd;
- public AstNode selectionNode;
-
- public static final char[] SUPER = "super"/*nonNLS*/.toCharArray();
-public SelectionParser(ProblemReporter problemReporter) {
- super(problemReporter);
-}
-public char[] assistIdentifier(){
- return ((SelectionScanner)scanner).selectionIdentifier;
-}
-protected void attachOrphanCompletionNode(){
- if (isOrphanCompletionNode){
- isOrphanCompletionNode = false;
- Statement statement = (Statement)wrapWithExplicitConstructorCallIfNeeded(this.assistNode);
- currentElement = currentElement.add(statement, 0);
- currentToken = 0; // given we are not on an eof, we do not want side effects caused by looked-ahead token
- }
-}
-protected void classInstanceCreation(boolean alwaysQualified) {
- // ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
-
- // ClassBodyopt produces a null item on the astStak if it produces NO class body
- // An empty class body produces a 0 on the length stack.....
-
- if (this.indexOfAssistIdentifier() < 0) {
- super.classInstanceCreation(alwaysQualified);
- return;
- }
- QualifiedAllocationExpression alloc;
- int length;
- if (((length = astLengthStack[astLengthPtr--]) == 1)
- && (astStack[astPtr] == null)) {
- //NO ClassBody
- astPtr--;
- alloc = new SelectionOnQualifiedAllocationExpression();
- alloc.sourceEnd = endPosition; //the position has been stored explicitly
-
- if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
- expressionPtr -= length;
- System.arraycopy(
- expressionStack,
- expressionPtr + 1,
- alloc.arguments = new Expression[length],
- 0,
- length);
- }
- // trick to avoid creating a selection on type reference
- char [] oldIdent = this.assistIdentifier();
- this.setAssistIdentifier(null);
- alloc.type = getTypeReference(0);
- this.setAssistIdentifier(oldIdent);
-
- //the default constructor with the correct number of argument
- //will be created and added by the TC (see createsInternalConstructorWithBinding)
- alloc.sourceStart = intStack[intPtr--];
- pushOnExpressionStack(alloc);
-
- this.assistNode = alloc;
- this.lastCheckPoint = alloc.sourceEnd + 1;
- restartRecovery = true; // force to restart into recovery mode
- isOrphanCompletionNode = true;
- }
-}
-protected void consumeArrayCreationExpression() {
- // ArrayCreationExpression ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializeropt
- // ArrayCreationExpression ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializeropt
-
- super.consumeArrayCreationExpression();
-
- ArrayAllocationExpression alloc = (ArrayAllocationExpression)expressionStack[expressionPtr];
- if (alloc.type == assistNode){
- restartRecovery = true;
- isOrphanCompletionNode = true;
- }
-}
-protected void consumeEnterAnonymousClassBody() {
- // EnterAnonymousClassBody ::= $empty
-
- if (this.indexOfAssistIdentifier() < 0) {
- super.consumeEnterAnonymousClassBody();
- return;
- }
- QualifiedAllocationExpression alloc;
- AnonymousLocalTypeDeclaration anonymousType =
- new AnonymousLocalTypeDeclaration();
- alloc =
- anonymousType.allocation = new SelectionOnQualifiedAllocationExpression(anonymousType);
- pushOnAstStack(anonymousType);
-
- alloc.sourceEnd = rParenPos; //the position has been stored explicitly
- int argumentLength;
- if ((argumentLength = expressionLengthStack[expressionLengthPtr--]) != 0) {
- expressionPtr -= argumentLength;
- System.arraycopy(
- expressionStack,
- expressionPtr + 1,
- alloc.arguments = new Expression[argumentLength],
- 0,
- argumentLength);
- }
- // trick to avoid creating a selection on type reference
- char [] oldIdent = this.assistIdentifier();
- this.setAssistIdentifier(null);
- alloc.type = getTypeReference(0);
- this.setAssistIdentifier(oldIdent);
-
- anonymousType.sourceEnd = alloc.sourceEnd;
- //position at the type while it impacts the anonymous declaration
- anonymousType.sourceStart = anonymousType.declarationSourceStart = alloc.type.sourceStart;
- alloc.sourceStart = intStack[intPtr--];
- pushOnExpressionStack(alloc);
-
- assistNode = alloc;
- this.lastCheckPoint = alloc.sourceEnd + 1;
- restartRecovery = true; // force to restart into recovery mode
- isOrphanCompletionNode = true;
-
- anonymousType.bodyStart = scanner.currentPosition;
- listLength = 0; // will be updated when reading super-interfaces
- // recovery
- if (currentElement != null){
- lastCheckPoint = anonymousType.bodyStart;
- currentElement = currentElement.add(anonymousType, 0); // the recoveryTokenCheck will deal with the open brace
- lastIgnoredToken = -1;
- }
-}
-protected void consumeEnterVariable() {
- // EnterVariable ::= $empty
- // do nothing by default
-
- super.consumeEnterVariable();
-
- AbstractVariableDeclaration variable = (AbstractVariableDeclaration) astStack[astPtr];
- if (variable.type == assistNode){
- restartRecovery = true;
- isOrphanCompletionNode = false; // already attached inside variable decl
- }
-}
-protected void consumeFieldAccess(boolean isSuperAccess) {
- // FieldAccess ::= Primary '.' 'Identifier'
- // FieldAccess ::= 'super' '.' 'Identifier'
-
- if (this.indexOfAssistIdentifier() < 0) {
- super.consumeFieldAccess(isSuperAccess);
- return;
- }
- FieldReference fieldReference =
- new SelectionOnFieldReference(
- identifierStack[identifierPtr],
- identifierPositionStack[identifierPtr--]);
- identifierLengthPtr--;
- if (isSuperAccess) { //considerates the fieldReferenceerence beginning at the 'super' ....
- fieldReference.sourceStart = intStack[intPtr--];
- fieldReference.receiver = new SuperReference(fieldReference.sourceStart, endPosition);
- pushOnExpressionStack(fieldReference);
- } else { //optimize push/pop
- if ((fieldReference.receiver = expressionStack[expressionPtr]).isThis()) { //fieldReferenceerence begins at the this
- fieldReference.sourceStart = fieldReference.receiver.sourceStart;
- }
- expressionStack[expressionPtr] = fieldReference;
- }
- assistNode = fieldReference;
- this.lastCheckPoint = fieldReference.sourceEnd + 1;
- restartRecovery = true; // force to restart in recovery mode
- isOrphanCompletionNode = true;
-}
-protected void consumeMethodInvocationName() {
- // MethodInvocation ::= Name '(' ArgumentListopt ')'
-
- // when the name is only an identifier...we have a message send to "this" (implicit)
-
- char[] selector = identifierStack[identifierPtr];
- if (!(selector == this.assistIdentifier() && CharOperation.equals(selector, SUPER))){
- super.consumeMethodInvocationName();
- return;
- }
- ExplicitConstructorCall constructorCall = new SelectionOnExplicitConstructorCall(ExplicitConstructorCall.Super);
- constructorCall.sourceEnd = rParenPos;
- constructorCall.sourceStart = (int) (identifierPositionStack[identifierPtr] >>> 32);
- int length;
- if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
- expressionPtr -= length;
- System.arraycopy(expressionStack, expressionPtr + 1, constructorCall.arguments = new Expression[length], 0, length);
- }
-
- pushOnAstStack(constructorCall);
- this.assistNode = constructorCall;
- this.lastCheckPoint = constructorCall.sourceEnd + 1;
- restartRecovery = true; // force to restart in recovery mode
- isOrphanCompletionNode = true;
-}
-protected void consumeMethodInvocationPrimary() {
- //optimize the push/pop
- //MethodInvocation ::= Primary '.' 'Identifier' '(' ArgumentListopt ')'
-
- char[] selector = identifierStack[identifierPtr];
- if (!(selector == this.assistIdentifier() && CharOperation.equals(selector, SUPER))){
- super.consumeMethodInvocationPrimary();
- return;
- }
- ExplicitConstructorCall constructorCall = new SelectionOnExplicitConstructorCall(ExplicitConstructorCall.Super);
- constructorCall.sourceEnd = rParenPos;
- int length;
- if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
- expressionPtr -= length;
- System.arraycopy(expressionStack, expressionPtr + 1, constructorCall.arguments = new Expression[length], 0, length);
- }
- constructorCall.qualification = expressionStack[expressionPtr--];
- constructorCall.sourceStart = constructorCall.qualification.sourceStart;
-
- pushOnAstStack(constructorCall);
- this.assistNode = constructorCall;
- this.lastCheckPoint = constructorCall.sourceEnd + 1;
- restartRecovery = true; // force to restart in recovery mode
- isOrphanCompletionNode = true;
-}
-protected void consumeTypeImportOnDemandDeclarationName() {
- // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
- /* push an ImportRef build from the last name
- stored in the identifier stack. */
-
- int index;
-
- /* no need to take action if not inside assist identifiers */
- if ((index = indexOfAssistIdentifier()) < 0) {
- super.consumeTypeImportOnDemandDeclarationName();
- return;
- }
- /* retrieve identifiers subset and whole positions, the assist node positions
- should include the entire replaced source. */
- int length = identifierLengthStack[identifierLengthPtr];
- char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
- identifierLengthPtr--;
- identifierPtr -= length;
- long[] positions = new long[length];
- System.arraycopy(
- identifierPositionStack,
- identifierPtr + 1,
- positions,
- 0,
- length);
-
- /* build specific assist node on import statement */
- ImportReference reference = this.createAssistImportReference(subset, positions);
- reference.onDemand = true;
- assistNode = reference;
- this.lastCheckPoint = reference.sourceEnd + 1;
-
- pushOnAstStack(reference);
-
- if (currentToken == TokenNameSEMICOLON){
- reference.declarationSourceEnd = scanner.currentPosition - 1;
- } else {
- reference.declarationSourceEnd = (int) positions[length-1];
- }
- //endPosition is just before the ;
- reference.declarationSourceStart = intStack[intPtr--];
- // flush annotations defined prior to import statements
- reference.declarationSourceEnd = this.flushAnnotationsDefinedPriorTo(reference.declarationSourceEnd);
-
- // recovery
- if (currentElement != null){
- lastCheckPoint = reference.declarationSourceEnd+1;
- currentElement = currentElement.add(reference, 0);
- lastIgnoredToken = -1;
- restartRecovery = true; // used to avoid branching back into the regular automaton
- }
-}
-public ImportReference createAssistImportReference(char[][] tokens, long[] positions){
- return new SelectionOnImportReference(tokens, positions);
-}
-public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){
- return new SelectionOnPackageReference(tokens, positions);
-}
-public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] name, long[] positions){
- return new SelectionOnQualifiedNameReference(
- previousIdentifiers,
- name,
- positions);
-}
-public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] name, long[] positions){
- return new SelectionOnQualifiedTypeReference(
- previousIdentifiers,
- name,
- positions);
-}
-public NameReference createSingleAssistNameReference(char[] name, long position) {
- return new SelectionOnSingleNameReference(name, position);
-}
-public TypeReference createSingleAssistTypeReference(char[] name, long position) {
- return new SelectionOnSingleTypeReference(name, position);
-}
-public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int selectionStart, int selectionEnd) {
-
- this.selectionStart = selectionStart;
- this.selectionEnd = selectionEnd;
- SelectionScanner selectionScanner = (SelectionScanner)this.scanner;
- selectionScanner.selectionIdentifier = null;
- selectionScanner.selectionStart = selectionStart;
- selectionScanner.selectionEnd = selectionEnd;
- return this.dietParse(sourceUnit, compilationResult);
-}
-/*
- * Flush parser/scanner state regarding to code assist
- */
-public void flushAssistState() {
-
- super.flushAssistState();
- this.selectionNode = null;
- this.setAssistIdentifier(null);
-}
-protected NameReference getUnspecifiedReference() {
- /* build a (unspecified) NameReference which may be qualified*/
-
- int completionIndex;
-
- /* no need to take action if not inside completed identifiers */
- if ((completionIndex = indexOfAssistIdentifier()) < 0) {
- return super.getUnspecifiedReference();
- }
-
- int length = identifierLengthStack[identifierLengthPtr];
- if (CharOperation.equals(assistIdentifier(), SUPER)){
- Reference reference;
- if (completionIndex > 0){ // qualified super
- // discard 'super' from identifier stacks
- identifierLengthStack[identifierLengthPtr] = completionIndex;
- int ptr = identifierPtr -= (length - completionIndex);
- reference =
- new SelectionOnQualifiedSuperReference(
- getTypeReference(0),
- (int)(identifierPositionStack[ptr+1] >>> 32),
- (int) identifierPositionStack[ptr+1]);
- } else { // standard super
- identifierPtr -= length;
- identifierLengthPtr--;
- reference = new SelectionOnSuperReference((int)(identifierPositionStack[identifierPtr+1] >>> 32), (int) identifierPositionStack[identifierPtr+1]);
- }
- pushOnAstStack(reference);
- this.assistNode = reference;
- this.lastCheckPoint = reference.sourceEnd + 1;
- restartRecovery = true; // force to restart in recovery mode
- isOrphanCompletionNode = true;
- return new SingleNameReference(new char[0], 0); // dummy reference
- }
- NameReference nameReference;
- /* retrieve identifiers subset and whole positions, the completion node positions
- should include the entire replaced source. */
- char[][] subset = identifierSubSet(completionIndex);
- identifierLengthPtr--;
- identifierPtr -= length;
- long[] positions = new long[length];
- System.arraycopy(
- identifierPositionStack,
- identifierPtr + 1,
- positions,
- 0,
- length);
- /* build specific completion on name reference */
- if (completionIndex == 0) {
- /* completion inside first identifier */
- nameReference = this.createSingleAssistNameReference(assistIdentifier(), positions[0]);
- } else {
- /* completion inside subsequent identifier */
- nameReference = this.createQualifiedAssistNameReference(subset, assistIdentifier(), positions);
- }
- assistNode = nameReference;
- this.lastCheckPoint = nameReference.sourceEnd + 1;
- isOrphanCompletionNode = true;
- restartRecovery = true; // force to restart into recovery mode
- return nameReference;
-}
-/*
- * Copy of code from superclass with the following change:
- * In the case of qualified name reference if the cursor location is on the
- * qualified name reference, then create a CompletionOnQualifiedNameReference
- * instead.
- */
-protected NameReference getUnspecifiedReferenceOptimized() {
-
- int index = indexOfAssistIdentifier();
- NameReference reference = super.getUnspecifiedReferenceOptimized();
-
- if (index >= 0){
- restartRecovery = true; // force to stop and restart in recovery mode
- isOrphanCompletionNode = true;
- }
- return reference;
-}
-public void initializeScanner(){
- this.scanner = new SelectionScanner();
-}
-protected MessageSend newMessageSend() {
- // '(' ArgumentListopt ')'
- // the arguments are on the expression stack
-
- char[] selector = identifierStack[identifierPtr];
- if (selector != this.assistIdentifier()){
- return super.newMessageSend();
- }
- MessageSend messageSend = new SelectionOnMessageSend();
- int length;
- if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
- expressionPtr -= length;
- System.arraycopy(
- expressionStack,
- expressionPtr + 1,
- messageSend.arguments = new Expression[length],
- 0,
- length);
- };
- assistNode = messageSend;
- restartRecovery = true; // force to restart in recovery mode
- isOrphanCompletionNode = true;
- return messageSend;
-}
-public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int selectionStart, int selectionEnd) {
-
- this.selectionStart = selectionStart;
- this.selectionEnd = selectionEnd;
- SelectionScanner selectionScanner = (SelectionScanner)this.scanner;
- selectionScanner.selectionIdentifier = null;
- selectionScanner.selectionStart = selectionStart;
- selectionScanner.selectionEnd = selectionEnd;
- return this.parse(sourceUnit, compilationResult);
-}
-/*
- * Reset context so as to resume to regular parse loop
- * If unable to reset for resuming, answers false.
- *
- * Move checkpoint location, reset internal stacks and
- * decide which grammar goal is activated.
- */
-protected boolean resumeAfterRecovery() {
-
- /* if reached assist node inside method body, but still inside nested type,
- should continue in diet mode until the end of the method body */
- if (this.assistNode != null
- && !(referenceContext instanceof CompilationUnitDeclaration)){
- currentElement.preserveEnclosingBlocks();
- if (currentElement.enclosingType() == null){
- this.resetStacks();
- return false;
- }
- }
- return super.resumeAfterRecovery();
-}
-public void setAssistIdentifier(char[] assistIdent){
- ((SelectionScanner)scanner).selectionIdentifier = assistIdent;
-}
-/*
- * Update recovery state based on current parser/scanner state
- */
-protected void updateRecoveryState() {
-
- /* expose parser state to recovery state */
- currentElement.updateFromParserState();
-
- /* may be able to retrieve completionNode as an orphan, and then attach it */
- this.attachOrphanCompletionNode();
-
- /* check and update recovered state based on current token,
- this action is also performed when shifting token after recovery
- got activated once.
- */
- this.recoveryTokenCheck();
-}
-}
+package org.eclipse.jdt.internal.codeassist.select;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+/*
+ * Parser able to build specific completion parse nodes, given a cursorLocation.
+ *
+ * Cursor location denotes the position of the last character behind which completion
+ * got requested:
+ * -1 means completion at the very beginning of the source
+ * 0 means completion behind the first character
+ * n means completion behind the n-th character
+ */
+
+import org.eclipse.jdt.internal.compiler.*;
+import org.eclipse.jdt.internal.compiler.env.*;
+
+import org.eclipse.jdt.internal.codeassist.impl.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.compiler.util.CharOperation;
+
+public class SelectionParser extends AssistParser {
+
+ /* public fields */
+
+ public int selectionStart, selectionEnd;
+ public AstNode selectionNode;
+
+ public static final char[] SUPER = "super"/*nonNLS*/.toCharArray();
+public SelectionParser(ProblemReporter problemReporter) {
+ super(problemReporter);
+}
+public char[] assistIdentifier(){
+ return ((SelectionScanner)scanner).selectionIdentifier;
+}
+protected void attachOrphanCompletionNode(){
+ if (isOrphanCompletionNode){
+ isOrphanCompletionNode = false;
+ Statement statement = (Statement)wrapWithExplicitConstructorCallIfNeeded(this.assistNode);
+ currentElement = currentElement.add(statement, 0);
+ currentToken = 0; // given we are not on an eof, we do not want side effects caused by looked-ahead token
+ }
+}
+protected void classInstanceCreation(boolean alwaysQualified) {
+ // ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
+
+ // ClassBodyopt produces a null item on the astStak if it produces NO class body
+ // An empty class body produces a 0 on the length stack.....
+
+ if (this.indexOfAssistIdentifier() < 0) {
+ super.classInstanceCreation(alwaysQualified);
+ return;
+ }
+ QualifiedAllocationExpression alloc;
+ int length;
+ if (((length = astLengthStack[astLengthPtr--]) == 1)
+ && (astStack[astPtr] == null)) {
+ //NO ClassBody
+ astPtr--;
+ alloc = new SelectionOnQualifiedAllocationExpression();
+ alloc.sourceEnd = endPosition; //the position has been stored explicitly
+
+ if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+ expressionPtr -= length;
+ System.arraycopy(
+ expressionStack,
+ expressionPtr + 1,
+ alloc.arguments = new Expression[length],
+ 0,
+ length);
+ }
+ // trick to avoid creating a selection on type reference
+ char [] oldIdent = this.assistIdentifier();
+ this.setAssistIdentifier(null);
+ alloc.type = getTypeReference(0);
+ this.setAssistIdentifier(oldIdent);
+
+ //the default constructor with the correct number of argument
+ //will be created and added by the TC (see createsInternalConstructorWithBinding)
+ alloc.sourceStart = intStack[intPtr--];
+ pushOnExpressionStack(alloc);
+
+ this.assistNode = alloc;
+ this.lastCheckPoint = alloc.sourceEnd + 1;
+ restartRecovery = true; // force to restart into recovery mode
+ isOrphanCompletionNode = true;
+ }
+}
+protected void consumeArrayCreationExpression() {
+ // ArrayCreationExpression ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializeropt
+ // ArrayCreationExpression ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializeropt
+
+ super.consumeArrayCreationExpression();
+
+ ArrayAllocationExpression alloc = (ArrayAllocationExpression)expressionStack[expressionPtr];
+ if (alloc.type == assistNode){
+ restartRecovery = true;
+ isOrphanCompletionNode = true;
+ }
+}
+protected void consumeEnterAnonymousClassBody() {
+ // EnterAnonymousClassBody ::= $empty
+
+ if (this.indexOfAssistIdentifier() < 0) {
+ super.consumeEnterAnonymousClassBody();
+ return;
+ }
+ QualifiedAllocationExpression alloc;
+ AnonymousLocalTypeDeclaration anonymousType =
+ new AnonymousLocalTypeDeclaration();
+ alloc =
+ anonymousType.allocation = new SelectionOnQualifiedAllocationExpression(anonymousType);
+ pushOnAstStack(anonymousType);
+
+ alloc.sourceEnd = rParenPos; //the position has been stored explicitly
+ int argumentLength;
+ if ((argumentLength = expressionLengthStack[expressionLengthPtr--]) != 0) {
+ expressionPtr -= argumentLength;
+ System.arraycopy(
+ expressionStack,
+ expressionPtr + 1,
+ alloc.arguments = new Expression[argumentLength],
+ 0,
+ argumentLength);
+ }
+ // trick to avoid creating a selection on type reference
+ char [] oldIdent = this.assistIdentifier();
+ this.setAssistIdentifier(null);
+ alloc.type = getTypeReference(0);
+ this.setAssistIdentifier(oldIdent);
+
+ anonymousType.sourceEnd = alloc.sourceEnd;
+ //position at the type while it impacts the anonymous declaration
+ anonymousType.sourceStart = anonymousType.declarationSourceStart = alloc.type.sourceStart;
+ alloc.sourceStart = intStack[intPtr--];
+ pushOnExpressionStack(alloc);
+
+ assistNode = alloc;
+ this.lastCheckPoint = alloc.sourceEnd + 1;
+ restartRecovery = true; // force to restart into recovery mode
+ isOrphanCompletionNode = true;
+
+ anonymousType.bodyStart = scanner.currentPosition;
+ listLength = 0; // will be updated when reading super-interfaces
+ // recovery
+ if (currentElement != null){
+ lastCheckPoint = anonymousType.bodyStart;
+ currentElement = currentElement.add(anonymousType, 0); // the recoveryTokenCheck will deal with the open brace
+ lastIgnoredToken = -1;
+ }
+}
+protected void consumeEnterVariable() {
+ // EnterVariable ::= $empty
+ // do nothing by default
+
+ super.consumeEnterVariable();
+
+ AbstractVariableDeclaration variable = (AbstractVariableDeclaration) astStack[astPtr];
+ if (variable.type == assistNode){
+ restartRecovery = true;
+ isOrphanCompletionNode = false; // already attached inside variable decl
+ }
+}
+protected void consumeFieldAccess(boolean isSuperAccess) {
+ // FieldAccess ::= Primary '.' 'Identifier'
+ // FieldAccess ::= 'super' '.' 'Identifier'
+
+ if (this.indexOfAssistIdentifier() < 0) {
+ super.consumeFieldAccess(isSuperAccess);
+ return;
+ }
+ FieldReference fieldReference =
+ new SelectionOnFieldReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ identifierLengthPtr--;
+ if (isSuperAccess) { //considerates the fieldReferenceerence beginning at the 'super' ....
+ fieldReference.sourceStart = intStack[intPtr--];
+ fieldReference.receiver = new SuperReference(fieldReference.sourceStart, endPosition);
+ pushOnExpressionStack(fieldReference);
+ } else { //optimize push/pop
+ if ((fieldReference.receiver = expressionStack[expressionPtr]).isThis()) { //fieldReferenceerence begins at the this
+ fieldReference.sourceStart = fieldReference.receiver.sourceStart;
+ }
+ expressionStack[expressionPtr] = fieldReference;
+ }
+ assistNode = fieldReference;
+ this.lastCheckPoint = fieldReference.sourceEnd + 1;
+ restartRecovery = true; // force to restart in recovery mode
+ isOrphanCompletionNode = true;
+}
+protected void consumeMethodInvocationName() {
+ // MethodInvocation ::= Name '(' ArgumentListopt ')'
+
+ // when the name is only an identifier...we have a message send to "this" (implicit)
+
+ char[] selector = identifierStack[identifierPtr];
+ if (!(selector == this.assistIdentifier() && CharOperation.equals(selector, SUPER))){
+ super.consumeMethodInvocationName();
+ return;
+ }
+ ExplicitConstructorCall constructorCall = new SelectionOnExplicitConstructorCall(ExplicitConstructorCall.Super);
+ constructorCall.sourceEnd = rParenPos;
+ constructorCall.sourceStart = (int) (identifierPositionStack[identifierPtr] >>> 32);
+ int length;
+ if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+ expressionPtr -= length;
+ System.arraycopy(expressionStack, expressionPtr + 1, constructorCall.arguments = new Expression[length], 0, length);
+ }
+
+ pushOnAstStack(constructorCall);
+ this.assistNode = constructorCall;
+ this.lastCheckPoint = constructorCall.sourceEnd + 1;
+ restartRecovery = true; // force to restart in recovery mode
+ isOrphanCompletionNode = true;
+}
+protected void consumeMethodInvocationPrimary() {
+ //optimize the push/pop
+ //MethodInvocation ::= Primary '.' 'Identifier' '(' ArgumentListopt ')'
+
+ char[] selector = identifierStack[identifierPtr];
+ if (!(selector == this.assistIdentifier() && CharOperation.equals(selector, SUPER))){
+ super.consumeMethodInvocationPrimary();
+ return;
+ }
+ ExplicitConstructorCall constructorCall = new SelectionOnExplicitConstructorCall(ExplicitConstructorCall.Super);
+ constructorCall.sourceEnd = rParenPos;
+ int length;
+ if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+ expressionPtr -= length;
+ System.arraycopy(expressionStack, expressionPtr + 1, constructorCall.arguments = new Expression[length], 0, length);
+ }
+ constructorCall.qualification = expressionStack[expressionPtr--];
+ constructorCall.sourceStart = constructorCall.qualification.sourceStart;
+
+ pushOnAstStack(constructorCall);
+ this.assistNode = constructorCall;
+ this.lastCheckPoint = constructorCall.sourceEnd + 1;
+ restartRecovery = true; // force to restart in recovery mode
+ isOrphanCompletionNode = true;
+}
+protected void consumeTypeImportOnDemandDeclarationName() {
+ // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
+ /* push an ImportRef build from the last name
+ stored in the identifier stack. */
+
+ int index;
+
+ /* no need to take action if not inside assist identifiers */
+ if ((index = indexOfAssistIdentifier()) < 0) {
+ super.consumeTypeImportOnDemandDeclarationName();
+ return;
+ }
+ /* retrieve identifiers subset and whole positions, the assist node positions
+ should include the entire replaced source. */
+ int length = identifierLengthStack[identifierLengthPtr];
+ char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
+ identifierLengthPtr--;
+ identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(
+ identifierPositionStack,
+ identifierPtr + 1,
+ positions,
+ 0,
+ length);
+
+ /* build specific assist node on import statement */
+ ImportReference reference = this.createAssistImportReference(subset, positions);
+ reference.onDemand = true;
+ assistNode = reference;
+ this.lastCheckPoint = reference.sourceEnd + 1;
+
+ pushOnAstStack(reference);
+
+ if (currentToken == TokenNameSEMICOLON){
+ reference.declarationSourceEnd = scanner.currentPosition - 1;
+ } else {
+ reference.declarationSourceEnd = (int) positions[length-1];
+ }
+ //endPosition is just before the ;
+ reference.declarationSourceStart = intStack[intPtr--];
+ // flush annotations defined prior to import statements
+ reference.declarationSourceEnd = this.flushAnnotationsDefinedPriorTo(reference.declarationSourceEnd);
+
+ // recovery
+ if (currentElement != null){
+ lastCheckPoint = reference.declarationSourceEnd+1;
+ currentElement = currentElement.add(reference, 0);
+ lastIgnoredToken = -1;
+ restartRecovery = true; // used to avoid branching back into the regular automaton
+ }
+}
+public ImportReference createAssistImportReference(char[][] tokens, long[] positions){
+ return new SelectionOnImportReference(tokens, positions);
+}
+public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){
+ return new SelectionOnPackageReference(tokens, positions);
+}
+public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] name, long[] positions){
+ return new SelectionOnQualifiedNameReference(
+ previousIdentifiers,
+ name,
+ positions);
+}
+public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] name, long[] positions){
+ return new SelectionOnQualifiedTypeReference(
+ previousIdentifiers,
+ name,
+ positions);
+}
+public NameReference createSingleAssistNameReference(char[] name, long position) {
+ return new SelectionOnSingleNameReference(name, position);
+}
+public TypeReference createSingleAssistTypeReference(char[] name, long position) {
+ return new SelectionOnSingleTypeReference(name, position);
+}
+public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int selectionStart, int selectionEnd) {
+
+ this.selectionStart = selectionStart;
+ this.selectionEnd = selectionEnd;
+ SelectionScanner selectionScanner = (SelectionScanner)this.scanner;
+ selectionScanner.selectionIdentifier = null;
+ selectionScanner.selectionStart = selectionStart;
+ selectionScanner.selectionEnd = selectionEnd;
+ return this.dietParse(sourceUnit, compilationResult);
+}
+/*
+ * Flush parser/scanner state regarding to code assist
+ */
+public void flushAssistState() {
+
+ super.flushAssistState();
+ this.selectionNode = null;
+ this.setAssistIdentifier(null);
+}
+protected NameReference getUnspecifiedReference() {
+ /* build a (unspecified) NameReference which may be qualified*/
+
+ int completionIndex;
+
+ /* no need to take action if not inside completed identifiers */
+ if ((completionIndex = indexOfAssistIdentifier()) < 0) {
+ return super.getUnspecifiedReference();
+ }
+
+ int length = identifierLengthStack[identifierLengthPtr];
+ if (CharOperation.equals(assistIdentifier(), SUPER)){
+ Reference reference;
+ if (completionIndex > 0){ // qualified super
+ // discard 'super' from identifier stacks
+ identifierLengthStack[identifierLengthPtr] = completionIndex;
+ int ptr = identifierPtr -= (length - completionIndex);
+ reference =
+ new SelectionOnQualifiedSuperReference(
+ getTypeReference(0),
+ (int)(identifierPositionStack[ptr+1] >>> 32),
+ (int) identifierPositionStack[ptr+1]);
+ } else { // standard super
+ identifierPtr -= length;
+ identifierLengthPtr--;
+ reference = new SelectionOnSuperReference((int)(identifierPositionStack[identifierPtr+1] >>> 32), (int) identifierPositionStack[identifierPtr+1]);
+ }
+ pushOnAstStack(reference);
+ this.assistNode = reference;
+ this.lastCheckPoint = reference.sourceEnd + 1;
+ restartRecovery = true; // force to restart in recovery mode
+ isOrphanCompletionNode = true;
+ return new SingleNameReference(new char[0], 0); // dummy reference
+ }
+ NameReference nameReference;
+ /* retrieve identifiers subset and whole positions, the completion node positions
+ should include the entire replaced source. */
+ char[][] subset = identifierSubSet(completionIndex);
+ identifierLengthPtr--;
+ identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(
+ identifierPositionStack,
+ identifierPtr + 1,
+ positions,
+ 0,
+ length);
+ /* build specific completion on name reference */
+ if (completionIndex == 0) {
+ /* completion inside first identifier */
+ nameReference = this.createSingleAssistNameReference(assistIdentifier(), positions[0]);
+ } else {
+ /* completion inside subsequent identifier */
+ nameReference = this.createQualifiedAssistNameReference(subset, assistIdentifier(), positions);
+ }
+ assistNode = nameReference;
+ this.lastCheckPoint = nameReference.sourceEnd + 1;
+ isOrphanCompletionNode = true;
+ restartRecovery = true; // force to restart into recovery mode
+ return nameReference;
+}
+/*
+ * Copy of code from superclass with the following change:
+ * In the case of qualified name reference if the cursor location is on the
+ * qualified name reference, then create a CompletionOnQualifiedNameReference
+ * instead.
+ */
+protected NameReference getUnspecifiedReferenceOptimized() {
+
+ int index = indexOfAssistIdentifier();
+ NameReference reference = super.getUnspecifiedReferenceOptimized();
+
+ if (index >= 0){
+ restartRecovery = true; // force to stop and restart in recovery mode
+ isOrphanCompletionNode = true;
+ }
+ return reference;
+}
+public void initializeScanner(){
+ this.scanner = new SelectionScanner();
+}
+protected MessageSend newMessageSend() {
+ // '(' ArgumentListopt ')'
+ // the arguments are on the expression stack
+
+ char[] selector = identifierStack[identifierPtr];
+ if (selector != this.assistIdentifier()){
+ return super.newMessageSend();
+ }
+ MessageSend messageSend = new SelectionOnMessageSend();
+ int length;
+ if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+ expressionPtr -= length;
+ System.arraycopy(
+ expressionStack,
+ expressionPtr + 1,
+ messageSend.arguments = new Expression[length],
+ 0,
+ length);
+ };
+ assistNode = messageSend;
+ restartRecovery = true; // force to restart in recovery mode
+ isOrphanCompletionNode = true;
+ return messageSend;
+}
+public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int selectionStart, int selectionEnd) {
+
+ this.selectionStart = selectionStart;
+ this.selectionEnd = selectionEnd;
+ SelectionScanner selectionScanner = (SelectionScanner)this.scanner;
+ selectionScanner.selectionIdentifier = null;
+ selectionScanner.selectionStart = selectionStart;
+ selectionScanner.selectionEnd = selectionEnd;
+ return this.parse(sourceUnit, compilationResult);
+}
+/*
+ * Reset context so as to resume to regular parse loop
+ * If unable to reset for resuming, answers false.
+ *
+ * Move checkpoint location, reset internal stacks and
+ * decide which grammar goal is activated.
+ */
+protected boolean resumeAfterRecovery() {
+
+ /* if reached assist node inside method body, but still inside nested type,
+ should continue in diet mode until the end of the method body */
+ if (this.assistNode != null
+ && !(referenceContext instanceof CompilationUnitDeclaration)){
+ currentElement.preserveEnclosingBlocks();
+ if (currentElement.enclosingType() == null){
+ this.resetStacks();
+ return false;
+ }
+ }
+ return super.resumeAfterRecovery();
+}
+public void setAssistIdentifier(char[] assistIdent){
+ ((SelectionScanner)scanner).selectionIdentifier = assistIdent;
+}
+/*
+ * Update recovery state based on current parser/scanner state
+ */
+protected void updateRecoveryState() {
+
+ /* expose parser state to recovery state */
+ currentElement.updateFromParserState();
+
+ /* may be able to retrieve completionNode as an orphan, and then attach it */
+ this.attachOrphanCompletionNode();
+
+ /* check and update recovered state based on current token,
+ this action is also performed when shifting token after recovery
+ got activated once.
+ */
+ this.recoveryTokenCheck();
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index 5c055b1..8e29f7f 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -1,2440 +1,2438 @@
-package org.eclipse.jdt.internal.compiler;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-/**
- * Represents a class file wrapper on bytes, it is aware of its actual
- * type name.
- *
- * Public APIs are listed below:
- *
- * byte[] getBytes();
- * Answer the actual bytes of the class file
- *
- * char[][] getCompoundName();
- * Answer the compound name of the class file.
- * For example, {{java}, {util}, {Hashtable}}.
- *
- * byte[] getReducedBytes();
- * Answer a smaller byte format, which is only contains some structural
- * information. Those bytes are decodable with a regular class file reader,
- * such as DietClassFileReader
- */
-
-import java.io.*;
-import java.util.*;
-import org.eclipse.jdt.internal.compiler.Compiler;
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.compiler.util.*;
-
-
-public class ClassFile implements AttributeNamesConstants, CompilerModifiers, TypeConstants, TypeIds {
- public SourceTypeBinding referenceBinding;
- public ConstantPool constantPool;
- public ClassFile enclosingClassFile; // used to generate private access methods
- public int produceDebugAttributes;
- public ReferenceBinding[] innerClassesBindings;
- public int numberOfInnerClasses;
- public byte[] header; // the header contains all the bytes till the end of the constant pool
- public byte[] contents; // that collection contains all the remaining bytes of the .class file
- public int headerOffset;
- public int contentsOffset;
- public int constantPoolOffset;
- public int methodCountOffset;
- public int methodCount;
- protected boolean creatingProblemType;
- public static final int INITIAL_CONTENTS_SIZE = 1000;
- public static final int INITIAL_HEADER_SIZE = 1000;
- public static final int INCREMENT_SIZE = 1000;
- public static final int INNER_CLASSES_SIZE = 5;
- protected CharArrayCache nameUsage;
- public CodeStream codeStream;
- protected int problemLine; // used to create line number attributes for problem methods
-/**
- * INTERNAL USE-ONLY
- * This methods creates a new instance of the receiver.
- */
-public ClassFile() {}
-/**
- * INTERNAL USE-ONLY
- * This methods creates a new instance of the receiver.
- *
- * @param aType org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding
- * @param enclosingClassFile org.eclipse.jdt.internal.compiler.ClassFile
- * @param creatingProblemType <CODE>boolean</CODE>
- */
-public ClassFile(SourceTypeBinding aType, ClassFile enclosingClassFile, boolean creatingProblemType) {
- referenceBinding = aType;
- header = new byte[INITIAL_HEADER_SIZE];
- // generate the magic numbers inside the header
- header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
- header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
- header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
- header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
- if (((SourceTypeBinding) referenceBinding).scope.environment().options.targetJDK == CompilerOptions.JDK1_2) {
- // Compatible with JDK 1.2
- header[headerOffset++] = 0; // minorVersion = 0 means we just need to offset the current offset by 2
- header[headerOffset++] = 0;
- header[headerOffset++] = 0;
- header[headerOffset++] = 46;
- } else {
- // Compatible with JDK 1.1
- header[headerOffset++] = 0;
- header[headerOffset++] = 3;
- header[headerOffset++] = 0;
- header[headerOffset++] = 45;
- }
- constantPoolOffset = headerOffset;
- headerOffset += 2;
- constantPool = new ConstantPool(this);
-
- int accessFlags = aType.getAccessFlags();
- if (aType.isProtected()) {
- // set Acc_Public
- accessFlags |= AccPublic;
- }
- // clear all bits that are illegal for a class or an interface
- accessFlags
- &= ~(
- AccStrictfp
- | AccProtected
- | AccPrivate
- | AccStatic
- | AccSynchronized
- | AccNative);
-
- // set the AccSuper flag (has to be done after clearing AccSynchronized - since same value)
- accessFlags |= AccSuper;
-
- this.enclosingClassFile = enclosingClassFile;
- // innerclasses get their names computed at code gen time
- if (aType.isLocalType()) {
- ((LocalTypeBinding) aType).constantPoolName(computeConstantPoolName((LocalTypeBinding) aType));
- ReferenceBinding[] memberTypes = aType.memberTypes();
- for (int i = 0, max = memberTypes.length; i < max; i++) {
- ((LocalTypeBinding) memberTypes[i]).constantPoolName(computeConstantPoolName((LocalTypeBinding) memberTypes[i]));
- }
- }
- contents = new byte[INITIAL_CONTENTS_SIZE];
- // now we continue to generate the bytes inside the contents array
- contents[contentsOffset++] = (byte) (accessFlags >> 8);
- contents[contentsOffset++] = (byte) accessFlags;
- int classNameIndex = constantPool.literalIndex(aType);
- contents[contentsOffset++] = (byte) (classNameIndex >> 8);
- contents[contentsOffset++] = (byte) classNameIndex;
- int superclassNameIndex;
- if (aType.isInterface()) {
- superclassNameIndex = constantPool.literalIndexForJavaLangObject();
- } else {
- superclassNameIndex = (aType.superclass == null ? 0 : constantPool.literalIndex(aType.superclass));
- }
- contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
- contents[contentsOffset++] = (byte) superclassNameIndex;
- ReferenceBinding[] superInterfacesBinding = aType.superInterfaces();
- int interfacesCount = superInterfacesBinding.length;
- contents[contentsOffset++] = (byte) (interfacesCount >> 8);
- contents[contentsOffset++] = (byte) interfacesCount;
- if (superInterfacesBinding != null) {
- for (int i = 0; i < interfacesCount; i++) {
- int interfaceIndex = constantPool.literalIndex(superInterfacesBinding[i]);
- contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
- contents[contentsOffset++] = (byte) interfaceIndex;
- }
- }
- produceDebugAttributes = ((SourceTypeBinding) referenceBinding).scope.environment().options.produceDebugAttributes;
- innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE];
- this.creatingProblemType = creatingProblemType;
- codeStream = new CodeStream(this);
-
- // retrieve the enclosing one guaranteed to be the one matching the propagated flow info
- // 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
- ClassFile outermostClassFile = this.outerMostEnclosingClassFile();
- if (this == outermostClassFile) {
- codeStream.maxFieldCount = aType.scope.referenceType().maxFieldCount;
- } else {
- codeStream.maxFieldCount = outermostClassFile.codeStream.maxFieldCount;
- }
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a boggus method.
- *
- * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
- */
-public void addAbstractMethod(
- AbstractMethodDeclaration method,
- MethodBinding methodBinding) {
-
- // force the modifiers to be public and abstract
- methodBinding.modifiers = AccPublic | AccAbstract;
-
- this.generateMethodInfoHeader(methodBinding);
- int methodAttributeOffset = this.contentsOffset;
- int attributeNumber = this.generateMethodInfoAttribute(methodBinding);
- this.completeMethodInfo(methodAttributeOffset, attributeNumber);
-}
-/**
- * INTERNAL USE-ONLY
- * This methods generate all the attributes for the receiver.
- * For a class they could be:
- * - source file attribute
- * - inner classes attribute
- * - deprecated attribute
- */
-public void addAttributes() {
- // update the method count
- contents[methodCountOffset++] = (byte) (methodCount >> 8);
- contents[methodCountOffset] = (byte) methodCount;
-
- int attributeNumber = 0;
- // leave two bytes for the number of attributes and store the current offset
- int attributeOffset = contentsOffset;
- contentsOffset += 2;
- int contentsLength;
-
- // source attribute
- if ((produceDebugAttributes & CompilerOptions.Source) != 0) {
- String fullFileName = new String(referenceBinding.scope.referenceCompilationUnit().getFileName());
- fullFileName = fullFileName.replace('\\', '/');
- int lastIndex = fullFileName.lastIndexOf('/');
- if (lastIndex != -1) {
- fullFileName = fullFileName.substring(lastIndex + 1, fullFileName.length());
- }
- // check that there is enough space to write all the bytes for the field info corresponding
- // to the @fieldBinding
- if (contentsOffset + 8 >= (contentsLength = contents.length)) {
- System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- int sourceAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SourceName);
- contents[contentsOffset++] = (byte) (sourceAttributeNameIndex >> 8);
- contents[contentsOffset++] = (byte) sourceAttributeNameIndex;
- // The length of a source file attribute is 2. This is a fixed-length
- // attribute
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 2;
- // write the source file name
- int fileNameIndex = constantPool.literalIndex(fullFileName.toCharArray());
- contents[contentsOffset++] = (byte) (fileNameIndex >> 8);
- contents[contentsOffset++] = (byte) fileNameIndex;
- attributeNumber++;
- }
-
- // Deprecated attribute
- if (referenceBinding.isDeprecated()) {
- // check that there is enough space to write all the bytes for the field info corresponding
- // to the @fieldBinding
- if (contentsOffset + 6 >= (contentsLength = contents.length)) {
- System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- int deprecatedAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
- contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
- contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
- // the length of a deprecated attribute is equals to 0
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- attributeNumber++;
- }
-
- // Inner class attribute
- if (numberOfInnerClasses != 0) {
- // Generate the inner class attribute
- int exSize;
- if (contentsOffset + (exSize = (8 * numberOfInnerClasses + 8)) >= (contentsLength = contents.length)) {
- System.arraycopy(contents, 0, (contents = new byte[contentsLength + (exSize >= INCREMENT_SIZE ? exSize : INCREMENT_SIZE)]), 0, contentsLength);
- }
- // Now we now the size of the attribute and the number of entries
- // attribute name
- int attributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.InnerClassName);
- contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
- contents[contentsOffset++] = (byte) attributeNameIndex;
- int value = (numberOfInnerClasses << 3) + 2;
- contents[contentsOffset++] = (byte) (value >> 24);
- contents[contentsOffset++] = (byte) (value >> 16);
- contents[contentsOffset++] = (byte) (value >> 8);
- contents[contentsOffset++] = (byte) value;
- contents[contentsOffset++] = (byte) (numberOfInnerClasses >> 8);
- contents[contentsOffset++] = (byte) numberOfInnerClasses;
- for (int i = 0; i < numberOfInnerClasses; i++) {
- ReferenceBinding innerClass = innerClassesBindings[i];
- int accessFlags = innerClass.getAccessFlags();
- int innerClassIndex = constantPool.literalIndex(innerClass);
- // inner class index
- contents[contentsOffset++] = (byte) (innerClassIndex >> 8);
- contents[contentsOffset++] = (byte) innerClassIndex;
- // outer class index: anonymous and local have no outer class index
- if (innerClass.isMemberType()) {
- // member or member of local
- int outerClassIndex = constantPool.literalIndex(innerClass.enclosingType());
- contents[contentsOffset++] = (byte) (outerClassIndex >> 8);
- contents[contentsOffset++] = (byte) outerClassIndex;
- } else {
- // equals to 0 if the innerClass is not a member type
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- }
- // name index
- if (!innerClass.isAnonymousType()) {
- int nameIndex = constantPool.literalIndex(innerClass.sourceName());
- contents[contentsOffset++] = (byte) (nameIndex >> 8);
- contents[contentsOffset++] = (byte) nameIndex;
- } else {
- // equals to 0 if the innerClass is an anonymous type
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- }
- // access flag
- if (innerClass.isAnonymousType()) {
- accessFlags |= AccPrivate;
- } else
- if (innerClass.isLocalType() && !innerClass.isMemberType()) {
- accessFlags |= AccPrivate;
- }
- contents[contentsOffset++] = (byte) (accessFlags >> 8);
- contents[contentsOffset++] = (byte) accessFlags;
- }
- attributeNumber++;
- }
- // update the number of attributes
- if (attributeOffset + 2 >= (contentsLength = contents.length)) {
- System.arraycopy(
- contents,
- 0,
- (contents = new byte[contentsLength + INCREMENT_SIZE]),
- 0,
- contentsLength);
- }
- contents[attributeOffset++] = (byte) (attributeNumber >> 8);
- contents[attributeOffset] = (byte) attributeNumber;
-
- // resynchronize all offsets of the classfile
- header = constantPool.poolContent;
- headerOffset = constantPool.currentOffset;
- int constantPoolCount = constantPool.currentIndex;
- header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
- header[constantPoolOffset] = (byte) constantPoolCount;
-}
-/**
- * INTERNAL USE-ONLY
- * This methods generate all the default abstract method infos that correpond to
- * the abstract methods inherited from superinterfaces.
- */
-public void addDefaultAbstractMethods() { // default abstract methods
- MethodBinding[] defaultAbstractMethods = referenceBinding.getDefaultAbstractMethods();
- for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
- generateMethodInfoHeader(defaultAbstractMethods[i]);
- int methodAttributeOffset = contentsOffset;
- int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
- completeMethodInfo(methodAttributeOffset, attributeNumber);
- }
-}
-/**
- * INTERNAL USE-ONLY
- * This methods generates the bytes for the field binding passed like a parameter
- * @param fieldBinding org.eclipse.jdt.internal.compiler.lookup.FieldBinding
- */
-public void addFieldInfo(FieldBinding fieldBinding) {
- int attributeNumber = 0;
- // check that there is enough space to write all the bytes for the field info corresponding
- // to the @fieldBinding
- int contentsLength;
- if (contentsOffset + 30 >= (contentsLength = contents.length)) {
- System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- // Generate two attribute: constantValueAttribute and SyntheticAttribute
- // Now we can generate all entries into the byte array
- // First the accessFlags
- int accessFlags = fieldBinding.getAccessFlags();
- contents[contentsOffset++] = (byte) (accessFlags >> 8);
- contents[contentsOffset++] = (byte) accessFlags;
- // Then the nameIndex
- int nameIndex = constantPool.literalIndex(fieldBinding.name);
- contents[contentsOffset++] = (byte) (nameIndex >> 8);
- contents[contentsOffset++] = (byte) nameIndex;
- // Then the descriptorIndex
- int descriptorIndex = constantPool.literalIndex(fieldBinding.type.signature());
- contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
- contents[contentsOffset++] = (byte) descriptorIndex;
- // leave some space for the number of attributes
- int fieldAttributeOffset = contentsOffset;
- contentsOffset += 2;
- // 4.7.2 only static constant fields get a ConstantAttribute
- if (fieldBinding.isStatic()
- && fieldBinding.constant != Constant.NotAConstant
- && fieldBinding.constant.typeID() != T_null) {
- // Now we generate the constant attribute corresponding to the fieldBinding
- int constantValueNameIndex = constantPool.literalIndex(AttributeNamesConstants.ConstantValueName);
- contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
- contents[contentsOffset++] = (byte) constantValueNameIndex;
- // The attribute length = 2 in case of a constantValue attribute
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 2;
- attributeNumber++;
- // Need to add the constant_value_index
- switch (fieldBinding.constant.typeID()) {
- case T_boolean :
- int booleanValueIndex = constantPool.literalIndex(fieldBinding.constant.booleanValue() ? 1 : 0);
- contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
- contents[contentsOffset++] = (byte) booleanValueIndex;
- break;
- case T_byte :
- case T_char :
- case T_int :
- case T_short :
- int integerValueIndex = constantPool.literalIndex(fieldBinding.constant.intValue());
- contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
- contents[contentsOffset++] = (byte) integerValueIndex;
- break;
- case T_float :
- int floatValueIndex = constantPool.literalIndex(fieldBinding.constant.floatValue());
- contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
- contents[contentsOffset++] = (byte) floatValueIndex;
- break;
- case T_double :
- int doubleValueIndex = constantPool.literalIndex(fieldBinding.constant.doubleValue());
- contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
- contents[contentsOffset++] = (byte) doubleValueIndex;
- break;
- case T_long :
- int longValueIndex = constantPool.literalIndex(fieldBinding.constant.longValue());
- contents[contentsOffset++] = (byte) (longValueIndex >> 8);
- contents[contentsOffset++] = (byte) longValueIndex;
- break;
- case T_String :
- int stringValueIndex = constantPool.literalIndex(((StringConstant) fieldBinding.constant).stringValue());
- if (stringValueIndex == -1) {
- if (!creatingProblemType) {
- // report an error and abort: will lead to a problem type classfile creation
- TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
- FieldDeclaration[] fieldDecls = typeDeclaration.fields;
- for (int i = 0, max = fieldDecls.length; i < max; i++) {
- if (fieldDecls[i].binding == fieldBinding) {
- // problem should abort
- typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(fieldDecls[i]);
- }
- }
- } else {
- // already inside a problem type creation : no constant for this field
- contentsOffset = fieldAttributeOffset + 2; // +2 is necessary to keep the two byte space for the attribute number
- attributeNumber--;
- }
- } else {
- contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
- contents[contentsOffset++] = (byte) stringValueIndex;
- }
- }
- }
- if (fieldBinding.isSynthetic()) {
- int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
- contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
- contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
- // the length of a synthetic attribute is equals to 0
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- attributeNumber++;
- }
- if (fieldBinding.isDeprecated()) {
- int deprecatedAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
- contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
- contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
- // the length of a deprecated attribute is equals to 0
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- attributeNumber++;
- }
- contents[fieldAttributeOffset++] = (byte) (attributeNumber >> 8);
- contents[fieldAttributeOffset] = (byte) attributeNumber;
-}
-/**
- * INTERNAL USE-ONLY
- * This methods generate all the fields infos for the receiver.
- * This includes:
- * - a field info for each defined field of that class
- * - a field info for each synthetic field (e.g. this$0)
- */
-public void addFieldInfos() {
- SourceTypeBinding currentBinding = referenceBinding;
- FieldBinding[] syntheticFields = currentBinding.syntheticFields();
- int fieldCount = currentBinding.fieldCount() + (syntheticFields == null ? 0 : syntheticFields.length);
-
- // write the number of fields
- contents[contentsOffset++] = (byte) (fieldCount >> 8);
- contents[contentsOffset++] = (byte) fieldCount;
-
- FieldBinding[] fieldBindings = currentBinding.fields();
- for (int i = 0, max = fieldBindings.length; i < max; i++) {
- addFieldInfo(fieldBindings[i]);
- }
- if (syntheticFields != null) {
- for (int i = 0, max = syntheticFields.length; i < max; i++) {
- addFieldInfo(syntheticFields[i]);
- }
- }
-}
-/**
- * INTERNAL USE-ONLY
- * This methods stores the bindings for each inner class. They will be used to know which entries
- * have to be generated for the inner classes attributes.
- * @param referenceBinding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
- */
-public void addInnerClasses(ReferenceBinding referenceBinding) {
- // check first if that reference binding is there
- for (int i = 0; i < numberOfInnerClasses; i++) {
- if (innerClassesBindings[i] == referenceBinding)
- return;
- }
- int length = innerClassesBindings.length;
- if (numberOfInnerClasses == length) {
- System.arraycopy(innerClassesBindings, 0, (innerClassesBindings = new ReferenceBinding[length * 2]), 0, length);
- }
- innerClassesBindings[numberOfInnerClasses++] = referenceBinding;
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem clinit method info that correspond to a boggus method.
- *
- * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
- */
-public void addProblemClinit(IProblem[] problems) {
- generateMethodInfoHeaderForClinit();
- // leave two spaces for the number of attributes
- contentsOffset -= 2;
- int attributeOffset = contentsOffset;
- contentsOffset += 2;
- ReferenceBinding[] thrownsExceptions;
- int attributeNumber = 0;
- int contentsLength;
-
- int codeAttributeOffset = contentsOffset;
- generateCodeAttributeHeader();
- codeStream.resetForProblemClinit(this);
- String problemString = ""/*nonNLS*/;
- if (problems != null) {
- int max = problems.length;
- StringBuffer buffer = new StringBuffer(25);
- int count = 0;
- for (int i = 0; i < max; i++) {
- IProblem problem = problems[i];
- if ((problem != null) && (problem.isError())) {
- buffer.append("\t"/*nonNLS*/ + problem.getMessage() + "\n"/*nonNLS*/);
- count++;
- if (problemLine == 0) {
- problemLine = problem.getSourceLineNumber();
- }
- problems[i] = null;
- }
- } // insert the top line afterwards, once knowing how many problems we have to consider
- if (count > 1) {
- buffer.insert(0, Util.bind("compilation.unresolvedProblems"/*nonNLS*/));
- } else {
- buffer.insert(0, Util.bind("compilation.unresolvedProblem"/*nonNLS*/));
- }
- problemString = buffer.toString();
- }
-
- // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
- int[] exceptionHandler = codeStream.generateCodeAttributeForProblemMethod(referenceBinding.scope.problemReporter().options.runtimeExceptionNameForCompileError, problemString);
- attributeNumber++; // code attribute
- completeCodeAttributeForClinit(
- codeAttributeOffset,
- exceptionHandler,
- referenceBinding
- .scope
- .referenceCompilationUnit()
- .compilationResult
- .lineSeparatorPositions);
- contents[attributeOffset++] = (byte) (attributeNumber >> 8);
- contents[attributeOffset] = (byte) attributeNumber;
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a boggus constructor.
- *
- * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
- * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
- */
-public void addProblemConstructor(
- AbstractMethodDeclaration method,
- MethodBinding methodBinding,
- IProblem[] problems) {
-
- // always clear the strictfp/native/abstract bit for a problem method
- methodBinding.modifiers &= ~(AccStrictfp | AccNative | AccAbstract);
-
- generateMethodInfoHeader(methodBinding);
- // We know that we won't get more than 1 attribute: the code attribute
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 1; // Code attribute
- int codeAttributeOffset = contentsOffset;
- generateCodeAttributeHeader();
- final ProblemReporter problemReporter = method.scope.problemReporter();
- codeStream.reset(method, this);
- String problemString = ""/*nonNLS*/;
- if (problems != null) {
- int max = problems.length;
- StringBuffer buffer = new StringBuffer(25);
- int count = 0;
- for (int i = 0; i < max; i++) {
- IProblem problem = problems[i];
- if ((problem != null) && (problem.isError())) {
- buffer.append("\t"/*nonNLS*/ + problem.getMessage() + "\n"/*nonNLS*/);
- count++;
- if (problemLine == 0) {
- problemLine = problem.getSourceLineNumber();
- }
- }
- } // insert the top line afterwards, once knowing how many problems we have to consider
- if (count > 1) {
- buffer.insert(0, Util.bind("compilation.unresolvedProblems"/*nonNLS*/));
- } else {
- buffer.insert(0, Util.bind("compilation.unresolvedProblem"/*nonNLS*/));
- }
- problemString = buffer.toString();
- }
-
- // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
- int[] exceptionHandler =
- codeStream.generateCodeAttributeForProblemMethod(
- problemReporter.options.runtimeExceptionNameForCompileError,
- problemString);
- completeCodeAttributeForProblemMethod(
- method,
- methodBinding,
- codeAttributeOffset,
- exceptionHandler,
- ((SourceTypeBinding) methodBinding.declaringClass)
- .scope
- .referenceCompilationUnit()
- .compilationResult
- .lineSeparatorPositions);
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a boggus constructor.
- * Reset the position inside the contents byte array to the savedOffset.
- *
- * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
- * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
- * @param savedOffset <CODE>int</CODE>
- */
-public void addProblemConstructor(AbstractMethodDeclaration method, MethodBinding methodBinding,IProblem[] problems, int savedOffset) {
- // we need to move back the contentsOffset to the value at the beginning of the method
- contentsOffset = savedOffset;
- methodCount--; // we need to remove the method that causes the problem
- addProblemConstructor(method, methodBinding, problems);
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a boggus method.
- *
- * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
- * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
- */
-public void addProblemMethod(
- AbstractMethodDeclaration method,
- MethodBinding methodBinding,
- IProblem[] problems) {
- if (methodBinding.isAbstract() && methodBinding.declaringClass.isInterface()) {
- method.abort(AbstractMethodDeclaration.AbortType);
- }
- // always clear the strictfp/native/abstract bit for a problem method
- methodBinding.modifiers &= ~(AccStrictfp | AccNative | AccAbstract);
-
- generateMethodInfoHeader(methodBinding);
- // leave two spaces for the number of attributes
- int attributeOffset = contentsOffset;
- contentsOffset += 2;
- ReferenceBinding[] thrownsExceptions;
- int attributeNumber = 0;
- int contentsLength;
-
- if ((thrownsExceptions = methodBinding.thrownExceptions) != NoExceptions) {
- // The method has a throw clause. So we need to add an exception attribute
- // check that there is enough space to write all the bytes for the exception attribute
- int length = thrownsExceptions.length;
- if (contentsOffset + (8 + length * 2) >= (contentsLength = contents.length)) {
- System.arraycopy(contents, 0, (contents = new byte[contentsLength + Math.max(INCREMENT_SIZE, (8 + length * 2))]), 0, contentsLength);
- }
- int exceptionNameIndex = constantPool.literalIndex(AttributeNamesConstants.ExceptionsName);
- contents[contentsOffset++] = (byte) (exceptionNameIndex >> 8);
- contents[contentsOffset++] = (byte) exceptionNameIndex;
- // The attribute length = length * 2 + 2 in case of a exception attribute
- int attributeLength = length * 2 + 2;
- contents[contentsOffset++] = (byte) (attributeLength >> 24);
- contents[contentsOffset++] = (byte) (attributeLength >> 16);
- contents[contentsOffset++] = (byte) (attributeLength >> 8);
- contents[contentsOffset++] = (byte) attributeLength;
- contents[contentsOffset++] = (byte) (length >> 8);
- contents[contentsOffset++] = (byte) length;
- for (int i = 0; i < length; i++) {
- int exceptionIndex = constantPool.literalIndex(thrownsExceptions[i]);
- contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
- contents[contentsOffset++] = (byte) exceptionIndex;
- }
- attributeNumber++;
- }
-
- // Deprecated attribute
- // Check that there is enough space to write the deprecated attribute
- if (contentsOffset + 6 >= (contentsLength = contents.length)) {
- System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- if (methodBinding.isDeprecated()) {
- int deprecatedAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
- contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
- contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
- // the length of a deprecated attribute is equals to 0
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
-
- attributeNumber++;
- }
-
- int codeAttributeOffset = contentsOffset;
- generateCodeAttributeHeader();
- final ProblemReporter problemReporter = method.scope.problemReporter();
- codeStream.reset(method, this);
- String problemString = ""/*nonNLS*/;
- if (problems != null) {
- int max = problems.length;
- StringBuffer buffer = new StringBuffer(25);
- int count = 0;
- for (int i = 0; i < max; i++) {
- IProblem problem = problems[i];
- if ((problem != null)
- && (problem.isError())
- && (problem.getSourceStart() >= method.declarationSourceStart)
- && (problem.getSourceEnd() <= method.declarationSourceEnd)) {
- buffer.append("\t"/*nonNLS*/ + problem.getMessage() + "\n"/*nonNLS*/);
- count++;
- if (problemLine == 0) {
- problemLine = problem.getSourceLineNumber();
- }
- problems[i] = null;
- }
- } // insert the top line afterwards, once knowing how many problems we have to consider
- if (count > 1) {
- buffer.insert(0, Util.bind("compilation.unresolvedProblems"/*nonNLS*/));
- } else {
- buffer.insert(0, Util.bind("compilation.unresolvedProblem"/*nonNLS*/));
- }
- problemString = buffer.toString();
- }
-
- // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
- int[] exceptionHandler =
- codeStream.generateCodeAttributeForProblemMethod(
- problemReporter.options.runtimeExceptionNameForCompileError,
- problemString);
- attributeNumber++; // code attribute
- completeCodeAttributeForProblemMethod(
- method,
- methodBinding,
- codeAttributeOffset,
- exceptionHandler,
- ((SourceTypeBinding) methodBinding.declaringClass)
- .scope
- .referenceCompilationUnit()
- .compilationResult
- .lineSeparatorPositions);
- contents[attributeOffset++] = (byte) (attributeNumber >> 8);
- contents[attributeOffset] = (byte) attributeNumber;
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a boggus method.
- * Reset the position inside the contents byte array to the savedOffset.
- *
- * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
- * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
- * @param savedOffset <CODE>int</CODE>
- */
-public void addProblemMethod(AbstractMethodDeclaration method, MethodBinding methodBinding,IProblem[] problems, int savedOffset) {
- // we need to move back the contentsOffset to the value at the beginning of the method
- contentsOffset = savedOffset;
- methodCount--; // we need to remove the method that causes the problem
- addProblemMethod(method, methodBinding, problems);
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for all the special method infos.
- * They are:
- * - synthetic access methods
- * - default abstract methods
- */
-public void addSpecialMethods() {
- // add all methods (default abstract methods and synthetic)
-
- // default abstract methods
- SourceTypeBinding currentBinding = referenceBinding;
- MethodBinding[] defaultAbstractMethods = currentBinding.getDefaultAbstractMethods();
- for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
- generateMethodInfoHeader(defaultAbstractMethods[i]);
- int methodAttributeOffset = contentsOffset;
- int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
- completeMethodInfo(methodAttributeOffset, attributeNumber);
- }
-
- // add synthetic methods infos
- SyntheticAccessMethodBinding[] syntheticAccessMethods = currentBinding.syntheticAccessMethods();
- if (syntheticAccessMethods != null) {
- for (int i = 0, max = syntheticAccessMethods.length; i < max; i++) {
- SyntheticAccessMethodBinding accessMethodBinding = syntheticAccessMethods[i];
- switch (accessMethodBinding.accessType) {
- case SyntheticAccessMethodBinding.FieldReadAccess :
- // generate a method info to emulate an reading access to
- // a private field
- addSyntheticFieldReadAccessMethod(syntheticAccessMethods[i]);
- break;
- case SyntheticAccessMethodBinding.FieldWriteAccess :
- // generate a method info to emulate an writing access to
- // a private field
- addSyntheticFieldWriteAccessMethod(syntheticAccessMethods[i]);
- break;
- case SyntheticAccessMethodBinding.MethodAccess :
- // generate a method info to emulate an access to a private method
- addSyntheticMethodAccessMethod(syntheticAccessMethods[i]);
- break;
- case SyntheticAccessMethodBinding.ConstructorAccess :
- // generate a method info to emulate an access to a private method
- addSyntheticConstructorAccessMethod(syntheticAccessMethods[i]);
- }
- }
- }
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a synthetic method that
- * generate an access to a private constructor.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
- */
-public void addSyntheticConstructorAccessMethod(SyntheticAccessMethodBinding methodBinding) {
- generateMethodInfoHeader(methodBinding);
- // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 2;
- // Code attribute
- int codeAttributeOffset = contentsOffset;
- generateCodeAttributeHeader();
- codeStream.init(this);
- codeStream.generateSyntheticBodyForConstructorAccess(methodBinding);
- completeCodeAttributeForSyntheticAccessMethod(methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass).scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions);
- // add the synthetic attribute
- int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
- contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
- contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
- // the length of a synthetic attribute is equals to 0
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a synthetic method that
- * generate an read access to a private field.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
- */
-public void addSyntheticFieldReadAccessMethod(SyntheticAccessMethodBinding methodBinding) {
- generateMethodInfoHeader(methodBinding);
- // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 2;
- // Code attribute
- int codeAttributeOffset = contentsOffset;
- generateCodeAttributeHeader();
- codeStream.init(this);
- codeStream.generateSyntheticBodyForFieldReadAccess(methodBinding);
- completeCodeAttributeForSyntheticAccessMethod(methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass).scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions);
- // add the synthetic attribute
- int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
- contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
- contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
- // the length of a synthetic attribute is equals to 0
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a synthetic method that
- * generate an write access to a private field.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
- */
-public void addSyntheticFieldWriteAccessMethod(SyntheticAccessMethodBinding methodBinding) {
- generateMethodInfoHeader(methodBinding);
- // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 2;
- // Code attribute
- int codeAttributeOffset = contentsOffset;
- generateCodeAttributeHeader();
- codeStream.init(this);
- codeStream.generateSyntheticBodyForFieldWriteAccess(methodBinding);
- completeCodeAttributeForSyntheticAccessMethod(methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass).scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions);
- // add the synthetic attribute
- int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
- contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
- contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
- // the length of a synthetic attribute is equals to 0
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a synthetic method that
- * generate an access to a private method.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
- */
-public void addSyntheticMethodAccessMethod(SyntheticAccessMethodBinding methodBinding) {
- generateMethodInfoHeader(methodBinding);
- // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 2;
- // Code attribute
- int codeAttributeOffset = contentsOffset;
- generateCodeAttributeHeader();
- codeStream.init(this);
- codeStream.generateSyntheticBodyForMethodAccess(methodBinding);
- completeCodeAttributeForSyntheticAccessMethod(methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass).scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions);
- // add the synthetic attribute
- int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
- contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
- contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
- // the length of a synthetic attribute is equals to 0
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
-}
-/**
- * INTERNAL USE-ONLY
- * Build all the directories and subdirectories corresponding to the packages names
- * into the directory specified in parameters.
- *
- * outputPath is formed like:
- * c:\temp\ the last character is a file separator
- * relativeFileName is formed like:
- * java\lang\String.class *
- *
- * @param outputPath java.lang.String
- * @param relativeFileName java.lang.String
- * @return java.lang.String
- */
-public static String buildAllDirectoriesInto(String outputPath, String relativeFileName) throws IOException {
- char fileSeparatorChar = File.separatorChar;
- String fileSeparator = File.separator;
- File f;
- // First we ensure that the outputPath exists
- outputPath = outputPath.replace('/', fileSeparatorChar);
- // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
- if (outputPath.endsWith(fileSeparator)) {
- outputPath = outputPath.substring(0, outputPath.length() - 1);
- }
- f = new File(outputPath);
- if (f.exists()) {
- if (!f.isDirectory()) {
- System.out.println(Util.bind("output.isFile"/*nonNLS*/,f.getAbsolutePath()));
- throw new IOException(Util.bind("output.isFileNotDirectory"/*nonNLS*/));
- }
- } else {
- // we have to create that directory
- if (!f.mkdirs()) {
- System.out.println(Util.bind("output.dirName"/*nonNLS*/,f.getAbsolutePath()));
- throw new IOException(Util.bind("output.notValidAll"/*nonNLS*/));
- }
- }
- StringBuffer outDir = new StringBuffer(outputPath);
- outDir.append(fileSeparator);
- StringTokenizer tokenizer = new StringTokenizer(relativeFileName, fileSeparator);
- String token = tokenizer.nextToken();
- while (tokenizer.hasMoreTokens()) {
- f = new File(outDir.append(token).append(fileSeparator).toString());
- if (f.exists()) {
- // The outDir already exists, so we proceed the next entry
- // System.out.println("outDir: " + outDir + " already exists.");
- } else {
- // Need to add the outDir
- if (!f.mkdir()) {
- System.out.println(Util.bind("output.fileName"/*nonNLS*/,f.getName()));
- throw new IOException(Util.bind("output.notValid"/*nonNLS*/));
- }
- }
- token = tokenizer.nextToken();
- }
- // token contains the last one
- return outDir.append(token).toString();
-}
-/**
- * INTERNAL USE-ONLY
- * That method completes the creation of the code attribute by setting
- * - the attribute_length
- * - max_stack
- * - max_locals
- * - code_length
- * - exception table
- * - and debug attributes if necessary.
- *
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param codeAttributeOffset <CODE>int</CODE>
- */
-public void completeCodeAttribute(int codeAttributeOffset) {
- // reinitialize the localContents with the byte modified by the code stream
- byte[] localContents = contents = codeStream.bCodeStream;
- int localContentsOffset = codeStream.classFileOffset;
- // codeAttributeOffset is the position inside localContents byte array before we started to write
- // any information about the codeAttribute
- // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
- // to get the right position, 6 for the max_stack etc...
- int contentsLength;
- int code_length = codeStream.position;
- if (code_length > 65535) {
- codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(codeStream.methodDeclaration);
- }
- if (localContentsOffset + 20 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- int max_stack = codeStream.stackMax;
- localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
- localContents[codeAttributeOffset + 7] = (byte) max_stack;
- int max_locals = codeStream.maxLocals;
- localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
- localContents[codeAttributeOffset + 9] = (byte) max_locals;
- localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
- localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
- localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
- localContents[codeAttributeOffset + 13] = (byte) code_length;
-
- // write the exception table
- int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
- ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
- int exSize;
- if (localContentsOffset + (exSize = (exceptionHandlersNumber * 8 + 2)) >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + (exSize > INCREMENT_SIZE ? exSize : INCREMENT_SIZE)]), 0, contentsLength);
- }
- // there is no exception table, so we need to offset by 2 the current offset and move
- // on the attribute generation
- localContents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
- localContents[localContentsOffset++] = (byte) exceptionHandlersNumber;
- for (int i = 0; i < exceptionHandlersNumber; i++) {
- ExceptionLabel exceptionHandler = exceptionHandlers[i];
- int start = exceptionHandler.start;
- localContents[localContentsOffset++] = (byte) (start >> 8);
- localContents[localContentsOffset++] = (byte) start;
- int end = exceptionHandler.end;
- localContents[localContentsOffset++] = (byte) (end >> 8);
- localContents[localContentsOffset++] = (byte) end;
- int handlerPC = exceptionHandler.position;
- localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
- localContents[localContentsOffset++] = (byte) handlerPC;
- if (exceptionHandler.exceptionType == null) {
- // any exception handler
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 0;
- } else {
- int nameIndex;
- if (exceptionHandler.exceptionType == TypeBinding.NullBinding) {
- /* represents ClassNotFoundException, see class literal access*/
- nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
- } else {
- nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
- }
- localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
- localContents[localContentsOffset++] = (byte) nameIndex;
- }
- }
-
- // debug attributes
- int codeAttributeAttributeOffset = localContentsOffset;
- int attributeNumber = 0;
- // leave two bytes for the attribute_length
- localContentsOffset += 2;
-
- // first we handle the linenumber attribute
- if (codeStream.generateLineNumberAttributes) {
- /* Create and add the line number attribute (used for debugging)
- * Build the pairs of:
- * (bytecodePC lineNumber)
- * according to the table of start line indexes and the pcToSourceMap table
- * contained into the codestream
- */
- /** OLD CODE
- int[][] pcToSourceMapTable;
- int previousLineNumber;
- int[] flatTable;
- int index;
- int startLineIndexes[] = codeStream.methodDeclaration.scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions;
- int max = startLineIndexes.length;
- */
- int[] pcToSourceMapTable;
- if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null) && (codeStream.pcToSourceMapSize != 0)) {
- int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
- if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
- localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
- int lineNumberTableOffset = localContentsOffset;
- localContentsOffset += 6; // leave space for attribute_length and line_number_table_length
- /** OLD CODE
- previousLineNumber = 0;
-
- // Seems like do would be better, but this preserves the existing behavior.
-
- flatTable = new int[code_length];
- for (int i = codeStream.pcToSourceMapSize - 1; i >= 0; i--) {
- // entry contains the following structure:
- // position 1: startPC
- // position 2: endPC
- // position 3: sourceStart
- // position 4: sourceEnd
- // Compute the line number for a given source position
- index = searchLineNumber(startLineIndexes, pcToSourceMapTable[i][2]);
- for (int j = pcToSourceMapTable[i][0]; j < pcToSourceMapTable[i][1]; j++)
- flatTable[j] = index;
- }
- previousLineNumber = -1;
-
- */
- int numberOfEntries = 0;
- int length = codeStream.pcToSourceMapSize;
- /** OLD CODE
- int length = flatTable.length;
- for (int i = 0; i < length; i++) {
- if (flatTable[i] != previousLineNumber) {
- previousLineNumber = flatTable[i];
- // write the entry
- if (localContentsOffset + 4 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- localContents[localContentsOffset++] = (byte) (i >> 8);
- localContents[localContentsOffset++] = (byte) i;
- localContents[localContentsOffset++] = (byte) (previousLineNumber >> 8);
- localContents[localContentsOffset++] = (byte) previousLineNumber;
- numberOfEntries++;
- }
- }
- */
- for (int i = 0; i < length;) {
- // write the entry
- if (localContentsOffset + 4 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- int pc = pcToSourceMapTable[i++];
- localContents[localContentsOffset++] = (byte) (pc >> 8);
- localContents[localContentsOffset++] = (byte) pc;
- int lineNumber = pcToSourceMapTable[i++];
- localContents[localContentsOffset++] = (byte) (lineNumber >> 8);
- localContents[localContentsOffset++] = (byte) lineNumber;
- numberOfEntries++;
- }
- // now we change the size of the line number attribute
- int lineNumberAttr_length = numberOfEntries * 4 + 2;
- localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
- localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
- localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
- localContents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
- localContents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
- localContents[lineNumberTableOffset++] = (byte) numberOfEntries;
- attributeNumber++;
- }
- }
-
-
-
- // then we do the local variable attribute
- if (codeStream.generateLocalVariableTableAttributes) {
- int localVariableTableOffset = localContentsOffset;
- int numberOfEntries = 0;
- int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
- if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
- localContents[localContentsOffset++] = (byte) localVariableNameIndex;
- localContentsOffset += 6; // leave space for attribute_length and local_variable_table_length
- int nameIndex;
- int descriptorIndex;
- if (!codeStream.methodDeclaration.isStatic()) {
- numberOfEntries++;
- if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- localContentsOffset += 2; // the startPC for this is always 0
- localContents[localContentsOffset++] = (byte) (code_length >> 8);
- localContents[localContentsOffset++] = (byte) code_length;
- nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
- localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
- localContents[localContentsOffset++] = (byte) nameIndex;
- descriptorIndex = constantPool.literalIndex(codeStream.methodDeclaration.binding.declaringClass.signature());
- localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
- localContents[localContentsOffset++] = (byte) descriptorIndex;
- localContentsOffset += 2; // the resolved position for this is always 0
- }
- for (int i = 0; i < codeStream.allLocalsCounter; i++) {
- LocalVariableBinding localVariable = codeStream.locals[i];
- for (int j = 0; j < localVariable.initializationCount; j++) {
- int startPC = localVariable.initializationPCs[j << 1];
- int endPC = localVariable.initializationPCs[(j << 1) + 1];
- if (startPC != endPC) { // only entries for non zero length
- int currentLength;
- if (endPC == -1) {
- localVariable.declaringScope.problemReporter().abortDueToInternalError(Util.bind("abort.invalidAttribute"/*nonNLS*/,new String(localVariable.name)), (AstNode) localVariable.declaringScope.methodScope().referenceContext);
- }
- if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- // now we can safely add the local entry
- numberOfEntries++;
- localContents[localContentsOffset++] = (byte) (startPC >> 8);
- localContents[localContentsOffset++] = (byte) startPC;
- int length = endPC - startPC;
- localContents[localContentsOffset++] = (byte) (length >> 8);
- localContents[localContentsOffset++] = (byte) length;
- nameIndex = constantPool.literalIndex(localVariable.name);
- localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
- localContents[localContentsOffset++] = (byte) nameIndex;
- descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
- localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
- localContents[localContentsOffset++] = (byte) descriptorIndex;
- int resolvedPosition = localVariable.resolvedPosition;
- localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
- localContents[localContentsOffset++] = (byte) resolvedPosition;
- }
- }
- }
- int value = numberOfEntries * 10 + 2;
- localVariableTableOffset += 2;
- localContents[localVariableTableOffset++] = (byte) (value >> 24);
- localContents[localVariableTableOffset++] = (byte) (value >> 16);
- localContents[localVariableTableOffset++] = (byte) (value >> 8);
- localContents[localVariableTableOffset++] = (byte) value;
- localContents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
- localContents[localVariableTableOffset] = (byte) numberOfEntries;
- attributeNumber++;
- }
- // update the number of attributes
- // ensure first that there is enough space available inside the localContents array
- if (codeAttributeAttributeOffset + 2 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
- localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
-
- // update the attribute length
- int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
- localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
- localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
- localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
- localContents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
- contentsOffset = localContentsOffset;
-}
-/**
- * INTERNAL USE-ONLY
- * That method completes the creation of the code attribute by setting
- * - the attribute_length
- * - max_stack
- * - max_locals
- * - code_length
- * - exception table
- * - and debug attributes if necessary.
- *
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param codeAttributeOffset <CODE>int</CODE>
- */
-public void completeCodeAttributeForClinit(int codeAttributeOffset) {
- // reinitialize the contents with the byte modified by the code stream
- byte[] localContents = contents = codeStream.bCodeStream;
- int localContentsOffset = codeStream.classFileOffset;
- // codeAttributeOffset is the position inside contents byte array before we started to write
- // any information about the codeAttribute
- // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
- // to get the right position, 6 for the max_stack etc...
- int contentsLength;
- int code_length = codeStream.position;
- if (code_length > 65535) {
- codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(codeStream.methodDeclaration.scope.referenceType());
- }
- if (localContentsOffset + 20 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- int max_stack = codeStream.stackMax;
- localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
- localContents[codeAttributeOffset + 7] = (byte) max_stack;
- int max_locals = codeStream.maxLocals;
- localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
- localContents[codeAttributeOffset + 9] = (byte) max_locals;
- localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
- localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
- localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
- localContents[codeAttributeOffset + 13] = (byte) code_length;
-
- // write the exception table
- int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
- ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
- int exSize;
- if (localContentsOffset + (exSize = (exceptionHandlersNumber * 8 + 2)) >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + (exSize > INCREMENT_SIZE ? exSize : INCREMENT_SIZE)]), 0, contentsLength);
- }
- // there is no exception table, so we need to offset by 2 the current offset and move
- // on the attribute generation
- localContents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
- localContents[localContentsOffset++] = (byte) exceptionHandlersNumber;
- for (int i = 0; i < exceptionHandlersNumber; i++) {
- ExceptionLabel exceptionHandler = exceptionHandlers[i];
- int start = exceptionHandler.start;
- localContents[localContentsOffset++] = (byte) (start >> 8);
- localContents[localContentsOffset++] = (byte) start;
- int end = exceptionHandler.end;
- localContents[localContentsOffset++] = (byte) (end >> 8);
- localContents[localContentsOffset++] = (byte) end;
- int handlerPC = exceptionHandler.position;
- localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
- localContents[localContentsOffset++] = (byte) handlerPC;
- if (exceptionHandler.exceptionType == null) {
- // any exception handler
- localContentsOffset += 2;
- } else {
- int nameIndex;
- if (exceptionHandler.exceptionType == TypeBinding.NullBinding) {
- /* represents denote ClassNotFoundException, see class literal access*/
- nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
- } else {
- nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
- }
- localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
- localContents[localContentsOffset++] = (byte) nameIndex;
- }
- }
-
- // debug attributes
- int codeAttributeAttributeOffset = localContentsOffset;
- int attributeNumber = 0;
- // leave two bytes for the attribute_length
- localContentsOffset += 2;
-
- // first we handle the linenumber attribute
- if (codeStream.generateLineNumberAttributes) {
- /* Create and add the line number attribute (used for debugging)
- * Build the pairs of:
- * (bytecodePC lineNumber)
- * according to the table of start line indexes and the pcToSourceMap table
- * contained into the codestream
- */
- int[] pcToSourceMapTable;
- if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null) && (codeStream.pcToSourceMapSize != 0)) {
- int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
- if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
- localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
- int lineNumberTableOffset = localContentsOffset;
- localContentsOffset += 6; // leave space for attribute_length and line_number_table_length
- int numberOfEntries = 0;
- int length = codeStream.pcToSourceMapSize;
- for (int i = 0; i < length;) {
- // write the entry
- if (localContentsOffset + 4 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- int pc = pcToSourceMapTable[i++];
- localContents[localContentsOffset++] = (byte) (pc >> 8);
- localContents[localContentsOffset++] = (byte) pc;
- int lineNumber = pcToSourceMapTable[i++];
- localContents[localContentsOffset++] = (byte) (lineNumber >> 8);
- localContents[localContentsOffset++] = (byte) lineNumber;
- numberOfEntries++;
- }
- // now we change the size of the line number attribute
- int lineNumberAttr_length = numberOfEntries * 4 + 2;
- localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
- localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
- localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
- localContents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
- localContents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
- localContents[lineNumberTableOffset++] = (byte) numberOfEntries;
- attributeNumber++;
- }
- }
-
-
-
- // then we do the local variable attribute
- if (codeStream.generateLocalVariableTableAttributes) {
- int localVariableTableOffset = localContentsOffset;
- int numberOfEntries = 0;
- // codeAttribute.addLocalVariableTableAttribute(this);
- if ((codeStream.pcToSourceMap != null) && (codeStream.pcToSourceMapSize != 0)) {
- int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
- if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
- localContents[localContentsOffset++] = (byte) localVariableNameIndex;
- localContentsOffset += 6; // leave space for attribute_length and local_variable_table_length
- int nameIndex;
- int descriptorIndex;
- for (int i = 0; i < codeStream.allLocalsCounter; i++) {
- LocalVariableBinding localVariable = codeStream.locals[i];
- for (int j = 0; j < localVariable.initializationCount; j++) {
- int startPC = localVariable.initializationPCs[j << 1];
- int endPC = localVariable.initializationPCs[ (j << 1) + 1];
- if (startPC != endPC) { // only entries for non zero length
- int currentLength;
- if (endPC == -1) {
- localVariable.declaringScope.problemReporter().abortDueToInternalError(Util.bind("abort.invalidAttribute"/*nonNLS*/,new String(localVariable.name)), (AstNode) localVariable.declaringScope.methodScope().referenceContext);
- }
- if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- // now we can safely add the local entry
- numberOfEntries++;
- localContents[localContentsOffset++] = (byte) (startPC >> 8);
- localContents[localContentsOffset++] = (byte) startPC;
- int length = endPC - startPC;
- localContents[localContentsOffset++] = (byte) (length >> 8);
- localContents[localContentsOffset++] = (byte) length;
- nameIndex = constantPool.literalIndex(localVariable.name);
- localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
- localContents[localContentsOffset++] = (byte) nameIndex;
- descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
- localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
- localContents[localContentsOffset++] = (byte) descriptorIndex;
- int resolvedPosition = localVariable.resolvedPosition;
- localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
- localContents[localContentsOffset++] = (byte) resolvedPosition;
- }
- }
- }
- int value = numberOfEntries * 10 + 2;
- localVariableTableOffset += 2;
- localContents[localVariableTableOffset++] = (byte) (value >> 24);
- localContents[localVariableTableOffset++] = (byte) (value >> 16);
- localContents[localVariableTableOffset++] = (byte) (value >> 8);
- localContents[localVariableTableOffset++] = (byte) value;
- localContents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
- localContents[localVariableTableOffset] = (byte) numberOfEntries;
- attributeNumber++;
- }
- }
- // update the number of attributes
- // ensure first that there is enough space available inside the contents array
- if (codeAttributeAttributeOffset + 2 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
- localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
- // update the attribute length
- int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
- localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
- localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
- localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
- localContents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
- contentsOffset = localContentsOffset;
-}
-/**
- * INTERNAL USE-ONLY
- * That method completes the creation of the code attribute by setting
- * - the attribute_length
- * - max_stack
- * - max_locals
- * - code_length
- * - exception table
- * - and debug attributes if necessary.
- *
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param codeAttributeOffset <CODE>int</CODE>
- * @param exceptionHandler int[]
- * @param startIndexes int[]
- */
-public void completeCodeAttributeForClinit(int codeAttributeOffset, int[] exceptionHandler, int[] startLineIndexes) {
- // reinitialize the contents with the byte modified by the code stream
- byte[] localContents = contents = codeStream.bCodeStream;
- int localContentsOffset = codeStream.classFileOffset;
- // codeAttributeOffset is the position inside contents byte array before we started to write
- // any information about the codeAttribute
- // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
- // to get the right position, 6 for the max_stack etc...
- int contentsLength;
- int code_length = codeStream.position;
- if (code_length > 65535) {
- codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(codeStream.methodDeclaration.scope.referenceType());
- }
- if (localContentsOffset + 20 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- int max_stack = codeStream.stackMax;
- localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
- localContents[codeAttributeOffset + 7] = (byte) max_stack;
- int max_locals = codeStream.maxLocals;
- localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
- localContents[codeAttributeOffset + 9] = (byte) max_locals;
- localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
- localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
- localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
- localContents[codeAttributeOffset + 13] = (byte) code_length;
-
- // write the exception table
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 1;
- int start = exceptionHandler[0];
- localContents[localContentsOffset++] = (byte) (start >> 8);
- localContents[localContentsOffset++] = (byte) start;
- int end = exceptionHandler[1];
- localContents[localContentsOffset++] = (byte) (end >> 8);
- localContents[localContentsOffset++] = (byte) end;
- int handlerPC = exceptionHandler[2];
- localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
- localContents[localContentsOffset++] = (byte) handlerPC;
- int nameIndex = constantPool.literalIndexForJavaLangException();
- localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
- localContents[localContentsOffset++] = (byte) nameIndex;
-
- // debug attributes
- int codeAttributeAttributeOffset = localContentsOffset;
- int attributeNumber = 0; // leave two bytes for the attribute_length
- localContentsOffset += 2; // first we handle the linenumber attribute
-
- // first we handle the linenumber attribute
- if (codeStream.generateLineNumberAttributes) {
- /* Create and add the line number attribute (used for debugging)
- * Build the pairs of:
- * (bytecodePC lineNumber)
- * according to the table of start line indexes and the pcToSourceMap table
- * contained into the codestream
- */
- int index = 0, max = startLineIndexes.length;
- int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
- localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
- localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 6;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 1;
- // first entry at pc = 0
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = (byte) (problemLine >> 8);
- localContents[localContentsOffset++] = (byte) problemLine;
- // now we change the size of the line number attribute
- attributeNumber++;
- }
-
- // then we do the local variable attribute
- if (codeStream.generateLocalVariableTableAttributes) {
- int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
- if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
- localContents[localContentsOffset++] = (byte) localVariableNameIndex;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 2;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 0;
- attributeNumber++;
- }
-
- // update the number of attributes
- // ensure first that there is enough space available inside the contents array
- if (codeAttributeAttributeOffset + 2 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
- localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
- // update the attribute length
- int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
- localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
- localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
- localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
- localContents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
- contentsOffset = localContentsOffset;
-}
-/**
- * INTERNAL USE-ONLY
- * That method completes the creation of the code attribute by setting
- * - the attribute_length
- * - max_stack
- * - max_locals
- * - code_length
- * - exception table
- * - and debug attributes if necessary.
- *
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param codeAttributeOffset <CODE>int</CODE>
- * @param exceptionHandler int[]
- */
-public void completeCodeAttributeForProblemMethod(AbstractMethodDeclaration method, MethodBinding binding, int codeAttributeOffset, int[] exceptionHandler, int[] startLineIndexes) {
- // reinitialize the localContents with the byte modified by the code stream
- byte[] localContents = contents = codeStream.bCodeStream;
- int localContentsOffset = codeStream.classFileOffset;
- // codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc...
- int max_stack = codeStream.stackMax;
- localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
- localContents[codeAttributeOffset + 7] = (byte) max_stack;
- int max_locals = codeStream.maxLocals;
- localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
- localContents[codeAttributeOffset + 9] = (byte) max_locals;
- int code_length = codeStream.position;
- localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
- localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
- localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
- localContents[codeAttributeOffset + 13] = (byte) code_length;
- // write the exception table
- int contentsLength;
- if (localContentsOffset + 50 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 1;
- int start = exceptionHandler[0];
- localContents[localContentsOffset++] = (byte) (start >> 8);
- localContents[localContentsOffset++] = (byte) start;
- int end = exceptionHandler[1];
- localContents[localContentsOffset++] = (byte) (end >> 8);
- localContents[localContentsOffset++] = (byte) end;
- int handlerPC = exceptionHandler[2];
- localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
- localContents[localContentsOffset++] = (byte) handlerPC;
- int nameIndex = constantPool.literalIndexForJavaLangException();
- localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
- localContents[localContentsOffset++] = (byte) nameIndex; // debug attributes
- int codeAttributeAttributeOffset = localContentsOffset;
- int attributeNumber = 0; // leave two bytes for the attribute_length
- localContentsOffset += 2; // first we handle the linenumber attribute
-
- if (codeStream.generateLineNumberAttributes) {
- /* Create and add the line number attribute (used for debugging)
- * Build the pairs of:
- * (bytecodePC lineNumber)
- * according to the table of start line indexes and the pcToSourceMap table
- * contained into the codestream
- */
- int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
- localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
- localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 6;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 1;
- if (problemLine == 0) {
- problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
- }
- // first entry at pc = 0
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = (byte) (problemLine >> 8);
- localContents[localContentsOffset++] = (byte) problemLine;
- // now we change the size of the line number attribute
- attributeNumber++;
- }
-
- // then we do the local variable attribute
- if (codeStream.generateLocalVariableTableAttributes) {
- // compute the resolved position for the arguments of the method
- int argSize;
- int localVariableTableOffset = localContentsOffset;
- int numberOfEntries = 0;
- // codeAttribute.addLocalVariableTableAttribute(this);
- int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
- if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
- localContents[localContentsOffset++] = (byte) localVariableNameIndex;
- localContentsOffset += 6; // leave space for attribute_length and local_variable_table_length
- int descriptorIndex;
- if (!codeStream.methodDeclaration.isStatic()) {
- numberOfEntries++;
- if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = (byte) (code_length >> 8);
- localContents[localContentsOffset++] = (byte) code_length;
- nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
- localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
- localContents[localContentsOffset++] = (byte) nameIndex;
- descriptorIndex = constantPool.literalIndex(codeStream.methodDeclaration.binding.declaringClass.signature());
- localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
- localContents[localContentsOffset++] = (byte) descriptorIndex;
- // the resolved position for this is always 0
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 0;
- }
- if (binding.isConstructor()) {
- ReferenceBinding declaringClass = binding.declaringClass;
- if (declaringClass.isNestedType()) {
- NestedTypeBinding methodDeclaringClass = (NestedTypeBinding) declaringClass;
- argSize = methodDeclaringClass.syntheticArgumentsOffset;
- SyntheticArgumentBinding[] syntheticArguments;
- if ((syntheticArguments = methodDeclaringClass.syntheticEnclosingInstances()) != null) {
- for (int i = 0, max = syntheticArguments.length; i < max; i++) {
- LocalVariableBinding localVariable = syntheticArguments[i];
- int currentLength;
- if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- // now we can safely add the local entry
- numberOfEntries++;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = (byte) (code_length >> 8);
- localContents[localContentsOffset++] = (byte) code_length;
- nameIndex = constantPool.literalIndex(localVariable.name);
- localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
- localContents[localContentsOffset++] = (byte) nameIndex;
- descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
- localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
- localContents[localContentsOffset++] = (byte) descriptorIndex;
- int resolvedPosition = localVariable.resolvedPosition;
- localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
- localContents[localContentsOffset++] = (byte) resolvedPosition;
- }
- }
- } else {
- argSize = 1;
- }
- } else {
- argSize = binding.isStatic() ? 0 : 1;
- }
- if (method.binding != null) {
- TypeBinding[] parameters = method.binding.parameters;
- Argument[] arguments = method.arguments;
- if ((parameters != null) && (arguments != null)) {
- for (int i = 0, max = parameters.length; i < max; i++) {
- TypeBinding argumentBinding = parameters[i];
- int currentLength;
- if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- // now we can safely add the local entry
- numberOfEntries++;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = 0;
- localContents[localContentsOffset++] = (byte) (code_length >> 8);
- localContents[localContentsOffset++] = (byte) code_length;
- nameIndex = constantPool.literalIndex(arguments[i].name);
- localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
- localContents[localContentsOffset++] = (byte) nameIndex;
- descriptorIndex = constantPool.literalIndex(argumentBinding.signature());
- localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
- localContents[localContentsOffset++] = (byte) descriptorIndex;
- int resolvedPosition = argSize;
- if ((argumentBinding == TypeBinding.LongBinding) || (argumentBinding == TypeBinding.DoubleBinding))
- argSize += 2;
- else
- argSize++;
- localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
- localContents[localContentsOffset++] = (byte) resolvedPosition;
- }
- }
- }
- int value = numberOfEntries * 10 + 2;
- localVariableTableOffset += 2;
- localContents[localVariableTableOffset++] = (byte) (value >> 24);
- localContents[localVariableTableOffset++] = (byte) (value >> 16);
- localContents[localVariableTableOffset++] = (byte) (value >> 8);
- localContents[localVariableTableOffset++] = (byte) value;
- localContents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
- localContents[localVariableTableOffset] = (byte) numberOfEntries;
- attributeNumber++;
- }
-
- // update the number of attributes// ensure first that there is enough space available inside the localContents array
- if (codeAttributeAttributeOffset + 2 >= (contentsLength = localContents.length)) {
- System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
- localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
- // update the attribute length
- int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
- localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
- localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
- localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
- localContents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
- contentsOffset = localContentsOffset;
-}
-/**
- * INTERNAL USE-ONLY
- * That method completes the creation of the code attribute by setting
- * - the attribute_length
- * - max_stack
- * - max_locals
- * - code_length
- * - exception table
- * - and debug attributes if necessary.
- *
- * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param codeAttributeOffset <CODE>int</CODE>
- */
-public void completeCodeAttributeForSyntheticAccessMethod(SyntheticAccessMethodBinding binding, int codeAttributeOffset, int[] startLineIndexes) {
- // reinitialize the contents with the byte modified by the code stream
- contents = codeStream.bCodeStream;
- int localContentsOffset = codeStream.classFileOffset;
- // codeAttributeOffset is the position inside contents byte array before we started to write
- // any information about the codeAttribute
- // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
- // to get the right position, 6 for the max_stack etc...
- int max_stack = codeStream.stackMax;
- contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
- contents[codeAttributeOffset + 7] = (byte) max_stack;
- int max_locals = codeStream.maxLocals;
- contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
- contents[codeAttributeOffset + 9] = (byte) max_locals;
- int code_length = codeStream.position;
- contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
- contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
- contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
- contents[codeAttributeOffset + 13] = (byte) code_length;
- int contentsLength;
- if ((localContentsOffset + 40) >= (contentsLength = contents.length)) {
- System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- // there is no exception table, so we need to offset by 2 the current offset and move
- // on the attribute generation
- localContentsOffset += 2;
- // debug attributes
- int codeAttributeAttributeOffset = localContentsOffset;
- int attributeNumber = 0;
- // leave two bytes for the attribute_length
- localContentsOffset += 2;
-
- // first we handle the linenumber attribute
- if (codeStream.generateLineNumberAttributes) {
- int index = 0, max = startLineIndexes.length;
- int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
- contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
- contents[localContentsOffset++] = (byte) lineNumberNameIndex;
- int lineNumberTableOffset = localContentsOffset;
- localContentsOffset += 6; // leave space for attribute_length and line_number_table_length
- // Seems like do would be better, but this preserves the existing behavior.
- index = searchLineNumber(startLineIndexes, binding.sourceStart);
- contents[localContentsOffset++] = 0;
- contents[localContentsOffset++] = 0;
- contents[localContentsOffset++] = (byte) (index >> 8);
- contents[localContentsOffset++] = (byte) index;
- // now we change the size of the line number attribute
- contents[lineNumberTableOffset++] = 0;
- contents[lineNumberTableOffset++] = 0;
- contents[lineNumberTableOffset++] = 0;
- contents[lineNumberTableOffset++] = 6;
- contents[lineNumberTableOffset++] = 0;
- contents[lineNumberTableOffset++] = 1;
- attributeNumber++;
- }
-
- // then we do the local variable attribute
- if (codeStream.generateLocalVariableTableAttributes) {
- int localVariableTableOffset = localContentsOffset;
- int numberOfEntries = 0;
- int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
- if (localContentsOffset + 8 > (contentsLength = contents.length)) {
- System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
- contents[localContentsOffset++] = (byte) localVariableNameIndex;
- localContentsOffset += 6; // leave space for attribute_length and local_variable_table_length
- int nameIndex;
- int descriptorIndex;
- for (int i = 0; i < codeStream.allLocalsCounter; i++) {
- LocalVariableBinding localVariable = codeStream.locals[i];
- for (int j = 0; j < localVariable.initializationCount; j++) {
- int startPC = localVariable.initializationPCs[j << 1];
- int endPC = localVariable.initializationPCs[(j << 1) + 1];
- if (startPC != endPC) { // only entries for non zero length
- int currentLength;
- if (endPC == -1) {
- localVariable.declaringScope.problemReporter().abortDueToInternalError(Util.bind("abort.invalidAttribute"/*nonNLS*/,new String(localVariable.name)), (AstNode) localVariable.declaringScope.methodScope().referenceContext);
- }
- if (localContentsOffset + 10 > (contentsLength = contents.length)) {
- System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- // now we can safely add the local entry
- numberOfEntries++;
- contents[localContentsOffset++] = (byte) (startPC >> 8);
- contents[localContentsOffset++] = (byte) startPC;
- int length = endPC - startPC;
- contents[localContentsOffset++] = (byte) (length >> 8);
- contents[localContentsOffset++] = (byte) length;
- nameIndex = constantPool.literalIndex(localVariable.name);
- contents[localContentsOffset++] = (byte) (nameIndex >> 8);
- contents[localContentsOffset++] = (byte) nameIndex;
- descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
- contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
- contents[localContentsOffset++] = (byte) descriptorIndex;
- int resolvedPosition = localVariable.resolvedPosition;
- contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
- contents[localContentsOffset++] = (byte) resolvedPosition;
- }
- }
- }
- int value = numberOfEntries * 10 + 2;
- localVariableTableOffset += 2;
- contents[localVariableTableOffset++] = (byte) (value >> 24);
- contents[localVariableTableOffset++] = (byte) (value >> 16);
- contents[localVariableTableOffset++] = (byte) (value >> 8);
- contents[localVariableTableOffset++] = (byte) value;
- contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
- contents[localVariableTableOffset] = (byte) numberOfEntries;
- attributeNumber++;
- }
-
- // update the number of attributes
- // ensure first that there is enough space available inside the contents array
- if (codeAttributeAttributeOffset + 2 >= (contentsLength = contents.length)) {
- System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
- contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
-
- // update the attribute length
- int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
- contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
- contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
- contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
- contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
- contentsOffset = localContentsOffset;
-}
-/**
- * INTERNAL USE-ONLY
- * Complete the creation of a method info by setting up the number of attributes at the right offset.
- *
- * @param methodAttributeOffset <CODE>int</CODE>
- * @param attributeNumber <CODE>int</CODE>
- */
-public void completeMethodInfo(int methodAttributeOffset, int attributeNumber) {
- // update the number of attributes
- contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
- contents[methodAttributeOffset] = (byte) attributeNumber;
-}
-/*
- * INTERNAL USE-ONLY
- * Innerclasses get their name computed as they are generated, since some may not
- * be actually outputed if sitting inside unreachable code.
- *
- * @param localType org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding
- */
-public char[] computeConstantPoolName(LocalTypeBinding localType) {
- if (localType.constantPoolName() != null) {
- return localType.constantPoolName();
- }
-
- // delegates to the outermost enclosing classfile, since it is the only one with a global vision of its innertypes.
- if (enclosingClassFile != null) {
- return this.outerMostEnclosingClassFile().computeConstantPoolName(localType);
- }
-
- if (nameUsage == null) {
- nameUsage = new CharArrayCache();
- }
- if (localType.isMemberType()) { // catches member types of local types
- return CharOperation.concat(
- localType.enclosingType().constantPoolName(),
- localType.sourceName,
- '$');
- } else {
- char[][] compoundName = (char[][]) referenceBinding.compoundName.clone();
- int last = compoundName.length - 1;
- StringBuffer nameBuffer = new StringBuffer().append(compoundName[last]);
- // retrieve the number of use of the combination
- char[] simpleName = localType.sourceName;
- //if (simpleName == null) simpleName = new char[]{}; // for anonymous
- int nameCount = nameUsage.get(simpleName); // -1 if not found
- nameCount = nameCount == -1 ? 1 : nameCount + 1;
- nameBuffer.append('$').append(nameCount);
- nameUsage.put(simpleName, nameCount);
- if (!localType.isAnonymousType()) { // named local type
- nameBuffer.append('$').append(simpleName);
- }
- compoundName[last] = nameBuffer.toString().toCharArray();
- return CharOperation.concatWith(compoundName, '/');
- }
-}
-/**
- * INTERNAL USE-ONLY
- * Request the creation of a ClassFile compatible representation of a problematic type
- *
- * @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
- * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
- */
-public static void createProblemType(TypeDeclaration typeDeclaration, CompilationResult unitResult) {
- SourceTypeBinding typeBinding = typeDeclaration.binding;
- ClassFile classFile = new ClassFile(typeBinding, null, true);
-
- // inner attributes
- if (typeBinding.isMemberType())
- classFile.recordEnclosingTypeAttributes(typeBinding);
-
- // add its fields
- FieldBinding[] fields = typeBinding.fields;
- if ((fields != null) && (fields != NoFields)) {
- for (int i = 0, max = fields.length; i < max; i++) {
- if (fields[i].constant == null) {
- FieldReference.getConstantFor(fields[i], false, null, 0);
- }
- }
- classFile.addFieldInfos();
- } else {
- // we have to set the number of fields to be equals to 0
- classFile.contents[classFile.contentsOffset++] = 0;
- classFile.contents[classFile.contentsOffset++] = 0;
- }
- // leave some space for the methodCount
- classFile.setForMethodInfos();
- // add its user defined methods
- MethodBinding[] methods = typeBinding.methods;
- AbstractMethodDeclaration[] methodDeclarations = typeDeclaration.methods;
- int maxMethodDecl = methodDeclarations == null ? 0 : methodDeclarations.length;
- int problemsLength;
- IProblem[] problems = unitResult.getProblems();
- if (problems == null) {
- problems = new IProblem[0];
- }
- IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
- System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
- if (methods != null) {
- if (typeBinding.isInterface()) {
- // we cannot create problem methods for an interface. So we have to generate a clinit
- // which should contain all the problem
- classFile.addProblemClinit(problemsCopy);
- for (int i = 0, max = methods.length; i < max; i++) {
- MethodBinding methodBinding;
- if ((methodBinding = methods[i]) != null) {
- // find the corresponding method declaration
- for (int j = 0; j < maxMethodDecl; j++) {
- if ((methodDeclarations[j] != null) && (methodDeclarations[j].binding == methods[i])) {
- if (!methodBinding.isConstructor()) {
- classFile.addAbstractMethod(methodDeclarations[j], methodBinding);
- }
- break;
- }
- }
- }
- }
- } else {
- for (int i = 0, max = methods.length; i < max; i++) {
- MethodBinding methodBinding;
- if ((methodBinding = methods[i]) != null) {
- // find the corresponding method declaration
- for (int j = 0; j < maxMethodDecl; j++) {
- if ((methodDeclarations[j] != null) && (methodDeclarations[j].binding == methods[i])) {
- AbstractMethodDeclaration methodDecl;
- if ((methodDecl = methodDeclarations[j]).isConstructor()) {
- classFile.addProblemConstructor(methodDecl, methodBinding, problemsCopy);
- } else {
- classFile.addProblemMethod(methodDecl, methodBinding, problemsCopy);
- }
- break;
- }
- }
- }
- }
- }
- // add abstract methods
- classFile.addDefaultAbstractMethods();
- }
- // propagate generation of (problem) member types
- if (typeDeclaration.memberTypes != null) {
- CompilationResult result = typeDeclaration.scope.referenceCompilationUnit().compilationResult;
- for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) {
- TypeDeclaration memberType = typeDeclaration.memberTypes[i];
- if (memberType.binding != null) {
- classFile.recordNestedMemberAttribute(memberType.binding);
- ClassFile.createProblemType(memberType, unitResult);
- }
- }
- }
- classFile.addAttributes();
- unitResult.record(typeBinding.constantPoolName(), classFile);
-}
-/**
- * INTERNAL USE-ONLY
- * This methods returns a char[] representing the file name of the receiver
- *
- * @return char[]
- */
-public char[] fileName() {
- return constantPool.UTF8Cache.returnKeyFor(1);
-}
-/**
- * INTERNAL USE-ONLY
- * That method generates the header of a code attribute.
- * - the index inside the constant pool for the attribute name (i.e. Code)
- * - leave some space for attribute_length(4), max_stack(2), max_locals(2), code_length(4).
- */
-public void generateCodeAttributeHeader() {
- int contentsLength;
- if (contentsOffset + 20 >= (contentsLength = contents.length)) {
- System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- int constantValueNameIndex = constantPool.literalIndex(AttributeNamesConstants.CodeName);
- contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
- contents[contentsOffset++] = (byte) constantValueNameIndex;
- // leave space for attribute_length(4), max_stack(2), max_locals(2), code_length(4)
- contentsOffset += 12;
-}
-/**
- * INTERNAL USE-ONLY
- * That method generates the attributes of a code attribute.
- * They could be:
- * - an exception attribute for each try/catch found inside the method
- * - a deprecated attribute
- * - a synthetic attribute for synthetic access methods
- *
- * It returns the number of attributes created for the code attribute.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- * @return <CODE>int</CODE>
- */
-public int generateMethodInfoAttribute(MethodBinding methodBinding) {
- // leave two bytes for the attribute_number
- contentsOffset += 2;
- // now we can handle all the attribute for that method info:
- // it could be:
- // - a CodeAttribute
- // - a ExceptionAttribute
- // - a DeprecatedAttribute
- // - a SyntheticAttribute
-
- // Exception attribute
- ReferenceBinding[] thrownsExceptions;
- int contentsLength;
- int attributeNumber = 0;
- if ((thrownsExceptions = methodBinding.thrownExceptions) != NoExceptions) {
- // The method has a throw clause. So we need to add an exception attribute
- // check that there is enough space to write all the bytes for the exception attribute
- int length = thrownsExceptions.length;
- if (contentsOffset + (8 + length * 2) >= (contentsLength = contents.length)) {
- System.arraycopy(contents, 0, (contents = new byte[contentsLength + Math.max(INCREMENT_SIZE, (8 + length * 2))]), 0, contentsLength);
- }
- int exceptionNameIndex = constantPool.literalIndex(AttributeNamesConstants.ExceptionsName);
- contents[contentsOffset++] = (byte) (exceptionNameIndex >> 8);
- contents[contentsOffset++] = (byte) exceptionNameIndex;
- // The attribute length = length * 2 + 2 in case of a exception attribute
- int attributeLength = length * 2 + 2;
- contents[contentsOffset++] = (byte) (attributeLength >> 24);
- contents[contentsOffset++] = (byte) (attributeLength >> 16);
- contents[contentsOffset++] = (byte) (attributeLength >> 8);
- contents[contentsOffset++] = (byte) attributeLength;
- contents[contentsOffset++] = (byte) (length >> 8);
- contents[contentsOffset++] = (byte) length;
- for (int i = 0; i < length; i++) {
- int exceptionIndex = constantPool.literalIndex(thrownsExceptions[i]);
- contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
- contents[contentsOffset++] = (byte) exceptionIndex;
- }
- attributeNumber++;
- }
-
- // Deprecated attribute
- // Check that there is enough space to write the deprecated attribute
- if (contentsOffset + 6 >= (contentsLength = contents.length)) {
- System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- if (methodBinding.isDeprecated()) {
- int deprecatedAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
- contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
- contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
- // the length of a deprecated attribute is equals to 0
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
-
- attributeNumber++;
- }
-
- // Synthetic attribute
- // Check that there is enough space to write the deprecated attribute
- if (contentsOffset + 6 >= (contentsLength = contents.length)) {
- System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- if (methodBinding.isSynthetic()) {
- int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
- contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
- contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
- // the length of a synthetic attribute is equals to 0
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 0;
-
- attributeNumber++;
- }
- return attributeNumber;
-}
-/**
- * INTERNAL USE-ONLY
- * That method generates the header of a method info:
- * The header consists in:
- * - the access flags
- * - the name index of the method name inside the constant pool
- * - the descriptor index of the signature of the method inside the constant pool.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- */
-public void generateMethodInfoHeader(MethodBinding methodBinding) {
- // check that there is enough space to write all the bytes for the method info corresponding
- // to the @methodBinding
- int contentsLength;
- methodCount++; // add one more method
- if (contentsOffset + 10 >= (contentsLength = contents.length)) {
- System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- int accessFlags = methodBinding.getAccessFlags();
- if (methodBinding.isRequiredToClearPrivateModifier()) {
- accessFlags &= ~AccPrivate;
- }
- contents[contentsOffset++] = (byte) (accessFlags >> 8);
- contents[contentsOffset++] = (byte) accessFlags;
- int nameIndex = constantPool.literalIndex(methodBinding.selector);
- contents[contentsOffset++] = (byte) (nameIndex >> 8);
- contents[contentsOffset++] = (byte) nameIndex;
- int descriptorIndex = constantPool.literalIndex(methodBinding.signature());
- contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
- contents[contentsOffset++] = (byte) descriptorIndex;
-}
-/**
- * INTERNAL USE-ONLY
- * That method generates the method info header of a clinit:
- * The header consists in:
- * - the access flags (always default access + static)
- * - the name index of the method name (always <clinit>) inside the constant pool
- * - the descriptor index of the signature (always ()V) of the method inside the constant pool.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- */
-public void generateMethodInfoHeaderForClinit() {
- // check that there is enough space to write all the bytes for the method info corresponding
- // to the @methodBinding
- int contentsLength;
- methodCount++; // add one more method
- if (contentsOffset + 10 >= (contentsLength = contents.length)) {
- System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
- }
- contents[contentsOffset++] = (byte) ((AccDefault | AccStatic) >> 8);
- contents[contentsOffset++] = (byte) (AccDefault | AccStatic);
- int nameIndex = constantPool.literalIndex(QualifiedNamesConstants.Clinit);
- contents[contentsOffset++] = (byte) (nameIndex >> 8);
- contents[contentsOffset++] = (byte) nameIndex;
- int descriptorIndex = constantPool.literalIndex(QualifiedNamesConstants.ClinitSignature);
- contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
- contents[contentsOffset++] = (byte) descriptorIndex;
- // We know that we won't get more than 1 attribute: the code attribute
- contents[contentsOffset++] = 0;
- contents[contentsOffset++] = 1;
-}
-/**
- * EXTERNAL API
- * Answer the actual bytes of the class file
- *
- * This method encodes the receiver structure into a byte array which is the content of the classfile.
- * Returns the byte array that represents the encoded structure of the receiver.
- *
- * @return byte[]
- */
-public byte[] getBytes() {
- byte[] fullContents = new byte[headerOffset + contentsOffset];
- System.arraycopy(header, 0, fullContents, 0, headerOffset);
- System.arraycopy(contents, 0, fullContents, headerOffset, contentsOffset);
- return fullContents;
-}
-/**
- * EXTERNAL API
- * Answer the compound name of the class file.
- * @return char[][]
- * e.g. {{java}, {util}, {Hashtable}}.
- */
-public char[][] getCompoundName() {
- return CharOperation.splitOn('/', fileName());
-}
-/**
- * EXTERNAL API
- * Answer a smaller byte format, which is only contains some structural information.
- *
- * Those bytes are decodable with a regular class file reader, such as:
- * DietClassFileReader
- */
-
-public byte[] getReducedBytes() {
- return getBytes(); // might be improved
-}
-/**
- * INTERNAL USE-ONLY
- * Returns the most enclosing classfile of the receiver. This is used know to store the constant pool name
- * for all inner types of the receiver.
- * @return org.eclipse.jdt.internal.compiler.codegen.ClassFile
- */
-public ClassFile outerMostEnclosingClassFile() {
- ClassFile current = this;
- while (current.enclosingClassFile != null)
- current = current.enclosingClassFile;
- return current;
-}
-/**
- * INTERNAL USE-ONLY
- * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
- * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
- *
- * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
- */
-public void recordEnclosingTypeAttributes(ReferenceBinding binding) {
- // add all the enclosing types
- ReferenceBinding enclosingType = referenceBinding.enclosingType();
- int depth = 0;
- while (enclosingType != null) {
- depth++;
- enclosingType = enclosingType.enclosingType();
- }
- enclosingType = referenceBinding;
- ReferenceBinding enclosingTypes[];
- if (depth >= 2) {
- enclosingTypes = new ReferenceBinding[depth];
- for (int i = depth - 1; i >= 0; i--) {
- enclosingTypes[i] = enclosingType;
- enclosingType = enclosingType.enclosingType();
- }
- for (int i = 0; i < depth; i++) {
- addInnerClasses(enclosingTypes[i]);
- }
- } else {
- addInnerClasses(referenceBinding);
- }
-}
-/**
- * INTERNAL USE-ONLY
- * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
- * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
- *
- * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
- */
-public void recordNestedLocalAttribute(ReferenceBinding binding) {
- // add all the enclosing types
- ReferenceBinding enclosingType = referenceBinding.enclosingType();
- int depth = 0;
- while (enclosingType != null) {
- depth++;
- enclosingType = enclosingType.enclosingType();
- }
- enclosingType = referenceBinding;
- ReferenceBinding enclosingTypes[];
- if (depth >= 2) {
- enclosingTypes = new ReferenceBinding[depth];
- for (int i = depth - 1; i >= 0; i--) {
- enclosingTypes[i] = enclosingType;
- enclosingType = enclosingType.enclosingType();
- }
- for (int i = 0; i < depth; i++)
- addInnerClasses(enclosingTypes[i]);
- } else {
- addInnerClasses(binding);
- }
-}
-/**
- * INTERNAL USE-ONLY
- * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
- * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
- *
- * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
- */
-public void recordNestedMemberAttribute(ReferenceBinding binding) {
- addInnerClasses(binding);
-}
-/**
- * INTERNAL USE-ONLY
- * Search the line number corresponding to a specific position
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
- */
-public static final int searchLineNumber(int[] startLineIndexes, int position) {
- // this code is completely useless, but it is the same implementation than
- // org.eclipse.jdt.internal.compiler.problem.ProblemHandler.searchLineNumber(int[], int)
- // if (startLineIndexes == null)
- // return 1;
- int length = startLineIndexes.length;
- if (length == 0)
- return 1;
- int g = 0, d = length - 1;
- int m = 0;
- while (g <= d) {
- m = (g + d) /2;
- if (position < startLineIndexes[m]) {
- d = m-1;
- } else if (position > startLineIndexes[m]) {
- g = m+1;
- } else {
- return m + 1;
- }
- }
- if (position < startLineIndexes[m]) {
- return m+1;
- }
- return m+2;
-}
-/**
- * INTERNAL USE-ONLY
- * This methods leaves the space for method counts recording.
- */
-public void setForMethodInfos() {
- // leave some space for the methodCount
- methodCountOffset = contentsOffset;
- contentsOffset += 2;
-}
-/**
- * INTERNAL USE-ONLY
- * outputPath is formed like:
- * c:\temp\ the last character is a file separator
- * relativeFileName is formed like:
- * java\lang\String.class
- * @param fileName java.lang.String
- * @param content byte[]
- */
-public static void writeToDisk(String outputPath, String relativeFileName, byte[] contents) throws IOException {
- String fileName;
- File file;
- FileOutputStream output = new FileOutputStream(file = new File((fileName = buildAllDirectoriesInto(outputPath, relativeFileName))));
- output.write(contents);
- output.flush();
- output.close();
-}
-}
+package org.eclipse.jdt.internal.compiler;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+/**
+ * Represents a class file wrapper on bytes, it is aware of its actual
+ * type name.
+ *
+ * Public APIs are listed below:
+ *
+ * byte[] getBytes();
+ * Answer the actual bytes of the class file
+ *
+ * char[][] getCompoundName();
+ * Answer the compound name of the class file.
+ * For example, {{java}, {util}, {Hashtable}}.
+ *
+ * byte[] getReducedBytes();
+ * Answer a smaller byte format, which is only contains some structural
+ * information. Those bytes are decodable with a regular class file reader,
+ * such as DietClassFileReader
+ */
+
+import java.io.*;
+import java.util.*;
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.compiler.util.*;
+
+
+public class ClassFile implements AttributeNamesConstants, CompilerModifiers, TypeConstants, TypeIds {
+ public SourceTypeBinding referenceBinding;
+ public ConstantPool constantPool;
+ public ClassFile enclosingClassFile; // used to generate private access methods
+ public int produceDebugAttributes;
+ public ReferenceBinding[] innerClassesBindings;
+ public int numberOfInnerClasses;
+ public byte[] header; // the header contains all the bytes till the end of the constant pool
+ public byte[] contents; // that collection contains all the remaining bytes of the .class file
+ public int headerOffset;
+ public int contentsOffset;
+ public int constantPoolOffset;
+ public int methodCountOffset;
+ public int methodCount;
+ protected boolean creatingProblemType;
+ public static final int INITIAL_CONTENTS_SIZE = 1000;
+ public static final int INITIAL_HEADER_SIZE = 1000;
+ public static final int INCREMENT_SIZE = 1000;
+ public static final int INNER_CLASSES_SIZE = 5;
+ protected CharArrayCache nameUsage;
+ public CodeStream codeStream;
+ protected int problemLine; // used to create line number attributes for problem methods
+/**
+ * INTERNAL USE-ONLY
+ * This methods creates a new instance of the receiver.
+ */
+public ClassFile() {}
+/**
+ * INTERNAL USE-ONLY
+ * This methods creates a new instance of the receiver.
+ *
+ * @param aType org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding
+ * @param enclosingClassFile org.eclipse.jdt.internal.compiler.ClassFile
+ * @param creatingProblemType <CODE>boolean</CODE>
+ */
+public ClassFile(SourceTypeBinding aType, ClassFile enclosingClassFile, boolean creatingProblemType) {
+ referenceBinding = aType;
+ header = new byte[INITIAL_HEADER_SIZE];
+ // generate the magic numbers inside the header
+ header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
+ header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
+ header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
+ header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
+ if (((SourceTypeBinding) referenceBinding).scope.environment().options.targetJDK == CompilerOptions.JDK1_2) {
+ // Compatible with JDK 1.2
+ header[headerOffset++] = 0; // minorVersion = 0 means we just need to offset the current offset by 2
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 46;
+ } else {
+ // Compatible with JDK 1.1
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 3;
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 45;
+ }
+ constantPoolOffset = headerOffset;
+ headerOffset += 2;
+ constantPool = new ConstantPool(this);
+
+ int accessFlags = aType.getAccessFlags();
+ if (aType.isProtected()) {
+ // set Acc_Public
+ accessFlags |= AccPublic;
+ }
+ // clear all bits that are illegal for a class or an interface
+ accessFlags
+ &= ~(
+ AccStrictfp
+ | AccProtected
+ | AccPrivate
+ | AccStatic
+ | AccSynchronized
+ | AccNative);
+
+ // set the AccSuper flag (has to be done after clearing AccSynchronized - since same value)
+ accessFlags |= AccSuper;
+
+ this.enclosingClassFile = enclosingClassFile;
+ // innerclasses get their names computed at code gen time
+ if (aType.isLocalType()) {
+ ((LocalTypeBinding) aType).constantPoolName(computeConstantPoolName((LocalTypeBinding) aType));
+ ReferenceBinding[] memberTypes = aType.memberTypes();
+ for (int i = 0, max = memberTypes.length; i < max; i++) {
+ ((LocalTypeBinding) memberTypes[i]).constantPoolName(computeConstantPoolName((LocalTypeBinding) memberTypes[i]));
+ }
+ }
+ contents = new byte[INITIAL_CONTENTS_SIZE];
+ // now we continue to generate the bytes inside the contents array
+ contents[contentsOffset++] = (byte) (accessFlags >> 8);
+ contents[contentsOffset++] = (byte) accessFlags;
+ int classNameIndex = constantPool.literalIndex(aType);
+ contents[contentsOffset++] = (byte) (classNameIndex >> 8);
+ contents[contentsOffset++] = (byte) classNameIndex;
+ int superclassNameIndex;
+ if (aType.isInterface()) {
+ superclassNameIndex = constantPool.literalIndexForJavaLangObject();
+ } else {
+ superclassNameIndex = (aType.superclass == null ? 0 : constantPool.literalIndex(aType.superclass));
+ }
+ contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
+ contents[contentsOffset++] = (byte) superclassNameIndex;
+ ReferenceBinding[] superInterfacesBinding = aType.superInterfaces();
+ int interfacesCount = superInterfacesBinding.length;
+ contents[contentsOffset++] = (byte) (interfacesCount >> 8);
+ contents[contentsOffset++] = (byte) interfacesCount;
+ if (superInterfacesBinding != null) {
+ for (int i = 0; i < interfacesCount; i++) {
+ int interfaceIndex = constantPool.literalIndex(superInterfacesBinding[i]);
+ contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
+ contents[contentsOffset++] = (byte) interfaceIndex;
+ }
+ }
+ produceDebugAttributes = ((SourceTypeBinding) referenceBinding).scope.environment().options.produceDebugAttributes;
+ innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE];
+ this.creatingProblemType = creatingProblemType;
+ codeStream = new CodeStream(this);
+
+ // retrieve the enclosing one guaranteed to be the one matching the propagated flow info
+ // 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
+ ClassFile outermostClassFile = this.outerMostEnclosingClassFile();
+ if (this == outermostClassFile) {
+ codeStream.maxFieldCount = aType.scope.referenceType().maxFieldCount;
+ } else {
+ codeStream.maxFieldCount = outermostClassFile.codeStream.maxFieldCount;
+ }
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a boggus method.
+ *
+ * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+ */
+public void addAbstractMethod(
+ AbstractMethodDeclaration method,
+ MethodBinding methodBinding) {
+
+ // force the modifiers to be public and abstract
+ methodBinding.modifiers = AccPublic | AccAbstract;
+
+ this.generateMethodInfoHeader(methodBinding);
+ int methodAttributeOffset = this.contentsOffset;
+ int attributeNumber = this.generateMethodInfoAttribute(methodBinding);
+ this.completeMethodInfo(methodAttributeOffset, attributeNumber);
+}
+/**
+ * INTERNAL USE-ONLY
+ * This methods generate all the attributes for the receiver.
+ * For a class they could be:
+ * - source file attribute
+ * - inner classes attribute
+ * - deprecated attribute
+ */
+public void addAttributes() {
+ // update the method count
+ contents[methodCountOffset++] = (byte) (methodCount >> 8);
+ contents[methodCountOffset] = (byte) methodCount;
+
+ int attributeNumber = 0;
+ // leave two bytes for the number of attributes and store the current offset
+ int attributeOffset = contentsOffset;
+ contentsOffset += 2;
+ int contentsLength;
+
+ // source attribute
+ if ((produceDebugAttributes & CompilerOptions.Source) != 0) {
+ String fullFileName = new String(referenceBinding.scope.referenceCompilationUnit().getFileName());
+ fullFileName = fullFileName.replace('\\', '/');
+ int lastIndex = fullFileName.lastIndexOf('/');
+ if (lastIndex != -1) {
+ fullFileName = fullFileName.substring(lastIndex + 1, fullFileName.length());
+ }
+ // check that there is enough space to write all the bytes for the field info corresponding
+ // to the @fieldBinding
+ if (contentsOffset + 8 >= (contentsLength = contents.length)) {
+ System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ int sourceAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SourceName);
+ contents[contentsOffset++] = (byte) (sourceAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) sourceAttributeNameIndex;
+ // The length of a source file attribute is 2. This is a fixed-length
+ // attribute
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 2;
+ // write the source file name
+ int fileNameIndex = constantPool.literalIndex(fullFileName.toCharArray());
+ contents[contentsOffset++] = (byte) (fileNameIndex >> 8);
+ contents[contentsOffset++] = (byte) fileNameIndex;
+ attributeNumber++;
+ }
+
+ // Deprecated attribute
+ if (referenceBinding.isDeprecated()) {
+ // check that there is enough space to write all the bytes for the field info corresponding
+ // to the @fieldBinding
+ if (contentsOffset + 6 >= (contentsLength = contents.length)) {
+ System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ int deprecatedAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
+ contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
+ // the length of a deprecated attribute is equals to 0
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ attributeNumber++;
+ }
+
+ // Inner class attribute
+ if (numberOfInnerClasses != 0) {
+ // Generate the inner class attribute
+ int exSize;
+ if (contentsOffset + (exSize = (8 * numberOfInnerClasses + 8)) >= (contentsLength = contents.length)) {
+ System.arraycopy(contents, 0, (contents = new byte[contentsLength + (exSize >= INCREMENT_SIZE ? exSize : INCREMENT_SIZE)]), 0, contentsLength);
+ }
+ // Now we now the size of the attribute and the number of entries
+ // attribute name
+ int attributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.InnerClassName);
+ contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) attributeNameIndex;
+ int value = (numberOfInnerClasses << 3) + 2;
+ contents[contentsOffset++] = (byte) (value >> 24);
+ contents[contentsOffset++] = (byte) (value >> 16);
+ contents[contentsOffset++] = (byte) (value >> 8);
+ contents[contentsOffset++] = (byte) value;
+ contents[contentsOffset++] = (byte) (numberOfInnerClasses >> 8);
+ contents[contentsOffset++] = (byte) numberOfInnerClasses;
+ for (int i = 0; i < numberOfInnerClasses; i++) {
+ ReferenceBinding innerClass = innerClassesBindings[i];
+ int accessFlags = innerClass.getAccessFlags();
+ int innerClassIndex = constantPool.literalIndex(innerClass);
+ // inner class index
+ contents[contentsOffset++] = (byte) (innerClassIndex >> 8);
+ contents[contentsOffset++] = (byte) innerClassIndex;
+ // outer class index: anonymous and local have no outer class index
+ if (innerClass.isMemberType()) {
+ // member or member of local
+ int outerClassIndex = constantPool.literalIndex(innerClass.enclosingType());
+ contents[contentsOffset++] = (byte) (outerClassIndex >> 8);
+ contents[contentsOffset++] = (byte) outerClassIndex;
+ } else {
+ // equals to 0 if the innerClass is not a member type
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ }
+ // name index
+ if (!innerClass.isAnonymousType()) {
+ int nameIndex = constantPool.literalIndex(innerClass.sourceName());
+ contents[contentsOffset++] = (byte) (nameIndex >> 8);
+ contents[contentsOffset++] = (byte) nameIndex;
+ } else {
+ // equals to 0 if the innerClass is an anonymous type
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ }
+ // access flag
+ if (innerClass.isAnonymousType()) {
+ accessFlags |= AccPrivate;
+ } else
+ if (innerClass.isLocalType() && !innerClass.isMemberType()) {
+ accessFlags |= AccPrivate;
+ }
+ contents[contentsOffset++] = (byte) (accessFlags >> 8);
+ contents[contentsOffset++] = (byte) accessFlags;
+ }
+ attributeNumber++;
+ }
+ // update the number of attributes
+ if (attributeOffset + 2 >= (contentsLength = contents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ contents[attributeOffset++] = (byte) (attributeNumber >> 8);
+ contents[attributeOffset] = (byte) attributeNumber;
+
+ // resynchronize all offsets of the classfile
+ header = constantPool.poolContent;
+ headerOffset = constantPool.currentOffset;
+ int constantPoolCount = constantPool.currentIndex;
+ header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
+ header[constantPoolOffset] = (byte) constantPoolCount;
+}
+/**
+ * INTERNAL USE-ONLY
+ * This methods generate all the default abstract method infos that correpond to
+ * the abstract methods inherited from superinterfaces.
+ */
+public void addDefaultAbstractMethods() { // default abstract methods
+ MethodBinding[] defaultAbstractMethods = referenceBinding.getDefaultAbstractMethods();
+ for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
+ generateMethodInfoHeader(defaultAbstractMethods[i]);
+ int methodAttributeOffset = contentsOffset;
+ int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
+ completeMethodInfo(methodAttributeOffset, attributeNumber);
+ }
+}
+/**
+ * INTERNAL USE-ONLY
+ * This methods generates the bytes for the field binding passed like a parameter
+ * @param fieldBinding org.eclipse.jdt.internal.compiler.lookup.FieldBinding
+ */
+public void addFieldInfo(FieldBinding fieldBinding) {
+ int attributeNumber = 0;
+ // check that there is enough space to write all the bytes for the field info corresponding
+ // to the @fieldBinding
+ int contentsLength;
+ if (contentsOffset + 30 >= (contentsLength = contents.length)) {
+ System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ // Generate two attribute: constantValueAttribute and SyntheticAttribute
+ // Now we can generate all entries into the byte array
+ // First the accessFlags
+ int accessFlags = fieldBinding.getAccessFlags();
+ contents[contentsOffset++] = (byte) (accessFlags >> 8);
+ contents[contentsOffset++] = (byte) accessFlags;
+ // Then the nameIndex
+ int nameIndex = constantPool.literalIndex(fieldBinding.name);
+ contents[contentsOffset++] = (byte) (nameIndex >> 8);
+ contents[contentsOffset++] = (byte) nameIndex;
+ // Then the descriptorIndex
+ int descriptorIndex = constantPool.literalIndex(fieldBinding.type.signature());
+ contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
+ contents[contentsOffset++] = (byte) descriptorIndex;
+ // leave some space for the number of attributes
+ int fieldAttributeOffset = contentsOffset;
+ contentsOffset += 2;
+ // 4.7.2 only static constant fields get a ConstantAttribute
+ if (fieldBinding.isStatic()
+ && fieldBinding.constant != Constant.NotAConstant
+ && fieldBinding.constant.typeID() != T_null) {
+ // Now we generate the constant attribute corresponding to the fieldBinding
+ int constantValueNameIndex = constantPool.literalIndex(AttributeNamesConstants.ConstantValueName);
+ contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
+ contents[contentsOffset++] = (byte) constantValueNameIndex;
+ // The attribute length = 2 in case of a constantValue attribute
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 2;
+ attributeNumber++;
+ // Need to add the constant_value_index
+ switch (fieldBinding.constant.typeID()) {
+ case T_boolean :
+ int booleanValueIndex = constantPool.literalIndex(fieldBinding.constant.booleanValue() ? 1 : 0);
+ contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
+ contents[contentsOffset++] = (byte) booleanValueIndex;
+ break;
+ case T_byte :
+ case T_char :
+ case T_int :
+ case T_short :
+ int integerValueIndex = constantPool.literalIndex(fieldBinding.constant.intValue());
+ contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
+ contents[contentsOffset++] = (byte) integerValueIndex;
+ break;
+ case T_float :
+ int floatValueIndex = constantPool.literalIndex(fieldBinding.constant.floatValue());
+ contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
+ contents[contentsOffset++] = (byte) floatValueIndex;
+ break;
+ case T_double :
+ int doubleValueIndex = constantPool.literalIndex(fieldBinding.constant.doubleValue());
+ contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
+ contents[contentsOffset++] = (byte) doubleValueIndex;
+ break;
+ case T_long :
+ int longValueIndex = constantPool.literalIndex(fieldBinding.constant.longValue());
+ contents[contentsOffset++] = (byte) (longValueIndex >> 8);
+ contents[contentsOffset++] = (byte) longValueIndex;
+ break;
+ case T_String :
+ int stringValueIndex = constantPool.literalIndex(((StringConstant) fieldBinding.constant).stringValue());
+ if (stringValueIndex == -1) {
+ if (!creatingProblemType) {
+ // report an error and abort: will lead to a problem type classfile creation
+ TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
+ FieldDeclaration[] fieldDecls = typeDeclaration.fields;
+ for (int i = 0, max = fieldDecls.length; i < max; i++) {
+ if (fieldDecls[i].binding == fieldBinding) {
+ // problem should abort
+ typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(fieldDecls[i]);
+ }
+ }
+ } else {
+ // already inside a problem type creation : no constant for this field
+ contentsOffset = fieldAttributeOffset + 2; // +2 is necessary to keep the two byte space for the attribute number
+ attributeNumber--;
+ }
+ } else {
+ contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
+ contents[contentsOffset++] = (byte) stringValueIndex;
+ }
+ }
+ }
+ if (fieldBinding.isSynthetic()) {
+ int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+ contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+ // the length of a synthetic attribute is equals to 0
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ attributeNumber++;
+ }
+ if (fieldBinding.isDeprecated()) {
+ int deprecatedAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
+ contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
+ // the length of a deprecated attribute is equals to 0
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ attributeNumber++;
+ }
+ contents[fieldAttributeOffset++] = (byte) (attributeNumber >> 8);
+ contents[fieldAttributeOffset] = (byte) attributeNumber;
+}
+/**
+ * INTERNAL USE-ONLY
+ * This methods generate all the fields infos for the receiver.
+ * This includes:
+ * - a field info for each defined field of that class
+ * - a field info for each synthetic field (e.g. this$0)
+ */
+public void addFieldInfos() {
+ SourceTypeBinding currentBinding = referenceBinding;
+ FieldBinding[] syntheticFields = currentBinding.syntheticFields();
+ int fieldCount = currentBinding.fieldCount() + (syntheticFields == null ? 0 : syntheticFields.length);
+
+ // write the number of fields
+ contents[contentsOffset++] = (byte) (fieldCount >> 8);
+ contents[contentsOffset++] = (byte) fieldCount;
+
+ FieldBinding[] fieldBindings = currentBinding.fields();
+ for (int i = 0, max = fieldBindings.length; i < max; i++) {
+ addFieldInfo(fieldBindings[i]);
+ }
+ if (syntheticFields != null) {
+ for (int i = 0, max = syntheticFields.length; i < max; i++) {
+ addFieldInfo(syntheticFields[i]);
+ }
+ }
+}
+/**
+ * INTERNAL USE-ONLY
+ * This methods stores the bindings for each inner class. They will be used to know which entries
+ * have to be generated for the inner classes attributes.
+ * @param referenceBinding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
+ */
+public void addInnerClasses(ReferenceBinding referenceBinding) {
+ // check first if that reference binding is there
+ for (int i = 0; i < numberOfInnerClasses; i++) {
+ if (innerClassesBindings[i] == referenceBinding)
+ return;
+ }
+ int length = innerClassesBindings.length;
+ if (numberOfInnerClasses == length) {
+ System.arraycopy(innerClassesBindings, 0, (innerClassesBindings = new ReferenceBinding[length * 2]), 0, length);
+ }
+ innerClassesBindings[numberOfInnerClasses++] = referenceBinding;
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem clinit method info that correspond to a boggus method.
+ *
+ * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
+ */
+public void addProblemClinit(IProblem[] problems) {
+ generateMethodInfoHeaderForClinit();
+ // leave two spaces for the number of attributes
+ contentsOffset -= 2;
+ int attributeOffset = contentsOffset;
+ contentsOffset += 2;
+ ReferenceBinding[] thrownsExceptions;
+ int attributeNumber = 0;
+ int contentsLength;
+
+ int codeAttributeOffset = contentsOffset;
+ generateCodeAttributeHeader();
+ codeStream.resetForProblemClinit(this);
+ String problemString = ""/*nonNLS*/;
+ if (problems != null) {
+ int max = problems.length;
+ StringBuffer buffer = new StringBuffer(25);
+ int count = 0;
+ for (int i = 0; i < max; i++) {
+ IProblem problem = problems[i];
+ if ((problem != null) && (problem.isError())) {
+ buffer.append("\t"/*nonNLS*/ + problem.getMessage() + "\n"/*nonNLS*/);
+ count++;
+ if (problemLine == 0) {
+ problemLine = problem.getSourceLineNumber();
+ }
+ problems[i] = null;
+ }
+ } // insert the top line afterwards, once knowing how many problems we have to consider
+ if (count > 1) {
+ buffer.insert(0, Util.bind("compilation.unresolvedProblems"/*nonNLS*/));
+ } else {
+ buffer.insert(0, Util.bind("compilation.unresolvedProblem"/*nonNLS*/));
+ }
+ problemString = buffer.toString();
+ }
+
+ // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+ int[] exceptionHandler = codeStream.generateCodeAttributeForProblemMethod(referenceBinding.scope.problemReporter().options.runtimeExceptionNameForCompileError, problemString);
+ attributeNumber++; // code attribute
+ completeCodeAttributeForClinit(
+ codeAttributeOffset,
+ exceptionHandler,
+ referenceBinding
+ .scope
+ .referenceCompilationUnit()
+ .compilationResult
+ .lineSeparatorPositions);
+ contents[attributeOffset++] = (byte) (attributeNumber >> 8);
+ contents[attributeOffset] = (byte) attributeNumber;
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a boggus constructor.
+ *
+ * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+ * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
+ */
+public void addProblemConstructor(
+ AbstractMethodDeclaration method,
+ MethodBinding methodBinding,
+ IProblem[] problems) {
+
+ // always clear the strictfp/native/abstract bit for a problem method
+ methodBinding.modifiers &= ~(AccStrictfp | AccNative | AccAbstract);
+
+ generateMethodInfoHeader(methodBinding);
+ // We know that we won't get more than 1 attribute: the code attribute
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 1; // Code attribute
+ int codeAttributeOffset = contentsOffset;
+ generateCodeAttributeHeader();
+ final ProblemReporter problemReporter = method.scope.problemReporter();
+ codeStream.reset(method, this);
+ String problemString = ""/*nonNLS*/;
+ if (problems != null) {
+ int max = problems.length;
+ StringBuffer buffer = new StringBuffer(25);
+ int count = 0;
+ for (int i = 0; i < max; i++) {
+ IProblem problem = problems[i];
+ if ((problem != null) && (problem.isError())) {
+ buffer.append("\t"/*nonNLS*/ + problem.getMessage() + "\n"/*nonNLS*/);
+ count++;
+ if (problemLine == 0) {
+ problemLine = problem.getSourceLineNumber();
+ }
+ }
+ } // insert the top line afterwards, once knowing how many problems we have to consider
+ if (count > 1) {
+ buffer.insert(0, Util.bind("compilation.unresolvedProblems"/*nonNLS*/));
+ } else {
+ buffer.insert(0, Util.bind("compilation.unresolvedProblem"/*nonNLS*/));
+ }
+ problemString = buffer.toString();
+ }
+
+ // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+ int[] exceptionHandler =
+ codeStream.generateCodeAttributeForProblemMethod(
+ problemReporter.options.runtimeExceptionNameForCompileError,
+ problemString);
+ completeCodeAttributeForProblemMethod(
+ method,
+ methodBinding,
+ codeAttributeOffset,
+ exceptionHandler,
+ ((SourceTypeBinding) methodBinding.declaringClass)
+ .scope
+ .referenceCompilationUnit()
+ .compilationResult
+ .lineSeparatorPositions);
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a boggus constructor.
+ * Reset the position inside the contents byte array to the savedOffset.
+ *
+ * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+ * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
+ * @param savedOffset <CODE>int</CODE>
+ */
+public void addProblemConstructor(AbstractMethodDeclaration method, MethodBinding methodBinding,IProblem[] problems, int savedOffset) {
+ // we need to move back the contentsOffset to the value at the beginning of the method
+ contentsOffset = savedOffset;
+ methodCount--; // we need to remove the method that causes the problem
+ addProblemConstructor(method, methodBinding, problems);
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a boggus method.
+ *
+ * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+ * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
+ */
+public void addProblemMethod(
+ AbstractMethodDeclaration method,
+ MethodBinding methodBinding,
+ IProblem[] problems) {
+ if (methodBinding.isAbstract() && methodBinding.declaringClass.isInterface()) {
+ method.abort(AbstractMethodDeclaration.AbortType);
+ }
+ // always clear the strictfp/native/abstract bit for a problem method
+ methodBinding.modifiers &= ~(AccStrictfp | AccNative | AccAbstract);
+
+ generateMethodInfoHeader(methodBinding);
+ // leave two spaces for the number of attributes
+ int attributeOffset = contentsOffset;
+ contentsOffset += 2;
+ ReferenceBinding[] thrownsExceptions;
+ int attributeNumber = 0;
+ int contentsLength;
+
+ if ((thrownsExceptions = methodBinding.thrownExceptions) != NoExceptions) {
+ // The method has a throw clause. So we need to add an exception attribute
+ // check that there is enough space to write all the bytes for the exception attribute
+ int length = thrownsExceptions.length;
+ if (contentsOffset + (8 + length * 2) >= (contentsLength = contents.length)) {
+ System.arraycopy(contents, 0, (contents = new byte[contentsLength + Math.max(INCREMENT_SIZE, (8 + length * 2))]), 0, contentsLength);
+ }
+ int exceptionNameIndex = constantPool.literalIndex(AttributeNamesConstants.ExceptionsName);
+ contents[contentsOffset++] = (byte) (exceptionNameIndex >> 8);
+ contents[contentsOffset++] = (byte) exceptionNameIndex;
+ // The attribute length = length * 2 + 2 in case of a exception attribute
+ int attributeLength = length * 2 + 2;
+ contents[contentsOffset++] = (byte) (attributeLength >> 24);
+ contents[contentsOffset++] = (byte) (attributeLength >> 16);
+ contents[contentsOffset++] = (byte) (attributeLength >> 8);
+ contents[contentsOffset++] = (byte) attributeLength;
+ contents[contentsOffset++] = (byte) (length >> 8);
+ contents[contentsOffset++] = (byte) length;
+ for (int i = 0; i < length; i++) {
+ int exceptionIndex = constantPool.literalIndex(thrownsExceptions[i]);
+ contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
+ contents[contentsOffset++] = (byte) exceptionIndex;
+ }
+ attributeNumber++;
+ }
+
+ // Deprecated attribute
+ // Check that there is enough space to write the deprecated attribute
+ if (contentsOffset + 6 >= (contentsLength = contents.length)) {
+ System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ if (methodBinding.isDeprecated()) {
+ int deprecatedAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
+ contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
+ // the length of a deprecated attribute is equals to 0
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+
+ attributeNumber++;
+ }
+
+ int codeAttributeOffset = contentsOffset;
+ generateCodeAttributeHeader();
+ final ProblemReporter problemReporter = method.scope.problemReporter();
+ codeStream.reset(method, this);
+ String problemString = ""/*nonNLS*/;
+ if (problems != null) {
+ int max = problems.length;
+ StringBuffer buffer = new StringBuffer(25);
+ int count = 0;
+ for (int i = 0; i < max; i++) {
+ IProblem problem = problems[i];
+ if ((problem != null)
+ && (problem.isError())
+ && (problem.getSourceStart() >= method.declarationSourceStart)
+ && (problem.getSourceEnd() <= method.declarationSourceEnd)) {
+ buffer.append("\t"/*nonNLS*/ + problem.getMessage() + "\n"/*nonNLS*/);
+ count++;
+ if (problemLine == 0) {
+ problemLine = problem.getSourceLineNumber();
+ }
+ problems[i] = null;
+ }
+ } // insert the top line afterwards, once knowing how many problems we have to consider
+ if (count > 1) {
+ buffer.insert(0, Util.bind("compilation.unresolvedProblems"/*nonNLS*/));
+ } else {
+ buffer.insert(0, Util.bind("compilation.unresolvedProblem"/*nonNLS*/));
+ }
+ problemString = buffer.toString();
+ }
+
+ // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+ int[] exceptionHandler =
+ codeStream.generateCodeAttributeForProblemMethod(
+ problemReporter.options.runtimeExceptionNameForCompileError,
+ problemString);
+ attributeNumber++; // code attribute
+ completeCodeAttributeForProblemMethod(
+ method,
+ methodBinding,
+ codeAttributeOffset,
+ exceptionHandler,
+ ((SourceTypeBinding) methodBinding.declaringClass)
+ .scope
+ .referenceCompilationUnit()
+ .compilationResult
+ .lineSeparatorPositions);
+ contents[attributeOffset++] = (byte) (attributeNumber >> 8);
+ contents[attributeOffset] = (byte) attributeNumber;
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a boggus method.
+ * Reset the position inside the contents byte array to the savedOffset.
+ *
+ * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+ * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
+ * @param savedOffset <CODE>int</CODE>
+ */
+public void addProblemMethod(AbstractMethodDeclaration method, MethodBinding methodBinding,IProblem[] problems, int savedOffset) {
+ // we need to move back the contentsOffset to the value at the beginning of the method
+ contentsOffset = savedOffset;
+ methodCount--; // we need to remove the method that causes the problem
+ addProblemMethod(method, methodBinding, problems);
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for all the special method infos.
+ * They are:
+ * - synthetic access methods
+ * - default abstract methods
+ */
+public void addSpecialMethods() {
+ // add all methods (default abstract methods and synthetic)
+
+ // default abstract methods
+ SourceTypeBinding currentBinding = referenceBinding;
+ MethodBinding[] defaultAbstractMethods = currentBinding.getDefaultAbstractMethods();
+ for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
+ generateMethodInfoHeader(defaultAbstractMethods[i]);
+ int methodAttributeOffset = contentsOffset;
+ int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
+ completeMethodInfo(methodAttributeOffset, attributeNumber);
+ }
+
+ // add synthetic methods infos
+ SyntheticAccessMethodBinding[] syntheticAccessMethods = currentBinding.syntheticAccessMethods();
+ if (syntheticAccessMethods != null) {
+ for (int i = 0, max = syntheticAccessMethods.length; i < max; i++) {
+ SyntheticAccessMethodBinding accessMethodBinding = syntheticAccessMethods[i];
+ switch (accessMethodBinding.accessType) {
+ case SyntheticAccessMethodBinding.FieldReadAccess :
+ // generate a method info to emulate an reading access to
+ // a private field
+ addSyntheticFieldReadAccessMethod(syntheticAccessMethods[i]);
+ break;
+ case SyntheticAccessMethodBinding.FieldWriteAccess :
+ // generate a method info to emulate an writing access to
+ // a private field
+ addSyntheticFieldWriteAccessMethod(syntheticAccessMethods[i]);
+ break;
+ case SyntheticAccessMethodBinding.MethodAccess :
+ // generate a method info to emulate an access to a private method
+ addSyntheticMethodAccessMethod(syntheticAccessMethods[i]);
+ break;
+ case SyntheticAccessMethodBinding.ConstructorAccess :
+ // generate a method info to emulate an access to a private method
+ addSyntheticConstructorAccessMethod(syntheticAccessMethods[i]);
+ }
+ }
+ }
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a synthetic method that
+ * generate an access to a private constructor.
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+ */
+public void addSyntheticConstructorAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+ generateMethodInfoHeader(methodBinding);
+ // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 2;
+ // Code attribute
+ int codeAttributeOffset = contentsOffset;
+ generateCodeAttributeHeader();
+ codeStream.init(this);
+ codeStream.generateSyntheticBodyForConstructorAccess(methodBinding);
+ completeCodeAttributeForSyntheticAccessMethod(methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass).scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions);
+ // add the synthetic attribute
+ int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+ contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+ // the length of a synthetic attribute is equals to 0
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a synthetic method that
+ * generate an read access to a private field.
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+ */
+public void addSyntheticFieldReadAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+ generateMethodInfoHeader(methodBinding);
+ // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 2;
+ // Code attribute
+ int codeAttributeOffset = contentsOffset;
+ generateCodeAttributeHeader();
+ codeStream.init(this);
+ codeStream.generateSyntheticBodyForFieldReadAccess(methodBinding);
+ completeCodeAttributeForSyntheticAccessMethod(methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass).scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions);
+ // add the synthetic attribute
+ int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+ contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+ // the length of a synthetic attribute is equals to 0
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a synthetic method that
+ * generate an write access to a private field.
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+ */
+public void addSyntheticFieldWriteAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+ generateMethodInfoHeader(methodBinding);
+ // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 2;
+ // Code attribute
+ int codeAttributeOffset = contentsOffset;
+ generateCodeAttributeHeader();
+ codeStream.init(this);
+ codeStream.generateSyntheticBodyForFieldWriteAccess(methodBinding);
+ completeCodeAttributeForSyntheticAccessMethod(methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass).scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions);
+ // add the synthetic attribute
+ int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+ contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+ // the length of a synthetic attribute is equals to 0
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a synthetic method that
+ * generate an access to a private method.
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+ */
+public void addSyntheticMethodAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+ generateMethodInfoHeader(methodBinding);
+ // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 2;
+ // Code attribute
+ int codeAttributeOffset = contentsOffset;
+ generateCodeAttributeHeader();
+ codeStream.init(this);
+ codeStream.generateSyntheticBodyForMethodAccess(methodBinding);
+ completeCodeAttributeForSyntheticAccessMethod(methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass).scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions);
+ // add the synthetic attribute
+ int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+ contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+ // the length of a synthetic attribute is equals to 0
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+}
+/**
+ * INTERNAL USE-ONLY
+ * Build all the directories and subdirectories corresponding to the packages names
+ * into the directory specified in parameters.
+ *
+ * outputPath is formed like:
+ * c:\temp\ the last character is a file separator
+ * relativeFileName is formed like:
+ * java\lang\String.class *
+ *
+ * @param outputPath java.lang.String
+ * @param relativeFileName java.lang.String
+ * @return java.lang.String
+ */
+public static String buildAllDirectoriesInto(String outputPath, String relativeFileName) throws IOException {
+ char fileSeparatorChar = File.separatorChar;
+ String fileSeparator = File.separator;
+ File f;
+ // First we ensure that the outputPath exists
+ outputPath = outputPath.replace('/', fileSeparatorChar);
+ // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
+ if (outputPath.endsWith(fileSeparator)) {
+ outputPath = outputPath.substring(0, outputPath.length() - 1);
+ }
+ f = new File(outputPath);
+ if (f.exists()) {
+ if (!f.isDirectory()) {
+ System.out.println(Util.bind("output.isFile"/*nonNLS*/,f.getAbsolutePath()));
+ throw new IOException(Util.bind("output.isFileNotDirectory"/*nonNLS*/));
+ }
+ } else {
+ // we have to create that directory
+ if (!f.mkdirs()) {
+ System.out.println(Util.bind("output.dirName"/*nonNLS*/,f.getAbsolutePath()));
+ throw new IOException(Util.bind("output.notValidAll"/*nonNLS*/));
+ }
+ }
+ StringBuffer outDir = new StringBuffer(outputPath);
+ outDir.append(fileSeparator);
+ StringTokenizer tokenizer = new StringTokenizer(relativeFileName, fileSeparator);
+ String token = tokenizer.nextToken();
+ while (tokenizer.hasMoreTokens()) {
+ f = new File(outDir.append(token).append(fileSeparator).toString());
+ if (f.exists()) {
+ // The outDir already exists, so we proceed the next entry
+ // System.out.println("outDir: " + outDir + " already exists.");
+ } else {
+ // Need to add the outDir
+ if (!f.mkdir()) {
+ System.out.println(Util.bind("output.fileName"/*nonNLS*/,f.getName()));
+ throw new IOException(Util.bind("output.notValid"/*nonNLS*/));
+ }
+ }
+ token = tokenizer.nextToken();
+ }
+ // token contains the last one
+ return outDir.append(token).toString();
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method completes the creation of the code attribute by setting
+ * - the attribute_length
+ * - max_stack
+ * - max_locals
+ * - code_length
+ * - exception table
+ * - and debug attributes if necessary.
+ *
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param codeAttributeOffset <CODE>int</CODE>
+ */
+public void completeCodeAttribute(int codeAttributeOffset) {
+ // reinitialize the localContents with the byte modified by the code stream
+ byte[] localContents = contents = codeStream.bCodeStream;
+ int localContentsOffset = codeStream.classFileOffset;
+ // codeAttributeOffset is the position inside localContents byte array before we started to write
+ // any information about the codeAttribute
+ // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
+ // to get the right position, 6 for the max_stack etc...
+ int contentsLength;
+ int code_length = codeStream.position;
+ if (code_length > 65535) {
+ codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(codeStream.methodDeclaration);
+ }
+ if (localContentsOffset + 20 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ int max_stack = codeStream.stackMax;
+ localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+ localContents[codeAttributeOffset + 7] = (byte) max_stack;
+ int max_locals = codeStream.maxLocals;
+ localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+ localContents[codeAttributeOffset + 9] = (byte) max_locals;
+ localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+ localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+ localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+ localContents[codeAttributeOffset + 13] = (byte) code_length;
+
+ // write the exception table
+ int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
+ ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
+ int exSize;
+ if (localContentsOffset + (exSize = (exceptionHandlersNumber * 8 + 2)) >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + (exSize > INCREMENT_SIZE ? exSize : INCREMENT_SIZE)]), 0, contentsLength);
+ }
+ // there is no exception table, so we need to offset by 2 the current offset and move
+ // on the attribute generation
+ localContents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
+ localContents[localContentsOffset++] = (byte) exceptionHandlersNumber;
+ for (int i = 0; i < exceptionHandlersNumber; i++) {
+ ExceptionLabel exceptionHandler = exceptionHandlers[i];
+ int start = exceptionHandler.start;
+ localContents[localContentsOffset++] = (byte) (start >> 8);
+ localContents[localContentsOffset++] = (byte) start;
+ int end = exceptionHandler.end;
+ localContents[localContentsOffset++] = (byte) (end >> 8);
+ localContents[localContentsOffset++] = (byte) end;
+ int handlerPC = exceptionHandler.position;
+ localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
+ localContents[localContentsOffset++] = (byte) handlerPC;
+ if (exceptionHandler.exceptionType == null) {
+ // any exception handler
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ } else {
+ int nameIndex;
+ if (exceptionHandler.exceptionType == TypeBinding.NullBinding) {
+ /* represents ClassNotFoundException, see class literal access*/
+ nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
+ } else {
+ nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
+ }
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) nameIndex;
+ }
+ }
+
+ // debug attributes
+ int codeAttributeAttributeOffset = localContentsOffset;
+ int attributeNumber = 0;
+ // leave two bytes for the attribute_length
+ localContentsOffset += 2;
+
+ // first we handle the linenumber attribute
+ if (codeStream.generateLineNumberAttributes) {
+ /* Create and add the line number attribute (used for debugging)
+ * Build the pairs of:
+ * (bytecodePC lineNumber)
+ * according to the table of start line indexes and the pcToSourceMap table
+ * contained into the codestream
+ */
+ /** OLD CODE
+ int[][] pcToSourceMapTable;
+ int previousLineNumber;
+ int[] flatTable;
+ int index;
+ int startLineIndexes[] = codeStream.methodDeclaration.scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions;
+ int max = startLineIndexes.length;
+ */
+ int[] pcToSourceMapTable;
+ if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null) && (codeStream.pcToSourceMapSize != 0)) {
+ int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+ if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
+ int lineNumberTableOffset = localContentsOffset;
+ localContentsOffset += 6; // leave space for attribute_length and line_number_table_length
+ /** OLD CODE
+ previousLineNumber = 0;
+
+ // Seems like do would be better, but this preserves the existing behavior.
+
+ flatTable = new int[code_length];
+ for (int i = codeStream.pcToSourceMapSize - 1; i >= 0; i--) {
+ // entry contains the following structure:
+ // position 1: startPC
+ // position 2: endPC
+ // position 3: sourceStart
+ // position 4: sourceEnd
+ // Compute the line number for a given source position
+ index = searchLineNumber(startLineIndexes, pcToSourceMapTable[i][2]);
+ for (int j = pcToSourceMapTable[i][0]; j < pcToSourceMapTable[i][1]; j++)
+ flatTable[j] = index;
+ }
+ previousLineNumber = -1;
+
+ */
+ int numberOfEntries = 0;
+ int length = codeStream.pcToSourceMapSize;
+ /** OLD CODE
+ int length = flatTable.length;
+ for (int i = 0; i < length; i++) {
+ if (flatTable[i] != previousLineNumber) {
+ previousLineNumber = flatTable[i];
+ // write the entry
+ if (localContentsOffset + 4 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ localContents[localContentsOffset++] = (byte) (i >> 8);
+ localContents[localContentsOffset++] = (byte) i;
+ localContents[localContentsOffset++] = (byte) (previousLineNumber >> 8);
+ localContents[localContentsOffset++] = (byte) previousLineNumber;
+ numberOfEntries++;
+ }
+ }
+ */
+ for (int i = 0; i < length;) {
+ // write the entry
+ if (localContentsOffset + 4 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ int pc = pcToSourceMapTable[i++];
+ localContents[localContentsOffset++] = (byte) (pc >> 8);
+ localContents[localContentsOffset++] = (byte) pc;
+ int lineNumber = pcToSourceMapTable[i++];
+ localContents[localContentsOffset++] = (byte) (lineNumber >> 8);
+ localContents[localContentsOffset++] = (byte) lineNumber;
+ numberOfEntries++;
+ }
+ // now we change the size of the line number attribute
+ int lineNumberAttr_length = numberOfEntries * 4 + 2;
+ localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
+ localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
+ localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
+ localContents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
+ localContents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
+ localContents[lineNumberTableOffset++] = (byte) numberOfEntries;
+ attributeNumber++;
+ }
+ }
+
+
+
+ // then we do the local variable attribute
+ if (codeStream.generateLocalVariableTableAttributes) {
+ int localVariableTableOffset = localContentsOffset;
+ int numberOfEntries = 0;
+ int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+ if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) localVariableNameIndex;
+ localContentsOffset += 6; // leave space for attribute_length and local_variable_table_length
+ int nameIndex;
+ int descriptorIndex;
+ if (!codeStream.methodDeclaration.isStatic()) {
+ numberOfEntries++;
+ if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ localContentsOffset += 2; // the startPC for this is always 0
+ localContents[localContentsOffset++] = (byte) (code_length >> 8);
+ localContents[localContentsOffset++] = (byte) code_length;
+ nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(codeStream.methodDeclaration.binding.declaringClass.signature());
+ localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ localContents[localContentsOffset++] = (byte) descriptorIndex;
+ localContentsOffset += 2; // the resolved position for this is always 0
+ }
+ for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+ LocalVariableBinding localVariable = codeStream.locals[i];
+ for (int j = 0; j < localVariable.initializationCount; j++) {
+ int startPC = localVariable.initializationPCs[j << 1];
+ int endPC = localVariable.initializationPCs[(j << 1) + 1];
+ if (startPC != endPC) { // only entries for non zero length
+ int currentLength;
+ if (endPC == -1) {
+ localVariable.declaringScope.problemReporter().abortDueToInternalError(Util.bind("abort.invalidAttribute"/*nonNLS*/,new String(localVariable.name)), (AstNode) localVariable.declaringScope.methodScope().referenceContext);
+ }
+ if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ // now we can safely add the local entry
+ numberOfEntries++;
+ localContents[localContentsOffset++] = (byte) (startPC >> 8);
+ localContents[localContentsOffset++] = (byte) startPC;
+ int length = endPC - startPC;
+ localContents[localContentsOffset++] = (byte) (length >> 8);
+ localContents[localContentsOffset++] = (byte) length;
+ nameIndex = constantPool.literalIndex(localVariable.name);
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+ localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ localContents[localContentsOffset++] = (byte) descriptorIndex;
+ int resolvedPosition = localVariable.resolvedPosition;
+ localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+ localContents[localContentsOffset++] = (byte) resolvedPosition;
+ }
+ }
+ }
+ int value = numberOfEntries * 10 + 2;
+ localVariableTableOffset += 2;
+ localContents[localVariableTableOffset++] = (byte) (value >> 24);
+ localContents[localVariableTableOffset++] = (byte) (value >> 16);
+ localContents[localVariableTableOffset++] = (byte) (value >> 8);
+ localContents[localVariableTableOffset++] = (byte) value;
+ localContents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+ localContents[localVariableTableOffset] = (byte) numberOfEntries;
+ attributeNumber++;
+ }
+ // update the number of attributes
+ // ensure first that there is enough space available inside the localContents array
+ if (codeAttributeAttributeOffset + 2 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+ localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+
+ // update the attribute length
+ int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+ localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+ localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+ localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+ localContents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+ contentsOffset = localContentsOffset;
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method completes the creation of the code attribute by setting
+ * - the attribute_length
+ * - max_stack
+ * - max_locals
+ * - code_length
+ * - exception table
+ * - and debug attributes if necessary.
+ *
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param codeAttributeOffset <CODE>int</CODE>
+ */
+public void completeCodeAttributeForClinit(int codeAttributeOffset) {
+ // reinitialize the contents with the byte modified by the code stream
+ byte[] localContents = contents = codeStream.bCodeStream;
+ int localContentsOffset = codeStream.classFileOffset;
+ // codeAttributeOffset is the position inside contents byte array before we started to write
+ // any information about the codeAttribute
+ // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
+ // to get the right position, 6 for the max_stack etc...
+ int contentsLength;
+ int code_length = codeStream.position;
+ if (code_length > 65535) {
+ codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(codeStream.methodDeclaration.scope.referenceType());
+ }
+ if (localContentsOffset + 20 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ int max_stack = codeStream.stackMax;
+ localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+ localContents[codeAttributeOffset + 7] = (byte) max_stack;
+ int max_locals = codeStream.maxLocals;
+ localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+ localContents[codeAttributeOffset + 9] = (byte) max_locals;
+ localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+ localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+ localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+ localContents[codeAttributeOffset + 13] = (byte) code_length;
+
+ // write the exception table
+ int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
+ ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
+ int exSize;
+ if (localContentsOffset + (exSize = (exceptionHandlersNumber * 8 + 2)) >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + (exSize > INCREMENT_SIZE ? exSize : INCREMENT_SIZE)]), 0, contentsLength);
+ }
+ // there is no exception table, so we need to offset by 2 the current offset and move
+ // on the attribute generation
+ localContents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
+ localContents[localContentsOffset++] = (byte) exceptionHandlersNumber;
+ for (int i = 0; i < exceptionHandlersNumber; i++) {
+ ExceptionLabel exceptionHandler = exceptionHandlers[i];
+ int start = exceptionHandler.start;
+ localContents[localContentsOffset++] = (byte) (start >> 8);
+ localContents[localContentsOffset++] = (byte) start;
+ int end = exceptionHandler.end;
+ localContents[localContentsOffset++] = (byte) (end >> 8);
+ localContents[localContentsOffset++] = (byte) end;
+ int handlerPC = exceptionHandler.position;
+ localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
+ localContents[localContentsOffset++] = (byte) handlerPC;
+ if (exceptionHandler.exceptionType == null) {
+ // any exception handler
+ localContentsOffset += 2;
+ } else {
+ int nameIndex;
+ if (exceptionHandler.exceptionType == TypeBinding.NullBinding) {
+ /* represents denote ClassNotFoundException, see class literal access*/
+ nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
+ } else {
+ nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
+ }
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) nameIndex;
+ }
+ }
+
+ // debug attributes
+ int codeAttributeAttributeOffset = localContentsOffset;
+ int attributeNumber = 0;
+ // leave two bytes for the attribute_length
+ localContentsOffset += 2;
+
+ // first we handle the linenumber attribute
+ if (codeStream.generateLineNumberAttributes) {
+ /* Create and add the line number attribute (used for debugging)
+ * Build the pairs of:
+ * (bytecodePC lineNumber)
+ * according to the table of start line indexes and the pcToSourceMap table
+ * contained into the codestream
+ */
+ int[] pcToSourceMapTable;
+ if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null) && (codeStream.pcToSourceMapSize != 0)) {
+ int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+ if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
+ int lineNumberTableOffset = localContentsOffset;
+ localContentsOffset += 6; // leave space for attribute_length and line_number_table_length
+ int numberOfEntries = 0;
+ int length = codeStream.pcToSourceMapSize;
+ for (int i = 0; i < length;) {
+ // write the entry
+ if (localContentsOffset + 4 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ int pc = pcToSourceMapTable[i++];
+ localContents[localContentsOffset++] = (byte) (pc >> 8);
+ localContents[localContentsOffset++] = (byte) pc;
+ int lineNumber = pcToSourceMapTable[i++];
+ localContents[localContentsOffset++] = (byte) (lineNumber >> 8);
+ localContents[localContentsOffset++] = (byte) lineNumber;
+ numberOfEntries++;
+ }
+ // now we change the size of the line number attribute
+ int lineNumberAttr_length = numberOfEntries * 4 + 2;
+ localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
+ localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
+ localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
+ localContents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
+ localContents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
+ localContents[lineNumberTableOffset++] = (byte) numberOfEntries;
+ attributeNumber++;
+ }
+ }
+
+
+
+ // then we do the local variable attribute
+ if (codeStream.generateLocalVariableTableAttributes) {
+ int localVariableTableOffset = localContentsOffset;
+ int numberOfEntries = 0;
+ // codeAttribute.addLocalVariableTableAttribute(this);
+ if ((codeStream.pcToSourceMap != null) && (codeStream.pcToSourceMapSize != 0)) {
+ int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+ if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) localVariableNameIndex;
+ localContentsOffset += 6; // leave space for attribute_length and local_variable_table_length
+ int nameIndex;
+ int descriptorIndex;
+ for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+ LocalVariableBinding localVariable = codeStream.locals[i];
+ for (int j = 0; j < localVariable.initializationCount; j++) {
+ int startPC = localVariable.initializationPCs[j << 1];
+ int endPC = localVariable.initializationPCs[ (j << 1) + 1];
+ if (startPC != endPC) { // only entries for non zero length
+ int currentLength;
+ if (endPC == -1) {
+ localVariable.declaringScope.problemReporter().abortDueToInternalError(Util.bind("abort.invalidAttribute"/*nonNLS*/,new String(localVariable.name)), (AstNode) localVariable.declaringScope.methodScope().referenceContext);
+ }
+ if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ // now we can safely add the local entry
+ numberOfEntries++;
+ localContents[localContentsOffset++] = (byte) (startPC >> 8);
+ localContents[localContentsOffset++] = (byte) startPC;
+ int length = endPC - startPC;
+ localContents[localContentsOffset++] = (byte) (length >> 8);
+ localContents[localContentsOffset++] = (byte) length;
+ nameIndex = constantPool.literalIndex(localVariable.name);
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+ localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ localContents[localContentsOffset++] = (byte) descriptorIndex;
+ int resolvedPosition = localVariable.resolvedPosition;
+ localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+ localContents[localContentsOffset++] = (byte) resolvedPosition;
+ }
+ }
+ }
+ int value = numberOfEntries * 10 + 2;
+ localVariableTableOffset += 2;
+ localContents[localVariableTableOffset++] = (byte) (value >> 24);
+ localContents[localVariableTableOffset++] = (byte) (value >> 16);
+ localContents[localVariableTableOffset++] = (byte) (value >> 8);
+ localContents[localVariableTableOffset++] = (byte) value;
+ localContents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+ localContents[localVariableTableOffset] = (byte) numberOfEntries;
+ attributeNumber++;
+ }
+ }
+ // update the number of attributes
+ // ensure first that there is enough space available inside the contents array
+ if (codeAttributeAttributeOffset + 2 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+ localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+ // update the attribute length
+ int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+ localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+ localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+ localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+ localContents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+ contentsOffset = localContentsOffset;
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method completes the creation of the code attribute by setting
+ * - the attribute_length
+ * - max_stack
+ * - max_locals
+ * - code_length
+ * - exception table
+ * - and debug attributes if necessary.
+ *
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param codeAttributeOffset <CODE>int</CODE>
+ * @param exceptionHandler int[]
+ * @param startIndexes int[]
+ */
+public void completeCodeAttributeForClinit(int codeAttributeOffset, int[] exceptionHandler, int[] startLineIndexes) {
+ // reinitialize the contents with the byte modified by the code stream
+ byte[] localContents = contents = codeStream.bCodeStream;
+ int localContentsOffset = codeStream.classFileOffset;
+ // codeAttributeOffset is the position inside contents byte array before we started to write
+ // any information about the codeAttribute
+ // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
+ // to get the right position, 6 for the max_stack etc...
+ int contentsLength;
+ int code_length = codeStream.position;
+ if (code_length > 65535) {
+ codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(codeStream.methodDeclaration.scope.referenceType());
+ }
+ if (localContentsOffset + 20 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ int max_stack = codeStream.stackMax;
+ localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+ localContents[codeAttributeOffset + 7] = (byte) max_stack;
+ int max_locals = codeStream.maxLocals;
+ localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+ localContents[codeAttributeOffset + 9] = (byte) max_locals;
+ localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+ localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+ localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+ localContents[codeAttributeOffset + 13] = (byte) code_length;
+
+ // write the exception table
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 1;
+ int start = exceptionHandler[0];
+ localContents[localContentsOffset++] = (byte) (start >> 8);
+ localContents[localContentsOffset++] = (byte) start;
+ int end = exceptionHandler[1];
+ localContents[localContentsOffset++] = (byte) (end >> 8);
+ localContents[localContentsOffset++] = (byte) end;
+ int handlerPC = exceptionHandler[2];
+ localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
+ localContents[localContentsOffset++] = (byte) handlerPC;
+ int nameIndex = constantPool.literalIndexForJavaLangException();
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) nameIndex;
+
+ // debug attributes
+ int codeAttributeAttributeOffset = localContentsOffset;
+ int attributeNumber = 0; // leave two bytes for the attribute_length
+ localContentsOffset += 2; // first we handle the linenumber attribute
+
+ // first we handle the linenumber attribute
+ if (codeStream.generateLineNumberAttributes) {
+ /* Create and add the line number attribute (used for debugging)
+ * Build the pairs of:
+ * (bytecodePC lineNumber)
+ * according to the table of start line indexes and the pcToSourceMap table
+ * contained into the codestream
+ */
+ int index = 0, max = startLineIndexes.length;
+ int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+ localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 6;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 1;
+ // first entry at pc = 0
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = (byte) (problemLine >> 8);
+ localContents[localContentsOffset++] = (byte) problemLine;
+ // now we change the size of the line number attribute
+ attributeNumber++;
+ }
+
+ // then we do the local variable attribute
+ if (codeStream.generateLocalVariableTableAttributes) {
+ int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+ if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) localVariableNameIndex;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 2;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ attributeNumber++;
+ }
+
+ // update the number of attributes
+ // ensure first that there is enough space available inside the contents array
+ if (codeAttributeAttributeOffset + 2 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+ localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+ // update the attribute length
+ int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+ localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+ localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+ localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+ localContents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+ contentsOffset = localContentsOffset;
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method completes the creation of the code attribute by setting
+ * - the attribute_length
+ * - max_stack
+ * - max_locals
+ * - code_length
+ * - exception table
+ * - and debug attributes if necessary.
+ *
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param codeAttributeOffset <CODE>int</CODE>
+ * @param exceptionHandler int[]
+ */
+public void completeCodeAttributeForProblemMethod(AbstractMethodDeclaration method, MethodBinding binding, int codeAttributeOffset, int[] exceptionHandler, int[] startLineIndexes) {
+ // reinitialize the localContents with the byte modified by the code stream
+ byte[] localContents = contents = codeStream.bCodeStream;
+ int localContentsOffset = codeStream.classFileOffset;
+ // codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc...
+ int max_stack = codeStream.stackMax;
+ localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+ localContents[codeAttributeOffset + 7] = (byte) max_stack;
+ int max_locals = codeStream.maxLocals;
+ localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+ localContents[codeAttributeOffset + 9] = (byte) max_locals;
+ int code_length = codeStream.position;
+ localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+ localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+ localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+ localContents[codeAttributeOffset + 13] = (byte) code_length;
+ // write the exception table
+ int contentsLength;
+ if (localContentsOffset + 50 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 1;
+ int start = exceptionHandler[0];
+ localContents[localContentsOffset++] = (byte) (start >> 8);
+ localContents[localContentsOffset++] = (byte) start;
+ int end = exceptionHandler[1];
+ localContents[localContentsOffset++] = (byte) (end >> 8);
+ localContents[localContentsOffset++] = (byte) end;
+ int handlerPC = exceptionHandler[2];
+ localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
+ localContents[localContentsOffset++] = (byte) handlerPC;
+ int nameIndex = constantPool.literalIndexForJavaLangException();
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) nameIndex; // debug attributes
+ int codeAttributeAttributeOffset = localContentsOffset;
+ int attributeNumber = 0; // leave two bytes for the attribute_length
+ localContentsOffset += 2; // first we handle the linenumber attribute
+
+ if (codeStream.generateLineNumberAttributes) {
+ /* Create and add the line number attribute (used for debugging)
+ * Build the pairs of:
+ * (bytecodePC lineNumber)
+ * according to the table of start line indexes and the pcToSourceMap table
+ * contained into the codestream
+ */
+ int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+ localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 6;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 1;
+ if (problemLine == 0) {
+ problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
+ }
+ // first entry at pc = 0
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = (byte) (problemLine >> 8);
+ localContents[localContentsOffset++] = (byte) problemLine;
+ // now we change the size of the line number attribute
+ attributeNumber++;
+ }
+
+ // then we do the local variable attribute
+ if (codeStream.generateLocalVariableTableAttributes) {
+ // compute the resolved position for the arguments of the method
+ int argSize;
+ int localVariableTableOffset = localContentsOffset;
+ int numberOfEntries = 0;
+ // codeAttribute.addLocalVariableTableAttribute(this);
+ int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+ if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) localVariableNameIndex;
+ localContentsOffset += 6; // leave space for attribute_length and local_variable_table_length
+ int descriptorIndex;
+ if (!codeStream.methodDeclaration.isStatic()) {
+ numberOfEntries++;
+ if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = (byte) (code_length >> 8);
+ localContents[localContentsOffset++] = (byte) code_length;
+ nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(codeStream.methodDeclaration.binding.declaringClass.signature());
+ localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ localContents[localContentsOffset++] = (byte) descriptorIndex;
+ // the resolved position for this is always 0
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ }
+ if (binding.isConstructor()) {
+ ReferenceBinding declaringClass = binding.declaringClass;
+ if (declaringClass.isNestedType()) {
+ NestedTypeBinding methodDeclaringClass = (NestedTypeBinding) declaringClass;
+ argSize = methodDeclaringClass.syntheticArgumentsOffset;
+ SyntheticArgumentBinding[] syntheticArguments;
+ if ((syntheticArguments = methodDeclaringClass.syntheticEnclosingInstances()) != null) {
+ for (int i = 0, max = syntheticArguments.length; i < max; i++) {
+ LocalVariableBinding localVariable = syntheticArguments[i];
+ int currentLength;
+ if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ // now we can safely add the local entry
+ numberOfEntries++;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = (byte) (code_length >> 8);
+ localContents[localContentsOffset++] = (byte) code_length;
+ nameIndex = constantPool.literalIndex(localVariable.name);
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+ localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ localContents[localContentsOffset++] = (byte) descriptorIndex;
+ int resolvedPosition = localVariable.resolvedPosition;
+ localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+ localContents[localContentsOffset++] = (byte) resolvedPosition;
+ }
+ }
+ } else {
+ argSize = 1;
+ }
+ } else {
+ argSize = binding.isStatic() ? 0 : 1;
+ }
+ if (method.binding != null) {
+ TypeBinding[] parameters = method.binding.parameters;
+ Argument[] arguments = method.arguments;
+ if ((parameters != null) && (arguments != null)) {
+ for (int i = 0, max = parameters.length; i < max; i++) {
+ TypeBinding argumentBinding = parameters[i];
+ int currentLength;
+ if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ // now we can safely add the local entry
+ numberOfEntries++;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = (byte) (code_length >> 8);
+ localContents[localContentsOffset++] = (byte) code_length;
+ nameIndex = constantPool.literalIndex(arguments[i].name);
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(argumentBinding.signature());
+ localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ localContents[localContentsOffset++] = (byte) descriptorIndex;
+ int resolvedPosition = argSize;
+ if ((argumentBinding == TypeBinding.LongBinding) || (argumentBinding == TypeBinding.DoubleBinding))
+ argSize += 2;
+ else
+ argSize++;
+ localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+ localContents[localContentsOffset++] = (byte) resolvedPosition;
+ }
+ }
+ }
+ int value = numberOfEntries * 10 + 2;
+ localVariableTableOffset += 2;
+ localContents[localVariableTableOffset++] = (byte) (value >> 24);
+ localContents[localVariableTableOffset++] = (byte) (value >> 16);
+ localContents[localVariableTableOffset++] = (byte) (value >> 8);
+ localContents[localVariableTableOffset++] = (byte) value;
+ localContents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+ localContents[localVariableTableOffset] = (byte) numberOfEntries;
+ attributeNumber++;
+ }
+
+ // update the number of attributes// ensure first that there is enough space available inside the localContents array
+ if (codeAttributeAttributeOffset + 2 >= (contentsLength = localContents.length)) {
+ System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+ localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+ // update the attribute length
+ int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+ localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+ localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+ localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+ localContents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+ contentsOffset = localContentsOffset;
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method completes the creation of the code attribute by setting
+ * - the attribute_length
+ * - max_stack
+ * - max_locals
+ * - code_length
+ * - exception table
+ * - and debug attributes if necessary.
+ *
+ * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param codeAttributeOffset <CODE>int</CODE>
+ */
+public void completeCodeAttributeForSyntheticAccessMethod(SyntheticAccessMethodBinding binding, int codeAttributeOffset, int[] startLineIndexes) {
+ // reinitialize the contents with the byte modified by the code stream
+ contents = codeStream.bCodeStream;
+ int localContentsOffset = codeStream.classFileOffset;
+ // codeAttributeOffset is the position inside contents byte array before we started to write
+ // any information about the codeAttribute
+ // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
+ // to get the right position, 6 for the max_stack etc...
+ int max_stack = codeStream.stackMax;
+ contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+ contents[codeAttributeOffset + 7] = (byte) max_stack;
+ int max_locals = codeStream.maxLocals;
+ contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+ contents[codeAttributeOffset + 9] = (byte) max_locals;
+ int code_length = codeStream.position;
+ contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+ contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+ contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+ contents[codeAttributeOffset + 13] = (byte) code_length;
+ int contentsLength;
+ if ((localContentsOffset + 40) >= (contentsLength = contents.length)) {
+ System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ // there is no exception table, so we need to offset by 2 the current offset and move
+ // on the attribute generation
+ localContentsOffset += 2;
+ // debug attributes
+ int codeAttributeAttributeOffset = localContentsOffset;
+ int attributeNumber = 0;
+ // leave two bytes for the attribute_length
+ localContentsOffset += 2;
+
+ // first we handle the linenumber attribute
+ if (codeStream.generateLineNumberAttributes) {
+ int index = 0, max = startLineIndexes.length;
+ int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+ contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+ contents[localContentsOffset++] = (byte) lineNumberNameIndex;
+ int lineNumberTableOffset = localContentsOffset;
+ localContentsOffset += 6; // leave space for attribute_length and line_number_table_length
+ // Seems like do would be better, but this preserves the existing behavior.
+ index = searchLineNumber(startLineIndexes, binding.sourceStart);
+ contents[localContentsOffset++] = 0;
+ contents[localContentsOffset++] = 0;
+ contents[localContentsOffset++] = (byte) (index >> 8);
+ contents[localContentsOffset++] = (byte) index;
+ // now we change the size of the line number attribute
+ contents[lineNumberTableOffset++] = 0;
+ contents[lineNumberTableOffset++] = 0;
+ contents[lineNumberTableOffset++] = 0;
+ contents[lineNumberTableOffset++] = 6;
+ contents[lineNumberTableOffset++] = 0;
+ contents[lineNumberTableOffset++] = 1;
+ attributeNumber++;
+ }
+
+ // then we do the local variable attribute
+ if (codeStream.generateLocalVariableTableAttributes) {
+ int localVariableTableOffset = localContentsOffset;
+ int numberOfEntries = 0;
+ int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+ if (localContentsOffset + 8 > (contentsLength = contents.length)) {
+ System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+ contents[localContentsOffset++] = (byte) localVariableNameIndex;
+ localContentsOffset += 6; // leave space for attribute_length and local_variable_table_length
+ int nameIndex;
+ int descriptorIndex;
+ for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+ LocalVariableBinding localVariable = codeStream.locals[i];
+ for (int j = 0; j < localVariable.initializationCount; j++) {
+ int startPC = localVariable.initializationPCs[j << 1];
+ int endPC = localVariable.initializationPCs[(j << 1) + 1];
+ if (startPC != endPC) { // only entries for non zero length
+ int currentLength;
+ if (endPC == -1) {
+ localVariable.declaringScope.problemReporter().abortDueToInternalError(Util.bind("abort.invalidAttribute"/*nonNLS*/,new String(localVariable.name)), (AstNode) localVariable.declaringScope.methodScope().referenceContext);
+ }
+ if (localContentsOffset + 10 > (contentsLength = contents.length)) {
+ System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ // now we can safely add the local entry
+ numberOfEntries++;
+ contents[localContentsOffset++] = (byte) (startPC >> 8);
+ contents[localContentsOffset++] = (byte) startPC;
+ int length = endPC - startPC;
+ contents[localContentsOffset++] = (byte) (length >> 8);
+ contents[localContentsOffset++] = (byte) length;
+ nameIndex = constantPool.literalIndex(localVariable.name);
+ contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ contents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+ contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ contents[localContentsOffset++] = (byte) descriptorIndex;
+ int resolvedPosition = localVariable.resolvedPosition;
+ contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+ contents[localContentsOffset++] = (byte) resolvedPosition;
+ }
+ }
+ }
+ int value = numberOfEntries * 10 + 2;
+ localVariableTableOffset += 2;
+ contents[localVariableTableOffset++] = (byte) (value >> 24);
+ contents[localVariableTableOffset++] = (byte) (value >> 16);
+ contents[localVariableTableOffset++] = (byte) (value >> 8);
+ contents[localVariableTableOffset++] = (byte) value;
+ contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+ contents[localVariableTableOffset] = (byte) numberOfEntries;
+ attributeNumber++;
+ }
+
+ // update the number of attributes
+ // ensure first that there is enough space available inside the contents array
+ if (codeAttributeAttributeOffset + 2 >= (contentsLength = contents.length)) {
+ System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+ contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+
+ // update the attribute length
+ int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+ contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+ contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+ contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+ contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+ contentsOffset = localContentsOffset;
+}
+/**
+ * INTERNAL USE-ONLY
+ * Complete the creation of a method info by setting up the number of attributes at the right offset.
+ *
+ * @param methodAttributeOffset <CODE>int</CODE>
+ * @param attributeNumber <CODE>int</CODE>
+ */
+public void completeMethodInfo(int methodAttributeOffset, int attributeNumber) {
+ // update the number of attributes
+ contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
+ contents[methodAttributeOffset] = (byte) attributeNumber;
+}
+/*
+ * INTERNAL USE-ONLY
+ * Innerclasses get their name computed as they are generated, since some may not
+ * be actually outputed if sitting inside unreachable code.
+ *
+ * @param localType org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding
+ */
+public char[] computeConstantPoolName(LocalTypeBinding localType) {
+ if (localType.constantPoolName() != null) {
+ return localType.constantPoolName();
+ }
+
+ // delegates to the outermost enclosing classfile, since it is the only one with a global vision of its innertypes.
+ if (enclosingClassFile != null) {
+ return this.outerMostEnclosingClassFile().computeConstantPoolName(localType);
+ }
+
+ if (nameUsage == null) {
+ nameUsage = new CharArrayCache();
+ }
+ if (localType.isMemberType()) { // catches member types of local types
+ return CharOperation.concat(
+ localType.enclosingType().constantPoolName(),
+ localType.sourceName,
+ '$');
+ } else {
+ char[][] compoundName = (char[][]) referenceBinding.compoundName.clone();
+ int last = compoundName.length - 1;
+ StringBuffer nameBuffer = new StringBuffer().append(compoundName[last]);
+ // retrieve the number of use of the combination
+ char[] simpleName = localType.sourceName;
+ //if (simpleName == null) simpleName = new char[]{}; // for anonymous
+ int nameCount = nameUsage.get(simpleName); // -1 if not found
+ nameCount = nameCount == -1 ? 1 : nameCount + 1;
+ nameBuffer.append('$').append(nameCount);
+ nameUsage.put(simpleName, nameCount);
+ if (!localType.isAnonymousType()) { // named local type
+ nameBuffer.append('$').append(simpleName);
+ }
+ compoundName[last] = nameBuffer.toString().toCharArray();
+ return CharOperation.concatWith(compoundName, '/');
+ }
+}
+/**
+ * INTERNAL USE-ONLY
+ * Request the creation of a ClassFile compatible representation of a problematic type
+ *
+ * @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
+ * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
+ */
+public static void createProblemType(TypeDeclaration typeDeclaration, CompilationResult unitResult) {
+ SourceTypeBinding typeBinding = typeDeclaration.binding;
+ ClassFile classFile = new ClassFile(typeBinding, null, true);
+
+ // inner attributes
+ if (typeBinding.isMemberType())
+ classFile.recordEnclosingTypeAttributes(typeBinding);
+
+ // add its fields
+ FieldBinding[] fields = typeBinding.fields;
+ if ((fields != null) && (fields != NoFields)) {
+ for (int i = 0, max = fields.length; i < max; i++) {
+ if (fields[i].constant == null) {
+ FieldReference.getConstantFor(fields[i], false, null, 0);
+ }
+ }
+ classFile.addFieldInfos();
+ } else {
+ // we have to set the number of fields to be equals to 0
+ classFile.contents[classFile.contentsOffset++] = 0;
+ classFile.contents[classFile.contentsOffset++] = 0;
+ }
+ // leave some space for the methodCount
+ classFile.setForMethodInfos();
+ // add its user defined methods
+ MethodBinding[] methods = typeBinding.methods;
+ AbstractMethodDeclaration[] methodDeclarations = typeDeclaration.methods;
+ int maxMethodDecl = methodDeclarations == null ? 0 : methodDeclarations.length;
+ int problemsLength;
+ IProblem[] problems = unitResult.getProblems();
+ if (problems == null) {
+ problems = new IProblem[0];
+ }
+ IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+ System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+ if (methods != null) {
+ if (typeBinding.isInterface()) {
+ // we cannot create problem methods for an interface. So we have to generate a clinit
+ // which should contain all the problem
+ classFile.addProblemClinit(problemsCopy);
+ for (int i = 0, max = methods.length; i < max; i++) {
+ MethodBinding methodBinding;
+ if ((methodBinding = methods[i]) != null) {
+ // find the corresponding method declaration
+ for (int j = 0; j < maxMethodDecl; j++) {
+ if ((methodDeclarations[j] != null) && (methodDeclarations[j].binding == methods[i])) {
+ if (!methodBinding.isConstructor()) {
+ classFile.addAbstractMethod(methodDeclarations[j], methodBinding);
+ }
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ for (int i = 0, max = methods.length; i < max; i++) {
+ MethodBinding methodBinding;
+ if ((methodBinding = methods[i]) != null) {
+ // find the corresponding method declaration
+ for (int j = 0; j < maxMethodDecl; j++) {
+ if ((methodDeclarations[j] != null) && (methodDeclarations[j].binding == methods[i])) {
+ AbstractMethodDeclaration methodDecl;
+ if ((methodDecl = methodDeclarations[j]).isConstructor()) {
+ classFile.addProblemConstructor(methodDecl, methodBinding, problemsCopy);
+ } else {
+ classFile.addProblemMethod(methodDecl, methodBinding, problemsCopy);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ // add abstract methods
+ classFile.addDefaultAbstractMethods();
+ }
+ // propagate generation of (problem) member types
+ if (typeDeclaration.memberTypes != null) {
+ CompilationResult result = typeDeclaration.scope.referenceCompilationUnit().compilationResult;
+ for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) {
+ TypeDeclaration memberType = typeDeclaration.memberTypes[i];
+ if (memberType.binding != null) {
+ classFile.recordNestedMemberAttribute(memberType.binding);
+ ClassFile.createProblemType(memberType, unitResult);
+ }
+ }
+ }
+ classFile.addAttributes();
+ unitResult.record(typeBinding.constantPoolName(), classFile);
+}
+/**
+ * INTERNAL USE-ONLY
+ * This methods returns a char[] representing the file name of the receiver
+ *
+ * @return char[]
+ */
+public char[] fileName() {
+ return constantPool.UTF8Cache.returnKeyFor(1);
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method generates the header of a code attribute.
+ * - the index inside the constant pool for the attribute name (i.e. Code)
+ * - leave some space for attribute_length(4), max_stack(2), max_locals(2), code_length(4).
+ */
+public void generateCodeAttributeHeader() {
+ int contentsLength;
+ if (contentsOffset + 20 >= (contentsLength = contents.length)) {
+ System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ int constantValueNameIndex = constantPool.literalIndex(AttributeNamesConstants.CodeName);
+ contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
+ contents[contentsOffset++] = (byte) constantValueNameIndex;
+ // leave space for attribute_length(4), max_stack(2), max_locals(2), code_length(4)
+ contentsOffset += 12;
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method generates the attributes of a code attribute.
+ * They could be:
+ * - an exception attribute for each try/catch found inside the method
+ * - a deprecated attribute
+ * - a synthetic attribute for synthetic access methods
+ *
+ * It returns the number of attributes created for the code attribute.
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+ * @return <CODE>int</CODE>
+ */
+public int generateMethodInfoAttribute(MethodBinding methodBinding) {
+ // leave two bytes for the attribute_number
+ contentsOffset += 2;
+ // now we can handle all the attribute for that method info:
+ // it could be:
+ // - a CodeAttribute
+ // - a ExceptionAttribute
+ // - a DeprecatedAttribute
+ // - a SyntheticAttribute
+
+ // Exception attribute
+ ReferenceBinding[] thrownsExceptions;
+ int contentsLength;
+ int attributeNumber = 0;
+ if ((thrownsExceptions = methodBinding.thrownExceptions) != NoExceptions) {
+ // The method has a throw clause. So we need to add an exception attribute
+ // check that there is enough space to write all the bytes for the exception attribute
+ int length = thrownsExceptions.length;
+ if (contentsOffset + (8 + length * 2) >= (contentsLength = contents.length)) {
+ System.arraycopy(contents, 0, (contents = new byte[contentsLength + Math.max(INCREMENT_SIZE, (8 + length * 2))]), 0, contentsLength);
+ }
+ int exceptionNameIndex = constantPool.literalIndex(AttributeNamesConstants.ExceptionsName);
+ contents[contentsOffset++] = (byte) (exceptionNameIndex >> 8);
+ contents[contentsOffset++] = (byte) exceptionNameIndex;
+ // The attribute length = length * 2 + 2 in case of a exception attribute
+ int attributeLength = length * 2 + 2;
+ contents[contentsOffset++] = (byte) (attributeLength >> 24);
+ contents[contentsOffset++] = (byte) (attributeLength >> 16);
+ contents[contentsOffset++] = (byte) (attributeLength >> 8);
+ contents[contentsOffset++] = (byte) attributeLength;
+ contents[contentsOffset++] = (byte) (length >> 8);
+ contents[contentsOffset++] = (byte) length;
+ for (int i = 0; i < length; i++) {
+ int exceptionIndex = constantPool.literalIndex(thrownsExceptions[i]);
+ contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
+ contents[contentsOffset++] = (byte) exceptionIndex;
+ }
+ attributeNumber++;
+ }
+
+ // Deprecated attribute
+ // Check that there is enough space to write the deprecated attribute
+ if (contentsOffset + 6 >= (contentsLength = contents.length)) {
+ System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ if (methodBinding.isDeprecated()) {
+ int deprecatedAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
+ contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
+ // the length of a deprecated attribute is equals to 0
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+
+ attributeNumber++;
+ }
+
+ // Synthetic attribute
+ // Check that there is enough space to write the deprecated attribute
+ if (contentsOffset + 6 >= (contentsLength = contents.length)) {
+ System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ if (methodBinding.isSynthetic()) {
+ int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+ contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+ // the length of a synthetic attribute is equals to 0
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+
+ attributeNumber++;
+ }
+ return attributeNumber;
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method generates the header of a method info:
+ * The header consists in:
+ * - the access flags
+ * - the name index of the method name inside the constant pool
+ * - the descriptor index of the signature of the method inside the constant pool.
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+ */
+public void generateMethodInfoHeader(MethodBinding methodBinding) {
+ // check that there is enough space to write all the bytes for the method info corresponding
+ // to the @methodBinding
+ int contentsLength;
+ methodCount++; // add one more method
+ if (contentsOffset + 10 >= (contentsLength = contents.length)) {
+ System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ int accessFlags = methodBinding.getAccessFlags();
+ if (methodBinding.isRequiredToClearPrivateModifier()) {
+ accessFlags &= ~AccPrivate;
+ }
+ contents[contentsOffset++] = (byte) (accessFlags >> 8);
+ contents[contentsOffset++] = (byte) accessFlags;
+ int nameIndex = constantPool.literalIndex(methodBinding.selector);
+ contents[contentsOffset++] = (byte) (nameIndex >> 8);
+ contents[contentsOffset++] = (byte) nameIndex;
+ int descriptorIndex = constantPool.literalIndex(methodBinding.signature());
+ contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
+ contents[contentsOffset++] = (byte) descriptorIndex;
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method generates the method info header of a clinit:
+ * The header consists in:
+ * - the access flags (always default access + static)
+ * - the name index of the method name (always <clinit>) inside the constant pool
+ * - the descriptor index of the signature (always ()V) of the method inside the constant pool.
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+ */
+public void generateMethodInfoHeaderForClinit() {
+ // check that there is enough space to write all the bytes for the method info corresponding
+ // to the @methodBinding
+ int contentsLength;
+ methodCount++; // add one more method
+ if (contentsOffset + 10 >= (contentsLength = contents.length)) {
+ System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ contents[contentsOffset++] = (byte) ((AccDefault | AccStatic) >> 8);
+ contents[contentsOffset++] = (byte) (AccDefault | AccStatic);
+ int nameIndex = constantPool.literalIndex(QualifiedNamesConstants.Clinit);
+ contents[contentsOffset++] = (byte) (nameIndex >> 8);
+ contents[contentsOffset++] = (byte) nameIndex;
+ int descriptorIndex = constantPool.literalIndex(QualifiedNamesConstants.ClinitSignature);
+ contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
+ contents[contentsOffset++] = (byte) descriptorIndex;
+ // We know that we won't get more than 1 attribute: the code attribute
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 1;
+}
+/**
+ * EXTERNAL API
+ * Answer the actual bytes of the class file
+ *
+ * This method encodes the receiver structure into a byte array which is the content of the classfile.
+ * Returns the byte array that represents the encoded structure of the receiver.
+ *
+ * @return byte[]
+ */
+public byte[] getBytes() {
+ byte[] fullContents = new byte[headerOffset + contentsOffset];
+ System.arraycopy(header, 0, fullContents, 0, headerOffset);
+ System.arraycopy(contents, 0, fullContents, headerOffset, contentsOffset);
+ return fullContents;
+}
+/**
+ * EXTERNAL API
+ * Answer the compound name of the class file.
+ * @return char[][]
+ * e.g. {{java}, {util}, {Hashtable}}.
+ */
+public char[][] getCompoundName() {
+ return CharOperation.splitOn('/', fileName());
+}
+/**
+ * EXTERNAL API
+ * Answer a smaller byte format, which is only contains some structural information.
+ *
+ * Those bytes are decodable with a regular class file reader, such as:
+ * DietClassFileReader
+ */
+
+public byte[] getReducedBytes() {
+ return getBytes(); // might be improved
+}
+/**
+ * INTERNAL USE-ONLY
+ * Returns the most enclosing classfile of the receiver. This is used know to store the constant pool name
+ * for all inner types of the receiver.
+ * @return org.eclipse.jdt.internal.compiler.codegen.ClassFile
+ */
+public ClassFile outerMostEnclosingClassFile() {
+ ClassFile current = this;
+ while (current.enclosingClassFile != null)
+ current = current.enclosingClassFile;
+ return current;
+}
+/**
+ * INTERNAL USE-ONLY
+ * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
+ * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
+ *
+ * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
+ */
+public void recordEnclosingTypeAttributes(ReferenceBinding binding) {
+ // add all the enclosing types
+ ReferenceBinding enclosingType = referenceBinding.enclosingType();
+ int depth = 0;
+ while (enclosingType != null) {
+ depth++;
+ enclosingType = enclosingType.enclosingType();
+ }
+ enclosingType = referenceBinding;
+ ReferenceBinding enclosingTypes[];
+ if (depth >= 2) {
+ enclosingTypes = new ReferenceBinding[depth];
+ for (int i = depth - 1; i >= 0; i--) {
+ enclosingTypes[i] = enclosingType;
+ enclosingType = enclosingType.enclosingType();
+ }
+ for (int i = 0; i < depth; i++) {
+ addInnerClasses(enclosingTypes[i]);
+ }
+ } else {
+ addInnerClasses(referenceBinding);
+ }
+}
+/**
+ * INTERNAL USE-ONLY
+ * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
+ * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
+ *
+ * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
+ */
+public void recordNestedLocalAttribute(ReferenceBinding binding) {
+ // add all the enclosing types
+ ReferenceBinding enclosingType = referenceBinding.enclosingType();
+ int depth = 0;
+ while (enclosingType != null) {
+ depth++;
+ enclosingType = enclosingType.enclosingType();
+ }
+ enclosingType = referenceBinding;
+ ReferenceBinding enclosingTypes[];
+ if (depth >= 2) {
+ enclosingTypes = new ReferenceBinding[depth];
+ for (int i = depth - 1; i >= 0; i--) {
+ enclosingTypes[i] = enclosingType;
+ enclosingType = enclosingType.enclosingType();
+ }
+ for (int i = 0; i < depth; i++)
+ addInnerClasses(enclosingTypes[i]);
+ } else {
+ addInnerClasses(binding);
+ }
+}
+/**
+ * INTERNAL USE-ONLY
+ * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
+ * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
+ *
+ * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
+ */
+public void recordNestedMemberAttribute(ReferenceBinding binding) {
+ addInnerClasses(binding);
+}
+/**
+ * INTERNAL USE-ONLY
+ * Search the line number corresponding to a specific position
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+ */
+public static final int searchLineNumber(int[] startLineIndexes, int position) {
+ // this code is completely useless, but it is the same implementation than
+ // org.eclipse.jdt.internal.compiler.problem.ProblemHandler.searchLineNumber(int[], int)
+ // if (startLineIndexes == null)
+ // return 1;
+ int length = startLineIndexes.length;
+ if (length == 0)
+ return 1;
+ int g = 0, d = length - 1;
+ int m = 0;
+ while (g <= d) {
+ m = (g + d) /2;
+ if (position < startLineIndexes[m]) {
+ d = m-1;
+ } else if (position > startLineIndexes[m]) {
+ g = m+1;
+ } else {
+ return m + 1;
+ }
+ }
+ if (position < startLineIndexes[m]) {
+ return m+1;
+ }
+ return m+2;
+}
+/**
+ * INTERNAL USE-ONLY
+ * This methods leaves the space for method counts recording.
+ */
+public void setForMethodInfos() {
+ // leave some space for the methodCount
+ methodCountOffset = contentsOffset;
+ contentsOffset += 2;
+}
+/**
+ * INTERNAL USE-ONLY
+ * outputPath is formed like:
+ * c:\temp\ the last character is a file separator
+ * relativeFileName is formed like:
+ * java\lang\String.class
+ * @param fileName java.lang.String
+ * @param content byte[]
+ */
+public static void writeToDisk(String outputPath, String relativeFileName, byte[] contents) throws IOException {
+ String fileName;
+ File file;
+ FileOutputStream output = new FileOutputStream(file = new File((fileName = buildAllDirectoriesInto(outputPath, relativeFileName))));
+ output.write(contents);
+ output.flush();
+ output.close();
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/Compiler.java b/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
index f7cf45e..a38d0e9 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
@@ -1,438 +1,437 @@
-package org.eclipse.jdt.internal.compiler;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.env.*;
-
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.parser.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.compiler.util.*;
-
-import java.io.*;
-import java.util.*;
-
-public class Compiler implements ITypeRequestor, ProblemSeverities {
- public Parser parser;
- ICompilerRequestor requestor;
- public CompilerOptions options;
- public ProblemReporter problemReporter;
-
- // management of unit to be processed
- //public CompilationUnitResult currentCompilationUnitResult;
- CompilationUnitDeclaration[] unitsToProcess;
- int totalUnits; // (totalUnits-1) gives the last unit in unitToProcess
-
- // name lookup
- public LookupEnvironment lookupEnvironment;
-
- // ONCE STABILIZED, THESE SHOULD RETURN TO A FINAL FIELD
- public static final boolean DEBUG = false;
- public int parseThreshold = -1; // number of initial units parsed at once (-1: none)
-/**
- * Answer a new compiler using the given name environment and compiler options.
- * The environment and options will be in effect for the lifetime of the compiler.
- * When the compiler is run, compilation results are sent to the given requestor.
- *
- * @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
- * Environment used by the compiler in order to resolve type and package
- * names. The name environment implements the actual connection of the compiler
- * to the outside world (e.g. in batch mode the name environment is performing
- * pure file accesses, reuse previous build state or connection to repositories).
- * Note: the name environment is responsible for implementing the actual classpath
- * rules.
- *
- * @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
- * Configurable part for problem handling, allowing the compiler client to
- * specify the rules for handling problems (stop on first error or accumulate
- * them all) and at the same time perform some actions such as opening a dialog
- * in UI when compiling interactively.
- * @see org.eclipse.jdt.internal.compiler.api.problem.DefaultErrorHandlingPolicies
- *
- * @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
- * Component which will receive and persist all compilation results and is intended
- * to consume them as they are produced. Typically, in a batch compiler, it is
- * responsible for writing out the actual .class files to the file system.
- * @see org.eclipse.jdt.internal.compiler.api.CompilationResult
- *
- * @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
- * Factory used inside the compiler to create problem descriptors. It allows the
- * compiler client to supply its own representation of compilation problems in
- * order to avoid object conversions. Note that the factory is not supposed
- * to accumulate the created problems, the compiler will gather them all and hand
- * them back as part of the compilation unit result.
- */
-public Compiler(
- INameEnvironment environment,
- IErrorHandlingPolicy policy,
- ConfigurableOption[] settings,
- ICompilerRequestor requestor,
- IProblemFactory problemFactory) {
-
- // create a problem handler given a handling policy
- this.options = new CompilerOptions(settings);
- this.requestor = requestor;
- this.problemReporter =
- new ProblemReporter(
- policy,
- this.options,
- problemFactory);
- this.lookupEnvironment = new LookupEnvironment(this, options, problemReporter, environment);
- this.parser =
- new Parser(problemReporter, this.options.parseLiteralExpressionsAsConstants);
-}
-/**
- * Add an additional binary type
- */
-
-public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
- lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
-}
-/**
- * Add an additional compilation unit into the loop
- * -> build compilation unit declarations, their bindings and record their results.
- */
-
-public void accept(ICompilationUnit sourceUnit) {
- // Switch the current policy and compilation result for this unit to the requested one.
- CompilationResult unitResult =
- new CompilationResult(sourceUnit, totalUnits, totalUnits);
- try {
- // diet parsing for large collection of unit
- CompilationUnitDeclaration parsedUnit;
- if (totalUnits < parseThreshold) {
- parsedUnit = parser.parse(sourceUnit, unitResult);
- } else {
- parsedUnit = parser.dietParse(sourceUnit, unitResult);
- }
-
- if (options.verbose) {
- System.out.println(Util.bind("compilation.request"/*nonNLS*/,new String[]{String.valueOf(totalUnits + 1),String.valueOf(totalUnits + 1),new String(sourceUnit.getFileName())}));
- }
-
- // initial type binding creation
- lookupEnvironment.buildTypeBindings(parsedUnit);
- this.addCompilationUnit(sourceUnit, parsedUnit);
-
- // binding resolution
- lookupEnvironment.completeTypeBindings(parsedUnit);
- } catch (AbortCompilationUnit e) {
- // at this point, currentCompilationUnitResult may not be sourceUnit, but some other
- // one requested further along to resolve sourceUnit.
- if (unitResult.compilationUnit == sourceUnit) { // only report once
- requestor.acceptResult(unitResult.tagAsAccepted());
- } else {
- throw e; // want to abort enclosing request to compile
- }
- }
-}
-/**
- * Add an additional source type
- */
-
-public void accept(ISourceType sourceType, PackageBinding packageBinding) {
- problemReporter.abortDueToInternalError(Util.bind("abort.againstSourceModel "/*nonNLS*/,String.valueOf(sourceType.getName()),String.valueOf(sourceType.getFileName())));
-}
-protected void addCompilationUnit(ICompilationUnit sourceUnit, CompilationUnitDeclaration parsedUnit) {
-
- // append the unit to the list of ones to process later on
- int size = unitsToProcess.length;
- if (totalUnits == size) // when growing reposition units starting at position 0
- System.arraycopy(unitsToProcess, 0, (unitsToProcess = new CompilationUnitDeclaration[size * 2]), 0, totalUnits);
- unitsToProcess[totalUnits++] = parsedUnit;
-}
-/**
- * Add the initial set of compilation units into the loop
- * -> build compilation unit declarations, their bindings and record their results.
- */
-protected void beginToCompile(ICompilationUnit[] sourceUnits) {
- int maxUnits = sourceUnits.length;
- totalUnits = 0;
- unitsToProcess = new CompilationUnitDeclaration[maxUnits];
-
- // Switch the current policy and compilation result for this unit to the requested one.
- for (int i = 0; i < maxUnits; i++) {
- CompilationUnitDeclaration parsedUnit;
- CompilationResult unitResult = new CompilationResult(sourceUnits[i], i, maxUnits);
- try {
- // diet parsing for large collection of units
- if (totalUnits < parseThreshold)
- { parsedUnit = parser.parse(sourceUnits[i], unitResult);}
- else
- { parsedUnit = parser.dietParse(sourceUnits[i], unitResult);}
- if (options.verbose) {
- System.out.println(Util.bind("compilation.request"/*nonNLS*/,new String[]{String.valueOf(i+1),String.valueOf(maxUnits),new String(sourceUnits[i].getFileName())}));
- }
- // initial type binding creation
- lookupEnvironment.buildTypeBindings(parsedUnit);
- this.addCompilationUnit(sourceUnits[i], parsedUnit);
- //} catch (AbortCompilationUnit e) {
- // requestor.acceptResult(unitResult.tagAsAccepted());
- } finally {
- sourceUnits[i] = null; // no longer hold onto the unit
- }
- }
- // binding resolution
- lookupEnvironment.completeTypeBindings();
-}
-/**
- * General API
- * -> compile each of supplied files
- * -> recompile any required types for which we have an incomplete principle structure
- */
-
-public void compile(ICompilationUnit[] sourceUnits) {
- CompilationUnitDeclaration unit = null;
- int i = 0;
- try {
- // build and record parsed units
-
- beginToCompile(sourceUnits);
-
- // process all units (some more could be injected in the loop by the lookup environment)
- for (; i < totalUnits; i++) {
- unit = unitsToProcess[i];
- try {
- if (options.verbose) System.out.println(Util.bind("compilation.process"/*nonNLS*/,new String[]{String.valueOf(i + 1),String.valueOf(totalUnits),new String(unitsToProcess[i].getFileName())}));
- process(unit, i);
- } finally {
- // cleanup compilation unit result
- unit.cleanUp();
- if (options.verbose)
- System.out.println(Util.bind("compilation.done"/*nonNLS*/,new String[]{String.valueOf(i + 1),String.valueOf(totalUnits),new String(unitsToProcess[i].getFileName())}));
- }
- unitsToProcess[i] = null; // release reference to processed unit declaration
- requestor.acceptResult(unit.compilationResult.tagAsAccepted());
- }
- } catch (AbortCompilation e) {
- this.handleInternalException(e, unit);
- } catch (Error e) {
- this.handleInternalException(e, unit, null);
- throw e; // rethrow
- } catch (RuntimeException e) {
- this.handleInternalException(e, unit, null);
- throw e; // rethrow
- } finally {
- this.reset();
- }
- if (options.verbose) {
- if (totalUnits > 1) {
- System.out.println(Util.bind("compilation.units"/*nonNLS*/,String.valueOf(totalUnits)));
- } else {
- System.out.println(Util.bind("compilation.unit"/*nonNLS*/,String.valueOf(totalUnits)));
- }
- }
-}
-/**
- * Answer an array of descriptions for the configurable options.
- * The descriptions may be changed and passed back to a different
- * compiler.
- *
- * @return ConfigurableOption[] - array of configurable options
- */
-public static ConfigurableOption[] getDefaultOptions(Locale locale) {
- return new CompilerOptions().getConfigurableOptions(locale);
-}
-protected void getMethodBodies(CompilationUnitDeclaration unit, int place) {
- //fill the methods bodies in order for the code to be generated
-
- if (unit.ignoreMethodBodies) {
- unit.ignoreFurtherInvestigation = true;
- return; // if initial diet parse did not work, no need to dig into method bodies.
- }
-
- if (place < parseThreshold)
- return; //work already done ...
-
- //real parse of the method....
- parser.scanner.setSourceBuffer(unit.compilationResult.compilationUnit.getContents());
- if (unit.types != null) {
- for (int i = unit.types.length; --i >= 0;)
- unit.types[i].parseMethod(parser, unit);
- }
-}
-/*
- * Compiler crash recovery in case of unexpected runtime exceptions
- */
-protected void handleInternalException(Throwable internalException, CompilationUnitDeclaration unit, CompilationResult result) {
-
- /* dump a stack trace to the console */
- internalException.printStackTrace();
-
- /* find a compilation result */
- if ((unit != null)) // basing result upon the current unit if available
- result = unit.compilationResult; // current unit being processed ?
- if ((result == null) && (unitsToProcess != null) && (totalUnits > 0))
- result = unitsToProcess[totalUnits - 1].compilationResult; // last unit in beginToCompile ?
-
- if (result != null) {
- /* create and record a compilation problem */
- StringWriter stringWriter = new StringWriter();
- PrintWriter writer = new PrintWriter(stringWriter);
- internalException.printStackTrace(writer);
- StringBuffer buffer = stringWriter.getBuffer();
-
- result.record(
- problemReporter.createProblem(
- result.getFileName(),
- ProblemIrritants.UnclassifiedProblem,
- new String[] {Util.bind("compilation.internalError"/*nonNLS*/)+"\n"/*nonNLS*/ + buffer.toString()},
- Error, // severity
- 0, // source start
- 0, // source end
- 0)); // line number
-
- /* hand back the compilation result */
- if (!result.hasBeenAccepted) {
- requestor.acceptResult(result.tagAsAccepted());
- }
- }
-}
-/*
- * Compiler recovery in case of internal AbortCompilation event
- */
-protected void handleInternalException(AbortCompilation abortException, CompilationUnitDeclaration unit){
-
- /* special treatment for SilentAbort: silently cancelling the compilation process */
- if (abortException.isSilent){
- if (abortException.silentException == null) {
- return;
- } else {
- throw abortException.silentException;
- }
- }
-
- /* uncomment following line to see where the abort came from */
- // abortException.printStackTrace();
-
- // Exception may tell which compilation result it is related, and which problem caused it
- CompilationResult result = abortException.compilationResult;
- if ((result == null) && (unit != null)) result = unit.compilationResult; // current unit being processed ?
- if ((result == null) && (unitsToProcess != null) && (totalUnits > 0)) result = unitsToProcess[totalUnits - 1].compilationResult; // last unit in beginToCompile ?
- if (result != null && !result.hasBeenAccepted){
- /* distant problem which could not be reported back there */
- if (abortException.problemId != 0){
- result.record(
- problemReporter.createProblem(
- result.getFileName(),
- abortException.problemId,
- abortException.problemArguments,
- Error, // severity
- 0, // source start
- 0, // source end
- 0)); // line number
- } else {
- /* distant internal exception which could not be reported back there */
- if (abortException.exception != null){
- this.handleInternalException(abortException.exception, null, result);
- return;
- }
- }
- /* hand back the compilation result */
- if (!result.hasBeenAccepted) {
- requestor.acceptResult(result.tagAsAccepted());
- }
- } else {
- /*
- if (abortException.problemId != 0){
- IProblem problem =
- problemReporter.createProblem(
- "???".toCharArray(),
- abortException.problemId,
- abortException.problemArguments,
- Error, // severity
- 0, // source start
- 0, // source end
- 0); // line number
- System.out.println(problem.getMessage());
- }
- */
- abortException.printStackTrace();
- }
-}
-/**
- * Process a compilation unit already parsed and build.
- */
-private void process(CompilationUnitDeclaration unit,int i) {
-
- getMethodBodies(unit,i);
-
- // fault in fields & methods
- if (unit.scope != null)
- unit.scope.faultInTypes();
-
- // verify inherited methods
- if (unit.scope != null)
- unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
-
- // type checking
- long startTime = System.currentTimeMillis();
- unit.resolve();
-
- // flow analysis
- startTime = System.currentTimeMillis();
- unit.analyseCode();
-
- // code generation
- startTime = System.currentTimeMillis();
- unit.generateCode();
-
- // reference info
- if (options.produceReferenceInfo && unit.scope != null)
- unit.scope.storeDependencyInfo();
-
- // refresh the total number of units known at this stage
- unit.compilationResult.totalUnitsKnown = totalUnits;
-}
-public void reset(){
- lookupEnvironment.reset();
- parser.scanner.source = null;
- unitsToProcess = null;
-}
-/**
- * Internal API used to resolve a compilation unit minimally for code assist engine
- */
-
-public CompilationUnitDeclaration resolve(ICompilationUnit sourceUnit) {
- CompilationUnitDeclaration unit = null;
- try {
- // build and record parsed units
- parseThreshold = 1; // will request a full parse
- beginToCompile(new ICompilationUnit[] { sourceUnit });
- // process all units (some more could be injected in the loop by the lookup environment)
- unit = unitsToProcess[0];
- //getMethodBodies(unit,i);
- if (unit.scope != null) {
- // fault in fields & methods
- unit.scope.faultInTypes();
- // type checking
- unit.resolve();
- }
- unitsToProcess[0] = null; // release reference to processed unit declaration
- requestor.acceptResult(unit.compilationResult.tagAsAccepted());
- return unit;
- } catch (AbortCompilation e) {
- this.handleInternalException(e, unit);
- return unit == null ? unitsToProcess[0] : unit;
- } catch (Error e) {
- this.handleInternalException(e, unit, null);
- throw e; // rethrow
- } catch (RuntimeException e) {
- this.handleInternalException(e, unit, null);
- throw e; // rethrow
- } finally {
- // No reset is performed there anymore since,
- // within the CodeAssist (or related tools),
- // the compiler may be called *after* a call
- // to this resolve(...) method. And such a call
- // needs to have a compiler with a non-empty
- // environment.
- // this.reset();
- }
-}
-}
+package org.eclipse.jdt.internal.compiler;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.env.*;
+
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.parser.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.compiler.util.*;
+
+import java.io.*;
+import java.util.*;
+
+public class Compiler implements ITypeRequestor, ProblemSeverities {
+ public Parser parser;
+ ICompilerRequestor requestor;
+ public CompilerOptions options;
+ public ProblemReporter problemReporter;
+
+ // management of unit to be processed
+ //public CompilationUnitResult currentCompilationUnitResult;
+ CompilationUnitDeclaration[] unitsToProcess;
+ int totalUnits; // (totalUnits-1) gives the last unit in unitToProcess
+
+ // name lookup
+ public LookupEnvironment lookupEnvironment;
+
+ // ONCE STABILIZED, THESE SHOULD RETURN TO A FINAL FIELD
+ public static final boolean DEBUG = false;
+ public int parseThreshold = -1; // number of initial units parsed at once (-1: none)
+/**
+ * Answer a new compiler using the given name environment and compiler options.
+ * The environment and options will be in effect for the lifetime of the compiler.
+ * When the compiler is run, compilation results are sent to the given requestor.
+ *
+ * @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
+ * Environment used by the compiler in order to resolve type and package
+ * names. The name environment implements the actual connection of the compiler
+ * to the outside world (e.g. in batch mode the name environment is performing
+ * pure file accesses, reuse previous build state or connection to repositories).
+ * Note: the name environment is responsible for implementing the actual classpath
+ * rules.
+ *
+ * @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
+ * Configurable part for problem handling, allowing the compiler client to
+ * specify the rules for handling problems (stop on first error or accumulate
+ * them all) and at the same time perform some actions such as opening a dialog
+ * in UI when compiling interactively.
+ * @see org.eclipse.jdt.internal.compiler.api.problem.DefaultErrorHandlingPolicies
+ *
+ * @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
+ * Component which will receive and persist all compilation results and is intended
+ * to consume them as they are produced. Typically, in a batch compiler, it is
+ * responsible for writing out the actual .class files to the file system.
+ * @see org.eclipse.jdt.internal.compiler.api.CompilationResult
+ *
+ * @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
+ * Factory used inside the compiler to create problem descriptors. It allows the
+ * compiler client to supply its own representation of compilation problems in
+ * order to avoid object conversions. Note that the factory is not supposed
+ * to accumulate the created problems, the compiler will gather them all and hand
+ * them back as part of the compilation unit result.
+ */
+public Compiler(
+ INameEnvironment environment,
+ IErrorHandlingPolicy policy,
+ ConfigurableOption[] settings,
+ ICompilerRequestor requestor,
+ IProblemFactory problemFactory) {
+
+ // create a problem handler given a handling policy
+ this.options = new CompilerOptions(settings);
+ this.requestor = requestor;
+ this.problemReporter =
+ new ProblemReporter(
+ policy,
+ this.options,
+ problemFactory);
+ this.lookupEnvironment = new LookupEnvironment(this, options, problemReporter, environment);
+ this.parser =
+ new Parser(problemReporter, this.options.parseLiteralExpressionsAsConstants);
+}
+/**
+ * Add an additional binary type
+ */
+
+public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
+ lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
+}
+/**
+ * Add an additional compilation unit into the loop
+ * -> build compilation unit declarations, their bindings and record their results.
+ */
+
+public void accept(ICompilationUnit sourceUnit) {
+ // Switch the current policy and compilation result for this unit to the requested one.
+ CompilationResult unitResult =
+ new CompilationResult(sourceUnit, totalUnits, totalUnits);
+ try {
+ // diet parsing for large collection of unit
+ CompilationUnitDeclaration parsedUnit;
+ if (totalUnits < parseThreshold) {
+ parsedUnit = parser.parse(sourceUnit, unitResult);
+ } else {
+ parsedUnit = parser.dietParse(sourceUnit, unitResult);
+ }
+
+ if (options.verbose) {
+ System.out.println(Util.bind("compilation.request"/*nonNLS*/,new String[]{String.valueOf(totalUnits + 1),String.valueOf(totalUnits + 1),new String(sourceUnit.getFileName())}));
+ }
+
+ // initial type binding creation
+ lookupEnvironment.buildTypeBindings(parsedUnit);
+ this.addCompilationUnit(sourceUnit, parsedUnit);
+
+ // binding resolution
+ lookupEnvironment.completeTypeBindings(parsedUnit);
+ } catch (AbortCompilationUnit e) {
+ // at this point, currentCompilationUnitResult may not be sourceUnit, but some other
+ // one requested further along to resolve sourceUnit.
+ if (unitResult.compilationUnit == sourceUnit) { // only report once
+ requestor.acceptResult(unitResult.tagAsAccepted());
+ } else {
+ throw e; // want to abort enclosing request to compile
+ }
+ }
+}
+/**
+ * Add an additional source type
+ */
+
+public void accept(ISourceType sourceType, PackageBinding packageBinding) {
+ problemReporter.abortDueToInternalError(Util.bind("abort.againstSourceModel "/*nonNLS*/,String.valueOf(sourceType.getName()),String.valueOf(sourceType.getFileName())));
+}
+protected void addCompilationUnit(ICompilationUnit sourceUnit, CompilationUnitDeclaration parsedUnit) {
+
+ // append the unit to the list of ones to process later on
+ int size = unitsToProcess.length;
+ if (totalUnits == size) // when growing reposition units starting at position 0
+ System.arraycopy(unitsToProcess, 0, (unitsToProcess = new CompilationUnitDeclaration[size * 2]), 0, totalUnits);
+ unitsToProcess[totalUnits++] = parsedUnit;
+}
+/**
+ * Add the initial set of compilation units into the loop
+ * -> build compilation unit declarations, their bindings and record their results.
+ */
+protected void beginToCompile(ICompilationUnit[] sourceUnits) {
+ int maxUnits = sourceUnits.length;
+ totalUnits = 0;
+ unitsToProcess = new CompilationUnitDeclaration[maxUnits];
+
+ // Switch the current policy and compilation result for this unit to the requested one.
+ for (int i = 0; i < maxUnits; i++) {
+ CompilationUnitDeclaration parsedUnit;
+ CompilationResult unitResult = new CompilationResult(sourceUnits[i], i, maxUnits);
+ try {
+ // diet parsing for large collection of units
+ if (totalUnits < parseThreshold)
+ { parsedUnit = parser.parse(sourceUnits[i], unitResult);}
+ else
+ { parsedUnit = parser.dietParse(sourceUnits[i], unitResult);}
+ if (options.verbose) {
+ System.out.println(Util.bind("compilation.request"/*nonNLS*/,new String[]{String.valueOf(i+1),String.valueOf(maxUnits),new String(sourceUnits[i].getFileName())}));
+ }
+ // initial type binding creation
+ lookupEnvironment.buildTypeBindings(parsedUnit);
+ this.addCompilationUnit(sourceUnits[i], parsedUnit);
+ //} catch (AbortCompilationUnit e) {
+ // requestor.acceptResult(unitResult.tagAsAccepted());
+ } finally {
+ sourceUnits[i] = null; // no longer hold onto the unit
+ }
+ }
+ // binding resolution
+ lookupEnvironment.completeTypeBindings();
+}
+/**
+ * General API
+ * -> compile each of supplied files
+ * -> recompile any required types for which we have an incomplete principle structure
+ */
+
+public void compile(ICompilationUnit[] sourceUnits) {
+ CompilationUnitDeclaration unit = null;
+ int i = 0;
+ try {
+ // build and record parsed units
+
+ beginToCompile(sourceUnits);
+
+ // process all units (some more could be injected in the loop by the lookup environment)
+ for (; i < totalUnits; i++) {
+ unit = unitsToProcess[i];
+ try {
+ if (options.verbose) System.out.println(Util.bind("compilation.process"/*nonNLS*/,new String[]{String.valueOf(i + 1),String.valueOf(totalUnits),new String(unitsToProcess[i].getFileName())}));
+ process(unit, i);
+ } finally {
+ // cleanup compilation unit result
+ unit.cleanUp();
+ if (options.verbose)
+ System.out.println(Util.bind("compilation.done"/*nonNLS*/,new String[]{String.valueOf(i + 1),String.valueOf(totalUnits),new String(unitsToProcess[i].getFileName())}));
+ }
+ unitsToProcess[i] = null; // release reference to processed unit declaration
+ requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+ }
+ } catch (AbortCompilation e) {
+ this.handleInternalException(e, unit);
+ } catch (Error e) {
+ this.handleInternalException(e, unit, null);
+ throw e; // rethrow
+ } catch (RuntimeException e) {
+ this.handleInternalException(e, unit, null);
+ throw e; // rethrow
+ } finally {
+ this.reset();
+ }
+ if (options.verbose) {
+ if (totalUnits > 1) {
+ System.out.println(Util.bind("compilation.units"/*nonNLS*/,String.valueOf(totalUnits)));
+ } else {
+ System.out.println(Util.bind("compilation.unit"/*nonNLS*/,String.valueOf(totalUnits)));
+ }
+ }
+}
+/**
+ * Answer an array of descriptions for the configurable options.
+ * The descriptions may be changed and passed back to a different
+ * compiler.
+ *
+ * @return ConfigurableOption[] - array of configurable options
+ */
+public static ConfigurableOption[] getDefaultOptions(Locale locale) {
+ return new CompilerOptions().getConfigurableOptions(locale);
+}
+protected void getMethodBodies(CompilationUnitDeclaration unit, int place) {
+ //fill the methods bodies in order for the code to be generated
+
+ if (unit.ignoreMethodBodies) {
+ unit.ignoreFurtherInvestigation = true;
+ return; // if initial diet parse did not work, no need to dig into method bodies.
+ }
+
+ if (place < parseThreshold)
+ return; //work already done ...
+
+ //real parse of the method....
+ parser.scanner.setSourceBuffer(unit.compilationResult.compilationUnit.getContents());
+ if (unit.types != null) {
+ for (int i = unit.types.length; --i >= 0;)
+ unit.types[i].parseMethod(parser, unit);
+ }
+}
+/*
+ * Compiler crash recovery in case of unexpected runtime exceptions
+ */
+protected void handleInternalException(Throwable internalException, CompilationUnitDeclaration unit, CompilationResult result) {
+
+ /* dump a stack trace to the console */
+ internalException.printStackTrace();
+
+ /* find a compilation result */
+ if ((unit != null)) // basing result upon the current unit if available
+ result = unit.compilationResult; // current unit being processed ?
+ if ((result == null) && (unitsToProcess != null) && (totalUnits > 0))
+ result = unitsToProcess[totalUnits - 1].compilationResult; // last unit in beginToCompile ?
+
+ if (result != null) {
+ /* create and record a compilation problem */
+ StringWriter stringWriter = new StringWriter();
+ PrintWriter writer = new PrintWriter(stringWriter);
+ internalException.printStackTrace(writer);
+ StringBuffer buffer = stringWriter.getBuffer();
+
+ result.record(
+ problemReporter.createProblem(
+ result.getFileName(),
+ ProblemIrritants.UnclassifiedProblem,
+ new String[] {Util.bind("compilation.internalError"/*nonNLS*/)+"\n"/*nonNLS*/ + buffer.toString()},
+ Error, // severity
+ 0, // source start
+ 0, // source end
+ 0)); // line number
+
+ /* hand back the compilation result */
+ if (!result.hasBeenAccepted) {
+ requestor.acceptResult(result.tagAsAccepted());
+ }
+ }
+}
+/*
+ * Compiler recovery in case of internal AbortCompilation event
+ */
+protected void handleInternalException(AbortCompilation abortException, CompilationUnitDeclaration unit){
+
+ /* special treatment for SilentAbort: silently cancelling the compilation process */
+ if (abortException.isSilent){
+ if (abortException.silentException == null) {
+ return;
+ } else {
+ throw abortException.silentException;
+ }
+ }
+
+ /* uncomment following line to see where the abort came from */
+ // abortException.printStackTrace();
+
+ // Exception may tell which compilation result it is related, and which problem caused it
+ CompilationResult result = abortException.compilationResult;
+ if ((result == null) && (unit != null)) result = unit.compilationResult; // current unit being processed ?
+ if ((result == null) && (unitsToProcess != null) && (totalUnits > 0)) result = unitsToProcess[totalUnits - 1].compilationResult; // last unit in beginToCompile ?
+ if (result != null && !result.hasBeenAccepted){
+ /* distant problem which could not be reported back there */
+ if (abortException.problemId != 0){
+ result.record(
+ problemReporter.createProblem(
+ result.getFileName(),
+ abortException.problemId,
+ abortException.problemArguments,
+ Error, // severity
+ 0, // source start
+ 0, // source end
+ 0)); // line number
+ } else {
+ /* distant internal exception which could not be reported back there */
+ if (abortException.exception != null){
+ this.handleInternalException(abortException.exception, null, result);
+ return;
+ }
+ }
+ /* hand back the compilation result */
+ if (!result.hasBeenAccepted) {
+ requestor.acceptResult(result.tagAsAccepted());
+ }
+ } else {
+ /*
+ if (abortException.problemId != 0){
+ IProblem problem =
+ problemReporter.createProblem(
+ "???".toCharArray(),
+ abortException.problemId,
+ abortException.problemArguments,
+ Error, // severity
+ 0, // source start
+ 0, // source end
+ 0); // line number
+ System.out.println(problem.getMessage());
+ }
+ */
+ abortException.printStackTrace();
+ }
+}
+/**
+ * Process a compilation unit already parsed and build.
+ */
+private void process(CompilationUnitDeclaration unit,int i) {
+
+ getMethodBodies(unit,i);
+
+ // fault in fields & methods
+ if (unit.scope != null)
+ unit.scope.faultInTypes();
+
+ // verify inherited methods
+ if (unit.scope != null)
+ unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
+
+ // type checking
+ long startTime = System.currentTimeMillis();
+ unit.resolve();
+
+ // flow analysis
+ startTime = System.currentTimeMillis();
+ unit.analyseCode();
+
+ // code generation
+ startTime = System.currentTimeMillis();
+ unit.generateCode();
+
+ // reference info
+ if (options.produceReferenceInfo && unit.scope != null)
+ unit.scope.storeDependencyInfo();
+
+ // refresh the total number of units known at this stage
+ unit.compilationResult.totalUnitsKnown = totalUnits;
+}
+public void reset(){
+ lookupEnvironment.reset();
+ parser.scanner.source = null;
+ unitsToProcess = null;
+}
+/**
+ * Internal API used to resolve a compilation unit minimally for code assist engine
+ */
+
+public CompilationUnitDeclaration resolve(ICompilationUnit sourceUnit) {
+ CompilationUnitDeclaration unit = null;
+ try {
+ // build and record parsed units
+ parseThreshold = 1; // will request a full parse
+ beginToCompile(new ICompilationUnit[] { sourceUnit });
+ // process all units (some more could be injected in the loop by the lookup environment)
+ unit = unitsToProcess[0];
+ //getMethodBodies(unit,i);
+ if (unit.scope != null) {
+ // fault in fields & methods
+ unit.scope.faultInTypes();
+ // type checking
+ unit.resolve();
+ }
+ unitsToProcess[0] = null; // release reference to processed unit declaration
+ requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+ return unit;
+ } catch (AbortCompilation e) {
+ this.handleInternalException(e, unit);
+ return unit == null ? unitsToProcess[0] : unit;
+ } catch (Error e) {
+ this.handleInternalException(e, unit, null);
+ throw e; // rethrow
+ } catch (RuntimeException e) {
+ this.handleInternalException(e, unit, null);
+ throw e; // rethrow
+ } finally {
+ // No reset is performed there anymore since,
+ // within the CodeAssist (or related tools),
+ // the compiler may be called *after* a call
+ // to this resolve(...) method. And such a call
+ // needs to have a compiler with a non-empty
+ // environment.
+ // this.reset();
+ }
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/DefaultErrorHandlingPolicies.java b/compiler/org/eclipse/jdt/internal/compiler/DefaultErrorHandlingPolicies.java
index 70e19d2..b672313 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/DefaultErrorHandlingPolicies.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/DefaultErrorHandlingPolicies.java
@@ -1,74 +1,69 @@
-package org.eclipse.jdt.internal.compiler;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.problem.ProblemHandler;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-public class DefaultErrorHandlingPolicies {
-
-/*
- * Accumulate all problems, then exit without proceeding.
- *
- * Typically, the #proceedWithProblems(Problem[]) should
- * show the problems.
- *
- */
-public static IErrorHandlingPolicy exitAfterAllProblems() {
- return new IErrorHandlingPolicy() {
- public boolean stopOnFirstError() {
- return false;
- }
- public boolean proceedOnErrors(){
- return false;
- }
- };
-}
-/*
- * Exit without proceeding on the first problem wich appears
- * to be an error.
- *
- */
-public static IErrorHandlingPolicy exitOnFirstError() {
- return new IErrorHandlingPolicy() {
- public boolean stopOnFirstError() {
- return true;
- }
- public boolean proceedOnErrors(){
- return false;
- }
- };
-}
-/*
- * Proceed on the first error met.
- *
- */
-public static IErrorHandlingPolicy proceedOnFirstError() {
- return new IErrorHandlingPolicy() {
- public boolean stopOnFirstError() {
- return true;
- }
- public boolean proceedOnErrors(){
- return true;
- }
- };
-}
-/*
- * Accumulate all problems, then proceed with them.
- *
- */
-public static IErrorHandlingPolicy proceedWithAllProblems() {
- return new IErrorHandlingPolicy() {
- public boolean stopOnFirstError() {
- return false;
- }
- public boolean proceedOnErrors(){
- return true;
- }
- };
-}
-}
+package org.eclipse.jdt.internal.compiler;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+public class DefaultErrorHandlingPolicies {
+
+/*
+ * Accumulate all problems, then exit without proceeding.
+ *
+ * Typically, the #proceedWithProblems(Problem[]) should
+ * show the problems.
+ *
+ */
+public static IErrorHandlingPolicy exitAfterAllProblems() {
+ return new IErrorHandlingPolicy() {
+ public boolean stopOnFirstError() {
+ return false;
+ }
+ public boolean proceedOnErrors(){
+ return false;
+ }
+ };
+}
+/*
+ * Exit without proceeding on the first problem wich appears
+ * to be an error.
+ *
+ */
+public static IErrorHandlingPolicy exitOnFirstError() {
+ return new IErrorHandlingPolicy() {
+ public boolean stopOnFirstError() {
+ return true;
+ }
+ public boolean proceedOnErrors(){
+ return false;
+ }
+ };
+}
+/*
+ * Proceed on the first error met.
+ *
+ */
+public static IErrorHandlingPolicy proceedOnFirstError() {
+ return new IErrorHandlingPolicy() {
+ public boolean stopOnFirstError() {
+ return true;
+ }
+ public boolean proceedOnErrors(){
+ return true;
+ }
+ };
+}
+/*
+ * Accumulate all problems, then proceed with them.
+ *
+ */
+public static IErrorHandlingPolicy proceedWithAllProblems() {
+ return new IErrorHandlingPolicy() {
+ public boolean stopOnFirstError() {
+ return false;
+ }
+ public boolean proceedOnErrors(){
+ return true;
+ }
+ };
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/DocumentElementParser.java b/compiler/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
index d49cd5c..b013059 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
@@ -1,1318 +1,1317 @@
-package org.eclipse.jdt.internal.compiler;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-/*
- * A document element parser extracts structural information
- * from a piece of source, providing detailed source positions info.
- *
- * also see @IDocumentElementRequestor
- *
- * The structural investigation includes:
- * - the package statement
- * - import statements
- * - top-level types: package member, member types (member types of member types...)
- * - fields
- * - methods
- *
- * Any (parsing) problem encountered is also provided.
- */
-import org.eclipse.jdt.internal.compiler.Compiler;
-import org.eclipse.jdt.internal.compiler.env.*;
-
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.parser.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.compiler.util.*;
-
-public class DocumentElementParser extends Parser {
- IDocumentElementRequestor requestor;
- private int localIntPtr;
- private int lastFieldEndPosition;
- private int lastFieldBodyEndPosition;
- private int typeStartPosition;
- private long selectorSourcePositions;
- private int typeDims;
- private int extendsDim;
- private int declarationSourceStart;
-
- /* int[] stack for storing javadoc positions */
- int[][] intArrayStack;
- int intArrayPtr;
-public DocumentElementParser(
- final IDocumentElementRequestor requestor,
- IProblemFactory problemFactory) {
- super(new ProblemReporter(
- DefaultErrorHandlingPolicies.exitAfterAllProblems(),
- new CompilerOptions(),
- problemFactory) {
- public void record(IProblem problem, CompilationResult unitResult) {
- requestor.acceptProblem(problem);
- }
- }, false);
- this.requestor = requestor;
- intArrayStack = new int[30][];
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void adjustInterfaceModifiers() {
- intStack[intPtr - 2] |= AccInterface;
-}
-/*
- * Will clear the comment stack when looking
- * for a potential JavaDoc which might contain @deprecated.
- *
- * Additionally, before investigating for @deprecated, retrieve the positions
- * of the JavaDoc comments so as to notify requestor with them.
- */
-public void checkAnnotation() {
-
- /* persisting javadoc positions */
- pushOnIntArrayStack(this.getJavaDocPositions());
- boolean deprecated = false;
- int lastAnnotationIndex = -1;
-
- //since jdk1.2 look only in the last java doc comment...
- found : {
- if ((lastAnnotationIndex = scanner.commentPtr) >= 0) { //look for @deprecated
- scanner.commentPtr = -1;
- // reset the comment stack, since not necessary after having checked
- int commentSourceStart = scanner.commentStarts[lastAnnotationIndex];
- // javadoc only (non javadoc comment have negative end positions.)
- int commentSourceEnd = scanner.commentStops[lastAnnotationIndex] - 1;
- //stop is one over
- char[] comment = scanner.source;
-
- for (int i = commentSourceStart + 3; i < commentSourceEnd - 10; i++) {
- if ((comment[i] == '@')
- && (comment[i + 1] == 'd')
- && (comment[i + 2] == 'e')
- && (comment[i + 3] == 'p')
- && (comment[i + 4] == 'r')
- && (comment[i + 5] == 'e')
- && (comment[i + 6] == 'c')
- && (comment[i + 7] == 'a')
- && (comment[i + 8] == 't')
- && (comment[i + 9] == 'e')
- && (comment[i + 10] == 'd')) {
- // ensure the tag is properly ended: either followed by a space, line end or asterisk.
- int nextPos = i + 11;
- deprecated =
- (comment[nextPos] == ' ')
- || (comment[nextPos] == '\n')
- || (comment[nextPos] == '\r')
- || (comment[nextPos] == '*');
- break found;
- }
- }
- }
- }
- if (deprecated) {
- checkAndSetModifiers(AccDeprecated);
- }
- // modify the modifier source start to point at the first comment
- if (lastAnnotationIndex >= 0) {
- declarationSourceStart = scanner.commentStarts[0];
- }
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeClassBodyDeclaration() {
- // ClassBodyDeclaration ::= Diet Block
- //push an Initializer
- //optimize the push/pop
-
- super.consumeClassBodyDeclaration();
- Initializer initializer = (Initializer) astStack[astPtr];
- requestor.acceptInitializer(
- initializer.declarationSourceStart,
- initializer.declarationSourceEnd,
- intArrayStack[intArrayPtr--],
- 0,
- modifiersSourceStart,
- initializer.block.sourceStart,
- initializer.block.sourceEnd);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeClassDeclaration() {
- super.consumeClassDeclaration();
- // we know that we have a TypeDeclaration on the top of the astStack
- if (isLocalDeclaration()) {
- // we ignore the local variable declarations
- return;
- }
- requestor.exitClass(endStatementPosition, // '}' is the end of the body
- ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeClassHeader() {
- //ClassHeader ::= $empty
- super.consumeClassHeader();
- if (isLocalDeclaration()) {
- // we ignore the local variable declarations
- intArrayPtr--;
- return;
- }
- TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
- TypeReference[] superInterfaces = typeDecl.superInterfaces;
- char[][] interfaceNames = null;
- int[] interfaceNameStarts = null;
- int[] interfaceNameEnds = null;
- if (superInterfaces != null) {
- int superInterfacesLength = superInterfaces.length;
- interfaceNames = new char[superInterfacesLength][];
- interfaceNameStarts = new int[superInterfacesLength];
- interfaceNameEnds = new int[superInterfacesLength];
- for (int i = 0; i < superInterfacesLength; i++) {
- TypeReference superInterface = superInterfaces[i];
- interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.');
- interfaceNameStarts[i] = superInterface.sourceStart();
- interfaceNameEnds[i] = superInterface.sourceEnd();
- }
- }
- // flush the comments related to the class header
- scanner.commentPtr = -1;
- TypeReference superclass = typeDecl.superclass;
- if (superclass == null) {
- requestor.enterClass(
- typeDecl.declarationSourceStart,
- intArrayStack[intArrayPtr--],
- typeDecl.modifiers,
- typeDecl.modifiersSourceStart,
- typeStartPosition,
- typeDecl.name,
- typeDecl.sourceStart(),
- typeDecl.sourceEnd(),
- null,
- -1,
- -1,
- interfaceNames,
- interfaceNameStarts,
- interfaceNameEnds,
- scanner.currentPosition - 1);
- } else {
- requestor.enterClass(
- typeDecl.declarationSourceStart,
- intArrayStack[intArrayPtr--],
- typeDecl.modifiers,
- typeDecl.modifiersSourceStart,
- typeStartPosition,
- typeDecl.name,
- typeDecl.sourceStart(),
- typeDecl.sourceEnd(),
- CharOperation.concatWith(superclass.getTypeName(), '.'),
- superclass.sourceStart(),
- superclass.sourceEnd(),
- interfaceNames,
- interfaceNameStarts,
- interfaceNameEnds,
- scanner.currentPosition - 1);
-
- }
-}
-protected void consumeClassHeaderName() {
- // ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
- TypeDeclaration typeDecl;
- int length;
- if (nestedMethod[nestedType] == 0) {
- if (nestedType != 0) {
- typeDecl = new MemberTypeDeclaration();
- } else {
- typeDecl = new TypeDeclaration();
- }
- } else {
- // Record that the block has a declaration for local types
- typeDecl = new LocalTypeDeclaration();
- blockReal();
- }
-
- //highlight the name of the type
- long pos = identifierPositionStack[identifierPtr];
- typeDecl.sourceEnd = (int) pos;
- typeDecl.sourceStart = (int) (pos >>> 32);
- typeDecl.name = identifierStack[identifierPtr--];
- identifierLengthPtr--;
-
- //compute the declaration source too
- // 'class' and 'interface' push an int position
- typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
- int declarationSourceStart = intStack[intPtr--];
- typeDecl.modifiersSourceStart = intStack[intPtr--];
- typeDecl.modifiers = intStack[intPtr--];
- if (typeDecl.declarationSourceStart > declarationSourceStart) {
- typeDecl.declarationSourceStart = declarationSourceStart;
- }
- typeDecl.bodyStart = typeDecl.sourceEnd + 1;
- pushOnAstStack(typeDecl);
-
- length = 0; // will be updated when reading super-interfaces
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeCompilationUnit() {
- // CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt
- requestor.exitCompilationUnit(scanner.source.length - 1);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeConstructorDeclaration() {
- // ConstructorDeclaration ::= ConstructorHeader ConstructorBody
- super.consumeConstructorDeclaration();
- if (isLocalDeclaration()) {
- // we ignore the local variable declarations
- return;
- }
- ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
- requestor.exitConstructor(endStatementPosition, cd.declarationSourceEnd);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeConstructorHeader() {
- // ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
- super.consumeConstructorHeader();
- if (isLocalDeclaration()) {
- // we ignore the local variable declarations
- intArrayPtr--;
- return;
- }
- ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
- Argument[] arguments = cd.arguments;
- char[][] argumentTypes = null;
- char[][] argumentNames = null;
- int[] argumentTypeStarts = null;
- int[] argumentTypeEnds = null;
- int[] argumentNameStarts = null;
- int[] argumentNameEnds = null;
- if (arguments != null) {
- int argumentLength = arguments.length;
- argumentTypes = new char[argumentLength][];
- argumentNames = new char[argumentLength][];
- argumentNameStarts = new int[argumentLength];
- argumentNameEnds = new int[argumentLength];
- argumentTypeStarts = new int[argumentLength];
- argumentTypeEnds = new int[argumentLength];
- for (int i = 0; i < argumentLength; i++) {
- Argument argument = arguments[i];
- TypeReference argumentType = argument.type;
- argumentTypes[i] = returnTypeName(argumentType);
- argumentNames[i] = argument.name;
- argumentNameStarts[i] = argument.sourceStart();
- argumentNameEnds[i] = argument.sourceEnd();
- argumentTypeStarts[i] = argumentType.sourceStart();
- argumentTypeEnds[i] = argumentType.sourceEnd();
- }
- }
- TypeReference[] thrownExceptions = cd.thrownExceptions;
- char[][] exceptionTypes = null;
- int[] exceptionTypeStarts = null;
- int[] exceptionTypeEnds = null;
- if (thrownExceptions != null) {
- int thrownExceptionLength = thrownExceptions.length;
- exceptionTypes = new char[thrownExceptionLength][];
- exceptionTypeStarts = new int[thrownExceptionLength];
- exceptionTypeEnds = new int[thrownExceptionLength];
- for (int i = 0; i < thrownExceptionLength; i++) {
- TypeReference exception = thrownExceptions[i];
- exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
- exceptionTypeStarts[i] = exception.sourceStart();
- exceptionTypeEnds[i] = exception.sourceEnd();
- }
- }
- requestor
- .enterConstructor(
- cd.declarationSourceStart,
- intArrayStack[intArrayPtr--],
- cd.modifiers,
- cd.modifiersSourceStart,
- cd.selector,
- cd.sourceStart(),
- (int) (selectorSourcePositions & 0xFFFFFFFFL),
- // retrieve the source end of the name
- argumentTypes,
- argumentTypeStarts,
- argumentTypeEnds,
- argumentNames,
- argumentNameStarts,
- argumentNameEnds,
- rParenPos,
- // right parenthesis
- exceptionTypes,
- exceptionTypeStarts,
- exceptionTypeEnds,
- scanner.currentPosition - 1);
-}
-protected void consumeConstructorHeaderName() {
- // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
- ConstructorDeclaration cd = new ConstructorDeclaration();
-
- //name -- this is not really revelant but we do .....
- cd.selector = identifierStack[identifierPtr];
- selectorSourcePositions = identifierPositionStack[identifierPtr--];
- identifierLengthPtr--;
-
- //modifiers
- cd.declarationSourceStart = intStack[intPtr--];
- cd.modifiersSourceStart = intStack[intPtr--];
- cd.modifiers = intStack[intPtr--];
-
- //highlight starts at the selector starts
- cd.sourceStart = (int) (selectorSourcePositions >>> 32);
- pushOnAstStack(cd);
-
- cd.sourceEnd = lParenPos;
- cd.bodyStart = lParenPos + 1;
-}
-protected void consumeDefaultModifiers() {
- checkAnnotation(); // might update modifiers with AccDeprecated
- pushOnIntStack(modifiers); // modifiers
- pushOnIntStack(-1);
- pushOnIntStack(
- declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition);
- resetModifiers();
-}
-protected void consumeDiet() {
- // Diet ::= $empty
- super.consumeDiet();
- /* persisting javadoc positions
- * Will be consume in consumeClassBodyDeclaration
- */
- pushOnIntArrayStack(this.getJavaDocPositions());
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeEnterCompilationUnit() {
- // EnterCompilationUnit ::= $empty
- requestor.enterCompilationUnit();
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeEnterVariable() {
- // EnterVariable ::= $empty
- boolean isLocalDeclaration = isLocalDeclaration();
- if (!isLocalDeclaration && (variablesCounter[nestedType] != 0)) {
- requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
- }
- char[] name = identifierStack[identifierPtr];
- long namePosition = identifierPositionStack[identifierPtr--];
- int extendedTypeDimension = intStack[intPtr--];
-
- AbstractVariableDeclaration declaration;
- if (nestedMethod[nestedType] != 0) {
- // create the local variable declarations
- declaration =
- new LocalDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition);
- } else {
- // create the field declaration
- declaration =
- new FieldDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition);
- }
- identifierLengthPtr--;
- TypeReference type;
- int variableIndex = variablesCounter[nestedType];
- int typeDim = 0;
- if (variableIndex == 0) {
- // first variable of the declaration (FieldDeclaration or LocalDeclaration)
- if (nestedMethod[nestedType] != 0) {
- // local declaration
- declaration.declarationSourceStart = intStack[intPtr--];
- declaration.modifiersSourceStart = intStack[intPtr--];
- declaration.modifiers = intStack[intPtr--];
- type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
- pushOnAstStack(type);
- } else {
- // field declaration
- type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
- pushOnAstStack(type);
- declaration.declarationSourceStart = intStack[intPtr--];
- declaration.modifiersSourceStart = intStack[intPtr--];
- declaration.modifiers = intStack[intPtr--];
- }
- } else {
- type = (TypeReference) astStack[astPtr - variableIndex];
- typeDim = type.dimensions();
- AbstractVariableDeclaration previousVariable =
- (AbstractVariableDeclaration) astStack[astPtr];
- declaration.declarationSourceStart = previousVariable.declarationSourceStart;
- declaration.modifiers = previousVariable.modifiers;
- declaration.modifiersSourceStart = previousVariable.modifiersSourceStart;
- }
-
- localIntPtr = intPtr;
-
- if (extendedTypeDimension == 0) {
- declaration.type = type;
- } else {
- int dimension = typeDim + extendedTypeDimension;
- //on the identifierLengthStack there is the information about the type....
- int baseType;
- if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
- //it was a baseType
- declaration.type = TypeReference.baseTypeReference(-baseType, dimension);
- } else {
- declaration.type = type.copyDims(dimension);
- }
- }
- variablesCounter[nestedType]++;
- nestedMethod[nestedType]++;
- pushOnAstStack(declaration);
-
- int[] javadocPositions = intArrayStack[intArrayPtr];
- if (!isLocalDeclaration) {
- requestor
- .enterField(
- declaration.declarationSourceStart,
- javadocPositions,
- declaration.modifiers,
- declaration.modifiersSourceStart,
- returnTypeName(declaration.type),
- type.sourceStart(),
- type.sourceEnd(),
- typeDims,
- name,
- (int) (namePosition >>> 32),
- (int) namePosition,
- extendedTypeDimension,
- extendedTypeDimension == 0 ? -1 : endPosition);
- }
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeExitVariableWithInitialization() {
- // ExitVariableWithInitialization ::= $empty
- // the scanner is located after the comma or the semi-colon.
- // we want to include the comma or the semi-colon
- super.consumeExitVariableWithInitialization();
- nestedMethod[nestedType]--;
- lastFieldEndPosition = scanner.currentPosition - 1;
- lastFieldBodyEndPosition = ((AbstractVariableDeclaration) astStack[astPtr]).initialization.sourceEnd();
-}
-protected void consumeExitVariableWithoutInitialization() {
- // ExitVariableWithoutInitialization ::= $empty
- // do nothing by default
- super.consumeExitVariableWithoutInitialization();
- nestedMethod[nestedType]--;
- lastFieldEndPosition = scanner.currentPosition - 1;
- lastFieldBodyEndPosition = scanner.startPosition - 1;
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeFieldDeclaration() {
- // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
- // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
- // the super.consumeFieldDeclaration will reinitialize the variableCounter[nestedType]
- int variableIndex = variablesCounter[nestedType];
- super.consumeFieldDeclaration();
- intArrayPtr--;
- if (isLocalDeclaration())
- return;
- if (variableIndex != 0) {
- requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
- }
-}
-protected void consumeFormalParameter() {
- // FormalParameter ::= Type VariableDeclaratorId ==> false
- // FormalParameter ::= Modifiers Type VariableDeclaratorId ==> true
- /*
- astStack :
- identifierStack : type identifier
- intStack : dim dim
- ==>
- astStack : Argument
- identifierStack :
- intStack :
- */
-
- identifierLengthPtr--;
- char[] name = identifierStack[identifierPtr];
- long namePositions = identifierPositionStack[identifierPtr--];
- TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
- intPtr -= 3;
- Argument arg =
- new Argument(
- name,
- namePositions,
- type,
- intStack[intPtr + 1]); // modifiers
- pushOnAstStack(arg);
- intArrayPtr--;
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeInterfaceDeclaration() {
- super.consumeInterfaceDeclaration();
- // we know that we have a TypeDeclaration on the top of the astStack
- if (isLocalDeclaration()) {
- // we ignore the local variable declarations
- return;
- }
- requestor.exitInterface(endStatementPosition, // the '}' is the end of the body
- ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeInterfaceHeader() {
- //InterfaceHeader ::= $empty
- super.consumeInterfaceHeader();
- if (isLocalDeclaration()) {
- // we ignore the local variable declarations
- intArrayPtr--;
- return;
- }
- TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
- TypeReference[] superInterfaces = typeDecl.superInterfaces;
- char[][] interfaceNames = null;
- int[] interfaceNameStarts = null;
- int[] interfacenameEnds = null;
- int superInterfacesLength = 0;
- if (superInterfaces != null) {
- superInterfacesLength = superInterfaces.length;
- interfaceNames = new char[superInterfacesLength][];
- interfaceNameStarts = new int[superInterfacesLength];
- interfacenameEnds = new int[superInterfacesLength];
- }
- if (superInterfaces != null) {
- for (int i = 0; i < superInterfacesLength; i++) {
- TypeReference superInterface = superInterfaces[i];
- interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.');
- interfaceNameStarts[i] = superInterface.sourceStart();
- interfacenameEnds[i] = superInterface.sourceEnd();
- }
- }
- // flush the comments related to the interface header
- scanner.commentPtr = -1;
- requestor.enterInterface(
- typeDecl.declarationSourceStart,
- intArrayStack[intArrayPtr--],
- typeDecl.modifiers,
- typeDecl.modifiersSourceStart,
- typeStartPosition,
- typeDecl.name,
- typeDecl.sourceStart(),
- typeDecl.sourceEnd(),
- interfaceNames,
- interfaceNameStarts,
- interfacenameEnds,
- scanner.currentPosition - 1);
-}
-protected void consumeInterfaceHeaderName() {
- // InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
- TypeDeclaration typeDecl;
- int length;
- if (nestedMethod[nestedType] == 0) {
- if (nestedType != 0) {
- typeDecl = new MemberTypeDeclaration();
- } else {
- typeDecl = new TypeDeclaration();
- }
- } else {
- // Record that the block has a declaration for local types
- typeDecl = new LocalTypeDeclaration();
- blockReal();
- }
-
- //highlight the name of the type
- long pos = identifierPositionStack[identifierPtr];
- typeDecl.sourceEnd = (int) pos;
- typeDecl.sourceStart = (int) (pos >>> 32);
- typeDecl.name = identifierStack[identifierPtr--];
- identifierLengthPtr--;
-
- //compute the declaration source too
- // 'class' and 'interface' push an int position
- typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
- int declarationSourceStart = intStack[intPtr--];
- typeDecl.modifiersSourceStart = intStack[intPtr--];
- typeDecl.modifiers = intStack[intPtr--];
- if (typeDecl.declarationSourceStart > declarationSourceStart) {
- typeDecl.declarationSourceStart = declarationSourceStart;
- }
- typeDecl.bodyStart = typeDecl.sourceEnd + 1;
- pushOnAstStack(typeDecl);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeLocalVariableDeclaration() {
- // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
- // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
-
- super.consumeLocalVariableDeclaration();
- intArrayPtr--;
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeMethodDeclaration(boolean isNotAbstract) {
- // MethodDeclaration ::= MethodHeader MethodBody
- // AbstractMethodDeclaration ::= MethodHeader ';'
- super.consumeMethodDeclaration(isNotAbstract);
- if (isLocalDeclaration()) {
- // we ignore the local variable declarations
- return;
- }
- MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
- requestor.exitMethod(endStatementPosition, md.declarationSourceEnd);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeMethodHeader() {
- // MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
- super.consumeMethodHeader();
- if (isLocalDeclaration()) {
- // we ignore the local variable declarations
- intArrayPtr--;
- return;
- }
- int length;
- MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
-
- TypeReference returnType = md.returnType;
- char[] returnTypeName = returnTypeName(returnType);
- Argument[] arguments = md.arguments;
- char[][] argumentTypes = null;
- char[][] argumentNames = null;
- int[] argumentTypeStarts = null;
- int[] argumentTypeEnds = null;
- int[] argumentNameStarts = null;
- int[] argumentNameEnds = null;
- if (arguments != null) {
- int argumentLength = arguments.length;
- argumentTypes = new char[argumentLength][];
- argumentNames = new char[argumentLength][];
- argumentNameStarts = new int[argumentLength];
- argumentNameEnds = new int[argumentLength];
- argumentTypeStarts = new int[argumentLength];
- argumentTypeEnds = new int[argumentLength];
- for (int i = 0; i < argumentLength; i++) {
- Argument argument = arguments[i];
- TypeReference argumentType = argument.type;
- argumentTypes[i] = returnTypeName(argumentType);
- argumentNames[i] = argument.name;
- argumentNameStarts[i] = argument.sourceStart();
- argumentNameEnds[i] = argument.sourceEnd();
- argumentTypeStarts[i] = argumentType.sourceStart();
- argumentTypeEnds[i] = argumentType.sourceEnd();
- }
- }
- TypeReference[] thrownExceptions = md.thrownExceptions;
- char[][] exceptionTypes = null;
- int[] exceptionTypeStarts = null;
- int[] exceptionTypeEnds = null;
- if (thrownExceptions != null) {
- int thrownExceptionLength = thrownExceptions.length;
- exceptionTypeStarts = new int[thrownExceptionLength];
- exceptionTypeEnds = new int[thrownExceptionLength];
- exceptionTypes = new char[thrownExceptionLength][];
- for (int i = 0; i < thrownExceptionLength; i++) {
- TypeReference exception = thrownExceptions[i];
- exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
- exceptionTypeStarts[i] = exception.sourceStart();
- exceptionTypeEnds[i] = exception.sourceEnd();
- }
- }
- requestor
- .enterMethod(
- md.declarationSourceStart,
- intArrayStack[intArrayPtr--],
- md.modifiers,
- md.modifiersSourceStart,
- returnTypeName,
- returnType.sourceStart(),
- returnType.sourceEnd(),
- typeDims,
- md.selector,
- md.sourceStart(),
- (int) (selectorSourcePositions & 0xFFFFFFFFL),
- argumentTypes,
- argumentTypeStarts,
- argumentTypeEnds,
- argumentNames,
- argumentNameStarts,
- argumentNameEnds,
- rParenPos,
- extendsDim,
- extendsDim == 0 ? -1 : endPosition,
- exceptionTypes,
- exceptionTypeStarts,
- exceptionTypeEnds,
- scanner.currentPosition - 1);
-}
-protected void consumeMethodHeaderExtendedDims() {
- // MethodHeaderExtendedDims ::= Dimsopt
- // now we update the returnType of the method
- MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
- int extendedDims = intStack[intPtr--];
- extendsDim = extendedDims;
- if (extendedDims != 0) {
- TypeReference returnType = md.returnType;
- md.sourceEnd = endPosition;
- int dims = returnType.dimensions() + extendedDims;
- int baseType;
- if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
- //it was a baseType
- int sourceStart = returnType.sourceStart();
- int sourceEnd = returnType.sourceEnd();
- returnType = TypeReference.baseTypeReference(-baseType, dims);
- returnType.sourceStart = sourceStart;
- returnType.sourceEnd = sourceEnd;
- md.returnType = returnType;
- } else {
- md.returnType = md.returnType.copyDims(dims);
- }
- if (currentToken == TokenNameLBRACE) {
- md.bodyStart = endPosition + 1;
- }
- }
-}
-protected void consumeMethodHeaderName() {
- // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
- int length;
- MethodDeclaration md = new MethodDeclaration();
-
- //name
- md.selector = identifierStack[identifierPtr];
- selectorSourcePositions = identifierPositionStack[identifierPtr--];
- identifierLengthPtr--;
- //type
- md.returnType = getTypeReference(typeDims = intStack[intPtr--]);
- //modifiers
- md.declarationSourceStart = intStack[intPtr--];
- md.modifiersSourceStart = intStack[intPtr--];
- md.modifiers = intStack[intPtr--];
-
- //highlight starts at selector start
- md.sourceStart = (int) (selectorSourcePositions >>> 32);
- pushOnAstStack(md);
- md.bodyStart = scanner.currentPosition-1;
-}
-protected void consumeModifiers() {
- checkAnnotation(); // might update modifiers with AccDeprecated
- pushOnIntStack(modifiers); // modifiers
- pushOnIntStack(modifiersSourceStart);
- pushOnIntStack(
- declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
- resetModifiers();
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumePackageDeclarationName() {
- /* persisting javadoc positions */
- pushOnIntArrayStack(this.getJavaDocPositions());
-
- super.consumePackageDeclarationName();
- ImportReference importReference = compilationUnit.currentPackage;
-
- requestor.acceptPackage(
- importReference.declarationSourceStart,
- importReference.declarationSourceEnd,
- intArrayStack[intArrayPtr--],
- CharOperation.concatWith(importReference.getImportName(), '.'),
- importReference.sourceStart());
-}
-protected void consumePushModifiers() {
- checkAnnotation(); // might update modifiers with AccDeprecated
- pushOnIntStack(modifiers); // modifiers
- if (modifiersSourceStart < 0) {
- pushOnIntStack(-1);
- pushOnIntStack(
- declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition);
- } else {
- pushOnIntStack(modifiersSourceStart);
- pushOnIntStack(
- declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
- }
- resetModifiers();
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeSingleTypeImportDeclarationName() {
- // SingleTypeImportDeclarationName ::= 'import' Name
-
- /* persisting javadoc positions */
- pushOnIntArrayStack(this.getJavaDocPositions());
-
- super.consumeSingleTypeImportDeclarationName();
- ImportReference importReference = (ImportReference) astStack[astPtr];
- requestor.acceptImport(
- importReference.declarationSourceStart,
- importReference.declarationSourceEnd,
- intArrayStack[intArrayPtr--],
- CharOperation.concatWith(importReference.getImportName(), '.'),
- importReference.sourceStart(),
- false);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeStaticInitializer() {
- // StaticInitializer ::= StaticOnly Block
- //push an Initializer
- //optimize the push/pop
- super.consumeStaticInitializer();
- Initializer initializer = (Initializer) astStack[astPtr];
- requestor.acceptInitializer(
- initializer.declarationSourceStart,
- initializer.declarationSourceEnd,
- intArrayStack[intArrayPtr--],
- AccStatic,
- intStack[intPtr--],
- initializer.block.sourceStart,
- initializer.declarationSourceEnd);
-}
-protected void consumeStaticOnly() {
- // StaticOnly ::= 'static'
- checkAnnotation(); // might update declaration source start
- pushOnIntStack(modifiersSourceStart);
- pushOnIntStack(
- declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
- jumpOverMethodBody();
- nestedMethod[nestedType]++;
- resetModifiers();
-}
-protected void consumeToken(int type) {
- super.consumeToken(type);
-
- switch (type) {
- case TokenNamevoid :
- case TokenNameboolean :
- case TokenNamebyte :
- case TokenNamechar :
- case TokenNamedouble :
- case TokenNamefloat :
- case TokenNameint :
- case TokenNamelong :
- case TokenNameshort :
- // we need this position to know where the base type name ends.
- pushOnIntStack(scanner.currentPosition - 1);
- break;
- }
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeTypeImportOnDemandDeclarationName() {
- // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
-
- /* persisting javadoc positions */
- pushOnIntArrayStack(this.getJavaDocPositions());
-
- super.consumeTypeImportOnDemandDeclarationName();
- ImportReference importReference = (ImportReference) astStack[astPtr];
- requestor.acceptImport(
- importReference.declarationSourceStart,
- importReference.declarationSourceEnd,
- intArrayStack[intArrayPtr--],
- CharOperation.concatWith(importReference.getImportName(), '.'),
- importReference.sourceStart(),
- true);
-}
-public CompilationUnitDeclaration endParse(int act) {
- if (scanner.recordLineSeparator) {
- requestor.acceptLineSeparatorPositions(scanner.lineEnds());
- }
- return super.endParse(act);
-}
-/*
- * Flush annotations defined prior to a given positions.
- *
- * Note: annotations are stacked in syntactical order
- *
- * Either answer given <position>, or the end position of a comment line
- * immediately following the <position> (same line)
- *
- * e.g.
- * void foo(){
- * } // end of method foo
- */
-
-public int flushAnnotationsDefinedPriorTo(int position) {
-
- return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
-}
-protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
-This variable is a type reference and dim will be its dimensions*/
-
- int length;
- TypeReference ref;
- if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
- // single variable reference
- if (dim == 0) {
- ref =
- new SingleTypeReference(
- identifierStack[identifierPtr],
- identifierPositionStack[identifierPtr--]);
- } else {
- ref =
- new ArrayTypeReference(
- identifierStack[identifierPtr],
- dim,
- identifierPositionStack[identifierPtr--]);
- }
- } else {
- if (length < 0) { //flag for precompiled type reference on base types
- ref = TypeReference.baseTypeReference(-length, dim);
- ref.sourceEnd = intStack[intPtr--];
- ref.sourceStart = intStack[intPtr--];
- } else { //Qualified variable reference
- char[][] tokens = new char[length][];
- identifierPtr -= length;
- long[] positions = new long[length];
- System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
- System.arraycopy(
- identifierPositionStack,
- identifierPtr + 1,
- positions,
- 0,
- length);
- if (dim == 0)
- ref = new QualifiedTypeReference(tokens, positions);
- else
- ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
- }
- };
- return ref;
-}
-public void initialize() {
- //positionning the parser for a new compilation unit
- //avoiding stack reallocation and all that....
- super.initialize();
- intArrayPtr = -1;
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-private boolean isLocalDeclaration() {
- int nestedDepth = nestedType;
- while (nestedDepth >= 0) {
- if (nestedMethod[nestedDepth] != 0) {
- return true;
- }
- nestedDepth--;
- }
- return false;
-}
-/*
- * Investigate one entire unit.
- */
-public void parseCompilationUnit(ICompilationUnit unit) {
- char[] regionSource = unit.getContents();
- try {
- initialize();
- goForCompilationUnit();
- referenceContext =
- compilationUnit =
- compilationUnit =
- new CompilationUnitDeclaration(
- problemReporter(),
- new CompilationResult(unit, 0, 0),
- regionSource.length);
- scanner.resetTo(0, regionSource.length);
- scanner.setSourceBuffer(regionSource);
- parse();
- } catch (AbortCompilation ex) {
- }
-}
-/*
- * Investigate one constructor declaration.
- */
-public void parseConstructor(char[] regionSource) {
- try {
- initialize();
- goForClassBodyDeclarations();
- referenceContext =
- compilationUnit =
- compilationUnit =
- new CompilationUnitDeclaration(
- problemReporter(),
- new CompilationResult(regionSource, 0, 0),
- regionSource.length);
- scanner.resetTo(0, regionSource.length);
- scanner.setSourceBuffer(regionSource);
- parse();
- } catch (AbortCompilation ex) {
- }
-}
-/*
- * Investigate one field declaration statement (might have multiple declarations in it).
- */
-public void parseField(char[] regionSource) {
- try {
- initialize();
- goForFieldDeclaration();
- referenceContext =
- compilationUnit =
- compilationUnit =
- new CompilationUnitDeclaration(
- problemReporter(),
- new CompilationResult(regionSource, 0, 0),
- regionSource.length);
- scanner.resetTo(0, regionSource.length);
- scanner.setSourceBuffer(regionSource);
- parse();
- } catch (AbortCompilation ex) {
- }
-
-}
-/*
- * Investigate one import statement declaration.
- */
-public void parseImport(char[] regionSource) {
- try {
- initialize();
- goForImportDeclaration();
- referenceContext =
- compilationUnit =
- compilationUnit =
- new CompilationUnitDeclaration(
- problemReporter(),
- new CompilationResult(regionSource, 0, 0),
- regionSource.length);
- scanner.resetTo(0, regionSource.length);
- scanner.setSourceBuffer(regionSource);
- parse();
- } catch (AbortCompilation ex) {
- }
-
-}
-/*
- * Investigate one initializer declaration.
- * regionSource need to content exactly an initializer declaration.
- * e.g: static { i = 4; }
- * { name = "test"; }
- */
-public void parseInitializer(char[] regionSource) {
- try {
- initialize();
- goForInitializer();
- referenceContext =
- compilationUnit =
- compilationUnit =
- new CompilationUnitDeclaration(
- problemReporter(),
- new CompilationResult(regionSource, 0, 0),
- regionSource.length);
- scanner.resetTo(0, regionSource.length);
- scanner.setSourceBuffer(regionSource);
- parse();
- } catch (AbortCompilation ex) {
- }
-
-}
-/*
- * Investigate one method declaration.
- */
-public void parseMethod(char[] regionSource) {
- try {
- initialize();
- goForGenericMethodDeclaration();
- referenceContext =
- compilationUnit =
- compilationUnit =
- new CompilationUnitDeclaration(
- problemReporter(),
- new CompilationResult(regionSource, 0, 0),
- regionSource.length);
- scanner.resetTo(0, regionSource.length);
- scanner.setSourceBuffer(regionSource);
- parse();
- } catch (AbortCompilation ex) {
- }
-
-}
-/*
- * Investigate one package statement declaration.
- */
-public void parsePackage(char[] regionSource) {
- try {
- initialize();
- goForPackageDeclaration();
- referenceContext =
- compilationUnit =
- compilationUnit =
- new CompilationUnitDeclaration(
- problemReporter(),
- new CompilationResult(regionSource, 0, 0),
- regionSource.length);
- scanner.resetTo(0, regionSource.length);
- scanner.setSourceBuffer(regionSource);
- parse();
- } catch (AbortCompilation ex) {
- }
-
-}
-/*
- * Investigate one type declaration, its fields, methods and member types.
- */
-public void parseType(char[] regionSource) {
- try {
- initialize();
- goForTypeDeclaration();
- referenceContext =
- compilationUnit =
- compilationUnit =
- new CompilationUnitDeclaration(
- problemReporter(),
- new CompilationResult(regionSource, 0, 0),
- regionSource.length);
- scanner.resetTo(0, regionSource.length);
- scanner.setSourceBuffer(regionSource);
- parse();
- } catch (AbortCompilation ex) {
- }
-
-}
-/**
- * Returns this parser's problem reporter initialized with its reference context.
- * Also it is assumed that a problem is going to be reported, so initializes
- * the compilation result's line positions.
- */
-public ProblemReporter problemReporter() {
- problemReporter.referenceContext = referenceContext;
- return problemReporter;
-}
-protected void pushOnIntArrayStack(int[] positions) {
-
- try {
- intArrayStack[++intArrayPtr] = positions;
- } catch (IndexOutOfBoundsException e) {
- //intPtr is correct
- int oldStackLength = intArrayStack.length;
- int oldStack[][] = intArrayStack;
- intArrayStack = new int[oldStackLength + StackIncrement][];
- System.arraycopy(oldStack, 0, intArrayStack, 0, oldStackLength);
- intArrayStack[intArrayPtr] = positions;
- }
-}
-protected void resetModifiers() {
- super.resetModifiers();
- declarationSourceStart = -1;
-}
-/*
- * Syntax error was detected. Will attempt to perform some recovery action in order
- * to resume to the regular parse loop.
- */
-protected boolean resumeOnSyntaxError() {
- return false;
-}
-/*
- * Answer a char array representation of the type name formatted like:
- * - type name + dimensions
- * Example:
- * "A[][]".toCharArray()
- * "java.lang.String".toCharArray()
- */
-private char[] returnTypeName(TypeReference type) {
- int dimension = type.dimensions();
- if (dimension != 0) {
- char[] dimensionsArray = new char[dimension * 2];
- for (int i = 0; i < dimension; i++) {
- dimensionsArray[i*2] = '[';
- dimensionsArray[(i*2) + 1] = ']';
- }
- return CharOperation.concat(
- CharOperation.concatWith(type.getTypeName(), '.'),
- dimensionsArray);
- }
- return CharOperation.concatWith(type.getTypeName(), '.');
-}
-public String toString() {
- StringBuffer buffer = new StringBuffer();
- buffer.append("intArrayPtr = "/*nonNLS*/ + intArrayPtr + "\n"/*nonNLS*/);
- buffer.append(super.toString());
- return buffer.toString();
-}
-/**
- * INTERNAL USE ONLY
- */
-protected TypeReference typeReference(
- int dim,
- int localIdentifierPtr,
- int localIdentifierLengthPtr) {
- /* build a Reference on a variable that may be qualified or not
- * This variable is a type reference and dim will be its dimensions.
- * We don't have any side effect on the stacks' pointers.
- */
-
- int length;
- TypeReference ref;
- if ((length = identifierLengthStack[localIdentifierLengthPtr]) == 1) {
- // single variable reference
- if (dim == 0) {
- ref =
- new SingleTypeReference(
- identifierStack[localIdentifierPtr],
- identifierPositionStack[localIdentifierPtr--]);
- } else {
- ref =
- new ArrayTypeReference(
- identifierStack[localIdentifierPtr],
- dim,
- identifierPositionStack[localIdentifierPtr--]);
- }
- } else {
- if (length < 0) { //flag for precompiled type reference on base types
- ref = TypeReference.baseTypeReference(-length, dim);
- ref.sourceEnd = intStack[localIntPtr--];
- ref.sourceStart = intStack[localIntPtr--];
- } else { //Qualified variable reference
- char[][] tokens = new char[length][];
- localIdentifierPtr -= length;
- long[] positions = new long[length];
- System.arraycopy(identifierStack, localIdentifierPtr + 1, tokens, 0, length);
- System.arraycopy(
- identifierPositionStack,
- localIdentifierPtr + 1,
- positions,
- 0,
- length);
- if (dim == 0)
- ref = new QualifiedTypeReference(tokens, positions);
- else
- ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
- }
- };
- return ref;
-}
-}
+package org.eclipse.jdt.internal.compiler;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+/*
+ * A document element parser extracts structural information
+ * from a piece of source, providing detailed source positions info.
+ *
+ * also see @IDocumentElementRequestor
+ *
+ * The structural investigation includes:
+ * - the package statement
+ * - import statements
+ * - top-level types: package member, member types (member types of member types...)
+ * - fields
+ * - methods
+ *
+ * Any (parsing) problem encountered is also provided.
+ */
+import org.eclipse.jdt.internal.compiler.env.*;
+
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.parser.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.compiler.util.*;
+
+public class DocumentElementParser extends Parser {
+ IDocumentElementRequestor requestor;
+ private int localIntPtr;
+ private int lastFieldEndPosition;
+ private int lastFieldBodyEndPosition;
+ private int typeStartPosition;
+ private long selectorSourcePositions;
+ private int typeDims;
+ private int extendsDim;
+ private int declarationSourceStart;
+
+ /* int[] stack for storing javadoc positions */
+ int[][] intArrayStack;
+ int intArrayPtr;
+public DocumentElementParser(
+ final IDocumentElementRequestor requestor,
+ IProblemFactory problemFactory) {
+ super(new ProblemReporter(
+ DefaultErrorHandlingPolicies.exitAfterAllProblems(),
+ new CompilerOptions(),
+ problemFactory) {
+ public void record(IProblem problem, CompilationResult unitResult) {
+ requestor.acceptProblem(problem);
+ }
+ }, false);
+ this.requestor = requestor;
+ intArrayStack = new int[30][];
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void adjustInterfaceModifiers() {
+ intStack[intPtr - 2] |= AccInterface;
+}
+/*
+ * Will clear the comment stack when looking
+ * for a potential JavaDoc which might contain @deprecated.
+ *
+ * Additionally, before investigating for @deprecated, retrieve the positions
+ * of the JavaDoc comments so as to notify requestor with them.
+ */
+public void checkAnnotation() {
+
+ /* persisting javadoc positions */
+ pushOnIntArrayStack(this.getJavaDocPositions());
+ boolean deprecated = false;
+ int lastAnnotationIndex = -1;
+
+ //since jdk1.2 look only in the last java doc comment...
+ found : {
+ if ((lastAnnotationIndex = scanner.commentPtr) >= 0) { //look for @deprecated
+ scanner.commentPtr = -1;
+ // reset the comment stack, since not necessary after having checked
+ int commentSourceStart = scanner.commentStarts[lastAnnotationIndex];
+ // javadoc only (non javadoc comment have negative end positions.)
+ int commentSourceEnd = scanner.commentStops[lastAnnotationIndex] - 1;
+ //stop is one over
+ char[] comment = scanner.source;
+
+ for (int i = commentSourceStart + 3; i < commentSourceEnd - 10; i++) {
+ if ((comment[i] == '@')
+ && (comment[i + 1] == 'd')
+ && (comment[i + 2] == 'e')
+ && (comment[i + 3] == 'p')
+ && (comment[i + 4] == 'r')
+ && (comment[i + 5] == 'e')
+ && (comment[i + 6] == 'c')
+ && (comment[i + 7] == 'a')
+ && (comment[i + 8] == 't')
+ && (comment[i + 9] == 'e')
+ && (comment[i + 10] == 'd')) {
+ // ensure the tag is properly ended: either followed by a space, line end or asterisk.
+ int nextPos = i + 11;
+ deprecated =
+ (comment[nextPos] == ' ')
+ || (comment[nextPos] == '\n')
+ || (comment[nextPos] == '\r')
+ || (comment[nextPos] == '*');
+ break found;
+ }
+ }
+ }
+ }
+ if (deprecated) {
+ checkAndSetModifiers(AccDeprecated);
+ }
+ // modify the modifier source start to point at the first comment
+ if (lastAnnotationIndex >= 0) {
+ declarationSourceStart = scanner.commentStarts[0];
+ }
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeClassBodyDeclaration() {
+ // ClassBodyDeclaration ::= Diet Block
+ //push an Initializer
+ //optimize the push/pop
+
+ super.consumeClassBodyDeclaration();
+ Initializer initializer = (Initializer) astStack[astPtr];
+ requestor.acceptInitializer(
+ initializer.declarationSourceStart,
+ initializer.declarationSourceEnd,
+ intArrayStack[intArrayPtr--],
+ 0,
+ modifiersSourceStart,
+ initializer.block.sourceStart,
+ initializer.block.sourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeClassDeclaration() {
+ super.consumeClassDeclaration();
+ // we know that we have a TypeDeclaration on the top of the astStack
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ return;
+ }
+ requestor.exitClass(endStatementPosition, // '}' is the end of the body
+ ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeClassHeader() {
+ //ClassHeader ::= $empty
+ super.consumeClassHeader();
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ intArrayPtr--;
+ return;
+ }
+ TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
+ TypeReference[] superInterfaces = typeDecl.superInterfaces;
+ char[][] interfaceNames = null;
+ int[] interfaceNameStarts = null;
+ int[] interfaceNameEnds = null;
+ if (superInterfaces != null) {
+ int superInterfacesLength = superInterfaces.length;
+ interfaceNames = new char[superInterfacesLength][];
+ interfaceNameStarts = new int[superInterfacesLength];
+ interfaceNameEnds = new int[superInterfacesLength];
+ for (int i = 0; i < superInterfacesLength; i++) {
+ TypeReference superInterface = superInterfaces[i];
+ interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.');
+ interfaceNameStarts[i] = superInterface.sourceStart();
+ interfaceNameEnds[i] = superInterface.sourceEnd();
+ }
+ }
+ // flush the comments related to the class header
+ scanner.commentPtr = -1;
+ TypeReference superclass = typeDecl.superclass;
+ if (superclass == null) {
+ requestor.enterClass(
+ typeDecl.declarationSourceStart,
+ intArrayStack[intArrayPtr--],
+ typeDecl.modifiers,
+ typeDecl.modifiersSourceStart,
+ typeStartPosition,
+ typeDecl.name,
+ typeDecl.sourceStart(),
+ typeDecl.sourceEnd(),
+ null,
+ -1,
+ -1,
+ interfaceNames,
+ interfaceNameStarts,
+ interfaceNameEnds,
+ scanner.currentPosition - 1);
+ } else {
+ requestor.enterClass(
+ typeDecl.declarationSourceStart,
+ intArrayStack[intArrayPtr--],
+ typeDecl.modifiers,
+ typeDecl.modifiersSourceStart,
+ typeStartPosition,
+ typeDecl.name,
+ typeDecl.sourceStart(),
+ typeDecl.sourceEnd(),
+ CharOperation.concatWith(superclass.getTypeName(), '.'),
+ superclass.sourceStart(),
+ superclass.sourceEnd(),
+ interfaceNames,
+ interfaceNameStarts,
+ interfaceNameEnds,
+ scanner.currentPosition - 1);
+
+ }
+}
+protected void consumeClassHeaderName() {
+ // ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
+ TypeDeclaration typeDecl;
+ int length;
+ if (nestedMethod[nestedType] == 0) {
+ if (nestedType != 0) {
+ typeDecl = new MemberTypeDeclaration();
+ } else {
+ typeDecl = new TypeDeclaration();
+ }
+ } else {
+ // Record that the block has a declaration for local types
+ typeDecl = new LocalTypeDeclaration();
+ blockReal();
+ }
+
+ //highlight the name of the type
+ long pos = identifierPositionStack[identifierPtr];
+ typeDecl.sourceEnd = (int) pos;
+ typeDecl.sourceStart = (int) (pos >>> 32);
+ typeDecl.name = identifierStack[identifierPtr--];
+ identifierLengthPtr--;
+
+ //compute the declaration source too
+ // 'class' and 'interface' push an int position
+ typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
+ int declarationSourceStart = intStack[intPtr--];
+ typeDecl.modifiersSourceStart = intStack[intPtr--];
+ typeDecl.modifiers = intStack[intPtr--];
+ if (typeDecl.declarationSourceStart > declarationSourceStart) {
+ typeDecl.declarationSourceStart = declarationSourceStart;
+ }
+ typeDecl.bodyStart = typeDecl.sourceEnd + 1;
+ pushOnAstStack(typeDecl);
+
+ length = 0; // will be updated when reading super-interfaces
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeCompilationUnit() {
+ // CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt
+ requestor.exitCompilationUnit(scanner.source.length - 1);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeConstructorDeclaration() {
+ // ConstructorDeclaration ::= ConstructorHeader ConstructorBody
+ super.consumeConstructorDeclaration();
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ return;
+ }
+ ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
+ requestor.exitConstructor(endStatementPosition, cd.declarationSourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeConstructorHeader() {
+ // ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
+ super.consumeConstructorHeader();
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ intArrayPtr--;
+ return;
+ }
+ ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
+ Argument[] arguments = cd.arguments;
+ char[][] argumentTypes = null;
+ char[][] argumentNames = null;
+ int[] argumentTypeStarts = null;
+ int[] argumentTypeEnds = null;
+ int[] argumentNameStarts = null;
+ int[] argumentNameEnds = null;
+ if (arguments != null) {
+ int argumentLength = arguments.length;
+ argumentTypes = new char[argumentLength][];
+ argumentNames = new char[argumentLength][];
+ argumentNameStarts = new int[argumentLength];
+ argumentNameEnds = new int[argumentLength];
+ argumentTypeStarts = new int[argumentLength];
+ argumentTypeEnds = new int[argumentLength];
+ for (int i = 0; i < argumentLength; i++) {
+ Argument argument = arguments[i];
+ TypeReference argumentType = argument.type;
+ argumentTypes[i] = returnTypeName(argumentType);
+ argumentNames[i] = argument.name;
+ argumentNameStarts[i] = argument.sourceStart();
+ argumentNameEnds[i] = argument.sourceEnd();
+ argumentTypeStarts[i] = argumentType.sourceStart();
+ argumentTypeEnds[i] = argumentType.sourceEnd();
+ }
+ }
+ TypeReference[] thrownExceptions = cd.thrownExceptions;
+ char[][] exceptionTypes = null;
+ int[] exceptionTypeStarts = null;
+ int[] exceptionTypeEnds = null;
+ if (thrownExceptions != null) {
+ int thrownExceptionLength = thrownExceptions.length;
+ exceptionTypes = new char[thrownExceptionLength][];
+ exceptionTypeStarts = new int[thrownExceptionLength];
+ exceptionTypeEnds = new int[thrownExceptionLength];
+ for (int i = 0; i < thrownExceptionLength; i++) {
+ TypeReference exception = thrownExceptions[i];
+ exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
+ exceptionTypeStarts[i] = exception.sourceStart();
+ exceptionTypeEnds[i] = exception.sourceEnd();
+ }
+ }
+ requestor
+ .enterConstructor(
+ cd.declarationSourceStart,
+ intArrayStack[intArrayPtr--],
+ cd.modifiers,
+ cd.modifiersSourceStart,
+ cd.selector,
+ cd.sourceStart(),
+ (int) (selectorSourcePositions & 0xFFFFFFFFL),
+ // retrieve the source end of the name
+ argumentTypes,
+ argumentTypeStarts,
+ argumentTypeEnds,
+ argumentNames,
+ argumentNameStarts,
+ argumentNameEnds,
+ rParenPos,
+ // right parenthesis
+ exceptionTypes,
+ exceptionTypeStarts,
+ exceptionTypeEnds,
+ scanner.currentPosition - 1);
+}
+protected void consumeConstructorHeaderName() {
+ // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
+ ConstructorDeclaration cd = new ConstructorDeclaration();
+
+ //name -- this is not really revelant but we do .....
+ cd.selector = identifierStack[identifierPtr];
+ selectorSourcePositions = identifierPositionStack[identifierPtr--];
+ identifierLengthPtr--;
+
+ //modifiers
+ cd.declarationSourceStart = intStack[intPtr--];
+ cd.modifiersSourceStart = intStack[intPtr--];
+ cd.modifiers = intStack[intPtr--];
+
+ //highlight starts at the selector starts
+ cd.sourceStart = (int) (selectorSourcePositions >>> 32);
+ pushOnAstStack(cd);
+
+ cd.sourceEnd = lParenPos;
+ cd.bodyStart = lParenPos + 1;
+}
+protected void consumeDefaultModifiers() {
+ checkAnnotation(); // might update modifiers with AccDeprecated
+ pushOnIntStack(modifiers); // modifiers
+ pushOnIntStack(-1);
+ pushOnIntStack(
+ declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition);
+ resetModifiers();
+}
+protected void consumeDiet() {
+ // Diet ::= $empty
+ super.consumeDiet();
+ /* persisting javadoc positions
+ * Will be consume in consumeClassBodyDeclaration
+ */
+ pushOnIntArrayStack(this.getJavaDocPositions());
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeEnterCompilationUnit() {
+ // EnterCompilationUnit ::= $empty
+ requestor.enterCompilationUnit();
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeEnterVariable() {
+ // EnterVariable ::= $empty
+ boolean isLocalDeclaration = isLocalDeclaration();
+ if (!isLocalDeclaration && (variablesCounter[nestedType] != 0)) {
+ requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
+ }
+ char[] name = identifierStack[identifierPtr];
+ long namePosition = identifierPositionStack[identifierPtr--];
+ int extendedTypeDimension = intStack[intPtr--];
+
+ AbstractVariableDeclaration declaration;
+ if (nestedMethod[nestedType] != 0) {
+ // create the local variable declarations
+ declaration =
+ new LocalDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition);
+ } else {
+ // create the field declaration
+ declaration =
+ new FieldDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition);
+ }
+ identifierLengthPtr--;
+ TypeReference type;
+ int variableIndex = variablesCounter[nestedType];
+ int typeDim = 0;
+ if (variableIndex == 0) {
+ // first variable of the declaration (FieldDeclaration or LocalDeclaration)
+ if (nestedMethod[nestedType] != 0) {
+ // local declaration
+ declaration.declarationSourceStart = intStack[intPtr--];
+ declaration.modifiersSourceStart = intStack[intPtr--];
+ declaration.modifiers = intStack[intPtr--];
+ type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
+ pushOnAstStack(type);
+ } else {
+ // field declaration
+ type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
+ pushOnAstStack(type);
+ declaration.declarationSourceStart = intStack[intPtr--];
+ declaration.modifiersSourceStart = intStack[intPtr--];
+ declaration.modifiers = intStack[intPtr--];
+ }
+ } else {
+ type = (TypeReference) astStack[astPtr - variableIndex];
+ typeDim = type.dimensions();
+ AbstractVariableDeclaration previousVariable =
+ (AbstractVariableDeclaration) astStack[astPtr];
+ declaration.declarationSourceStart = previousVariable.declarationSourceStart;
+ declaration.modifiers = previousVariable.modifiers;
+ declaration.modifiersSourceStart = previousVariable.modifiersSourceStart;
+ }
+
+ localIntPtr = intPtr;
+
+ if (extendedTypeDimension == 0) {
+ declaration.type = type;
+ } else {
+ int dimension = typeDim + extendedTypeDimension;
+ //on the identifierLengthStack there is the information about the type....
+ int baseType;
+ if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
+ //it was a baseType
+ declaration.type = TypeReference.baseTypeReference(-baseType, dimension);
+ } else {
+ declaration.type = type.copyDims(dimension);
+ }
+ }
+ variablesCounter[nestedType]++;
+ nestedMethod[nestedType]++;
+ pushOnAstStack(declaration);
+
+ int[] javadocPositions = intArrayStack[intArrayPtr];
+ if (!isLocalDeclaration) {
+ requestor
+ .enterField(
+ declaration.declarationSourceStart,
+ javadocPositions,
+ declaration.modifiers,
+ declaration.modifiersSourceStart,
+ returnTypeName(declaration.type),
+ type.sourceStart(),
+ type.sourceEnd(),
+ typeDims,
+ name,
+ (int) (namePosition >>> 32),
+ (int) namePosition,
+ extendedTypeDimension,
+ extendedTypeDimension == 0 ? -1 : endPosition);
+ }
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeExitVariableWithInitialization() {
+ // ExitVariableWithInitialization ::= $empty
+ // the scanner is located after the comma or the semi-colon.
+ // we want to include the comma or the semi-colon
+ super.consumeExitVariableWithInitialization();
+ nestedMethod[nestedType]--;
+ lastFieldEndPosition = scanner.currentPosition - 1;
+ lastFieldBodyEndPosition = ((AbstractVariableDeclaration) astStack[astPtr]).initialization.sourceEnd();
+}
+protected void consumeExitVariableWithoutInitialization() {
+ // ExitVariableWithoutInitialization ::= $empty
+ // do nothing by default
+ super.consumeExitVariableWithoutInitialization();
+ nestedMethod[nestedType]--;
+ lastFieldEndPosition = scanner.currentPosition - 1;
+ lastFieldBodyEndPosition = scanner.startPosition - 1;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeFieldDeclaration() {
+ // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
+ // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
+ // the super.consumeFieldDeclaration will reinitialize the variableCounter[nestedType]
+ int variableIndex = variablesCounter[nestedType];
+ super.consumeFieldDeclaration();
+ intArrayPtr--;
+ if (isLocalDeclaration())
+ return;
+ if (variableIndex != 0) {
+ requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
+ }
+}
+protected void consumeFormalParameter() {
+ // FormalParameter ::= Type VariableDeclaratorId ==> false
+ // FormalParameter ::= Modifiers Type VariableDeclaratorId ==> true
+ /*
+ astStack :
+ identifierStack : type identifier
+ intStack : dim dim
+ ==>
+ astStack : Argument
+ identifierStack :
+ intStack :
+ */
+
+ identifierLengthPtr--;
+ char[] name = identifierStack[identifierPtr];
+ long namePositions = identifierPositionStack[identifierPtr--];
+ TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
+ intPtr -= 3;
+ Argument arg =
+ new Argument(
+ name,
+ namePositions,
+ type,
+ intStack[intPtr + 1]); // modifiers
+ pushOnAstStack(arg);
+ intArrayPtr--;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeInterfaceDeclaration() {
+ super.consumeInterfaceDeclaration();
+ // we know that we have a TypeDeclaration on the top of the astStack
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ return;
+ }
+ requestor.exitInterface(endStatementPosition, // the '}' is the end of the body
+ ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeInterfaceHeader() {
+ //InterfaceHeader ::= $empty
+ super.consumeInterfaceHeader();
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ intArrayPtr--;
+ return;
+ }
+ TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
+ TypeReference[] superInterfaces = typeDecl.superInterfaces;
+ char[][] interfaceNames = null;
+ int[] interfaceNameStarts = null;
+ int[] interfacenameEnds = null;
+ int superInterfacesLength = 0;
+ if (superInterfaces != null) {
+ superInterfacesLength = superInterfaces.length;
+ interfaceNames = new char[superInterfacesLength][];
+ interfaceNameStarts = new int[superInterfacesLength];
+ interfacenameEnds = new int[superInterfacesLength];
+ }
+ if (superInterfaces != null) {
+ for (int i = 0; i < superInterfacesLength; i++) {
+ TypeReference superInterface = superInterfaces[i];
+ interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.');
+ interfaceNameStarts[i] = superInterface.sourceStart();
+ interfacenameEnds[i] = superInterface.sourceEnd();
+ }
+ }
+ // flush the comments related to the interface header
+ scanner.commentPtr = -1;
+ requestor.enterInterface(
+ typeDecl.declarationSourceStart,
+ intArrayStack[intArrayPtr--],
+ typeDecl.modifiers,
+ typeDecl.modifiersSourceStart,
+ typeStartPosition,
+ typeDecl.name,
+ typeDecl.sourceStart(),
+ typeDecl.sourceEnd(),
+ interfaceNames,
+ interfaceNameStarts,
+ interfacenameEnds,
+ scanner.currentPosition - 1);
+}
+protected void consumeInterfaceHeaderName() {
+ // InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
+ TypeDeclaration typeDecl;
+ int length;
+ if (nestedMethod[nestedType] == 0) {
+ if (nestedType != 0) {
+ typeDecl = new MemberTypeDeclaration();
+ } else {
+ typeDecl = new TypeDeclaration();
+ }
+ } else {
+ // Record that the block has a declaration for local types
+ typeDecl = new LocalTypeDeclaration();
+ blockReal();
+ }
+
+ //highlight the name of the type
+ long pos = identifierPositionStack[identifierPtr];
+ typeDecl.sourceEnd = (int) pos;
+ typeDecl.sourceStart = (int) (pos >>> 32);
+ typeDecl.name = identifierStack[identifierPtr--];
+ identifierLengthPtr--;
+
+ //compute the declaration source too
+ // 'class' and 'interface' push an int position
+ typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
+ int declarationSourceStart = intStack[intPtr--];
+ typeDecl.modifiersSourceStart = intStack[intPtr--];
+ typeDecl.modifiers = intStack[intPtr--];
+ if (typeDecl.declarationSourceStart > declarationSourceStart) {
+ typeDecl.declarationSourceStart = declarationSourceStart;
+ }
+ typeDecl.bodyStart = typeDecl.sourceEnd + 1;
+ pushOnAstStack(typeDecl);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeLocalVariableDeclaration() {
+ // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
+ // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
+
+ super.consumeLocalVariableDeclaration();
+ intArrayPtr--;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodDeclaration(boolean isNotAbstract) {
+ // MethodDeclaration ::= MethodHeader MethodBody
+ // AbstractMethodDeclaration ::= MethodHeader ';'
+ super.consumeMethodDeclaration(isNotAbstract);
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ return;
+ }
+ MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
+ requestor.exitMethod(endStatementPosition, md.declarationSourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodHeader() {
+ // MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
+ super.consumeMethodHeader();
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ intArrayPtr--;
+ return;
+ }
+ int length;
+ MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
+
+ TypeReference returnType = md.returnType;
+ char[] returnTypeName = returnTypeName(returnType);
+ Argument[] arguments = md.arguments;
+ char[][] argumentTypes = null;
+ char[][] argumentNames = null;
+ int[] argumentTypeStarts = null;
+ int[] argumentTypeEnds = null;
+ int[] argumentNameStarts = null;
+ int[] argumentNameEnds = null;
+ if (arguments != null) {
+ int argumentLength = arguments.length;
+ argumentTypes = new char[argumentLength][];
+ argumentNames = new char[argumentLength][];
+ argumentNameStarts = new int[argumentLength];
+ argumentNameEnds = new int[argumentLength];
+ argumentTypeStarts = new int[argumentLength];
+ argumentTypeEnds = new int[argumentLength];
+ for (int i = 0; i < argumentLength; i++) {
+ Argument argument = arguments[i];
+ TypeReference argumentType = argument.type;
+ argumentTypes[i] = returnTypeName(argumentType);
+ argumentNames[i] = argument.name;
+ argumentNameStarts[i] = argument.sourceStart();
+ argumentNameEnds[i] = argument.sourceEnd();
+ argumentTypeStarts[i] = argumentType.sourceStart();
+ argumentTypeEnds[i] = argumentType.sourceEnd();
+ }
+ }
+ TypeReference[] thrownExceptions = md.thrownExceptions;
+ char[][] exceptionTypes = null;
+ int[] exceptionTypeStarts = null;
+ int[] exceptionTypeEnds = null;
+ if (thrownExceptions != null) {
+ int thrownExceptionLength = thrownExceptions.length;
+ exceptionTypeStarts = new int[thrownExceptionLength];
+ exceptionTypeEnds = new int[thrownExceptionLength];
+ exceptionTypes = new char[thrownExceptionLength][];
+ for (int i = 0; i < thrownExceptionLength; i++) {
+ TypeReference exception = thrownExceptions[i];
+ exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
+ exceptionTypeStarts[i] = exception.sourceStart();
+ exceptionTypeEnds[i] = exception.sourceEnd();
+ }
+ }
+ requestor
+ .enterMethod(
+ md.declarationSourceStart,
+ intArrayStack[intArrayPtr--],
+ md.modifiers,
+ md.modifiersSourceStart,
+ returnTypeName,
+ returnType.sourceStart(),
+ returnType.sourceEnd(),
+ typeDims,
+ md.selector,
+ md.sourceStart(),
+ (int) (selectorSourcePositions & 0xFFFFFFFFL),
+ argumentTypes,
+ argumentTypeStarts,
+ argumentTypeEnds,
+ argumentNames,
+ argumentNameStarts,
+ argumentNameEnds,
+ rParenPos,
+ extendsDim,
+ extendsDim == 0 ? -1 : endPosition,
+ exceptionTypes,
+ exceptionTypeStarts,
+ exceptionTypeEnds,
+ scanner.currentPosition - 1);
+}
+protected void consumeMethodHeaderExtendedDims() {
+ // MethodHeaderExtendedDims ::= Dimsopt
+ // now we update the returnType of the method
+ MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
+ int extendedDims = intStack[intPtr--];
+ extendsDim = extendedDims;
+ if (extendedDims != 0) {
+ TypeReference returnType = md.returnType;
+ md.sourceEnd = endPosition;
+ int dims = returnType.dimensions() + extendedDims;
+ int baseType;
+ if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
+ //it was a baseType
+ int sourceStart = returnType.sourceStart();
+ int sourceEnd = returnType.sourceEnd();
+ returnType = TypeReference.baseTypeReference(-baseType, dims);
+ returnType.sourceStart = sourceStart;
+ returnType.sourceEnd = sourceEnd;
+ md.returnType = returnType;
+ } else {
+ md.returnType = md.returnType.copyDims(dims);
+ }
+ if (currentToken == TokenNameLBRACE) {
+ md.bodyStart = endPosition + 1;
+ }
+ }
+}
+protected void consumeMethodHeaderName() {
+ // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+ int length;
+ MethodDeclaration md = new MethodDeclaration();
+
+ //name
+ md.selector = identifierStack[identifierPtr];
+ selectorSourcePositions = identifierPositionStack[identifierPtr--];
+ identifierLengthPtr--;
+ //type
+ md.returnType = getTypeReference(typeDims = intStack[intPtr--]);
+ //modifiers
+ md.declarationSourceStart = intStack[intPtr--];
+ md.modifiersSourceStart = intStack[intPtr--];
+ md.modifiers = intStack[intPtr--];
+
+ //highlight starts at selector start
+ md.sourceStart = (int) (selectorSourcePositions >>> 32);
+ pushOnAstStack(md);
+ md.bodyStart = scanner.currentPosition-1;
+}
+protected void consumeModifiers() {
+ checkAnnotation(); // might update modifiers with AccDeprecated
+ pushOnIntStack(modifiers); // modifiers
+ pushOnIntStack(modifiersSourceStart);
+ pushOnIntStack(
+ declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
+ resetModifiers();
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumePackageDeclarationName() {
+ /* persisting javadoc positions */
+ pushOnIntArrayStack(this.getJavaDocPositions());
+
+ super.consumePackageDeclarationName();
+ ImportReference importReference = compilationUnit.currentPackage;
+
+ requestor.acceptPackage(
+ importReference.declarationSourceStart,
+ importReference.declarationSourceEnd,
+ intArrayStack[intArrayPtr--],
+ CharOperation.concatWith(importReference.getImportName(), '.'),
+ importReference.sourceStart());
+}
+protected void consumePushModifiers() {
+ checkAnnotation(); // might update modifiers with AccDeprecated
+ pushOnIntStack(modifiers); // modifiers
+ if (modifiersSourceStart < 0) {
+ pushOnIntStack(-1);
+ pushOnIntStack(
+ declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition);
+ } else {
+ pushOnIntStack(modifiersSourceStart);
+ pushOnIntStack(
+ declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
+ }
+ resetModifiers();
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeSingleTypeImportDeclarationName() {
+ // SingleTypeImportDeclarationName ::= 'import' Name
+
+ /* persisting javadoc positions */
+ pushOnIntArrayStack(this.getJavaDocPositions());
+
+ super.consumeSingleTypeImportDeclarationName();
+ ImportReference importReference = (ImportReference) astStack[astPtr];
+ requestor.acceptImport(
+ importReference.declarationSourceStart,
+ importReference.declarationSourceEnd,
+ intArrayStack[intArrayPtr--],
+ CharOperation.concatWith(importReference.getImportName(), '.'),
+ importReference.sourceStart(),
+ false);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeStaticInitializer() {
+ // StaticInitializer ::= StaticOnly Block
+ //push an Initializer
+ //optimize the push/pop
+ super.consumeStaticInitializer();
+ Initializer initializer = (Initializer) astStack[astPtr];
+ requestor.acceptInitializer(
+ initializer.declarationSourceStart,
+ initializer.declarationSourceEnd,
+ intArrayStack[intArrayPtr--],
+ AccStatic,
+ intStack[intPtr--],
+ initializer.block.sourceStart,
+ initializer.declarationSourceEnd);
+}
+protected void consumeStaticOnly() {
+ // StaticOnly ::= 'static'
+ checkAnnotation(); // might update declaration source start
+ pushOnIntStack(modifiersSourceStart);
+ pushOnIntStack(
+ declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
+ jumpOverMethodBody();
+ nestedMethod[nestedType]++;
+ resetModifiers();
+}
+protected void consumeToken(int type) {
+ super.consumeToken(type);
+
+ switch (type) {
+ case TokenNamevoid :
+ case TokenNameboolean :
+ case TokenNamebyte :
+ case TokenNamechar :
+ case TokenNamedouble :
+ case TokenNamefloat :
+ case TokenNameint :
+ case TokenNamelong :
+ case TokenNameshort :
+ // we need this position to know where the base type name ends.
+ pushOnIntStack(scanner.currentPosition - 1);
+ break;
+ }
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeTypeImportOnDemandDeclarationName() {
+ // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
+
+ /* persisting javadoc positions */
+ pushOnIntArrayStack(this.getJavaDocPositions());
+
+ super.consumeTypeImportOnDemandDeclarationName();
+ ImportReference importReference = (ImportReference) astStack[astPtr];
+ requestor.acceptImport(
+ importReference.declarationSourceStart,
+ importReference.declarationSourceEnd,
+ intArrayStack[intArrayPtr--],
+ CharOperation.concatWith(importReference.getImportName(), '.'),
+ importReference.sourceStart(),
+ true);
+}
+public CompilationUnitDeclaration endParse(int act) {
+ if (scanner.recordLineSeparator) {
+ requestor.acceptLineSeparatorPositions(scanner.lineEnds());
+ }
+ return super.endParse(act);
+}
+/*
+ * Flush annotations defined prior to a given positions.
+ *
+ * Note: annotations are stacked in syntactical order
+ *
+ * Either answer given <position>, or the end position of a comment line
+ * immediately following the <position> (same line)
+ *
+ * e.g.
+ * void foo(){
+ * } // end of method foo
+ */
+
+public int flushAnnotationsDefinedPriorTo(int position) {
+
+ return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
+}
+protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
+This variable is a type reference and dim will be its dimensions*/
+
+ int length;
+ TypeReference ref;
+ if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+ // single variable reference
+ if (dim == 0) {
+ ref =
+ new SingleTypeReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ } else {
+ ref =
+ new ArrayTypeReference(
+ identifierStack[identifierPtr],
+ dim,
+ identifierPositionStack[identifierPtr--]);
+ }
+ } else {
+ if (length < 0) { //flag for precompiled type reference on base types
+ ref = TypeReference.baseTypeReference(-length, dim);
+ ref.sourceEnd = intStack[intPtr--];
+ ref.sourceStart = intStack[intPtr--];
+ } else { //Qualified variable reference
+ char[][] tokens = new char[length][];
+ identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(
+ identifierPositionStack,
+ identifierPtr + 1,
+ positions,
+ 0,
+ length);
+ if (dim == 0)
+ ref = new QualifiedTypeReference(tokens, positions);
+ else
+ ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
+ }
+ };
+ return ref;
+}
+public void initialize() {
+ //positionning the parser for a new compilation unit
+ //avoiding stack reallocation and all that....
+ super.initialize();
+ intArrayPtr = -1;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+private boolean isLocalDeclaration() {
+ int nestedDepth = nestedType;
+ while (nestedDepth >= 0) {
+ if (nestedMethod[nestedDepth] != 0) {
+ return true;
+ }
+ nestedDepth--;
+ }
+ return false;
+}
+/*
+ * Investigate one entire unit.
+ */
+public void parseCompilationUnit(ICompilationUnit unit) {
+ char[] regionSource = unit.getContents();
+ try {
+ initialize();
+ goForCompilationUnit();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(unit, 0, 0),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSourceBuffer(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+}
+/*
+ * Investigate one constructor declaration.
+ */
+public void parseConstructor(char[] regionSource) {
+ try {
+ initialize();
+ goForClassBodyDeclarations();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSourceBuffer(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+}
+/*
+ * Investigate one field declaration statement (might have multiple declarations in it).
+ */
+public void parseField(char[] regionSource) {
+ try {
+ initialize();
+ goForFieldDeclaration();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSourceBuffer(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/*
+ * Investigate one import statement declaration.
+ */
+public void parseImport(char[] regionSource) {
+ try {
+ initialize();
+ goForImportDeclaration();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSourceBuffer(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/*
+ * Investigate one initializer declaration.
+ * regionSource need to content exactly an initializer declaration.
+ * e.g: static { i = 4; }
+ * { name = "test"; }
+ */
+public void parseInitializer(char[] regionSource) {
+ try {
+ initialize();
+ goForInitializer();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSourceBuffer(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/*
+ * Investigate one method declaration.
+ */
+public void parseMethod(char[] regionSource) {
+ try {
+ initialize();
+ goForGenericMethodDeclaration();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSourceBuffer(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/*
+ * Investigate one package statement declaration.
+ */
+public void parsePackage(char[] regionSource) {
+ try {
+ initialize();
+ goForPackageDeclaration();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSourceBuffer(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/*
+ * Investigate one type declaration, its fields, methods and member types.
+ */
+public void parseType(char[] regionSource) {
+ try {
+ initialize();
+ goForTypeDeclaration();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSourceBuffer(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/**
+ * Returns this parser's problem reporter initialized with its reference context.
+ * Also it is assumed that a problem is going to be reported, so initializes
+ * the compilation result's line positions.
+ */
+public ProblemReporter problemReporter() {
+ problemReporter.referenceContext = referenceContext;
+ return problemReporter;
+}
+protected void pushOnIntArrayStack(int[] positions) {
+
+ try {
+ intArrayStack[++intArrayPtr] = positions;
+ } catch (IndexOutOfBoundsException e) {
+ //intPtr is correct
+ int oldStackLength = intArrayStack.length;
+ int oldStack[][] = intArrayStack;
+ intArrayStack = new int[oldStackLength + StackIncrement][];
+ System.arraycopy(oldStack, 0, intArrayStack, 0, oldStackLength);
+ intArrayStack[intArrayPtr] = positions;
+ }
+}
+protected void resetModifiers() {
+ super.resetModifiers();
+ declarationSourceStart = -1;
+}
+/*
+ * Syntax error was detected. Will attempt to perform some recovery action in order
+ * to resume to the regular parse loop.
+ */
+protected boolean resumeOnSyntaxError() {
+ return false;
+}
+/*
+ * Answer a char array representation of the type name formatted like:
+ * - type name + dimensions
+ * Example:
+ * "A[][]".toCharArray()
+ * "java.lang.String".toCharArray()
+ */
+private char[] returnTypeName(TypeReference type) {
+ int dimension = type.dimensions();
+ if (dimension != 0) {
+ char[] dimensionsArray = new char[dimension * 2];
+ for (int i = 0; i < dimension; i++) {
+ dimensionsArray[i*2] = '[';
+ dimensionsArray[(i*2) + 1] = ']';
+ }
+ return CharOperation.concat(
+ CharOperation.concatWith(type.getTypeName(), '.'),
+ dimensionsArray);
+ }
+ return CharOperation.concatWith(type.getTypeName(), '.');
+}
+public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("intArrayPtr = "/*nonNLS*/ + intArrayPtr + "\n"/*nonNLS*/);
+ buffer.append(super.toString());
+ return buffer.toString();
+}
+/**
+ * INTERNAL USE ONLY
+ */
+protected TypeReference typeReference(
+ int dim,
+ int localIdentifierPtr,
+ int localIdentifierLengthPtr) {
+ /* build a Reference on a variable that may be qualified or not
+ * This variable is a type reference and dim will be its dimensions.
+ * We don't have any side effect on the stacks' pointers.
+ */
+
+ int length;
+ TypeReference ref;
+ if ((length = identifierLengthStack[localIdentifierLengthPtr]) == 1) {
+ // single variable reference
+ if (dim == 0) {
+ ref =
+ new SingleTypeReference(
+ identifierStack[localIdentifierPtr],
+ identifierPositionStack[localIdentifierPtr--]);
+ } else {
+ ref =
+ new ArrayTypeReference(
+ identifierStack[localIdentifierPtr],
+ dim,
+ identifierPositionStack[localIdentifierPtr--]);
+ }
+ } else {
+ if (length < 0) { //flag for precompiled type reference on base types
+ ref = TypeReference.baseTypeReference(-length, dim);
+ ref.sourceEnd = intStack[localIntPtr--];
+ ref.sourceStart = intStack[localIntPtr--];
+ } else { //Qualified variable reference
+ char[][] tokens = new char[length][];
+ localIdentifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(identifierStack, localIdentifierPtr + 1, tokens, 0, length);
+ System.arraycopy(
+ identifierPositionStack,
+ localIdentifierPtr + 1,
+ positions,
+ 0,
+ length);
+ if (dim == 0)
+ ref = new QualifiedTypeReference(tokens, positions);
+ else
+ ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
+ }
+ };
+ return ref;
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ICompilerRequestor.java b/compiler/org/eclipse/jdt/internal/compiler/ICompilerRequestor.java
index 5790ba3..d1b9988 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ICompilerRequestor.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ICompilerRequestor.java
@@ -1,16 +1,15 @@
-package org.eclipse.jdt.internal.compiler;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.Compiler;
-
-/**
- * A callback interface for receiving compilation results.
- */
-public interface ICompilerRequestor {
- /**
- * Accept a compilation result.
- */
- public void acceptResult(CompilationResult result);
-}
+package org.eclipse.jdt.internal.compiler;
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+/**
+ * A callback interface for receiving compilation results.
+ */
+public interface ICompilerRequestor {
+ /**
+ * Accept a compilation result.
+ */
+ public void acceptResult(CompilationResult result);
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/IErrorHandlingPolicy.java b/compiler/org/eclipse/jdt/internal/compiler/IErrorHandlingPolicy.java
index 96ed4b9..9e13486 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/IErrorHandlingPolicy.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/IErrorHandlingPolicy.java
@@ -1,23 +1,22 @@
-package org.eclipse.jdt.internal.compiler;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.problem.ProblemHandler;
-
-/*
- * Handler policy is responsible to answer the 2 following
- * questions:
- * 1. should the handler stop on first problem which appears
- * to be a real error (i.e. not a warning),
- * 2. should it proceed once it has gathered all problems
- *
- * The intent is that one can supply its own policy to implement
- * some interactive error handling strategy where some UI would
- * display problems and ask user if he wants to proceed or not.
- */
-
-public interface IErrorHandlingPolicy {
- boolean proceedOnErrors();
- boolean stopOnFirstError();
-}
+package org.eclipse.jdt.internal.compiler;
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+/*
+ * Handler policy is responsible to answer the 2 following
+ * questions:
+ * 1. should the handler stop on first problem which appears
+ * to be a real error (i.e. not a warning),
+ * 2. should it proceed once it has gathered all problems
+ *
+ * The intent is that one can supply its own policy to implement
+ * some interactive error handling strategy where some UI would
+ * display problems and ask user if he wants to proceed or not.
+ */
+
+public interface IErrorHandlingPolicy {
+ boolean proceedOnErrors();
+ boolean stopOnFirstError();
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/IProblem.java b/compiler/org/eclipse/jdt/internal/compiler/IProblem.java
index b67f0fe..8871384 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/IProblem.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/IProblem.java
@@ -1,79 +1,78 @@
-package org.eclipse.jdt.internal.compiler;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.problem.ProblemHandler;
-
-/*
- * Handler policy is responsible to answer the 2 following
- * questions:
- * 1. should the handler stop on first problem which appears
- * to be a real error (i.e. not a warning),
- * 2. should it proceed once it has gathered all problems
- *
- * The intent is that one can supply its own policy to implement
- * some interactive error handling strategy where some UI would
- * display problems and ask user if he wants to proceed or not.
- */
-
-public interface IProblem {
- final int Error = 1; // when bit is set: problem is error, if not it is a warning
-/**
- * Answer back the original arguments recorded into the problem.
- */
-String[] getArguments();
-/**
- *
- * @return int
- */
-int getID();
-/**
- * Answer a localized, human-readable message string which describes the problem.
- */
-String getMessage();
-/**
- * Answer the file name in which the problem was found.
- */
-char[] getOriginatingFileName();
-/**
- * Answer the severity of the problem.
- */
-int getSeverity();
-/**
- * Answer the end position of the problem (inclusive), or -1 if unknown.
- */
-int getSourceEnd();
-/**
- * Answer the line number in source where the problem begins.
- */
-int getSourceLineNumber();
-/**
- * Answer the start position of the problem (inclusive), or -1 if unknown.
- */
-int getSourceStart();
-/*
- * Helper method: checks the severity to see if the Error bit is set.
- */
-boolean isError();
-/*
- * Helper method: checks the severity to see if the Error bit is not set.
- */
-boolean isWarning();
-/**
- * Set the end position of the problem (inclusive), or -1 if unknown.
- *
- * Used for shifting problem positions.
- */
-void setSourceEnd(int sourceEnd);
-/**
- * Set the line number in source where the problem begins.
- */
-void setSourceLineNumber(int lineNumber);
-/**
- * Set the start position of the problem (inclusive), or -1 if unknown.
- *
- * Used for shifting problem positions.
- */
-void setSourceStart(int sourceStart);
-}
+package org.eclipse.jdt.internal.compiler;
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+/*
+ * Handler policy is responsible to answer the 2 following
+ * questions:
+ * 1. should the handler stop on first problem which appears
+ * to be a real error (i.e. not a warning),
+ * 2. should it proceed once it has gathered all problems
+ *
+ * The intent is that one can supply its own policy to implement
+ * some interactive error handling strategy where some UI would
+ * display problems and ask user if he wants to proceed or not.
+ */
+
+public interface IProblem {
+ final int Error = 1; // when bit is set: problem is error, if not it is a warning
+/**
+ * Answer back the original arguments recorded into the problem.
+ */
+String[] getArguments();
+/**
+ *
+ * @return int
+ */
+int getID();
+/**
+ * Answer a localized, human-readable message string which describes the problem.
+ */
+String getMessage();
+/**
+ * Answer the file name in which the problem was found.
+ */
+char[] getOriginatingFileName();
+/**
+ * Answer the severity of the problem.
+ */
+int getSeverity();
+/**
+ * Answer the end position of the problem (inclusive), or -1 if unknown.
+ */
+int getSourceEnd();
+/**
+ * Answer the line number in source where the problem begins.
+ */
+int getSourceLineNumber();
+/**
+ * Answer the start position of the problem (inclusive), or -1 if unknown.
+ */
+int getSourceStart();
+/*
+ * Helper method: checks the severity to see if the Error bit is set.
+ */
+boolean isError();
+/*
+ * Helper method: checks the severity to see if the Error bit is not set.
+ */
+boolean isWarning();
+/**
+ * Set the end position of the problem (inclusive), or -1 if unknown.
+ *
+ * Used for shifting problem positions.
+ */
+void setSourceEnd(int sourceEnd);
+/**
+ * Set the line number in source where the problem begins.
+ */
+void setSourceLineNumber(int lineNumber);
+/**
+ * Set the start position of the problem (inclusive), or -1 if unknown.
+ *
+ * Used for shifting problem positions.
+ */
+void setSourceStart(int sourceStart);
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/SourceElementParser.java b/compiler/org/eclipse/jdt/internal/compiler/SourceElementParser.java
index 4529056..ca700ef 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/SourceElementParser.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/SourceElementParser.java
@@ -1,936 +1,884 @@
-package org.eclipse.jdt.internal.compiler;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-/**
- * A source element parser extracts structural and reference information
- * from a piece of source.
- *
- * also see @ISourceElementRequestor
- *
- * The structural investigation includes:
- * - the package statement
- * - import statements
- * - top-level types: package member, member types (member types of member types...)
- * - fields
- * - methods
- *
- * If reference information is requested, then all source constructs are
- * investigated and type, field & method references are provided as well.
- *
- * Any (parsing) problem encountered is also provided.
- */
-import java.lang.reflect.Constructor;
-
-import org.eclipse.jdt.internal.compiler.Compiler;
-import org.eclipse.jdt.internal.compiler.env.*;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.parser.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.compiler.util.*;
-
-public class SourceElementParser extends Parser {
- ISourceElementRequestor requestor;
- private int fieldCount;
- private int localIntPtr;
- private int lastFieldEndPosition;
- private ISourceType sourceType;
- private boolean reportReferenceInfo;
- private char[][] typeNames;
- private char[][] superTypeNames;
- private int nestedTypeIndex;
- private static final char[] JAVA_LANG_OBJECT = "java.lang.Object"/*nonNLS*/.toCharArray();
-public SourceElementParser(
- final ISourceElementRequestor requestor,
- IProblemFactory problemFactory) {
- // we want to notify all syntax error with the acceptProblem API
- // To do so, we define the record method of the ProblemReporter
- super(new ProblemReporter(
- DefaultErrorHandlingPolicies.exitAfterAllProblems(),
- new CompilerOptions(),
- problemFactory) {
- public void record(IProblem problem, CompilationResult unitResult) {
- unitResult.record(problem);
- requestor.acceptProblem(problem);
- }
- }, false);
- this.requestor = requestor;
- typeNames = new char[4][];
- superTypeNames = new char[4][];
- nestedTypeIndex = 0;
-}
-protected void classInstanceCreation(boolean alwaysQualified) {
-
- boolean previousFlag = reportReferenceInfo;
- reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
- super.classInstanceCreation(alwaysQualified);
- reportReferenceInfo = previousFlag;
- if (reportReferenceInfo){
- AllocationExpression alloc = (AllocationExpression)expressionStack[expressionPtr];
- TypeReference typeRef = alloc.type;
- requestor.acceptConstructorReference(
- typeRef instanceof SingleTypeReference
- ? ((SingleTypeReference) typeRef).token
- : CharOperation.concatWith(alloc.type.getTypeName(), '.'),
- alloc.arguments == null ? 0 : alloc.arguments.length,
- alloc.sourceStart);
- }
-}
-protected void consumeConstructorHeaderName() {
- // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
-
- /* recovering - might be an empty message send */
- if (currentElement != null){
- if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
- lastCheckPoint = scanner.startPosition; // force to restart at this exact position
- restartRecovery = true;
- return;
- }
- }
- SourceConstructorDeclaration cd = new SourceConstructorDeclaration();
-
- //name -- this is not really revelant but we do .....
- cd.selector = identifierStack[identifierPtr];
- long selectorSourcePositions = identifierPositionStack[identifierPtr--];
- identifierLengthPtr--;
-
- //modifiers
- cd.declarationSourceStart = intStack[intPtr--];
- cd.modifiers = intStack[intPtr--];
-
- //highlight starts at the selector starts
- cd.sourceStart = (int) (selectorSourcePositions >>> 32);
- cd.selectorSourceEnd = (int) selectorSourcePositions;
- pushOnAstStack(cd);
-
- cd.sourceEnd = lParenPos;
- cd.bodyStart = lParenPos+1;
- listLength = 0; // initialize listLength before reading parameters/throws
-
- // recovery
- if (currentElement != null){
- lastCheckPoint = cd.bodyStart;
- if ((currentElement instanceof RecoveredType && lastIgnoredToken != TokenNameDOT)
- || cd.modifiers != 0){
- currentElement = currentElement.add(cd, 0);
- lastIgnoredToken = -1;
- }
- }
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeExitVariableWithInitialization() {
- // ExitVariableWithInitialization ::= $empty
- // the scanner is located after the comma or the semi-colon.
- // we want to include the comma or the semi-colon
- super.consumeExitVariableWithInitialization();
- if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
- return;
- ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
-}
-protected void consumeExitVariableWithoutInitialization() {
- // ExitVariableWithoutInitialization ::= $empty
- // do nothing by default
- if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
- return;
- ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeFieldAccess(boolean isSuperAccess) {
- // FieldAccess ::= Primary '.' 'Identifier'
- // FieldAccess ::= 'super' '.' 'Identifier'
- super.consumeFieldAccess(isSuperAccess);
- FieldReference fr = (FieldReference) expressionStack[expressionPtr];
- if (reportReferenceInfo) {
- requestor.acceptFieldReference(fr.token, fr.sourceStart);
- }
-}
-protected void consumeMethodHeaderName() {
- // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
- int length;
- SourceMethodDeclaration md = new SourceMethodDeclaration();
-
- //name
- md.selector = identifierStack[identifierPtr];
- long selectorSourcePositions = identifierPositionStack[identifierPtr--];
- identifierLengthPtr--;
- //type
- md.returnType = getTypeReference(intStack[intPtr--]);
- //modifiers
- md.declarationSourceStart = intStack[intPtr--];
- md.modifiers = intStack[intPtr--];
-
- //highlight starts at selector start
- md.sourceStart = (int) (selectorSourcePositions >>> 32);
- md.selectorSourceEnd = (int) selectorSourcePositions;
- pushOnAstStack(md);
- md.sourceEnd = lParenPos;
- md.bodyStart = lParenPos+1;
- listLength = 0; // initialize listLength before reading parameters/throws
-
- // recovery
- if (currentElement != null){
- if (currentElement instanceof RecoveredType
- //|| md.modifiers != 0
- || (scanner.searchLineNumber(md.returnType.sourceStart)
- == scanner.searchLineNumber(md.sourceStart))){
- lastCheckPoint = md.bodyStart;
- currentElement = currentElement.add(md, 0);
- lastIgnoredToken = -1;
- } else {
- lastCheckPoint = md.sourceStart;
- restartRecovery = true;
- }
- }
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeMethodInvocationName() {
- // MethodInvocation ::= Name '(' ArgumentListopt ')'
-
- // when the name is only an identifier...we have a message send to "this" (implicit)
- super.consumeMethodInvocationName();
- MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
- Expression[] args = messageSend.arguments;
- if (reportReferenceInfo) {
- requestor.acceptMethodReference(
- messageSend.selector,
- args == null ? 0 : args.length,
- (int)(messageSend.nameSourcePosition >>> 32));
- }
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeMethodInvocationPrimary() {
- super.consumeMethodInvocationPrimary();
- MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
- Expression[] args = messageSend.arguments;
- if (reportReferenceInfo) {
- requestor.acceptMethodReference(
- messageSend.selector,
- args == null ? 0 : args.length,
- (int)(messageSend.nameSourcePosition >>> 32));
- }
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeMethodInvocationSuper() {
- // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
- super.consumeMethodInvocationSuper();
- MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
- Expression[] args = messageSend.arguments;
- if (reportReferenceInfo) {
- requestor.acceptMethodReference(
- messageSend.selector,
- args == null ? 0 : args.length,
- (int)(messageSend.nameSourcePosition >>> 32));
- }
-}
-protected void consumeSingleTypeImportDeclarationName() {
- // SingleTypeImportDeclarationName ::= 'import' Name
- /* push an ImportRef build from the last name
- stored in the identifier stack. */
-
- super.consumeSingleTypeImportDeclarationName();
- ImportReference impt = (ImportReference)astStack[astPtr];
- if (reportReferenceInfo) {
- requestor.acceptTypeReference(impt.tokens, impt.sourceStart(), impt.sourceEnd());
- }
-}
-protected void consumeTypeImportOnDemandDeclarationName() {
- // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
- /* push an ImportRef build from the last name
- stored in the identifier stack. */
-
- super.consumeTypeImportOnDemandDeclarationName();
- ImportReference impt = (ImportReference)astStack[astPtr];
- if (reportReferenceInfo) {
- requestor.acceptUnknownReference(impt.tokens, impt.sourceStart(), impt.sourceEnd());
- }
-}
-protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
- return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
-}
-protected CompilationUnitDeclaration endParse(int act) {
-
- if (sourceType != null) {
- if (sourceType.isInterface()) {
- consumeInterfaceDeclaration();
- } else {
- consumeClassDeclaration();
- }
- }
- CompilationUnitDeclaration result = super.endParse(act);
- notifySourceElementRequestor();
- return result;
-}
-/*
- * Flush annotations defined prior to a given positions.
- *
- * Note: annotations are stacked in syntactical order
- *
- * Either answer given <position>, or the end position of a comment line
- * immediately following the <position> (same line)
- *
- * e.g.
- * void foo(){
- * } // end of method foo
- */
-
-public int flushAnnotationsDefinedPriorTo(int position) {
-
- return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
-}
-public TypeReference getTypeReference(int dim) {
- /* build a Reference on a variable that may be qualified or not
- * This variable is a type reference and dim will be its dimensions
- */
- int length;
- if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
- // single variable reference
- if (dim == 0) {
- SingleTypeReference ref =
- new SingleTypeReference(
- identifierStack[identifierPtr],
- identifierPositionStack[identifierPtr--]);
- if (reportReferenceInfo) {
- requestor.acceptTypeReference(ref.token, ref.sourceStart);
- }
- return ref;
- } else {
- ArrayTypeReference ref =
- new ArrayTypeReference(
- identifierStack[identifierPtr],
- dim,
- identifierPositionStack[identifierPtr--]);
- if (reportReferenceInfo) {
- requestor.acceptTypeReference(ref.token, ref.sourceStart);
- }
- return ref;
- }
- } else {
- if (length < 0) { //flag for precompiled type reference on base types
- TypeReference ref = TypeReference.baseTypeReference(-length, dim);
- ref.sourceStart = intStack[intPtr--];
- return ref;
- } else { //Qualified variable reference
- char[][] tokens = new char[length][];
- identifierPtr -= length;
- long[] positions = new long[length];
- System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
- System.arraycopy(
- identifierPositionStack,
- identifierPtr + 1,
- positions,
- 0,
- length);
- if (dim == 0) {
- QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
- if (reportReferenceInfo) {
- requestor.acceptTypeReference(ref.tokens, ref.sourceStart(), ref.sourceEnd());
- }
- return ref;
- } else {
- ArrayQualifiedTypeReference ref =
- new ArrayQualifiedTypeReference(tokens, dim, positions);
- if (reportReferenceInfo) {
- requestor.acceptTypeReference(ref.tokens, ref.sourceStart(), ref.sourceEnd());
- }
- return ref;
- }
- }
- }
-}
-public NameReference getUnspecifiedReference() {
- /* build a (unspecified) NameReference which may be qualified*/
-
- int length;
- if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
- // single variable reference
- SingleNameReference ref =
- new SingleNameReference(
- identifierStack[identifierPtr],
- identifierPositionStack[identifierPtr--]);
- if (reportReferenceInfo) {
- requestor.acceptUnknownReference(ref.token, ref.sourceStart());
- }
- return ref;
- } else {
- //Qualified variable reference
- char[][] tokens = new char[length][];
- identifierPtr -= length;
- System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
- QualifiedNameReference ref =
- new QualifiedNameReference(
- tokens,
- (int) (identifierPositionStack[identifierPtr + 1] >> 32),
- // sourceStart
- (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
- if (reportReferenceInfo) {
- requestor.acceptUnknownReference(
- ref.tokens,
- ref.sourceStart(),
- ref.sourceEnd());
- }
- return ref;
- }
-}
-public NameReference getUnspecifiedReferenceOptimized() {
- /* build a (unspecified) NameReference which may be qualified
- The optimization occurs for qualified reference while we are
- certain in this case the last item of the qualified name is
- a field access. This optimization is IMPORTANT while it results
- that when a NameReference is build, the type checker should always
- look for that it is not a type reference */
-
- int length;
- if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
- // single variable reference
- SingleNameReference ref =
- new SingleNameReference(
- identifierStack[identifierPtr],
- identifierPositionStack[identifierPtr--]);
- ref.bits &= ~NameReference.RestrictiveFlagMASK;
- ref.bits |= LOCAL | FIELD;
- if (reportReferenceInfo) {
- requestor.acceptUnknownReference(ref.token, ref.sourceStart());
- }
- return ref;
- }
-
- //Qualified-variable-reference
- //In fact it is variable-reference DOT field-ref , but it would result in a type
- //conflict tha can be only reduce by making a superclass (or inetrface ) between
- //nameReference and FiledReference or putting FieldReference under NameReference
- //or else..........This optimisation is not really relevant so just leave as it is
-
- char[][] tokens = new char[length][];
- identifierPtr -= length;
- System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
- QualifiedNameReference ref =
- new QualifiedNameReference(
- tokens,
- (int) (identifierPositionStack[identifierPtr + 1] >> 32),
- // sourceStart
- (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
- ref.bits &= ~NameReference.RestrictiveFlagMASK;
- ref.bits |= LOCAL | FIELD;
- if (reportReferenceInfo) {
- requestor.acceptUnknownReference(
- ref.tokens,
- ref.sourceStart(),
- ref.sourceEnd());
- }
- return ref;
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-private boolean isLocalDeclaration() {
- int nestedDepth = nestedType;
- while (nestedDepth >= 0) {
- if (nestedMethod[nestedDepth] != 0) {
- return true;
- }
- nestedDepth--;
- }
- return false;
-}
-/*
- * Update the bodyStart of the corresponding parse node
- */
-public void notifySourceElementRequestor() {
-
- if (sourceType == null){
- if (scanner.initialPosition == 0) {
- requestor.enterCompilationUnit();
- }
- // first we notify the package declaration
- ImportReference currentPackage = compilationUnit.currentPackage;
- if (currentPackage != null) {
- notifySourceElementRequestor(currentPackage, true);
- }
- // then the imports
- ImportReference[] imports = compilationUnit.imports;
- if (imports != null) {
- for (int i = 0, max = imports.length; i < max; i++) {
- notifySourceElementRequestor(imports[i], false);
- }
- }
- }
- // then the types contained by this compilation unit
- TypeDeclaration[] types = compilationUnit.types;
- if (types != null) {
- for (int i = 0, max = types.length; i < max; i++) {
- notifySourceElementRequestor(types[i], sourceType == null);
- }
- }
- if (sourceType == null){
- if (scanner.eofPosition >= compilationUnit.sourceEnd) {
- requestor.exitCompilationUnit(compilationUnit.sourceEnd);
- }
- }
-}
-/*
- * Update the bodyStart of the corresponding parse node
- */
-public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
- if (methodDeclaration.isClinit())
- return;
-
- if (methodDeclaration.isDefaultConstructor()) {
- if (reportReferenceInfo) {
- ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
- ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
- if (constructorCall != null) {
- switch(constructorCall.accessMode) {
- case ExplicitConstructorCall.This :
- requestor.acceptConstructorReference(
- typeNames[nestedTypeIndex-1],
- constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
- constructorCall.sourceStart);
- break;
- case ExplicitConstructorCall.Super :
- case ExplicitConstructorCall.ImplicitSuper :
- requestor.acceptConstructorReference(
- superTypeNames[nestedTypeIndex-1],
- constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
- constructorCall.sourceStart);
- break;
- }
- }
- }
- return;
- }
- char[][] argumentTypes = null;
- char[][] argumentNames = null;
- Argument[] arguments = methodDeclaration.arguments;
- if (arguments != null) {
- int argumentLength = arguments.length;
- argumentTypes = new char[argumentLength][];
- argumentNames = new char[argumentLength][];
- for (int i = 0; i < argumentLength; i++) {
- argumentTypes[i] = returnTypeName(arguments[i].type);
- argumentNames[i] = arguments[i].name;
- }
- }
- char[][] thrownExceptionTypes = null;
- TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
- if (thrownExceptions != null) {
- int thrownExceptionLength = thrownExceptions.length;
- thrownExceptionTypes = new char[thrownExceptionLength][];
- for (int i = 0; i < thrownExceptionLength; i++) {
- thrownExceptionTypes[i] =
- CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.');
- }
- }
- // by default no selector end position
- int selectorSourceEnd = -1;
- if (methodDeclaration.isConstructor()) {
- if (methodDeclaration instanceof SourceConstructorDeclaration) {
- selectorSourceEnd =
- ((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd;
- }
- if (scanner.initialPosition <= methodDeclaration.declarationSourceStart) {
- requestor.enterConstructor(
- methodDeclaration.declarationSourceStart,
- methodDeclaration.modifiers,
- methodDeclaration.selector,
- methodDeclaration.sourceStart,
- selectorSourceEnd,
- argumentTypes,
- argumentNames,
- thrownExceptionTypes);
- if (reportReferenceInfo) {
- ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
- ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
- if (constructorCall != null) {
- switch(constructorCall.accessMode) {
- case ExplicitConstructorCall.This :
- requestor.acceptConstructorReference(
- typeNames[nestedTypeIndex-1],
- constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
- constructorCall.sourceStart);
- break;
- case ExplicitConstructorCall.Super :
- case ExplicitConstructorCall.ImplicitSuper :
- requestor.acceptConstructorReference(
- superTypeNames[nestedTypeIndex-1],
- constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
- constructorCall.sourceStart);
- break;
- }
- }
- }
- }
- if (scanner.eofPosition >= methodDeclaration.declarationSourceEnd) {
- requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
- }
- return;
- }
- if (methodDeclaration instanceof SourceMethodDeclaration) {
- selectorSourceEnd =
- ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd;
- }
- requestor.enterMethod(
- methodDeclaration.declarationSourceStart,
- methodDeclaration.modifiers,
- returnTypeName(((MethodDeclaration) methodDeclaration).returnType),
- methodDeclaration.selector,
- methodDeclaration.sourceStart,
- selectorSourceEnd,
- argumentTypes,
- argumentNames,
- thrownExceptionTypes);
- requestor.exitMethod(methodDeclaration.declarationSourceEnd);
-}
-/*
-* Update the bodyStart of the corresponding parse node
-*/
-public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
- if (fieldDeclaration.isField()) {
- int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
- if (fieldDeclaration instanceof SourceFieldDeclaration) {
- fieldEndPosition = ((SourceFieldDeclaration) fieldDeclaration).fieldEndPosition;
- if (fieldEndPosition == 0) {
- // use the declaration source end by default
- fieldEndPosition = fieldDeclaration.declarationSourceEnd;
- }
- }
- requestor.enterField(
- fieldDeclaration.declarationSourceStart,
- fieldDeclaration.modifiers,
- returnTypeName(fieldDeclaration.type),
- fieldDeclaration.name,
- fieldDeclaration.sourceStart,
- fieldDeclaration.sourceEnd);
- requestor.exitField(fieldEndPosition);
-
- } else {
- requestor.acceptInitializer(
- fieldDeclaration.modifiers,
- fieldDeclaration.declarationSourceStart,
- fieldDeclaration.declarationSourceEnd);
- }
-}
-public void notifySourceElementRequestor(
- ImportReference importReference,
- boolean isPackage) {
- if (isPackage) {
- requestor.acceptPackage(
- importReference.declarationSourceStart,
- importReference.declarationSourceEnd,
- CharOperation.concatWith(importReference.getImportName(), '.'));
- } else {
- requestor.acceptImport(
- importReference.declarationSourceStart,
- importReference.declarationSourceEnd,
- CharOperation.concatWith(importReference.getImportName(), '.'),
- importReference.onDemand);
- }
-}
-public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
- FieldDeclaration[] fields = typeDeclaration.fields;
- AbstractMethodDeclaration[] methods = typeDeclaration.methods;
- MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
- int fieldCount = fields == null ? 0 : fields.length;
- int methodCount = methods == null ? 0 : methods.length;
- int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
- int fieldIndex = 0;
- int methodIndex = 0;
- int memberTypeIndex = 0;
- boolean isInterface = typeDeclaration.isInterface();
-
- if (notifyTypePresence){
- char[][] interfaceNames = null;
- int superInterfacesLength = 0;
- TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
- if (superInterfaces != null) {
- superInterfacesLength = superInterfaces.length;
- interfaceNames = new char[superInterfacesLength][];
- }
- if (superInterfaces != null) {
- for (int i = 0; i < superInterfacesLength; i++) {
- interfaceNames[i] =
- CharOperation.concatWith(superInterfaces[i].getTypeName(), '.');
- }
- }
- if (isInterface) {
- requestor.enterInterface(
- typeDeclaration.declarationSourceStart,
- typeDeclaration.modifiers,
- typeDeclaration.name,
- typeDeclaration.sourceStart,
- typeDeclaration.sourceEnd,
- interfaceNames);
- if (nestedTypeIndex == typeNames.length) {
- // need a resize
- System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
- System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
- }
- typeNames[nestedTypeIndex] = typeDeclaration.name;
- superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
- } else {
- TypeReference superclass = typeDeclaration.superclass;
- if (superclass == null) {
- requestor.enterClass(
- typeDeclaration.declarationSourceStart,
- typeDeclaration.modifiers,
- typeDeclaration.name,
- typeDeclaration.sourceStart,
- typeDeclaration.sourceEnd,
- null,
- interfaceNames);
- } else {
- requestor.enterClass(
- typeDeclaration.declarationSourceStart,
- typeDeclaration.modifiers,
- typeDeclaration.name,
- typeDeclaration.sourceStart,
- typeDeclaration.sourceEnd,
- CharOperation.concatWith(superclass.getTypeName(), '.'),
- interfaceNames);
- }
- if (nestedTypeIndex == typeNames.length) {
- // need a resize
- System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
- System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
- }
- typeNames[nestedTypeIndex] = typeDeclaration.name;
- superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass.getTypeName(), '.');
- }
- }
- while ((fieldIndex < fieldCount)
- || (memberTypeIndex < memberTypeCount)
- || (methodIndex < methodCount)) {
- FieldDeclaration nextFieldDeclaration = null;
- AbstractMethodDeclaration nextMethodDeclaration = null;
- TypeDeclaration nextMemberDeclaration = null;
-
- int position = Integer.MAX_VALUE;
- int nextDeclarationType = -1;
- if (fieldIndex < fieldCount) {
- nextFieldDeclaration = fields[fieldIndex];
- if (nextFieldDeclaration.declarationSourceStart < position) {
- position = nextFieldDeclaration.declarationSourceStart;
- nextDeclarationType = 0; // FIELD
- }
- }
- if (methodIndex < methodCount) {
- nextMethodDeclaration = methods[methodIndex];
- if (nextMethodDeclaration.declarationSourceStart < position) {
- position = nextMethodDeclaration.declarationSourceStart;
- nextDeclarationType = 1; // METHOD
- }
- }
- if (memberTypeIndex < memberTypeCount) {
- nextMemberDeclaration = memberTypes[memberTypeIndex];
- if (nextMemberDeclaration.declarationSourceStart < position) {
- position = nextMemberDeclaration.declarationSourceStart;
- nextDeclarationType = 2; // MEMBER
- }
- }
- switch (nextDeclarationType) {
- case 0 :
- fieldIndex++;
- notifySourceElementRequestor(nextFieldDeclaration);
- break;
- case 1 :
- methodIndex++;
- notifySourceElementRequestor(nextMethodDeclaration);
- break;
- case 2 :
- memberTypeIndex++;
- notifySourceElementRequestor(nextMemberDeclaration, true);
- }
- }
- if (notifyTypePresence){
- if (isInterface) {
- requestor.exitInterface(typeDeclaration.declarationSourceEnd);
- } else {
- requestor.exitClass(typeDeclaration.declarationSourceEnd);
- }
- nestedTypeIndex--;
- }
-}
-public void parseCompilationUnit(
- ICompilationUnit unit,
- int start,
- int end,
- boolean needReferenceInfo) {
-
- CompilationUnitDeclaration result;
- reportReferenceInfo = needReferenceInfo;
- boolean old = diet;
- try {
- diet = !needReferenceInfo;
- CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0);
- result = parse(unit, compilationUnitResult, start, end);
- } catch (AbortCompilation e) {
- } finally {
- if (scanner.recordLineSeparator) {
- requestor.acceptLineSeparatorPositions(scanner.lineEnds());
- }
- diet = old;
- }
-}
-public void parseCompilationUnit(
- ICompilationUnit unit,
- boolean needReferenceInfo) {
-
- CompilationUnitDeclaration result;
- boolean old = diet;
- try {
- diet = !needReferenceInfo;
- reportReferenceInfo = needReferenceInfo;
- CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0);
- result = parse(unit, compilationUnitResult);
- } catch (AbortCompilation e) {
- } finally {
- if (scanner.recordLineSeparator) {
- requestor.acceptLineSeparatorPositions(scanner.lineEnds());
- }
- diet = old;
- }
-}
-public void parseTypeMemberDeclarations(
- ISourceType sourceType,
- ICompilationUnit sourceUnit,
- int start,
- int end,
- boolean needReferenceInfo) {
-
- boolean old = diet;
- try {
- diet = !needReferenceInfo;
- reportReferenceInfo = needReferenceInfo;
- CompilationResult compilationUnitResult =
- new CompilationResult(sourceUnit, 0, 0);
-
- CompilationUnitDeclaration unit =
- SourceTypeConverter.buildCompilationUnit(
- sourceType,
- false,
- false,
- problemReporter(),
- compilationUnitResult);
- if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
- return;
-
- this.sourceType = sourceType;
-
- try {
- /* automaton initialization */
- initialize();
- goForClassBodyDeclarations();
- /* scanner initialization */
- scanner.setSourceBuffer(sourceUnit.getContents());
- int sourceLength = scanner.source.length;
- scanner.resetTo(start, end);
- /* unit creation */
- referenceContext = compilationUnit = unit;
-
- /* initialize the astStacl */
- // the compilationUnitDeclaration should contain exactly one type
- pushOnAstStack(unit.types[0]);
- /* run automaton */
- parse();
- } finally {
- unit = compilationUnit;
- compilationUnit = null; // reset parser
- }
- } catch (AbortCompilation e) {
- } finally {
- if (scanner.recordLineSeparator) {
- requestor.acceptLineSeparatorPositions(scanner.lineEnds());
- }
- diet = old;
- }
-}
-/*
- * Answer a char array representation of the type name formatted like:
- * - type name + dimensions
- * Example:
- * "A[][]".toCharArray()
- * "java.lang.String".toCharArray()
- */
-private char[] returnTypeName(TypeReference type) {
- if (type == null)
- return null;
- int dimension = type.dimensions();
- if (dimension != 0) {
- char[] dimensionsArray = new char[dimension * 2];
- for (int i = 0; i < dimension; i++) {
- dimensionsArray[i * 2] = '[';
- dimensionsArray[(i * 2) + 1] = ']';
- }
- return CharOperation.concat(
- CharOperation.concatWith(type.getTypeName(), '.'),
- dimensionsArray);
- }
- return CharOperation.concatWith(type.getTypeName(), '.');
-}
-private TypeReference typeReference(
- int dim,
- int localIdentifierPtr,
- int localIdentifierLengthPtr) {
- /* build a Reference on a variable that may be qualified or not
- * This variable is a type reference and dim will be its dimensions.
- * We don't have any side effect on the stacks' pointers.
- */
-
- int length;
- TypeReference ref;
- if ((length = identifierLengthStack[localIdentifierLengthPtr]) == 1) {
- // single variable reference
- if (dim == 0) {
- ref =
- new SingleTypeReference(
- identifierStack[localIdentifierPtr],
- identifierPositionStack[localIdentifierPtr--]);
- } else {
- ref =
- new ArrayTypeReference(
- identifierStack[localIdentifierPtr],
- dim,
- identifierPositionStack[localIdentifierPtr--]);
- }
- } else {
- if (length < 0) { //flag for precompiled type reference on base types
- ref = TypeReference.baseTypeReference(-length, dim);
- ref.sourceStart = intStack[localIntPtr--];
- } else { //Qualified variable reference
- char[][] tokens = new char[length][];
- localIdentifierPtr -= length;
- long[] positions = new long[length];
- System.arraycopy(identifierStack, localIdentifierPtr + 1, tokens, 0, length);
- System.arraycopy(
- identifierPositionStack,
- localIdentifierPtr + 1,
- positions,
- 0,
- length);
- if (dim == 0)
- ref = new QualifiedTypeReference(tokens, positions);
- else
- ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
- }
- };
- return ref;
-}
-}
+package org.eclipse.jdt.internal.compiler;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+/**
+ * A source element parser extracts structural and reference information
+ * from a piece of source.
+ *
+ * also see @ISourceElementRequestor
+ *
+ * The structural investigation includes:
+ * - the package statement
+ * - import statements
+ * - top-level types: package member, member types (member types of member types...)
+ * - fields
+ * - methods
+ *
+ * If reference information is requested, then all source constructs are
+ * investigated and type, field & method references are provided as well.
+ *
+ * Any (parsing) problem encountered is also provided.
+ */
+
+import org.eclipse.jdt.internal.compiler.env.*;
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.parser.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.compiler.util.*;
+
+public class SourceElementParser extends Parser {
+ ISourceElementRequestor requestor;
+ private int lastFieldEndPosition;
+ private ISourceType sourceType;
+ private boolean reportReferenceInfo;
+ private char[][] typeNames;
+ private char[][] superTypeNames;
+ private int nestedTypeIndex;
+ private static final char[] JAVA_LANG_OBJECT = "java.lang.Object"/*nonNLS*/.toCharArray();
+public SourceElementParser(
+ final ISourceElementRequestor requestor,
+ IProblemFactory problemFactory) {
+ // we want to notify all syntax error with the acceptProblem API
+ // To do so, we define the record method of the ProblemReporter
+ super(new ProblemReporter(
+ DefaultErrorHandlingPolicies.exitAfterAllProblems(),
+ new CompilerOptions(),
+ problemFactory) {
+ public void record(IProblem problem, CompilationResult unitResult) {
+ unitResult.record(problem);
+ requestor.acceptProblem(problem);
+ }
+ }, false);
+ this.requestor = requestor;
+ typeNames = new char[4][];
+ superTypeNames = new char[4][];
+ nestedTypeIndex = 0;
+}
+protected void classInstanceCreation(boolean alwaysQualified) {
+
+ boolean previousFlag = reportReferenceInfo;
+ reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
+ super.classInstanceCreation(alwaysQualified);
+ reportReferenceInfo = previousFlag;
+ if (reportReferenceInfo){
+ AllocationExpression alloc = (AllocationExpression)expressionStack[expressionPtr];
+ TypeReference typeRef = alloc.type;
+ requestor.acceptConstructorReference(
+ typeRef instanceof SingleTypeReference
+ ? ((SingleTypeReference) typeRef).token
+ : CharOperation.concatWith(alloc.type.getTypeName(), '.'),
+ alloc.arguments == null ? 0 : alloc.arguments.length,
+ alloc.sourceStart);
+ }
+}
+protected void consumeConstructorHeaderName() {
+ // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
+
+ /* recovering - might be an empty message send */
+ if (currentElement != null){
+ if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
+ lastCheckPoint = scanner.startPosition; // force to restart at this exact position
+ restartRecovery = true;
+ return;
+ }
+ }
+ SourceConstructorDeclaration cd = new SourceConstructorDeclaration();
+
+ //name -- this is not really revelant but we do .....
+ cd.selector = identifierStack[identifierPtr];
+ long selectorSourcePositions = identifierPositionStack[identifierPtr--];
+ identifierLengthPtr--;
+
+ //modifiers
+ cd.declarationSourceStart = intStack[intPtr--];
+ cd.modifiers = intStack[intPtr--];
+
+ //highlight starts at the selector starts
+ cd.sourceStart = (int) (selectorSourcePositions >>> 32);
+ cd.selectorSourceEnd = (int) selectorSourcePositions;
+ pushOnAstStack(cd);
+
+ cd.sourceEnd = lParenPos;
+ cd.bodyStart = lParenPos+1;
+ listLength = 0; // initialize listLength before reading parameters/throws
+
+ // recovery
+ if (currentElement != null){
+ lastCheckPoint = cd.bodyStart;
+ if ((currentElement instanceof RecoveredType && lastIgnoredToken != TokenNameDOT)
+ || cd.modifiers != 0){
+ currentElement = currentElement.add(cd, 0);
+ lastIgnoredToken = -1;
+ }
+ }
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeExitVariableWithInitialization() {
+ // ExitVariableWithInitialization ::= $empty
+ // the scanner is located after the comma or the semi-colon.
+ // we want to include the comma or the semi-colon
+ super.consumeExitVariableWithInitialization();
+ if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
+ return;
+ ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
+}
+protected void consumeExitVariableWithoutInitialization() {
+ // ExitVariableWithoutInitialization ::= $empty
+ // do nothing by default
+ if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
+ return;
+ ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeFieldAccess(boolean isSuperAccess) {
+ // FieldAccess ::= Primary '.' 'Identifier'
+ // FieldAccess ::= 'super' '.' 'Identifier'
+ super.consumeFieldAccess(isSuperAccess);
+ FieldReference fr = (FieldReference) expressionStack[expressionPtr];
+ if (reportReferenceInfo) {
+ requestor.acceptFieldReference(fr.token, fr.sourceStart);
+ }
+}
+protected void consumeMethodHeaderName() {
+ // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+ int length;
+ SourceMethodDeclaration md = new SourceMethodDeclaration();
+
+ //name
+ md.selector = identifierStack[identifierPtr];
+ long selectorSourcePositions = identifierPositionStack[identifierPtr--];
+ identifierLengthPtr--;
+ //type
+ md.returnType = getTypeReference(intStack[intPtr--]);
+ //modifiers
+ md.declarationSourceStart = intStack[intPtr--];
+ md.modifiers = intStack[intPtr--];
+
+ //highlight starts at selector start
+ md.sourceStart = (int) (selectorSourcePositions >>> 32);
+ md.selectorSourceEnd = (int) selectorSourcePositions;
+ pushOnAstStack(md);
+ md.sourceEnd = lParenPos;
+ md.bodyStart = lParenPos+1;
+ listLength = 0; // initialize listLength before reading parameters/throws
+
+ // recovery
+ if (currentElement != null){
+ if (currentElement instanceof RecoveredType
+ //|| md.modifiers != 0
+ || (scanner.searchLineNumber(md.returnType.sourceStart)
+ == scanner.searchLineNumber(md.sourceStart))){
+ lastCheckPoint = md.bodyStart;
+ currentElement = currentElement.add(md, 0);
+ lastIgnoredToken = -1;
+ } else {
+ lastCheckPoint = md.sourceStart;
+ restartRecovery = true;
+ }
+ }
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodInvocationName() {
+ // MethodInvocation ::= Name '(' ArgumentListopt ')'
+
+ // when the name is only an identifier...we have a message send to "this" (implicit)
+ super.consumeMethodInvocationName();
+ MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
+ Expression[] args = messageSend.arguments;
+ if (reportReferenceInfo) {
+ requestor.acceptMethodReference(
+ messageSend.selector,
+ args == null ? 0 : args.length,
+ (int)(messageSend.nameSourcePosition >>> 32));
+ }
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodInvocationPrimary() {
+ super.consumeMethodInvocationPrimary();
+ MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
+ Expression[] args = messageSend.arguments;
+ if (reportReferenceInfo) {
+ requestor.acceptMethodReference(
+ messageSend.selector,
+ args == null ? 0 : args.length,
+ (int)(messageSend.nameSourcePosition >>> 32));
+ }
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodInvocationSuper() {
+ // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
+ super.consumeMethodInvocationSuper();
+ MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
+ Expression[] args = messageSend.arguments;
+ if (reportReferenceInfo) {
+ requestor.acceptMethodReference(
+ messageSend.selector,
+ args == null ? 0 : args.length,
+ (int)(messageSend.nameSourcePosition >>> 32));
+ }
+}
+protected void consumeSingleTypeImportDeclarationName() {
+ // SingleTypeImportDeclarationName ::= 'import' Name
+ /* push an ImportRef build from the last name
+ stored in the identifier stack. */
+
+ super.consumeSingleTypeImportDeclarationName();
+ ImportReference impt = (ImportReference)astStack[astPtr];
+ if (reportReferenceInfo) {
+ requestor.acceptTypeReference(impt.tokens, impt.sourceStart(), impt.sourceEnd());
+ }
+}
+protected void consumeTypeImportOnDemandDeclarationName() {
+ // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
+ /* push an ImportRef build from the last name
+ stored in the identifier stack. */
+
+ super.consumeTypeImportOnDemandDeclarationName();
+ ImportReference impt = (ImportReference)astStack[astPtr];
+ if (reportReferenceInfo) {
+ requestor.acceptUnknownReference(impt.tokens, impt.sourceStart(), impt.sourceEnd());
+ }
+}
+protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
+ return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
+}
+protected CompilationUnitDeclaration endParse(int act) {
+
+ if (sourceType != null) {
+ if (sourceType.isInterface()) {
+ consumeInterfaceDeclaration();
+ } else {
+ consumeClassDeclaration();
+ }
+ }
+ CompilationUnitDeclaration result = super.endParse(act);
+ notifySourceElementRequestor();
+ return result;
+}
+/*
+ * Flush annotations defined prior to a given positions.
+ *
+ * Note: annotations are stacked in syntactical order
+ *
+ * Either answer given <position>, or the end position of a comment line
+ * immediately following the <position> (same line)
+ *
+ * e.g.
+ * void foo(){
+ * } // end of method foo
+ */
+
+public int flushAnnotationsDefinedPriorTo(int position) {
+
+ return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
+}
+public TypeReference getTypeReference(int dim) {
+ /* build a Reference on a variable that may be qualified or not
+ * This variable is a type reference and dim will be its dimensions
+ */
+ int length;
+ if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+ // single variable reference
+ if (dim == 0) {
+ SingleTypeReference ref =
+ new SingleTypeReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ if (reportReferenceInfo) {
+ requestor.acceptTypeReference(ref.token, ref.sourceStart);
+ }
+ return ref;
+ } else {
+ ArrayTypeReference ref =
+ new ArrayTypeReference(
+ identifierStack[identifierPtr],
+ dim,
+ identifierPositionStack[identifierPtr--]);
+ if (reportReferenceInfo) {
+ requestor.acceptTypeReference(ref.token, ref.sourceStart);
+ }
+ return ref;
+ }
+ } else {
+ if (length < 0) { //flag for precompiled type reference on base types
+ TypeReference ref = TypeReference.baseTypeReference(-length, dim);
+ ref.sourceStart = intStack[intPtr--];
+ return ref;
+ } else { //Qualified variable reference
+ char[][] tokens = new char[length][];
+ identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(
+ identifierPositionStack,
+ identifierPtr + 1,
+ positions,
+ 0,
+ length);
+ if (dim == 0) {
+ QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
+ if (reportReferenceInfo) {
+ requestor.acceptTypeReference(ref.tokens, ref.sourceStart(), ref.sourceEnd());
+ }
+ return ref;
+ } else {
+ ArrayQualifiedTypeReference ref =
+ new ArrayQualifiedTypeReference(tokens, dim, positions);
+ if (reportReferenceInfo) {
+ requestor.acceptTypeReference(ref.tokens, ref.sourceStart(), ref.sourceEnd());
+ }
+ return ref;
+ }
+ }
+ }
+}
+public NameReference getUnspecifiedReference() {
+ /* build a (unspecified) NameReference which may be qualified*/
+
+ int length;
+ if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+ // single variable reference
+ SingleNameReference ref =
+ new SingleNameReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ if (reportReferenceInfo) {
+ requestor.acceptUnknownReference(ref.token, ref.sourceStart());
+ }
+ return ref;
+ } else {
+ //Qualified variable reference
+ char[][] tokens = new char[length][];
+ identifierPtr -= length;
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ QualifiedNameReference ref =
+ new QualifiedNameReference(
+ tokens,
+ (int) (identifierPositionStack[identifierPtr + 1] >> 32),
+ // sourceStart
+ (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
+ if (reportReferenceInfo) {
+ requestor.acceptUnknownReference(
+ ref.tokens,
+ ref.sourceStart(),
+ ref.sourceEnd());
+ }
+ return ref;
+ }
+}
+public NameReference getUnspecifiedReferenceOptimized() {
+ /* build a (unspecified) NameReference which may be qualified
+ The optimization occurs for qualified reference while we are
+ certain in this case the last item of the qualified name is
+ a field access. This optimization is IMPORTANT while it results
+ that when a NameReference is build, the type checker should always
+ look for that it is not a type reference */
+
+ int length;
+ if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+ // single variable reference
+ SingleNameReference ref =
+ new SingleNameReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ ref.bits &= ~NameReference.RestrictiveFlagMASK;
+ ref.bits |= LOCAL | FIELD;
+ if (reportReferenceInfo) {
+ requestor.acceptUnknownReference(ref.token, ref.sourceStart());
+ }
+ return ref;
+ }
+
+ //Qualified-variable-reference
+ //In fact it is variable-reference DOT field-ref , but it would result in a type
+ //conflict tha can be only reduce by making a superclass (or inetrface ) between
+ //nameReference and FiledReference or putting FieldReference under NameReference
+ //or else..........This optimisation is not really relevant so just leave as it is
+
+ char[][] tokens = new char[length][];
+ identifierPtr -= length;
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ QualifiedNameReference ref =
+ new QualifiedNameReference(
+ tokens,
+ (int) (identifierPositionStack[identifierPtr + 1] >> 32),
+ // sourceStart
+ (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
+ ref.bits &= ~NameReference.RestrictiveFlagMASK;
+ ref.bits |= LOCAL | FIELD;
+ if (reportReferenceInfo) {
+ requestor.acceptUnknownReference(
+ ref.tokens,
+ ref.sourceStart(),
+ ref.sourceEnd());
+ }
+ return ref;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+private boolean isLocalDeclaration() {
+ int nestedDepth = nestedType;
+ while (nestedDepth >= 0) {
+ if (nestedMethod[nestedDepth] != 0) {
+ return true;
+ }
+ nestedDepth--;
+ }
+ return false;
+}
+/*
+ * Update the bodyStart of the corresponding parse node
+ */
+public void notifySourceElementRequestor() {
+
+ if (sourceType == null){
+ if (scanner.initialPosition == 0) {
+ requestor.enterCompilationUnit();
+ }
+ // first we notify the package declaration
+ ImportReference currentPackage = compilationUnit.currentPackage;
+ if (currentPackage != null) {
+ notifySourceElementRequestor(currentPackage, true);
+ }
+ // then the imports
+ ImportReference[] imports = compilationUnit.imports;
+ if (imports != null) {
+ for (int i = 0, max = imports.length; i < max; i++) {
+ notifySourceElementRequestor(imports[i], false);
+ }
+ }
+ }
+ // then the types contained by this compilation unit
+ TypeDeclaration[] types = compilationUnit.types;
+ if (types != null) {
+ for (int i = 0, max = types.length; i < max; i++) {
+ notifySourceElementRequestor(types[i], sourceType == null);
+ }
+ }
+ if (sourceType == null){
+ if (scanner.eofPosition >= compilationUnit.sourceEnd) {
+ requestor.exitCompilationUnit(compilationUnit.sourceEnd);
+ }
+ }
+}
+/*
+ * Update the bodyStart of the corresponding parse node
+ */
+public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
+ if (methodDeclaration.isClinit())
+ return;
+
+ if (methodDeclaration.isDefaultConstructor()) {
+ if (reportReferenceInfo) {
+ ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
+ ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
+ if (constructorCall != null) {
+ switch(constructorCall.accessMode) {
+ case ExplicitConstructorCall.This :
+ requestor.acceptConstructorReference(
+ typeNames[nestedTypeIndex-1],
+ constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
+ constructorCall.sourceStart);
+ break;
+ case ExplicitConstructorCall.Super :
+ case ExplicitConstructorCall.ImplicitSuper :
+ requestor.acceptConstructorReference(
+ superTypeNames[nestedTypeIndex-1],
+ constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
+ constructorCall.sourceStart);
+ break;
+ }
+ }
+ }
+ return;
+ }
+ char[][] argumentTypes = null;
+ char[][] argumentNames = null;
+ Argument[] arguments = methodDeclaration.arguments;
+ if (arguments != null) {
+ int argumentLength = arguments.length;
+ argumentTypes = new char[argumentLength][];
+ argumentNames = new char[argumentLength][];
+ for (int i = 0; i < argumentLength; i++) {
+ argumentTypes[i] = returnTypeName(arguments[i].type);
+ argumentNames[i] = arguments[i].name;
+ }
+ }
+ char[][] thrownExceptionTypes = null;
+ TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
+ if (thrownExceptions != null) {
+ int thrownExceptionLength = thrownExceptions.length;
+ thrownExceptionTypes = new char[thrownExceptionLength][];
+ for (int i = 0; i < thrownExceptionLength; i++) {
+ thrownExceptionTypes[i] =
+ CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.');
+ }
+ }
+ // by default no selector end position
+ int selectorSourceEnd = -1;
+ if (methodDeclaration.isConstructor()) {
+ if (methodDeclaration instanceof SourceConstructorDeclaration) {
+ selectorSourceEnd =
+ ((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd;
+ }
+ if (scanner.initialPosition <= methodDeclaration.declarationSourceStart) {
+ requestor.enterConstructor(
+ methodDeclaration.declarationSourceStart,
+ methodDeclaration.modifiers,
+ methodDeclaration.selector,
+ methodDeclaration.sourceStart,
+ selectorSourceEnd,
+ argumentTypes,
+ argumentNames,
+ thrownExceptionTypes);
+ if (reportReferenceInfo) {
+ ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
+ ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
+ if (constructorCall != null) {
+ switch(constructorCall.accessMode) {
+ case ExplicitConstructorCall.This :
+ requestor.acceptConstructorReference(
+ typeNames[nestedTypeIndex-1],
+ constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
+ constructorCall.sourceStart);
+ break;
+ case ExplicitConstructorCall.Super :
+ case ExplicitConstructorCall.ImplicitSuper :
+ requestor.acceptConstructorReference(
+ superTypeNames[nestedTypeIndex-1],
+ constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
+ constructorCall.sourceStart);
+ break;
+ }
+ }
+ }
+ }
+ if (scanner.eofPosition >= methodDeclaration.declarationSourceEnd) {
+ requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
+ }
+ return;
+ }
+ if (methodDeclaration instanceof SourceMethodDeclaration) {
+ selectorSourceEnd =
+ ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd;
+ }
+ requestor.enterMethod(
+ methodDeclaration.declarationSourceStart,
+ methodDeclaration.modifiers,
+ returnTypeName(((MethodDeclaration) methodDeclaration).returnType),
+ methodDeclaration.selector,
+ methodDeclaration.sourceStart,
+ selectorSourceEnd,
+ argumentTypes,
+ argumentNames,
+ thrownExceptionTypes);
+ requestor.exitMethod(methodDeclaration.declarationSourceEnd);
+}
+/*
+* Update the bodyStart of the corresponding parse node
+*/
+public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
+ if (fieldDeclaration.isField()) {
+ int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
+ if (fieldDeclaration instanceof SourceFieldDeclaration) {
+ fieldEndPosition = ((SourceFieldDeclaration) fieldDeclaration).fieldEndPosition;
+ if (fieldEndPosition == 0) {
+ // use the declaration source end by default
+ fieldEndPosition = fieldDeclaration.declarationSourceEnd;
+ }
+ }
+ requestor.enterField(
+ fieldDeclaration.declarationSourceStart,
+ fieldDeclaration.modifiers,
+ returnTypeName(fieldDeclaration.type),
+ fieldDeclaration.name,
+ fieldDeclaration.sourceStart,
+ fieldDeclaration.sourceEnd);
+ requestor.exitField(fieldEndPosition);
+
+ } else {
+ requestor.acceptInitializer(
+ fieldDeclaration.modifiers,
+ fieldDeclaration.declarationSourceStart,
+ fieldDeclaration.declarationSourceEnd);
+ }
+}
+public void notifySourceElementRequestor(
+ ImportReference importReference,
+ boolean isPackage) {
+ if (isPackage) {
+ requestor.acceptPackage(
+ importReference.declarationSourceStart,
+ importReference.declarationSourceEnd,
+ CharOperation.concatWith(importReference.getImportName(), '.'));
+ } else {
+ requestor.acceptImport(
+ importReference.declarationSourceStart,
+ importReference.declarationSourceEnd,
+ CharOperation.concatWith(importReference.getImportName(), '.'),
+ importReference.onDemand);
+ }
+}
+public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
+ FieldDeclaration[] fields = typeDeclaration.fields;
+ AbstractMethodDeclaration[] methods = typeDeclaration.methods;
+ MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
+ int fieldCount = fields == null ? 0 : fields.length;
+ int methodCount = methods == null ? 0 : methods.length;
+ int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
+ int fieldIndex = 0;
+ int methodIndex = 0;
+ int memberTypeIndex = 0;
+ boolean isInterface = typeDeclaration.isInterface();
+
+ if (notifyTypePresence){
+ char[][] interfaceNames = null;
+ int superInterfacesLength = 0;
+ TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
+ if (superInterfaces != null) {
+ superInterfacesLength = superInterfaces.length;
+ interfaceNames = new char[superInterfacesLength][];
+ }
+ if (superInterfaces != null) {
+ for (int i = 0; i < superInterfacesLength; i++) {
+ interfaceNames[i] =
+ CharOperation.concatWith(superInterfaces[i].getTypeName(), '.');
+ }
+ }
+ if (isInterface) {
+ requestor.enterInterface(
+ typeDeclaration.declarationSourceStart,
+ typeDeclaration.modifiers,
+ typeDeclaration.name,
+ typeDeclaration.sourceStart,
+ typeDeclaration.sourceEnd,
+ interfaceNames);
+ if (nestedTypeIndex == typeNames.length) {
+ // need a resize
+ System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+ System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+ }
+ typeNames[nestedTypeIndex] = typeDeclaration.name;
+ superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
+ } else {
+ TypeReference superclass = typeDeclaration.superclass;
+ if (superclass == null) {
+ requestor.enterClass(
+ typeDeclaration.declarationSourceStart,
+ typeDeclaration.modifiers,
+ typeDeclaration.name,
+ typeDeclaration.sourceStart,
+ typeDeclaration.sourceEnd,
+ null,
+ interfaceNames);
+ } else {
+ requestor.enterClass(
+ typeDeclaration.declarationSourceStart,
+ typeDeclaration.modifiers,
+ typeDeclaration.name,
+ typeDeclaration.sourceStart,
+ typeDeclaration.sourceEnd,
+ CharOperation.concatWith(superclass.getTypeName(), '.'),
+ interfaceNames);
+ }
+ if (nestedTypeIndex == typeNames.length) {
+ // need a resize
+ System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+ System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+ }
+ typeNames[nestedTypeIndex] = typeDeclaration.name;
+ superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass.getTypeName(), '.');
+ }
+ }
+ while ((fieldIndex < fieldCount)
+ || (memberTypeIndex < memberTypeCount)
+ || (methodIndex < methodCount)) {
+ FieldDeclaration nextFieldDeclaration = null;
+ AbstractMethodDeclaration nextMethodDeclaration = null;
+ TypeDeclaration nextMemberDeclaration = null;
+
+ int position = Integer.MAX_VALUE;
+ int nextDeclarationType = -1;
+ if (fieldIndex < fieldCount) {
+ nextFieldDeclaration = fields[fieldIndex];
+ if (nextFieldDeclaration.declarationSourceStart < position) {
+ position = nextFieldDeclaration.declarationSourceStart;
+ nextDeclarationType = 0; // FIELD
+ }
+ }
+ if (methodIndex < methodCount) {
+ nextMethodDeclaration = methods[methodIndex];
+ if (nextMethodDeclaration.declarationSourceStart < position) {
+ position = nextMethodDeclaration.declarationSourceStart;
+ nextDeclarationType = 1; // METHOD
+ }
+ }
+ if (memberTypeIndex < memberTypeCount) {
+ nextMemberDeclaration = memberTypes[memberTypeIndex];
+ if (nextMemberDeclaration.declarationSourceStart < position) {
+ position = nextMemberDeclaration.declarationSourceStart;
+ nextDeclarationType = 2; // MEMBER
+ }
+ }
+ switch (nextDeclarationType) {
+ case 0 :
+ fieldIndex++;
+ notifySourceElementRequestor(nextFieldDeclaration);
+ break;
+ case 1 :
+ methodIndex++;
+ notifySourceElementRequestor(nextMethodDeclaration);
+ break;
+ case 2 :
+ memberTypeIndex++;
+ notifySourceElementRequestor(nextMemberDeclaration, true);
+ }
+ }
+ if (notifyTypePresence){
+ if (isInterface) {
+ requestor.exitInterface(typeDeclaration.declarationSourceEnd);
+ } else {
+ requestor.exitClass(typeDeclaration.declarationSourceEnd);
+ }
+ nestedTypeIndex--;
+ }
+}
+public void parseCompilationUnit(
+ ICompilationUnit unit,
+ int start,
+ int end,
+ boolean needReferenceInfo) {
+
+ CompilationUnitDeclaration result;
+ reportReferenceInfo = needReferenceInfo;
+ boolean old = diet;
+ try {
+ diet = !needReferenceInfo;
+ CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0);
+ result = parse(unit, compilationUnitResult, start, end);
+ } catch (AbortCompilation e) {
+ } finally {
+ if (scanner.recordLineSeparator) {
+ requestor.acceptLineSeparatorPositions(scanner.lineEnds());
+ }
+ diet = old;
+ }
+}
+public void parseCompilationUnit(
+ ICompilationUnit unit,
+ boolean needReferenceInfo) {
+
+ CompilationUnitDeclaration result;
+ boolean old = diet;
+ try {
+ diet = !needReferenceInfo;
+ reportReferenceInfo = needReferenceInfo;
+ CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0);
+ result = parse(unit, compilationUnitResult);
+ } catch (AbortCompilation e) {
+ } finally {
+ if (scanner.recordLineSeparator) {
+ requestor.acceptLineSeparatorPositions(scanner.lineEnds());
+ }
+ diet = old;
+ }
+}
+public void parseTypeMemberDeclarations(
+ ISourceType sourceType,
+ ICompilationUnit sourceUnit,
+ int start,
+ int end,
+ boolean needReferenceInfo) {
+
+ boolean old = diet;
+ try {
+ diet = !needReferenceInfo;
+ reportReferenceInfo = needReferenceInfo;
+ CompilationResult compilationUnitResult =
+ new CompilationResult(sourceUnit, 0, 0);
+
+ CompilationUnitDeclaration unit =
+ SourceTypeConverter.buildCompilationUnit(
+ sourceType,
+ false,
+ false,
+ problemReporter(),
+ compilationUnitResult);
+ if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
+ return;
+
+ this.sourceType = sourceType;
+
+ try {
+ /* automaton initialization */
+ initialize();
+ goForClassBodyDeclarations();
+ /* scanner initialization */
+ scanner.setSourceBuffer(sourceUnit.getContents());
+ int sourceLength = scanner.source.length;
+ scanner.resetTo(start, end);
+ /* unit creation */
+ referenceContext = compilationUnit = unit;
+
+ /* initialize the astStacl */
+ // the compilationUnitDeclaration should contain exactly one type
+ pushOnAstStack(unit.types[0]);
+ /* run automaton */
+ parse();
+ } finally {
+ unit = compilationUnit;
+ compilationUnit = null; // reset parser
+ }
+ } catch (AbortCompilation e) {
+ } finally {
+ if (scanner.recordLineSeparator) {
+ requestor.acceptLineSeparatorPositions(scanner.lineEnds());
+ }
+ diet = old;
+ }
+}
+/*
+ * Answer a char array representation of the type name formatted like:
+ * - type name + dimensions
+ * Example:
+ * "A[][]".toCharArray()
+ * "java.lang.String".toCharArray()
+ */
+private char[] returnTypeName(TypeReference type) {
+ if (type == null)
+ return null;
+ int dimension = type.dimensions();
+ if (dimension != 0) {
+ char[] dimensionsArray = new char[dimension * 2];
+ for (int i = 0; i < dimension; i++) {
+ dimensionsArray[i * 2] = '[';
+ dimensionsArray[(i * 2) + 1] = ']';
+ }
+ return CharOperation.concat(
+ CharOperation.concatWith(type.getTypeName(), '.'),
+ dimensionsArray);
+ }
+ return CharOperation.concatWith(type.getTypeName(), '.');
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java b/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
index 8539431..0a7caff 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
@@ -1,37 +1,35 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public abstract class AbstractVariableDeclaration extends Statement {
- public int modifiers;
-
- public TypeReference type;
- public Expression initialization;
-
- public char[] name;
-
- public int declarationSourceStart;
- public int declarationSourceEnd;
- public int modifiersSourceStart;
-public AbstractVariableDeclaration(){}
-public String name(){
-
- return "anonymous storage box"/*nonNLS*/; }
-public String toString(int tab) {
- /*slow code*/
-
- String s = tabString(tab);
- if (modifiers != AccDefault) {
- s += modifiersString(modifiers);
- }
- s += type.toString(0) + " "/*nonNLS*/ + new String(name());
- if (initialization != null)
- s += " = "/*nonNLS*/ + initialization.toStringExpression(tab);
- return s;
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+public abstract class AbstractVariableDeclaration extends Statement {
+ public int modifiers;
+
+ public TypeReference type;
+ public Expression initialization;
+
+ public char[] name;
+
+ public int declarationSourceStart;
+ public int declarationSourceEnd;
+ public int modifiersSourceStart;
+public AbstractVariableDeclaration(){}
+public String name(){
+
+ return "anonymous storage box"/*nonNLS*/; }
+public String toString(int tab) {
+ /*slow code*/
+
+ String s = tabString(tab);
+ if (modifiers != AccDefault) {
+ s += modifiersString(modifiers);
+ }
+ s += type.toString(0) + " "/*nonNLS*/ + new String(name());
+ if (initialization != null)
+ s += " = "/*nonNLS*/ + initialization.toStringExpression(tab);
+ return s;
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
index 4ae4b54..216ffe3 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
@@ -1,199 +1,198 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class AllocationExpression extends Expression implements InvocationSite {
- public TypeReference type;
- public Expression[] arguments;
- public MethodBinding binding;
-
- MethodBinding syntheticAccessor;
-
-public AllocationExpression() {
- super();
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-
- // must verify that exceptions potentially thrown by this expression are caught in the method
-
- // process arguments
- if (arguments != null) {
- for (int i = 0, count = arguments.length; i < count; i++) {
- flowInfo = arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
- }
- }
- // record some dependency information for exception types
- int count;
- ReferenceBinding[] thrownExceptions;
- if ((count = (thrownExceptions = binding.thrownExceptions).length) != 0) {
- // check exception handling
- flowContext.checkExceptionHandlers(thrownExceptions, this, flowInfo, currentScope);
- }
- manageEnclosingInstanceAccessIfNecessary(currentScope);
- manageSyntheticAccessIfNecessary(currentScope);
- return flowInfo;
-}
-public Expression enclosingInstance() {
- return null;
-}
-public void generateCode(
- BlockScope currentScope,
- CodeStream codeStream,
- boolean valueRequired) {
-
- int pc = codeStream.position;
- ReferenceBinding allocatedType = binding.declaringClass;
-
- codeStream.new_(allocatedType);
- if (valueRequired) {
- codeStream.dup();
- }
- // better highlight for allocation: display the type individually
- codeStream.recordPositionsFrom(pc, type);
-
- // handling innerclass instance allocation
- if (allocatedType.isNestedType()) {
- codeStream.generateSyntheticArgumentValues(
- currentScope,
- allocatedType,
- enclosingInstance(),
- this);
- }
- // generate the arguments for constructor
- if (arguments != null) {
- for (int i = 0, count = arguments.length; i < count; i++) {
- arguments[i].generateCode(currentScope, codeStream, true);
- }
- }
- // invoke constructor
- if (syntheticAccessor == null) {
- codeStream.invokespecial(binding);
- } else {
- // synthetic accessor got some extra arguments appended to its signature, which need values
- for (int i = 0, max = syntheticAccessor.parameters.length - binding.parameters.length; i < max; i++) {
- codeStream.aconst_null();
- }
- codeStream.invokespecial(syntheticAccessor);
- }
- codeStream.recordPositionsFrom(pc, this);
-}
-public boolean isSuperAccess() {
- return false;
-}
-public boolean isTypeAccess(){
- return true;
-}
-/* Inner emulation consists in either recording a dependency
- * link only, or performing one level of propagation.
- *
- * Dependency mechanism is used whenever dealing with source target
- * types, since by the time we reach them, we might not yet know their
- * exact need.
- */
-public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
- ReferenceBinding invocationType, allocatedType;
-
- // perform some emulation work in case there is some and we are inside a local type only
- if ((allocatedType = binding.declaringClass).isNestedType()
- && currentScope.enclosingSourceType().isLocalType()) {
-
- if (allocatedType.isLocalType()){
- ((LocalTypeBinding)allocatedType).addInnerEmulationDependent(currentScope, false, false); // request cascade of accesses
- } else {
- // locally propagate, since we already now the desired shape for sure
- currentScope.propagateInnerEmulation(allocatedType, false, false); // request cascade of accesses
- }
- }
-}
-public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
- if (binding.isPrivate() && (currentScope.enclosingSourceType() != binding.declaringClass)) {
-
- if (currentScope.environment().options.isPrivateConstructorAccessChangingVisibility){
- binding.tagForClearingPrivateModifier(); // constructor will not be dumped as private, no emulation required thus
- } else {
- syntheticAccessor = ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding);
- currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
- }
- }
-}
-public TypeBinding resolveType(BlockScope scope) {
- // Propagate the type checking to the arguments, and check if the constructor is defined.
- constant = NotAConstant;
- TypeBinding typeBinding = type.resolveType(scope); // will check for null after args are resolved
-
- // buffering the arguments' types
- TypeBinding[] argumentTypes = NoParameters;
- if (arguments != null) {
- boolean argHasError = false;
- int length = arguments.length;
- argumentTypes = new TypeBinding[length];
- for (int i = 0; i < length; i++)
- if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
- argHasError = true;
- if (argHasError)
- return null;
- }
- if (typeBinding == null)
- return null;
-
- if (!typeBinding.canBeInstantiated()) {
- scope.problemReporter().cannotInstantiate(type, typeBinding);
- return null;
- }
- ReferenceBinding allocatedType = (ReferenceBinding) typeBinding;
- if (!(binding = scope.getConstructor(allocatedType, argumentTypes, this)).isValidBinding()) {
- if (binding.declaringClass == null)
- binding.declaringClass = allocatedType;
- scope.problemReporter().invalidConstructor(this, binding);
- return null;
- }
- if (isMethodUseDeprecated(binding, scope))
- scope.problemReporter().deprecatedMethod(binding, this);
-
- if (arguments != null)
- for (int i = 0; i < arguments.length; i++)
- arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
- return allocatedType;
-}
-public void setDepth(int i) {
- // ignored
-}
-public void setFieldIndex(int i) {
- // ignored
-}
-public String toStringExpression() {
- /* slow code */
-
- String s = "new "/*nonNLS*/ + type.toString(0);
- if (arguments == null)
- s = s + "()"/*nonNLS*/ ;
- else
- { s = s + "("/*nonNLS*/;
- for (int i = 0 ; i < arguments.length ; i++)
- { s = s + arguments[i].toStringExpression();
- if (i == (arguments.length-1))
- s = s + ")"/*nonNLS*/ ;
- else
- s = s + ", "/*nonNLS*/; };};
- return s ;}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
- if (visitor.visit(this, scope)) {
- int argumentsLength;
- type.traverse(visitor, scope);
- if (arguments != null) {
- argumentsLength = arguments.length;
- for (int i = 0; i < argumentsLength; i++)
- arguments[i].traverse(visitor, scope);
- }
- }
- visitor.endVisit(this, scope);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class AllocationExpression extends Expression implements InvocationSite {
+ public TypeReference type;
+ public Expression[] arguments;
+ public MethodBinding binding;
+
+ MethodBinding syntheticAccessor;
+
+public AllocationExpression() {
+ super();
+}
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+ // must verify that exceptions potentially thrown by this expression are caught in the method
+
+ // process arguments
+ if (arguments != null) {
+ for (int i = 0, count = arguments.length; i < count; i++) {
+ flowInfo = arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+ }
+ }
+ // record some dependency information for exception types
+ int count;
+ ReferenceBinding[] thrownExceptions;
+ if ((count = (thrownExceptions = binding.thrownExceptions).length) != 0) {
+ // check exception handling
+ flowContext.checkExceptionHandlers(thrownExceptions, this, flowInfo, currentScope);
+ }
+ manageEnclosingInstanceAccessIfNecessary(currentScope);
+ manageSyntheticAccessIfNecessary(currentScope);
+ return flowInfo;
+}
+public Expression enclosingInstance() {
+ return null;
+}
+public void generateCode(
+ BlockScope currentScope,
+ CodeStream codeStream,
+ boolean valueRequired) {
+
+ int pc = codeStream.position;
+ ReferenceBinding allocatedType = binding.declaringClass;
+
+ codeStream.new_(allocatedType);
+ if (valueRequired) {
+ codeStream.dup();
+ }
+ // better highlight for allocation: display the type individually
+ codeStream.recordPositionsFrom(pc, type);
+
+ // handling innerclass instance allocation
+ if (allocatedType.isNestedType()) {
+ codeStream.generateSyntheticArgumentValues(
+ currentScope,
+ allocatedType,
+ enclosingInstance(),
+ this);
+ }
+ // generate the arguments for constructor
+ if (arguments != null) {
+ for (int i = 0, count = arguments.length; i < count; i++) {
+ arguments[i].generateCode(currentScope, codeStream, true);
+ }
+ }
+ // invoke constructor
+ if (syntheticAccessor == null) {
+ codeStream.invokespecial(binding);
+ } else {
+ // synthetic accessor got some extra arguments appended to its signature, which need values
+ for (int i = 0, max = syntheticAccessor.parameters.length - binding.parameters.length; i < max; i++) {
+ codeStream.aconst_null();
+ }
+ codeStream.invokespecial(syntheticAccessor);
+ }
+ codeStream.recordPositionsFrom(pc, this);
+}
+public boolean isSuperAccess() {
+ return false;
+}
+public boolean isTypeAccess(){
+ return true;
+}
+/* Inner emulation consists in either recording a dependency
+ * link only, or performing one level of propagation.
+ *
+ * Dependency mechanism is used whenever dealing with source target
+ * types, since by the time we reach them, we might not yet know their
+ * exact need.
+ */
+public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
+ ReferenceBinding invocationType, allocatedType;
+
+ // perform some emulation work in case there is some and we are inside a local type only
+ if ((allocatedType = binding.declaringClass).isNestedType()
+ && currentScope.enclosingSourceType().isLocalType()) {
+
+ if (allocatedType.isLocalType()){
+ ((LocalTypeBinding)allocatedType).addInnerEmulationDependent(currentScope, false, false); // request cascade of accesses
+ } else {
+ // locally propagate, since we already now the desired shape for sure
+ currentScope.propagateInnerEmulation(allocatedType, false, false); // request cascade of accesses
+ }
+ }
+}
+public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
+ if (binding.isPrivate() && (currentScope.enclosingSourceType() != binding.declaringClass)) {
+
+ if (currentScope.environment().options.isPrivateConstructorAccessChangingVisibility){
+ binding.tagForClearingPrivateModifier(); // constructor will not be dumped as private, no emulation required thus
+ } else {
+ syntheticAccessor = ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding);
+ currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
+ }
+ }
+}
+public TypeBinding resolveType(BlockScope scope) {
+ // Propagate the type checking to the arguments, and check if the constructor is defined.
+ constant = NotAConstant;
+ TypeBinding typeBinding = type.resolveType(scope); // will check for null after args are resolved
+
+ // buffering the arguments' types
+ TypeBinding[] argumentTypes = NoParameters;
+ if (arguments != null) {
+ boolean argHasError = false;
+ int length = arguments.length;
+ argumentTypes = new TypeBinding[length];
+ for (int i = 0; i < length; i++)
+ if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
+ argHasError = true;
+ if (argHasError)
+ return null;
+ }
+ if (typeBinding == null)
+ return null;
+
+ if (!typeBinding.canBeInstantiated()) {
+ scope.problemReporter().cannotInstantiate(type, typeBinding);
+ return null;
+ }
+ ReferenceBinding allocatedType = (ReferenceBinding) typeBinding;
+ if (!(binding = scope.getConstructor(allocatedType, argumentTypes, this)).isValidBinding()) {
+ if (binding.declaringClass == null)
+ binding.declaringClass = allocatedType;
+ scope.problemReporter().invalidConstructor(this, binding);
+ return null;
+ }
+ if (isMethodUseDeprecated(binding, scope))
+ scope.problemReporter().deprecatedMethod(binding, this);
+
+ if (arguments != null)
+ for (int i = 0; i < arguments.length; i++)
+ arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
+ return allocatedType;
+}
+public void setDepth(int i) {
+ // ignored
+}
+public void setFieldIndex(int i) {
+ // ignored
+}
+public String toStringExpression() {
+ /* slow code */
+
+ String s = "new "/*nonNLS*/ + type.toString(0);
+ if (arguments == null)
+ s = s + "()"/*nonNLS*/ ;
+ else
+ { s = s + "("/*nonNLS*/;
+ for (int i = 0 ; i < arguments.length ; i++)
+ { s = s + arguments[i].toStringExpression();
+ if (i == (arguments.length-1))
+ s = s + ")"/*nonNLS*/ ;
+ else
+ s = s + ", "/*nonNLS*/; };};
+ return s ;}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ int argumentsLength;
+ type.traverse(visitor, scope);
+ if (arguments != null) {
+ argumentsLength = arguments.length;
+ for (int i = 0; i < argumentsLength; i++)
+ arguments[i].traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, scope);
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/AnonymousLocalTypeDeclaration.java b/compiler/org/eclipse/jdt/internal/compiler/ast/AnonymousLocalTypeDeclaration.java
index aaa8ee6..1e84888 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/AnonymousLocalTypeDeclaration.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/AnonymousLocalTypeDeclaration.java
@@ -1,159 +1,158 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-
-public class AnonymousLocalTypeDeclaration extends LocalTypeDeclaration {
- //a temporal default name
- public static final char[] ANONYMOUS_EMPTY_NAME = new char[]{} ;
- public QualifiedAllocationExpression allocation;
-public AnonymousLocalTypeDeclaration(){
- super();
- modifiers = AccDefault ;
- name = ANONYMOUS_EMPTY_NAME; } // use a default name in order to th name lookup
- // to operate juat like a regular type (which has a name)
- //without checking systematically if the naem is null ....
-public MethodBinding createsInternalConstructorWithBinding(MethodBinding inheritedConstructorBinding) {
- //Add to method'set, the default constuctor that just recall the
- //super constructor with the same arguments
-
- String baseName = "$anonymous"/*nonNLS*/;
- TypeBinding[] argumentTypes = inheritedConstructorBinding.parameters;
- int argumentsLength = argumentTypes.length;
- //the constructor
- ConstructorDeclaration cd = new ConstructorDeclaration();
- cd.selector = new char[] {'x'}; //no maining
- cd.sourceStart = sourceStart;
- cd.sourceEnd = sourceEnd;
- cd.modifiers = modifiers & AccVisibilityMASK;
-
- if (argumentsLength > 0) {
- Argument[] arguments = (cd.arguments = new Argument[argumentsLength]);
- for (int i = argumentsLength; --i >= 0;) {
- arguments[i] =
- new Argument(
- (baseName + i).toCharArray(),
- 0L,
- //toCharArray() could be optimized ....
- null, //no meaning (a TypeReference)
- AccDefault);
- }
- }
-
- //the super call inside the constructor
- cd.constructorCall =
- new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
- cd.constructorCall.sourceStart = sourceStart;
- cd.constructorCall.sourceEnd = sourceEnd;
-
- if (argumentsLength > 0) {
- Expression[] args;
- args = cd.constructorCall.arguments = new Expression[argumentsLength];
- for (int i = argumentsLength; --i >= 0;) {
- args[i] = new SingleNameReference((baseName + i).toCharArray(), 0L);
- }
- }
-
- //adding the constructor in the methods list
- if (methods == null) {
- methods = new AbstractMethodDeclaration[] {cd};
- } else {
- AbstractMethodDeclaration[] newMethods;
- System.arraycopy(
- methods,
- 0,
- newMethods = new AbstractMethodDeclaration[methods.length + 1],
- 1,
- methods.length);
- newMethods[0] = cd;
- methods = newMethods;
- }
-
- //============BINDING UPDATE==========================
- cd.binding = new MethodBinding(
- cd.modifiers, //methodDeclaration
- argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
- inheritedConstructorBinding.thrownExceptions, //exceptions
- binding); //declaringClass
- cd.scope = new MethodScope(scope, this, true);
- cd.bindArguments();
- cd.constructorCall.resolve(cd.scope);
- if (binding.methods == null) {
- binding.methods = new MethodBinding[] {cd.binding};
- } else {
- MethodBinding[] newMethods;
- System.arraycopy(
- binding.methods,
- 0,
- newMethods = new MethodBinding[binding.methods.length + 1],
- 1,
- binding.methods.length);
- newMethods[0] = cd.binding;
- binding.methods = newMethods;
- }
- //===================================================
-
- return cd.binding;
-
-}
-public void resolve(BlockScope scope) {
- // scope and binding are provided in updateBindingSuperclass
-
- resolve();
- updateMaxFieldCount();
-}
-public String toString(int tab ){
- /*slow code */
-
- return toStringBody(tab);
- }
-/**
- * Iteration for a local anonymous innertype
- *
- */
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
- if (ignoreFurtherInvestigation)
- return;
- try {
- if (visitor.visit(this, blockScope)) {
-
- int fieldsLength;
- int methodsLength;
- int memberTypesLength;
-
- // <superclass> is bound to the actual type from the allocation expression
- // therefore it has already been iterated at this point.
-
- if (memberTypes != null) {
- memberTypesLength = memberTypes.length;
- for (int i = 0; i < memberTypesLength; i++)
- memberTypes[i].traverse(visitor, scope);
- }
- if (fields != null) {
- fieldsLength = fields.length;
- for (int i = 0; i < fieldsLength; i++) {
- FieldDeclaration field;
- if ((field = fields[i]).isStatic()) {
- // local type cannot have static fields
- } else {
- field.traverse(visitor, initializerScope);
- }
- }
- }
- if (methods != null) {
- methodsLength = methods.length;
- for (int i = 0; i < methodsLength; i++)
- methods[i].traverse(visitor, scope);
- }
- }
- visitor.endVisit(this, blockScope);
- } catch (AbortType e) {
- }
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+
+public class AnonymousLocalTypeDeclaration extends LocalTypeDeclaration {
+ //a temporal default name
+ public static final char[] ANONYMOUS_EMPTY_NAME = new char[]{} ;
+ public QualifiedAllocationExpression allocation;
+public AnonymousLocalTypeDeclaration(){
+ super();
+ modifiers = AccDefault ;
+ name = ANONYMOUS_EMPTY_NAME; } // use a default name in order to th name lookup
+ // to operate juat like a regular type (which has a name)
+ //without checking systematically if the naem is null ....
+public MethodBinding createsInternalConstructorWithBinding(MethodBinding inheritedConstructorBinding) {
+ //Add to method'set, the default constuctor that just recall the
+ //super constructor with the same arguments
+
+ String baseName = "$anonymous"/*nonNLS*/;
+ TypeBinding[] argumentTypes = inheritedConstructorBinding.parameters;
+ int argumentsLength = argumentTypes.length;
+ //the constructor
+ ConstructorDeclaration cd = new ConstructorDeclaration();
+ cd.selector = new char[] {'x'}; //no maining
+ cd.sourceStart = sourceStart;
+ cd.sourceEnd = sourceEnd;
+ cd.modifiers = modifiers & AccVisibilityMASK;
+
+ if (argumentsLength > 0) {
+ Argument[] arguments = (cd.arguments = new Argument[argumentsLength]);
+ for (int i = argumentsLength; --i >= 0;) {
+ arguments[i] =
+ new Argument(
+ (baseName + i).toCharArray(),
+ 0L,
+ //toCharArray() could be optimized ....
+ null, //no meaning (a TypeReference)
+ AccDefault);
+ }
+ }
+
+ //the super call inside the constructor
+ cd.constructorCall =
+ new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
+ cd.constructorCall.sourceStart = sourceStart;
+ cd.constructorCall.sourceEnd = sourceEnd;
+
+ if (argumentsLength > 0) {
+ Expression[] args;
+ args = cd.constructorCall.arguments = new Expression[argumentsLength];
+ for (int i = argumentsLength; --i >= 0;) {
+ args[i] = new SingleNameReference((baseName + i).toCharArray(), 0L);
+ }
+ }
+
+ //adding the constructor in the methods list
+ if (methods == null) {
+ methods = new AbstractMethodDeclaration[] {cd};
+ } else {
+ AbstractMethodDeclaration[] newMethods;
+ System.arraycopy(
+ methods,
+ 0,
+ newMethods = new AbstractMethodDeclaration[methods.length + 1],
+ 1,
+ methods.length);
+ newMethods[0] = cd;
+ methods = newMethods;
+ }
+
+ //============BINDING UPDATE==========================
+ cd.binding = new MethodBinding(
+ cd.modifiers, //methodDeclaration
+ argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
+ inheritedConstructorBinding.thrownExceptions, //exceptions
+ binding); //declaringClass
+ cd.scope = new MethodScope(scope, this, true);
+ cd.bindArguments();
+ cd.constructorCall.resolve(cd.scope);
+ if (binding.methods == null) {
+ binding.methods = new MethodBinding[] {cd.binding};
+ } else {
+ MethodBinding[] newMethods;
+ System.arraycopy(
+ binding.methods,
+ 0,
+ newMethods = new MethodBinding[binding.methods.length + 1],
+ 1,
+ binding.methods.length);
+ newMethods[0] = cd.binding;
+ binding.methods = newMethods;
+ }
+ //===================================================
+
+ return cd.binding;
+
+}
+public void resolve(BlockScope scope) {
+ // scope and binding are provided in updateBindingSuperclass
+
+ resolve();
+ updateMaxFieldCount();
+}
+public String toString(int tab ){
+ /*slow code */
+
+ return toStringBody(tab);
+ }
+/**
+ * Iteration for a local anonymous innertype
+ *
+ */
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+ if (ignoreFurtherInvestigation)
+ return;
+ try {
+ if (visitor.visit(this, blockScope)) {
+
+ int fieldsLength;
+ int methodsLength;
+ int memberTypesLength;
+
+ // <superclass> is bound to the actual type from the allocation expression
+ // therefore it has already been iterated at this point.
+
+ if (memberTypes != null) {
+ memberTypesLength = memberTypes.length;
+ for (int i = 0; i < memberTypesLength; i++)
+ memberTypes[i].traverse(visitor, scope);
+ }
+ if (fields != null) {
+ fieldsLength = fields.length;
+ for (int i = 0; i < fieldsLength; i++) {
+ FieldDeclaration field;
+ if ((field = fields[i]).isStatic()) {
+ // local type cannot have static fields
+ } else {
+ field.traverse(visitor, initializerScope);
+ }
+ }
+ }
+ if (methods != null) {
+ methodsLength = methods.length;
+ for (int i = 0; i < methodsLength; i++)
+ methods[i].traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, blockScope);
+ } catch (AbortType e) {
+ }
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java b/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
index d28f16d..1ab99e0 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
@@ -5,7 +5,6 @@
* All Rights Reserved.
*/
import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
public class Argument extends LocalDeclaration {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
index 7553690..cccdbe3 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
@@ -1,46 +1,45 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class ArrayQualifiedTypeReference extends QualifiedTypeReference {
- int dimensions;
-public ArrayQualifiedTypeReference(char[][] sources , int dim, long[] poss) {
- super( sources , poss);
- dimensions = dim ;
-}
-public ArrayQualifiedTypeReference(char[][] sources , TypeBinding tb, int dim, long[] poss) {
- super( sources , tb, poss);
- dimensions = dim ;
-}
-public int dimensions() {
- return dimensions;
-}
-public TypeBinding getTypeBinding(Scope scope) {
- if (binding != null)
- return binding;
- return scope.createArray(scope.getType(tokens), dimensions);
-}
-public String toStringExpression(int tab){
- /* slow speed */
-
- String s = super.toStringExpression(tab) ;
- if (dimensions == 1 ) return s + "[]"/*nonNLS*/ ;
- for (int i=1 ; i <= dimensions ; i++)
- s = s + "[]"/*nonNLS*/ ;
- return s ;
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
- visitor.visit(this, scope);
- visitor.endVisit(this, scope);
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, ClassScope scope) {
- visitor.visit(this, scope);
- visitor.endVisit(this, scope);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class ArrayQualifiedTypeReference extends QualifiedTypeReference {
+ int dimensions;
+public ArrayQualifiedTypeReference(char[][] sources , int dim, long[] poss) {
+ super( sources , poss);
+ dimensions = dim ;
+}
+public ArrayQualifiedTypeReference(char[][] sources , TypeBinding tb, int dim, long[] poss) {
+ super( sources , tb, poss);
+ dimensions = dim ;
+}
+public int dimensions() {
+ return dimensions;
+}
+public TypeBinding getTypeBinding(Scope scope) {
+ if (binding != null)
+ return binding;
+ return scope.createArray(scope.getType(tokens), dimensions);
+}
+public String toStringExpression(int tab){
+ /* slow speed */
+
+ String s = super.toStringExpression(tab) ;
+ if (dimensions == 1 ) return s + "[]"/*nonNLS*/ ;
+ for (int i=1 ; i <= dimensions ; i++)
+ s = s + "[]"/*nonNLS*/ ;
+ return s ;
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, ClassScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
index 6776245..c1acd4d 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
@@ -1,47 +1,46 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class ArrayTypeReference extends SingleTypeReference {
- public int dimensions;
-/**
- * ArrayTypeReference constructor comment.
- * @param source char[]
- * @param dim int
- * @param pos int
- */
-public ArrayTypeReference(char[] source, int dim, long pos) {
- super(source, pos);
- dimensions = dim ;
-}
-public ArrayTypeReference(char[] source, TypeBinding tb, int dim, long pos) {
- super(source, tb, pos);
- dimensions = dim ;}
-public int dimensions() {
- return dimensions;
-}
-public TypeBinding getTypeBinding(Scope scope) {
- if (binding != null)
- return binding;
- return scope.createArray(scope.getType(token), dimensions);
-}
-public String toStringExpression(int tab){
- /* slow speed */
-
- String s = super.toStringExpression(tab) ;
- if (dimensions == 1 ) return s + "[]"/*nonNLS*/ ;
- for (int i=1 ; i <= dimensions ; i++)
- s = s + "[]"/*nonNLS*/ ;
- return s ;
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
- visitor.visit(this, scope);
- visitor.endVisit(this, scope);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class ArrayTypeReference extends SingleTypeReference {
+ public int dimensions;
+/**
+ * ArrayTypeReference constructor comment.
+ * @param source char[]
+ * @param dim int
+ * @param pos int
+ */
+public ArrayTypeReference(char[] source, int dim, long pos) {
+ super(source, pos);
+ dimensions = dim ;
+}
+public ArrayTypeReference(char[] source, TypeBinding tb, int dim, long pos) {
+ super(source, tb, pos);
+ dimensions = dim ;}
+public int dimensions() {
+ return dimensions;
+}
+public TypeBinding getTypeBinding(Scope scope) {
+ if (binding != null)
+ return binding;
+ return scope.createArray(scope.getType(token), dimensions);
+}
+public String toStringExpression(int tab){
+ /* slow speed */
+
+ String s = super.toStringExpression(tab) ;
+ if (dimensions == 1 ) return s + "[]"/*nonNLS*/ ;
+ for (int i=1 ; i <= dimensions ; i++)
+ s = s + "[]"/*nonNLS*/ ;
+ return s ;
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java b/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
index 1d142c9..4453657 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
@@ -1,122 +1,121 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class Assignment extends Expression {
- public Reference lhs ;
- public Expression expression ;
-public Assignment(Expression lhs, Expression expression) {
- //lhs is always a reference by construction ,
- //but is build as an expression ==> the checkcast cannot fail
-
- this.lhs = (Reference) lhs;
- this.expression = expression ;
-
- sourceStart = lhs.sourceStart;
- sourceEnd = expression.sourceEnd;
-
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
- // record setting a variable: various scenarii are possible, setting an array reference,
- // a field reference, a blank final field reference, a field of an enclosing instance or
- // just a local variable.
-
- return lhs.analyseAssignment(currentScope, flowContext, flowInfo, this, false).unconditionalInits();
-}
-public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
-
- // various scenarii are possible, setting an array reference,
- // a field reference, a blank final field reference, a field of an enclosing instance or
- // just a local variable.
-
- int pc = codeStream.position;
- lhs.generateAssignment(currentScope, codeStream, this, valueRequired); // variable may have been optimized out
- // the lhs is responsible to perform the implicitConversion generation for the assignment since optimized for unused local assignment.
- codeStream.recordPositionsFrom(pc, this);
-}
-public TypeBinding resolveType(BlockScope scope) {
- // due to syntax lhs may be only a NameReference, a FieldReference or an ArrayReference
-
- constant = NotAConstant;
- TypeBinding lhsTb = lhs.resolveType(scope);
- TypeBinding expressionTb = expression.resolveType(scope);
- if (lhsTb == null || expressionTb == null)
- return null;
-
- // Compile-time conversion of base-types : implicit narrowing integer into byte/short/character
- // may require to widen the rhs expression at runtime
- if ((expression.isConstantValueOfTypeAssignableToType(expressionTb, lhsTb) ||
- (lhsTb.isBaseType() && BaseTypeBinding.isWidening(lhsTb.id, expressionTb.id))) ||
- (scope.areTypesCompatible(expressionTb, lhsTb))) {
- expression.implicitWidening(lhsTb, expressionTb);
- return lhsTb;
- }
- scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionTb, lhsTb);
- return null;
-
-
- /*------------code deported to the flow analysis-------------------
- if (lhs.isFieldReference()) {
- // cover also the case of a nameReference that refers to a field...(of course !...)
- if (lhsTb.isFinal()) {
- // if the field is final, then the assignment may be done only in constructors/initializers
- // (this does not insure that the assignment is valid....the flow analysis will tell so)
- if (scope.enclosingType() == lhs.fieldBinding().declaringClass) {
- scope.problemReporter().cannotAssignToFinalField(this, lhs.fieldBinding());
- return null;
- }
- if (!scope.enclosingMethod().isConstructorOrInintilizer()) {
- scope.problemReporter().cannotAssignToFinalField(this, lhs.fieldBinding());
- return null;
- }
- }
- }
- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
-
- /*----------------------------------------------------------------
- the code that test if the local is an outer local (it is by definition final)
- and thus cannot be assigned , has been moved to flow analysis
- ------------------------------------------------------------------*/
-
- /*-----------------------------------------------------------------
- The code that detect the a.b = a.b + 1 ; is done by the flow analysis too
- -------------------------------------------------------------------*/
-}
-public String toString(int tab){
- /* slow code*/
-
- //no () when used as a statement
-
- return tabString(tab) + toStringExpressionNoParenthesis() ; }
-public String toStringExpression(){
- /* slow code*/
-
- //subclass redefine toStringExpressionNoParenthesis()
-
- return "("/*nonNLS*/ + toStringExpressionNoParenthesis() + ")"/*nonNLS*/; }
-public String toStringExpressionNoParenthesis() {
-
- return lhs.toStringExpression() + " "/*nonNLS*/ +
- "="/*nonNLS*/ +
-
- ( (expression.constant != null ) && (expression.constant != NotAConstant) ?
- " /*cst:"/*nonNLS*/+expression.constant.toString()+"*/ "/*nonNLS*/ :
- " "/*nonNLS*/ ) +
-
- expression.toStringExpression() ; }
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
- if (visitor.visit(this, scope)) {
- lhs.traverse(visitor, scope);
- expression.traverse(visitor, scope);
- }
- visitor.endVisit(this, scope);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class Assignment extends Expression {
+ public Reference lhs ;
+ public Expression expression ;
+public Assignment(Expression lhs, Expression expression) {
+ //lhs is always a reference by construction ,
+ //but is build as an expression ==> the checkcast cannot fail
+
+ this.lhs = (Reference) lhs;
+ this.expression = expression ;
+
+ sourceStart = lhs.sourceStart;
+ sourceEnd = expression.sourceEnd;
+
+}
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+ // record setting a variable: various scenarii are possible, setting an array reference,
+ // a field reference, a blank final field reference, a field of an enclosing instance or
+ // just a local variable.
+
+ return lhs.analyseAssignment(currentScope, flowContext, flowInfo, this, false).unconditionalInits();
+}
+public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+
+ // various scenarii are possible, setting an array reference,
+ // a field reference, a blank final field reference, a field of an enclosing instance or
+ // just a local variable.
+
+ int pc = codeStream.position;
+ lhs.generateAssignment(currentScope, codeStream, this, valueRequired); // variable may have been optimized out
+ // the lhs is responsible to perform the implicitConversion generation for the assignment since optimized for unused local assignment.
+ codeStream.recordPositionsFrom(pc, this);
+}
+public TypeBinding resolveType(BlockScope scope) {
+ // due to syntax lhs may be only a NameReference, a FieldReference or an ArrayReference
+
+ constant = NotAConstant;
+ TypeBinding lhsTb = lhs.resolveType(scope);
+ TypeBinding expressionTb = expression.resolveType(scope);
+ if (lhsTb == null || expressionTb == null)
+ return null;
+
+ // Compile-time conversion of base-types : implicit narrowing integer into byte/short/character
+ // may require to widen the rhs expression at runtime
+ if ((expression.isConstantValueOfTypeAssignableToType(expressionTb, lhsTb) ||
+ (lhsTb.isBaseType() && BaseTypeBinding.isWidening(lhsTb.id, expressionTb.id))) ||
+ (scope.areTypesCompatible(expressionTb, lhsTb))) {
+ expression.implicitWidening(lhsTb, expressionTb);
+ return lhsTb;
+ }
+ scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionTb, lhsTb);
+ return null;
+
+
+ /*------------code deported to the flow analysis-------------------
+ if (lhs.isFieldReference()) {
+ // cover also the case of a nameReference that refers to a field...(of course !...)
+ if (lhsTb.isFinal()) {
+ // if the field is final, then the assignment may be done only in constructors/initializers
+ // (this does not insure that the assignment is valid....the flow analysis will tell so)
+ if (scope.enclosingType() == lhs.fieldBinding().declaringClass) {
+ scope.problemReporter().cannotAssignToFinalField(this, lhs.fieldBinding());
+ return null;
+ }
+ if (!scope.enclosingMethod().isConstructorOrInintilizer()) {
+ scope.problemReporter().cannotAssignToFinalField(this, lhs.fieldBinding());
+ return null;
+ }
+ }
+ }
+ -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
+
+ /*----------------------------------------------------------------
+ the code that test if the local is an outer local (it is by definition final)
+ and thus cannot be assigned , has been moved to flow analysis
+ ------------------------------------------------------------------*/
+
+ /*-----------------------------------------------------------------
+ The code that detect the a.b = a.b + 1 ; is done by the flow analysis too
+ -------------------------------------------------------------------*/
+}
+public String toString(int tab){
+ /* slow code*/
+
+ //no () when used as a statement
+
+ return tabString(tab) + toStringExpressionNoParenthesis() ; }
+public String toStringExpression(){
+ /* slow code*/
+
+ //subclass redefine toStringExpressionNoParenthesis()
+
+ return "("/*nonNLS*/ + toStringExpressionNoParenthesis() + ")"/*nonNLS*/; }
+public String toStringExpressionNoParenthesis() {
+
+ return lhs.toStringExpression() + " "/*nonNLS*/ +
+ "="/*nonNLS*/ +
+
+ ( (expression.constant != null ) && (expression.constant != NotAConstant) ?
+ " /*cst:"/*nonNLS*/+expression.constant.toString()+"*/ "/*nonNLS*/ :
+ " "/*nonNLS*/ ) +
+
+ expression.toStringExpression() ; }
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ lhs.traverse(visitor, scope);
+ expression.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/AstNode.java b/compiler/org/eclipse/jdt/internal/compiler/ast/AstNode.java
index a233a1f..06b8a39 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/AstNode.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/AstNode.java
@@ -5,9 +5,7 @@
* All Rights Reserved.
*/
import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
public abstract class AstNode implements BaseTypes, CompilerModifiers, TypeConstants, TypeIds {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java b/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
index 2443f2b..0033cd5 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
@@ -1,129 +1,128 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class Block extends Statement {
- public Statement[] statements;
- public int explicitDeclarations; // the number of explicit declaration , used to create scope
- public BlockScope scope;
- public static final Block None = new Block(0);
-public Block(int explicitDeclarations) {
- this.explicitDeclarations = explicitDeclarations;
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-
- // iterate on statements
-
- // empty block
- if (statements == null)
- return flowInfo;
- for (int i = 0, max = statements.length; i < max; i++) {
- Statement stat;
- if (!flowInfo.complainIfUnreachable((stat = statements[i]), scope)) {
- flowInfo = stat.analyseCode(scope, flowContext, flowInfo);
- }
- }
- return flowInfo;
-}
-public static final Block EmptyWith(int sourceStart, int sourceEnd) {
- //return an empty block which position is s and e
-
- Block bk = new Block(0);
- bk.sourceStart = sourceStart;
- bk.sourceEnd = sourceEnd;
- return bk;
-}
-/**
- * Code generation for a block
- * i.e. propagate to statements
- */
-public void generateCode(BlockScope currentScope, CodeStream codeStream) {
- if ((bits & IsReachableMASK) == 0) {
- return;
- }
- int pc = codeStream.position;
- if (statements != null) {
- for (int i = 0, max = statements.length; i < max; i++) {
- statements[i].generateCode(scope, codeStream);
- }
- } // for local variable debug attributes
- if (scope != currentScope){ // was really associated with its own scope
- codeStream.exitUserScope(scope);
- }
- codeStream.recordPositionsFrom(pc, this);
-}
-public boolean isEmptyBlock(){
- return statements == null;
-}
-public void resolve(BlockScope upperScope) {
- if (statements != null) {
- scope = explicitDeclarations == 0 ? upperScope : new BlockScope(upperScope, explicitDeclarations);
- int i = 0, length = statements.length;
- while (i < length)
- statements[i++].resolve(scope);
- }
-}
-public void resolveUsing(BlockScope givenScope) {
- // this optimized resolve(...) is sent only on none empty blocks
-
- scope = givenScope;
- if (statements != null) {
- int i = 0, length = statements.length;
- while (i < length)
- statements[i++].resolve(scope);
- }
-}
-public String toString(int tab) {
- /* slow code */
-
- String s = tabString(tab);
- if (this.statements == null) {
- s += "{\n"/*nonNLS*/;
- s += tabString(tab);
- s += "}"/*nonNLS*/;
- return s;
- }
-
- // s = s + (explicitDeclarations != 0
- // ? " { // ---scope needed for "+String.valueOf(explicitDeclarations) +" locals------------ \n"
- // : "{// ---NO scope needed------ \n") ;
-
- s += "{\n"/*nonNLS*/;
- s += this.toStringStatements(tab);
- s += tabString(tab);
- s += "}"/*nonNLS*/;
- return s;
-}
-public String toStringStatements(int tab) {
- /* slow code */
- if (this.statements == null) return ""/*nonNLS*/;
- StringBuffer buffer = new StringBuffer();
- for (int i = 0; i < statements.length; i++) {
- buffer.append(statements[i].toString(tab + 1));
- if (statements[i] instanceof Block){
- buffer.append("\n"/*nonNLS*/);
- } else {
- buffer.append(";\n"/*nonNLS*/);
- }
- };
- return buffer.toString();
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
- if (visitor.visit(this, blockScope)) {
- if (statements != null) {
- int statementLength = statements.length;
- for (int i = 0; i < statementLength; i++)
- statements[i].traverse(visitor, scope);
- }
- }
- visitor.endVisit(this, blockScope);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class Block extends Statement {
+ public Statement[] statements;
+ public int explicitDeclarations; // the number of explicit declaration , used to create scope
+ public BlockScope scope;
+ public static final Block None = new Block(0);
+public Block(int explicitDeclarations) {
+ this.explicitDeclarations = explicitDeclarations;
+}
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+ // iterate on statements
+
+ // empty block
+ if (statements == null)
+ return flowInfo;
+ for (int i = 0, max = statements.length; i < max; i++) {
+ Statement stat;
+ if (!flowInfo.complainIfUnreachable((stat = statements[i]), scope)) {
+ flowInfo = stat.analyseCode(scope, flowContext, flowInfo);
+ }
+ }
+ return flowInfo;
+}
+public static final Block EmptyWith(int sourceStart, int sourceEnd) {
+ //return an empty block which position is s and e
+
+ Block bk = new Block(0);
+ bk.sourceStart = sourceStart;
+ bk.sourceEnd = sourceEnd;
+ return bk;
+}
+/**
+ * Code generation for a block
+ * i.e. propagate to statements
+ */
+public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+ if ((bits & IsReachableMASK) == 0) {
+ return;
+ }
+ int pc = codeStream.position;
+ if (statements != null) {
+ for (int i = 0, max = statements.length; i < max; i++) {
+ statements[i].generateCode(scope, codeStream);
+ }
+ } // for local variable debug attributes
+ if (scope != currentScope){ // was really associated with its own scope
+ codeStream.exitUserScope(scope);
+ }
+ codeStream.recordPositionsFrom(pc, this);
+}
+public boolean isEmptyBlock(){
+ return statements == null;
+}
+public void resolve(BlockScope upperScope) {
+ if (statements != null) {
+ scope = explicitDeclarations == 0 ? upperScope : new BlockScope(upperScope, explicitDeclarations);
+ int i = 0, length = statements.length;
+ while (i < length)
+ statements[i++].resolve(scope);
+ }
+}
+public void resolveUsing(BlockScope givenScope) {
+ // this optimized resolve(...) is sent only on none empty blocks
+
+ scope = givenScope;
+ if (statements != null) {
+ int i = 0, length = statements.length;
+ while (i < length)
+ statements[i++].resolve(scope);
+ }
+}
+public String toString(int tab) {
+ /* slow code */
+
+ String s = tabString(tab);
+ if (this.statements == null) {
+ s += "{\n"/*nonNLS*/;
+ s += tabString(tab);
+ s += "}"/*nonNLS*/;
+ return s;
+ }
+
+ // s = s + (explicitDeclarations != 0
+ // ? " { // ---scope needed for "+String.valueOf(explicitDeclarations) +" locals------------ \n"
+ // : "{// ---NO scope needed------ \n") ;
+
+ s += "{\n"/*nonNLS*/;
+ s += this.toStringStatements(tab);
+ s += tabString(tab);
+ s += "}"/*nonNLS*/;
+ return s;
+}
+public String toStringStatements(int tab) {
+ /* slow code */
+ if (this.statements == null) return ""/*nonNLS*/;
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < statements.length; i++) {
+ buffer.append(statements[i].toString(tab + 1));
+ if (statements[i] instanceof Block){
+ buffer.append("\n"/*nonNLS*/);
+ } else {
+ buffer.append(";\n"/*nonNLS*/);
+ }
+ };
+ return buffer.toString();
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+ if (visitor.visit(this, blockScope)) {
+ if (statements != null) {
+ int statementLength = statements.length;
+ for (int i = 0; i < statementLength; i++)
+ statements[i].traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, blockScope);
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java b/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java
index ee3f29f..f339cab 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java
@@ -1,58 +1,57 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public abstract class BranchStatement extends Statement {
- public char[] label;
- public Label targetLabel;
- public AstNode[] subroutines;
-/**
- * BranchStatement constructor comment.
- */
-public BranchStatement(char[] l, int s,int e) {
- label = l ;
- sourceStart = s;
- sourceEnd = e;
-}
-/**
- * Branch code generation
- *
- * generate the finallyInvocationSequence.
- */
-public void generateCode(BlockScope currentScope, CodeStream codeStream) {
-
- if ((bits & IsReachableMASK) == 0) {
- return;
- }
- int pc = codeStream.position;
-
- // generation of code responsible for invoking the finally
- // blocks in sequence
- if (subroutines != null){
- for (int i = 0, max = subroutines.length; i < max; i++){
- AstNode sub;
- if ((sub = subroutines[i]) instanceof SynchronizedStatement){
- codeStream.load(((SynchronizedStatement)sub).synchroVariable);
- codeStream.monitorexit();
- } else {
- TryStatement trySub = (TryStatement) sub;
- if (trySub.subRoutineCannotReturn) {
- codeStream.goto_(trySub.subRoutineStartLabel);
- codeStream.recordPositionsFrom(pc, this);
- return;
- } else {
- codeStream.jsr(trySub.subRoutineStartLabel);
- }
- }
- }
- }
- codeStream.goto_(targetLabel);
- codeStream.recordPositionsFrom(pc, this);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public abstract class BranchStatement extends Statement {
+ public char[] label;
+ public Label targetLabel;
+ public AstNode[] subroutines;
+/**
+ * BranchStatement constructor comment.
+ */
+public BranchStatement(char[] l, int s,int e) {
+ label = l ;
+ sourceStart = s;
+ sourceEnd = e;
+}
+/**
+ * Branch code generation
+ *
+ * generate the finallyInvocationSequence.
+ */
+public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+
+ if ((bits & IsReachableMASK) == 0) {
+ return;
+ }
+ int pc = codeStream.position;
+
+ // generation of code responsible for invoking the finally
+ // blocks in sequence
+ if (subroutines != null){
+ for (int i = 0, max = subroutines.length; i < max; i++){
+ AstNode sub;
+ if ((sub = subroutines[i]) instanceof SynchronizedStatement){
+ codeStream.load(((SynchronizedStatement)sub).synchroVariable);
+ codeStream.monitorexit();
+ } else {
+ TryStatement trySub = (TryStatement) sub;
+ if (trySub.subRoutineCannotReturn) {
+ codeStream.goto_(trySub.subRoutineStartLabel);
+ codeStream.recordPositionsFrom(pc, this);
+ return;
+ } else {
+ codeStream.jsr(trySub.subRoutineStartLabel);
+ }
+ }
+ }
+ }
+ codeStream.goto_(targetLabel);
+ codeStream.recordPositionsFrom(pc, this);
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/Break.java b/compiler/org/eclipse/jdt/internal/compiler/ast/Break.java
index 1a1786e..885b33b 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/Break.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/Break.java
@@ -1,77 +1,76 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class Break extends BranchStatement {
-public Break(char[] label, int sourceStart, int e) {
- super(label, sourceStart,e);
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-
- // here requires to generate a sequence of finally blocks invocations depending corresponding
- // to each of the traversed try statements, so that execution will terminate properly.
-
- // lookup the label, this should answer the returnContext
- FlowContext targetContext;
- if (label == null) {
- targetContext = flowContext.getTargetContextForDefaultBreak();
- } else {
- targetContext = flowContext.getTargetContextForBreakLabel(label);
- }
- if (targetContext == null) {
- if (label == null) {
- currentScope.problemReporter().invalidBreak(this);
- } else {
- currentScope.problemReporter().undefinedLabel(this); // need to improve
- }
- } else {
- targetLabel = targetContext.breakLabel();
- targetContext.recordBreakFrom(flowInfo);
- FlowContext traversedContext = flowContext;
- int subIndex = 0, maxSub = 5;
- subroutines = new AstNode[maxSub];
- while (true) {
- AstNode sub;
- if ((sub = traversedContext.subRoutine()) != null) {
- if (subIndex == maxSub) {
- System.arraycopy(subroutines, 0, (subroutines = new AstNode[maxSub *= 2]), 0, subIndex); // grow
- }
- subroutines[subIndex++] = sub;
- if (sub.cannotReturn()) {
- break;
- }
- }
- if (traversedContext == targetContext) {
- break;
- } else {
- traversedContext = traversedContext.parent;
- }
- }
- // resize subroutines
- if (subIndex != maxSub) {
- System.arraycopy(subroutines, 0, (subroutines = new AstNode[subIndex]), 0, subIndex);
- }
- }
- return FlowInfo.DeadEnd;
-}
-public String toString(int tab){
- /* slow code */
-
- String s = tabString(tab) ;
- s = s + "break "/*nonNLS*/;
- if (label != null )
- s = s + new String(label) ;
- return s;
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockscope) {
- visitor.visit(this, blockscope);
- visitor.endVisit(this, blockscope);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class Break extends BranchStatement {
+public Break(char[] label, int sourceStart, int e) {
+ super(label, sourceStart,e);
+}
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+ // here requires to generate a sequence of finally blocks invocations depending corresponding
+ // to each of the traversed try statements, so that execution will terminate properly.
+
+ // lookup the label, this should answer the returnContext
+ FlowContext targetContext;
+ if (label == null) {
+ targetContext = flowContext.getTargetContextForDefaultBreak();
+ } else {
+ targetContext = flowContext.getTargetContextForBreakLabel(label);
+ }
+ if (targetContext == null) {
+ if (label == null) {
+ currentScope.problemReporter().invalidBreak(this);
+ } else {
+ currentScope.problemReporter().undefinedLabel(this); // need to improve
+ }
+ } else {
+ targetLabel = targetContext.breakLabel();
+ targetContext.recordBreakFrom(flowInfo);
+ FlowContext traversedContext = flowContext;
+ int subIndex = 0, maxSub = 5;
+ subroutines = new AstNode[maxSub];
+ while (true) {
+ AstNode sub;
+ if ((sub = traversedContext.subRoutine()) != null) {
+ if (subIndex == maxSub) {
+ System.arraycopy(subroutines, 0, (subroutines = new AstNode[maxSub *= 2]), 0, subIndex); // grow
+ }
+ subroutines[subIndex++] = sub;
+ if (sub.cannotReturn()) {
+ break;
+ }
+ }
+ if (traversedContext == targetContext) {
+ break;
+ } else {
+ traversedContext = traversedContext.parent;
+ }
+ }
+ // resize subroutines
+ if (subIndex != maxSub) {
+ System.arraycopy(subroutines, 0, (subroutines = new AstNode[subIndex]), 0, subIndex);
+ }
+ }
+ return FlowInfo.DeadEnd;
+}
+public String toString(int tab){
+ /* slow code */
+
+ String s = tabString(tab) ;
+ s = s + "break "/*nonNLS*/;
+ if (label != null )
+ s = s + new String(label) ;
+ return s;
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockscope) {
+ visitor.visit(this, blockscope);
+ visitor.endVisit(this, blockscope);
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
index 6ceaa8d..df4149e 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
@@ -1,246 +1,244 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.compiler.util.*;
-
-public class CastExpression extends Expression {
- public Expression expression;
- public Expression type;
- public boolean needRuntimeCheckcast ;
- public TypeBinding castTb ;
-
- //expression.implicitConversion holds the cast for baseType casting
-
-
-
-public CastExpression(Expression e , Expression t) {
- expression = e ;
- type = t ;
-
- //due to the fact an expression may start with ( and that a cast also start with (
- //the field is an expression....it can be a TypeReference OR a NameReference Or
- //an expression <--this last one is invalid.......
-
- // :-( .............
-
- //if (type instanceof TypeReference )
- // flag = IsTypeReference ;
- //else
- // if (type instanceof NameReference)
- // flag = IsNameReference ;
- // else
- // flag = IsExpression ;
-
-
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-
- /* EXTRA REFERENCE RECORDING
- if (!needsRuntimeCheck && (implicitConversion == NoConversion)) {
- // need to manually remember the castType as part of the reference information"
- currentScope.currentMethodDeclaration().recordReferenceTo(type.getTypeBinding());
- }
- */
-
- return expression.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
-}
-public final void areTypesCastCompatible(BlockScope scope, TypeBinding castTb, TypeBinding expressionTb) {
- // see specifications p.68
- // handle errors and process constant when needed
-
- // if either one of the type is null ==>
- // some error has been already reported some where ==>
- // we then do not report an obvious-cascade-error.
-
- needRuntimeCheckcast = false;
- if (castTb == null || expressionTb == null)
- return;
- if (castTb.isBaseType()) {
- if (expressionTb.isBaseType()) {
- if (expressionTb == castTb) {
- constant = expression.constant; //use the same constant
- return;
- }
- if (scope.areTypesCompatible(expressionTb, castTb)
- || BaseTypeBinding.isNarrowing(castTb.id, expressionTb.id)) {
- expression.implicitConversion = (castTb.id << 4) + expressionTb.id;
- if (expression.constant != Constant.NotAConstant)
- constant = expression.constant.castTo(expression.implicitConversion);
- return;
- }
- }
- scope.problemReporter().typeCastError(this, castTb, expressionTb);
- return;
- }
-
- //-----------cast to something which is NOT a base type--------------------------
- if (expressionTb == NullBinding)
- return; //null is compatible with every thing
-
- if (expressionTb.isBaseType()) {
- scope.problemReporter().typeCastError(this, castTb, expressionTb);
- return;
- }
-
- if (expressionTb.isArrayType()) {
- if (castTb.isArrayType()) { //------- (castTb.isArray) expressionTb.isArray -----------
- TypeBinding expressionEltTb = ((ArrayBinding) expressionTb).elementsType(scope);
- if (expressionEltTb.isBaseType()) {
- // <---stop the recursion-------
- if (((ArrayBinding) castTb).elementsType(scope) == expressionEltTb)
- needRuntimeCheckcast = true;
- else
- scope.problemReporter().typeCastError(this, castTb, expressionTb);
- return;
- }
- // recursively on the elements...
- areTypesCastCompatible(scope, ((ArrayBinding) castTb).elementsType(scope), expressionEltTb);
- return;
- } else if (castTb.isClass()) { //------(castTb.isClass) expressionTb.isArray ---------------
- if (scope.isJavaLangObject(castTb))
- return;
- } else { //------- (castTb.isInterface) expressionTb.isArray -----------
- if (scope.isJavaLangCloneable(castTb) || scope.isJavaIoSerializable(castTb)) {
- needRuntimeCheckcast = true;
- return;
- }
- }
- scope.problemReporter().typeCastError(this, castTb, expressionTb);
- return;
- }
-
- if (expressionTb.isClass()) {
- if (castTb.isArrayType()) { // ---- (castTb.isArray) expressionTb.isClass -------
- if (scope.isJavaLangObject(expressionTb)) { // potential runtime error
- needRuntimeCheckcast = true;
- return;
- }
- } else if (castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isClass ------
- if (scope.areTypesCompatible(expressionTb, castTb)) // no runtime error
- return;
- if (scope.areTypesCompatible(castTb, expressionTb)) { // potential runtime error
- needRuntimeCheckcast = true;
- return;
- }
- } else { // ----- (castTb.isInterface) expressionTb.isClass -------
- if (((ReferenceBinding) expressionTb).isFinal()) { // no subclass for expressionTb, thus compile-time check is valid
- if (scope.areTypesCompatible(expressionTb, castTb))
- return;
- } else { // a subclass may implement the interface ==> no check at compile time
- needRuntimeCheckcast = true;
- return;
- }
- }
- scope.problemReporter().typeCastError(this, castTb, expressionTb);
- return;
- }
-
-// if (expressionTb.isInterface()) { cannot be anything else
- if (castTb.isArrayType()) { // ----- (castTb.isArray) expressionTb.isInterface ------
- if (scope.isJavaLangCloneable(expressionTb) || scope.isJavaIoSerializable(expressionTb)) // potential runtime error
- needRuntimeCheckcast = true;
- else
- scope.problemReporter().typeCastError(this, castTb, expressionTb);
- return;
- } else if (castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isInterface --------
- if (scope.isJavaLangObject(castTb)) // no runtime error
- return;
- if (((ReferenceBinding) castTb).isFinal()) { // no subclass for castTb, thus compile-time check is valid
- if (!scope.areTypesCompatible(castTb, expressionTb)) { // potential runtime error
- scope.problemReporter().typeCastError(this, castTb, expressionTb);
- return;
- }
- }
- } else { // ----- (castTb.isInterface) expressionTb.isInterface -------
- if (castTb != expressionTb && (scope.compareTypes(castTb, expressionTb) == NotRelated)) {
- MethodBinding[] castTbMethods = ((ReferenceBinding) castTb).methods();
- MethodBinding[] expressionTbMethods = ((ReferenceBinding) expressionTb).methods();
- int exprMethodsLength = expressionTbMethods.length;
- for (int i = 0, castMethodsLength = castTbMethods.length; i < castMethodsLength; i++)
- for (int j = 0; j < exprMethodsLength; j++)
- if (castTbMethods[i].returnType != expressionTbMethods[j].returnType)
- if (castTbMethods[i].selector == expressionTbMethods[j].selector)
- if (castTbMethods[i].areParametersEqual(expressionTbMethods[j]))
- scope.problemReporter().typeCastError(this, castTb, expressionTb);
- }
- }
- needRuntimeCheckcast = true;
- return;
-}
-/**
- * Cast expression code generation
- *
- * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param valueRequired boolean
- */
-public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
- int pc = codeStream.position;
- if (constant != NotAConstant) {
- if (valueRequired || needRuntimeCheckcast) { // Added for: 1F1W9IG: IVJCOM:WINNT - Compiler omits casting check
- codeStream.generateConstant(constant, implicitConversion);
- if (needRuntimeCheckcast) {
- codeStream.checkcast(castTb);
- if (!valueRequired)
- codeStream.pop();
- }
- }
- codeStream.recordPositionsFrom(pc, this);
- return;
- }
- expression.generateCode(currentScope, codeStream, valueRequired || needRuntimeCheckcast);
- if (needRuntimeCheckcast) {
- codeStream.checkcast(castTb);
- if (!valueRequired)
- codeStream.pop();
- } else {
- if (valueRequired)
- codeStream.generateImplicitConversion(implicitConversion);
- }
- codeStream.recordPositionsFrom(pc, this);
-}
-public TypeBinding resolveType(BlockScope scope) {
- // compute a new constant if the cast is effective
-
- // due to the fact an expression may start with ( and that a cast can also start with (
- // the field is an expression....it can be a TypeReference OR a NameReference Or
- // any kind of Expression <-- this last one is invalid.......
-
- constant = Constant.NotAConstant;
- implicitConversion = T_undefined;
- TypeBinding expressionTb = expression.resolveType(scope);
- if (expressionTb == null)
- return null;
-
- if ((type instanceof TypeReference) || (type instanceof NameReference)) {
- if ((castTb = type.resolveType(scope)) == null)
- return null;
- areTypesCastCompatible(scope, castTb, expressionTb);
- return castTb;
- } else { // expression as a cast !!!!!!!!
- scope.problemReporter().invalidTypeReference(type);
- return null;
- }
-}
-public String toStringExpression(){
- /*slow code*/
-
- return "("/*nonNLS*/ + type.toString(0)+ ") "/*nonNLS*/ +
- expression.toStringExpression() ; }
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
- if (visitor.visit(this, blockScope)) {
- type.traverse(visitor, blockScope);
- expression.traverse(visitor, blockScope);
- }
- visitor.endVisit(this, blockScope);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class CastExpression extends Expression {
+ public Expression expression;
+ public Expression type;
+ public boolean needRuntimeCheckcast ;
+ public TypeBinding castTb ;
+
+ //expression.implicitConversion holds the cast for baseType casting
+
+
+
+public CastExpression(Expression e , Expression t) {
+ expression = e ;
+ type = t ;
+
+ //due to the fact an expression may start with ( and that a cast also start with (
+ //the field is an expression....it can be a TypeReference OR a NameReference Or
+ //an expression <--this last one is invalid.......
+
+ // :-( .............
+
+ //if (type instanceof TypeReference )
+ // flag = IsTypeReference ;
+ //else
+ // if (type instanceof NameReference)
+ // flag = IsNameReference ;
+ // else
+ // flag = IsExpression ;
+
+
+}
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+ /* EXTRA REFERENCE RECORDING
+ if (!needsRuntimeCheck && (implicitConversion == NoConversion)) {
+ // need to manually remember the castType as part of the reference information"
+ currentScope.currentMethodDeclaration().recordReferenceTo(type.getTypeBinding());
+ }
+ */
+
+ return expression.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+}
+public final void areTypesCastCompatible(BlockScope scope, TypeBinding castTb, TypeBinding expressionTb) {
+ // see specifications p.68
+ // handle errors and process constant when needed
+
+ // if either one of the type is null ==>
+ // some error has been already reported some where ==>
+ // we then do not report an obvious-cascade-error.
+
+ needRuntimeCheckcast = false;
+ if (castTb == null || expressionTb == null)
+ return;
+ if (castTb.isBaseType()) {
+ if (expressionTb.isBaseType()) {
+ if (expressionTb == castTb) {
+ constant = expression.constant; //use the same constant
+ return;
+ }
+ if (scope.areTypesCompatible(expressionTb, castTb)
+ || BaseTypeBinding.isNarrowing(castTb.id, expressionTb.id)) {
+ expression.implicitConversion = (castTb.id << 4) + expressionTb.id;
+ if (expression.constant != Constant.NotAConstant)
+ constant = expression.constant.castTo(expression.implicitConversion);
+ return;
+ }
+ }
+ scope.problemReporter().typeCastError(this, castTb, expressionTb);
+ return;
+ }
+
+ //-----------cast to something which is NOT a base type--------------------------
+ if (expressionTb == NullBinding)
+ return; //null is compatible with every thing
+
+ if (expressionTb.isBaseType()) {
+ scope.problemReporter().typeCastError(this, castTb, expressionTb);
+ return;
+ }
+
+ if (expressionTb.isArrayType()) {
+ if (castTb.isArrayType()) { //------- (castTb.isArray) expressionTb.isArray -----------
+ TypeBinding expressionEltTb = ((ArrayBinding) expressionTb).elementsType(scope);
+ if (expressionEltTb.isBaseType()) {
+ // <---stop the recursion-------
+ if (((ArrayBinding) castTb).elementsType(scope) == expressionEltTb)
+ needRuntimeCheckcast = true;
+ else
+ scope.problemReporter().typeCastError(this, castTb, expressionTb);
+ return;
+ }
+ // recursively on the elements...
+ areTypesCastCompatible(scope, ((ArrayBinding) castTb).elementsType(scope), expressionEltTb);
+ return;
+ } else if (castTb.isClass()) { //------(castTb.isClass) expressionTb.isArray ---------------
+ if (scope.isJavaLangObject(castTb))
+ return;
+ } else { //------- (castTb.isInterface) expressionTb.isArray -----------
+ if (scope.isJavaLangCloneable(castTb) || scope.isJavaIoSerializable(castTb)) {
+ needRuntimeCheckcast = true;
+ return;
+ }
+ }
+ scope.problemReporter().typeCastError(this, castTb, expressionTb);
+ return;
+ }
+
+ if (expressionTb.isClass()) {
+ if (castTb.isArrayType()) { // ---- (castTb.isArray) expressionTb.isClass -------
+ if (scope.isJavaLangObject(expressionTb)) { // potential runtime error
+ needRuntimeCheckcast = true;
+ return;
+ }
+ } else if (castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isClass ------
+ if (scope.areTypesCompatible(expressionTb, castTb)) // no runtime error
+ return;
+ if (scope.areTypesCompatible(castTb, expressionTb)) { // potential runtime error
+ needRuntimeCheckcast = true;
+ return;
+ }
+ } else { // ----- (castTb.isInterface) expressionTb.isClass -------
+ if (((ReferenceBinding) expressionTb).isFinal()) { // no subclass for expressionTb, thus compile-time check is valid
+ if (scope.areTypesCompatible(expressionTb, castTb))
+ return;
+ } else { // a subclass may implement the interface ==> no check at compile time
+ needRuntimeCheckcast = true;
+ return;
+ }
+ }
+ scope.problemReporter().typeCastError(this, castTb, expressionTb);
+ return;
+ }
+
+// if (expressionTb.isInterface()) { cannot be anything else
+ if (castTb.isArrayType()) { // ----- (castTb.isArray) expressionTb.isInterface ------
+ if (scope.isJavaLangCloneable(expressionTb) || scope.isJavaIoSerializable(expressionTb)) // potential runtime error
+ needRuntimeCheckcast = true;
+ else
+ scope.problemReporter().typeCastError(this, castTb, expressionTb);
+ return;
+ } else if (castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isInterface --------
+ if (scope.isJavaLangObject(castTb)) // no runtime error
+ return;
+ if (((ReferenceBinding) castTb).isFinal()) { // no subclass for castTb, thus compile-time check is valid
+ if (!scope.areTypesCompatible(castTb, expressionTb)) { // potential runtime error
+ scope.problemReporter().typeCastError(this, castTb, expressionTb);
+ return;
+ }
+ }
+ } else { // ----- (castTb.isInterface) expressionTb.isInterface -------
+ if (castTb != expressionTb && (scope.compareTypes(castTb, expressionTb) == NotRelated)) {
+ MethodBinding[] castTbMethods = ((ReferenceBinding) castTb).methods();
+ MethodBinding[] expressionTbMethods = ((ReferenceBinding) expressionTb).methods();
+ int exprMethodsLength = expressionTbMethods.length;
+ for (int i = 0, castMethodsLength = castTbMethods.length; i < castMethodsLength; i++)
+ for (int j = 0; j < exprMethodsLength; j++)
+ if (castTbMethods[i].returnType != expressionTbMethods[j].returnType)
+ if (castTbMethods[i].selector == expressionTbMethods[j].selector)
+ if (castTbMethods[i].areParametersEqual(expressionTbMethods[j]))
+ scope.problemReporter().typeCastError(this, castTb, expressionTb);
+ }
+ }
+ needRuntimeCheckcast = true;
+ return;
+}
+/**
+ * Cast expression code generation
+ *
+ * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param valueRequired boolean
+ */
+public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+ int pc = codeStream.position;
+ if (constant != NotAConstant) {
+ if (valueRequired || needRuntimeCheckcast) { // Added for: 1F1W9IG: IVJCOM:WINNT - Compiler omits casting check
+ codeStream.generateConstant(constant, implicitConversion);
+ if (needRuntimeCheckcast) {
+ codeStream.checkcast(castTb);
+ if (!valueRequired)
+ codeStream.pop();
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this);
+ return;
+ }
+ expression.generateCode(currentScope, codeStream, valueRequired || needRuntimeCheckcast);
+ if (needRuntimeCheckcast) {
+ codeStream.checkcast(castTb);
+ if (!valueRequired)
+ codeStream.pop();
+ } else {
+ if (valueRequired)
+ codeStream.generateImplicitConversion(implicitConversion);
+ }
+ codeStream.recordPositionsFrom(pc, this);
+}
+public TypeBinding resolveType(BlockScope scope) {
+ // compute a new constant if the cast is effective
+
+ // due to the fact an expression may start with ( and that a cast can also start with (
+ // the field is an expression....it can be a TypeReference OR a NameReference Or
+ // any kind of Expression <-- this last one is invalid.......
+
+ constant = Constant.NotAConstant;
+ implicitConversion = T_undefined;
+ TypeBinding expressionTb = expression.resolveType(scope);
+ if (expressionTb == null)
+ return null;
+
+ if ((type instanceof TypeReference) || (type instanceof NameReference)) {
+ if ((castTb = type.resolveType(scope)) == null)
+ return null;
+ areTypesCastCompatible(scope, castTb, expressionTb);
+ return castTb;
+ } else { // expression as a cast !!!!!!!!
+ scope.problemReporter().invalidTypeReference(type);
+ return null;
+ }
+}
+public String toStringExpression(){
+ /*slow code*/
+
+ return "("/*nonNLS*/ + type.toString(0)+ ") "/*nonNLS*/ +
+ expression.toStringExpression() ; }
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+ if (visitor.visit(this, blockScope)) {
+ type.traverse(visitor, blockScope);
+ expression.traverse(visitor, blockScope);
+ }
+ visitor.endVisit(this, blockScope);
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
index 4521446..8d26653 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
@@ -1,71 +1,70 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class ClassLiteralAccess extends Expression {
- public TypeReference type;
- public TypeBinding targetType;
- FieldBinding syntheticField;
-
-public ClassLiteralAccess(int pos, TypeReference t) {
- type = t;
- sourceEnd = (sourceStart = pos)+4 ; // "class" length - 1
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-
- // if reachable, request the addition of a synthetic field for caching the class descriptor
- SourceTypeBinding sourceType = currentScope.outerMostMethodScope().enclosingSourceType();
- if (!(sourceType.isInterface() // no field generated in interface case (would'nt verify) see 1FHHEZL
- || sourceType.isBaseType())){
- syntheticField = sourceType.addSyntheticField(targetType, currentScope);
- }
- return flowInfo;
-}
-/**
- * MessageSendDotClass code generation
- *
- * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param valueRequired boolean
- */
-public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
- int pc = codeStream.position;
-
- // in interface case, no caching occurs, since cannot make a cache field for interface
- if (valueRequired)
- codeStream.generateClassLiteralAccessForType(type.binding, syntheticField);
- codeStream.recordPositionsFrom(pc, this);
-}
-public TypeBinding resolveType(BlockScope scope) {
- constant = NotAConstant;
- if ((targetType = type.resolveType(scope)) == null)
- return null;
-
- if (targetType.isArrayType() && ((ArrayBinding) targetType).leafComponentType == VoidBinding) {
- scope.problemReporter().cannotAllocateVoidArray(this);
- return null;
- }
-
- return scope.getJavaLangClass();
-}
-public String toStringExpression(){
- /*slow code*/
-
- String s = ""/*nonNLS*/;
- s = s + type.toString(0) + ".class"/*nonNLS*/ ;
- return s;}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
- if (visitor.visit(this, blockScope)) {
- type.traverse(visitor, blockScope);
- }
- visitor.endVisit(this, blockScope);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class ClassLiteralAccess extends Expression {
+ public TypeReference type;
+ public TypeBinding targetType;
+ FieldBinding syntheticField;
+
+public ClassLiteralAccess(int pos, TypeReference t) {
+ type = t;
+ sourceEnd = (sourceStart = pos)+4 ; // "class" length - 1
+}
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+ // if reachable, request the addition of a synthetic field for caching the class descriptor
+ SourceTypeBinding sourceType = currentScope.outerMostMethodScope().enclosingSourceType();
+ if (!(sourceType.isInterface() // no field generated in interface case (would'nt verify) see 1FHHEZL
+ || sourceType.isBaseType())){
+ syntheticField = sourceType.addSyntheticField(targetType, currentScope);
+ }
+ return flowInfo;
+}
+/**
+ * MessageSendDotClass code generation
+ *
+ * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param valueRequired boolean
+ */
+public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+ int pc = codeStream.position;
+
+ // in interface case, no caching occurs, since cannot make a cache field for interface
+ if (valueRequired)
+ codeStream.generateClassLiteralAccessForType(type.binding, syntheticField);
+ codeStream.recordPositionsFrom(pc, this);
+}
+public TypeBinding resolveType(BlockScope scope) {
+ constant = NotAConstant;
+ if ((targetType = type.resolveType(scope)) == null)
+ return null;
+
+ if (targetType.isArrayType() && ((ArrayBinding) targetType).leafComponentType == VoidBinding) {
+ scope.problemReporter().cannotAllocateVoidArray(this);
+ return null;
+ }
+
+ return scope.getJavaLangClass();
+}
+public String toStringExpression(){
+ /*slow code*/
+
+ String s = ""/*nonNLS*/;
+ s = s + type.toString(0) + ".class"/*nonNLS*/ ;
+ return s;}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+ if (visitor.visit(this, blockScope)) {
+ type.traverse(visitor, blockScope);
+ }
+ visitor.endVisit(this, blockScope);
+}
+}