/** * If the given ast node is inside an explicit constructor call * then wrap it with a fake constructor call. * Returns the wrapped completion node or the completion node itself. */ protected ASTNode wrapWithExplicitConstructorCallIfNeeded(ASTNode ast) { int selector; if (ast != null && topKnownElementKind(ASSIST_PARSER) == K_SELECTOR && ast instanceof Expression && (((selector = topKnownElementInfo(ASSIST_PARSER)) == THIS_CONSTRUCTOR) || (selector == SUPER_CONSTRUCTOR))) { ExplicitConstructorCall call = new ExplicitConstructorCall( (selector == THIS_CONSTRUCTOR) ? ExplicitConstructorCall.This : ExplicitConstructorCall.Super ); call.arguments = new Expression[] {(Expression)ast}; call.sourceStart = ast.sourceStart; call.sourceEnd = ast.sourceEnd; return call; } else { return ast; } }
public void unhandledException(TypeBinding exceptionType, ASTNode location) { boolean insideDefaultConstructor = (this.referenceContext instanceof ConstructorDeclaration) && ((ConstructorDeclaration)this.referenceContext).isDefaultConstructor(); boolean insideImplicitConstructorCall = (location instanceof ExplicitConstructorCall) && (((ExplicitConstructorCall) location).accessMode == ExplicitConstructorCall.ImplicitSuper); int sourceEnd = location.sourceEnd; if (location instanceof LocalDeclaration) { sourceEnd = ((LocalDeclaration) location).declarationEnd; } this.handle( insideDefaultConstructor ? IProblem.UnhandledExceptionInDefaultConstructor : (insideImplicitConstructorCall ? IProblem.UndefinedConstructorInImplicitConstructorCall : IProblem.UnhandledException), new String[] {new String(exceptionType.readableName())}, new String[] {new String(exceptionType.shortReadableName())}, location.sourceStart, sourceEnd); }
private void createPrivateDefaultConstructor(EclipseNode typeNode, EclipseNode sourceNode) { ASTNode source = sourceNode.get(); TypeDeclaration typeDeclaration = ((TypeDeclaration) typeNode.get()); long p = (long) source.sourceStart << 32 | source.sourceEnd; ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) typeNode.top().get()).compilationResult); constructor.modifiers = ClassFileConstants.AccPrivate; constructor.selector = typeDeclaration.name; constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper); constructor.constructorCall.sourceStart = source.sourceStart; constructor.constructorCall.sourceEnd = source.sourceEnd; constructor.thrownExceptions = null; constructor.typeParameters = null; constructor.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart; constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd; constructor.arguments = null; AllocationExpression exception = new AllocationExpression(); setGeneratedBy(exception, source); long[] ps = new long[JAVA_LANG_UNSUPPORTED_OPERATION_EXCEPTION.length]; Arrays.fill(ps, p); exception.type = new QualifiedTypeReference(JAVA_LANG_UNSUPPORTED_OPERATION_EXCEPTION, ps); setGeneratedBy(exception.type, source); exception.arguments = new Expression[] { new StringLiteral(UNSUPPORTED_MESSAGE, source.sourceStart, source.sourceEnd, 0) }; setGeneratedBy(exception.arguments[0], source); ThrowStatement throwStatement = new ThrowStatement(exception, source.sourceStart, source.sourceEnd); setGeneratedBy(throwStatement, source); constructor.statements = new Statement[] {throwStatement}; injectMethod(typeNode, constructor); }
public void handleMethod(EclipseNode annotation, AbstractMethodDeclaration method, List<DeclaredException> exceptions) { if (method.isAbstract()) { annotation.addError("@SneakyThrows can only be used on concrete methods."); return; } if (method.statements == null || method.statements.length == 0) { boolean hasConstructorCall = false; if (method instanceof ConstructorDeclaration) { ExplicitConstructorCall constructorCall = ((ConstructorDeclaration) method).constructorCall; hasConstructorCall = constructorCall != null && !constructorCall.isImplicitSuper() && !constructorCall.isImplicitThis(); } if (hasConstructorCall) { annotation.addWarning("Calls to sibling / super constructors are always excluded from @SneakyThrows; @SneakyThrows has been ignored because there is no other code in this constructor."); } else { annotation.addWarning("This method or constructor is empty; @SneakyThrows has been ignored."); } return; } Statement[] contents = method.statements; for (DeclaredException exception : exceptions) { contents = new Statement[] { buildTryCatchBlock(contents, exception, exception.node, method) }; } method.statements = contents; annotation.up().rebuild(); }
@Override @Nullable public ResolvedNode resolve(@NonNull JavaContext context, @NonNull Node node) { Object nativeNode = getNativeNode(node); if (nativeNode == null) { return null; } if (nativeNode instanceof NameReference) { return resolve(((NameReference) nativeNode).binding); } else if (nativeNode instanceof TypeReference) { return resolve(((TypeReference) nativeNode).resolvedType); } else if (nativeNode instanceof MessageSend) { return resolve(((MessageSend) nativeNode).binding); } else if (nativeNode instanceof AllocationExpression) { return resolve(((AllocationExpression) nativeNode).binding); } else if (nativeNode instanceof TypeDeclaration) { return resolve(((TypeDeclaration) nativeNode).binding); } else if (nativeNode instanceof ExplicitConstructorCall) { return resolve(((ExplicitConstructorCall) nativeNode).binding); } else if (nativeNode instanceof Annotation) { return resolve(((Annotation) nativeNode).resolvedType); } else if (nativeNode instanceof AbstractMethodDeclaration) { return resolve(((AbstractMethodDeclaration) nativeNode).binding); } else if (nativeNode instanceof AbstractVariableDeclaration) { if (nativeNode instanceof LocalDeclaration) { return resolve(((LocalDeclaration) nativeNode).binding); } else if (nativeNode instanceof FieldDeclaration) { return resolve(((FieldDeclaration) nativeNode).binding); } } // TODO: Handle org.eclipse.jdt.internal.compiler.ast.SuperReference. It // doesn't contain an actual method binding; the parent node call should contain // it, but is missing a native node reference; investigate the ECJ bridge's super // handling. return null; }
synchronized IMethodBinding resolveConstructor(ConstructorInvocation expression) { org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression); if (node instanceof ExplicitConstructorCall) { ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall) node; return getMethodBinding(explicitConstructorCall.binding); } return null; }
synchronized IMethodBinding resolveConstructor(SuperConstructorInvocation expression) { org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression); if (node instanceof ExplicitConstructorCall) { ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall) node; return getMethodBinding(explicitConstructorCall.binding); } return null; }
protected void consumeExplicitConstructorInvocation(int flag, int recFlag) { /* flag allows to distinguish 3 cases : (0) : ExplicitConstructorInvocation ::= 'this' '(' ArgumentListopt ')' ';' ExplicitConstructorInvocation ::= 'super' '(' ArgumentListopt ')' ';' (1) : ExplicitConstructorInvocation ::= Primary '.' 'super' '(' ArgumentListopt ')' ';' ExplicitConstructorInvocation ::= Primary '.' 'this' '(' ArgumentListopt ')' ';' (2) : ExplicitConstructorInvocation ::= Name '.' 'super' '(' ArgumentListopt ')' ';' ExplicitConstructorInvocation ::= Name '.' 'this' '(' ArgumentListopt ')' ';' */ int startPosition = this.intStack[this.intPtr--]; ExplicitConstructorCall ecc = new ExplicitConstructorCall(recFlag); int length; if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) { this.expressionPtr -= length; System.arraycopy(this.expressionStack, this.expressionPtr + 1, ecc.arguments = new Expression[length], 0, length); } switch (flag) { case 0 : ecc.sourceStart = startPosition; break; case 1 : this.expressionLengthPtr--; ecc.sourceStart = (ecc.qualification = this.expressionStack[this.expressionPtr--]).sourceStart; break; case 2 : ecc.sourceStart = (ecc.qualification = getUnspecifiedReferenceOptimized()).sourceStart; break; } pushOnAstStack(ecc); ecc.sourceEnd = this.endStatementPosition; }
public void cannotInvokeSuperConstructorInEnum(ExplicitConstructorCall constructorCall, MethodBinding enumConstructor) { this.handle( IProblem.CannotInvokeSuperConstructorInEnum, new String[] { new String(enumConstructor.declaringClass.sourceName()), typesAsString(enumConstructor, false), }, new String[] { new String(enumConstructor.declaringClass.sourceName()), typesAsString(enumConstructor, true), }, constructorCall.sourceStart, constructorCall.sourceEnd); }
public void noSuchEnclosingInstance(TypeBinding targetType, ASTNode location, boolean isConstructorCall) { int id; if (isConstructorCall) { //28 = No enclosing instance of type {0} is available due to some intermediate constructor invocation id = IProblem.EnclosingInstanceInConstructorCall; } else if ((location instanceof ExplicitConstructorCall) && ((ExplicitConstructorCall) location).accessMode == ExplicitConstructorCall.ImplicitSuper) { //20 = No enclosing instance of type {0} is accessible to invoke the super constructor. Must define a constructor and explicitly qualify its super constructor invocation with an instance of {0} (e.g. x.super() where x is an instance of {0}). id = IProblem.MissingEnclosingInstanceForConstructorCall; } else if (location instanceof AllocationExpression && (((AllocationExpression) location).binding.declaringClass.isMemberType() || (((AllocationExpression) location).binding.declaringClass.isAnonymousType() && ((AllocationExpression) location).binding.declaringClass.superclass().isMemberType()))) { //21 = No enclosing instance of type {0} is accessible. Must qualify the allocation with an enclosing instance of type {0} (e.g. x.new A() where x is an instance of {0}). id = IProblem.MissingEnclosingInstance; } else { // default //22 = No enclosing instance of the type {0} is accessible in scope id = IProblem.IncorrectEnclosingInstanceReference; } this.handle( id, new String[] { new String(targetType.readableName())}, new String[] { new String(targetType.shortReadableName())}, location.sourceStart, location.sourceEnd); }
public void recursiveConstructorInvocation(ExplicitConstructorCall constructorCall) { this.handle( IProblem.RecursiveConstructorInvocation, new String[] { new String(constructorCall.binding.declaringClass.readableName()), typesAsString(constructorCall.binding, false) }, new String[] { new String(constructorCall.binding.declaringClass.shortReadableName()), typesAsString(constructorCall.binding, true) }, constructorCall.sourceStart, constructorCall.sourceEnd); }
private void handleMethod(EclipseNode annotation, AbstractMethodDeclaration method, List<DeclaredException> exceptions) { if (method.isAbstract()) { annotation.addError("@SneakyThrows can only be used on concrete methods."); return; } if (method.statements == null || method.statements.length == 0) { boolean hasConstructorCall = false; if (method instanceof ConstructorDeclaration) { ExplicitConstructorCall constructorCall = ((ConstructorDeclaration) method).constructorCall; hasConstructorCall = constructorCall != null && !constructorCall.isImplicitSuper() && !constructorCall.isImplicitThis(); } if (hasConstructorCall) { annotation.addWarning("Calls to sibling / super constructors are always excluded from @SneakyThrows; @SneakyThrows has been ignored because there is no other code in this constructor."); } else { annotation.addWarning("This method or constructor is empty; @SneakyThrows has been ignored."); } return; } Statement[] contents = method.statements; for (DeclaredException exception : exceptions) { contents = new Statement[] { buildTryCatchBlock(contents, exception, exception.node, method) }; } method.statements = contents; annotation.up().rebuild(); }
@Override public boolean visit(ExplicitConstructorCall node, BlockScope scope) { fixPositions(setGeneratedBy(node, source)); return super.visit(node, scope); }
public static ConstructorDeclaration createConstructor( AccessLevel level, EclipseNode type, Collection<EclipseNode> fields, Boolean suppressConstructorProperties, EclipseNode sourceNode, List<Annotation> onConstructor) { ASTNode source = sourceNode.get(); TypeDeclaration typeDeclaration = ((TypeDeclaration)type.get()); long p = (long)source.sourceStart << 32 | source.sourceEnd; boolean isEnum = (((TypeDeclaration)type.get()).modifiers & ClassFileConstants.AccEnum) != 0; if (isEnum) level = AccessLevel.PRIVATE; if (suppressConstructorProperties == null) { if (fields.isEmpty()) { suppressConstructorProperties = false; } else { suppressConstructorProperties = Boolean.TRUE.equals(type.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES)); } } ConstructorDeclaration constructor = new ConstructorDeclaration( ((CompilationUnitDeclaration) type.top().get()).compilationResult); constructor.modifiers = toEclipseModifier(level); constructor.selector = typeDeclaration.name; constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper); constructor.constructorCall.sourceStart = source.sourceStart; constructor.constructorCall.sourceEnd = source.sourceEnd; constructor.thrownExceptions = null; constructor.typeParameters = null; constructor.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart; constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd; constructor.arguments = null; List<Argument> params = new ArrayList<Argument>(); List<Statement> assigns = new ArrayList<Statement>(); List<Statement> nullChecks = new ArrayList<Statement>(); for (EclipseNode fieldNode : fields) { FieldDeclaration field = (FieldDeclaration) fieldNode.get(); char[] rawName = field.name; char[] fieldName = removePrefixFromField(fieldNode); FieldReference thisX = new FieldReference(rawName, p); thisX.receiver = new ThisReference((int)(p >> 32), (int)p); SingleNameReference assignmentNameRef = new SingleNameReference(fieldName, p); Assignment assignment = new Assignment(thisX, assignmentNameRef, (int)p); assignment.sourceStart = (int)(p >> 32); assignment.sourceEnd = assignment.statementEnd = (int)(p >> 32); assigns.add(assignment); long fieldPos = (((long)field.sourceStart) << 32) | field.sourceEnd; Argument parameter = new Argument(fieldName, fieldPos, copyType(field.type, source), Modifier.FINAL); Annotation[] nonNulls = findAnnotations(field, NON_NULL_PATTERN); Annotation[] nullables = findAnnotations(field, NULLABLE_PATTERN); if (nonNulls.length != 0) { Statement nullCheck = generateNullCheck(field, sourceNode); if (nullCheck != null) nullChecks.add(nullCheck); } parameter.annotations = copyAnnotations(source, nonNulls, nullables); params.add(parameter); } nullChecks.addAll(assigns); constructor.statements = nullChecks.isEmpty() ? null : nullChecks.toArray(new Statement[nullChecks.size()]); constructor.arguments = params.isEmpty() ? null : params.toArray(new Argument[params.size()]); /* Generate annotations that must be put on the generated method, and attach them. */ { Annotation[] constructorProperties = null; if (!suppressConstructorProperties && level != AccessLevel.PRIVATE && level != AccessLevel.PACKAGE && !isLocalType(type)) { constructorProperties = createConstructorProperties(source, fields); } constructor.annotations = copyAnnotations(source, onConstructor.toArray(new Annotation[0]), constructorProperties); } constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope); return constructor; }
protected void consumeMethodInvocationName() { // MethodInvocation ::= Name '(' ArgumentListopt ')' // when the name is only an identifier...we have a message send to "this" (implicit) char[] selector = this.identifierStack[this.identifierPtr]; int accessMode; if(selector == assistIdentifier()) { if(CharOperation.equals(selector, SUPER)) { accessMode = ExplicitConstructorCall.Super; } else if(CharOperation.equals(selector, THIS)) { accessMode = ExplicitConstructorCall.This; } else { super.consumeMethodInvocationName(); return; } } else { super.consumeMethodInvocationName(); return; } final ExplicitConstructorCall constructorCall = new SelectionOnExplicitConstructorCall(accessMode); constructorCall.sourceEnd = this.rParenPos; constructorCall.sourceStart = (int) (this.identifierPositionStack[this.identifierPtr] >>> 32); int length; if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) { this.expressionPtr -= length; System.arraycopy(this.expressionStack, this.expressionPtr + 1, constructorCall.arguments = new Expression[length], 0, length); } if (!this.diet){ pushOnAstStack(constructorCall); this.restartRecovery = true; // force to restart in recovery mode this.lastIgnoredToken = -1; } else { pushOnExpressionStack(new Expression(){ public TypeBinding resolveType(BlockScope scope) { constructorCall.resolve(scope); return null; } public StringBuffer printExpression(int indent, StringBuffer output) { return output; } }); } this.assistNode = constructorCall; this.lastCheckPoint = constructorCall.sourceEnd + 1; this.isOrphanCompletionNode = true; }
protected void consumeMethodInvocationPrimary() { //optimize the push/pop //MethodInvocation ::= Primary '.' 'Identifier' '(' ArgumentListopt ')' char[] selector = this.identifierStack[this.identifierPtr]; int accessMode; if(selector == assistIdentifier()) { if(CharOperation.equals(selector, SUPER)) { accessMode = ExplicitConstructorCall.Super; } else if(CharOperation.equals(selector, THIS)) { accessMode = ExplicitConstructorCall.This; } else { super.consumeMethodInvocationPrimary(); return; } } else { super.consumeMethodInvocationPrimary(); return; } final ExplicitConstructorCall constructorCall = new SelectionOnExplicitConstructorCall(accessMode); constructorCall.sourceEnd = this.rParenPos; int length; if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) { this.expressionPtr -= length; System.arraycopy(this.expressionStack, this.expressionPtr + 1, constructorCall.arguments = new Expression[length], 0, length); } constructorCall.qualification = this.expressionStack[this.expressionPtr--]; constructorCall.sourceStart = constructorCall.qualification.sourceStart; if (!this.diet){ pushOnAstStack(constructorCall); this.restartRecovery = true; // force to restart in recovery mode this.lastIgnoredToken = -1; } else { pushOnExpressionStack(new Expression(){ public TypeBinding resolveType(BlockScope scope) { constructorCall.resolve(scope); return null; } public StringBuffer printExpression(int indent, StringBuffer output) { return output; } }); } this.assistNode = constructorCall; this.lastCheckPoint = constructorCall.sourceEnd + 1; this.isOrphanCompletionNode = true; }
/** * Parse the block statements inside the given constructor declaration and try to complete at the * cursor location. */ public void parseBlockStatements(ConstructorDeclaration cd, CompilationUnitDeclaration unit) { //only parse the method body of cd //fill out its statements //convert bugs into parse error initialize(); // set the lastModifiers to reflect the modifiers of the constructor whose // block statements are being parsed // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=202634 this.lastModifiers = cd.modifiers; this.lastModifiersStart = cd.modifiersSourceStart; // simulate goForConstructorBody except that we don't want to balance brackets because they are not going to be balanced goForBlockStatementsopt(); this.referenceContext = cd; this.compilationUnit = unit; this.scanner.resetTo(cd.bodyStart, bodyEnd(cd)); consumeNestedMethod(); try { parse(); } catch (AbortCompilation ex) { this.lastAct = ERROR_ACTION; } if (this.lastAct == ERROR_ACTION) { cd.bits |= ASTNode.HasSyntaxErrors; return; } // attach the statements as we might be searching for a reference to a local type cd.explicitDeclarations = this.realBlockStack[this.realBlockPtr--]; int length; if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) { this.astPtr -= length; if (this.astStack[this.astPtr + 1] instanceof ExplicitConstructorCall) //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ? { System.arraycopy( this.astStack, this.astPtr + 2, cd.statements = new Statement[length - 1], 0, length - 1); cd.constructorCall = (ExplicitConstructorCall) this.astStack[this.astPtr + 1]; } else { //need to add explicitly the super(); System.arraycopy( this.astStack, this.astPtr + 1, cd.statements = new Statement[length], 0, length); cd.constructorCall = SuperReference.implicitSuperConstructorCall(); } } else { cd.constructorCall = SuperReference.implicitSuperConstructorCall(); if (!containsComment(cd.bodyStart, cd.bodyEnd)) { cd.bits |= ASTNode.UndocumentedEmptyBlock; } } if (cd.constructorCall.sourceEnd == 0) { cd.constructorCall.sourceEnd = cd.sourceEnd; cd.constructorCall.sourceStart = cd.sourceStart; } }
/** * @see org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String) */ public TextEdit format(String string, ConstructorDeclaration constructorDeclaration) { // reset the scribe this.scribe.reset(); long startTime = 0; if (DEBUG) { startTime = System.currentTimeMillis(); } final char[] compilationUnitSource = string.toCharArray(); this.localScanner.setSource(compilationUnitSource); this.scribe.resetScanner(compilationUnitSource); if (constructorDeclaration == null) { return null; } this.lastLocalDeclarationSourceStart = -1; try { ExplicitConstructorCall explicitConstructorCall = constructorDeclaration.constructorCall; if (explicitConstructorCall != null && !explicitConstructorCall.isImplicitSuper()) { explicitConstructorCall.traverse(this, null); } Statement[] statements = constructorDeclaration.statements; if (statements != null) { formatStatements(null, statements, false); } if (hasComments()) { this.scribe.printNewLine(); } this.scribe.printComment(); } catch(AbortFormatting e){ return failedToFormat(); } if (DEBUG){ System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime)); //$NON-NLS-1$ } return this.scribe.getRootEdit(); }
protected void consumeExplicitConstructorInvocationWithTypeArguments(int flag, int recFlag) { /* flag allows to distinguish 3 cases : (0) : ExplicitConstructorInvocation ::= TypeArguments 'this' '(' ArgumentListopt ')' ';' ExplicitConstructorInvocation ::= TypeArguments 'super' '(' ArgumentListopt ')' ';' (1) : ExplicitConstructorInvocation ::= Primary '.' TypeArguments 'super' '(' ArgumentListopt ')' ';' ExplicitConstructorInvocation ::= Primary '.' TypeArguments 'this' '(' ArgumentListopt ')' ';' (2) : ExplicitConstructorInvocation ::= Name '.' TypeArguments 'super' '(' ArgumentListopt ')' ';' ExplicitConstructorInvocation ::= Name '.' TypeArguments 'this' '(' ArgumentListopt ')' ';' */ int startPosition = this.intStack[this.intPtr--]; ExplicitConstructorCall ecc = new ExplicitConstructorCall(recFlag); int length; if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) { this.expressionPtr -= length; System.arraycopy(this.expressionStack, this.expressionPtr + 1, ecc.arguments = new Expression[length], 0, length); } length = this.genericsLengthStack[this.genericsLengthPtr--]; this.genericsPtr -= length; System.arraycopy(this.genericsStack, this.genericsPtr + 1, ecc.typeArguments = new TypeReference[length], 0, length); ecc.typeArgumentsSourceStart = this.intStack[this.intPtr--]; switch (flag) { case 0 : ecc.sourceStart = startPosition; break; case 1 : this.expressionLengthPtr--; ecc.sourceStart = (ecc.qualification = this.expressionStack[this.expressionPtr--]).sourceStart; break; case 2 : ecc.sourceStart = (ecc.qualification = getUnspecifiedReferenceOptimized()).sourceStart; break; } pushOnAstStack(ecc); ecc.sourceEnd = this.endStatementPosition; }
/** * Code responsible to generate the suitable code to supply values for the synthetic enclosing * instance arguments of a constructor invocation of a nested type. */ public void generateSyntheticEnclosingInstanceValues(BlockScope currentScope, ReferenceBinding targetType, Expression enclosingInstance, ASTNode invocationSite) { // supplying enclosing instance for the anonymous type's superclass ReferenceBinding checkedTargetType = targetType.isAnonymousType() ? (ReferenceBinding)targetType.superclass().erasure() : targetType; boolean hasExtraEnclosingInstance = enclosingInstance != null; if (hasExtraEnclosingInstance && (!checkedTargetType.isNestedType() || checkedTargetType.isStatic())) { currentScope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, checkedTargetType); return; } // perform some emulation work in case there is some and we are inside a local type only ReferenceBinding[] syntheticArgumentTypes; if ((syntheticArgumentTypes = targetType.syntheticEnclosingInstanceTypes()) != null) { ReferenceBinding targetEnclosingType = checkedTargetType.enclosingType(); long compliance = currentScope.compilerOptions().complianceLevel; // deny access to enclosing instance argument for allocation and super constructor call (if 1.4) // always consider it if complying to 1.5 boolean denyEnclosingArgInConstructorCall; if (compliance <= ClassFileConstants.JDK1_3) { denyEnclosingArgInConstructorCall = invocationSite instanceof AllocationExpression; } else if (compliance == ClassFileConstants.JDK1_4){ denyEnclosingArgInConstructorCall = invocationSite instanceof AllocationExpression || invocationSite instanceof ExplicitConstructorCall && ((ExplicitConstructorCall)invocationSite).isSuperAccess(); } else { //compliance >= JDK1_5 denyEnclosingArgInConstructorCall = (invocationSite instanceof AllocationExpression || invocationSite instanceof ExplicitConstructorCall && ((ExplicitConstructorCall)invocationSite).isSuperAccess()) && !targetType.isLocalType(); } boolean complyTo14 = compliance >= ClassFileConstants.JDK1_4; for (int i = 0, max = syntheticArgumentTypes.length; i < max; i++) { ReferenceBinding syntheticArgType = syntheticArgumentTypes[i]; if (hasExtraEnclosingInstance && TypeBinding.equalsEquals(syntheticArgType, targetEnclosingType)) { hasExtraEnclosingInstance = false; enclosingInstance.generateCode(currentScope, this, true); if (complyTo14){ dup(); invokeObjectGetClass(); // will perform null check pop(); } } else { Object[] emulationPath = currentScope.getEmulationPath( syntheticArgType, false /*not only exact match (that is, allow compatible)*/, denyEnclosingArgInConstructorCall); generateOuterAccess(emulationPath, invocationSite, syntheticArgType, currentScope); } } if (hasExtraEnclosingInstance){ currentScope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, checkedTargetType); } } }
/** * Code responsible to generate the suitable code to supply values for the synthetic enclosing * instance arguments of a constructor invocation of a nested type. */ public void generateSyntheticEnclosingInstanceValues(BlockScope currentScope, ReferenceBinding targetType, Expression enclosingInstance, ASTNode invocationSite) { // supplying enclosing instance for the anonymous type's superclass ReferenceBinding checkedTargetType = targetType.isAnonymousType() ? (ReferenceBinding)targetType.superclass().erasure() : targetType; boolean hasExtraEnclosingInstance = enclosingInstance != null; if (hasExtraEnclosingInstance && (!checkedTargetType.isNestedType() || checkedTargetType.isStatic())) { currentScope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, checkedTargetType); return; } // perform some emulation work in case there is some and we are inside a local type only ReferenceBinding[] syntheticArgumentTypes; if ((syntheticArgumentTypes = targetType.syntheticEnclosingInstanceTypes()) != null) { ReferenceBinding targetEnclosingType = checkedTargetType.enclosingType(); long compliance = currentScope.compilerOptions().complianceLevel; // deny access to enclosing instance argument for allocation and super constructor call (if 1.4) // always consider it if complying to 1.5 boolean denyEnclosingArgInConstructorCall; if (compliance <= ClassFileConstants.JDK1_3) { denyEnclosingArgInConstructorCall = invocationSite instanceof AllocationExpression; } else if (compliance == ClassFileConstants.JDK1_4){ denyEnclosingArgInConstructorCall = invocationSite instanceof AllocationExpression || invocationSite instanceof ExplicitConstructorCall && ((ExplicitConstructorCall)invocationSite).isSuperAccess(); } else { //compliance >= JDK1_5 denyEnclosingArgInConstructorCall = (invocationSite instanceof AllocationExpression || invocationSite instanceof ExplicitConstructorCall && ((ExplicitConstructorCall)invocationSite).isSuperAccess()) && !targetType.isLocalType(); } boolean complyTo14 = compliance >= ClassFileConstants.JDK1_4; for (int i = 0, max = syntheticArgumentTypes.length; i < max; i++) { ReferenceBinding syntheticArgType = syntheticArgumentTypes[i]; if (hasExtraEnclosingInstance && syntheticArgType == targetEnclosingType) { hasExtraEnclosingInstance = false; enclosingInstance.generateCode(currentScope, this, true); if (complyTo14){ dup(); invokeObjectGetClass(); // will perform null check pop(); } } else { Object[] emulationPath = currentScope.getEmulationPath( syntheticArgType, false /*not only exact match (that is, allow compatible)*/, denyEnclosingArgInConstructorCall); generateOuterAccess(emulationPath, invocationSite, syntheticArgType, currentScope); } } if (hasExtraEnclosingInstance){ currentScope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, checkedTargetType); } } }
@Override public boolean visit(ExplicitConstructorCall explicitConstructor, BlockScope scope) { scope.methodScope().isConstructorCall = true; return true; }
@Override public boolean visit(ExplicitConstructorCall node, BlockScope scope) { setGeneratedBy(node, source); applyOffsetASTNode(node); return super.visit(node, scope); }