/** {@inheritDoc} */ @Override protected EclipseNode buildTree(ASTNode node, Kind kind) { switch (kind) { case COMPILATION_UNIT: return buildCompilationUnit((CompilationUnitDeclaration) node); case TYPE: return buildType((TypeDeclaration) node); case FIELD: return buildField((FieldDeclaration) node); case INITIALIZER: return buildInitializer((Initializer) node); case METHOD: return buildMethod((AbstractMethodDeclaration) node); case ARGUMENT: return buildLocal((Argument) node, kind); case LOCAL: return buildLocal((LocalDeclaration) node, kind); case STATEMENT: return buildStatement((Statement) node); case ANNOTATION: return buildAnnotation((Annotation) node, false); default: throw new AssertionError("Did not expect to arrive here: " + kind); } }
/** * Checks if there is a (non-default) constructor. In case of multiple constructors (overloading), only * the first constructor decides if EXISTS_BY_USER or EXISTS_BY_LOMBOK is returned. * * @param node Any node that represents the Type (TypeDeclaration) to look in, or any child node thereof. */ public static MemberExistsResult constructorExists(EclipseNode node) { while (node != null && !(node.get() instanceof TypeDeclaration)) { node = node.up(); } if (node != null && node.get() instanceof TypeDeclaration) { TypeDeclaration typeDecl = (TypeDeclaration)node.get(); if (typeDecl.methods != null) top: for (AbstractMethodDeclaration def : typeDecl.methods) { if (def instanceof ConstructorDeclaration) { if ((def.bits & ASTNode.IsDefaultConstructor) != 0) continue; if (def.annotations != null) for (Annotation anno : def.annotations) { if (typeMatches(Tolerate.class, node, anno.type)) continue top; } return getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK; } } } return MemberExistsResult.NOT_EXISTS; }
private void makeSimpleSetterMethodForBuilder(EclipseNode builderType, EclipseNode fieldNode, EclipseNode sourceNode, boolean fluent, boolean chain) { TypeDeclaration td = (TypeDeclaration) builderType.get(); AbstractMethodDeclaration[] existing = td.methods; if (existing == null) existing = EMPTY; int len = existing.length; FieldDeclaration fd = (FieldDeclaration) fieldNode.get(); char[] name = fd.name; for (int i = 0; i < len; i++) { if (!(existing[i] instanceof MethodDeclaration)) continue; char[] existingName = existing[i].selector; if (Arrays.equals(name, existingName)) return; } String setterName = fluent ? fieldNode.getName() : HandlerUtil.buildAccessorName("set", fieldNode.getName()); MethodDeclaration setter = HandleSetter.createSetter(td, fieldNode, setterName, chain, ClassFileConstants.AccPublic, sourceNode, Collections.<Annotation>emptyList(), Collections.<Annotation>emptyList()); injectMethod(builderType, setter); }
private ASTNode getEnclosingDeclaration() { int i = this.parentsPtr; while (i > -1) { ASTNode parent = this.parents[i]; if (parent instanceof AbstractMethodDeclaration) { return parent; } else if (parent instanceof Initializer) { return parent; } else if (parent instanceof FieldDeclaration) { return parent; } else if (parent instanceof TypeDeclaration) { return parent; } i--; } return null; }
protected char[][] getThrownExceptions(AbstractMethodDeclaration methodDeclaration) { char[][] thrownExceptionTypes = null; TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions; if (thrownExceptions != null) { int thrownExceptionLength = thrownExceptions.length; int thrownExceptionCount = 0; thrownExceptionTypes = new char[thrownExceptionLength][]; next : for (int i = 0; i < thrownExceptionLength; i++) { TypeReference thrownException = thrownExceptions[i]; if (thrownException instanceof CompletionOnKeyword) continue next; if (CompletionUnitStructureRequestor.hasEmptyName(thrownException, this.assistNode)) continue next; thrownExceptionTypes[thrownExceptionCount++] = CharOperation.concatWith(thrownException.getParameterizedTypeName(), '.'); } if (thrownExceptionCount == 0) return null; if (thrownExceptionCount < thrownExceptionLength) { System.arraycopy(thrownExceptionTypes, 0, thrownExceptionTypes = new char[thrownExceptionCount][], 0, thrownExceptionCount); } } return thrownExceptionTypes; }
private void formatMethodArguments( AbstractMethodDeclaration methodDeclaration, boolean spaceBeforeOpenParen, boolean spaceBetweenEmptyParameters, boolean spaceBeforeClosingParen, boolean spaceBeforeFirstParameter, boolean spaceBeforeComma, boolean spaceAfterComma, int methodDeclarationParametersAlignment) { formatMethodArguments( methodDeclaration.receiver, methodDeclaration.arguments, methodDeclaration.scope, spaceBeforeOpenParen, spaceBetweenEmptyParameters, spaceBeforeClosingParen, spaceBeforeFirstParameter, spaceBeforeComma, spaceAfterComma, methodDeclarationParametersAlignment); }
synchronized IMethodBinding resolveMethod(MethodDeclaration method) { Object oldNode = this.newAstToOldAst.get(method); if (oldNode instanceof AbstractMethodDeclaration) { AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) oldNode; IMethodBinding methodBinding = getMethodBinding(methodDeclaration.binding); if (methodBinding == null) { return null; } this.bindingsToAstNodes.put(methodBinding, method); String key = methodBinding.getKey(); if (key != null) { this.bindingTables.bindingKeysToBindings.put(key, methodBinding); } return methodBinding; } return null; }
private void addDefaultConstructorIfNecessary(TypeInfo typeInfo) { boolean hasConstructor = false; TypeDeclaration typeDeclaration = typeInfo.node; AbstractMethodDeclaration[] methods = typeDeclaration.methods; int methodCounter = methods == null ? 0 : methods.length; done : for (int i = 0; i < methodCounter; i++) { AbstractMethodDeclaration method = methods[i]; if (method.isConstructor() && !method.isDefaultConstructor()) { hasConstructor = true; break done; } } if (!hasConstructor) { this.indexer.addDefaultConstructorDeclaration( typeInfo.name, this.packageName == null ? CharOperation.NO_CHAR : this.packageName, typeInfo.modifiers, getMoreExtraFlags(typeInfo.extraFlags)); } }
private void convertAndSetReceiver(AbstractMethodDeclaration method, MethodDeclaration methodDecl) { Receiver receiver = method.receiver; if (receiver.qualifyingName != null) { final SimpleName name = new SimpleName(this.ast); name.internalSetIdentifier(new String(receiver.qualifyingName.getName()[0])); int start = receiver.qualifyingName.sourceStart; int nameEnd = receiver.qualifyingName.sourceEnd; name.setSourceRange(start, nameEnd - start + 1); methodDecl.setReceiverQualifier(name); if (this.resolveBindings) { recordNodes(name, receiver); } } Type type = convertType(receiver.type); methodDecl.setReceiverType(type); if (receiver.modifiers != 0) { methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED); } if (this.resolveBindings) { recordNodes(type, receiver); type.resolveBinding(); } }
IMethodBinding resolveMember(AnnotationTypeMemberDeclaration declaration) { Object oldNode = this.newAstToOldAst.get(declaration); if (oldNode instanceof AbstractMethodDeclaration) { AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) oldNode; IMethodBinding methodBinding = getMethodBinding(methodDeclaration.binding); if (methodBinding == null) { return null; } this.bindingsToAstNodes.put(methodBinding, declaration); String key = methodBinding.getKey(); if (key != null) { this.bindingTables.bindingKeysToBindings.put(key, methodBinding); } return methodBinding; } return null; }
public void illegalReturnRedefinition(AbstractMethodDeclaration abstractMethodDecl, MethodBinding inheritedMethod, char[][] nonNullAnnotationName) { MethodDeclaration methodDecl = (MethodDeclaration) abstractMethodDecl; StringBuffer methodSignature = new StringBuffer(); methodSignature .append(inheritedMethod.declaringClass.readableName()) .append('.') .append(inheritedMethod.readableName()); StringBuffer shortSignature = new StringBuffer(); shortSignature .append(inheritedMethod.declaringClass.shortReadableName()) .append('.') .append(inheritedMethod.shortReadableName()); int sourceStart = methodDecl.returnType.sourceStart; Annotation[] annotations = methodDecl.annotations; Annotation annotation = findAnnotation(annotations, TypeIds.T_ConfiguredAnnotationNullable); if (annotation != null) { sourceStart = annotation.sourceStart; } this.handle( IProblem.IllegalReturnNullityRedefinition, new String[] { methodSignature.toString(), CharOperation.toString(nonNullAnnotationName)}, new String[] { shortSignature.toString(), new String(nonNullAnnotationName[nonNullAnnotationName.length-1])}, sourceStart, methodDecl.returnType.sourceEnd); }
/** * @return the default value for this annotation method or <code>null</code> if there is no default value */ public Object getDefaultValue() { MethodBinding originalMethod = original(); if ((originalMethod.tagBits & TagBits.DefaultValueResolved) == 0) { //The method has not been resolved nor has its class been resolved. //It can only be from a source type within compilation units to process. if (originalMethod.declaringClass instanceof SourceTypeBinding) { SourceTypeBinding sourceType = (SourceTypeBinding) originalMethod.declaringClass; if (sourceType.scope != null) { AbstractMethodDeclaration methodDeclaration = originalMethod.sourceMethod(); if (methodDeclaration != null && methodDeclaration.isAnnotationMethod()) { methodDeclaration.resolve(sourceType.scope); } } } originalMethod.tagBits |= TagBits.DefaultValueResolved; } AnnotationHolder holder = originalMethod.declaringClass.retrieveAnnotationHolder(originalMethod, true); return holder == null ? null : holder.getDefaultValue(); }
public AbstractMethodDeclaration sourceMethod() { if (isSynthetic()) { return null; } SourceTypeBinding sourceType; try { sourceType = (SourceTypeBinding) this.declaringClass; } catch (ClassCastException e) { return null; } AbstractMethodDeclaration[] methods = sourceType.scope.referenceContext.methods; if (methods != null) { for (int i = methods.length; --i >= 0;) if (this == methods[i].binding) return methods[i]; } return null; }
public void bytecodeExceeds64KLimit(AbstractMethodDeclaration location) { MethodBinding method = location.binding; if (location.isConstructor()) { this.handle( IProblem.BytecodeExceeds64KLimitForConstructor, new String[] {new String(location.selector), typesAsString(method, false)}, new String[] {new String(location.selector), typesAsString(method, true)}, ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal, location.sourceStart, location.sourceEnd); } else { this.handle( IProblem.BytecodeExceeds64KLimit, new String[] {new String(location.selector), typesAsString(method, false)}, new String[] {new String(location.selector), typesAsString(method, true)}, ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal, location.sourceStart, location.sourceEnd); } }
public void enumAbstractMethodMustBeImplemented(AbstractMethodDeclaration method) { MethodBinding abstractMethod = method.binding; this.handle( // Must implement the inherited abstract method %1 // 8.4.3 - Every non-abstract subclass of an abstract type, A, must provide a concrete implementation of all of A's methods. IProblem.EnumAbstractMethodMustBeImplemented, new String[] { new String(abstractMethod.selector), typesAsString(abstractMethod, false), new String(abstractMethod.declaringClass.readableName()), }, new String[] { new String(abstractMethod.selector), typesAsString(abstractMethod, true), new String(abstractMethod.declaringClass.shortReadableName()), }, method.sourceStart(), method.sourceEnd()); }
public void illegalModifierForInterfaceMethod(AbstractMethodDeclaration methodDecl, boolean isJDK18orGreater) { // cannot include parameter types since they are not resolved yet // and the error message would be too long this.handle( isJDK18orGreater ? IProblem.IllegalModifierForInterfaceMethod18 : IProblem.IllegalModifierForInterfaceMethod, new String[] { new String(methodDecl.selector) }, new String[] { new String(methodDecl.selector) }, methodDecl.sourceStart, methodDecl.sourceEnd); }
private void createArgumentBindings(MethodBinding method, CompilerOptions compilerOptions) { if (!isPrototype()) throw new IllegalStateException(); if (compilerOptions.isAnnotationBasedNullAnalysisEnabled) getNullDefault(); // ensure initialized AbstractMethodDeclaration methodDecl = method.sourceMethod(); if (methodDecl != null) { // while creating argument bindings we also collect explicit null annotations: if (method.parameters != Binding.NO_PARAMETERS) methodDecl.createArgumentBindings(); // add implicit annotations (inherited(?) & default): if (compilerOptions.isAnnotationBasedNullAnalysisEnabled) { new ImplicitNullAnnotationVerifier(this.scope.environment()).checkImplicitNullAnnotations(method, methodDecl, true, this.scope); } } }
public AbstractMethodDeclaration sourceMethod() { if (isSynthetic()) { return null; } SourceTypeBinding sourceType; try { sourceType = (SourceTypeBinding) this.declaringClass; } catch (ClassCastException e) { return null; } AbstractMethodDeclaration[] methods = sourceType.scope != null ? sourceType.scope.referenceContext.methods : null; if (methods != null) { for (int i = methods.length; --i >= 0;) if (this == methods[i].binding) return methods[i]; } return null; }
@Override public boolean visit(Argument argument, BlockScope scope) { Annotation[] annotations = argument.annotations; ReferenceContext referenceContext = scope.referenceContext(); if (referenceContext instanceof AbstractMethodDeclaration) { MethodBinding binding = ((AbstractMethodDeclaration) referenceContext).binding; if (binding != null) { TypeDeclaration typeDeclaration = scope.referenceType(); typeDeclaration.binding.resolveTypesFor(binding); if (argument.binding != null) { argument.binding = new AptSourceLocalVariableBinding(argument.binding, binding); } } if (annotations != null) { this.resolveAnnotations( scope, annotations, argument.binding); } } return false; }
public static boolean hasClinit(TypeDeclaration parent) { if (parent.methods == null) return false; for (AbstractMethodDeclaration method : parent.methods) { if (method instanceof Clinit) return true; } return false; }
public void visitMethod(EclipseNode node, AbstractMethodDeclaration method) { String type = method instanceof ConstructorDeclaration ? "CONSTRUCTOR" : "METHOD"; print("<%s %s: %s%s%s>", type, str(method.selector), method.statements != null ? "filled" : "blank", isGenerated(method) ? " (GENERATED)" : "", position(node)); indent++; if (printContent) { if (method.statements != null) print("%s", method); disablePrinting++; } }
private EclipseNode buildMethod(AbstractMethodDeclaration method) { if (setAndGetAsHandled(method)) return null; List<EclipseNode> childNodes = new ArrayList<EclipseNode>(); childNodes.addAll(buildArguments(method.arguments)); if (method instanceof ConstructorDeclaration) { ConstructorDeclaration constructor = (ConstructorDeclaration) method; addIfNotNull(childNodes, buildStatement(constructor.constructorCall)); } childNodes.addAll(buildStatements(method.statements)); childNodes.addAll(buildAnnotations(method.annotations, false)); return putInMap(new EclipseNode(this, method, childNodes, Kind.METHOD)); }
@Override public void handle(AnnotationValues<SneakyThrows> annotation, Annotation source, EclipseNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.SNEAKY_THROWS_FLAG_USAGE, "@SneakyThrows"); List<String> exceptionNames = annotation.getRawExpressions("value"); List<DeclaredException> exceptions = new ArrayList<DeclaredException>(); MemberValuePair[] memberValuePairs = source.memberValuePairs(); if (memberValuePairs == null || memberValuePairs.length == 0) { exceptions.add(new DeclaredException("java.lang.Throwable", source)); } else { Expression arrayOrSingle = memberValuePairs[0].value; final Expression[] exceptionNameNodes; if (arrayOrSingle instanceof ArrayInitializer) { exceptionNameNodes = ((ArrayInitializer)arrayOrSingle).expressions; } else exceptionNameNodes = new Expression[] { arrayOrSingle }; if (exceptionNames.size() != exceptionNameNodes.length) { annotationNode.addError( "LOMBOK BUG: The number of exception classes in the annotation isn't the same pre- and post- guessing."); } int idx = 0; for (String exceptionName : exceptionNames) { if (exceptionName.endsWith(".class")) exceptionName = exceptionName.substring(0, exceptionName.length() - 6); exceptions.add(new DeclaredException(exceptionName, exceptionNameNodes[idx++])); } } EclipseNode owner = annotationNode.up(); switch (owner.getKind()) { // case FIELD: // return handleField(annotationNode, (FieldDeclaration)owner.get(), exceptions); case METHOD: handleMethod(annotationNode, (AbstractMethodDeclaration)owner.get(), exceptions); break; default: annotationNode.addError("@SneakyThrows is legal only on methods and constructors."); } }
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(); }
/** * Inserts a method into an existing type. The type must represent a {@code TypeDeclaration}. */ public static EclipseNode injectMethod(EclipseNode type, AbstractMethodDeclaration method) { method.annotations = addSuppressWarningsAll(type, method, method.annotations); method.annotations = addGenerated(type, method, method.annotations); TypeDeclaration parent = (TypeDeclaration) type.get(); if (parent.methods == null) { parent.methods = new AbstractMethodDeclaration[1]; parent.methods[0] = method; } else { if (method instanceof ConstructorDeclaration) { for (int i = 0 ; i < parent.methods.length ; i++) { if (parent.methods[i] instanceof ConstructorDeclaration && (parent.methods[i].bits & ASTNode.IsDefaultConstructor) != 0) { EclipseNode tossMe = type.getNodeFor(parent.methods[i]); AbstractMethodDeclaration[] withoutGeneratedConstructor = new AbstractMethodDeclaration[parent.methods.length - 1]; System.arraycopy(parent.methods, 0, withoutGeneratedConstructor, 0, i); System.arraycopy(parent.methods, i + 1, withoutGeneratedConstructor, i, parent.methods.length - i - 1); parent.methods = withoutGeneratedConstructor; if (tossMe != null) tossMe.up().removeChild(tossMe); break; } } } //We insert the method in the last position of the methods registered to the type //When changing this behavior, this may trigger issue #155 and #377 AbstractMethodDeclaration[] newArray = new AbstractMethodDeclaration[parent.methods.length + 1]; System.arraycopy(parent.methods, 0, newArray, 0, parent.methods.length); newArray[parent.methods.length] = method; parent.methods = newArray; } return type.add(method, Kind.METHOD); }
private void fixPositions(AbstractMethodDeclaration node) { node.sourceEnd = sourceEnd; node.sourceStart = sourceStart; node.bodyEnd = sourceEnd; node.bodyStart = sourceStart; node.declarationSourceEnd = sourceEnd; node.declarationSourceStart = sourceStart; node.modifiersSourceStart = sourceStart; }
public void setGeneratedByRecursive(ASTNode target) { SetGeneratedByVisitor visitor = new SetGeneratedByVisitor(source); if (target instanceof AbstractMethodDeclaration) { ((AbstractMethodDeclaration) target).traverse(visitor, (ClassScope) null); } else if (target instanceof FieldDeclaration) { ((FieldDeclaration) target).traverse(visitor, (MethodScope) null); } else { target.traverse(visitor, null); } }
/** {@inheritDoc} */ @Override public String getName() { final char[] n; if (node instanceof TypeDeclaration) n = ((TypeDeclaration)node).name; else if (node instanceof FieldDeclaration) n = ((FieldDeclaration)node).name; else if (node instanceof AbstractMethodDeclaration) n = ((AbstractMethodDeclaration)node).selector; else if (node instanceof LocalDeclaration) n = ((LocalDeclaration)node).name; else n = null; return n == null ? null : new String(n); }
/** {@inheritDoc} */ @Override protected boolean calculateIsStructurallySignificant(ASTNode parent) { if (node instanceof TypeDeclaration) return true; if (node instanceof AbstractMethodDeclaration) return true; if (node instanceof FieldDeclaration) return true; if (node instanceof LocalDeclaration) return true; if (node instanceof CompilationUnitDeclaration) return true; return false; }
@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; }