public void call(SourceUnit source) throws CompilationFailedException { List<ClassNode> classes = source.ast.getClasses(); for (ClassNode node : classes) { CompileUnit cu = node.getCompileUnit(); for (Iterator iter = cu.iterateClassNodeToCompile(); iter.hasNext(); ) { String name = (String) iter.next(); SourceUnit su = ast.getScriptSourceLocation(name); List<ClassNode> classesInSourceUnit = su.ast.getClasses(); StringBuffer message = new StringBuffer(); message .append("Compilation incomplete: expected to find the class ") .append(name) .append(" in ") .append(su.getName()); if (classesInSourceUnit.isEmpty()) { message.append(", but the file seems not to contain any classes"); } else { message.append(", but the file contains the classes: "); boolean first = true; for (ClassNode cn : classesInSourceUnit) { if (!first) { message.append(", "); } else { first = false; } message.append(cn.getName()); } } getErrorCollector() .addErrorAndContinue(new SimpleMessage(message.toString(), CompilationUnit.this)); iter.remove(); } } }
public static void visitScriptCode(SourceUnit source, GroovyCodeVisitor transformer) { source.getAST().getStatementBlock().visit(transformer); for (Object method : source.getAST().getMethods()) { MethodNode methodNode = (MethodNode) method; methodNode.getCode().visit(transformer); } }
@Override public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { ImportCustomizer importCustomizer = new ImportCustomizer(); // Additional auto configuration for (CompilerAutoConfiguration autoConfiguration : GroovyCompiler.this.compilerAutoConfigurations) { if (autoConfiguration.matches(classNode)) { if (GroovyCompiler.this.configuration.isGuessImports()) { autoConfiguration.applyImports(importCustomizer); importCustomizer.call(source, context, classNode); } if (source.getAST().getClasses().size() > 0 && classNode.equals(source.getAST().getClasses().get(0))) { autoConfiguration.applyToMainClass( GroovyCompiler.this.loader, GroovyCompiler.this.configuration, context, source, classNode); } autoConfiguration.apply( GroovyCompiler.this.loader, GroovyCompiler.this.configuration, context, source, classNode); } } importCustomizer.call(source, context, classNode); }
private void verifyCompilePhase(AnnotationNode annotation, Class<?> klass) { GroovyASTTransformation transformationClass = klass.getAnnotation(GroovyASTTransformation.class); if (transformationClass != null) { CompilePhase specifiedCompilePhase = transformationClass.phase(); if (specifiedCompilePhase.getPhaseNumber() < CompilePhase.SEMANTIC_ANALYSIS.getPhaseNumber()) { source .getErrorCollector() .addError( new SimpleMessage( annotation.getClassNode().getName() + " is defined to be run in compile phase " + specifiedCompilePhase + ". Local AST transformations must run in " + CompilePhase.SEMANTIC_ANALYSIS + " or later!", source)); } } else { source .getErrorCollector() .addError( new SimpleMessage( "AST transformation implementation classes must be annotated with " + GroovyASTTransformation.class.getName() + ". " + klass.getName() + " lacks this annotation.", source)); } }
public void visit(ASTNode[] nodes, SourceUnit source) { List<ClassNode> classes = source.getAST().getClasses(); AnnotationNode annotation = null; for (ClassNode clazz : classes) { annotation = findAnnotation(clazz); if (annotation != null) { break; } } if (annotation == null) { return; } int[] array = extractLineNumberArray(annotation); if (array != null) { LineNumberVisitor visitor = new LineNumberVisitor(array); for (ClassNode clazz : classes) { visitor.visitClass(clazz); } } String sourceName = extractSourceName(annotation); if (sourceName != null) { source.getAST().setDescription(sourceName); // source.name = sourceName Field field = ReflectionUtils.findField(SourceUnit.class, "name"); field.setAccessible(true); ReflectionUtils.setField(field, source, sourceName); } }
@SuppressWarnings("unused") private List<String> getTransformClassNames( AnnotationNode annotation, Annotation transformClassAnnotation) { List<String> result = new ArrayList<String>(); try { Method valueMethod = transformClassAnnotation.getClass().getMethod("value"); String[] names = (String[]) valueMethod.invoke(transformClassAnnotation); result.addAll(Arrays.asList(names)); Method classesMethod = transformClassAnnotation.getClass().getMethod("classes"); Class[] classes = (Class[]) classesMethod.invoke(transformClassAnnotation); for (Class klass : classes) { result.add(klass.getName()); } if (names.length > 0 && classes.length > 0) { source .getErrorCollector() .addError( new SimpleMessage( "@GroovyASTTransformationClass in " + annotation.getClassNode().getName() + " should specify transforms only by class names or by classes and not by both", source)); } } catch (Exception e) { source.addException(e); } return result; }
public void call(SourceUnit source) throws CompilationFailedException { source.convert(); CompilationUnit.this.ast.addModule(source.getAST()); if (CompilationUnit.this.progressCallback != null) { CompilationUnit.this.progressCallback.call(source, CompilationUnit.this.phase); } }
public static ClassNode getScriptClass(SourceUnit source) { if (source.getAST().getStatementBlock().getStatements().isEmpty() && source.getAST().getMethods().isEmpty()) { // There is no script class when there are no statements or methods declared in the script return null; } return source.getAST().getClasses().get(0); }
public void call(SourceUnit source) throws CompilationFailedException { if (source.phase < phase) { source.gotoPhase(phase); } if (source.phase == phase && phaseComplete && !source.phaseComplete) { source.completePhase(); } }
// GRECLIPSE start protected void addTypeError(String msg, ClassNode expr) { int line = expr.getLineNumber(); int col = expr.getColumnNumber(); SourceUnit source = getSourceUnit(); source .getErrorCollector() .addErrorAndContinue( // GRECLIPSE: start new SyntaxErrorMessage( new PreciseSyntaxException( msg + '\n', line, col, expr.getNameStart(), expr.getNameEnd()), source) // end ); }
@Override public void call(SourceUnit source) { if (!source.getAST().getMethods().isEmpty()) { hasMethods = true; } emptyScript = isEmpty(source); }
/** * Snoops through the declaring class and all parents looking for methods * * <ul> * <li><code>public String getMessage(java.lang.String)</code> * <li><code>public String getMessage(java.lang.String, java.util.Locale)</code> * <li><code>public String getMessage(java.lang.String, java.lang.Object[])</code> * <li><code>public String getMessage(java.lang.String, java.lang.Object[], java.util.Locale) * </code> * <li><code>public String getMessage(java.lang.String, java.util.List)</code> * <li><code>public String getMessage(java.lang.String, java.util.List, java.util.Locale)</code> * <li><code>public String getMessage(java.lang.String, java.util.Map)</code> * <li><code>public String getMessage(java.lang.String, java.util.Map, java.util.Locale)</code> * <li><code>public String getMessage(java.lang.String, java.lang.String)</code> * <li><code>public String getMessage(java.lang.String, java.lang.String, java.util.Locale) * </code> * <li><code>public String getMessage(java.lang.String, java.lang.Object[], java.lang.String) * </code> * <li><code> * public String getMessage(java.lang.String, java.lang.Object[], java.lang.String, java.util.Locale) * </code> * <li><code>public String getMessage(java.lang.String, java.util.List, java.lang.String)</code> * <li><code> * public String getMessage(java.lang.String, java.util.List, java.lang.String, java.util.Locale) * </code> * <li><code>public String getMessage(java.lang.String, java.util.Map, java.lang.String)</code> * <li><code> * public String getMessage(java.lang.String, java.util.Map, java.lang.String, java.util.Locale) * </code> * </ul> * * If any are defined all must be defined or a compilation error results. * * @param declaringClass the class to search * @param sourceUnit the source unit, for error reporting. {@code @NotNull}. * @return true if property change support should be added */ protected static boolean needsMessageSource(ClassNode declaringClass, SourceUnit sourceUnit) { boolean found = false; ClassNode consideredClass = declaringClass; while (consideredClass != null) { for (MethodNode method : consideredClass.getMethods()) { // just check length, MOP will match it up found = method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 1; found |= method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 2; found |= method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 3; found |= method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 4; if (found) return false; } consideredClass = consideredClass.getSuperClass(); } if (found) { sourceUnit .getErrorCollector() .addErrorAndContinue( new SimpleMessage( "@MessageSourceAware cannot be processed on " + declaringClass.getName() + " because some but not all of variants of getMessage() were declared in the current class or super classes.", sourceUnit)); return false; } return true; }
private void addTransformsToClassNode( AnnotationNode annotation, String[] transformClassNames, Class[] transformClasses) { if (transformClassNames.length == 0 && transformClasses.length == 0) { source .getErrorCollector() .addError( new SimpleMessage( "@GroovyASTTransformationClass in " + annotation.getClassNode().getName() + " does not specify any transform class names/classes", source)); } if (transformClassNames.length > 0 && transformClasses.length > 0) { source .getErrorCollector() .addError( new SimpleMessage( "@GroovyASTTransformationClass in " + annotation.getClassNode().getName() + " should specify transforms only by class names or by classes and not by both", source)); } for (String transformClass : transformClassNames) { try { Class klass = transformLoader.loadClass(transformClass, false, true, false); verifyAndAddTransform(annotation, klass); } catch (ClassNotFoundException e) { source .getErrorCollector() .addErrorAndContinue( new SimpleMessage( "Could not find class for Transformation Processor " + transformClass + " declared by " + annotation.getClassNode().getName(), source)); } } for (Class klass : transformClasses) { verifyAndAddTransform(annotation, klass); } }
public static boolean isVisible(SourceUnit source, String className) { try { source.getClassLoader().loadClass(className); return true; } catch (ClassNotFoundException e) { return false; } }
private Class[] getTransformClasses(ClassNode classNode) { if (!classNode.hasClass()) { List<AnnotationNode> annotations = classNode.getAnnotations(); AnnotationNode transformAnnotation = null; for (AnnotationNode anno : annotations) { if (anno.getClassNode().getName().equals(GroovyASTTransformationClass.class.getName())) { transformAnnotation = anno; break; } } if (transformAnnotation != null) { Expression expr = (Expression) transformAnnotation.getMember("classes"); if (expr == null) { return NO_CLASSES; } Class<?>[] values = NO_CLASSES; // Will need to extract the classnames if (expr instanceof ListExpression) { List<Class<?>> loadedClasses = new ArrayList<Class<?>>(); ListExpression expression = (ListExpression) expr; List<Expression> expressions = expression.getExpressions(); for (Expression oneExpr : expressions) { String classname = ((ClassExpression) oneExpr).getType().getName(); try { Class<?> clazz = Class.forName(classname, false, transformLoader); loadedClasses.add(clazz); } catch (ClassNotFoundException cnfe) { source .getErrorCollector() .addError( new SimpleMessage( "Ast transform processing, cannot find " + classname, source)); } } if (loadedClasses.size() != 0) { values = loadedClasses.toArray(new Class<?>[loadedClasses.size()]); } return values; } else { } throw new RuntimeException( "nyi implemented in eclipse: need to support: " + expr + " (class=" + expr.getClass() + ")"); } return null; } else { Annotation transformClassAnnotation = getTransformClassAnnotation(classNode); if (transformClassAnnotation == null) { return null; } return getTransformClasses(transformClassAnnotation); } }
private boolean addCollectedAnnotations( List<AnnotationNode> collected, AnnotationNode aliasNode, AnnotatedNode origin) { ClassNode classNode = aliasNode.getClassNode(); boolean ret = false; for (AnnotationNode annotation : classNode.getAnnotations()) { if (annotation.getClassNode().getName().equals(AnnotationCollector.class.getName())) { Expression processorExp = annotation.getMember("processor"); AnnotationCollectorTransform act = null; assertStringConstant(processorExp); if (processorExp != null) { String className = (String) ((ConstantExpression) processorExp).getValue(); Class klass = loadTransformClass(className, aliasNode); if (klass != null) { try { act = (AnnotationCollectorTransform) klass.newInstance(); } catch (InstantiationException e) { source.getErrorCollector().addErrorAndContinue(new ExceptionMessage(e, true, source)); } catch (IllegalAccessException e) { source.getErrorCollector().addErrorAndContinue(new ExceptionMessage(e, true, source)); } } } else { act = new AnnotationCollectorTransform(); } if (act != null) { // GRECLIPSE edit // collected.addAll(act.visit(annotation, aliasNode, origin, source)); // original annotation added to metadata to prevent import organizer from deleting its // import List<AnnotationNode> visitResult = act.visit(annotation, aliasNode, origin, source); for (AnnotationNode annotationNode : visitResult) { Set<AnnotationNode> aliases = annotationNode.getNodeMetaData("AnnotationCollector"); if (aliases == null) annotationNode.setNodeMetaData("AnnotationCollector", (aliases = new HashSet(1))); aliases.add(aliasNode); } collected.addAll(visitResult); // GRECLIPSE end } ret = true; } } return ret; }
private Class[] getTransformClasses(Annotation transformClassAnnotation) { try { Method classesMethod = transformClassAnnotation.getClass().getMethod("classes"); return (Class[]) classesMethod.invoke(transformClassAnnotation); } catch (Exception e) { source.addException(e); return new Class[0]; } }
private String[] getTransformClassNames(Annotation transformClassAnnotation) { try { Method valueMethod = transformClassAnnotation.getClass().getMethod("value"); return (String[]) valueMethod.invoke(transformClassAnnotation); } catch (Exception e) { source.addException(e); return new String[0]; } }
private void changeBugText(GroovyBugError e, SourceUnit context) { e.setBugText( "exception in phase '" + getPhaseDescription() + "' in source unit '" + ((context != null) ? context.getName() : "?") + "' " + e.getBugText()); }
/** * Attempts to parse the specified code with the specified tolerance. Updates the <code>parser * </code> and <code>error</code> members appropriately. Returns true if the text parsed, false * otherwise. The attempts to identify and suppress errors resulting from the unfinished source * text. * * <p><b>Note:</b> taken from {@link groovy.ui.InteractiveShell}. */ private static boolean parse(final String code, final int tolerance) { assert code != null; boolean parsed = false; // Create the parser and attempt to parse the text as a top-level statement. try { SourceUnit parser = SourceUnit.create("vrl-script", code, tolerance); parser.parse(); parsed = true; } // We report errors other than unexpected EOF to the user. catch (CompilationFailedException e) { // } catch (Exception e) { // } return parsed; }
/** * Generates a fatal compilation error * * @param sourceUnit the SourceUnit * @param astNode the ASTNode which caused the error * @param message The error message * @param fatal indicates if this is a fatal error */ public static void error( final SourceUnit sourceUnit, final ASTNode astNode, final String message, final boolean fatal) { final SyntaxException syntaxException = new SyntaxException(message, astNode.getLineNumber(), astNode.getColumnNumber()); final SyntaxErrorMessage syntaxErrorMessage = new SyntaxErrorMessage(syntaxException, sourceUnit); sourceUnit.getErrorCollector().addError(syntaxErrorMessage, fatal); }
private boolean isEmpty(SourceUnit source) { List<Statement> statements = source.getAST().getStatementBlock().getStatements(); for (Statement statement : statements) { if (AstUtils.mayHaveAnEffect(statement)) { return false; } } // No statements, or no statements that have an effect return true; }
/** Adds a SourceUnit to the unit. */ public SourceUnit addSource(SourceUnit source) { String name = source.getName(); source.setClassLoader(this.classLoader); for (SourceUnit su : queuedSources) { if (name.equals(su.getName())) return su; } // GRECLIPSE: start if (iterating) { GroovyBugError gbe = new GroovyBugError( "Queuing new source whilst already iterating. Queued source is '" + source.getName() + "'"); gbe.printStackTrace(); throw gbe; } // end queuedSources.add(source); return source; }
private void verifyClass(AnnotationNode annotation, Class klass) { if (!ASTTransformation.class.isAssignableFrom(klass)) { source .getErrorCollector() .addError( new SimpleMessage( "Not an ASTTransformation: " + klass.getName() + " declared by " + annotation.getClassNode().getName(), source)); } }
private void assertStringConstant(Expression exp) { if (exp == null) return; if (!(exp instanceof ConstantExpression)) { source .getErrorCollector() .addErrorAndContinue( new SyntaxErrorMessage( new SyntaxException( "Expected a String constant.", exp.getLineNumber(), exp.getColumnNumber()), source)); } ConstantExpression ce = (ConstantExpression) exp; if (!(ce.getValue() instanceof String)) { source .getErrorCollector() .addErrorAndContinue( new SyntaxErrorMessage( new SyntaxException( "Expected a String constant.", exp.getLineNumber(), exp.getColumnNumber()), source)); } }
protected void addError(String msg, ASTNode expr) { int line = expr.getLineNumber(); int col = expr.getColumnNumber(); // GRECLIPSE int start = expr.getStart(); int end = expr.getEnd() - 1; if (expr instanceof ClassNode) { // assume we have a class declaration ClassNode cn = (ClassNode) expr; if (cn.getNameEnd() > 0) { start = cn.getNameStart(); end = cn.getNameEnd(); } else if (cn.getComponentType() != null) { // avoid extra whitespace after closing ] end--; } } else if (expr instanceof DeclarationExpression) { // assume that we just want to underline the variable declaration DeclarationExpression decl = (DeclarationExpression) expr; Expression lhs = decl.getLeftExpression(); start = lhs.getStart(); // avoid extra space before = if a variable end = lhs instanceof VariableExpression ? start + lhs.getText().length() - 1 : lhs.getEnd() - 1; } // end SourceUnit source = getSourceUnit(); source .getErrorCollector() .addErrorAndContinue( // GRECLIPSE: start new SyntaxErrorMessage( new PreciseSyntaxException(msg + '\n', line, col, start, end), source) // end ); }
private Class doParseClass(GroovyCodeSource codeSource) { validate(codeSource); Class answer; // Was neither already loaded nor compiling, so compile and add to cache. CompilationUnit unit = createCompilationUnit(config, codeSource.getCodeSource()); if (recompile != null && recompile || recompile == null && config.getRecompileGroovySource()) { unit.addFirstPhaseOperation( TimestampAdder.INSTANCE, CompilePhase.CLASS_GENERATION.getPhaseNumber()); } SourceUnit su = null; File file = codeSource.getFile(); if (file != null) { su = unit.addSource(file); } else { URL url = codeSource.getURL(); if (url != null) { su = unit.addSource(url); } else { su = unit.addSource(codeSource.getName(), codeSource.getScriptText()); } } ClassCollector collector = createCollector(unit, su); unit.setClassgenCallback(collector); int goalPhase = Phases.CLASS_GENERATION; if (config != null && config.getTargetDirectory() != null) goalPhase = Phases.OUTPUT; unit.compile(goalPhase); answer = collector.generatedClass; String mainClass = su.getAST().getMainClassName(); for (Object o : collector.getLoadedClasses()) { Class clazz = (Class) o; String clazzName = clazz.getName(); definePackage(clazzName); setClassCacheEntry(clazz); if (clazzName.equals(mainClass)) answer = clazz; } return answer; }
private void changeBaseScriptTypeFromPackageOrImport( final SourceUnit source, final AnnotatedNode parent, final AnnotationNode node) { Expression value = node.getMember("value"); if (!(value instanceof ClassExpression)) { addError("Annotation " + MY_TYPE_NAME + " member 'value' should be a class literal.", value); return; } List<ClassNode> classes = source.getAST().getClasses(); for (ClassNode classNode : classes) { if (classNode.isScriptBody()) { changeBaseScriptType(parent, classNode, value.getType()); } } }
public static void filterAndTransformStatements( SourceUnit source, FilteredTransformer<? extends Statement, ? super Statement> transformer) { ListIterator<Statement> statementIterator = source.getAST().getStatementBlock().getStatements().listIterator(); while (statementIterator.hasNext()) { Statement statement = statementIterator.next(); if (transformer.getSpec().isSatisfiedBy(statement)) { Statement transformed = transformer.getTransformer().transform(statement); statementIterator.set(transformed); } else { statementIterator.remove(); } } }
/** * Dequeues any source units add through addSource and resets the compiler phase to * initialization. * * <p>Note: this does not mean a file is recompiled. If a SourceUnit has already passed a phase it * is skipped until a higher phase is reached. * * @return true if there was a queued source * @throws CompilationFailedException */ protected boolean dequeued() throws CompilationFailedException { boolean dequeue = !queuedSources.isEmpty(); while (!queuedSources.isEmpty()) { SourceUnit su = queuedSources.removeFirst(); String name = su.getName(); // GRECLIPSE: start if (iterating) { GroovyBugError gbe = new GroovyBugError( "Damaging 'names' whilst already iterating. Name getting added is '" + su.getName() + "'"); gbe.printStackTrace(); throw gbe; } // end names.add(name); sources.put(name, su); } if (dequeue) { gotoPhase(Phases.INITIALIZATION); } return dequeue; }