Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBogdan Gheorghe2013-10-17 10:28:47 -0400
committerBogdan Gheorghe2013-10-17 10:28:47 -0400
commit8a0708eda3701bca07ed8d9c6daba144b1d911f2 (patch)
treecb6f93e0dde969b06358c352b3653de68aa1a410
parentd9659416ed840653e00ccf49fe47cfd2b3c387c8 (diff)
downloadeclipse.platform.swt-8a0708eda3701bca07ed8d9c6daba144b1d911f2.tar.gz
eclipse.platform.swt-8a0708eda3701bca07ed8d9c6daba144b1d911f2.tar.xz
eclipse.platform.swt-8a0708eda3701bca07ed8d9c6daba144b1d911f2.zip
Bug 409353 - JavadocBasher should only change comments
-rw-r--r--bundles/org.eclipse.swt.tools/.classpath1
-rw-r--r--bundles/org.eclipse.swt.tools/JavadocBasher/org/eclipse/swt/tools/internal/JavadocBasher.java455
-rw-r--r--bundles/org.eclipse.swt.tools/META-INF/MANIFEST.MF4
3 files changed, 459 insertions, 1 deletions
diff --git a/bundles/org.eclipse.swt.tools/.classpath b/bundles/org.eclipse.swt.tools/.classpath
index 22ab26bdb9..9c2b44de92 100644
--- a/bundles/org.eclipse.swt.tools/.classpath
+++ b/bundles/org.eclipse.swt.tools/.classpath
@@ -8,6 +8,7 @@
<classpathentry kind="src" path="Mozilla Generation"/>
<classpathentry kind="src" path="NativeStats"/>
<classpathentry kind="src" path="Icon Exe"/>
+ <classpathentry kind="src" path="JavadocBasher"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/bundles/org.eclipse.swt.tools/JavadocBasher/org/eclipse/swt/tools/internal/JavadocBasher.java b/bundles/org.eclipse.swt.tools/JavadocBasher/org/eclipse/swt/tools/internal/JavadocBasher.java
new file mode 100644
index 0000000000..e564ee1ff2
--- /dev/null
+++ b/bundles/org.eclipse.swt.tools/JavadocBasher/org/eclipse/swt/tools/internal/JavadocBasher.java
@@ -0,0 +1,455 @@
+package org.eclipse.swt.tools.internal;
+
+import java.io.*;
+import java.util.*;
+
+import org.eclipse.jdt.core.dom.*;
+import org.eclipse.jdt.core.dom.rewrite.*;
+import org.eclipse.jface.text.*;
+
+/**
+ * Bashes the javadoc from one source tree into another. Only produces new
+ * source files for compilation units that have changed.
+ *
+ * How to use: 1) make sure you have the latest org.eclipse.swt (master branch)
+ * in your workspace, and that you have no outstanding org.eclipse.swt changes
+ * 2) create a Bugzilla bug called
+ * "Do the annual javadoc/copyright bash for x.x" 3) make a version (tag) of the
+ * org.eclipse.swt project before you bash here is a sample tag name:
+ * BEFORE_JAVADOC_BASH_FOR_43RC3 use the Bugzilla bug for the tag comment 4)
+ * modify the code in main, below, so that 'workspaceDir' and 'outputDir' point
+ * to the (git) directory that contains org.eclipse.swt in your workspace,
+ * typically C:/git/eclipse.platform.swt/bundles (prior to 3.8/4.2, these
+ * pointed to the workspace directory) 5) make sure 'sourceSubdir' (usually
+ * win32), 'targetSubdirs' (all others), and 'folders' are correct (note: there
+ * are typically a few new targetSubdirs and folders every year... although
+ * nothing new for 4.3) 6) run JavadocBasher (for a more verbose output, set
+ * fVerbose to true) 7) refresh (F5) the org.eclipse.swt project inside eclipse
+ * 8) search for *** in console output to see results of API consistency
+ * checking 9) synchronize, carefully reviewing every change. Watch out for: -
+ * duplicated comments - // comments that have been removed (if they appear
+ * before a javadoc comment) 10) use the Bugzilla bug as the commit comment for
+ * javadoc and copyright bash commits 11) make a version of the org.eclipse.swt
+ * project after bashing (use tag name AFTER_...)
+ *
+ * 12) Copyright bash (tag before and after): NOTE: JavadocBasher does not fix
+ * copyrights. Use the "Fix Copyrights" tool in org.eclipse.releng.tools for
+ * that (always fix copyrights after bash). Use Help->Install New Software... to
+ * install "Releng Tools" from the "Eclipse Project Updates" site (for release -
+ * 1). Select org.eclipse.swt project and choose "Fix Copyrights" from the
+ * context menu. See http://wiki.eclipse.org/Development_Resources/
+ * How_to_Use_Eclipse_Copyright_Tool for more info. NOTE: The copyright tool
+ * takes about 45 minutes to run (for SWT). NOTE 2: Check console for possible
+ * errors/warnings, refresh (F5), synchronize, and browse all changes. Use
+ * keyboard (Ctrl+.) for next diff instead of mouse (keyboard is faster because
+ * there are fewer focus changes). Only use git History view as needed - if it
+ * is open and linked with editor, it gets bogged down and lags behind. NOTE 3:
+ * SWT anomalies that confuse the tool: - Some ns*.h files in
+ * Mozilla/common/library do not contain the word "copyright" so the tool tries
+ * to add one - don't keep it (the text is fine as-is). - Other ns*.h files in
+ * Mozilla/common/library have a copyright line that should not be updated
+ * (Initial Developer) - don't keep the change suggested by the tool (the text
+ * is fine as-is). - The ns*.java and some other *.java files in
+ * internal/mozilla have 2 copyright lines and the tool tries to change the 1st
+ * - don't keep the 1st change (Netscape 1998-1999), but update the 2nd (IBM)
+ * manually.
+ *
+ * NOTE: JavadocBasher now does a fairly good job of checking API consistency.
+ * We used to use org.eclipse.swt.diff for API consistency checking, but it was
+ * difficult to maintain.
+ */
+public class JavadocBasher {
+ static final boolean fVerbose = false; // set to true for verbose output
+ List fBashed;
+ List fUnchanged;
+ List fSkipped;
+ private ASTRewrite rewriter;
+
+ public JavadocBasher() {
+ fBashed = new ArrayList();
+ fUnchanged = new ArrayList();
+ fSkipped = new ArrayList();
+ }
+
+ public static class Edit {
+ int start, length;
+ String text;
+
+ public Edit(int start, int length, String text) {
+ this.start = start;
+ this.length = length;
+ this.text = text;
+ }
+ }
+
+ public static void main(String[] args) {
+ String workspaceDir = ".."; // use forward slashes, no final slash
+ String outputDir = ".."; // can point to another directory for debugging
+ String[] folders = new String[] { // commented folders do not need to be
+ // bashed
+ "Eclipse SWT", "Eclipse SWT Accessibility",
+ "Eclipse SWT AWT",
+ "Eclipse SWT Browser",
+ // "Eclipse SWT Custom Widgets",
+ "Eclipse SWT Drag and Drop", "Eclipse SWT Effects",
+ "Eclipse SWT Mozilla",
+ // "Eclipse SWT OLE Win32",
+ "Eclipse SWT OpenGL",
+ // "Eclipse SWT PI",
+ "Eclipse SWT Printing", "Eclipse SWT Program",
+ "Eclipse SWT Theme", "Eclipse SWT WebKit", };
+ String sourceSubdir = "win32";
+ String[] targetSubdirs = new String[] { "cairo", // used by gtk, motif
+ // "carbon", // we are no longer maintaining carbon
+ "cde", // used by gtk, motif
+ "cocoa",
+ // "common",
+ // "common_j2me",
+ // "common_j2se",
+ "emulated", "emulated/bidi", // used by carbon, cocoa, dojo,
+ // flex, gtk, motif, photon, wpf
+ "emulated/coolbar", // used by carbon, cocoa, flex, gtk, motif,
+ // photon
+ // "emulated/datetime", // only used by motif, photon, wpf
+ "emulated/expand", // used by carbon, cocoa, flex, motif, photon
+ // "emulated/graphics", // only used by photon
+ "emulated/ime", // used by dojo, flex, motif, photon, wpf
+ // "emulated/tabfolder", // only used by motif
+ "emulated/taskbar", // used by carbon, gtk, motif, photon, wpf
+ // "emulated/textlayout", // only used by photon
+ "emulated/tooltip", // used by cocoa (?!), motif, photon, wpf
+ // "emulated/tray", // only used by carbon_j2me, motif, photon
+ // "emulated/treetable", // only used by motif, photon
+ // "forms", // only used by wpf
+ "gnome", // used by gtk, motif
+ "glx", // used by gtk, motif
+ "gtk",
+ // "motif", // we are no longer maintaining motif
+ // "motif_gtk", // only used by motif
+ "mozilla", // used by carbon, cocoa, gtk, motif, win32
+ // "photon", // we are no longer maintaining photon
+ // "qt", // folder should be deleted
+ // "wpf", // we are no longer maintaining wpf
+ // "wpf_win32", // only used by wpf
+ };
+
+ System.out.println("==== Start Bashing ====");
+ int totalBashed = 0;
+ for (int t = 0; t < targetSubdirs.length; t++) {
+ for (int f = 0; f < folders.length; f++) {
+ String targetSubdir = folders[f] + "/" + targetSubdirs[t];
+ File source = new File(workspaceDir + "/org.eclipse.swt/"
+ + folders[f] + "/" + sourceSubdir);
+ File target = new File(workspaceDir + "/org.eclipse.swt/"
+ + targetSubdir);
+ File out = new File(outputDir + "/org.eclipse.swt/"
+ + targetSubdir);
+ JavadocBasher basher = new JavadocBasher();
+ System.out.println("\n==== Start Bashing " + targetSubdir);
+ basher.bashJavaSourceTree(source, target, out);
+ List bashedList = basher.getBashed();
+ basher.status("Bashed", bashedList, targetSubdir);
+ if (bashedList.size() > 0) {
+ totalBashed += bashedList.size();
+ if (fVerbose)
+ basher.status("Didn't change", basher.getUnchanged(),
+ targetSubdir);
+ basher.status("Skipped", basher.getSkipped(), targetSubdir);
+ }
+ System.out.println("==== Done Bashing " + targetSubdir);
+ }
+ }
+ System.out.println("\n==== Done Bashing (Bashed " + totalBashed
+ + " files in total) - Be sure to Refresh (F5) project(s) ====");
+ }
+
+ void status(String label, List list, String targetSubdir) {
+ int count = list.size();
+ System.out.println(label + " " + count
+ + ((count == 1) ? " file" : " files") + " in " + targetSubdir
+ + ((count > 0) ? ":" : "."));
+ if (count > 0) {
+ Iterator i = list.iterator();
+ while (i.hasNext())
+ System.out.println(label + ": " + i.next());
+ System.out.println();
+ }
+ }
+
+ char[] readFile(File file) {
+ try {
+ Reader in = new FileReader(file);
+ CharArrayWriter storage = new CharArrayWriter();
+ char[] chars = new char[8192];
+ int read = in.read(chars);
+ while (read > 0) {
+ storage.write(chars, 0, read);
+ storage.flush();
+ read = in.read(chars);
+ }
+ in.close();
+ return storage.toCharArray();
+ } catch (IOException ioe) {
+ System.out.println("*** Could not read " + file);
+ }
+ return null;
+ }
+
+ void writeFile(char[] contents, File file) {
+ try {
+ Writer out = new FileWriter(file);
+ out.write(contents);
+ out.flush();
+ out.close();
+ } catch (IOException ioe) {
+ System.out.println("*** Could not write to " + file);
+ if (fVerbose) {
+ System.out.println("<dump filename=\"" + file + "\">");
+ System.out.println(contents);
+ System.out.println("</dump>");
+ }
+ }
+ }
+
+ void bashJavaSourceTree(File sourceDir, File targetDir, File outDir) {
+ if (fVerbose)
+ System.out.println("Reading source javadoc from " + sourceDir);
+ if (!sourceDir.exists()) {
+ System.out.println("Source: " + sourceDir + " was missing");
+ return;
+ }
+ if (!targetDir.exists()) {
+ System.out.println("Target: " + targetDir + " was missing");
+ return;
+ }
+
+ String[] list = sourceDir.list();
+ if (list != null) {
+ int count = list.length;
+ for (int i = 0; i < count; i++) {
+ String filename = list[i];
+ if (filename.equals("CVS") || filename.equals("internal")
+ || filename.equals("library"))
+ continue;
+ File source = new File(sourceDir, filename);
+ File target = new File(targetDir, filename);
+ File out = new File(outDir, filename);
+ if (source.exists() && target.exists()) {
+ if (source.isDirectory()) {
+ if (target.isDirectory()) {
+ bashJavaSourceTree(source, target, out);
+ } else {
+ System.out.println("*** " + target
+ + " should have been a directory.");
+ }
+ } else {
+ if (filename.toLowerCase().endsWith(".java")) {
+ bashFile(source, target, out);
+ } else {
+ fSkipped.add(source + " (not a java file)");
+ }
+ }
+ } else {
+ if (source.exists()) {
+ fSkipped.add(target + " (does not exist)");
+ } else {
+ fSkipped.add(source + " (does not exist)");
+ }
+ }
+ }
+ }
+ }
+
+
+ void bashFile(final File source, final File target, File out) {
+ char[] contents = readFile(source);
+ if (contents == null) return;
+ ASTParser parser = ASTParser.newParser(AST.JLS4);
+ final Document sourceDocument = new Document(new String(contents));
+ parser.setSource(contents);
+ CompilationUnit sourceUnit = (CompilationUnit)parser.createAST(null);
+
+ contents = readFile(target);
+ if (contents == null) return;
+ String targetContents = new String(contents);
+ final Document targetDocument = new Document(targetContents);
+ parser.setSource(contents);
+ CompilationUnit targetUnit = (CompilationUnit)parser.createAST(null);
+
+ final HashMap comments = new HashMap();
+ sourceUnit.accept(new ASTVisitor() {
+ String prefix = "";
+ public boolean visit(Block node) {
+ return false;
+ }
+ public boolean visit(VariableDeclarationFragment node) {
+ FieldDeclaration field = (FieldDeclaration)node.getParent();
+ int mods = field.getModifiers();
+ if (Modifier.isPublic(mods) || Modifier.isProtected(mods)) {
+ Javadoc javadoc = field.getJavadoc();
+ if (field.fragments().size() > 1 && javadoc != null) {
+ System.err.println("Field declaration with multiple variables is not supported. -> " + source + " " + node.getName().getFullyQualifiedName());
+ }
+ try {
+ String key = prefix + "." + node.getName().getFullyQualifiedName();
+ comments.put(key, javadoc != null ? sourceDocument.get(javadoc.getStartPosition(), getJavadocLength(sourceDocument, javadoc)) : "");
+ } catch (BadLocationException e) {}
+ return true;
+ }
+ return false;
+ }
+ public boolean visit(MethodDeclaration node) {
+ int mods = node.getModifiers();
+ if (Modifier.isPublic(mods) || Modifier.isProtected(mods)) {
+ Javadoc javadoc = node.getJavadoc();
+ try {
+ String key = prefix + "." + node.getName().getFullyQualifiedName();
+ for (Iterator iterator = node.parameters().iterator(); iterator.hasNext();) {
+ SingleVariableDeclaration param = (SingleVariableDeclaration) iterator.next();
+ key += param.getType().toString();
+ }
+ comments.put(key, javadoc != null ? sourceDocument.get(javadoc.getStartPosition(), getJavadocLength(sourceDocument, javadoc)) : "");
+ } catch (BadLocationException e) {}
+ return true;
+ }
+ return false;
+ }
+ public boolean visit(TypeDeclaration node) {
+ int mods = node.getModifiers();
+ if (Modifier.isPublic(mods) || Modifier.isProtected(mods)) {
+ Javadoc javadoc = node.getJavadoc();
+ try {
+ String key = prefix + "." + node.getName().getFullyQualifiedName();
+ comments.put(key, javadoc != null ? sourceDocument.get(javadoc.getStartPosition(), getJavadocLength(sourceDocument, javadoc)) : "");
+ } catch (BadLocationException e) {}
+ prefix = node.getName().getFullyQualifiedName();
+ return true;
+ }
+ return false;
+ }
+ });
+
+
+ final List edits = new ArrayList();
+ targetUnit.accept(new ASTVisitor() {
+ String prefix = "";
+ public boolean visit(Block node) {
+ return false;
+ }
+ public boolean visit(VariableDeclarationFragment node) {
+ FieldDeclaration field = (FieldDeclaration)node.getParent();
+ int mods = field.getModifiers();
+ if (Modifier.isPublic(mods) || Modifier.isProtected(mods)) {
+ Javadoc javadoc = field.getJavadoc();
+ if (field.fragments().size() > 1 && javadoc != null) {
+ System.err.println("Field declaration with multiple variables is not supported. -> " + target + " " + node.getName().getFullyQualifiedName());
+ }
+ String key = prefix + "." + node.getName().getFullyQualifiedName();
+ String newComment = (String)comments.get(key);
+ if (newComment != null) {
+ if (javadoc != null) {
+ edits.add(new Edit(javadoc.getStartPosition(), getJavadocLength(targetDocument, javadoc), newComment));
+ } else {
+ edits.add(new Edit(field.getStartPosition(), 0, newComment));
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+ public boolean visit(MethodDeclaration node) {
+ int mods = node.getModifiers();
+ if (Modifier.isPublic(mods) || Modifier.isProtected(mods)) {
+ Javadoc javadoc = node.getJavadoc();
+ String key = prefix + "." + node.getName().getFullyQualifiedName();
+ for (Iterator iterator = node.parameters().iterator(); iterator.hasNext();) {
+ SingleVariableDeclaration param = (SingleVariableDeclaration) iterator.next();
+ key += param.getType().toString();
+ }
+ String newComment = (String)comments.get(key);
+ if (newComment != null) {
+ if (javadoc != null) {
+ edits.add(new Edit(javadoc.getStartPosition(), getJavadocLength(targetDocument, javadoc), newComment));
+ } else {
+ edits.add(new Edit(node.getStartPosition(), 0, newComment));
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+ public boolean visit(TypeDeclaration node) {
+ int mods = node.getModifiers();
+ if (Modifier.isPublic(mods) || Modifier.isProtected(mods)) {
+ Javadoc javadoc = node.getJavadoc();
+ String key = prefix + "." + node.getName().getFullyQualifiedName();
+ String newComment = (String)comments.get(key);
+ if (newComment != null) {
+ if (javadoc != null) {
+ edits.add(new Edit(javadoc.getStartPosition(), getJavadocLength(targetDocument, javadoc), newComment));
+ } else {
+ edits.add(new Edit(node.getStartPosition(), 0, newComment));
+ }
+ }
+ prefix = node.getName().getFullyQualifiedName();
+ return true;
+ }
+ return false;
+ }
+ });
+
+ for (int i = edits.size() - 1; i >=0 ; i--) {
+ Edit edit = (Edit)edits.get(i);
+ try {
+ targetDocument.replace(edit.start, edit.length, edit.text);
+ } catch (BadLocationException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ String newContents = targetDocument.get();
+ if (!targetContents.equals(newContents)) {
+ if (makeDirectory(out.getParentFile())) {
+ writeFile(newContents.toCharArray(), out);
+ fBashed.add(target);
+ } else {
+ System.out.println("*** Could not create " + out.getParent());
+ }
+ } else {
+ fUnchanged.add(target);
+ }
+ }
+
+ int getJavadocLength(Document sourceDocument, Javadoc javadoc) {
+ return skipWhitespace(sourceDocument, javadoc.getStartPosition() + javadoc.getLength()) - javadoc.getStartPosition();
+ }
+
+ int skipWhitespace(Document doc, int offset) {
+ try {
+ while (Character.isWhitespace(doc.getChar(offset))){
+ offset++;
+ }
+ } catch (BadLocationException e) {
+ }
+ return offset;
+ }
+
+ boolean makeDirectory(File directory) {
+ if (directory.exists())
+ return true;
+ return directory.mkdirs();
+ }
+
+ List getBashed() {
+ return fBashed;
+ }
+
+ List getUnchanged() {
+ return fUnchanged;
+ }
+
+ List getSkipped() {
+ return fSkipped;
+ }
+}
diff --git a/bundles/org.eclipse.swt.tools/META-INF/MANIFEST.MF b/bundles/org.eclipse.swt.tools/META-INF/MANIFEST.MF
index b93cca3955..9f5d72190b 100644
--- a/bundles/org.eclipse.swt.tools/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.swt.tools/META-INF/MANIFEST.MF
@@ -15,4 +15,6 @@ Require-Bundle: org.eclipse.swt;bundle-version="3.4.0",
org.eclipse.core.resources;bundle-version="3.4.0",
org.eclipse.jdt.core;bundle-version="3.4.0",
org.eclipse.ui;bundle-version="3.4.0",
- org.eclipse.ui.editors;bundle-version="3.4.0"
+ org.eclipse.ui.editors;bundle-version="3.4.0",
+ org.eclipse.jface.text;bundle-version="3.8.200"
+Import-Package: org.eclipse.text.edits

Back to the top