private Map<String, GroovyClassDoc> parseGroovy(String packagePath, String file, String src) throws RecognitionException, TokenStreamException { SourceBuffer sourceBuffer = new SourceBuffer(); GroovyRecognizer parser = getGroovyParser(src, sourceBuffer); try { parser.compilationUnit(); } catch (OutOfMemoryError e) { log.error("Out of memory while processing: " + packagePath + "/" + file); throw e; } AST ast = parser.getAST(); // now do the business Visitor visitor = new SimpleGroovyClassDocAssembler(packagePath, file, sourceBuffer, links, properties, true); AntlrASTProcessor traverser = new SourceCodeTraversal(visitor); traverser.process(ast); return ((SimpleGroovyClassDocAssembler) visitor).getGroovyClassDocs(); }
@Override public void visitCtorIdent(GroovySourceAST t, int visit) { if (visit == OPENING_VISIT && !insideEnum && !insideAnonymousInnerClass()) { SimpleGroovyClassDoc currentClassDoc = getCurrentClassDoc(); SimpleGroovyConstructorDoc currentConstructorDoc = new SimpleGroovyConstructorDoc(currentClassDoc.name(), currentClassDoc); currentConstructorDoc.setRawCommentText(getJavaDocCommentsBeforeNode(t)); processModifiers(t, currentConstructorDoc); addParametersTo(t, currentConstructorDoc); processAnnotations(t, currentConstructorDoc); currentClassDoc.add(currentConstructorDoc); } }
private boolean insideAnonymousInnerClass() { GroovySourceAST grandParentNode = getGrandParentNode(); return grandParentNode != null && grandParentNode.getType() == LITERAL_new; }
private SimpleGroovyClassDoc getCurrentClassDoc() { if (stack.isEmpty()) return null; GroovySourceAST node = getParentNode(); if (isTopLevelConstruct(node)) return foundClasses.get(getIdentFor(node)); GroovySourceAST saved = stack.pop(); SimpleGroovyClassDoc result = getCurrentClassDoc(); stack.push(saved); return result; }
private SimpleGroovyMethodDoc createMethod(GroovySourceAST t, SimpleGroovyClassDoc currentClassDoc) { String methodName = getIdentFor(t); SimpleGroovyMethodDoc currentMethodDoc = new SimpleGroovyMethodDoc(methodName, currentClassDoc); currentMethodDoc.setRawCommentText(getJavaDocCommentsBeforeNode(t)); processModifiers(t, currentMethodDoc); currentMethodDoc.setReturnType(new SimpleGroovyType(getTypeOrDefault(t))); addParametersTo(t, currentMethodDoc); processAnnotations(t, currentMethodDoc); return currentMethodDoc; }
@Override public void visitVariableDef(GroovySourceAST t, int visit) { if (visit == OPENING_VISIT && !insideAnonymousInnerClass() && isFieldDefinition()) { SimpleGroovyClassDoc currentClassDoc = getCurrentClassDoc(); if (currentClassDoc != null) { String fieldName = getIdentFor(t); currentFieldDoc = new SimpleGroovyFieldDoc(fieldName, currentClassDoc); currentFieldDoc.setRawCommentText(getJavaDocCommentsBeforeNode(t)); boolean isProp = processModifiers(t, currentFieldDoc); currentFieldDoc.setType(new SimpleGroovyType(getTypeOrDefault(t))); processAnnotations(t, currentFieldDoc); if (isProp) { currentClassDoc.addProperty(currentFieldDoc); } else { currentClassDoc.add(currentFieldDoc); } } } }
@Override public void visitClassDef(GroovySourceAST t, int visit) { if (visit == OPENING_VISIT) { SimpleGroovyClassDoc parent = getCurrentClassDoc(); String shortName = getIdentFor(t); String className = shortName; if (parent != null && isNested() && !insideAnonymousInnerClass()) { className = parent.name() + "." + className; } else { foundClasses = new HashMap<String, SimpleGroovyClassDoc>(); } SimpleGroovyClassDoc current = (SimpleGroovyClassDoc) classDocs.get(packagePath + FS + className); if (current == null) { current = new SimpleGroovyClassDoc(importedClassesAndPackages, aliases, className, links); current.setGroovy(isGroovy); } current.setRawCommentText(getJavaDocCommentsBeforeNode(t)); current.setFullPathName(packagePath + FS + current.name()); current.setTokenType(t.getType()); current.setNameWithTypeArgs(getIdentPlusTypeArgsFor(t)); processAnnotations(t, current); processModifiers(t, current); classDocs.put(current.getFullPathName(), current); foundClasses.put(shortName, current); if (parent != null) { parent.addNested(current); current.setOuter(parent); } } }
@Override public void visitEnumConstantDef(GroovySourceAST t, int visit) { if (visit == OPENING_VISIT) { SimpleGroovyClassDoc currentClassDoc = getCurrentClassDoc(); insideEnum = true; String enumConstantName = getIdentFor(t); SimpleGroovyFieldDoc currentEnumConstantDoc = new SimpleGroovyFieldDoc(enumConstantName, currentClassDoc); currentEnumConstantDoc.setRawCommentText(getJavaDocCommentsBeforeNode(t)); processModifiers(t, currentEnumConstantDoc); String typeName = getTypeNodeAsText(t.childOfType(TYPE), currentClassDoc.getTypeDescription()); currentEnumConstantDoc.setType(new SimpleGroovyType(typeName)); currentClassDoc.addEnumConstant(currentEnumConstantDoc); } else if (visit == CLOSING_VISIT) { insideEnum = false; } }
@Override public void visitMethodDef(GroovySourceAST t, int visit) { if (visit == OPENING_VISIT && !insideEnum && !insideAnonymousInnerClass()) { SimpleGroovyClassDoc currentClassDoc = getCurrentClassDoc(); if (currentClassDoc != null) { String methodName = getIdentFor(t); SimpleGroovyMethodDoc currentMethodDoc = new SimpleGroovyMethodDoc(methodName, currentClassDoc); currentMethodDoc.setRawCommentText(getJavaDocCommentsBeforeNode(t)); processModifiers(t, currentMethodDoc); currentMethodDoc.setReturnType(new SimpleGroovyType(getTypeOrDefault(t))); addParametersTo(t, currentMethodDoc); processAnnotations(t, currentMethodDoc); currentClassDoc.add(currentMethodDoc); } } }
private void addParametersTo(GroovySourceAST t, SimpleGroovyExecutableMemberDoc executableMemberDoc) { // parameters GroovySourceAST parametersNode = t.childOfType(PARAMETERS); if (parametersNode != null && parametersNode.getNumberOfChildren() > 0) { GroovySourceAST currentNode = (GroovySourceAST) parametersNode.getFirstChild(); while (currentNode != null) { String parameterTypeName = getTypeOrDefault(currentNode); String parameterName = getText(currentNode.childOfType(IDENT)); SimpleGroovyParameter parameter = new SimpleGroovyParameter(parameterName); parameter.setVararg(currentNode.getType() == VARIABLE_PARAMETER_DEF); parameter.setTypeName(parameterTypeName); GroovySourceAST modifiers = currentNode.childOfType(MODIFIERS); if (modifiers != null) { List<GroovySourceAST> annotations = modifiers.childrenOfType(ANNOTATION); for (GroovySourceAST a : annotations) { addAnnotationRef(parameter, a); } } executableMemberDoc.add(parameter); if (currentNode.getNumberOfChildren() == 4) { handleDefaultValue(currentNode, parameter); } currentNode = (GroovySourceAST) currentNode.getNextSibling(); } } }
public void visitCtorIdent(GroovySourceAST t,int visit) { if (visit == OPENING_VISIT) { if (!insideAnonymousInnerClass()) { // now... get relevant values from the AST // name of class for the constructor currentConstructorDoc = new SimpleGroovyConstructorDoc(currentClassDoc.name()); // comments String commentText = getJavaDocCommentsBeforeNode(t); currentConstructorDoc.setRawCommentText(commentText); // modifiers processModifiers(t, currentConstructorDoc); addParametersTo(currentConstructorDoc, t, visit); // don't forget to tell the class about this constructor. currentClassDoc.add(currentConstructorDoc); } } }
public void visitVariableDef(GroovySourceAST t, int visit) { if (visit == OPENING_VISIT) { if (!insideAnonymousInnerClass()) { GroovySourceAST parentNode = getParentNode(); // todo - what about fields in interfaces/enums etc if (parentNode != null && parentNode.getType() == GroovyTokenTypes.OBJBLOCK) { // this should restrict us to just field definitions, and not local variable definitions // field name String fieldName = t.childOfType(GroovyTokenTypes.IDENT).getText(); SimpleGroovyFieldDoc currentFieldDoc = new SimpleGroovyFieldDoc(fieldName); // comments - todo check this is doing the right thing for fields... String commentText = getJavaDocCommentsBeforeNode(t); currentFieldDoc.setRawCommentText(commentText); // modifiers processModifiers(t, currentFieldDoc); // type String typeName = getTypeNodeAsText(t.childOfType(GroovyTokenTypes.TYPE),"def"); SimpleGroovyType type = new SimpleGroovyType(typeName); // todo !!! currentFieldDoc.setType(type); // don't forget to tell the class about this field so carefully constructed. currentClassDoc.add(currentFieldDoc); } } } }
private SimpleGroovyClassDoc getCurrentClassDoc() { GroovySourceAST pn = getParentNode(); if (isTopLevelConstruct(pn)) return foundClasses.get(getIdentFor(pn)); GroovySourceAST gpn = getGrandParentNode(); if (isTopLevelConstruct(gpn)) return foundClasses.get(getIdentFor(gpn)); return null; }
@Override public void visitMethodDef(GroovySourceAST t, int visit) { if (visit == OPENING_VISIT && !insideEnum && !insideAnonymousInnerClass()) { SimpleGroovyClassDoc currentClassDoc = getCurrentClassDoc(); if (currentClassDoc == null) { // assume we have a script if ("true".equals(properties.getProperty("processScripts", "true"))) { currentClassDoc = new SimpleGroovyClassDoc(importedClassesAndPackages, aliases, className, links); currentClassDoc.setFullPathName(packagePath + FS + className); currentClassDoc.setPublic(true); currentClassDoc.setScript(true); currentClassDoc.setGroovy(isGroovy); currentClassDoc.setSuperClassName("groovy/lang/Script"); if ("true".equals(properties.getProperty("includeMainForScripts", "true"))) { currentClassDoc.add(createMainMethod(currentClassDoc)); } classDocs.put(currentClassDoc.getFullPathName(), currentClassDoc); if (foundClasses == null) { foundClasses = new HashMap<String, SimpleGroovyClassDoc>(); } foundClasses.put(className, currentClassDoc); } else { return; } } SimpleGroovyMethodDoc currentMethodDoc = createMethod(t, currentClassDoc); currentClassDoc.add(currentMethodDoc); } }
@Override public void visitMethodDef(GroovySourceAST t, int visit) { if (visit == OPENING_VISIT && !insideEnum && !insideAnonymousInnerClass()) { SimpleGroovyClassDoc currentClassDoc = getCurrentClassDoc(); if (currentClassDoc == null) { // assume we have a script if ("true".equals(properties.getProperty("processScripts", "true"))) { currentClassDoc = getOrMakeScriptClassDoc(); } else { return; } } SimpleGroovyMethodDoc currentMethodDoc = createMethod(t, currentClassDoc); StringBuilder params = new StringBuilder(); getTypeParameters(t.childOfType(TYPE_PARAMETERS), params, "def"); currentMethodDoc.setTypeParameters(params.toString()); currentClassDoc.add(currentMethodDoc); } }
private String getTypeNodeAsText(GroovySourceAST typeNode, String defaultText) { // TODO refactor to retain richer type information rather than converting to String if (typeNode == null) { return defaultText; } if (typeNode.getType() == TYPE) { return getAsText(typeNode, defaultText); } else if (typeNode.getType() == TYPE_ARGUMENT) { return getTypeNodeAsText((GroovySourceAST) typeNode.getFirstChild(), defaultText); } else if (typeNode.getType() == WILDCARD_TYPE) { AST next = typeNode.getNextSibling(); if (next == null && typeNode.getFirstChild() != null) { // Java2Groovy produces a slightly different tree structure (TODO fix converter or java.g instead?) next = typeNode.getFirstChild(); } if (next == null) return "?"; String boundType = getTypeNodeAsText((GroovySourceAST) next.getFirstChild(), defaultText); if (next.getType() == TYPE_UPPER_BOUNDS) return "? extends " + boundType; if (next.getType() == TYPE_LOWER_BOUNDS) return "? super " + boundType; } else if (typeNode.getType() == IDENT) { return getAsTextCurrent(typeNode, defaultText); } return defaultText; }
private void gobbleComments(GroovySourceAST t, int visit) { if (visit == OPENING_VISIT) { SimpleGroovyClassDoc currentClassDoc = getCurrentClassDoc(); if (currentClassDoc == null || currentClassDoc.isScript()) { if (t.getLine() > lastLineCol.getLine() || (t.getLine() == lastLineCol.getLine() && t.getColumn() > lastLineCol.getColumn())) { getJavaDocCommentsBeforeNode(t); // not normally set for non-major types but appropriate for a script lastLineCol = new LineColumn(t.getLine(), t.getColumn()); } } } }
private String getTypeOrDefault(GroovySourceAST t) { GroovySourceAST typeNode = t.childOfType(TYPE); return getTypeNodeAsText(typeNode, "def"); }
private boolean isNested() { GroovySourceAST gpn = getGrandParentNode(); return getParentNode() != null && gpn != null && (gpn.getType() == CLASS_DEF || gpn.getType() == INTERFACE_DEF); }
public Map<String, GroovyClassDoc> getGroovyClassDocs() { postProcessClassDocs(); return classDocs; }