Skip to content
Snippets Groups Projects
Commit ae5f7be8 authored by Jakub Konvička's avatar Jakub Konvička
Browse files

fix(#24): Fix Activity and Class diagram code parsing

parent 6efc4cd7
Branches
1 merge request!15merge: develop into main
Pipeline #874 failed with stages
in 1 minute and 31 seconds
Showing
with 57 additions and 227 deletions
...@@ -3,4 +3,4 @@ obj/ ...@@ -3,4 +3,4 @@ obj/
/packages/ /packages/
riderModule.iml riderModule.iml
/_ReSharper.Caches/ /_ReSharper.Caches/
.idea .idea/
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoGeneratedRunConfigurationManager">
<projectFile>ConsoleApp1/ConsoleApp1.csproj</projectFile>
</component>
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="38df7b5a-e819-45ed-9bf5-eb7ce2106e88" name="Changes" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="MetaFilesCheckinStateConfiguration" checkMetaFiles="true" />
<component name="ProjectColorInfo"><![CDATA[{
"associatedIndex": 4
}]]></component>
<component name="ProjectId" id="2WL74YsffR7PLpZQhzToFOyb7sj" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectViewState">
<option name="autoscrollFromSource" value="true" />
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"WebServerToolWindowFactoryState": "false",
"git-widget-placeholder": "main",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"settings.editor.selected.configurable": "preferences.pluginManager",
"vue.rearranger.settings.migration": "true"
},
"keyToStringList": {
"rider.external.source.directories": [
"C:\\Users\\root\\AppData\\Roaming\\JetBrains\\Rider2023.2\\resharper-host\\DecompilerCache",
"C:\\Users\\root\\AppData\\Roaming\\JetBrains\\Rider2023.2\\resharper-host\\SourcesCache",
"C:\\Users\\root\\AppData\\Local\\Symbols\\src"
]
}
}]]></component>
<component name="RunManager">
<configuration name="ConsoleApp1" type="DotNetProject" factoryName=".NET Project">
<option name="EXE_PATH" value="" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="PASS_PARENT_ENVS" value="1" />
<option name="USE_EXTERNAL_CONSOLE" value="0" />
<option name="USE_MONO" value="0" />
<option name="RUNTIME_ARGUMENTS" value="" />
<option name="PROJECT_PATH" value="$PROJECT_DIR$/ConsoleApp1/ConsoleApp1.csproj" />
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value="" />
<method v="2">
<option name="Build" />
</method>
</configuration>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="38df7b5a-e819-45ed-9bf5-eb7ce2106e88" name="Changes" comment="" />
<created>1696499815256</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1696499815256</updated>
<workItem from="1696499816476" duration="339000" />
</task>
<task id="LOCAL-00001" summary="Add project files">
<option name="closed" value="true" />
<created>1696499974654</created>
<option name="number" value="00001" />
<option name="presentableId" value="LOCAL-00001" />
<option name="project" value="LOCAL" />
<updated>1696499974654</updated>
</task>
<task id="LOCAL-00002" summary="Rename solution">
<option name="closed" value="true" />
<created>1696500005181</created>
<option name="number" value="00002" />
<option name="presentableId" value="LOCAL-00002" />
<option name="project" value="LOCAL" />
<updated>1696500005181</updated>
</task>
<option name="localTasksCounter" value="3" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="UnityCheckinConfiguration" checkUnsavedScenes="true" />
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
</component>
<component name="VcsManagerConfiguration">
<option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="true" />
<MESSAGE value="Add project files" />
<MESSAGE value="Rename solution" />
<option name="LAST_COMMIT_MESSAGE" value="Rename solution" />
<option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="true" />
</component>
</project>
\ No newline at end of file
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/modules.xml
/projectSettingsUpdater.xml
/.idea.CodeParser.iml
/contentModel.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
CodeToXMI
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ANTLRGenerationPreferences">
<option name="perGrammarGenerationSettings">
<list>
<PerGrammarGenerationSettings>
<option name="fileName" value="$PROJECT_DIR$/LanguageRecogniser/Cpp/CPP14Parser.g4" />
<option name="autoGen" value="true" />
<option name="outputDir" value="/gen" />
<option name="libDir" value="" />
<option name="encoding" value="" />
<option name="pkg" value="" />
<option name="language" value="CSharp" />
<option name="generateVisitor" value="true" />
</PerGrammarGenerationSettings>
</list>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
# This is a generated file. Not intended for manual editing.
version: "3"
services:
codeToXMI_dev:
build:
context: "/Users/jakubkonvicka/RiderProjects/diplomathesis"
dockerfile: "./WebAPI/Dockerfile"
target: "base"
command: []
entrypoint:
- "dotnet"
- "/app/bin/Debug/net7.0/WebAPI.dll"
environment:
DOTNET_USE_POLLING_FILE_WATCHER: "true"
image: "webapi:dev"
ports: []
volumes:
- "/Users/jakubkonvicka/.nuget/packages:/root/.nuget/packages"
- "/Users/jakubkonvicka/RiderProjects/diplomathesis/WebAPI:/app:rw"
- "/Users/jakubkonvicka/RiderProjects/diplomathesis:/src:rw"
working_dir: "/app"
...@@ -25,10 +25,10 @@ public class ClassBuilder : IClassBuilder ...@@ -25,10 +25,10 @@ public class ClassBuilder : IClassBuilder
{ {
return new OperationBuilder(_xmiClassDiagramUmlBuilder, _class, name, returnType, visibilityType); return new OperationBuilder(_xmiClassDiagramUmlBuilder, _class, name, returnType, visibilityType);
} }
public IClassBuilder AddAssociation(string? targetClassName, VisibilityType visibilityType, AssociationType associationType) public IClassBuilder AddAssociation(string? targetClassName, string? name, VisibilityType visibilityType, AssociationType associationType)
{ {
_xmiClassDiagramUmlBuilder.AddAssociation(_class, targetClassName, visibilityType, associationType); _xmiClassDiagramUmlBuilder.AddAssociation(_class, targetClassName, name, visibilityType, associationType);
return this; return this;
} }
......
...@@ -30,9 +30,9 @@ public class OperationBuilder : IOperationBuilder ...@@ -30,9 +30,9 @@ public class OperationBuilder : IOperationBuilder
return this; return this;
} }
public IClassBuilder AddAssociation(string? targetClassName, VisibilityType visibilityType, AssociationType associationType) public IClassBuilder AddAssociation(string? targetClassName, string? name, VisibilityType visibilityType, AssociationType associationType)
{ {
_xmiClassDiagramUmlBuilder.AddAssociation(_class, targetClassName, visibilityType, associationType); _xmiClassDiagramUmlBuilder.AddAssociation(_class, targetClassName, name, visibilityType, associationType);
return this; return this;
} }
......
...@@ -6,6 +6,6 @@ public interface IClassBuilder ...@@ -6,6 +6,6 @@ public interface IClassBuilder
{ {
IClassBuilder AddProperty(string? name, VisibilityType visibilityType, PropertyType propertyType); IClassBuilder AddProperty(string? name, VisibilityType visibilityType, PropertyType propertyType);
IOperationBuilder AddOperation(string? name, PropertyType returnType, VisibilityType visibilityType); IOperationBuilder AddOperation(string? name, PropertyType returnType, VisibilityType visibilityType);
IClassBuilder AddAssociation(string? targetClass, VisibilityType visibilityType, AssociationType associationType); IClassBuilder AddAssociation(string? targetClass, string? name, VisibilityType visibilityType, AssociationType associationType);
IClassBuilder AddGeneralization(string? targetClass); IClassBuilder AddGeneralization(string? targetClass);
} }
\ No newline at end of file
...@@ -92,15 +92,15 @@ public class XmiClassDiagramUmlBuilder : DiagramUmlBuilder ...@@ -92,15 +92,15 @@ public class XmiClassDiagramUmlBuilder : DiagramUmlBuilder
return operation; return operation;
} }
public void AddAssociation(XmiElement parent, string? targetClassName, VisibilityType visibilityType, AssociationType associationType) public void AddAssociation(XmiElement parent, string? targetClassName, string? name, VisibilityType visibilityType, AssociationType associationType)
{ {
string? packageName = parent.XmlElement.GetAttribute("xmi:id").Split('-')[0]; string? packageName = parent.XmlElement.GetAttribute("xmi:id").Split('-')[0];
string parentName = parent.XmlElement.GetAttribute("name"); string parentName = parent.XmlElement.GetAttribute("name");
string associationName = $"{packageName}-Association{_nextPackageAssociationId[packageName].ToString()}"; string associationName = $"{packageName}-Association_{{name}}_{_nextPackageAssociationId[packageName].ToString()}";
var association = new Association() var association = new Association()
{ {
Name = $"Association{_nextPackageAssociationId[packageName].ToString()}", Name = $"Association_{name}_{_nextPackageAssociationId[packageName].ToString()}",
Package = packageName, Package = packageName,
Source = new AssociationDetail() Source = new AssociationDetail()
{ {
...@@ -264,7 +264,7 @@ public class XmiClassDiagramUmlBuilder : DiagramUmlBuilder ...@@ -264,7 +264,7 @@ public class XmiClassDiagramUmlBuilder : DiagramUmlBuilder
} }
else else
{ {
throw new ArgumentException($"Target class {association.Target.ClassName} not found"); Console.WriteLine($"Target class {association.Target.ClassName} not found");
} }
} }
} }
......
...@@ -10,11 +10,16 @@ public class CppActivityDiagramVisitor : CPP14ParserBaseVisitor<object> ...@@ -10,11 +10,16 @@ public class CppActivityDiagramVisitor : CPP14ParserBaseVisitor<object>
private IDiagramBuilder _diagramBuilder { get; set; } private IDiagramBuilder _diagramBuilder { get; set; }
private string functionIdentifier { get; set; } private string functionIdentifier { get; set; }
private Stack<(IDecisionBuilder, Stack<BranchType>)> _decisionBuilderStack { get; set; } = new Stack<(IDecisionBuilder, Stack<BranchType>)>(); private Stack<(IDecisionBuilder, Stack<BranchType>)> _decisionBuilderStack { get; set; } = new Stack<(IDecisionBuilder, Stack<BranchType>)>();
private long decisionUniqueueId { get; set; } = 0;
private string actualContext { get; set; } = string.Empty;
private string contextIdentifier { get; set; } = string.Empty;
public CppActivityDiagramVisitor(IDiagramBuilder diagramBuilder, string functionIdentifier) public CppActivityDiagramVisitor(IDiagramBuilder diagramBuilder, string contextIdentifier, string functionIdentifier)
{ {
_diagramBuilder = diagramBuilder; _diagramBuilder = diagramBuilder;
this.functionIdentifier = functionIdentifier; this.functionIdentifier = functionIdentifier;
this.contextIdentifier = contextIdentifier;
} }
public override object VisitTranslationUnit(CPP14Parser.TranslationUnitContext context) public override object VisitTranslationUnit(CPP14Parser.TranslationUnitContext context)
...@@ -49,16 +54,35 @@ public class CppActivityDiagramVisitor : CPP14ParserBaseVisitor<object> ...@@ -49,16 +54,35 @@ public class CppActivityDiagramVisitor : CPP14ParserBaseVisitor<object>
{ {
Visit(context.namespaceDefinition()); Visit(context.namespaceDefinition());
} }
else if(context.blockDeclaration().simpleDeclaration() != null)
{
VisitChildren(context.blockDeclaration().simpleDeclaration().declSpecifierSeq());
}
return null; return null;
} }
public override string VisitClassSpecifier(CPP14Parser.ClassSpecifierContext context)
{
var className = Visit(context.classHead().classHeadName());
this.actualContext = className as string;
Visit(context.memberSpecification());
this.actualContext = string.Empty;
return string.Empty;
}
public override string VisitClassName(CPP14Parser.ClassNameContext context)
{
return context.Identifier()?.GetText();
}
public override object VisitFunctionDefinition(CPP14Parser.FunctionDefinitionContext context) public override object VisitFunctionDefinition(CPP14Parser.FunctionDefinitionContext context)
{ {
var functionName = context.declarator().pointerDeclarator().noPointerDeclarator().noPointerDeclarator() var functionName = context.declarator().pointerDeclarator().noPointerDeclarator().noPointerDeclarator()
.declaratorid().GetText(); .declaratorid().GetText();
if (this.functionIdentifier == functionName) if (this.functionIdentifier == functionName && this.contextIdentifier == this.actualContext)
{ {
Visit(context.functionBody()); Visit(context.functionBody());
} }
...@@ -175,7 +199,8 @@ public class CppActivityDiagramVisitor : CPP14ParserBaseVisitor<object> ...@@ -175,7 +199,8 @@ public class CppActivityDiagramVisitor : CPP14ParserBaseVisitor<object>
} }
long count = _decisionBuilderStack.Count(); long count = _decisionBuilderStack.Count();
_decisionBuilderStack.Pop().Item1.AddMerge($"merge-{count}"); decisionUniqueueId++;
_decisionBuilderStack.Pop().Item1.AddMerge($"merge-{decisionUniqueueId}");
return null; return null;
} }
......
...@@ -112,31 +112,31 @@ public class CppClassDiagramVisitor : CPP14ParserBaseVisitor<object> ...@@ -112,31 +112,31 @@ public class CppClassDiagramVisitor : CPP14ParserBaseVisitor<object>
else else
{ {
// Regular expressions // Regular expressions
string aggregationPattern = @"^((std::)?vector<(\w*)\*>|(\w*)\*|(\w*)\* (\w*|\[\]))$"; string aggregationPattern = @"^(?:std::)?(?:vector<)?(\w+)\*>?(?![\w*])$";
string compositionPattern = @"^((std::)?vector<(\w*)>|(\w*)|(\w*) (\w*|\[\]))$"; string compositionPattern = @"^(?:std::)?(?:vector<)?(\w+)>?$";
// Check if the property type matches aggregation or composition // Check if the property type matches aggregation or composition
Match aggregationMatch = Regex.Match(atribute.Type, aggregationPattern); Match aggregationMatch = Regex.Match(atribute.Type, aggregationPattern);
Match compositionMatch = Regex.Match(atribute.Type, compositionPattern); Match compositionMatch = Regex.Match(atribute.Type, compositionPattern);
int groupMatch = 1;
if (aggregationMatch.Success && !string.IsNullOrEmpty(aggregationMatch.Groups[3].Value)) if (aggregationMatch.Success && !string.IsNullOrEmpty(aggregationMatch.Groups[groupMatch].Value))
{ {
// Aggregation type // Aggregation type
string? typeName = aggregationMatch.Groups[3].Value; // Second capturing group string? typeName = aggregationMatch.Groups[groupMatch].Value; // Second capturing group
_classes.Last().Value.AddAssociation(typeName, actualAccessSpecifier, _classes.Last().Value.AddAssociation(typeName, atribute.Name, actualAccessSpecifier,
AssociationType.Aggregation); AssociationType.Aggregation);
} }
else if (compositionMatch.Success && !string.IsNullOrEmpty(compositionMatch.Groups[2].Value)) else if (compositionMatch.Success && !string.IsNullOrEmpty(compositionMatch.Groups[groupMatch].Value))
{ {
// Composition type // Composition type
string? typeName = compositionMatch.Groups[3].Value; // Second capturing group string? typeName = compositionMatch.Groups[groupMatch].Value; // Second capturing group
_classes.Last().Value.AddAssociation(typeName, actualAccessSpecifier, _classes.Last().Value.AddAssociation(typeName, atribute.Name, actualAccessSpecifier,
AssociationType.Composition); AssociationType.Composition);
} }
else else
{ {
// Default to regular association if no match is found // Default to regular association if no match is found
_classes.Last().Value.AddAssociation(atribute.Type, actualAccessSpecifier, _classes.Last().Value.AddAssociation(atribute.Type, atribute.Name, actualAccessSpecifier,
AssociationType.Association); AssociationType.Association);
} }
} }
......
...@@ -120,7 +120,7 @@ public class ClassDiagramTests ...@@ -120,7 +120,7 @@ public class ClassDiagramTests
for (int i = 1; i < numberOfClasses; i++) for (int i = 1; i < numberOfClasses; i++)
{ {
package.AddClass($"Class{i}", false) package.AddClass($"Class{i}", false)
.AddAssociation($"Class{i-1}", VisibilityType.Public, AssociationType.Association); .AddAssociation($"Class{i-1}", $"name{i-1}",VisibilityType.Public, AssociationType.Association);
} }
var xmi = ClassDiagramBuilder.BuildDiagram(); var xmi = ClassDiagramBuilder.BuildDiagram();
...@@ -164,11 +164,11 @@ public class ClassDiagramTests ...@@ -164,11 +164,11 @@ public class ClassDiagramTests
{ {
var package1 = ClassDiagramBuilder.AddPackage("Package1"); var package1 = ClassDiagramBuilder.AddPackage("Package1");
package1.AddClass("Class1", false) package1.AddClass("Class1", false)
.AddAssociation("Class2", VisibilityType.Public, AssociationType.Association); .AddAssociation("Class2", "name2",VisibilityType.Public, AssociationType.Association);
var package2 = ClassDiagramBuilder.AddPackage("Package2"); var package2 = ClassDiagramBuilder.AddPackage("Package2");
package2.AddClass("Class2", false) package2.AddClass("Class2", false)
.AddAssociation("Class1", VisibilityType.Public, AssociationType.Aggregation); .AddAssociation("Class1", "name1",VisibilityType.Public, AssociationType.Aggregation);
var xmi = ClassDiagramBuilder.BuildDiagram(); var xmi = ClassDiagramBuilder.BuildDiagram();
AssertCommonAssertions(xmi); AssertCommonAssertions(xmi);
...@@ -202,7 +202,7 @@ public class ClassDiagramTests ...@@ -202,7 +202,7 @@ public class ClassDiagramTests
var class1 = package.AddClass("Class1", false); var class1 = package.AddClass("Class1", false);
var class2 = package.AddClass("Class2", false); var class2 = package.AddClass("Class2", false);
class2.AddAssociation(targetAssociation, visibilityType, type); class2.AddAssociation(targetAssociation, "association",visibilityType, type);
if (!isValid) if (!isValid)
{ {
......
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using Antlr4.Runtime; using Antlr4.Runtime;
using Antlr4.Runtime.Tree; using Antlr4.Runtime.Tree;
...@@ -43,6 +44,8 @@ namespace WebAPI.Controllers ...@@ -43,6 +44,8 @@ namespace WebAPI.Controllers
[Range(1, int.MaxValue, ErrorMessage = "Id must be greater than 0")] [Range(1, int.MaxValue, ErrorMessage = "Id must be greater than 0")]
int sourceCodeId, int sourceCodeId,
string? contextIdentifier,
[Required(ErrorMessage = "FunctionIdentifier is required")] [Required(ErrorMessage = "FunctionIdentifier is required")]
string functionIdentifier) string functionIdentifier)
{ {
...@@ -72,7 +75,7 @@ namespace WebAPI.Controllers ...@@ -72,7 +75,7 @@ namespace WebAPI.Controllers
if (parser.NumberOfSyntaxErrors == 0) if (parser.NumberOfSyntaxErrors == 0)
{ {
CppActivityDiagramVisitor activityDiagramVisitor = new CppActivityDiagramVisitor(diagramBuilder, functionIdentifier); CppActivityDiagramVisitor activityDiagramVisitor = new CppActivityDiagramVisitor(diagramBuilder, contextIdentifier, functionIdentifier);
Console.WriteLine(activityDiagramVisitor.Visit(tree)); Console.WriteLine(activityDiagramVisitor.Visit(tree));
} }
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment