TreeFunctions.java :  » IDE » tIDE » tide » syntaxtree » Java Open Source

Java Open Source » IDE » tIDE 
tIDE » tide » syntaxtree » TreeFunctions.java
package tide.syntaxtree;

import japa.parser.ast.body.*;
import japa.parser.ast.CompilationUnit;
import javaparser.*;
import javaparser.javacc_gen.*;
import tide.editor.*;
import tide.sources.*;
import snow.concurrent.*;
import snow.utils.gui.*;
import snow.utils.StringUtils;
import java.util.*;
import java.io.*;

/** Some collected functions acting on the whole tree or branches.
*   (removing trailing spaces, parsing to see warnings...)
*/
public final class TreeFunctions
{

  public static boolean detectSourcesWithoutTypeOfSameName = false;
  public static boolean detectSourcesWithoutType = false;

  private TreeFunctions()
  {
  }

/** Removes the tailing spaces at the end of the lines + trim the source.
*  TODO: don't work on files opened in the editor ...
*/
  public static void removeTailingSpaces(final List<SourceFile> sfs)
  {
    final ProgressModalDialog pmd = new ProgressModalDialog(MainEditorFrame.instance, "Removing unuseful spaces in "+sfs.size()+" sources", false);
    pmd.setProgressBounds(sfs.size());
    pmd.start();

    Thread t = new Thread()
    {
     public void run()
     {
       long removed = 0;
       try
       {
        MainEditorFrame.instance.outputPanels.selectToolsTab(true);
        MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendLine("Cleaning "+sfs.size()+" java files: removing tailing spaces\n");

        int modifFiles = 0;
  sfl:  for(SourceFile s: sfs)
        {
          pmd.incrementProgress(1);
          pmd.setProgressComment( s.getJavaName() );
          if(pmd.getWasCancelled())
          {
             MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendError("\nCleaning cancelled by user.\n");
             break;
          }

          if(!s.isEditable())  // was look
          {
             MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendError("\nNot editable source: "+s.getJavaName()+"\n");
             continue sfl;
          }

          try
          {
            String src = s.getContent().trim();
            String nsrc = StringUtils.removeLineTailSpaces(src);
            int diff = src.length()-nsrc.length();
            if(diff>0)
            {
               removed += diff;
               modifFiles++;

               if(MainEditorFrame.debug)
               {
                 MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendLine(s.getJavaName()+":0: removed "+diff+" chars");
               }

               s.setCaretPositionToRemember(s.getCaretLinePosition(), s.getCaretColumnPosition());
               s.setContentFromEditor(nsrc, true);  // allow, because we are quick, we will "win" and write our version, some millis after another.
               s.saveContentToFile();
            }
          }
          catch(Exception e)
          {
            MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendError("\nCleaner ERROR\n"+s.getJavaName()+":0: "+e.getMessage()+"\n");
            e.printStackTrace();
          }
        }
        MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.append(""+removed+" characters removed in "+modifFiles+" file"+(modifFiles==1?"":"s"));
       }
       finally
       {
         pmd.closeDialog();
       }
      }
    };
    t.setName("Removing tailing spaces");
    t.start();

  }

  /** Parses all files, searching for syntax problems and write them.
  *  REMARK: this allow us to see that the parse tree have NO memory leak !
  *  parsing 2500 files don't leaks !
  */
  public static void parseAllToSearchForProblems(final List<SourceFile> sfs, final boolean onlyRawParse)
  {
    final ProgressModalDialog pmd = new ProgressModalDialog(MainEditorFrame.instance, "Parsing "+sfs.size()
      +" sources with the CC parser of Sreenivasa Viswanadha", false);
    pmd.setProgressBounds(sfs.size());
    pmd.start();

    Thread t = new Thread()
    {
     public void run()
     {
       try
       {
        long t0 = System.currentTimeMillis();

        MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.setText("Parsing "+sfs.size()+" java files\n");
        MainEditorFrame.instance.outputPanels.selectToolsTab(false);
        int w = 0;
        int err = 0;
        int exc = 0;

        for(SourceFile s: sfs)
        {
          pmd.incrementProgress(1);
          pmd.setProgressComment( s.getJavaName() );
          if(pmd.getWasCancelled())
          {
            MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendError("\nParsing cancelled by user.");
            break;
          }

          try
          {
            int[] wee = parse(s, onlyRawParse); //.getContent(), s.getJavaName(), s.javaFile);
            w += wee[0];
            err += wee[1];
            exc += wee[2];
          }
          catch(Exception e)
          {
            MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendError("\nPARSER ERROR\n"+s.getJavaName()+": "+e.getMessage());
            e.printStackTrace();
          }
        }
        if(MainEditorFrame.debug)
        {
          MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.append("\nTotal time = " + (System.currentTimeMillis()-t0) + " ms, ");
        }
        MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.append("\n"+w+" warnings.");
        if(err>0)
        {
           MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendError(" "+err+" errors.");
        }
        if(exc>0)
        {
           MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendError(" "+exc+" exceptions.");
        }

       }
       finally
       {
         pmd.closeDialog();
       }
      }
    };
    t.setName("Parse debug");
    t.start();

  }

  /** Parses all files, searching for syntax problems and write them.
  *  REMARK: this allow us to see that the parse tree have NO memory leak !
  *  parsing 2500 files don't leaks !
  */
  public static void parseAllToSearchForProblems2(final List<SourceFile> sfs, final boolean onlyRawParse)
  {
    final ProgressModalDialog pmd = new ProgressModalDialog(MainEditorFrame.instance, "Parsing "+sfs.size()
      +" sources with the new CC parser of Jlio Vilmar Gesser (jgesser@gmail.com)", false);
    pmd.setProgressBounds(sfs.size());
    pmd.start();

    Thread t = new Thread()
    {
     public void run()
     {
       try
       {
        long t0 = System.currentTimeMillis();

        MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.setText("Parsing "+sfs.size()+" java files\n");
        MainEditorFrame.instance.outputPanels.selectToolsTab(false);
        int w = 0, err=0, exc=0;
        for(SourceFile s: sfs)
        {
          pmd.incrementProgress(1);
          pmd.setProgressComment( s.getJavaName() );
          if(pmd.getWasCancelled())
          {
            MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendError("\nParsing cancelled by user.");
            break;
          }

          try
          {
            int[] wee = parse2(s, onlyRawParse); //.getContent(), s.getJavaName(), s.javaFile);
            w += wee[0];
            err += wee[1];
            exc += wee[2];

          }
          catch(Exception e)
          {
            MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendError("\nPARSER ERROR\n"+s.getJavaName()+": "+e.getMessage());
            e.printStackTrace();
          }
        }
        //if(MainEditorFrame.debug)
        {
          MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.append("\nTotal time = " + (System.currentTimeMillis()-t0) + " ms, ");
        }
        MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.append("\n"+w+" warnings.");
        if(err>0)
        {
           MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendError(" "+err+" errors.");
        }
        if(exc>0)
        {
           MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendError(" "+exc+" exceptions.");
        }

       }
       finally
       {
         pmd.closeDialog();
       }
      }
    };
    t.setName("Parse debug");
    t.start();

  }


  /** The thread must be launched with start() after creation.
  */
  public static Thread createDetectDependenciesThread(final List<SourceFile> sfs, final boolean writeOut)
  {
    // A safe swing call
    final ProgressModalDialog[] pmd = new ProgressModalDialog[1];
    new SwingSafeRunnable(new Runnable() { public void run() {
       pmd[0] = new ProgressModalDialog(MainEditorFrame.instance, "Detecting dependencies of "+sfs.size()+" sources", false);
    }}, true).run();

    MainEditorFrame.debugOut("Detecting dependentcies of "+sfs.size()+" sources.");

    pmd[0].setProgressBounds(sfs.size());
    pmd[0].start();

    Thread t = new Thread()
    {
     public void run()
     {
       try
       {
        long t0 = System.currentTimeMillis();

        if(writeOut)
        {
          MainEditorFrame.instance.outputPanels.selectToolsTab(true);
        }

        /* debug
        MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.append("Detecting dependencies of "+sfs.size()+" java files");
        if(sfs.size()>0 && sfs.size()<5)
        {
           MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendLine(": "+sfs);
        }
        else
        {
           MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendLine("");
        }*/

        for(final SourceFile s: sfs)
        {
          pmd[0].incrementProgress(1);
          pmd[0].setProgressComment( s.getJavaName() );
          if(pmd[0].getWasCancelled())
          {
            MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendErrorLine("Parsing cancelled by user.");
            break;
          }

          try
          {
            DependenciesDetector.updateDependencies(s, writeOut);
            //MainEditorFrame.debugOut("Updated: "+s.sourceFileDependencies);
          }
          catch(Exception e)
          {
            MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendErrorLine("PARSER ERROR\n"+s.getJavaName()+": "+e.getMessage());
            e.printStackTrace();
          }
        }

        if(MainEditorFrame.debug)
        {
           long dt = (System.currentTimeMillis()-t0);
           if(dt>1000)
           {
             MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendLine("Total dependencies detecting time = " + dt + " ms for "+sfs.size()+" files");
           }
        }
       }
       finally
       {
         pmd[0].closeDialog();
       }
      }
    };
    t.setName("Dependencies detection");

    return t;
  }

  /** ex: japa.parser.ParseException: Encountered "(" at line 116, column 43.
   */
  private static int[] getLinColFromParserMess(String message)
  {
     int line = 0;
     int pos = message.indexOf("line ");
     if(pos>0)
     {
       int posE = message.indexOf(',', pos+5);
       if(posE>0)
       {
         String ls = message.substring(pos+5, posE);
         //System.out.println("Error node: ls="+ls);
         try
         {
            line = Integer.parseInt(ls);
         } catch(Exception ee) { }
       }
     }

     int column = 0;
     pos = message.indexOf("column ", pos);
     if(pos>0)
     {
       int posE = message.indexOf('.', pos+7);
       if(posE>0)
       {
         String ls = message.substring(pos+7, posE);
         try
         {
            column = Integer.parseInt(ls);
         } catch(Exception ee) { }
       }
     }
     return new int[]{line,column};
  }


/** @return the number of warnings.
*   AST dev trick: search in the DumpVisitor to find out where the items araises...
*/
  public static int[] parse2(FileItem f, boolean onlyRawParse)
  {
     int w = 0;
     int err = 0;
     int exc = 0;

     //long t0 = System.currentTimeMillis();
     try
     {
       // special case.
       if(f.getJavaPartName().equals("package-info")) return new int[3];

       StringReader sr = new StringReader(f.getContent());
       CompilationUnit cu = japa.parser.JavaParser.parse(sr);

       if(onlyRawParse) return new int[3];  // just to see if it is parsable

//       System.out.println(""+ cu.pakage.toString());
       String pan = cu.pakage != null ? cu.pakage.toString():"";
    /*   if(!f.getPackageName().equals(pan))
       {
          MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.append("\n\tat "+f.getJavaName()+"("+f.getJavaPartName()+".java:"+1+")");
          MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.append(": bad package name '"+pan+"' should be '"
            +f.getPackageName()+"'");
          w++;
       }*/

       List<TypeDeclaration> types = cu.types;

       //System.out.println(""+types);
       if(types==null || types.isEmpty())
       {
          if(detectSourcesWithoutType)
          {
            MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.append("\n\tat "+f.getJavaName()+"("+f.getJavaPartName()+".java:"+1+")");
            MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.append(": no declared type");
            w++;
          }
       }
       else
       {
          boolean hasNamed = false;
          for(TypeDeclaration ti : types)
          {
             //System.out.println("type: "+ti.name);
             // ti is null when classes blocks have exceding ";" at end, as in 1.6 and 1.7 src.
             if(detectSourcesWithoutTypeOfSameName && ti.name!=null && ti.name.equals(f.getJavaPartName()))
             {
                hasNamed = true;
             }
             //analyse(ti);
          }

          if(detectSourcesWithoutTypeOfSameName && !hasNamed)
          {
             w++;
             MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.append("\n\tat "+f.getJavaName()+"("+f.getJavaPartName()+".java:"+1+")");
             MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.append(": no type named '"+f.getJavaPartName()+"'");
          }
       }

     }
     catch(Error e)  // REALLY ! Lexical error
     {
       int[] lc = getLinColFromParserMess(e.getMessage());
       //MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendError("\nParseerror: "+e.getMessage());
       MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendErrorLine("\n\tat "+f.getJavaName()+"("+f.getJavaPartName()+".java:"+lc[0]+"): ERROR "+StringUtils.firstLine(e.getMessage()));
       //e.printStackTrace();
       err++;
     }
     catch(Exception e)
     {
       int[] lc = getLinColFromParserMess(e.getMessage());
       //MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendError("\nParseerror: "+e.getMessage());
       MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendErrorLine("\n\tat "+f.getJavaName()+"("+f.getJavaPartName()+".java:"+lc[0]+"): "+StringUtils.firstLine(e.getMessage()));
       //e.printStackTrace();
       exc++;
     }


     return new int[]{w,err,exc};
  }

@tide.annotations.Recurse
  static void analyse(TypeDeclaration ti)
  {
     System.out.println("Visiting type "+ti.name);

     JapaVisitor jv = new  JapaVisitor();
     ti.accept(jv, null); //??

     for(BodyDeclaration mi : ti.members)  // fields, methods, inner class,...
     {
       //System.out.println("mi:"+mi);
       mi.accept(jv, null); //??

       if(mi instanceof TypeDeclaration)
       {
          analyse((TypeDeclaration) mi);
       }
     }
  }

  /** @return the number of warnings.
  */
  public static int[] parse(FileItem f, boolean onlyRawParse)
  {
     int w = 0;
     int err = 0;
     int exc = 0;
     //long t0 = System.currentTimeMillis();
     try
     {
       StringReader sr = new StringReader(f.getContent());
       JavaParser pa = new JavaParser(sr);
       pa.disable_tracing();
       RAWSyntaxTree st = new RAWSyntaxTree(f.getJavaName());
       pa.parserOutputProcessor = st;

       pa.CompilationUnit();

       if(onlyRawParse) return new int[3];

       //System.out.println("\nJavaParser took " + (System.currentTimeMillis()-t0) + " ms for "+f);
       final SimplifiedSyntaxTree2 sst = new SimplifiedSyntaxTree2(st.root, f.getJavaName());
       TreeFunctions.searchForCommonProblems(sst, sst.root, f.getJavaName());
       sst.callAtEndToMakeWarningsVisible();

       w = sst.getWarningsCount();
       if(w>0)
       {
          for(int i=0; i<w; i++)
          {
            WarningNode wn = sst.getWarningNodeAt(i);
            MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.append("\n\tat "+f.getJavaName()+"("+f.getJavaPartName()+".java:"+wn.getStartLinCol()[0]+"): ");

            if(wn.gravity==1)
            {
              MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendError(wn.toString());
            }
            else
            {
              MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.append(wn.toString());
            }
          }
       }

       //System.out.println(""+fileName +"\t" +(System.currentTimeMillis()-t0) + "");
       //final DefaultTreeModel tm = new DefaultTreeModel(sst.root);
     }
     catch(Error e)  // REALLY ! Lexical error
     {
       int[] lc = getLinColFromParserMess(e.getMessage());
       //MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendError("\nParseerror: "+e.getMessage());
       MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendErrorLine("\n\tat "+f.getJavaName()+"("+f.getJavaPartName()+".java:"+lc[0]+"): ERROR "+StringUtils.firstLine(e.getMessage()));
       //e.printStackTrace();
       err++;
     }
     catch(Exception e)
     {
       int[] lc = getLinColFromParserMess(e.getMessage());
       //MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendError("\nParseerror: "+e.getMessage());
       MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.appendErrorLine("\n\tat "+f.getJavaName()+"("+f.getJavaPartName()+".java:"+lc[0]+"): "+StringUtils.firstLine(e.getMessage()));
       //e.printStackTrace();
       exc++;
     }

     return new int[]{w,err,exc};
  }

  /** Apply all searches for common known problems.
  */
  public static void searchForCommonProblems(SimplifiedSyntaxTree2 sst, final ParserTreeNode root, String javaName)
  {
    ProblemsSearch.analyseFile(sst, javaName);
    searchForCommonProblemsRecurse(sst, root);
  }

  private static void searchForCommonProblemsRecurse(SimplifiedSyntaxTree2 sst, final ParserTreeNode root)
  {

     for(int i=0; i<root.getChildCount(); i++)
     {
        final ParserTreeNode ci = root.getChildNodeAt(i);
        if(ci instanceof ClassNode)
        {
           ProblemsSearch.analyseClass(sst, (ClassNode) ci);
        }
        // recursively look for errors
        searchForCommonProblemsRecurse(sst, ci);
     }
  }


}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.