Loading de.ugoe.cs.swe.T3Q/src/de/ugoe/cs/swe/T3Q/DependencyAnalyzer.java 0 → 100644 +621 −0 Original line number Diff line number Diff line package de.ugoe.cs.swe.T3Q; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature.Setting; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.Resource.Diagnostic; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.xtext.CrossReference; import org.eclipse.xtext.EcoreUtil2; import org.eclipse.xtext.nodemodel.ICompositeNode; import org.eclipse.xtext.nodemodel.INode; import org.eclipse.xtext.nodemodel.util.NodeModelUtils; import com.google.common.base.Stopwatch; import com.google.common.collect.Lists; import de.ugoe.cs.swe.common.MiscTools; import de.ugoe.cs.swe.common.logging.LoggingInterface; import de.ugoe.cs.swe.common.logging.LoggingInterface.MessageClass; import de.ugoe.cs.swe.tTCN3.AltstepDef; import de.ugoe.cs.swe.tTCN3.BaseTemplate; import de.ugoe.cs.swe.tTCN3.ComponentDef; import de.ugoe.cs.swe.tTCN3.ConstDef; import de.ugoe.cs.swe.tTCN3.EnumDefNamed; import de.ugoe.cs.swe.tTCN3.ExtConstDef; import de.ugoe.cs.swe.tTCN3.ExtFunctionDef; import de.ugoe.cs.swe.tTCN3.FunctionDef; import de.ugoe.cs.swe.tTCN3.GroupDef; import de.ugoe.cs.swe.tTCN3.ImportDef; import de.ugoe.cs.swe.tTCN3.ModuleDefinition; import de.ugoe.cs.swe.tTCN3.ModulePar; import de.ugoe.cs.swe.tTCN3.ModuleParDef; import de.ugoe.cs.swe.tTCN3.ModuleParameter; import de.ugoe.cs.swe.tTCN3.NamedObject; import de.ugoe.cs.swe.tTCN3.PortDef; import de.ugoe.cs.swe.tTCN3.RecordDefNamed; import de.ugoe.cs.swe.tTCN3.RecordOfDefNamed; import de.ugoe.cs.swe.tTCN3.SetDefNamed; import de.ugoe.cs.swe.tTCN3.SetOfDefNamed; import de.ugoe.cs.swe.tTCN3.SignatureDef; import de.ugoe.cs.swe.tTCN3.SingleConstDef; import de.ugoe.cs.swe.tTCN3.SubTypeDefNamed; import de.ugoe.cs.swe.tTCN3.TTCN3File; import de.ugoe.cs.swe.tTCN3.TTCN3Module; import de.ugoe.cs.swe.tTCN3.TemplateDef; import de.ugoe.cs.swe.tTCN3.TestcaseDef; import de.ugoe.cs.swe.tTCN3.TypeDef; import de.ugoe.cs.swe.tTCN3.TypeDefBody; import de.ugoe.cs.swe.tTCN3.UnionDefNamed; import de.ugoe.cs.swe.validation.TTCN3StatisticsProvider; public class DependencyAnalyzer implements Callable<TTCN3Dependency> { private final Resource resource; private final LoggingInterface logger; public static boolean printUnresolvedObjects = false; private final LinkedHashMap<String,String> types = new LinkedHashMap<String, String>(); public DependencyAnalyzer(Resource resource, LoggingInterface logger) { this.resource = resource; this.logger = logger; types.put("TypeDef", "Type"); types.put("ComponentDef", "Type"); types.put("PortDef", "Type"); types.put("TemplateDef", "Template"); types.put("FunctionDef", "Function"); types.put("AltstepDef", "Altstep"); types.put("TestcaseDef", "Testcase"); types.put("ConstDef", "Constant"); types.put("ExtConstDef", "External Constant"); types.put("ExtFunctionDef", "External Function"); types.put("ModuleParDef", "Module Parameter"); types.put("SignatureDef", "Signature"); types.put("GroupDef", "Group"); } private TTCN3Dependency analyze() { final TTCN3Dependency output = new TTCN3Dependency(this.resource); final Stopwatch stopwatch = Stopwatch.createUnstarted(); stopwatch.start(); EcoreUtil.resolveAll(this.resource); EObject model = this.resource.getContents().get(0); for (TTCN3Module module : ((TTCN3File)model).getModules()) { List<ModuleDefinition> definitions = EcoreUtil2.getAllContentsOfType(module, ModuleDefinition.class); for (ModuleDefinition d : definitions) { INode node = NodeModelUtils.getNode(d); String moduleName = module.getName(); String elementName = getModuleDefinitionName(d); String id = moduleName+"-"+elementName; String type = types.get(d.getDef().eClass().getName()); String fileName = this.resource.getURI().segment(this.resource.getURI().segmentCount()-1); int startLine = node.getStartLine(); int endLine = node.getTotalEndLine(); if (type != null && elementName != null) { if (type.equals("Module Parameter")) { List<ModuleParameter> parameters = EcoreUtil2.getAllContentsOfType(d, ModuleParameter.class); String option = ""; if (parameters.size() > 1) { option = " conflicted=\"true\""; } for (ModuleParameter p : parameters) { String pElementName = p.getName(); String pid = moduleName+"-"+pElementName; INode pNode = NodeModelUtils.getNode(p); int pStartLine = pNode.getStartLine(); int pEndLine = pNode.getTotalEndLine(); //less precise, legacy way pStartLine = startLine; pEndLine = endLine; String references = ""; references += getReferences(p, pNode, pid); references += getReferences(((ModulePar)p.eContainer().eContainer()).getType(), pNode, pid); references = "\n\t\t<reflist>"+references+"\n\t\t</reflist>"; String xml = "\t" +"<element" +" id=\""+pid+"\"" +" name=\""+pElementName+"\"" +" type=\""+type+"\"" +" startline=\""+pStartLine+"\"" +" endline=\""+pEndLine+"\"" +" module=\""+moduleName+"\"" +" file=\""+fileName+"\"" +option + ">" +references +"\n\t" + "</element>" + "\n\n" ; output.getOutput().add(xml); } } else if (type.equals("Constant")) { List<SingleConstDef> constants = EcoreUtil2.getAllContentsOfType(d, SingleConstDef.class); String option = ""; if (constants.size() > 1) { option = " conflicted=\"true\""; } for (SingleConstDef p : constants) { String pElementName = p.getName(); String pid = moduleName+"-"+pElementName; INode pNode = NodeModelUtils.getNode(p); int pStartLine = pNode.getStartLine(); int pEndLine = pNode.getTotalEndLine(); //less precise, legacy way pStartLine = startLine; pEndLine = endLine; String references = ""; references += getReferences(p, pNode, pid); references += getReferences(((ConstDef)p.eContainer().eContainer()).getType(), pNode, pid); references = "\n\t\t<reflist>"+references+"\n\t\t</reflist>"; String xml = "\t" +"<element" +" id=\""+pid+"\"" +" name=\""+pElementName+"\"" +" type=\""+type+"\"" +" startline=\""+pStartLine+"\"" +" endline=\""+pEndLine+"\"" +" module=\""+moduleName+"\"" +" file=\""+fileName+"\"" +option + ">" +references +"\n\t" + "</element>" + "\n\n" ; output.getOutput().add(xml); } } else if (type.equals("External Constant")) { EList<NamedObject> ids = ((ExtConstDef)d.getDef()).getId().getIds(); String option = ""; if (ids.size() > 1) { option = " conflicted=\"true\""; } for (NamedObject p : ids) { String pElementName = p.getName(); String pid = moduleName+"-"+pElementName; INode pNode = NodeModelUtils.getNode(p); int pStartLine = pNode.getStartLine(); int pEndLine = pNode.getTotalEndLine(); //less precise, legacy way pStartLine = startLine; pEndLine = endLine; String references = ""; references += getReferences(((ExtConstDef)p.eContainer().eContainer()).getType(), pNode, pid); references = "\n\t\t<reflist>"+references+"\n\t\t</reflist>"; String xml = "\t" +"<element" +" id=\""+pid+"\"" +" name=\""+pElementName+"\"" +" type=\""+type+"\"" +" startline=\""+pStartLine+"\"" +" endline=\""+pEndLine+"\"" +" module=\""+moduleName+"\"" +" file=\""+fileName+"\"" +option + ">" +references +"\n\t" + "</element>" + "\n\n" ; output.getOutput().add(xml); } } else { String option = ""; String content = ""; String references = ""; if (type.equals("Group")) { content = getContent(d, node, moduleName); content = "\n\t\t<elementlist>"+content+"\n\t\t</elementlist>"; } else { references = getReferences(d, node, id); references = "\n\t\t<reflist>"+references+"\n\t\t</reflist>"; } String xml = "\t" +"<element" +" id=\""+id+"\"" +" name=\""+elementName+"\"" +" type=\""+type+"\"" +" startline=\""+startLine+"\"" +" endline=\""+endLine+"\"" +" module=\""+moduleName+"\"" +" file=\""+fileName+"\"" +option + ">" +content +references +"\n\t" + "</element>" + "\n\n" ; output.getOutput().add(xml); } } else { //handle / skip if (!(d.getDef() instanceof ImportDef)) { String message = "analyze: Element type ("+d.getDef().getClass().getName()+") not supported yet!"; logger.logFix(this.resource.getURI(), node.getStartLine(), node.getEndLine(), MessageClass.UNIVERSAL, message); } } } } // TODO: make this configurable for debug purposes if (printUnresolvedObjects) { for (Diagnostic d : this.resource.getErrors()) { TTCN3StatisticsProvider.getInstance().incrementCountUniversal(); logger.logInformation(this.resource.getURI(), d.getLine(), d.getLine(), MessageClass.UNIVERSAL, d.getMessage()); } for (Diagnostic d : this.resource.getWarnings()) { TTCN3StatisticsProvider.getInstance().incrementCountUniversal(); logger.logInformation(this.resource.getURI(), d.getLine(), d.getLine(), MessageClass.UNIVERSAL, d.getMessage()); } } stopwatch.stop(); System.out.println("Analyzing file: " + this.resource.getURI().devicePath().replaceFirst("///", "") + '\n' + " ...done in " + stopwatch.elapsed(TimeUnit.MILLISECONDS) + " ms (" + MiscTools.secondsToString(stopwatch.elapsed(TimeUnit.SECONDS)) + " minutes)."); return output; } private String getContent(ModuleDefinition d, INode node, String moduleName) { String content = ""; if (((GroupDef) d.getDef()).getList()!=null) { for (ModuleDefinition gd : ((GroupDef) d.getDef()).getList().getDefinitions()) { if (gd.getDef() instanceof ConstDef) { List<SingleConstDef> constants = EcoreUtil2.getAllContentsOfType(gd, SingleConstDef.class); for (SingleConstDef p : constants) { String pElementName = p.getName(); String pid = moduleName+"-"+pElementName; content += "\n\t\t\t" +"<ref" +" id=\""+pid+"\"" +"/>" ; } } else if (gd.getDef() instanceof ModuleParDef) { List<ModuleParameter> parameters = EcoreUtil2.getAllContentsOfType(gd, ModuleParameter.class); for (ModuleParameter p : parameters) { String pElementName = p.getName(); String pid = moduleName+"-"+pElementName; content += "\n\t\t\t" +"<ref" +" id=\""+pid+"\"" +"/>" ; } } else if (gd.getDef() instanceof ExtConstDef) { EList<NamedObject> ids = ((ExtConstDef)gd.getDef()).getId().getIds(); for (NamedObject ec : ids) { String pElementName = ec.getName(); String pid = moduleName+"-"+pElementName; content += "\n\t\t\t" +"<ref" +" id=\""+pid+"\"" +"/>" ; } } else { String gElementName = getModuleDefinitionName(gd); if (gElementName!=null) { String rid = moduleName+"-"+gElementName; content += "\n\t\t\t" +"<ref" +" id=\""+rid+"\"" +"/>" ; } else { String message = "getContent: Element ("+gd+") not supported yet!"; logger.logFix(this.resource.getURI(), node.getStartLine(), node.getEndLine(), MessageClass.UNIVERSAL, message); } } } } return content; } private String getReferences(EObject d, INode node, String id) { String references = ""; HashSet<String> rids = new HashSet<>(); Map<EObject, Collection<Setting>> crossReferences = EcoreUtil.CrossReferencer.find(Lists.newArrayList(d)); //TODO: this may be slow TreeMap<Integer, EObject> offsetCrossReferences = new TreeMap<>(); for (EObject o : crossReferences.keySet()) { int offset = NodeModelUtils.getNode(crossReferences.get(o).iterator().next().getEObject()).getOffset(); offsetCrossReferences.put(offset, o); } for (EObject o : offsetCrossReferences.values()) { TTCN3Module rModule = EcoreUtil2.getContainerOfType(o, TTCN3Module.class); if (rModule == null) { EObject sObject = crossReferences.get(o).iterator().next().getEObject(); String rName = getSObjectName(sObject); String rid = "unresolvedReference---"+rName.trim(); if (!rids.contains(rid)) { rids.add(rid); references += "\n\t\t\t" +"<ref" +" id=\""+rid+"\"" +"/>" ; String message = "getReferences: Element ("+o+") cannot be resolved! ("+sObject+")" ; logger.logFix(this.resource.getURI(), node.getStartLine(), node.getEndLine(), MessageClass.UNIVERSAL, message); } } else { String rModuleName = rModule.getName(); String rName = getReferencedDefinitionName(o); if (rName!=null) { String rid = rModuleName+"-"+rName; if (!rid.equals(id)) { if (!rids.contains(rid)) { rids.add(rid); references += "\n\t\t\t" +"<ref" +" id=\""+rid+"\"" +"/>" ; } } } else { // String sName = getSObjectName(o); // ModuleDefinition container = EcoreUtil2.getContainerOfType(o, ModuleDefinition.class); // if (o instanceof Enumeration) { // sName = ((Enumeration)o).getName(); // String rid = "unresolvedReference---"+sName.trim(); // references += "\n\t\t\t" // +"<ref" // +" id=\""+rid+"\"" // +"/>" // ; // } else { String message = "getReferences: Element ("+o+") not supported yet!"; logger.logFix(this.resource.getURI(), node.getStartLine(), node.getEndLine(), MessageClass.UNIVERSAL, message); // } } } } return references; } private String getSObjectName(EObject sObject) { String name = NodeModelUtils.getNode(sObject).getText().trim(); for (INode c : NodeModelUtils.getNode(sObject).getChildren()) { if (c.getGrammarElement() instanceof CrossReference) { name = c.getText().trim(); } } name = name.replaceAll("//.+\\s*\n\\s+", ""); // name = name.replaceAll("/\\*.+\\s*\n\\s+", ""); name = name.replaceAll("runs on ", ""); name = name.replaceAll("system ", ""); name = name.replaceAll("([\\d\\w_]+).*", "$1"); name = name.replaceAll("^\\.", ""); return name; } @Override public TTCN3Dependency call() throws Exception { return analyze(); } private String getModuleDefinitionName(ModuleDefinition d) { String name = null; String eClassName = d.getDef().eClass().getName(); switch (eClassName) { case "FunctionDef": name = ((FunctionDef)d.getDef()).getName(); break; case "ExtFunctionDef": name = ((ExtFunctionDef)d.getDef()).getName(); break; case "TemplateDef": name = ((TemplateDef)d.getDef()).getBase().getName(); break; case "TypeDef": TypeDefBody body = ((TypeDef)d.getDef()).getBody(); if (body.getStructured()!=null) { if (body.getStructured().getComponent()!=null) { name = body.getStructured().getComponent().getName(); } else if (body.getStructured().getPort()!=null) { name = body.getStructured().getPort().getName(); } else if (body.getStructured().getRecord()!=null) { if (body.getStructured().getRecord() instanceof RecordDefNamed) { name = ((RecordDefNamed)body.getStructured().getRecord()).getName(); } } else if (body.getStructured().getRecordOf()!=null) { if (body.getStructured().getRecordOf() instanceof RecordOfDefNamed) { name = ((RecordOfDefNamed)body.getStructured().getRecordOf()).getName(); } } else if (body.getStructured().getSet()!=null) { if (body.getStructured().getSet() instanceof SetDefNamed) { name = ((SetDefNamed)body.getStructured().getSet()).getName(); } } else if (body.getStructured().getSetOf()!=null) { if (body.getStructured().getSetOf() instanceof SetOfDefNamed) { name = ((SetOfDefNamed)body.getStructured().getSetOf()).getName(); } } else if (body.getStructured().getEnumDef()!=null) { if (body.getStructured().getEnumDef() instanceof EnumDefNamed) { name = ((EnumDefNamed)body.getStructured().getEnumDef()).getName(); } } else if (body.getStructured().getUnion()!=null) { if (body.getStructured().getUnion() instanceof UnionDefNamed) { name = ((UnionDefNamed)body.getStructured().getUnion()).getName(); } } } else { if (body.getSub() instanceof SubTypeDefNamed) { name = ((SubTypeDefNamed)body.getSub()).getName(); } } break; case "AltstepDef": name = ((AltstepDef)d.getDef()).getName(); break; case "TestcaseDef": name = ((TestcaseDef)d.getDef()).getName(); break; case "SignatureDef": name = ((SignatureDef)d.getDef()).getName(); break; case "ModuleParDef": //TODO: handle when multiple are defined? if (((ModuleParDef)d.getDef()).getParam()!=null) { name = ((ModuleParDef)d.getDef()).getParam().getList().getParams().get(0).getName(); } else if (((ModuleParDef)d.getDef()).getMultitypeParam()!=null && !((ModuleParDef)d.getDef()).getMultitypeParam().getParams().isEmpty()) { name = ((ModuleParDef)d.getDef()).getMultitypeParam().getParams().get(0).getList().getParams().get(0).getName(); } else { //empty module parameter? -> skip } break; case "GroupDef": name = ((GroupDef)d.getDef()).getName(); break; case "ConstDef": //TODO: handle when multiple are defined? name = ((ConstDef)d.getDef()).getDefs().getList().get(0).getName(); break; case "ExtConstDef": //TODO: handle when multiple are defined? name = ((ExtConstDef)d.getDef()).getId().getIds().get(0).getName(); break; default: String message = "getModuleDefinitionName: Element type ("+eClassName+") not supported yet!"; ICompositeNode node = NodeModelUtils.getNode(d); logger.logFix(this.resource.getURI(), node.getStartLine(), node.getEndLine(), MessageClass.UNIVERSAL, message); break; } return name; } private String getReferencedDefinitionName(EObject d) { String name = null; String eClassName = d.eClass().getName(); switch (eClassName) { case "FunctionDef": name = ((FunctionDef)d).getName(); break; case "ExtFunctionDef": name = ((ExtFunctionDef)d).getName(); break; case "NamedObject": name = ((NamedObject)d).getName(); break; case "BaseTemplate": name = ((BaseTemplate)d).getName(); break; case "TemplateDef": name = ((TemplateDef)d).getBase().getName(); break; case "ComponentDef": name = ((ComponentDef)d).getName(); break; case "PortDef": name = ((PortDef)d).getName(); break; case "RecordDefNamed": name = ((RecordDefNamed)d).getName(); break; case "RecordOfDefNamed": name = ((RecordOfDefNamed)d).getName(); break; case "SetDefNamed": name = ((SetDefNamed)d).getName(); break; case "SetOfDefNamed": name = ((SetOfDefNamed)d).getName(); break; case "UnionDefNamed": name = ((UnionDefNamed)d).getName(); break; case "EnumDefNamed": name = ((EnumDefNamed)d).getName(); break; // case "Enumeration": // name = ((Enumeration)d).getName(); // break; case "SubTypeDefNamed": name = ((SubTypeDefNamed)d).getName(); break; case "AltstepDef": name = ((AltstepDef)d).getName(); break; case "TestcaseDef": name = ((TestcaseDef)d).getName(); break; case "SignatureDef": name = ((SignatureDef)d).getName(); break; case "SingleConstDef": if (d.eContainer().eContainer().eContainer() instanceof ModuleDefinition) { name = ((SingleConstDef)d).getName(); } break; case "ModuleParameter": name = ((ModuleParameter)d).getName(); break; case "SingleVarInstance": break; default: String message = "getReferencedDefinitionName: Element type ("+eClassName+") not supported yet!"; ICompositeNode node = NodeModelUtils.getNode(d); logger.logFix(this.resource.getURI(), node.getStartLine(), node.getEndLine(), MessageClass.UNIVERSAL, message); break; } return name; } } Loading
de.ugoe.cs.swe.T3Q/src/de/ugoe/cs/swe/T3Q/DependencyAnalyzer.java 0 → 100644 +621 −0 Original line number Diff line number Diff line package de.ugoe.cs.swe.T3Q; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature.Setting; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.Resource.Diagnostic; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.xtext.CrossReference; import org.eclipse.xtext.EcoreUtil2; import org.eclipse.xtext.nodemodel.ICompositeNode; import org.eclipse.xtext.nodemodel.INode; import org.eclipse.xtext.nodemodel.util.NodeModelUtils; import com.google.common.base.Stopwatch; import com.google.common.collect.Lists; import de.ugoe.cs.swe.common.MiscTools; import de.ugoe.cs.swe.common.logging.LoggingInterface; import de.ugoe.cs.swe.common.logging.LoggingInterface.MessageClass; import de.ugoe.cs.swe.tTCN3.AltstepDef; import de.ugoe.cs.swe.tTCN3.BaseTemplate; import de.ugoe.cs.swe.tTCN3.ComponentDef; import de.ugoe.cs.swe.tTCN3.ConstDef; import de.ugoe.cs.swe.tTCN3.EnumDefNamed; import de.ugoe.cs.swe.tTCN3.ExtConstDef; import de.ugoe.cs.swe.tTCN3.ExtFunctionDef; import de.ugoe.cs.swe.tTCN3.FunctionDef; import de.ugoe.cs.swe.tTCN3.GroupDef; import de.ugoe.cs.swe.tTCN3.ImportDef; import de.ugoe.cs.swe.tTCN3.ModuleDefinition; import de.ugoe.cs.swe.tTCN3.ModulePar; import de.ugoe.cs.swe.tTCN3.ModuleParDef; import de.ugoe.cs.swe.tTCN3.ModuleParameter; import de.ugoe.cs.swe.tTCN3.NamedObject; import de.ugoe.cs.swe.tTCN3.PortDef; import de.ugoe.cs.swe.tTCN3.RecordDefNamed; import de.ugoe.cs.swe.tTCN3.RecordOfDefNamed; import de.ugoe.cs.swe.tTCN3.SetDefNamed; import de.ugoe.cs.swe.tTCN3.SetOfDefNamed; import de.ugoe.cs.swe.tTCN3.SignatureDef; import de.ugoe.cs.swe.tTCN3.SingleConstDef; import de.ugoe.cs.swe.tTCN3.SubTypeDefNamed; import de.ugoe.cs.swe.tTCN3.TTCN3File; import de.ugoe.cs.swe.tTCN3.TTCN3Module; import de.ugoe.cs.swe.tTCN3.TemplateDef; import de.ugoe.cs.swe.tTCN3.TestcaseDef; import de.ugoe.cs.swe.tTCN3.TypeDef; import de.ugoe.cs.swe.tTCN3.TypeDefBody; import de.ugoe.cs.swe.tTCN3.UnionDefNamed; import de.ugoe.cs.swe.validation.TTCN3StatisticsProvider; public class DependencyAnalyzer implements Callable<TTCN3Dependency> { private final Resource resource; private final LoggingInterface logger; public static boolean printUnresolvedObjects = false; private final LinkedHashMap<String,String> types = new LinkedHashMap<String, String>(); public DependencyAnalyzer(Resource resource, LoggingInterface logger) { this.resource = resource; this.logger = logger; types.put("TypeDef", "Type"); types.put("ComponentDef", "Type"); types.put("PortDef", "Type"); types.put("TemplateDef", "Template"); types.put("FunctionDef", "Function"); types.put("AltstepDef", "Altstep"); types.put("TestcaseDef", "Testcase"); types.put("ConstDef", "Constant"); types.put("ExtConstDef", "External Constant"); types.put("ExtFunctionDef", "External Function"); types.put("ModuleParDef", "Module Parameter"); types.put("SignatureDef", "Signature"); types.put("GroupDef", "Group"); } private TTCN3Dependency analyze() { final TTCN3Dependency output = new TTCN3Dependency(this.resource); final Stopwatch stopwatch = Stopwatch.createUnstarted(); stopwatch.start(); EcoreUtil.resolveAll(this.resource); EObject model = this.resource.getContents().get(0); for (TTCN3Module module : ((TTCN3File)model).getModules()) { List<ModuleDefinition> definitions = EcoreUtil2.getAllContentsOfType(module, ModuleDefinition.class); for (ModuleDefinition d : definitions) { INode node = NodeModelUtils.getNode(d); String moduleName = module.getName(); String elementName = getModuleDefinitionName(d); String id = moduleName+"-"+elementName; String type = types.get(d.getDef().eClass().getName()); String fileName = this.resource.getURI().segment(this.resource.getURI().segmentCount()-1); int startLine = node.getStartLine(); int endLine = node.getTotalEndLine(); if (type != null && elementName != null) { if (type.equals("Module Parameter")) { List<ModuleParameter> parameters = EcoreUtil2.getAllContentsOfType(d, ModuleParameter.class); String option = ""; if (parameters.size() > 1) { option = " conflicted=\"true\""; } for (ModuleParameter p : parameters) { String pElementName = p.getName(); String pid = moduleName+"-"+pElementName; INode pNode = NodeModelUtils.getNode(p); int pStartLine = pNode.getStartLine(); int pEndLine = pNode.getTotalEndLine(); //less precise, legacy way pStartLine = startLine; pEndLine = endLine; String references = ""; references += getReferences(p, pNode, pid); references += getReferences(((ModulePar)p.eContainer().eContainer()).getType(), pNode, pid); references = "\n\t\t<reflist>"+references+"\n\t\t</reflist>"; String xml = "\t" +"<element" +" id=\""+pid+"\"" +" name=\""+pElementName+"\"" +" type=\""+type+"\"" +" startline=\""+pStartLine+"\"" +" endline=\""+pEndLine+"\"" +" module=\""+moduleName+"\"" +" file=\""+fileName+"\"" +option + ">" +references +"\n\t" + "</element>" + "\n\n" ; output.getOutput().add(xml); } } else if (type.equals("Constant")) { List<SingleConstDef> constants = EcoreUtil2.getAllContentsOfType(d, SingleConstDef.class); String option = ""; if (constants.size() > 1) { option = " conflicted=\"true\""; } for (SingleConstDef p : constants) { String pElementName = p.getName(); String pid = moduleName+"-"+pElementName; INode pNode = NodeModelUtils.getNode(p); int pStartLine = pNode.getStartLine(); int pEndLine = pNode.getTotalEndLine(); //less precise, legacy way pStartLine = startLine; pEndLine = endLine; String references = ""; references += getReferences(p, pNode, pid); references += getReferences(((ConstDef)p.eContainer().eContainer()).getType(), pNode, pid); references = "\n\t\t<reflist>"+references+"\n\t\t</reflist>"; String xml = "\t" +"<element" +" id=\""+pid+"\"" +" name=\""+pElementName+"\"" +" type=\""+type+"\"" +" startline=\""+pStartLine+"\"" +" endline=\""+pEndLine+"\"" +" module=\""+moduleName+"\"" +" file=\""+fileName+"\"" +option + ">" +references +"\n\t" + "</element>" + "\n\n" ; output.getOutput().add(xml); } } else if (type.equals("External Constant")) { EList<NamedObject> ids = ((ExtConstDef)d.getDef()).getId().getIds(); String option = ""; if (ids.size() > 1) { option = " conflicted=\"true\""; } for (NamedObject p : ids) { String pElementName = p.getName(); String pid = moduleName+"-"+pElementName; INode pNode = NodeModelUtils.getNode(p); int pStartLine = pNode.getStartLine(); int pEndLine = pNode.getTotalEndLine(); //less precise, legacy way pStartLine = startLine; pEndLine = endLine; String references = ""; references += getReferences(((ExtConstDef)p.eContainer().eContainer()).getType(), pNode, pid); references = "\n\t\t<reflist>"+references+"\n\t\t</reflist>"; String xml = "\t" +"<element" +" id=\""+pid+"\"" +" name=\""+pElementName+"\"" +" type=\""+type+"\"" +" startline=\""+pStartLine+"\"" +" endline=\""+pEndLine+"\"" +" module=\""+moduleName+"\"" +" file=\""+fileName+"\"" +option + ">" +references +"\n\t" + "</element>" + "\n\n" ; output.getOutput().add(xml); } } else { String option = ""; String content = ""; String references = ""; if (type.equals("Group")) { content = getContent(d, node, moduleName); content = "\n\t\t<elementlist>"+content+"\n\t\t</elementlist>"; } else { references = getReferences(d, node, id); references = "\n\t\t<reflist>"+references+"\n\t\t</reflist>"; } String xml = "\t" +"<element" +" id=\""+id+"\"" +" name=\""+elementName+"\"" +" type=\""+type+"\"" +" startline=\""+startLine+"\"" +" endline=\""+endLine+"\"" +" module=\""+moduleName+"\"" +" file=\""+fileName+"\"" +option + ">" +content +references +"\n\t" + "</element>" + "\n\n" ; output.getOutput().add(xml); } } else { //handle / skip if (!(d.getDef() instanceof ImportDef)) { String message = "analyze: Element type ("+d.getDef().getClass().getName()+") not supported yet!"; logger.logFix(this.resource.getURI(), node.getStartLine(), node.getEndLine(), MessageClass.UNIVERSAL, message); } } } } // TODO: make this configurable for debug purposes if (printUnresolvedObjects) { for (Diagnostic d : this.resource.getErrors()) { TTCN3StatisticsProvider.getInstance().incrementCountUniversal(); logger.logInformation(this.resource.getURI(), d.getLine(), d.getLine(), MessageClass.UNIVERSAL, d.getMessage()); } for (Diagnostic d : this.resource.getWarnings()) { TTCN3StatisticsProvider.getInstance().incrementCountUniversal(); logger.logInformation(this.resource.getURI(), d.getLine(), d.getLine(), MessageClass.UNIVERSAL, d.getMessage()); } } stopwatch.stop(); System.out.println("Analyzing file: " + this.resource.getURI().devicePath().replaceFirst("///", "") + '\n' + " ...done in " + stopwatch.elapsed(TimeUnit.MILLISECONDS) + " ms (" + MiscTools.secondsToString(stopwatch.elapsed(TimeUnit.SECONDS)) + " minutes)."); return output; } private String getContent(ModuleDefinition d, INode node, String moduleName) { String content = ""; if (((GroupDef) d.getDef()).getList()!=null) { for (ModuleDefinition gd : ((GroupDef) d.getDef()).getList().getDefinitions()) { if (gd.getDef() instanceof ConstDef) { List<SingleConstDef> constants = EcoreUtil2.getAllContentsOfType(gd, SingleConstDef.class); for (SingleConstDef p : constants) { String pElementName = p.getName(); String pid = moduleName+"-"+pElementName; content += "\n\t\t\t" +"<ref" +" id=\""+pid+"\"" +"/>" ; } } else if (gd.getDef() instanceof ModuleParDef) { List<ModuleParameter> parameters = EcoreUtil2.getAllContentsOfType(gd, ModuleParameter.class); for (ModuleParameter p : parameters) { String pElementName = p.getName(); String pid = moduleName+"-"+pElementName; content += "\n\t\t\t" +"<ref" +" id=\""+pid+"\"" +"/>" ; } } else if (gd.getDef() instanceof ExtConstDef) { EList<NamedObject> ids = ((ExtConstDef)gd.getDef()).getId().getIds(); for (NamedObject ec : ids) { String pElementName = ec.getName(); String pid = moduleName+"-"+pElementName; content += "\n\t\t\t" +"<ref" +" id=\""+pid+"\"" +"/>" ; } } else { String gElementName = getModuleDefinitionName(gd); if (gElementName!=null) { String rid = moduleName+"-"+gElementName; content += "\n\t\t\t" +"<ref" +" id=\""+rid+"\"" +"/>" ; } else { String message = "getContent: Element ("+gd+") not supported yet!"; logger.logFix(this.resource.getURI(), node.getStartLine(), node.getEndLine(), MessageClass.UNIVERSAL, message); } } } } return content; } private String getReferences(EObject d, INode node, String id) { String references = ""; HashSet<String> rids = new HashSet<>(); Map<EObject, Collection<Setting>> crossReferences = EcoreUtil.CrossReferencer.find(Lists.newArrayList(d)); //TODO: this may be slow TreeMap<Integer, EObject> offsetCrossReferences = new TreeMap<>(); for (EObject o : crossReferences.keySet()) { int offset = NodeModelUtils.getNode(crossReferences.get(o).iterator().next().getEObject()).getOffset(); offsetCrossReferences.put(offset, o); } for (EObject o : offsetCrossReferences.values()) { TTCN3Module rModule = EcoreUtil2.getContainerOfType(o, TTCN3Module.class); if (rModule == null) { EObject sObject = crossReferences.get(o).iterator().next().getEObject(); String rName = getSObjectName(sObject); String rid = "unresolvedReference---"+rName.trim(); if (!rids.contains(rid)) { rids.add(rid); references += "\n\t\t\t" +"<ref" +" id=\""+rid+"\"" +"/>" ; String message = "getReferences: Element ("+o+") cannot be resolved! ("+sObject+")" ; logger.logFix(this.resource.getURI(), node.getStartLine(), node.getEndLine(), MessageClass.UNIVERSAL, message); } } else { String rModuleName = rModule.getName(); String rName = getReferencedDefinitionName(o); if (rName!=null) { String rid = rModuleName+"-"+rName; if (!rid.equals(id)) { if (!rids.contains(rid)) { rids.add(rid); references += "\n\t\t\t" +"<ref" +" id=\""+rid+"\"" +"/>" ; } } } else { // String sName = getSObjectName(o); // ModuleDefinition container = EcoreUtil2.getContainerOfType(o, ModuleDefinition.class); // if (o instanceof Enumeration) { // sName = ((Enumeration)o).getName(); // String rid = "unresolvedReference---"+sName.trim(); // references += "\n\t\t\t" // +"<ref" // +" id=\""+rid+"\"" // +"/>" // ; // } else { String message = "getReferences: Element ("+o+") not supported yet!"; logger.logFix(this.resource.getURI(), node.getStartLine(), node.getEndLine(), MessageClass.UNIVERSAL, message); // } } } } return references; } private String getSObjectName(EObject sObject) { String name = NodeModelUtils.getNode(sObject).getText().trim(); for (INode c : NodeModelUtils.getNode(sObject).getChildren()) { if (c.getGrammarElement() instanceof CrossReference) { name = c.getText().trim(); } } name = name.replaceAll("//.+\\s*\n\\s+", ""); // name = name.replaceAll("/\\*.+\\s*\n\\s+", ""); name = name.replaceAll("runs on ", ""); name = name.replaceAll("system ", ""); name = name.replaceAll("([\\d\\w_]+).*", "$1"); name = name.replaceAll("^\\.", ""); return name; } @Override public TTCN3Dependency call() throws Exception { return analyze(); } private String getModuleDefinitionName(ModuleDefinition d) { String name = null; String eClassName = d.getDef().eClass().getName(); switch (eClassName) { case "FunctionDef": name = ((FunctionDef)d.getDef()).getName(); break; case "ExtFunctionDef": name = ((ExtFunctionDef)d.getDef()).getName(); break; case "TemplateDef": name = ((TemplateDef)d.getDef()).getBase().getName(); break; case "TypeDef": TypeDefBody body = ((TypeDef)d.getDef()).getBody(); if (body.getStructured()!=null) { if (body.getStructured().getComponent()!=null) { name = body.getStructured().getComponent().getName(); } else if (body.getStructured().getPort()!=null) { name = body.getStructured().getPort().getName(); } else if (body.getStructured().getRecord()!=null) { if (body.getStructured().getRecord() instanceof RecordDefNamed) { name = ((RecordDefNamed)body.getStructured().getRecord()).getName(); } } else if (body.getStructured().getRecordOf()!=null) { if (body.getStructured().getRecordOf() instanceof RecordOfDefNamed) { name = ((RecordOfDefNamed)body.getStructured().getRecordOf()).getName(); } } else if (body.getStructured().getSet()!=null) { if (body.getStructured().getSet() instanceof SetDefNamed) { name = ((SetDefNamed)body.getStructured().getSet()).getName(); } } else if (body.getStructured().getSetOf()!=null) { if (body.getStructured().getSetOf() instanceof SetOfDefNamed) { name = ((SetOfDefNamed)body.getStructured().getSetOf()).getName(); } } else if (body.getStructured().getEnumDef()!=null) { if (body.getStructured().getEnumDef() instanceof EnumDefNamed) { name = ((EnumDefNamed)body.getStructured().getEnumDef()).getName(); } } else if (body.getStructured().getUnion()!=null) { if (body.getStructured().getUnion() instanceof UnionDefNamed) { name = ((UnionDefNamed)body.getStructured().getUnion()).getName(); } } } else { if (body.getSub() instanceof SubTypeDefNamed) { name = ((SubTypeDefNamed)body.getSub()).getName(); } } break; case "AltstepDef": name = ((AltstepDef)d.getDef()).getName(); break; case "TestcaseDef": name = ((TestcaseDef)d.getDef()).getName(); break; case "SignatureDef": name = ((SignatureDef)d.getDef()).getName(); break; case "ModuleParDef": //TODO: handle when multiple are defined? if (((ModuleParDef)d.getDef()).getParam()!=null) { name = ((ModuleParDef)d.getDef()).getParam().getList().getParams().get(0).getName(); } else if (((ModuleParDef)d.getDef()).getMultitypeParam()!=null && !((ModuleParDef)d.getDef()).getMultitypeParam().getParams().isEmpty()) { name = ((ModuleParDef)d.getDef()).getMultitypeParam().getParams().get(0).getList().getParams().get(0).getName(); } else { //empty module parameter? -> skip } break; case "GroupDef": name = ((GroupDef)d.getDef()).getName(); break; case "ConstDef": //TODO: handle when multiple are defined? name = ((ConstDef)d.getDef()).getDefs().getList().get(0).getName(); break; case "ExtConstDef": //TODO: handle when multiple are defined? name = ((ExtConstDef)d.getDef()).getId().getIds().get(0).getName(); break; default: String message = "getModuleDefinitionName: Element type ("+eClassName+") not supported yet!"; ICompositeNode node = NodeModelUtils.getNode(d); logger.logFix(this.resource.getURI(), node.getStartLine(), node.getEndLine(), MessageClass.UNIVERSAL, message); break; } return name; } private String getReferencedDefinitionName(EObject d) { String name = null; String eClassName = d.eClass().getName(); switch (eClassName) { case "FunctionDef": name = ((FunctionDef)d).getName(); break; case "ExtFunctionDef": name = ((ExtFunctionDef)d).getName(); break; case "NamedObject": name = ((NamedObject)d).getName(); break; case "BaseTemplate": name = ((BaseTemplate)d).getName(); break; case "TemplateDef": name = ((TemplateDef)d).getBase().getName(); break; case "ComponentDef": name = ((ComponentDef)d).getName(); break; case "PortDef": name = ((PortDef)d).getName(); break; case "RecordDefNamed": name = ((RecordDefNamed)d).getName(); break; case "RecordOfDefNamed": name = ((RecordOfDefNamed)d).getName(); break; case "SetDefNamed": name = ((SetDefNamed)d).getName(); break; case "SetOfDefNamed": name = ((SetOfDefNamed)d).getName(); break; case "UnionDefNamed": name = ((UnionDefNamed)d).getName(); break; case "EnumDefNamed": name = ((EnumDefNamed)d).getName(); break; // case "Enumeration": // name = ((Enumeration)d).getName(); // break; case "SubTypeDefNamed": name = ((SubTypeDefNamed)d).getName(); break; case "AltstepDef": name = ((AltstepDef)d).getName(); break; case "TestcaseDef": name = ((TestcaseDef)d).getName(); break; case "SignatureDef": name = ((SignatureDef)d).getName(); break; case "SingleConstDef": if (d.eContainer().eContainer().eContainer() instanceof ModuleDefinition) { name = ((SingleConstDef)d).getName(); } break; case "ModuleParameter": name = ((ModuleParameter)d).getName(); break; case "SingleVarInstance": break; default: String message = "getReferencedDefinitionName: Element type ("+eClassName+") not supported yet!"; ICompositeNode node = NodeModelUtils.getNode(d); logger.logFix(this.resource.getURI(), node.getStartLine(), node.getEndLine(), MessageClass.UNIVERSAL, message); break; } return name; } }