Skip to content
Permalink
Browse files

Merge pull request #1471 from umple/parseLabeledMethods

Progress on parsing labeled methods
  • Loading branch information...
TimLethbridge committed Jul 5, 2019
2 parents 7710392 + 897b0ab commit f6199eacd90768b3a2f8346b9ceb0a4ea0d3444f
@@ -216,7 +216,58 @@ for (StateMachine smq : uClass.getStateMachines())
{
#>><<@ UmpleToJava.enumerations_All >><<#
}


// This method allows the injection of some code before/after a code label inside a method of an umple class.
private void applyCodeInjectionToLabeledMethod(UmpleClass uClass, Method aMethod, String aspectType) {
List<CodeInjection> uClassCodeInectionList = uClass.getApplicableCodeInjectionsCustomMethod(aspectType, aMethod.getName(), aMethod.getMethodParameters());
if(uClassCodeInectionList.size() == 0 )
{
// no code to inject
// return;
}
CodeBlock methodCodeBlock = aMethod.getMethodBody().getCodeblock();
String codesKey_lang = ""; // the type of a language that the method belongs to
ArrayList<String> methodCodeWithLabels = methodCodeBlock.getCodeWithLabels(codesKey_lang);
ArrayList<Integer> indexToRemoveList = new ArrayList<Integer>();
for (CodeInjection codeInjectionItem: uClassCodeInectionList)
{

if(! codeInjectionItem.hasCodeLabel()) // we are concerning with only codeInjection item which has code labels.
continue;
//else
String methodLabelToLookat = codeInjectionItem.getInjectionlabel();
String codeToAdd = codeInjectionItem.getCode(codesKey_lang);

int indexOfLabel = methodCodeWithLabels.indexOf(methodLabelToLookat);
if (indexOfLabel == -1) // the method does not contain the required label
{
// raise error
// raise warning
}
else if (codeInjectionItem.getType().equals("before"))
{
methodCodeWithLabels.add(indexOfLabel, "\n"+codeToAdd + "\n");
}
else if (codeInjectionItem.getType().equals("after"))
{
if(indexOfLabel < methodCodeWithLabels.size())
methodCodeWithLabels.add(indexOfLabel+1, "\n"+codeToAdd + "\n");
else
methodCodeWithLabels.add("\n"+codeToAdd + "\n");
}
// at the end, remove the codeInjection belongs to labeled aspect
// otherwise it will be added to the code when handling aspects
//uClassCodeInectionList.remove(codeInjectionItem); // causes error:ConcurrentModificationException
//indexToRemoveList.add(uClassCodeInectionList.indexOf(codeInjectionItem));
// update the method code with addition
String resultCode="";
for (String stringItem : methodCodeWithLabels)
{
resultCode += stringItem ;
}
aMethod.getMethodBody().getCodeblock().setCode(codesKey_lang, resultCode);
}
}
/*
* Issue 1008 - A helper function to determine if a class uses an enum defined in the model
*/
@@ -80,6 +80,13 @@ class UmpleToJava {
{
// If this is not a constructor, this method should return "void"
methodType = methodType.equals("") ? "void" : methodType;
}
// check if labels have not been processed for aspect with labels
if(!aMethod.getLabelsProcessed())
{
applyCodeInjectionToLabeledMethod(uClass, aMethod, "before");
applyCodeInjectionToLabeledMethod(uClass, aMethod, "after");
aMethod.setLabelsProcessed(true);
}
String customBeforeInjectionCode = GeneratorHelper.toCode(uClass.getApplicableCodeInjectionsCustomMethod("before", aMethod.getName(), aMethod.getMethodParameters()));
String customAfterInjectionCode = GeneratorHelper.toCode(uClass.getApplicableCodeInjectionsCustomMethod("after", aMethod.getName(), aMethod.getMethodParameters()));
@@ -61,6 +61,8 @@ class GeneratorHelper
{
for (CodeInjection inject : allCodeInjections)
{
if(inject.hasCodeLabel())
continue;// handle the case when labels are used. // Do nothing
String comment = "//";//(inject.getSnippet().getCode("Ruby") != null)?"#":"//";
String positionString = "";
Position p = inject.getPosition();
@@ -85,7 +87,9 @@ class GeneratorHelper
{
asCode = positionString + inject.getConstraintCode(generator) + injectFooter;
}

else asCode = (inject.getCode()!=null)?positionString + inject.getCode() + injectFooter:positionString + injectFooter;

}
else
{
@@ -3680,6 +3680,7 @@ private Boolean checkIsDistributed(UmpleInterface uInterface)
private void analyzeInjectionCode(Token injectToken, UmpleClassifier uClassifier)
{
String type = injectToken.is("beforeCode") ? "before" : "after";
Token codeLabelToken = injectToken.getSubToken("codeLabel");
CodeBlock cb = new CodeBlock();
String operationName = getOperationName(injectToken);
String operationSource = getOperationSource(injectToken).toLowerCase();
@@ -3690,6 +3691,9 @@ private Boolean checkIsDistributed(UmpleInterface uInterface)

CodeInjection injection = new CodeInjection(type,operationName,"",uClassifier);
injection.setOperationSource(operationSource);
// check if the aspect needs to be injected before/after a label.
if(codeLabelToken != null)
injection.setInjectionlabel(codeLabelToken.getValue());

List<String> operationsParameters = getOperationsParameters(injectToken);
for(String operationParameters : operationsParameters) {
@@ -335,7 +335,46 @@ class UmpleInternalParser
return mixset ;
}



}

class CodeInjection{
String injectionlabel = "";

boolean hasCodeLabel()
{
return ! injectionlabel.equals("");
}
}

class CodeBlock{
depend java.util.regex.Matcher;
depend java.util.regex.Pattern;

public ArrayList<String> getCodeWithLabels(String codesKey) {
ArrayList <String> codeLabels = new ArrayList<String>();
String codeToLockAt = getCode(codesKey);
ArrayList<String> codeWithLabels = new ArrayList<String>();
Pattern labelPatternToMatch = Pattern.compile("(\\S+):");
Matcher matcher = labelPatternToMatch.matcher(codeToLockAt);
int lastMatchedIndex=0;
while (matcher.find()) {
String codeBeforeLabel = codeToLockAt.substring(lastMatchedIndex, matcher.start());
if(!codeBeforeLabel.equals(""))
codeWithLabels.add(codeBeforeLabel);
codeWithLabels.add(matcher.group()); //add the label itself to the source code.
codeLabels.add(matcher.group().replaceFirst(":","")); // remove colon and add it the list of labels
lastMatchedIndex = matcher.end();
}
// This for last label, to add the code after last matched label
String codeAfterLastLabel =codeToLockAt.substring(lastMatchedIndex);
codeWithLabels.add(codeAfterLastLabel);
return codeWithLabels;
}

class Method {
boolean labelsProcessed = false;
}

}

@@ -32,5 +32,5 @@ parameterListing : OPEN_ROUND_BRACKET ([[parameterTypes]])? CLOSE_ROUND_BRACKET

injectionOperation : [operationName] ([[parameterListing]])?

beforeCode : before ([=operationSource:custom|generated|all])? [[injectionOperation]] ( , [[injectionOperation]] )* ([[codeLang]] [[codeLangs]])? { [**code] } ( [[moreCode]] )*
afterCode : after ([=operationSource:custom|generated|all])? [[injectionOperation]] ( , [[injectionOperation]] )* ([[codeLang]] [[codeLangs]])? { [**code] } ( [[moreCode]] )*
beforeCode : before ([=operationSource:custom|generated|all])? ([!codeLabel:\S+:])? [[injectionOperation]] ( , [[injectionOperation]] )* ([[codeLang]] [[codeLangs]])? { [**code] } ( [[moreCode]] )*
afterCode : after ([=operationSource:custom|generated|all])? ([!codeLabel:\S+:])? [[injectionOperation]] ( , [[injectionOperation]] )* ([[codeLang]] [[codeLangs]])? { [**code] } ( [[moreCode]] )*
@@ -13,6 +13,7 @@
import cruise.umple.compiler.FeatureLink;
import cruise.umple.compiler.FeatureNode;
import cruise.umple.compiler.FeatureLeaf;
import cruise.umple.compiler.Method;

public class UmpleMixsetTest {

@@ -536,5 +537,32 @@ public void parseInlineMixsetInsideUmpleEntity()
List<UmpleClass> umpleClasses = model.getUmpleClasses();
Assert.assertEquals(umpleClasses.get(0).getAttribute(0).getName(),"attr1");
}
@Test
public void parseLabelsInsideMethod()
{
UmpleFile umpleFile =new UmpleFile(umpleParserTest.pathToInput,"parseLabelsInsideMethod_basic.ump");
UmpleModel umodel = new UmpleModel(umpleFile);
umodel.run();
umodel.generate();
UmpleClass uClass = umodel.getUmpleClass(0);
Method aMethod = uClass.getMethod(5);
String methodBodyCode= aMethod.getMethodBody().getCodeblock().getCode();
String beforeLabelCode = methodBodyCode.substring(0,methodBodyCode.indexOf("SecondLabel:"));
String afterLabelCode = methodBodyCode.substring(methodBodyCode.indexOf("SecondLabel:"));

Assert.assertEquals(true, beforeLabelCode.contains("code added before the SecondLabel in staticMethod()."));
Assert.assertEquals(true, methodBodyCode.contains("SecondLabel:"));
Assert.assertEquals(true, afterLabelCode.contains("code added after the SecondLabel in staticMethod()."));
try
{
SampleFileWriter.assertFileExists(umpleParserTest.pathToInput+"/"+"InjectToLabel.java");
}
finally
{
SampleFileWriter.destroy(umpleParserTest.pathToInput+"/"+"InjectToLabel.java");
}


}

}
@@ -0,0 +1,35 @@
class InjectToLabel
{
firstName;
lastName;
public static void staticMethod( )
{
FirstLabel: System.out.println("this is line 1.");
System.out.println("this is line 2.");
SecondLabel: System.out.println("this is line 3");
}

before custom SecondLabel:staticMethod
{
//Start before SecondLabel.
System.out.println("code added before the SecondLabel in staticMethod().");
//End before SecondLabel.
}

void main(String[] arg)
{

}

public void objectMethod()
{
}
after custom SecondLabel:staticMethod
{
//Start after SecondLabel.
System.out.println("code added after the SecondLabel in staticMethod().");
//End after SecondLabel.
}
}


0 comments on commit f6199ea

Please sign in to comment.
You can’t perform that action at this time.