628 lines
21 KiB
Java
Executable File
628 lines
21 KiB
Java
Executable File
package pyUML.pythonTree;
|
|
|
|
import java.util.Dictionary;
|
|
import java.util.Hashtable;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Vector;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
|
|
import org.eclipse.uml2.uml.Class;
|
|
import org.eclipse.uml2.uml.Classifier;
|
|
import org.eclipse.uml2.uml.Comment;
|
|
import org.eclipse.uml2.uml.Interface;
|
|
import org.eclipse.uml2.uml.NamedElement;
|
|
import org.eclipse.uml2.uml.Operation;
|
|
import org.eclipse.uml2.uml.Parameter;
|
|
import org.eclipse.uml2.uml.Property;
|
|
import org.eclipse.uml2.uml.VisibilityKind;
|
|
import org.python.pydev.parser.jython.ast.Expr;
|
|
import org.python.pydev.parser.jython.ast.FunctionDef;
|
|
import org.python.pydev.parser.jython.ast.Name;
|
|
import org.python.pydev.parser.jython.ast.NameTok;
|
|
import org.python.pydev.parser.jython.ast.Str;
|
|
import org.python.pydev.parser.jython.ast.exprType;
|
|
import org.python.pydev.parser.jython.ast.stmtType;
|
|
|
|
import pyUML.backend.GlobalConstants;
|
|
import pyUML.backend.ParseHelpers;
|
|
import pyUML.exceptions.PyUMLParseException;
|
|
import pyUML.exceptions.PyUMLSynchronizeCodeException;
|
|
import pyUML.refactoring.BicycleRefactoring;
|
|
import pyUML.refactoring.FileRefactoring;
|
|
|
|
|
|
/**
|
|
* This class represents a Method definition inside a Python Class
|
|
*/
|
|
public class PythonTreeMethod extends PythonTreeNode {
|
|
private FunctionDef astNode;
|
|
private boolean staticMethod;
|
|
private List<String> arguments;
|
|
private String docString;
|
|
private int docStringLine;
|
|
private int docStringCol;
|
|
private int lastLine;
|
|
private String indent = " ";
|
|
private Dictionary<String, String> argumentDefaultDict;
|
|
private Dictionary<String, Integer> argumentLineDict;
|
|
private Dictionary<String, Integer> argumentColumnDict;
|
|
|
|
public PythonTreeMethod(PythonTreeClass parent, FunctionDef astNode, int nextLine) throws PyUMLParseException{
|
|
super(parent);
|
|
this.astNode = astNode;
|
|
this.lastLine = nextLine - 1;
|
|
// set last non-empty line as last line of this method
|
|
while (this.lastLine>=0 && parent.inFile.getSplittedFileContent()[lastLine-1].matches("[\\s]*")) {
|
|
this.lastLine--;
|
|
}
|
|
|
|
this.arguments = new Vector<String>();
|
|
this.argumentDefaultDict = new Hashtable<String, String>();
|
|
this.argumentLineDict = new Hashtable<String, Integer>();
|
|
this.argumentColumnDict = new Hashtable<String, Integer>();
|
|
this.initMethod();
|
|
}
|
|
|
|
public void initMethod() throws PyUMLParseException{
|
|
this.name = ((NameTok) this.astNode.name).id;
|
|
|
|
if (this.name.matches(".*__init__.*") && this.getParent().getName().matches(".*CMCEntryBrows.*")) {
|
|
}
|
|
exprType[] argList = this.astNode.args.args;
|
|
exprType[] defaultList = this.astNode.args.defaults;
|
|
|
|
// ### Get Arguments ### //
|
|
|
|
// get offset of first argument with default value
|
|
int argCount = argList.length;
|
|
int defaultCount = defaultList.length;
|
|
int defaultOffset = argCount - defaultCount;
|
|
|
|
// get arguments with corresponding default values
|
|
int argNo = 0;
|
|
for (exprType arg : argList) {
|
|
// fix indent, if needed
|
|
String line = this.getParent().getInFile().getSplittedFileContent()[arg.beginLine ];
|
|
int indentLength=0;
|
|
if (line.length() > 0)
|
|
for (; line.charAt(indentLength) == ' ' && line.length() > indentLength +1 ; indentLength++) ;
|
|
if (this.indent.length() != indentLength && ! line.matches("^[\\s]*\\\"\\\"\\\".*$")) {
|
|
this.indent = "";
|
|
for (int i=0; i< indentLength; i++)
|
|
this.indent += " ";
|
|
}
|
|
|
|
// argument name
|
|
String argName = ((Name) arg).id;
|
|
if (this.arguments.contains(argName)) {
|
|
String message = "Argument inconsistency detected!\n"+
|
|
"The python method '"+this.name+ "' in the class '" +
|
|
this.getParent().getName() +
|
|
"'\nhas an argument inconsistency with the argument '" +
|
|
argName + "'.\n\n" +
|
|
"The argument exists mor than once!\n\n" +
|
|
"Please correct this error!";
|
|
throw new PyUMLParseException(message);
|
|
}
|
|
this.arguments.add(argName);
|
|
this.argumentLineDict.put(argName, arg.beginLine);
|
|
this.argumentColumnDict.put(argName, arg.beginColumn);
|
|
|
|
// argument default value
|
|
if (defaultCount> 0 && argNo >= defaultOffset && (! argName.equals("self"))) {
|
|
|
|
|
|
exprType defaultVal = defaultList[argNo - defaultOffset];
|
|
exprType defaultValBefore = null;
|
|
|
|
// test if parameter without default follows parameter with default
|
|
// -> this is not allowed but not caught by pyDev
|
|
if (argNo - defaultOffset >= 1)
|
|
defaultValBefore = defaultList[argNo - defaultOffset-1];
|
|
|
|
String defValString = ParseHelpers.getStringOfExpr(defaultVal, this.getParent().getInFile(), false, false, 0);
|
|
|
|
if (defaultVal == null && defaultValBefore!= null) {
|
|
String message = "Argument inconsistency detected!\n"+
|
|
"The python method '"+this.name+ "' in the class '" +
|
|
this.getParent().getName() +
|
|
"'\nhas an argument inconsistency with the argument '" +
|
|
argName + "'.\n\n" +
|
|
"There are arguments without default values" +
|
|
"\nfollowing arguments with default values.\n\n" +
|
|
"Please correct this error!";
|
|
throw new PyUMLParseException(message);
|
|
} else if (defaultVal != null){
|
|
this.argumentDefaultDict.put(argName, defValString);
|
|
}
|
|
}
|
|
argNo++;
|
|
}
|
|
|
|
// set static attribute */
|
|
if (argList.length == 0 || (! this.arguments.get(0).equals("self")))
|
|
this.staticMethod = true;
|
|
|
|
|
|
stmtType[] methodBody = this.astNode.body;
|
|
|
|
// extract DocString, if it exists
|
|
if (methodBody.length > 0 && methodBody[0] instanceof Expr) {
|
|
Expr exp = (Expr) methodBody[0];
|
|
if (exp.value instanceof Str) {
|
|
Str stringExp = (Str) exp.value;
|
|
if (stringExp.type == Str.TripleDouble ||
|
|
stringExp.type == Str.TripleSingle) {
|
|
this.docString=stringExp.s;
|
|
this.docStringLine = stringExp.beginLine;
|
|
this.docStringCol = stringExp.beginColumn;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public boolean synchronizeModel(NamedElement modelElement) {
|
|
|
|
super.synchronizeModel(modelElement);
|
|
Operation modelMethod = (Operation) modelElement;
|
|
|
|
// set this method private in model, if its name starts with "__"
|
|
// use protected, if class starts with "_" (this is only python convention)
|
|
if (this.getName().startsWith("__")) {
|
|
modelMethod.setVisibility(VisibilityKind.PRIVATE_LITERAL);
|
|
} else if (this.getName().startsWith("_")) {
|
|
modelMethod.setVisibility(VisibilityKind.PROTECTED_LITERAL);
|
|
}
|
|
|
|
// set/remove static flag
|
|
if (this.staticMethod != modelMethod.isStatic())
|
|
modelMethod.setIsStatic(this.staticMethod);
|
|
|
|
List<Parameter> parameterList = modelMethod.getOwnedParameters();
|
|
|
|
// for all parameters in code -> check if model parameters are the same;
|
|
/// if not, add them
|
|
for (int i=0; i< this.getArguments().size(); i++) {
|
|
String pyArg = this.getArguments().get(i);
|
|
if (parameterList.size() > i) {
|
|
Parameter modelParam = parameterList.get(i);
|
|
// check if parameter name and default value are the same
|
|
String defautlValue = (this.getArgumentDefaultDict().get(pyArg));
|
|
if (defautlValue == null)
|
|
defautlValue = "";
|
|
if ((! pyArg.equals(modelParam.getName())) ||
|
|
( ! defautlValue.equals(modelParam.getDefault()))) {
|
|
|
|
// this parameter is not the same!
|
|
// remove all parameters from here and create following parameters!
|
|
for (int j=i; j< parameterList.size(); j++)
|
|
parameterList.remove(j);
|
|
|
|
// restart loop at the current position (again)
|
|
i--;
|
|
}
|
|
} else {
|
|
// Parameter at this position does not exist
|
|
// Append new parameter
|
|
Parameter newParam = modelMethod.createOwnedParameter(pyArg, null);
|
|
newParam.setDefault(this.getArgumentDefaultDict().get(pyArg));
|
|
}
|
|
}
|
|
|
|
// test, if there are additional model parameters -> remove them!
|
|
if (parameterList.size() > this.getArguments().size()) {
|
|
for (int i=this.getArguments().size(); i < parameterList.size(); i++) {
|
|
parameterList.get(i).destroy();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public boolean synchronizeCode(Operation modelOp) throws PyUMLSynchronizeCodeException{
|
|
if (this.name.matches("search.*") && this.getParent().getName().startsWith("Group")) {
|
|
}
|
|
List<String> modelParameters = new Vector<String>();
|
|
int line = this.astNode.name.beginLine;
|
|
|
|
boolean parametersNeedRewrite = false;
|
|
|
|
boolean modelIsStatic = true;
|
|
|
|
methodChildLoop:
|
|
for (Parameter modelParameter : modelOp.getOwnedParameters()) {
|
|
|
|
// get all relevant data
|
|
String modelParName = modelParameter.getName();
|
|
modelParameters.add(modelParName);
|
|
|
|
// stop if this is not a parameter (null)
|
|
if (modelParName == null)
|
|
continue methodChildLoop;
|
|
|
|
if (modelParName.equals("self")) {
|
|
modelIsStatic = false;
|
|
}
|
|
|
|
String modelParDefault = modelParameter.getDefault();
|
|
|
|
if (this.arguments.contains(modelParName)){
|
|
//found parameter with same name!
|
|
String codeParDefault = this.getArgumentDefaultDict().get(modelParName);
|
|
|
|
if (((modelParDefault == codeParDefault)&&(codeParDefault== null))
|
|
|| (modelParDefault != null && codeParDefault != null
|
|
&& (codeParDefault.equals(modelParDefault)
|
|
|| (modelParDefault.equals(GlobalConstants.getUnknownExpression())))))
|
|
// parameter exists and has the same default value
|
|
// everything is fine!
|
|
continue methodChildLoop;
|
|
|
|
|
|
// parameter exists, but with different default!
|
|
// fix default value!
|
|
|
|
// if default value does not exist in model
|
|
if (modelParDefault == null) {
|
|
parametersNeedRewrite = true;
|
|
continue methodChildLoop;
|
|
}
|
|
else if (codeParDefault == null) { //if default value wasn't there
|
|
//add a default value
|
|
parametersNeedRewrite = true;
|
|
continue methodChildLoop;
|
|
}
|
|
else {
|
|
// default value changed
|
|
// -> change default value
|
|
parametersNeedRewrite = true;
|
|
continue methodChildLoop;
|
|
}
|
|
} else {
|
|
|
|
// parameter with this name not found!
|
|
// look if parameter was renamed (look in old model)
|
|
// this is done with bicycle repair man, so that
|
|
// all references will be renamed, too
|
|
|
|
String paramXMIId = this.getRoot().getModelXmiDict().get(modelParameter);
|
|
if (this.getRoot().getXmiModelDictOld().keySet().contains(paramXMIId)) {
|
|
// parameter found -> try to find old name in code
|
|
Parameter oldModelParam = (Parameter) this.getRoot().getXmiModelDictOld().get(paramXMIId);
|
|
String oldParamName = oldModelParam.getName();
|
|
if (this.arguments.contains(oldParamName)) {
|
|
// parameter with old name found -> rename it!
|
|
int col = this.argumentColumnDict.get(oldParamName);
|
|
BicycleRefactoring.doRenameObject(this.getParent().inFile,
|
|
modelParName, line, col, this.getRoot().getProject());
|
|
setChanged(line, modelParName);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
//parameter does and did not exist in code
|
|
//create it!
|
|
parametersNeedRewrite = true;
|
|
continue methodChildLoop;
|
|
|
|
}
|
|
|
|
// check if parameters were deleted -> delete them in code!
|
|
for (String parameter : this.arguments) {
|
|
if (! modelParameters.contains(parameter)) {
|
|
//parameter does not exist in model -> delete it
|
|
parametersNeedRewrite = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// if method changed its static property,
|
|
// ensure the "staticmethod" call is added/removed
|
|
if (this.fixStaticmethodCall(modelIsStatic))
|
|
return true;
|
|
|
|
if (parametersNeedRewrite) {
|
|
// write new parameters definition
|
|
String parametersDef = "";
|
|
|
|
for (Parameter modelParameter: modelOp.getOwnedParameters()) {
|
|
// get all relevant data
|
|
String modelParName = modelParameter.getName();
|
|
|
|
// stop if this is not a parameter (null)
|
|
if (modelParName == null)
|
|
continue;
|
|
|
|
String modelParDefault = modelParameter.getDefault();
|
|
|
|
if (parametersDef.length() > 0)
|
|
parametersDef += ", ";
|
|
|
|
parametersDef += modelParName;
|
|
if (modelParDefault != null)
|
|
parametersDef += "=" + modelParDefault;
|
|
}
|
|
|
|
// replace old definition with help of regex
|
|
Pattern pattern = Pattern.compile("([\\s]*def[\\s]*[^\\(]+[\\s]*\\()[^\\)]*(\\)[\\s]*:.*)");
|
|
String defLine = FileRefactoring.getLine(this.getParent().inFile, line);
|
|
Matcher matcher = pattern.matcher(defLine);
|
|
if (! matcher.find()){
|
|
return false;
|
|
}
|
|
|
|
// write the new method definition line
|
|
String newDefLine = matcher.group(1) + parametersDef + matcher.group(2);
|
|
FileRefactoring.replaceLine(this.getParent().inFile, line, newDefLine, true);
|
|
|
|
setChanged(line, newDefLine);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* On synchronizing code:
|
|
* Test the presence of all attributes
|
|
* - add/rename them, if needed
|
|
* - check initial value and fix it, if needed
|
|
*
|
|
* @param modelClass the class in the model where the attributes are defined
|
|
* @return true, if something was changed; false otherwise
|
|
*/
|
|
public static boolean fixAttributeDefinitions(
|
|
Classifier modelClass, String initIndent,
|
|
Map<String, PythonTreeAttribute> presentAttrs,
|
|
PythonTreeClass pyClass, int lastLine, boolean isStatic)
|
|
throws PyUMLSynchronizeCodeException{
|
|
|
|
// if this is the __init__ method, ensure all non-static attributes are defined here!
|
|
//Map<String, PythonTreeAttribute> presentAttrs = pyClass.getChildObjectAttrDict();
|
|
List<Property> neededAttrs = null;
|
|
if (modelClass instanceof Class)
|
|
neededAttrs = ((Class) modelClass).getOwnedAttributes();
|
|
else if (modelClass instanceof Interface)
|
|
neededAttrs = ((Interface) modelClass).getOwnedAttributes();
|
|
|
|
for (Property neededAttr : neededAttrs) {
|
|
if (isStatic != neededAttr.isStatic())
|
|
continue;
|
|
|
|
String attrName = neededAttr.getName();
|
|
String initialValue = neededAttr.getDefault();
|
|
|
|
// if initial value was abbreviated before, try to get
|
|
// full value out of model
|
|
if (initialValue != null && initialValue.endsWith("(...)")) {
|
|
for (Comment comment :neededAttr.getOwnedComments()) {
|
|
if (comment.getBody().startsWith(GlobalConstants.getFullDefault())) {
|
|
initialValue = comment.getBody().substring(GlobalConstants.getFullDefault().length());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (! presentAttrs.containsKey(attrName)) {
|
|
// attribute is not present -> find out, if it was renamed in model
|
|
String param_xmi = pyClass.getRoot().getModelXmiDict().get(neededAttr);
|
|
if (pyClass.getRoot().getXmiModelDictOld().containsKey(param_xmi)) {
|
|
Property oldParameter = (Property) pyClass.getRoot().getXmiModelDictOld().get(param_xmi);
|
|
String oldParamName = oldParameter.getName();
|
|
if (presentAttrs.containsKey(oldParamName)) {
|
|
// attribute was renamed -> rename it in code with Bicycle Repair Man
|
|
int line = presentAttrs.get(oldParamName).getLine();
|
|
int col = presentAttrs.get(oldParamName).getCol();
|
|
boolean success = BicycleRefactoring.doRenameObject(
|
|
pyClass.inFile,
|
|
attrName, line, col, pyClass.getRoot().getProject());
|
|
return success;
|
|
}
|
|
}
|
|
// attribute is and was not present -> create it!
|
|
String attrDefLine = (isStatic ? pyClass.getIndent() : initIndent+"self.")+ attrName + " = ";
|
|
if (initialValue != null && (! initialValue.endsWith("(...)")))
|
|
attrDefLine += initialValue;
|
|
else
|
|
attrDefLine += "None";
|
|
attrDefLine += " # created by PyUML";
|
|
if (lastLine <=0 )
|
|
FileRefactoring.appendToFile(pyClass.inFile, attrDefLine);
|
|
else
|
|
FileRefactoring.insertAtLine(pyClass.inFile,
|
|
lastLine, attrDefLine + "\n");
|
|
pyClass.getRoot().setChangedFileLine(pyClass.inFile.getFilePath().toOSString()+":"+lastLine + attrDefLine + ":");
|
|
return true;
|
|
|
|
} else {
|
|
// attribute is defined, check initial value
|
|
// if initial model value ends with (...),
|
|
// this value was cut when creating the model
|
|
// -> do not change it in code
|
|
PythonTreeAttribute pyAttr = presentAttrs.get(attrName);
|
|
if (pyAttr.getValue() != null && initialValue != null) {
|
|
}
|
|
if ((!pyAttr.getValue().equals(initialValue))
|
|
&& (!(pyAttr.getValue().equals("None") && initialValue==null))
|
|
&& (! initialValue.endsWith("(...)"))
|
|
&& (! initialValue.startsWith(pyAttr.getValue().replaceAll("\\(\\.\\.\\.\\)$", ""))) ){
|
|
// default value changed!
|
|
int line = pyAttr.getLine();
|
|
|
|
Pattern pattern = Pattern.compile("([\\s]*"+(isStatic?"":"self.")+"[^=]*=[\\s]*)([^#]+)(.*)");
|
|
String defLine = FileRefactoring.getLine(pyClass.getInFile(), line);
|
|
Matcher matcher = pattern.matcher(defLine);
|
|
|
|
if (! matcher.find()){
|
|
return false;
|
|
}
|
|
|
|
String initString = initialValue;
|
|
if (initString == null)
|
|
initString = "None";
|
|
|
|
// write the new method definition line
|
|
String commentGroup = matcher.group(3);
|
|
if (commentGroup.startsWith("#"))
|
|
commentGroup = " " + commentGroup;
|
|
String newDefLine = matcher.group(1) + initString + commentGroup;
|
|
|
|
// if this was a multi-line attribute, delete
|
|
// all following lines and preserver comments
|
|
for (int i = line ; i < pyAttr.getNextLine() - 1; i++)
|
|
pyClass.getInFile().setFileContent(FileRefactoring.removeLine(pyClass.inFile, i, false, true));
|
|
|
|
// now, just replace the changed line
|
|
FileRefactoring.replaceLine(pyClass.inFile, line, newDefLine, true);
|
|
|
|
pyClass.getRoot().setChangedFileLine(pyClass.inFile.getFilePath().toOSString()+":"+line);
|
|
return true;
|
|
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* On synchronizing code:
|
|
* Test staticmethod call of this method and
|
|
* fix it, if needed
|
|
*
|
|
* (python static methods must have the call
|
|
* <methodname> = staticmethod(<methodname>)
|
|
* after the method definition)
|
|
*
|
|
* @param modelIsStatic true, if this method should be static
|
|
* in code and vice versa
|
|
* @return true, if something was changed
|
|
* false, otherwise
|
|
*/
|
|
public boolean fixStaticmethodCall(boolean modelIsStatic) throws PyUMLSynchronizeCodeException{
|
|
// ensure there is a staticmethod call after the method
|
|
String fileContent[] = this.getParent().inFile.getFileContent().split("\n");
|
|
String lineContent = "";
|
|
int lineNo = this.lastLine;
|
|
|
|
if (this.lastLine <= 0)
|
|
lineNo= fileContent.length -1;
|
|
|
|
// if next command is "staticmethod", it is meant to be
|
|
// part of *this* method
|
|
if (fileContent.length > lineNo + 1
|
|
&& fileContent[lineNo+1].matches("^[\\s]*[^=\\(\\s]*[\\s]*=[\\s]*staticmethod[\\s]*\\([\\s]*[^\\)\\s]*[\\s]*\\)[\\s]*.*")) {
|
|
// the next command is the line to change
|
|
lineNo++;
|
|
}
|
|
|
|
// find the last non-empty non-comment line
|
|
for (; lineNo>=0; lineNo--){
|
|
lineContent = fileContent[lineNo];
|
|
if (! (lineContent.matches("^[\\s]*$") || lineContent.matches("^[\\s]*#.*$")) )
|
|
break;
|
|
}
|
|
|
|
if (lineContent.matches("^[\\s]*[^=\\(\\s]*[\\s]*=[\\s]*staticmethod[\\s]*\\([\\s]*[^\\)\\s]*[\\s]*\\)[\\s]*.*")) {
|
|
// there is already a staticmethod call
|
|
if (!modelIsStatic) {
|
|
// staticmethod call has to be removed
|
|
FileRefactoring.removeLine(this.getParent().inFile, lineNo, true, false);
|
|
return true;
|
|
}
|
|
|
|
// ensure staticmethod call is OK
|
|
if (lineContent.matches("[\\s]*"+this.getName()+"[\\s]*=[\\s]*staticmethod[\\s]*\\([^\\)\\s]*\\)[\\s]*.*")){
|
|
// staticmethod call alright, nothing needs to be changed
|
|
return false;
|
|
} else {
|
|
// fix staticmethod call (e.g. when method was renamed)
|
|
String newContent = this.getParent().getIndent() + this.getName()+" = staticmethod("+this.getName()+")";
|
|
FileRefactoring.replaceLine(this.getParent().inFile, lineNo+1, newContent, true);
|
|
setChanged(lineNo, newContent);
|
|
return true;
|
|
}
|
|
} else {
|
|
// there is no staticmethod call at all
|
|
if (!modelIsStatic) {
|
|
// all is OK
|
|
return false;
|
|
} else {
|
|
//-> insert it after the end of the method
|
|
String newContent = this.getParent().getIndent()+this.getName()+" = staticmethod("+this.getName()+")";
|
|
|
|
lineNo = this.lastLine;
|
|
|
|
if (this.lastLine <= 0)
|
|
lineNo = fileContent.length -1;
|
|
|
|
// from the next method, find the first before line with whitespace
|
|
for (; lineNo>=0; lineNo--){
|
|
lineContent = fileContent[lineNo];
|
|
if (! (lineContent.matches("^[\\s]*$")))
|
|
break;
|
|
}
|
|
FileRefactoring.insertAtLine(this.getParent().inFile, lineNo + 2, newContent + "\n");
|
|
|
|
setChanged(lineNo, newContent);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* tells the position of current code change to PythonTreeRoot
|
|
* so that it can decide if the same line is changed again
|
|
* and again and thus detect an unfinished loop.
|
|
*
|
|
* @param line the changed line in the file
|
|
*/
|
|
private void setChanged(int line, String pos) throws PyUMLSynchronizeCodeException{
|
|
if (pos == null)
|
|
pos = "";
|
|
else pos = ":position:"+pos;
|
|
this.getRoot().setChangedFileLine(getParent().inFile.getFilePath().toOSString()+":"+line+pos);
|
|
}
|
|
|
|
public boolean isStatic() {
|
|
return staticMethod;
|
|
}
|
|
|
|
public PythonTreeClass getParent() {
|
|
return (PythonTreeClass) super.getParent();
|
|
}
|
|
|
|
public String getDocString() {
|
|
return docString;
|
|
}
|
|
|
|
public int getDocStringLine() {
|
|
return docStringLine;
|
|
}
|
|
|
|
public int getDocStringCol() {
|
|
return docStringCol;
|
|
}
|
|
|
|
public FunctionDef getAstNode() {
|
|
return astNode;
|
|
}
|
|
|
|
public List<String> getArguments() {
|
|
return arguments;
|
|
}
|
|
|
|
public Dictionary<String, String> getArgumentDefaultDict() {
|
|
return argumentDefaultDict;
|
|
}
|
|
|
|
public int getLastLine() {
|
|
return lastLine;
|
|
}
|
|
|
|
public String getIndent() {
|
|
return indent;
|
|
}
|
|
|
|
}
|