blob: b6cfaa48a5a12cea7be65a5d62f8a7ef20db164e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2005 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.wtp.releng.tools.component.javadoc;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.core.runtime.IPlatformRunnable;
import org.eclipse.core.runtime.Platform;
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.FieldDeclaration;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodRef;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.TagElement;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.internal.core.util.CharArrayBuffer;
import org.eclipse.wtp.releng.tools.component.IFileLocation;
import org.eclipse.wtp.releng.tools.component.ILocation;
import org.eclipse.wtp.releng.tools.component.api.ClassAPI;
import org.eclipse.wtp.releng.tools.component.api.ComponentAPI;
import org.eclipse.wtp.releng.tools.component.api.FieldAPI;
import org.eclipse.wtp.releng.tools.component.api.JavadocCoverage;
import org.eclipse.wtp.releng.tools.component.api.MethodAPI;
import org.eclipse.wtp.releng.tools.component.api.PackageAPI;
import org.eclipse.wtp.releng.tools.component.internal.AbstractEmitter;
import org.eclipse.wtp.releng.tools.component.internal.FileLocation;
import org.eclipse.wtp.releng.tools.component.internal.PluginClasspath;
import org.eclipse.wtp.releng.tools.component.model.ComponentXML;
import org.eclipse.wtp.releng.tools.component.model.Package;
import org.eclipse.wtp.releng.tools.component.model.Plugin;
import org.eclipse.wtp.releng.tools.component.model.Type;
public class JavadocCoverageEmitter extends AbstractEmitter implements IPlatformRunnable
{
private ASTParser parser = ASTParser.newParser(AST.JLS2);
public Object run(Object arguments)
{
try
{
String compXMLDir = addTrailingSeperator(System.getProperty("compXMLDir"));
String compAPIDir = addTrailingSeperator(System.getProperty("compAPIDir"));
String srcDir = addTrailingSeperator(System.getProperty("srcDir"));
String outputDir = addTrailingSeperator(System.getProperty("outputDir"));
if (compXMLDir != null && srcDir != null && outputDir != null)
{
Map compName2CompXML = new HashMap();
harvestComponents(new File(compXMLDir), compName2CompXML);
List compAPIs = new ArrayList();
harvestComponentAPIs(new File(compAPIDir), compAPIs);
Map id2Plugin = new HashMap();
Map id2Fragment = new HashMap();
harvestPlugins(new File(srcDir), id2Plugin, id2Fragment);
linkPluginsAndFragments(id2Plugin, id2Fragment);
JavadocCoverageSummary summary = new JavadocCoverageSummary();
for (Iterator it = compAPIs.iterator(); it.hasNext();)
{
ComponentAPI compAPI = (ComponentAPI)it.next();
compAPI.load();
genJavadocCoverageXML(compAPI, (ComponentXML)compName2CompXML.get(compAPI.getName()), id2Plugin, outputDir);
summary.add(compAPI);
}
summary.save(new FileLocation(new File(outputDir + "index-api-javadoc.xml")));
summary.saveAsHTML("org/eclipse/wtp/releng/tools/component/xsl/component-api-javadoc-summary.xsl", new FileLocation(new File(outputDir + "index-api-javadoc.html")));
}
}
catch (Throwable t)
{
t.printStackTrace();
}
return IPlatformRunnable.EXIT_OK;
}
protected void harvestComponents(File file, Map compName2CompXML)
{
if (file.isDirectory())
{
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++)
harvestComponents(files[i], compName2CompXML);
}
else if (ComponentXML.CONST_COMPONENT_XML.equalsIgnoreCase(file.getName()))
{
ComponentXML compXML = new ComponentXML();
ILocation location = new FileLocation(file);
compXML.setLocation(location);
try
{
compXML.load();
compName2CompXML.put(compXML.getName(), compXML);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
protected void harvestComponentAPIs(File file, List compAPIs)
{
if (file.isDirectory())
{
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++)
harvestComponentAPIs(files[i], compAPIs);
}
else if (ComponentAPI.CONST_COMPONENT_API.equalsIgnoreCase(file.getName()))
{
ComponentAPI compAPI = new ComponentAPI();
ILocation location = new FileLocation(file);
compAPI.setLocation(location);
compAPIs.add(compAPI);
}
}
public PluginClasspath getPluginClasspath(IFileLocation fileLocation, boolean validate)
{
return super.getPluginClasspath(fileLocation, false);
}
private void genJavadocCoverageXML(ComponentAPI compAPI, ComponentXML compXML, Map id2Plugin, String outputDir) throws IOException, TransformerConfigurationException, TransformerException
{
for (Iterator it = compXML.getPlugins().iterator(); it.hasNext();)
{
Plugin plugin = (Plugin)it.next();
Object object = id2Plugin.get(plugin.getId());
if (object instanceof PluginClasspath)
{
PluginClasspath pluginCp = (PluginClasspath)object;
for (Iterator pkgsIt = compXML.getPackages().iterator(); pkgsIt.hasNext();)
{
genJavadocCoverageXML(compAPI, (Package)pkgsIt.next(), addTrailingSeperator(pluginCp.getDotClasspathLocation().getFile().getParentFile().getAbsolutePath()), pluginCp.getSrcPaths());
}
}
}
compAPI.save();
StringBuffer sb = new StringBuffer(outputDir);
sb.append(compAPI.getName());
sb.append("/component-api-javadoc.html");
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(new StreamSource(Platform.getBundle("org.eclipse.wtp.releng.tools.component.core").getResource("org/eclipse/wtp/releng/tools/component/xsl/component-api-javadoc.xsl").openStream()));
transformer.transform(new StreamSource(new ByteArrayInputStream(compAPI.toString().getBytes())), new StreamResult(new FileOutputStream(new File(sb.toString()))));
}
private void genJavadocCoverageXML(ComponentAPI compAPI, Package pkg, String baseDir, List srcPaths) throws IOException
{
String pkgName = pkg.getName();
String pkgDir = pkgName.replace('.', '/');
PackageAPI pkgAPI = null;
for (Iterator pkgIt = compAPI.getPackageAPIs().iterator(); pkgIt.hasNext();)
{
PackageAPI p = (PackageAPI)pkgIt.next();
if (pkgName.equals(p.getName()))
{
pkgAPI = p;
break;
}
}
if (pkgAPI != null)
{
if (pkg.isApi())
{
List excludes = new ArrayList();
Collection types = pkg.getTypes();
for (Iterator it = types.iterator(); it.hasNext();)
{
Type type = (Type)it.next();
if (!type.isImplement() && !type.isInstantiate() && !type.isReference() && !type.isSubclass())
excludes.add(type.getName() + ".java");
}
for (Iterator it = srcPaths.iterator(); it.hasNext();)
{
StringBuffer sb = new StringBuffer(baseDir);
sb.append((String)it.next());
sb.append('/');
sb.append(pkgDir);
genJavadocCoverageXML(pkgAPI, new File(sb.toString()), excludes);
}
}
else
{
Collection types = pkg.getTypes();
for (Iterator it = types.iterator(); it.hasNext();)
{
Type type = (Type)it.next();
if (type.isImplement() || type.isInstantiate() || type.isReference() || type.isSubclass())
{
for (Iterator srcIt = srcPaths.iterator(); srcIt.hasNext();)
{
String typeName = type.getName();
StringBuffer sb = new StringBuffer(baseDir);
sb.append((String)srcIt.next());
sb.append('/');
sb.append(pkgDir);
sb.append('/');
sb.append(typeName);
sb.append(".java");
for (Iterator classIt = pkgAPI.getClassAPIs().iterator(); classIt.hasNext();)
{
ClassAPI classAPI = (ClassAPI)classIt.next();
if (typeName.equals(classAPI.getName()))
{
genJavadocCoverageXML(classAPI, new File(sb.toString()));
break;
}
}
}
}
}
}
}
}
private void genJavadocCoverageXML(PackageAPI pkgAPI, File dir, List excludes) throws IOException
{
if (dir.exists() && dir.isDirectory())
{
String pkgName = pkgAPI.getName();
File[] children = dir.listFiles();
for (int i = 0; i < children.length; i++)
{
if (children[i].isFile())
{
String fileName = children[i].getName();
if (fileName.endsWith(".java") && (excludes == null || !excludes.contains(fileName)))
{
StringBuffer qualifiedName = new StringBuffer(pkgName);
qualifiedName.append('.');
qualifiedName.append(fileName.substring(0, fileName.length() - 5));
for (Iterator it = pkgAPI.getClassAPIs().iterator(); it.hasNext();)
{
ClassAPI classAPI = (ClassAPI)it.next();
if (qualifiedName.toString().equals(classAPI.getName()))
{
genJavadocCoverageXML(classAPI, children[i]);
break;
}
}
}
}
}
}
}
private void genJavadocCoverageXML(ClassAPI classAPI, File javaFile) throws IOException
{
FileReader fr = new FileReader(javaFile);
CharArrayBuffer cab = new CharArrayBuffer();
char[] c = new char[2048];
for (int read = fr.read(c); read != -1; read = fr.read(c))
cab.append(c, 0, read);
fr.close();
parser.setSource(cab.getContents());
ASTNode node = parser.createAST(null);
JavadocVisitor visitor = new JavadocVisitor(classAPI);
node.accept(visitor);
}
private class JavadocVisitor extends ASTVisitor
{
private ClassAPI classAPI;
public JavadocVisitor(ClassAPI classAPI)
{
this.classAPI = classAPI;
}
public boolean visit(TypeDeclaration node)
{
if (!checkModifier(node.getModifiers(), Modifier.PRIVATE))
{
Javadoc javadoc = node.getJavadoc();
if (javadoc != null)
{
List tags = javadoc.tags();
for (Iterator it = tags.iterator(); it.hasNext();)
{
TagElement tag = (TagElement)it.next();
String tagName = tag.getTagName();
if (tagName != null && tagName.equals(TagElement.TAG_SINCE))
{
return true;
}
}
}
classAPI.getJavadocCoverage().setHasSince(Boolean.FALSE);
}
return true;
}
public boolean visit(MethodDeclaration node)
{
String methodName = node.getName().getFullyQualifiedName();
if (classAPI.getName().endsWith("." + methodName))
methodName = "&lt;init>";
MethodAPI methodAPI = null;
for (Iterator it = classAPI.getMethodAPIs().iterator(); it.hasNext();)
{
MethodAPI m = (MethodAPI)it.next();
if (methodName.equals(m.getName()) && !m.isSetJavadocCoverage())
{
methodAPI = m;
break;
}
}
if (methodAPI != null && !checkModifier(node.getModifiers(), Modifier.PRIVATE))
{
boolean hasReturn = false;
org.eclipse.jdt.core.dom.Type returnType = node.getReturnType();
if (returnType instanceof PrimitiveType)
if (((PrimitiveType)returnType).getPrimitiveTypeCode() == PrimitiveType.VOID)
hasReturn = true;
List paramList = new ArrayList();
List params = node.parameters();
for (Iterator it = params.iterator(); it.hasNext();)
{
SingleVariableDeclaration param = (SingleVariableDeclaration)it.next();
SimpleName simpleName = param.getName();
paramList.add(simpleName.getIdentifier());
}
List throwList = new ArrayList();
List thrownExceptions = node.thrownExceptions();
for (Iterator it = thrownExceptions.iterator(); it.hasNext();)
{
Name name = (Name)it.next();
throwList.add(name.getFullyQualifiedName());
}
boolean hasDoc = false;
Javadoc javadoc = node.getJavadoc();
if (javadoc != null)
{
hasDoc = true;
List tags = javadoc.tags();
for (Iterator it = tags.iterator(); it.hasNext();)
{
TagElement tag = (TagElement)it.next();
String tagName = tag.getTagName();
if (tagName != null)
{
if (tagName.equals(TagElement.TAG_RETURN))
hasReturn = tag.fragments().size() > 0;
else if (tagName.equals(TagElement.TAG_PARAM))
{
List fragments = tag.fragments();
if (fragments.size() > 1)
{
Object fragment = fragments.get(0);
if (fragment instanceof SimpleName)
{
paramList.remove(((SimpleName)fragment).getIdentifier());
}
}
}
else if (tagName.equals(TagElement.TAG_THROWS) || tagName.equals(TagElement.TAG_EXCEPTION))
{
List fragments = tag.fragments();
if (fragments.size() > 1)
{
Object fragment = fragments.get(0);
if (fragment instanceof Name)
{
throwList.remove(((Name)fragment).getFullyQualifiedName());
}
}
}
else if (tagName.equals(TagElement.TAG_SEE))
{
List fragments = tag.fragments();
if (fragments.size() > 0)
{
Object fragment = fragments.get(0);
if (fragment instanceof MethodRef)
{
MethodRef methodRef = (MethodRef)fragment;
if (methodName.equals(methodRef.getName().getFullyQualifiedName()))
{
return true;
}
}
}
}
}
}
}
if (!hasDoc || !hasReturn || paramList.size() > 0 || throwList.size() > 0)
{
JavadocCoverage javadocCoverage = methodAPI.getJavadocCoverage();
if (!hasDoc)
{
javadocCoverage.setHasDoc(Boolean.FALSE);
}
if (!hasReturn)
{
javadocCoverage.setHasReturn(Boolean.FALSE);
}
if (paramList.size() > 0)
{
for (Iterator it = paramList.iterator(); it.hasNext();)
{
javadocCoverage.addMissingParam((String)it.next());
}
}
if (throwList.size() > 0)
{
for (Iterator it = throwList.iterator(); it.hasNext();)
{
javadocCoverage.addMissingThrow((String)it.next());
}
}
}
}
return true;
}
public boolean visit(FieldDeclaration node)
{
String fieldName = null;
List varDeclFragments = node.fragments();
for (Iterator it = varDeclFragments.iterator(); it.hasNext();)
{
VariableDeclarationFragment varDeclFragment = (VariableDeclarationFragment)it.next();
fieldName = varDeclFragment.getName().getFullyQualifiedName();
}
if (fieldName != null)
{
FieldAPI fieldAPI = null;
for (Iterator it = classAPI.getFieldAPIs().iterator(); it.hasNext();)
{
FieldAPI f = (FieldAPI)it.next();
if (fieldName.equals(f.getName()) && !f.isSetJavadocCoverage())
{
fieldAPI = f;
break;
}
}
if (fieldAPI != null && !checkModifier(node.getModifiers(), Modifier.PRIVATE))
{
Javadoc javadoc = node.getJavadoc();
if (javadoc == null)
{
fieldAPI.setJavadocCoverage(new JavadocCoverage());
}
}
}
return true;
}
private boolean checkModifier(int modifier, int bit)
{
return ((modifier & bit) == bit);
}
}
}