| /******************************************************************************* |
| * Copyright (c) 2012 Martin Reiterer, Alexej Strelzow. |
| * 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: |
| * Martin Reiterer - initial API and implementation |
| * Alexej Strelzow - seperation of ui/non-ui |
| ******************************************************************************/ |
| package org.eclipse.babel.tapiji.tools.java.util; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| |
| import org.eclipse.babel.core.message.IMessagesBundleGroup; |
| import org.eclipse.babel.core.message.manager.RBManager; |
| import org.eclipse.babel.tapiji.tools.core.Logger; |
| import org.eclipse.babel.tapiji.tools.core.model.SLLocation; |
| import org.eclipse.babel.tapiji.tools.java.visitor.MethodParameterDescriptor; |
| import org.eclipse.core.internal.registry.OffsetTable; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.dom.AST; |
| import org.eclipse.jdt.core.dom.ASTNode; |
| import org.eclipse.jdt.core.dom.ASTParser; |
| import org.eclipse.jdt.core.dom.ASTVisitor; |
| import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; |
| import org.eclipse.jdt.core.dom.CompilationUnit; |
| import org.eclipse.jdt.core.dom.ExpressionStatement; |
| import org.eclipse.jdt.core.dom.FieldDeclaration; |
| import org.eclipse.jdt.core.dom.IAnnotationBinding; |
| import org.eclipse.jdt.core.dom.ITypeBinding; |
| import org.eclipse.jdt.core.dom.IVariableBinding; |
| import org.eclipse.jdt.core.dom.ImportDeclaration; |
| import org.eclipse.jdt.core.dom.MethodDeclaration; |
| import org.eclipse.jdt.core.dom.MethodInvocation; |
| import org.eclipse.jdt.core.dom.Modifier; |
| import org.eclipse.jdt.core.dom.QualifiedName; |
| import org.eclipse.jdt.core.dom.SimpleName; |
| import org.eclipse.jdt.core.dom.SimpleType; |
| import org.eclipse.jdt.core.dom.StringLiteral; |
| import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; |
| import org.eclipse.jdt.core.dom.TypeDeclaration; |
| import org.eclipse.jdt.core.dom.VariableDeclarationFragment; |
| import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; |
| import org.eclipse.jdt.core.dom.rewrite.ListRewrite; |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.Document; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.text.edits.TextEdit; |
| |
| public class ASTutils { |
| |
| private static MethodParameterDescriptor rbDefinition; |
| private static MethodParameterDescriptor rbAccessor; |
| |
| public static MethodParameterDescriptor getRBDefinitionDesc() { |
| if (rbDefinition == null) { |
| // Init descriptor for Resource-Bundle-Definition |
| List<String> definition = new ArrayList<String>(); |
| definition.add("getBundle"); |
| rbDefinition = new MethodParameterDescriptor(definition, |
| "java.util.ResourceBundle", true, 0); |
| } |
| |
| return rbDefinition; |
| } |
| |
| public static MethodParameterDescriptor getRBAccessorDesc() { |
| if (rbAccessor == null) { |
| // Init descriptor for Resource-Bundle-Accessors |
| List<String> accessors = new ArrayList<String>(); |
| accessors.add("getString"); |
| accessors.add("getStringArray"); |
| rbAccessor = new MethodParameterDescriptor(accessors, |
| "java.util.ResourceBundle", true, 0); |
| } |
| |
| return rbAccessor; |
| } |
| |
| public static String resolveRBReferenceVar(IDocument document, |
| IResource resource, int pos, final String bundleId, |
| CompilationUnit cu) { |
| String bundleVar; |
| |
| PositionalTypeFinder typeFinder = new PositionalTypeFinder(pos); |
| cu.accept(typeFinder); |
| AnonymousClassDeclaration atd = typeFinder.getEnclosingAnonymType(); |
| TypeDeclaration td = typeFinder.getEnclosingType(); |
| MethodDeclaration meth = typeFinder.getEnclosingMethod(); |
| |
| if (atd == null) { |
| BundleDeclarationFinder bdf = new BundleDeclarationFinder( |
| bundleId, |
| td, |
| meth != null |
| && (meth.getModifiers() & Modifier.STATIC) == Modifier.STATIC); |
| td.accept(bdf); |
| |
| bundleVar = bdf.getVariableName(); |
| } else { |
| BundleDeclarationFinder bdf = new BundleDeclarationFinder( |
| bundleId, |
| atd, |
| meth != null |
| && (meth.getModifiers() & Modifier.STATIC) == Modifier.STATIC); |
| atd.accept(bdf); |
| |
| bundleVar = bdf.getVariableName(); |
| } |
| |
| // Check also method body |
| if (meth != null) { |
| try { |
| InMethodBundleDeclFinder imbdf = new InMethodBundleDeclFinder( |
| bundleId, pos); |
| typeFinder.getEnclosingMethod().accept(imbdf); |
| bundleVar = imbdf.getVariableName() != null ? imbdf |
| .getVariableName() : bundleVar; |
| } catch (Exception e) { |
| // ignore |
| } |
| } |
| |
| return bundleVar; |
| } |
| |
| public static String getNonExistingRBRefName(String bundleId, |
| CompilationUnit cu) { |
| String referenceName = null; |
| int i = 0; |
| |
| while (referenceName == null) { |
| String actRef = bundleId.substring(bundleId.lastIndexOf(".") + 1) |
| + "Ref" + (i == 0 ? "" : i); |
| actRef = actRef.toLowerCase(); |
| |
| VariableFinder vf = new VariableFinder(actRef); |
| cu.accept(vf); |
| |
| if (!vf.isVariableFound()) { |
| referenceName = actRef; |
| break; |
| } |
| |
| i++; |
| } |
| |
| return referenceName; |
| } |
| |
| @Deprecated |
| public static String resolveResourceBundle( |
| MethodInvocation methodInvocation, |
| MethodParameterDescriptor rbDefinition, |
| Map<IVariableBinding, VariableDeclarationFragment> variableBindingManagers) { |
| String bundleName = null; |
| |
| if (methodInvocation.getExpression() instanceof SimpleName) { |
| SimpleName vName = (SimpleName) methodInvocation.getExpression(); |
| IVariableBinding vBinding = (IVariableBinding) vName |
| .resolveBinding(); |
| VariableDeclarationFragment dec = variableBindingManagers |
| .get(vBinding); |
| |
| if (dec.getInitializer() instanceof MethodInvocation) { |
| MethodInvocation init = (MethodInvocation) dec.getInitializer(); |
| |
| // Check declaring class |
| boolean isValidClass = false; |
| ITypeBinding type = init.resolveMethodBinding() |
| .getDeclaringClass(); |
| while (type != null) { |
| if (type.getQualifiedName().equals( |
| rbDefinition.getDeclaringClass())) { |
| isValidClass = true; |
| break; |
| } else { |
| if (rbDefinition.isConsiderSuperclass()) { |
| type = type.getSuperclass(); |
| } else { |
| type = null; |
| } |
| } |
| |
| } |
| if (!isValidClass) { |
| return null; |
| } |
| |
| boolean isValidMethod = false; |
| for (String mn : rbDefinition.getMethodName()) { |
| if (init.getName().getFullyQualifiedName().equals(mn)) { |
| isValidMethod = true; |
| break; |
| } |
| } |
| if (!isValidMethod) { |
| return null; |
| } |
| |
| // retrieve bundlename |
| if (init.arguments().size() < rbDefinition.getPosition() + 1) { |
| return null; |
| } |
| |
| bundleName = ((StringLiteral) init.arguments().get( |
| rbDefinition.getPosition())).getLiteralValue(); |
| } |
| } |
| |
| return bundleName; |
| } |
| |
| public static SLLocation resolveResourceBundleLocation( |
| MethodInvocation methodInvocation, |
| MethodParameterDescriptor rbDefinition, |
| Map<IVariableBinding, VariableDeclarationFragment> variableBindingManagers) { |
| SLLocation bundleDesc = null; |
| |
| if (methodInvocation.getExpression() instanceof SimpleName) { |
| SimpleName vName = (SimpleName) methodInvocation.getExpression(); |
| IVariableBinding vBinding = (IVariableBinding) vName |
| .resolveBinding(); |
| VariableDeclarationFragment dec = variableBindingManagers |
| .get(vBinding); |
| |
| if (dec.getInitializer() instanceof MethodInvocation) { |
| MethodInvocation init = (MethodInvocation) dec.getInitializer(); |
| |
| // Check declaring class |
| boolean isValidClass = false; |
| ITypeBinding type = init.resolveMethodBinding() |
| .getDeclaringClass(); |
| while (type != null) { |
| if (type.getQualifiedName().equals( |
| rbDefinition.getDeclaringClass())) { |
| isValidClass = true; |
| break; |
| } else { |
| if (rbDefinition.isConsiderSuperclass()) { |
| type = type.getSuperclass(); |
| } else { |
| type = null; |
| } |
| } |
| |
| } |
| if (!isValidClass) { |
| return null; |
| } |
| |
| boolean isValidMethod = false; |
| for (String mn : rbDefinition.getMethodName()) { |
| if (init.getName().getFullyQualifiedName().equals(mn)) { |
| isValidMethod = true; |
| break; |
| } |
| } |
| if (!isValidMethod) { |
| return null; |
| } |
| |
| // retrieve bundlename |
| if (init.arguments().size() < rbDefinition.getPosition() + 1) { |
| return null; |
| } |
| |
| StringLiteral bundleLiteral = ((StringLiteral) init.arguments() |
| .get(rbDefinition.getPosition())); |
| bundleDesc = new SLLocation(null, |
| bundleLiteral.getStartPosition(), |
| bundleLiteral.getLength() |
| + bundleLiteral.getStartPosition(), |
| bundleLiteral.getLiteralValue()); |
| } |
| } |
| |
| return bundleDesc; |
| } |
| |
| private static boolean isMatchingMethodDescriptor( |
| MethodInvocation methodInvocation, MethodParameterDescriptor desc) { |
| boolean result = false; |
| |
| if (methodInvocation.resolveMethodBinding() == null) { |
| return false; |
| } |
| |
| String methodName = methodInvocation.resolveMethodBinding().getName(); |
| |
| // Check declaring class |
| ITypeBinding type = methodInvocation.resolveMethodBinding() |
| .getDeclaringClass(); |
| while (type != null) { |
| if (type.getQualifiedName().equals(desc.getDeclaringClass())) { |
| result = true; |
| break; |
| } else { |
| if (desc.isConsiderSuperclass()) { |
| type = type.getSuperclass(); |
| } else { |
| type = null; |
| } |
| } |
| |
| } |
| |
| if (!result) { |
| return false; |
| } |
| |
| result = !result; |
| |
| // Check method name |
| for (String method : desc.getMethodName()) { |
| if (method.equals(methodName)) { |
| result = true; |
| break; |
| } |
| } |
| |
| return result; |
| } |
| |
| public static boolean isMatchingMethodParamDesc( |
| MethodInvocation methodInvocation, String literal, |
| MethodParameterDescriptor desc) { |
| boolean result = isMatchingMethodDescriptor(methodInvocation, desc); |
| |
| if (!result) { |
| return false; |
| } else { |
| result = false; |
| } |
| |
| if (methodInvocation.arguments().size() > desc.getPosition()) { |
| if (methodInvocation.arguments().get(desc.getPosition()) instanceof StringLiteral) { |
| StringLiteral sl = (StringLiteral) methodInvocation.arguments() |
| .get(desc.getPosition()); |
| if (sl.getLiteralValue().trim().toLowerCase() |
| .equals(literal.toLowerCase())) { |
| result = true; |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| public static boolean isMatchingMethodParamDesc( |
| MethodInvocation methodInvocation, StringLiteral literal, |
| MethodParameterDescriptor desc) { |
| int keyParameter = desc.getPosition(); |
| boolean result = isMatchingMethodDescriptor(methodInvocation, desc); |
| |
| if (!result) { |
| return false; |
| } |
| |
| // Check position within method call |
| StructuralPropertyDescriptor spd = literal.getLocationInParent(); |
| if (spd.isChildListProperty()) { |
| @SuppressWarnings("unchecked") |
| List<ASTNode> arguments = (List<ASTNode>) methodInvocation |
| .getStructuralProperty(spd); |
| result = (arguments.size() > keyParameter && arguments |
| .get(keyParameter) == literal); |
| } |
| |
| return result; |
| } |
| |
| public static ICompilationUnit createCompilationUnit(IResource resource) { |
| // Instantiate a new AST parser |
| ASTParser parser = ASTParser.newParser(AST.JLS3); |
| parser.setResolveBindings(true); |
| |
| ICompilationUnit cu = JavaCore.createCompilationUnitFrom(resource |
| .getProject().getFile(resource.getRawLocation())); |
| |
| return cu; |
| } |
| |
| public static CompilationUnit createCompilationUnit(IDocument document) { |
| // Instantiate a new AST parser |
| ASTParser parser = ASTParser.newParser(AST.JLS3); |
| parser.setResolveBindings(true); |
| |
| parser.setSource(document.get().toCharArray()); |
| return (CompilationUnit) parser.createAST(null); |
| } |
| |
| public static void createImport(IDocument doc, IResource resource, |
| CompilationUnit cu, AST ast, ASTRewrite rewriter, |
| String qualifiedClassName) throws CoreException, |
| BadLocationException { |
| |
| ImportFinder impFinder = new ImportFinder(qualifiedClassName); |
| |
| cu.accept(impFinder); |
| |
| if (!impFinder.isImportFound()) { |
| ImportDeclaration id = ast.newImportDeclaration(); |
| id.setName(ast.newName(qualifiedClassName.split("\\."))); |
| id.setStatic(false); |
| |
| ListRewrite lrw = rewriter.getListRewrite(cu, |
| CompilationUnit.IMPORTS_PROPERTY); |
| lrw.insertFirst(id, null); |
| } |
| |
| } |
| |
| public static void createReplaceNonInternationalisationComment( |
| CompilationUnit cu, IDocument doc, int position) { |
| int i = findNonInternationalisationPosition(cu, doc, position); |
| |
| IRegion reg; |
| try { |
| reg = doc.getLineInformationOfOffset(position); |
| doc.replace(reg.getOffset() + reg.getLength(), 0, " //$NON-NLS-" |
| + i + "$"); |
| } catch (BadLocationException e) { |
| Logger.logError(e); |
| } |
| } |
| |
| // TODO export initializer specification into a methodinvocationdefinition |
| @SuppressWarnings("unchecked") |
| public static void createResourceBundleReference(IResource resource, |
| int typePos, IDocument doc, String bundleId, Locale locale, |
| boolean globalReference, String variableName, CompilationUnit cu, AST ast, ASTRewrite rewriter) { |
| |
| try { |
| |
| if (globalReference) { |
| |
| // retrieve compilation unit from document |
| PositionalTypeFinder typeFinder = new PositionalTypeFinder( |
| typePos); |
| cu.accept(typeFinder); |
| ASTNode node = typeFinder.getEnclosingType(); |
| ASTNode anonymNode = typeFinder.getEnclosingAnonymType(); |
| if (anonymNode != null) { |
| node = anonymNode; |
| } |
| |
| MethodDeclaration meth = typeFinder.getEnclosingMethod(); |
| |
| VariableDeclarationFragment vdf = ast |
| .newVariableDeclarationFragment(); |
| vdf.setName(ast.newSimpleName(variableName)); |
| |
| // set initializer |
| vdf.setInitializer(createResourceBundleGetter(ast, bundleId, |
| locale)); |
| |
| FieldDeclaration fd = ast.newFieldDeclaration(vdf); |
| fd.setType(ast.newSimpleType(ast |
| .newName(new String[] { "ResourceBundle" }))); |
| |
| if (meth != null |
| && (meth.getModifiers() & Modifier.STATIC) == Modifier.STATIC) { |
| fd.modifiers().addAll(ast.newModifiers(Modifier.STATIC)); |
| } |
| |
| // rewrite AST |
| ListRewrite lrw = rewriter |
| .getListRewrite( |
| node, |
| node instanceof TypeDeclaration ? TypeDeclaration.BODY_DECLARATIONS_PROPERTY |
| : AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY); |
| lrw.insertAt(fd, 0, null); |
| |
| // create import if required |
| createImport(doc, resource, cu, ast, rewriter, |
| getRBDefinitionDesc().getDeclaringClass()); |
| } else { |
| |
| } |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| protected static MethodInvocation createResourceBundleGetter(AST ast, |
| String bundleId, Locale locale) { |
| MethodInvocation mi = ast.newMethodInvocation(); |
| |
| mi.setName(ast.newSimpleName("getBundle")); |
| mi.setExpression(ast.newName(new String[] { "ResourceBundle" })); |
| |
| // Add bundle argument |
| StringLiteral sl = ast.newStringLiteral(); |
| sl.setLiteralValue(bundleId); |
| mi.arguments().add(sl); |
| |
| // TODO Add Locale argument |
| |
| return mi; |
| } |
| |
| public static ASTNode getEnclosingType(CompilationUnit cu, int pos) { |
| PositionalTypeFinder typeFinder = new PositionalTypeFinder(pos); |
| cu.accept(typeFinder); |
| return (typeFinder.getEnclosingAnonymType() != null) ? typeFinder |
| .getEnclosingAnonymType() : typeFinder.getEnclosingType(); |
| } |
| |
| public static ASTNode getEnclosingType(ASTNode cu, int pos) { |
| PositionalTypeFinder typeFinder = new PositionalTypeFinder(pos); |
| cu.accept(typeFinder); |
| return (typeFinder.getEnclosingAnonymType() != null) ? typeFinder |
| .getEnclosingAnonymType() : typeFinder.getEnclosingType(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| protected static MethodInvocation referenceResource(AST ast, |
| String accessorName, String key, Locale locale) { |
| MethodParameterDescriptor accessorDesc = getRBAccessorDesc(); |
| MethodInvocation mi = ast.newMethodInvocation(); |
| |
| mi.setName(ast.newSimpleName(accessorDesc.getMethodName().get(0))); |
| |
| // Declare expression |
| StringLiteral sl = ast.newStringLiteral(); |
| sl.setLiteralValue(key); |
| |
| // TODO define locale expression |
| if (mi.arguments().size() == accessorDesc.getPosition()) { |
| mi.arguments().add(sl); |
| } |
| |
| SimpleName name = ast.newSimpleName(accessorName); |
| mi.setExpression(name); |
| |
| return mi; |
| } |
| |
| public static String createResourceReference(String bundleId, String key, |
| Locale locale, IResource resource, int typePos, |
| String accessorName, AST ast, ASTRewrite astRewrite, CompilationUnit cu) { |
| |
| final StringLiteralFinder literalFinder = new StringLiteralFinder(typePos); |
| cu.accept(literalFinder); |
| final StringLiteral literal = literalFinder.getStringLiteral(); |
| |
| final MethodInvocation methodInvocation = referenceResource(ast, accessorName, |
| key, locale); |
| |
| astRewrite.replace(literal, methodInvocation, null); |
| |
| String exp = methodInvocation.toString(); |
| |
| // remove semicolon and line break at the end of this expression |
| // statement |
| if (exp.endsWith(";\n")) { |
| exp = exp.substring(0, exp.length() - 2); |
| } |
| |
| return exp; |
| } |
| |
| private static int findNonInternationalisationPosition(CompilationUnit cu, |
| IDocument doc, int offset) { |
| LinePreStringsFinder lsfinder = null; |
| try { |
| lsfinder = new LinePreStringsFinder(offset, doc); |
| cu.accept(lsfinder); |
| } catch (BadLocationException e) { |
| Logger.logError(e); |
| } |
| if (lsfinder == null) { |
| return 1; |
| } |
| |
| List<StringLiteral> strings = lsfinder.getStrings(); |
| |
| return strings.size() + 1; |
| } |
| |
| public static boolean existsNonInternationalisationComment( |
| StringLiteral literal) throws BadLocationException { |
| CompilationUnit cu = (CompilationUnit) literal.getRoot(); |
| ICompilationUnit icu = (ICompilationUnit) cu.getJavaElement(); |
| |
| IDocument doc = null; |
| try { |
| doc = new Document(icu.getSource()); |
| } catch (JavaModelException e) { |
| Logger.logError(e); |
| } |
| |
| // get whole line in which string literal |
| int lineNo = doc.getLineOfOffset(literal.getStartPosition()); |
| int lineOffset = doc.getLineOffset(lineNo); |
| int lineLength = doc.getLineLength(lineNo); |
| String lineOfString = doc.get(lineOffset, lineLength); |
| |
| // search for a line comment in this line |
| int indexComment = lineOfString.indexOf("//"); |
| |
| if (indexComment == -1) { |
| return false; |
| } |
| |
| String comment = lineOfString.substring(indexComment); |
| |
| // remove first "//" of line comment |
| comment = comment.substring(2).toLowerCase(); |
| |
| // split line comments, necessary if more NON-NLS comments exist in one line, eg.: $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3 |
| String[] comments = comment.split("//"); |
| |
| for (String commentFrag : comments) { |
| commentFrag = commentFrag.trim(); |
| |
| // if comment match format: "$non-nls$" then ignore whole line |
| if (commentFrag.matches("^\\$non-nls\\$$")) { |
| return true; |
| |
| // if comment match format: "$non-nls-{number}$" then only |
| // ignore string which is on given position |
| } else if (commentFrag.matches("^\\$non-nls-\\d+\\$$")) { |
| int iString = findNonInternationalisationPosition(cu, doc, |
| literal.getStartPosition()); |
| int iComment = new Integer(commentFrag.substring(9, 10)); |
| if (iString == iComment) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| public static StringLiteral getStringLiteralAtPos(CompilationUnit cu, |
| int position) { |
| StringLiteralFinder strFinder = new StringLiteralFinder(position); |
| cu.accept(strFinder); |
| return strFinder.getStringLiteral(); |
| } |
| |
| static class PositionalTypeFinder extends ASTVisitor { |
| |
| private int position; |
| private TypeDeclaration enclosingType; |
| private AnonymousClassDeclaration enclosingAnonymType; |
| private MethodDeclaration enclosingMethod; |
| |
| public PositionalTypeFinder(int pos) { |
| position = pos; |
| } |
| |
| public TypeDeclaration getEnclosingType() { |
| return enclosingType; |
| } |
| |
| public AnonymousClassDeclaration getEnclosingAnonymType() { |
| return enclosingAnonymType; |
| } |
| |
| public MethodDeclaration getEnclosingMethod() { |
| return enclosingMethod; |
| } |
| |
| @Override |
| public boolean visit(MethodDeclaration node) { |
| if (position >= node.getStartPosition() |
| && position <= (node.getStartPosition() + node.getLength())) { |
| enclosingMethod = node; |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| @Override |
| public boolean visit(TypeDeclaration node) { |
| if (position >= node.getStartPosition() |
| && position <= (node.getStartPosition() + node.getLength())) { |
| enclosingType = node; |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| @Override |
| public boolean visit(AnonymousClassDeclaration node) { |
| if (position >= node.getStartPosition() |
| && position <= (node.getStartPosition() + node.getLength())) { |
| enclosingAnonymType = node; |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| static class ImportFinder extends ASTVisitor { |
| |
| String qName; |
| boolean importFound = false; |
| |
| public ImportFinder(String qName) { |
| this.qName = qName; |
| } |
| |
| public boolean isImportFound() { |
| return importFound; |
| } |
| |
| @Override |
| public boolean visit(ImportDeclaration id) { |
| if (id.getName().getFullyQualifiedName().equals(qName)) { |
| importFound = true; |
| } |
| |
| return true; |
| } |
| } |
| |
| static class VariableFinder extends ASTVisitor { |
| |
| boolean found = false; |
| String variableName; |
| |
| public boolean isVariableFound() { |
| return found; |
| } |
| |
| public VariableFinder(String variableName) { |
| this.variableName = variableName; |
| } |
| |
| @Override |
| public boolean visit(VariableDeclarationFragment vdf) { |
| if (vdf.getName().getFullyQualifiedName().equals(variableName)) { |
| found = true; |
| return false; |
| } |
| |
| return true; |
| } |
| } |
| |
| static class InMethodBundleDeclFinder extends ASTVisitor { |
| String varName; |
| String bundleId; |
| int pos; |
| |
| public InMethodBundleDeclFinder(String bundleId, int pos) { |
| this.bundleId = bundleId; |
| this.pos = pos; |
| } |
| |
| public String getVariableName() { |
| return varName; |
| } |
| |
| @Override |
| public boolean visit(VariableDeclarationFragment fdvd) { |
| if (fdvd.getStartPosition() > pos) { |
| return false; |
| } |
| |
| // boolean bStatic = (fdvd.resolveBinding().getModifiers() & |
| // Modifier.STATIC) == Modifier.STATIC; |
| // if (!bStatic && isStatic) |
| // return true; |
| |
| String tmpVarName = fdvd.getName().getFullyQualifiedName(); |
| |
| if (fdvd.getInitializer() instanceof MethodInvocation) { |
| MethodInvocation fdi = (MethodInvocation) fdvd.getInitializer(); |
| if (isMatchingMethodParamDesc(fdi, bundleId, |
| getRBDefinitionDesc())) { |
| varName = tmpVarName; |
| } |
| } |
| return true; |
| } |
| } |
| |
| static class BundleDeclarationFinder extends ASTVisitor { |
| |
| String varName; |
| String bundleId; |
| ASTNode typeDef; |
| boolean isStatic; |
| |
| public BundleDeclarationFinder(String bundleId, ASTNode td, |
| boolean isStatic) { |
| this.bundleId = bundleId; |
| this.typeDef = td; |
| this.isStatic = isStatic; |
| } |
| |
| public String getVariableName() { |
| return varName; |
| } |
| |
| @Override |
| public boolean visit(MethodDeclaration md) { |
| return true; |
| } |
| |
| @Override |
| public boolean visit(FieldDeclaration fd) { |
| if (getEnclosingType(typeDef, fd.getStartPosition()) != typeDef) { |
| return false; |
| } |
| |
| boolean bStatic = (fd.getModifiers() & Modifier.STATIC) == Modifier.STATIC; |
| if (!bStatic && isStatic) { |
| return true; |
| } |
| |
| if (fd.getType() instanceof SimpleType) { |
| SimpleType fdType = (SimpleType) fd.getType(); |
| String typeName = fdType.getName().getFullyQualifiedName(); |
| String referenceName = getRBDefinitionDesc() |
| .getDeclaringClass(); |
| if (typeName.equals(referenceName) |
| || (referenceName.lastIndexOf(".") >= 0 && typeName |
| .equals(referenceName.substring(referenceName |
| .lastIndexOf(".") + 1)))) { |
| // Check VariableDeclarationFragment |
| if (fd.fragments().size() == 1) { |
| if (fd.fragments().get(0) instanceof VariableDeclarationFragment) { |
| VariableDeclarationFragment fdvd = (VariableDeclarationFragment) fd |
| .fragments().get(0); |
| String tmpVarName = fdvd.getName() |
| .getFullyQualifiedName(); |
| |
| if (fdvd.getInitializer() instanceof MethodInvocation) { |
| MethodInvocation fdi = (MethodInvocation) fdvd |
| .getInitializer(); |
| if (isMatchingMethodParamDesc(fdi, bundleId, |
| getRBDefinitionDesc())) { |
| varName = tmpVarName; |
| } |
| } |
| } |
| } |
| } |
| } |
| return false; |
| } |
| |
| } |
| |
| static class LinePreStringsFinder extends ASTVisitor { |
| private int position; |
| private int line; |
| private List<StringLiteral> strings; |
| private IDocument document; |
| |
| public LinePreStringsFinder(int position, IDocument document) |
| throws BadLocationException { |
| this.document = document; |
| this.position = position; |
| line = document.getLineOfOffset(position); |
| strings = new ArrayList<StringLiteral>(); |
| } |
| |
| public List<StringLiteral> getStrings() { |
| return strings; |
| } |
| |
| @Override |
| public boolean visit(StringLiteral node) { |
| try { |
| if (line == document.getLineOfOffset(node.getStartPosition()) |
| && node.getStartPosition() < position) { |
| strings.add(node); |
| return true; |
| } |
| } catch (BadLocationException e) { |
| } |
| return true; |
| } |
| } |
| |
| static class StringLiteralFinder extends ASTVisitor { |
| private int position; |
| private StringLiteral string; |
| |
| public StringLiteralFinder(int position) { |
| this.position = position; |
| } |
| |
| public StringLiteral getStringLiteral() { |
| return string; |
| } |
| |
| @Override |
| public boolean visit(StringLiteral node) { |
| if (position > node.getStartPosition() |
| && position < (node.getStartPosition() + node.getLength())) { |
| string = node; |
| } |
| return true; |
| } |
| } |
| |
| /** |
| * Decides if an enumeration can be refactored or not. In other words, gives |
| * the OK for the Proposal to display. |
| * |
| * @author Alexej Strelzow |
| */ |
| static class Cal10nEnumLiteralFinder extends ASTVisitor { |
| private int position; |
| private String projectName; |
| |
| private String[] metaData; |
| |
| // [0] resourceBunldeId |
| // [1] key value |
| // [2] relative path (to the project) of the enum file |
| |
| /** |
| * Constructor. |
| * |
| * @param position |
| * The position of the CTRL + Shift + Space operation |
| */ |
| public Cal10nEnumLiteralFinder(String projectName, int position) { |
| this.position = position; |
| this.projectName = projectName; |
| } |
| |
| /** |
| * Following constraints must be fulfilled to make an enum |
| * "refactorable":<br> |
| * <ol> |
| * <li>It must be known by the system (stored in a resource bundle file) |
| * </li> |
| * <li>It must be used by the class ch.qos.cal10n.IMessageConveyor |
| * (Cal10n framework)</li> |
| * </ol> |
| * |
| * {@inheritDoc} |
| */ |
| @Override |
| public boolean visit(MethodInvocation node) { |
| |
| boolean isCal10nCall = "ch.qos.cal10n.IMessageConveyor".equals(node |
| .resolveMethodBinding().getDeclaringClass() |
| .getQualifiedName()); |
| |
| if (!isCal10nCall) { |
| if (node.arguments().size() == 0) { |
| return false; |
| } else { |
| return true; // because the Cal10n call may be an argument! |
| } |
| } else { |
| int startPosition = node.getStartPosition(); |
| int length = startPosition + node.getLength(); |
| if (startPosition < this.position && length > position |
| && !node.arguments().isEmpty() |
| && node.arguments().get(0) instanceof QualifiedName) { |
| QualifiedName qName = (QualifiedName) node.arguments().get( |
| 0); |
| startPosition = qName.getStartPosition(); |
| length = startPosition + qName.getLength(); |
| |
| if (startPosition < this.position && length > position) { |
| String resourceBundleId = getResourceBundleId(qName); |
| String keyName = qName.getName().toString(); |
| |
| if (isKnownBySystem(resourceBundleId, keyName)) { |
| String path = qName.resolveTypeBinding() |
| .getJavaElement().getResource() |
| .getFullPath().toPortableString(); |
| this.metaData = new String[3]; |
| this.metaData[0] = resourceBundleId; |
| this.metaData[1] = keyName; |
| this.metaData[2] = path; |
| } |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| private boolean isKnownBySystem(String resourceBundleId, String keyName) { |
| IMessagesBundleGroup messagesBundleGroup = RBManager.getInstance( |
| this.projectName).getMessagesBundleGroup(resourceBundleId); |
| return messagesBundleGroup.containsKey(keyName); |
| } |
| |
| private String getResourceBundleId(QualifiedName qName) { |
| IAnnotationBinding[] annotations = qName.resolveTypeBinding() |
| .getAnnotations(); |
| for (IAnnotationBinding annotation : annotations) { |
| if ("BaseName".equals(annotation.getName())) { |
| return (String) annotation.getAllMemberValuePairs()[0] |
| .getValue(); |
| } |
| } |
| |
| return null; |
| } |
| |
| public String[] getMetaData() { |
| return metaData; |
| } |
| } |
| |
| /** |
| * Returns whether a refactoring proposal will be shown or not. |
| * |
| * @param projectName |
| * The name of the project the cu is in |
| * @param cu |
| * The {@link CompilationUnit} to analyze |
| * @param i |
| * The starting point to begin the analysis |
| * @return Meta data of the enum key to refactor or null |
| */ |
| public static String[] getCal10nEnumLiteralDataAtPos(String projectName, |
| CompilationUnit cu, int i) { |
| Cal10nEnumLiteralFinder enumFinder = new Cal10nEnumLiteralFinder( |
| projectName, i); |
| cu.accept(enumFinder); |
| return enumFinder.getMetaData(); |
| } |
| } |