Pārlūkot izejas kodu

SDK - Added code check for TempVars release

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7817 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
rem..om 14 gadi atpakaļ
vecāks
revīzija
fda07fb951

+ 197 - 0
jme3-code-check/src/com/jme3/gde/codecheck/hints/TempVarsHint.java

@@ -0,0 +1,197 @@
+package com.jme3.gde.codecheck.hints;
+
+import com.sun.source.tree.MethodTree;
+import com.sun.source.tree.StatementTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.tree.Tree.Kind;
+import com.sun.source.util.SourcePositions;
+import com.sun.source.util.TreePath;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import javax.lang.model.element.Element;
+import javax.swing.text.Document;
+import javax.swing.text.JTextComponent;
+import org.netbeans.api.editor.EditorRegistry;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.modules.java.hints.spi.AbstractHint;
+import org.netbeans.spi.editor.hints.ChangeInfo;
+import org.netbeans.spi.editor.hints.EnhancedFix;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
+import org.netbeans.spi.editor.hints.Fix;
+import org.openide.awt.StatusDisplayer;
+
+public class TempVarsHint extends AbstractHint {
+
+    //This hint does not enable the IDE to fix the problem:
+    private static final List<Fix> NO_FIXES = Collections.<Fix>emptyList();
+    //This hint applies to method invocations:
+    private static final Set<Tree.Kind> TREE_KINDS =
+            EnumSet.<Tree.Kind>of(Tree.Kind.METHOD);
+    private List<varsPosition> vars = new ArrayList<varsPosition>();
+
+    public TempVarsHint() {
+        super(true, true, AbstractHint.HintSeverity.WARNING);
+    }
+
+    //Specify the kind of code that the hint applies to, in this case,
+    //the hint applies to method invocations:
+    @Override
+    public Set<Kind> getTreeKinds() {
+        return TREE_KINDS;
+    }
+
+    @Override
+    public List<ErrorDescription> run(CompilationInfo info, TreePath treePath) {
+
+        MethodTree mt = (MethodTree) treePath.getLeaf();
+        vars.clear();
+        if (mt.getBody() != null) {
+            for (StatementTree t : mt.getBody().getStatements()) {
+
+
+                if (t.getKind().equals(Tree.Kind.VARIABLE)) {
+                    Element el = info.getTrees().getElement(info.getTrees().getPath(info.getCompilationUnit(), t));
+                    String name = t.toString();
+
+                    //This is where it all happens: if the method invocation is 'showMessageDialog',
+                    //then the hint infrastructure kicks into action:
+                    if (name.indexOf("TempVars.get()") >= 0) {
+
+                        SourcePositions sp = info.getTrees().getSourcePositions();
+                        int start = (int) sp.getStartPosition(info.getCompilationUnit(), t);
+                        int end = (int) sp.getEndPosition(info.getCompilationUnit(), t);
+                        vars.add(new varsPosition(el.getSimpleName().toString(), start, end));
+                        // System.err.println("TempVars.get() at " + start + " " + end+" for variable "+el.getSimpleName().toString());
+                    }
+
+                }
+                if (t.getKind().equals(Tree.Kind.EXPRESSION_STATEMENT) && !vars.isEmpty()) {
+                    Element el = info.getTrees().getElement(treePath);
+                    String name = t.toString();
+
+
+                    if (name.indexOf(".release()") >= 0) {
+
+                        for (Iterator<varsPosition> it = vars.iterator(); it.hasNext();) {
+                            varsPosition curVar = it.next();
+                            //This is where it all happens: if the method invocation is 'showMessageDialog',
+                            //then the hint infrastructure kicks into action:
+                            if (name.indexOf(curVar.varName + ".release()") >= 0) {
+                                //prepare selection for removing                       
+                                it.remove();
+
+//                            SourcePositions sp = info.getTrees().getSourcePositions();
+//                            int start = (int) sp.getStartPosition(info.getCompilationUnit(), t);
+//                            int end = (int) sp.getEndPosition(info.getCompilationUnit(), t);
+//                            System.err.println(curVar.varName + ".release() at " + start + " " + end);
+
+                            }
+                        }
+                    }
+
+                }
+
+
+            }
+        }
+        if (!vars.isEmpty()) {
+            List<ErrorDescription> list = new ArrayList<ErrorDescription>();
+
+            JTextComponent editor = EditorRegistry.lastFocusedComponent();
+            Document doc = editor.getDocument();
+            List<Fix> fixes = new ArrayList<Fix>();
+            SourcePositions sp = info.getTrees().getSourcePositions();
+            int methodEnd = (int) (sp.getEndPosition(info.getCompilationUnit(), mt) - 1);
+
+            for (varsPosition curVar : vars) {
+                String bodyText = "    "+curVar.varName + ".release();\n    ";
+                fixes.clear();
+                fixes.add(new MessagesFix(doc, methodEnd, bodyText));
+
+                list.add(ErrorDescriptionFactory.createErrorDescription(
+                        getSeverity().toEditorSeverity(),
+                        getDisplayName(),
+                        fixes,
+                        info.getFileObject(),
+                        curVar.start, curVar.end));
+            }
+            return list;
+        }
+
+        return null;
+
+    }
+
+    //This is called if/when the hint processing is cancelled:
+    @Override
+    public void cancel() {
+    }
+
+    //Message that the user sees in the left sidebar:
+    @Override
+    public String getDisplayName() {
+        return "TempVars might not be released";
+    }
+
+    //Name of the hint in the Options window:
+    @Override
+    public String getId() {
+        return "TempVars release check";
+    }
+
+    //Description of the hint in the Options window:
+    @Override
+    public String getDescription() {
+        return "Checks for calls TempVars.get() and search for correspondinng release() call";
+    }
+
+    class MessagesFix implements EnhancedFix {
+
+        Document doc = null;
+        int start = 0;
+        String bodyText = null;
+
+        public MessagesFix(Document doc, int start, String bodyText) {
+            this.doc = doc;
+            this.start = start;
+            this.bodyText = bodyText;
+        }
+
+        @Override
+        public CharSequence getSortText() {
+            return "charsequence";
+        }
+
+        @Override
+        public String getText() {
+            return "Add a release() call at the end of the method";
+        }
+
+        @Override
+        public ChangeInfo implement() throws Exception {
+            //Adding the release call
+            doc.insertString(start, bodyText, null);            
+            //Display message to user in status bar:
+            StatusDisplayer.getDefault().setStatusText("Added: " + bodyText);
+            return null;
+        }
+    }
+
+    class varsPosition {
+
+        String varName;
+        int start;
+        int end;
+
+        public varsPosition(String varName, int start, int end) {
+            this.varName = varName;
+            this.end = end;
+            this.start = start;
+        }
+    }
+}

+ 1 - 0
jme3-code-check/src/com/jme3/gde/codecheck/layer.xml

@@ -8,6 +8,7 @@
                     <file name="com-jme3-gde-codecheck-hints-UpdateHint.instance"/>
                     <file name="com-jme3-gde-codecheck-hints-ReadOnlyPrimitiveHint.instance"/>
                     <file name="com-jme3-gde-codecheck-hints-InternalMethodHint.instance"/>
+                    <file name="com-jme3-gde-codecheck-hints-TempVarsHint.instance"/>
                 </folder>
             </folder>
         </folder>