[subversion:26] Fix for issue #99 - Automatic import statements

  • From: sinnema313@kenai.com
  • To: commits@eplugin.kenai.com
  • Subject: [subversion:26] Fix for issue #99 - Automatic import statements
  • Date: Sat, 10 Jan 2009 14:31:55 +0000 (GMT)

Repository: subversion
Revision:   26
Author:     sinnema313
Date:       2009-01-10 14:31:51 UTC

Log Message:
-----------
Fix for issue #99 - Automatic import statements

Modified Paths:
--------------
    trunk/com.sun.javafx.eclipse.core/.classpath
    trunk/com.sun.javafx.eclipse.core/META-INF/MANIFEST.MF
    trunk/com.sun.javafx.eclipse.core/build.properties
    trunk/com.sun.javafx.eclipse.core/plugin.xml
   
trunk/com.sun.javafx.eclipse.core/src/com/sun/javafx/eclipse/core/build
er/JavaFXBuilder.java
   
trunk/com.sun.javafx.eclipse.core/src/com/sun/javafx/eclipse/core/build
er/JavaFXCompilerMessage.java

Added Paths:
-----------
   
trunk/com.sun.javafx.eclipse.core/src/com/sun/javafx/eclipse/core/build
er/AddImportStatementResolution.java
   
trunk/com.sun.javafx.eclipse.core/src/com/sun/javafx/eclipse/core/build
er/JavaFXMarkerResolutionGenerator.java
    trunk/com.sun.javafx.eclipse.core/test
    trunk/com.sun.javafx.eclipse.core/test/com
    trunk/com.sun.javafx.eclipse.core/test/com/sun
    trunk/com.sun.javafx.eclipse.core/test/com/sun/javafx
    trunk/com.sun.javafx.eclipse.core/test/com/sun/javafx/eclipse
    trunk/com.sun.javafx.eclipse.core/test/com/sun/javafx/eclipse/core
   
trunk/com.sun.javafx.eclipse.core/test/com/sun/javafx/eclipse/core/buil
der
   
trunk/com.sun.javafx.eclipse.core/test/com/sun/javafx/eclipse/core/buil
der/JavaFXCompilerMessageTest.java
   
trunk/com.sun.javafx.eclipse.core/test/com/sun/javafx/eclipse/core/buil
der/UnknownSymbolResolutionTest.java

Diffs:
-----
Index:
trunk/com.sun.javafx.eclipse.core/test/com/sun/javafx/eclipse/core/buil
der/JavaFXCompilerMessageTest.java
===================================================================
---
trunk/com.sun.javafx.eclipse.core/test/com/sun/javafx/eclipse/core/buil
der/JavaFXCompilerMessageTest.java   (revision 0)
+++
trunk/com.sun.javafx.eclipse.core/test/com/sun/javafx/eclipse/core/buil
der/JavaFXCompilerMessageTest.java   (revision 26)
@@ -0,0 +1,21 @@
+package com.sun.javafx.eclipse.core.builder;
+
+import junit.framework.TestCase;
+
+
+public class JavaFXCompilerMessageTest extends TestCase {
+
+    /**
+     * <code>javafxc</code> outputs errors on three lines; format this
in
+     * a way that is useful in Eclipse's Problems view.
+     */
+    public void testFormat() {
+        assertEquals("Default", "ape",
JavaFXCompilerMessage.format("ape"));
+        assertEquals("Remove new lines", "bear cheetah", 
+                JavaFXCompilerMessage.format("bear\ncheetah"));
+        assertEquals("'Cannot find symbol'", "cannot find symbol:
class dingo",
+                JavaFXCompilerMessage.format(
+                        "cannot find symbol\nsymbol  : class
dingo\nlocation: class Elephant"));
+    }
+    
+}
Index:
trunk/com.sun.javafx.eclipse.core/test/com/sun/javafx/eclipse/core/buil
der/UnknownSymbolResolutionTest.java
===================================================================
---
trunk/com.sun.javafx.eclipse.core/test/com/sun/javafx/eclipse/core/buil
der/UnknownSymbolResolutionTest.java (revision 0)
+++
trunk/com.sun.javafx.eclipse.core/test/com/sun/javafx/eclipse/core/buil
der/UnknownSymbolResolutionTest.java (revision 26)
@@ -0,0 +1,74 @@
+package com.sun.javafx.eclipse.core.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+
+public class UnknownSymbolResolutionTest extends TestCase {
+
+    private static final String CLASS_TO_IMPORT = "ape.bear.Cheetah";
+    private static final String PACKAGE_STATEMENT = "package
dingo.elephant;";
+
+    private AddImportStatementResolution resolution;
+    private List<String> lines;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        resolution = new
AddImportStatementResolution(CLASS_TO_IMPORT);
+        lines = new ArrayList<String>();
+    }
+
+    public void testAddImportWhenEmpty() {
+        assertImportStatement(0);
+    }
+
+    public void testAddImportWithPackage() {
+        lines.add(PACKAGE_STATEMENT);
+        assertImportStatement(1);
+    }
+    
+    public void testAddImportWithClassComment() {
+        lines.add(PACKAGE_STATEMENT);
+        lines.add("/**");
+        lines.add(" * @author flamingo");
+        lines.add(" */");
+        lines.add("Giraffe {");
+        lines.add("}");
+        assertImportStatement(1);
+    }
+    
+    public void testAddImportWithOtherImport() {
+        lines.add("/**");
+        lines.add(" * @author hyena");
+        lines.add(" */");
+        lines.add("import iguaga.jaguar.Koala;");
+        lines.add("Leopard {");
+        lines.add("}");
+        assertImportStatement(4);
+    }
+    
+    private void assertImportStatement(int expectedLine) {
+        int index = resolution.getImportStatementIndex(getText());
+        if (lines.size() > 0) {
+            int actualLine = 0;
+            while (index >= 0) {
+                index -= lines.get(actualLine++).length() + 1;
+            }
+            assertEquals("Import statement index", expectedLine,
actualLine);
+        } else {
+            assertEquals("Import statement index", 0, index);
+        }
+    }
+
+    private String getText() {
+        final StringBuffer result = new StringBuffer();
+        for (String line : lines) {
+            result.append(line).append('\n');
+        }
+        return result.toString();
+    }
+    
+}
Index: trunk/com.sun.javafx.eclipse.core/.classpath
===================================================================
--- trunk/com.sun.javafx.eclipse.core/.classpath        (revision 25)
+++ trunk/com.sun.javafx.eclipse.core/.classpath        (revision 26)
@@ -3,5 +3,6 @@
        <classpathentry kind="con"
path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
        <classpathentry kind="con"
path="org.eclipse.pde.core.requiredPlugins"/>
        <classpathentry kind="src" path="src"/>
+       <classpathentry kind="src" path="test"/>
        <classpathentry kind="output" path="bin"/>
 </classpath>
Index: trunk/com.sun.javafx.eclipse.core/META-INF/MANIFEST.MF
===================================================================
--- trunk/com.sun.javafx.eclipse.core/META-INF/MANIFEST.MF     
(revision 25)
+++ trunk/com.sun.javafx.eclipse.core/META-INF/MANIFEST.MF     
(revision 26)
@@ -26,8 +26,11 @@
  org.eclipse.equinox.http.jetty,
  org.eclipse.equinox.http.registry,
  org.eclipse.equinox.http.servlet,
- javax.servlet
+ javax.servlet,
+ org.junit
 Bundle-ActivationPolicy: lazy
-Import-Package: javax.tools;version="2.0.0"
+Import-Package: javax.tools;version="2.0.0",
+ org.eclipse.jface.text,
+ org.eclipse.ui.ide
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Export-Package: com.sun.javafx.eclipse.core
Index:
trunk/com.sun.javafx.eclipse.core/src/com/sun/javafx/eclipse/core/build
er/JavaFXCompilerMessage.java
===================================================================
---
trunk/com.sun.javafx.eclipse.core/src/com/sun/javafx/eclipse/core/build
er/JavaFXCompilerMessage.java        (revision 25)
+++
trunk/com.sun.javafx.eclipse.core/src/com/sun/javafx/eclipse/core/build
er/JavaFXCompilerMessage.java        (revision 26)
@@ -6,7 +6,7 @@
  */
 public class JavaFXCompilerMessage {
 
-    private static final String UNKNOWN_SYMBOL_BEGIN = "cannot find
symbol";
+    public static final String UNKNOWN_SYMBOL_BEGIN = "cannot find
symbol";
     private static final int UNKNOWN_SYMBOL_REMOVE = " symbol 
".length();
     private static final String UNKNOWN_SYMBOL_END = " location:";
 
Index:
trunk/com.sun.javafx.eclipse.core/src/com/sun/javafx/eclipse/core/build
er/JavaFXBuilder.java
===================================================================
---
trunk/com.sun.javafx.eclipse.core/src/com/sun/javafx/eclipse/core/build
er/JavaFXBuilder.java        (revision 25)
+++
trunk/com.sun.javafx.eclipse.core/src/com/sun/javafx/eclipse/core/build
er/JavaFXBuilder.java        (revision 26)
@@ -27,7 +27,6 @@
 
 package com.sun.javafx.eclipse.core.builder;
 
-import java.io.File;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -40,7 +39,6 @@
 import javax.tools.FileObject;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
-import javax.tools.Diagnostic.Kind;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
@@ -58,13 +56,13 @@
 import com.sun.javafx.eclipse.core.Activator;
 import com.sun.javafx.eclipse.core.builder.classpath.ClasspathInfo;
 import com.sun.javafx.eclipse.core.builder.classpath.SourceFileObject;
-import com.sun.tools.javac.code.Kinds;
 import com.sun.tools.javafx.api.JavafxcTool;
 
+
 public class JavaFXBuilder extends IncrementalProjectBuilder {
        public static final String BUILDER_ID =
"com.sun.javafx.eclipse.core.builder.JavaFXBuilder";
 
-       private static final String MARKER_TYPE =
"com.sun.javafx.eclipse.core.builder.fxproblem";
+       public static final String MARKER_TYPE =
"com.sun.javafx.eclipse.core.builder.fxproblem";
        
        private Map<IResource,Long> lastCheck = new
WeakHashMap<IResource,Long>();
        
@@ -212,7 +210,6 @@
                        return;
                }
                if (resource instanceof IFile &&
resource.getName().endsWith(".fx")) {
-                   String srcDir =
resource.getParent().getLocation().toOSString();
                        IFile file = (IFile) resource;
                        Long last = lastCheck.get(file);
                        long now = System.currentTimeMillis();
@@ -232,7 +229,6 @@
                        List<String> options = new ArrayList<String>();
                        //options.add("-Xjcov"); //NOI18N, Make the
compiler store end positions
                        options.add("-XDdisableStringFolding");
//NOI18N
-                       File f = new File(srcDir, file.getName());
                            JavafxcTask task = tool.getTask(null, fm,
dl, options, Collections.singleton(jfo));
                        task.parse();
                        task.analyze();
Index:
trunk/com.sun.javafx.eclipse.core/src/com/sun/javafx/eclipse/core/build
er/AddImportStatementResolution.java
===================================================================
---
trunk/com.sun.javafx.eclipse.core/src/com/sun/javafx/eclipse/core/build
er/AddImportStatementResolution.java (revision 0)
+++
trunk/com.sun.javafx.eclipse.core/src/com/sun/javafx/eclipse/core/build
er/AddImportStatementResolution.java (revision 26)
@@ -0,0 +1,93 @@
+package com.sun.javafx.eclipse.core.builder;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.IMarkerResolution;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+
+
+/**
+ * Resolve 'Unknown Symbol' errors by adding an import statement.
+ */
+public class AddImportStatementResolution implements IMarkerResolution
{
+
+    private String className;
+
+    public AddImportStatementResolution(String className) {
+        this.className = className;
+    }
+
+    public String getLabel() {
+        return "Import '" + className + "'";
+    }
+    
+    public String getDescription() {
+        return "Add '" + className + "' to the imports";
+    }
+
+    public Image getImage() {
+        return null;
+    }
+
+    public void run(IMarker marker) {
+        final IFile file = (IFile) marker.getResource();
+        try {
+            if (!file.isSynchronized(IResource.DEPTH_ZERO)) {
+              file.refreshLocal(IResource.DEPTH_ZERO, null);
+            }
+
+            addImportStatement(file, "import " + className + ";");
+        } catch (Exception e) {
+            e.printStackTrace();   
+        }
+    }
+
+    private void addImportStatement(IFile file, String
importStatement)
+            throws PartInitException, BadLocationException {        
+        ITextEditor editor = (ITextEditor) IDE.openEditor(PlatformUI
+               
.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file,
true);
+        IDocument doc = editor.getDocumentProvider().getDocument(
+                new FileEditorInput(file));
+        doc.replace(getImportStatementIndex(doc.get()), 0, "import " +
className + ";\n");
+        editor.doSave(null);
+    }
+
+    protected int getImportStatementIndex(final String text) {
+        int result = text.indexOf("import ");
+        if (result < 0) {
+            result = text.indexOf("package ");
+            if (result >= 0) {
+                result = text.indexOf(';', result) + 1;
+            } else {
+                result = 0;
+            }
+            int classStart = text.indexOf('{', result);
+            int commentStart = text.indexOf("/*", result);
+            if (0 <= commentStart && commentStart < classStart) {
+                result = commentStart - 1;
+            } else if (classStart >= 0) {
+                classStart--;
+                while
(Character.isWhitespace(text.charAt(classStart))) {
+                    classStart--;
+                }
+                while (classStart > 0 &&
!Character.isWhitespace(text.charAt(classStart))) {
+                    classStart--;
+                }
+                while (classStart > 0 &&
Character.isWhitespace(text.charAt(classStart))) {
+                    classStart--;
+                }
+                result = classStart;
+            }
+        }
+        return result;
+    }
+
+}
Index:
trunk/com.sun.javafx.eclipse.core/src/com/sun/javafx/eclipse/core/build
er/JavaFXMarkerResolutionGenerator.java
===================================================================
---
trunk/com.sun.javafx.eclipse.core/src/com/sun/javafx/eclipse/core/build
er/JavaFXMarkerResolutionGenerator.java      (revision 0)
+++
trunk/com.sun.javafx.eclipse.core/src/com/sun/javafx/eclipse/core/build
er/JavaFXMarkerResolutionGenerator.java      (revision 26)
@@ -0,0 +1,117 @@
+package com.sun.javafx.eclipse.core.builder;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.ui.IMarkerResolution;
+import org.eclipse.ui.IMarkerResolutionGenerator2;
+
+
+public class JavaFXMarkerResolutionGenerator implements
+        IMarkerResolutionGenerator2 {
+
+    private static final String JAVA_CLASS_EXTENSION = "class";
+    private static final Object JAVA_LIBARY_EXTENSION = "jar";
+    private static final String CLASS = "class ";
+    private static final char INTERNAL_CLASS_SEPARATOR = '$';
+
+    public boolean hasResolutions(final IMarker marker) {
+        return isUnknownSymbolError(marker) &&
!getFullyQualifiedNames(marker).isEmpty();
+    }
+
+    public IMarkerResolution[] getResolutions(final IMarker marker) {
+        final List<IMarkerResolution> result = new
ArrayList<IMarkerResolution>();
+        if (isUnknownSymbolError(marker)) {
+            for (String className : getFullyQualifiedNames(marker)) {
+                result.add(new
AddImportStatementResolution(className));
+            }
+        }
+        return (IMarkerResolution[]) result.toArray(new
IMarkerResolution[result.size()]);
+    }
+
+    private boolean isUnknownSymbolError(final IMarker marker) {
+        return isError(marker) &&
getMessage(marker).startsWith(JavaFXCompilerMessage.UNKNOWN_SYMBOL_BEGI
N);
+    }
+
+    private String getMessage(final IMarker marker) {
+        return marker.getAttribute(IMarker.MESSAGE, "");
+    }
+
+    private boolean isError(final IMarker marker) {
+        return marker.getAttribute(IMarker.SEVERITY,
IMarker.SEVERITY_INFO) == IMarker.SEVERITY_ERROR;
+    }
+    
+    private Set<String> getFullyQualifiedNames(final IMarker marker) {
+        final Set<String> result = new TreeSet<String>();
+        final String toMatch =
getMessage(marker).substring(JavaFXCompilerMessage.UNKNOWN_SYMBOL_BEGIN
.length() + 2);
+        if (toMatch.startsWith(CLASS)) {
+            addFullyQualifiedNames(marker.getResource().getProject(),
toMatch.substring(CLASS.length()), result);        
+        }
+        return result;
+    }
+
+    private void addFullyQualifiedNames(final IProject project, final
String className, final Set<String> result) {
+        final String classFileName = className + "." +
JAVA_CLASS_EXTENSION;
+        try {
+            IJavaProject javaProject = JavaCore.create(project);
+            for (IClasspathEntry classPathEntry :
javaProject.getResolvedClasspath(true)) {
+                if (classPathEntry.getEntryKind() ==
IClasspathEntry.CPE_LIBRARY) {
+                    if
(JAVA_LIBARY_EXTENSION.equals(classPathEntry.getPath().getFileExtension
())) {
+                        try {
+                            final JarFile jar = new
JarFile(classPathEntry.getPath().toFile());
+                            try {
+                              final Enumeration<JarEntry> entries =
jar.entries();
+                              while (entries.hasMoreElements()) {
+                                  JarEntry entry =
entries.nextElement();
+                                  if (!entry.isDirectory() &&
isClass(entry.getName(), classFileName)) {
+                                     
result.add(getFullyQualifiedName(entry.getName()));
+                                  }
+                              }
+                            } finally {
+                             jar.close();   
+                            }                        
+                        } catch (IOException ioe) {
+                            ioe.printStackTrace();
+                        }
+                    }
+                }
+            }
+        } catch (CoreException ce) {
+            ce.printStackTrace();
+        }        
+    }
+
+    private String getFullyQualifiedName(final String path) {
+        return path.substring(0, path.lastIndexOf('.')).replaceAll(
+                "\\" + File.separator, ".").replaceAll(
+                "\\" + INTERNAL_CLASS_SEPARATOR, ".");
+    }
+
+    private boolean isClass(final String fileName, final String
classFileName) {
+        final boolean result;
+        final int index = fileName.lastIndexOf(classFileName);
+        if (index < 0) {
+            result = false;
+        } else if (index == 0) {
+            result = true;
+        } else {
+            final char before = fileName.charAt(index - 1);
+            result = before == File.separatorChar || before ==
INTERNAL_CLASS_SEPARATOR;
+        }
+        return result;
+    }
+    
+}
Index: trunk/com.sun.javafx.eclipse.core/build.properties
===================================================================
--- trunk/com.sun.javafx.eclipse.core/build.properties  (revision 25)
+++ trunk/com.sun.javafx.eclipse.core/build.properties  (revision 26)
@@ -25,7 +25,7 @@
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #
 
-source.. = src/
+source.. = src/,test/
 output.. = bin/
 bin.includes = META-INF/,\
                .,\
Index: trunk/com.sun.javafx.eclipse.core/plugin.xml
===================================================================
--- trunk/com.sun.javafx.eclipse.core/plugin.xml        (revision 25)
+++ trunk/com.sun.javafx.eclipse.core/plugin.xml        (revision 26)
@@ -102,9 +102,8 @@
          id="com.sun.javafx.eclipse.core.builder.fxproblem"
          name="JavaFX Problem"
          point="org.eclipse.core.resources.markers">
-      <super
-            type="org.eclipse.core.resources.problemmarker">
-      </super>
+      <super type="org.eclipse.core.resources.problemmarker"/>
+      <super type="org.eclipse.core.resources.textmarker"/>
       <persistent
             value="true">
       </persistent>
@@ -303,4 +302,11 @@
       </menuContribution>
    </extension>
 
+   <extension
+         point="org.eclipse.ui.ide.markerResolution">
+       <markerResolutionGenerator
+           markerType="com.sun.javafx.eclipse.core.builder.fxproblem"
+          
class="com.sun.javafx.eclipse.core.builder.JavaFXMarkerResolutionGenera
tor"/>
+   </extension>
+   
 </plugin>


[subversion:26] Fix for issue #99 - Automatic import statements

sinnema313 01/10/2009
  • Mysql
  • Glassfish
  • Jruby
  • Rails
  • Nblogo
Terms of Use; Privacy Policy;
© 2010, Oracle Corporation and/or its affiliates
(revision 20120127.ac94057)
 
 
Close
loading
Please Confirm
Close