use of org.eclipse.jdt.internal.compiler.ast.MemberValuePair in project lombok by rzwitserloot.
the class HandleCleanup method handle.
public void handle(AnnotationValues<Cleanup> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.CLEANUP_FLAG_USAGE, "@Cleanup");
String cleanupName = annotation.getInstance().value();
if (cleanupName.length() == 0) {
annotationNode.addError("cleanupName cannot be the empty string.");
return;
}
if (annotationNode.up().getKind() != Kind.LOCAL) {
annotationNode.addError("@Cleanup is legal only on local variable declarations.");
return;
}
LocalDeclaration decl = (LocalDeclaration) annotationNode.up().get();
if (decl.initialization == null) {
annotationNode.addError("@Cleanup variable declarations need to be initialized.");
return;
}
EclipseNode ancestor = annotationNode.up().directUp();
ASTNode blockNode = ancestor.get();
final boolean isSwitch;
final Statement[] statements;
if (blockNode instanceof AbstractMethodDeclaration) {
isSwitch = false;
statements = ((AbstractMethodDeclaration) blockNode).statements;
} else if (blockNode instanceof Block) {
isSwitch = false;
statements = ((Block) blockNode).statements;
} else if (blockNode instanceof SwitchStatement) {
isSwitch = true;
statements = ((SwitchStatement) blockNode).statements;
} else {
annotationNode.addError("@Cleanup is legal only on a local variable declaration inside a block.");
return;
}
if (statements == null) {
annotationNode.addError("LOMBOK BUG: Parent block does not contain any statements.");
return;
}
int start = 0;
for (; start < statements.length; start++) {
if (statements[start] == decl)
break;
}
if (start == statements.length) {
annotationNode.addError("LOMBOK BUG: Can't find this local variable declaration inside its parent.");
return;
}
//We start with try{} *AFTER* the var declaration.
start++;
int end;
if (isSwitch) {
end = start + 1;
for (; end < statements.length; end++) {
if (statements[end] instanceof CaseStatement) {
break;
}
}
} else
end = statements.length;
//At this point:
// start-1 = Local Declaration marked with @Cleanup
// start = first instruction that needs to be wrapped into a try block
// end = last instruction of the scope -OR- last instruction before the next case label in switch statements.
// hence:
// [start, end) = statements for the try block.
Statement[] tryBlock = new Statement[end - start];
System.arraycopy(statements, start, tryBlock, 0, end - start);
//Remove the stuff we just dumped into the tryBlock, and then leave room for the try node.
//Remove room for every statement moved into try block...
int newStatementsLength = statements.length - (end - start);
//But add room for the TryStatement node itself.
newStatementsLength += 1;
Statement[] newStatements = new Statement[newStatementsLength];
//copy all statements before the try block verbatim.
System.arraycopy(statements, 0, newStatements, 0, start);
//For switch statements.
System.arraycopy(statements, end, newStatements, start + 1, statements.length - end);
doAssignmentCheck(annotationNode, tryBlock, decl.name);
TryStatement tryStatement = new TryStatement();
setGeneratedBy(tryStatement, ast);
tryStatement.tryBlock = new Block(0);
tryStatement.tryBlock.statements = tryBlock;
setGeneratedBy(tryStatement.tryBlock, ast);
// Positions for in-method generated nodes are special
int ss = decl.declarationSourceEnd + 1;
int se = ss;
if (tryBlock.length > 0) {
//+1 for the closing semicolon. Yes, there could be spaces. Bummer.
se = tryBlock[tryBlock.length - 1].sourceEnd + 1;
tryStatement.sourceStart = ss;
tryStatement.sourceEnd = se;
tryStatement.tryBlock.sourceStart = ss;
tryStatement.tryBlock.sourceEnd = se;
}
newStatements[start] = tryStatement;
Statement[] finallyBlock = new Statement[1];
MessageSend unsafeClose = new MessageSend();
setGeneratedBy(unsafeClose, ast);
unsafeClose.sourceStart = ast.sourceStart;
unsafeClose.sourceEnd = ast.sourceEnd;
SingleNameReference receiver = new SingleNameReference(decl.name, 0);
setGeneratedBy(receiver, ast);
unsafeClose.receiver = receiver;
long nameSourcePosition = (long) ast.sourceStart << 32 | ast.sourceEnd;
if (ast.memberValuePairs() != null)
for (MemberValuePair pair : ast.memberValuePairs()) {
if (pair.name != null && new String(pair.name).equals("value")) {
nameSourcePosition = (long) pair.value.sourceStart << 32 | pair.value.sourceEnd;
break;
}
}
unsafeClose.nameSourcePosition = nameSourcePosition;
unsafeClose.selector = cleanupName.toCharArray();
int pS = ast.sourceStart, pE = ast.sourceEnd;
long p = (long) pS << 32 | pE;
SingleNameReference varName = new SingleNameReference(decl.name, p);
setGeneratedBy(varName, ast);
NullLiteral nullLiteral = new NullLiteral(pS, pE);
setGeneratedBy(nullLiteral, ast);
MessageSend preventNullAnalysis = preventNullAnalysis(ast, varName);
EqualExpression equalExpression = new EqualExpression(preventNullAnalysis, nullLiteral, OperatorIds.NOT_EQUAL);
equalExpression.sourceStart = pS;
equalExpression.sourceEnd = pE;
setGeneratedBy(equalExpression, ast);
Block closeBlock = new Block(0);
closeBlock.statements = new Statement[1];
closeBlock.statements[0] = unsafeClose;
setGeneratedBy(closeBlock, ast);
IfStatement ifStatement = new IfStatement(equalExpression, closeBlock, 0, 0);
setGeneratedBy(ifStatement, ast);
finallyBlock[0] = ifStatement;
tryStatement.finallyBlock = new Block(0);
// Positions for in-method generated nodes are special
if (!isSwitch) {
tryStatement.finallyBlock.sourceStart = blockNode.sourceEnd;
tryStatement.finallyBlock.sourceEnd = blockNode.sourceEnd;
}
setGeneratedBy(tryStatement.finallyBlock, ast);
tryStatement.finallyBlock.statements = finallyBlock;
tryStatement.catchArguments = null;
tryStatement.catchBlocks = null;
if (blockNode instanceof AbstractMethodDeclaration) {
((AbstractMethodDeclaration) blockNode).statements = newStatements;
} else if (blockNode instanceof Block) {
((Block) blockNode).statements = newStatements;
} else if (blockNode instanceof SwitchStatement) {
((SwitchStatement) blockNode).statements = newStatements;
}
ancestor.rebuild();
}
use of org.eclipse.jdt.internal.compiler.ast.MemberValuePair in project lombok by rzwitserloot.
the class EclipseHandlerUtil method addAnnotation.
private static Annotation[] addAnnotation(ASTNode source, Annotation[] originalAnnotationArray, char[][] annotationTypeFqn, ASTNode arg) {
char[] simpleName = annotationTypeFqn[annotationTypeFqn.length - 1];
if (originalAnnotationArray != null)
for (Annotation ann : originalAnnotationArray) {
if (ann.type instanceof QualifiedTypeReference) {
char[][] t = ((QualifiedTypeReference) ann.type).tokens;
if (Arrays.deepEquals(t, annotationTypeFqn))
return originalAnnotationArray;
}
if (ann.type instanceof SingleTypeReference) {
char[] lastToken = ((SingleTypeReference) ann.type).token;
if (Arrays.equals(lastToken, simpleName))
return originalAnnotationArray;
}
}
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long) pS << 32 | pE;
long[] poss = new long[annotationTypeFqn.length];
Arrays.fill(poss, p);
QualifiedTypeReference qualifiedType = new QualifiedTypeReference(annotationTypeFqn, poss);
setGeneratedBy(qualifiedType, source);
Annotation ann;
if (arg instanceof Expression) {
SingleMemberAnnotation sma = new SingleMemberAnnotation(qualifiedType, pS);
sma.declarationSourceEnd = pE;
arg.sourceStart = pS;
arg.sourceEnd = pE;
sma.memberValue = (Expression) arg;
setGeneratedBy(sma.memberValue, source);
ann = sma;
} else if (arg instanceof MemberValuePair) {
NormalAnnotation na = new NormalAnnotation(qualifiedType, pS);
na.declarationSourceEnd = pE;
arg.sourceStart = pS;
arg.sourceEnd = pE;
na.memberValuePairs = new MemberValuePair[] { (MemberValuePair) arg };
setGeneratedBy(na.memberValuePairs[0], source);
setGeneratedBy(na.memberValuePairs[0].value, source);
na.memberValuePairs[0].value.sourceStart = pS;
na.memberValuePairs[0].value.sourceEnd = pE;
ann = na;
} else {
MarkerAnnotation ma = new MarkerAnnotation(qualifiedType, pS);
ma.declarationSourceEnd = pE;
ann = ma;
}
setGeneratedBy(ann, source);
if (originalAnnotationArray == null)
return new Annotation[] { ann };
Annotation[] newAnnotationArray = new Annotation[originalAnnotationArray.length + 1];
System.arraycopy(originalAnnotationArray, 0, newAnnotationArray, 0, originalAnnotationArray.length);
newAnnotationArray[originalAnnotationArray.length] = ann;
return newAnnotationArray;
}
use of org.eclipse.jdt.internal.compiler.ast.MemberValuePair in project lombok by rzwitserloot.
the class EclipseHandlerUtil method unboxAndRemoveAnnotationParameter.
public static List<Annotation> unboxAndRemoveAnnotationParameter(Annotation annotation, String annotationName, String errorName, EclipseNode errorNode) {
if ("value".equals(annotationName)) {
// and onConstructor. Let's exit early and very obviously:
throw new UnsupportedOperationException("Lombok cannot unbox 'value' from SingleMemberAnnotation at this time.");
}
if (!NormalAnnotation.class.equals(annotation.getClass())) {
// CompletionOnAnnotationMemberValuePair from triggering this handler.
return Collections.emptyList();
}
NormalAnnotation normalAnnotation = (NormalAnnotation) annotation;
MemberValuePair[] pairs = normalAnnotation.memberValuePairs;
if (pairs == null)
return Collections.emptyList();
char[] nameAsCharArray = annotationName.toCharArray();
top: for (int i = 0; i < pairs.length; i++) {
boolean allowRaw;
char[] name = pairs[i].name;
if (name == null)
continue;
if (name.length < nameAsCharArray.length)
continue;
for (int j = 0; j < nameAsCharArray.length; j++) {
if (name[j] != nameAsCharArray[j])
continue top;
}
allowRaw = name.length > nameAsCharArray.length;
for (int j = nameAsCharArray.length; j < name.length; j++) {
if (name[j] != '_')
continue top;
}
// If we're still here it's the targeted annotation param.
Expression value = pairs[i].value;
MemberValuePair[] newPairs = new MemberValuePair[pairs.length - 1];
if (i > 0)
System.arraycopy(pairs, 0, newPairs, 0, i);
if (i < pairs.length - 1)
System.arraycopy(pairs, i + 1, newPairs, i, pairs.length - i - 1);
normalAnnotation.memberValuePairs = newPairs;
// We have now removed the annotation parameter and stored the value,
// which we must now unbox. It's either annotations, or @__(annotations).
Expression content = null;
if (value instanceof ArrayInitializer) {
if (!allowRaw) {
addError(errorName, errorNode);
return Collections.emptyList();
}
content = value;
} else if (!(value instanceof Annotation)) {
addError(errorName, errorNode);
return Collections.emptyList();
} else {
Annotation atDummyIdentifier = (Annotation) value;
if (atDummyIdentifier.type instanceof SingleTypeReference && isAllValidOnXCharacters(((SingleTypeReference) atDummyIdentifier.type).token)) {
if (atDummyIdentifier instanceof MarkerAnnotation) {
return Collections.emptyList();
} else if (atDummyIdentifier instanceof NormalAnnotation) {
MemberValuePair[] mvps = ((NormalAnnotation) atDummyIdentifier).memberValuePairs;
if (mvps == null || mvps.length == 0) {
return Collections.emptyList();
}
if (mvps.length == 1 && Arrays.equals("value".toCharArray(), mvps[0].name)) {
content = mvps[0].value;
}
} else if (atDummyIdentifier instanceof SingleMemberAnnotation) {
content = ((SingleMemberAnnotation) atDummyIdentifier).memberValue;
} else {
addError(errorName, errorNode);
return Collections.emptyList();
}
} else {
if (allowRaw) {
content = atDummyIdentifier;
} else {
addError(errorName, errorNode);
return Collections.emptyList();
}
}
}
if (content == null) {
addError(errorName, errorNode);
return Collections.emptyList();
}
if (content instanceof Annotation) {
return Collections.singletonList((Annotation) content);
} else if (content instanceof ArrayInitializer) {
Expression[] expressions = ((ArrayInitializer) content).expressions;
List<Annotation> result = new ArrayList<Annotation>();
if (expressions != null)
for (Expression ex : expressions) {
if (ex instanceof Annotation)
result.add((Annotation) ex);
else {
addError(errorName, errorNode);
return Collections.emptyList();
}
}
return result;
} else {
addError(errorName, errorNode);
return Collections.emptyList();
}
}
return Collections.emptyList();
}
use of org.eclipse.jdt.internal.compiler.ast.MemberValuePair in project lombok by rzwitserloot.
the class EclipseHandlerUtil method addSuppressWarningsAll.
public static Annotation[] addSuppressWarningsAll(EclipseNode node, ASTNode source, Annotation[] originalAnnotationArray) {
Annotation[] anns = addAnnotation(source, originalAnnotationArray, TypeConstants.JAVA_LANG_SUPPRESSWARNINGS, new StringLiteral(ALL, 0, 0, 0));
if (Boolean.TRUE.equals(node.getAst().readConfiguration(ConfigurationKeys.ADD_FINDBUGS_SUPPRESSWARNINGS_ANNOTATIONS))) {
MemberValuePair mvp = new MemberValuePair(JUSTIFICATION, 0, 0, new StringLiteral(GENERATED_CODE, 0, 0, 0));
anns = addAnnotation(source, anns, EDU_UMD_CS_FINDBUGS_ANNOTATIONS_SUPPRESSFBWARNINGS, mvp);
}
return anns;
}
use of org.eclipse.jdt.internal.compiler.ast.MemberValuePair in project lombok by rzwitserloot.
the class EclipseHandlerUtil method createAnnotation.
/**
* Provides AnnotationValues with the data it needs to do its thing.
*/
public static <A extends java.lang.annotation.Annotation> AnnotationValues<A> createAnnotation(Class<A> type, final EclipseNode annotationNode) {
final Annotation annotation = (Annotation) annotationNode.get();
Map<String, AnnotationValue> values = new HashMap<String, AnnotationValue>();
MemberValuePair[] memberValuePairs = annotation.memberValuePairs();
if (memberValuePairs != null)
for (final MemberValuePair pair : memberValuePairs) {
List<String> raws = new ArrayList<String>();
List<Object> expressionValues = new ArrayList<Object>();
List<Object> guesses = new ArrayList<Object>();
Expression[] expressions = null;
char[] n = pair.name;
String mName = (n == null || n.length == 0) ? "value" : new String(pair.name);
final Expression rhs = pair.value;
if (rhs instanceof ArrayInitializer) {
expressions = ((ArrayInitializer) rhs).expressions;
} else if (rhs != null) {
expressions = new Expression[] { rhs };
}
if (expressions != null)
for (Expression ex : expressions) {
StringBuffer sb = new StringBuffer();
ex.print(0, sb);
raws.add(sb.toString());
expressionValues.add(ex);
guesses.add(calculateValue(ex));
}
final Expression[] exprs = expressions;
values.put(mName, new AnnotationValue(annotationNode, raws, expressionValues, guesses, true) {
@Override
public void setError(String message, int valueIdx) {
Expression ex;
if (valueIdx == -1)
ex = rhs;
else
ex = exprs != null ? exprs[valueIdx] : null;
if (ex == null)
ex = annotation;
int sourceStart = ex.sourceStart;
int sourceEnd = ex.sourceEnd;
annotationNode.addError(message, sourceStart, sourceEnd);
}
@Override
public void setWarning(String message, int valueIdx) {
Expression ex;
if (valueIdx == -1)
ex = rhs;
else
ex = exprs != null ? exprs[valueIdx] : null;
if (ex == null)
ex = annotation;
int sourceStart = ex.sourceStart;
int sourceEnd = ex.sourceEnd;
annotationNode.addWarning(message, sourceStart, sourceEnd);
}
});
}
for (Method m : type.getDeclaredMethods()) {
if (!Modifier.isPublic(m.getModifiers()))
continue;
String name = m.getName();
if (!values.containsKey(name)) {
values.put(name, new AnnotationValue(annotationNode, new ArrayList<String>(), new ArrayList<Object>(), new ArrayList<Object>(), false) {
@Override
public void setError(String message, int valueIdx) {
annotationNode.addError(message);
}
@Override
public void setWarning(String message, int valueIdx) {
annotationNode.addWarning(message);
}
});
}
}
return new AnnotationValues<A>(type, values, annotationNode);
}
Aggregations