Eclipse-PyUML/pyUml/src/pyUML/pythonTree/PythonTreeFile.java

167 lines
4.7 KiB
Java
Executable File

package pyUML.pythonTree;
import java.io.File;
import java.util.List;
import java.util.Vector;
import org.eclipse.core.runtime.IPath;
import org.python.pydev.parser.jython.SimpleNode;
import org.python.pydev.parser.jython.ast.ClassDef;
import org.python.pydev.parser.jython.ast.Module;
import org.python.pydev.parser.jython.ast.stmtType;
import org.python.pydev.refactoring.ast.visitors.VisitorFactory;
import pyUML.backend.EclipseHelperMethods;
import pyUML.backend.ParseHelpers;
import pyUML.exceptions.PyUMLCancelledException;
import pyUML.exceptions.PyUMLParseException;
/**
* This class represents a Python file in the Python
* Package structure.
* It must have a parent package and contains a
* pydev Abstract Syntax Tree (AST)
*
*/
public class PythonTreeFile extends PythonTreeNode{
private IPath filePath;
private PythonTreePackage parent;
private SimpleNode ast;
private List<PythonTreeClass> classesInFile;
private String fileContent;
private String[] splittedFileContent = null;
public PythonTreeFile(IPath filePath, PythonTreePackage parent) throws PyUMLParseException, PyUMLCancelledException{
super(parent);
this.filePath = filePath;
this.parent = parent;
this.name = filePath.lastSegment();
this.classesInFile = new Vector<PythonTreeClass>();
this.initAst();
this.initClassesWithAST();
}
/**
* Parses the given Python file and saves the ast
*/
private void initAst() throws PyUMLParseException{
// init AST so that it will never be null
this.ast=new SimpleNode();
// try to get content of python file
this.fileContent = ParseHelpers.fileToString(
new File(filePath.toOSString()), this.getProject());
if (this.fileContent==null) {
return;
}
// get AST of file
try{
this.ast = VisitorFactory.getRootNodeFromString(this.fileContent);
} catch (Throwable t) {
String message = t.getClass().getName()+ " while parsing file "
+ this.filePath.toOSString() +"\n\n" +t.getMessage();
throw new PyUMLParseException(message);
}
}
/**
* extracts all the top level clases (no inner classes)
* out of the AST
*/
private void initClassesWithAST() throws PyUMLParseException, PyUMLCancelledException{
if (this.ast instanceof Module) {
Module pyModule = (Module) this.ast;
stmtType[] statements = pyModule.body;
for (int i = 0; i < statements.length; i++) {
if (statements[i] instanceof ClassDef) {
// get end line of class -> look for following statement
int followingLine = 0;
if (i +1 < statements.length) {
stmtType followingStmt = statements[i+1];
followingLine = followingStmt.beginLine;
}
ClassDef pyClass = (ClassDef) statements[i];
PythonTreeClass cl = new PythonTreeClass(this.parent, this, pyClass, followingLine-1);
this.classesInFile.add(cl);
}
}
}
}
public void updateFileInEclipse() {
EclipseHelperMethods.updateFile(this.getFilePath().toOSString(), this.getProject());
}
/**
* re-inits a file -> re-parses the content
* and adds new classes, if needed.
* @throws PyUMLParseException
*/
public void reInitFile() throws PyUMLParseException, PyUMLCancelledException {
for (PythonTreeClass cl : this.getClassesInFile()) {
this.getRoot().getClassDict().remove(cl.getPackageStructure()+cl.getName());
this.getRoot().getClassNameDict().remove(cl.getPackageStructure()+cl.getName());
this.getParent().getChildClasses().remove(cl);
}
this.splittedFileContent=null;
this.classesInFile = new Vector<PythonTreeClass>();
this.initAst();
this.initClassesWithAST();
this.getParent().getChildClasses().addAll(this.getClassesInFile());
this.getRoot().getChildClasses().addAll(this.getParent().getChildClasses());
}
/**
* Splits the file content by "\n", which results in an array of lines.
* The result is cached for performance reasons.
* @return an Array containing the lines of the file content
*/
public String[] getSplittedFileContent() {
if (splittedFileContent == null)
splittedFileContent = fileContent.split("\n");
return splittedFileContent;
}
public IPath getFilePath() {
return filePath;
}
public SimpleNode getAst() {
return ast;
}
public PythonTreePackage getParent() {
return parent;
}
public List<PythonTreeClass> getClassesInFile() {
return classesInFile;
}
/**
* @return the content of the whole file as a String
*/
public String getFileContent() {
return fileContent;
}
/**
* Set this objects "file content" string. This does *not*
* update any real file!
* @param fileContent the file content as a String
*/
public void setFileContent(String fileContent) {
this.fileContent = fileContent;
this.splittedFileContent=null;
}
public void setFilePath(IPath filePath) {
this.filePath = filePath;
}
}