/******************************************************************************* * Copyright © 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * *******************************************************************************/ package org.eclipse.edt.compiler.binding; import java.math.BigDecimal; import org.eclipse.edt.compiler.core.ast.AbstractASTExpressionVisitor; import org.eclipse.edt.compiler.core.ast.AnnotationExpression; import org.eclipse.edt.compiler.core.ast.ArrayAccess; import org.eclipse.edt.compiler.core.ast.ArrayLiteral; import org.eclipse.edt.compiler.core.ast.BinaryExpression; import org.eclipse.edt.compiler.core.ast.BooleanLiteral; import org.eclipse.edt.compiler.core.ast.BytesLiteral; import org.eclipse.edt.compiler.core.ast.DecimalLiteral; import org.eclipse.edt.compiler.core.ast.Expression; import org.eclipse.edt.compiler.core.ast.FloatLiteral; import org.eclipse.edt.compiler.core.ast.FunctionInvocation; import org.eclipse.edt.compiler.core.ast.IntegerLiteral; import org.eclipse.edt.compiler.core.ast.QualifiedName; import org.eclipse.edt.compiler.core.ast.SQLLiteral; import org.eclipse.edt.compiler.core.ast.SetValuesExpression; import org.eclipse.edt.compiler.core.ast.SimpleName; import org.eclipse.edt.compiler.core.ast.StringLiteral; import org.eclipse.edt.compiler.core.ast.TypeLiteralExpression; import org.eclipse.edt.compiler.core.ast.UnaryExpression; import org.eclipse.edt.compiler.internal.core.builder.IProblemRequestor; import org.eclipse.edt.compiler.internal.core.dependency.IDependencyRequestor; import org.eclipse.edt.compiler.internal.core.lookup.AnnotationLeftHandScope; import org.eclipse.edt.compiler.internal.core.lookup.DefaultBinder; import org.eclipse.edt.compiler.internal.core.lookup.ICompilerOptions; import org.eclipse.edt.compiler.internal.core.lookup.Scope; import org.eclipse.edt.mof.egl.Annotation; import org.eclipse.edt.mof.egl.AnnotationType; import org.eclipse.edt.mof.egl.IrFactory; import org.eclipse.edt.mof.egl.Part; import org.eclipse.edt.mof.utils.EList; public class AnnotationValueGatherer extends DefaultBinder{ Expression expr; Object value; boolean isNegative; public AnnotationValueGatherer(Expression expr, Scope currentScope, Part currentBinding, IDependencyRequestor dependencyRequestor, IProblemRequestor problemRequestor, ICompilerOptions compilerOptions) { super(currentScope, currentBinding, dependencyRequestor, problemRequestor, compilerOptions); this.expr = expr; } public Object getValue() { expr.accept(this); return value; } public void endVisit(SimpleName simpleName) { if (simpleName.resolveElement() != null) { value = simpleName.resolveElement(); } else { value = simpleName.resolveType(); } } public void endVisit(QualifiedName qualifiedName) { if (qualifiedName.resolveElement() != null) { value = qualifiedName.resolveElement(); } else { value = qualifiedName.resolveType(); } } public void endVisit(ArrayAccess arrayAccess) { value = arrayAccess.resolveMember(); } public boolean visit(IntegerLiteral integerLiteral) { String str = integerLiteral.getValue(); if (isNegative) { str = "-" + str; } try { value = new Integer(str); } catch (NumberFormatException e) { problemRequestor.acceptProblem(integerLiteral, IProblemRequestor.INTEGER_LITERAL_OUT_OF_RANGE, new String[] { str }); value = null; } integerLiteral.setBindAttempted(true); return false; } public boolean visit(FloatLiteral floatLiteral) { String str = floatLiteral.getValue(); if (isNegative) { str = "-" + str; } value = new Double(str); floatLiteral.setBindAttempted(true); return false; } public boolean visit(DecimalLiteral decimalLiteral) { String str = decimalLiteral.getValue(); if (isNegative) { str = "-" + str; } value = new BigDecimal(str); decimalLiteral.setBindAttempted(true); return false; } public boolean visit(StringLiteral stringLiteral) { value = stringLiteral.getValue(); stringLiteral.setBindAttempted(true); return false; } private static class BinaryExpressionVisitor extends AbstractASTExpressionVisitor { private StringBuffer concatenatedString; private IProblemRequestor problemRequestor; private boolean exprValid = true; public BinaryExpressionVisitor(IProblemRequestor problemRequestor) { concatenatedString = new StringBuffer(); this.problemRequestor = problemRequestor; } public String getConcatenatedString() { return concatenatedString.toString(); } public boolean visit(BinaryExpression binaryExpression) { if(binaryExpression.getOperator() == BinaryExpression.Operator.PLUS || binaryExpression.getOperator() == BinaryExpression.Operator.CONCAT) { BinaryExpressionVisitor operand1Visitor = new BinaryExpressionVisitor(problemRequestor); binaryExpression.getFirstExpression().accept(operand1Visitor); concatenatedString.append(operand1Visitor.getConcatenatedString()); BinaryExpressionVisitor operand2Visitor = new BinaryExpressionVisitor(problemRequestor); binaryExpression.getSecondExpression().accept(operand2Visitor); concatenatedString.append(operand2Visitor.getConcatenatedString()); if(!operand1Visitor.exprValid || !operand2Visitor.exprValid) { problemRequestor.acceptProblem(binaryExpression, IProblemRequestor.INVALID_EXPRESSION_DATA_ACCESS_OR_STRING_LITERAL); } } else { exprValid = false; } binaryExpression.setBindAttempted(true); return false; } public boolean visit(StringLiteral stringLiteral) { if (stringLiteral.isHex()) { concatenatedString.append(convertUnicodeHexToString(stringLiteral.getValue())); } else { concatenatedString.append(stringLiteral.getValue()); } stringLiteral.setBindAttempted(true); return false; } private String convertUnicodeHexToString(String str) { try { int charLen = (str.length()) / 4; if (charLen * 4 != str.length()) { charLen = charLen + 1; } char[] chars = new char[charLen]; for (int i = 0; i < str.length(); i = i + 4) { String nextCharString; if (i + 4 < str.length()) { nextCharString = str.substring(i, i + 4); } else { nextCharString = str.substring(i); } char myUnicodeCharacter = (char) Integer.parseInt(nextCharString, 16); chars[i/4] = myUnicodeCharacter; } return new String(chars); } catch (NumberFormatException e) { return str; } } public boolean visitExpression(Expression expression) { exprValid = false; expression.setBindAttempted(true); return false; } } public void endVisit(BinaryExpression binaryExpression) { super.endVisit(binaryExpression); BinaryExpressionVisitor subVisitor = new BinaryExpressionVisitor(problemRequestor); binaryExpression.accept(subVisitor); if(!subVisitor.exprValid) { problemRequestor.acceptProblem(binaryExpression, IProblemRequestor.INVALID_EXPRESSION_DATA_ACCESS_OR_STRING_LITERAL); } else { value = subVisitor.getConcatenatedString(); } } public boolean visit(org.eclipse.edt.compiler.core.ast.NullLiteral nullLiteral) { value = IrFactory.INSTANCE.createNullLiteral(); nullLiteral.setBindAttempted(true); return false; } public boolean visit(BooleanLiteral booleanLiteral) { value = new Boolean(booleanLiteral.booleanValue() == org.eclipse.edt.compiler.core.Boolean.YES); booleanLiteral.setBindAttempted(true); return false; } public boolean visit(BytesLiteral bytesLiteral) { value = bytesLiteral.getValue(); bytesLiteral.setBindAttempted(true); return false; } public boolean visit(SQLLiteral sQLLiteral) { value = sQLLiteral.getValue(); sQLLiteral.setBindAttempted(true); return false; } public boolean visit(TypeLiteralExpression typeLiteralExpression) { super.visit(typeLiteralExpression); value = typeLiteralExpression.getType().resolveType(); typeLiteralExpression.setBindAttempted(true); return false; } public boolean visit(SetValuesExpression setValuesExpression) { Expression expr = setValuesExpression.getExpression(); if (expr instanceof AnnotationExpression) { AnnotationExpression annotationExpression = (AnnotationExpression) expr; Annotation ann = getAnnotation(annotationExpression, problemRequestor); if (ann != null) { AnnotationLeftHandScope scope = new AnnotationLeftHandScope(currentScope, ann, (AnnotationType)ann.getEClass(), ann); SettingsBlockAnnotationBindingsCompletor completor = new SettingsBlockAnnotationBindingsCompletor(currentScope, currentBinding, scope, dependencyRequestor, problemRequestor, compilerOptions); setValuesExpression.getSettingsBlock().accept(completor); value = ann; } } else { problemRequestor.acceptProblem(setValuesExpression, IProblemRequestor.INVALID_EXPRESSION_DATA_ACCESS_OR_STRING_LITERAL); setValuesExpression.getExpression().setBindAttempted(true); setBindAttemptedForNames(setValuesExpression.getSettingsBlock()); } return false; } public boolean visit(ArrayLiteral arrayLiteral) { EList<Object> entries = new EList<Object>(); for (Expression expr : arrayLiteral.getExpressions()) { AnnotationValueGatherer gatherer = getGatherer(expr); if (gatherer.getValue() != null) { entries.add(gatherer.getValue()); } } value = entries; arrayLiteral.setBindAttempted(true); return false; } AnnotationValueGatherer getGatherer(Expression expr) { return new AnnotationValueGatherer(expr, currentScope, currentBinding, dependencyRequestor, problemRequestor, compilerOptions); } public boolean visit(UnaryExpression unaryExpression) { if (unaryExpression.getOperator() == UnaryExpression.Operator.MINUS) { isNegative = !isNegative; } return true; } public boolean visit(FunctionInvocation functionInvocation) { super.visit(functionInvocation); value = functionInvocation.getTarget().resolveMember(); return false; } }