Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
afe9aea
feat[DE]: Add AnnotationSchema
simsimkic Dec 23, 2021
dc51c9e
Resolve merging conflicts
simsimkic Apr 27, 2022
c1e8996
Fix imports
simsimkic Apr 27, 2022
1f77853
feat[DE]: Move files and folders
simsimkic Apr 27, 2022
2af5e69
fix[DE]: Delete blank line
simsimkic Apr 27, 2022
64f692c
feat[DE]: Refactor AnnotationSchema controllers
simsimkic Apr 27, 2022
8350e35
feat[DE]: Remove smell-independent heuristics
simsimkic May 9, 2022
37962ac
feat[DE]: Remove SeverityRange from CodeSmellDefinition
simsimkic May 16, 2022
4e0990a
feat[DE]: Get smells and heuristics from annotation schema
simsimkic May 18, 2022
15dbdba
feat[DE]: Get code smell definition by name
simsimkic May 24, 2022
516b2ab
feat[DE]: Add annotator name
simsimkic May 26, 2022
23cca1d
feat[DE]: Add snippet type to code smell
simsimkic May 27, 2022
097255a
feat[DE]: Return created project
simsimkic May 27, 2022
1ece616
feat[DE]: Delete heuristic after schema update
simsimkic May 31, 2022
f0279fc
feat[DE]: Cascade deletion after code smell definition deletion
simsimkic May 31, 2022
864f8df
feat[DE]: Change severity type; Manage severity in schema
simsimkic Jun 2, 2022
fedfd75
fix[DE]: Delete blank lines
simsimkic Jun 2, 2022
5f786d9
fix[DE]: Fix paths to consistency tests
simsimkic Jun 2, 2022
7bdead4
feat[DE]: Add snippet type to CodeSmellDTO
simsimkic Jun 2, 2022
eeb1bc8
feat[DE]: Get code smell object instead of name
simsimkic Jun 3, 2022
fe5e2b7
fix[DE]: Remove blank line
simsimkic Jun 3, 2022
14574b4
Merge changes from master
simsimkic Jun 30, 2022
e92fde9
feat[DE]: Add graph instances
simsimkic Jun 30, 2022
ab4a3dc
feat[DE]: Independent graph load
simsimkic Jul 3, 2022
769acba
Add RelationType to GraphRelatedInstance
simsimkic Jul 21, 2022
4d3651e
Get graph instance with related instances
simsimkic Jul 21, 2022
2b8cb4f
refactor[DE]: Renaming
simsimkic Jul 21, 2022
66ffa09
feat[DE]: Add link to GraphRelatedInstance
simsimkic Aug 1, 2022
5d28af3
fix[DE]: Fix dataset export - get heuristics from schema
simsimkic Aug 22, 2022
33cf2f5
feat[DE]: Add relation type: class to which the method belongs
simsimkic Aug 23, 2022
b6623c5
feat[DE]: Add subclass in related instances
simsimkic Aug 24, 2022
e1409b0
fix[DE]: Fix string comparison
simsimkic Aug 26, 2022
7087b9f
feat[DE]: Add annotator registration
simsimkic Aug 31, 2022
cad2a00
refactor[DE]: Delete unused methods
simsimkic Aug 31, 2022
4960d5f
feat[DE]: Add annotator update methods
simsimkic Aug 31, 2022
04b8ada
fix[DE]: Fix dataset export
simsimkic Sep 6, 2022
58038b2
feat[DE]: Export complete dataset
simsimkic Sep 7, 2022
4048829
feat[DE]: Add clean code analysis export - clean names
simsimkic Feb 23, 2023
1d27d50
feat[DE]: Add clean code analysis export - clean functions/classes
simsimkic Feb 23, 2023
3577370
feat[DE]: Add conditional formatting
simsimkic Feb 25, 2023
f1462d4
Remove contructors from clean names analysis
simsimkic Mar 25, 2023
663d4fe
Replace members with properties and methods (for clean names analysis)
simsimkic Mar 25, 2023
ed164d2
Group same identifiers and count occurrence (for clean names analysis)
simsimkic Mar 25, 2023
f692235
Analyze params and vars from methods instead of members (clean names …
simsimkic Mar 25, 2023
89a730f
Add additional metrics and remove constructors (clean functions analy…
simsimkic Mar 25, 2023
c9408de
feat: Enables CSharpCodeParser to process partial classes.
Luburic Jan 31, 2024
8c788fa
fix: Minor tweak to CodeModelFactory constructor.
Luburic Jan 31, 2024
ece90b7
Merge branch 'feature/annotation-schema' of https://github.com/Clean-…
Luburic Feb 1, 2024
627410c
fix: Resolves partial issue.
Luburic Feb 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions CodeModel.Tests/Integration/CodeModelFactoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ public void Create_code_model_with_links(string folderLocation)
difference.ShouldBeEmpty();
}

[Fact]
public void Create_code_model_with_links_with_partial_classes()
{
CodeModelFactory factory = new CodeModelFactory(true);
var project = factory.CreateProjectWithCodeFileLinks("C:/sdataset-partial");

var projectClassesAndMembersCount = project.Classes.Count + project.Classes.Sum(c => c.Members.Count);

project.CodeLinks.Count.ShouldBe(projectClassesAndMembersCount);
}

[Fact]
public void Create_code_model_with_links_on_large_repo()
{
Expand All @@ -93,5 +104,27 @@ public void Create_code_model_with_links_on_large_repo()
locationLink.StartLoC.ShouldBe(15);
locationLink.EndLoC.ShouldBe(16);
}

[Theory]
//[InlineData("C:\\temp\\challenge-sandbox\\start\\01. Structural Cohesion")]
//[InlineData("C:\\temp\\challenge-sandbox\\end\\01. structural")]
//[InlineData("C:\\temp\\challenge-sandbox\\start\\03. Coupling\\Employees")]
//[InlineData("C:\\temp\\challenge-sandbox\\end\\03. coupling employee")]
//[InlineData("C:\\temp\\challenge-sandbox\\start\\03. Coupling\\Rental")]
//[InlineData("C:\\temp\\challenge-sandbox\\end\\03. coupling rental")]
//[InlineData("C:\\temp\\challenge-sandbox\\start\\04. SRP\\Achievements")]
//[InlineData("C:\\temp\\challenge-sandbox\\end\\04. srp achievements")]
[InlineData("C:\\temp\\challenge-sandbox\\start\\04. SRP\\Books")]
[InlineData("C:\\temp\\challenge-sandbox\\end\\04. srp books")]
public void Create_code_model(string folderLocation)
{
CodeModelFactory factory = new CodeModelFactory();
var project = factory.CreateProjectWithCodeFileLinks(folderLocation);

var classes = project.Classes;
var members = project.Classes.SelectMany(c => c.Members);

var firstClassMetrics = classes.First().Metrics;
}
}
}
1 change: 1 addition & 0 deletions CodeModel/CaDETModel/CodeItems/CaDETClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public string ContainerName
public List<CaDETMember> Members { get; internal set; }
public List<CaDETField> Fields { get; internal set; }
public Dictionary<CaDETMetric, double> Metrics { get; set; }
public List<CaDETClass> Subclasses { get; set; }

public CaDETClass(string name)
{
Expand Down
5 changes: 2 additions & 3 deletions CodeModel/CaDETModel/CodeItems/CaDETModifier.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using CodeModel.CodeParsers.CSharp.Exceptions;
using System.ComponentModel;
using System.ComponentModel;

namespace CodeModel.CaDETModel.CodeItems
{
Expand Down Expand Up @@ -27,7 +26,7 @@ public CaDETModifier(string modifier)
"const" => CaDETModifierValue.Const,
"async" => CaDETModifierValue.Async,
"volatile" => CaDETModifierValue.Volatile,
"partial" => throw new PartialIsNotSupportedException(),
"partial" => CaDETModifierValue.Partial,
_ => throw new InvalidEnumArgumentException(modifier)
};
}
Expand Down
1 change: 1 addition & 0 deletions CodeModel/CodeModel.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<RepositoryUrl>https://github.com/Clean-CaDET/platform/tree/master/CodeModel</RepositoryUrl>
<PackageLicenseExpression>GPL-3.0-or-later</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<Version>1.0.3</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion CodeModel/CodeModelCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public CaDETProject GetOrCreate(string repoAndCommitUrl, string repoFolder, Lang
{
if (_cache.TryGetValue(repoAndCommitUrl, out CaDETProject cacheEntry)) return cacheEntry;

cacheEntry = new CodeModelFactory(language).CreateProjectWithCodeFileLinks(repoFolder);
cacheEntry = new CodeModelFactory(false, language).CreateProjectWithCodeFileLinks(repoFolder);

var cacheEntryOptions = new MemoryCacheEntryOptions
{
Expand Down
6 changes: 4 additions & 2 deletions CodeModel/CodeModelFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@ namespace CodeModel
public class CodeModelFactory
{
private readonly LanguageEnum _language;
private readonly bool _includePartial;

public CodeModelFactory(LanguageEnum language = LanguageEnum.CSharp)
public CodeModelFactory(bool includePartial = false, LanguageEnum language = LanguageEnum.CSharp)
{
_includePartial = includePartial;
_language = language;
}

public CaDETProject CreateProject(IEnumerable<string> multipleClassSourceCode)
{
ICodeParser codeParser = SimpleParserFactory.CreateParser(_language);
return codeParser.Parse(multipleClassSourceCode);
return _includePartial ? codeParser.ParseWithPartial(multipleClassSourceCode) : codeParser.Parse(multipleClassSourceCode);
}

public CaDETProject CreateProject(string sourceCodeLocation, List<string> ignoredFolders)
Expand Down
28 changes: 25 additions & 3 deletions CodeModel/CodeParsers/CSharp/CSharpCodeParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,20 @@ public CSharpCodeParser()
public CaDETProject Parse(IEnumerable<string> sourceCode)
{
var syntaxErrors = LoadSyntaxTrees(sourceCode);
var parsedClasses = ParseClasses();
var parsedClasses = ParseClasses(false);
ValidateUniqueFullNameForNonPartial(parsedClasses);
parsedClasses = ConnectCaDETGraph(parsedClasses);
return new CaDETProject(LanguageEnum.CSharp, CalculateMetrics(parsedClasses), syntaxErrors);
}

public CaDETProject ParseWithPartial(IEnumerable<string> sourceCode)
{
var syntaxErrors = LoadSyntaxTrees(sourceCode);
var parsedClasses = ParseClasses(true);
parsedClasses = ConnectCaDETGraph(parsedClasses);
return new CaDETProject(LanguageEnum.CSharp, CalculateMetrics(parsedClasses), syntaxErrors);
}

private List<string> LoadSyntaxTrees(IEnumerable<string> sourceCode)
{
var syntaxErrors = new List<string>();
Expand All @@ -47,7 +55,7 @@ private List<string> LoadSyntaxTrees(IEnumerable<string> sourceCode)

return syntaxErrors;
}
private List<CaDETClass> ParseClasses()
private List<CaDETClass> ParseClasses(bool includePartial)
{
List<CaDETClass> builtClasses = new List<CaDETClass>();
foreach (var ast in _compilation.SyntaxTrees)
Expand All @@ -59,7 +67,7 @@ private List<CaDETClass> ParseClasses()
{
try
{
ValidateNoPartialModifier(node);
if(!includePartial) ValidateNoPartialModifier(node);
ValidateNoStructParent(node);
builtClasses.Add(ParseClass(semanticModel, node));
}
Expand Down Expand Up @@ -196,6 +204,7 @@ private List<CaDETClass> ConnectCaDETGraph(List<CaDETClass> classes)
foreach (var c in classes)
{
c.Parent = LinkParent(classes, c.Parent);
c.Subclasses = LinkSubclasses(classes, c);
var outerClass = LinkOuterClass(classes, c.ContainerName);
if (outerClass != null)
{
Expand All @@ -218,6 +227,19 @@ private static CaDETClass LinkParent(List<CaDETClass> classes, CaDETClass parent
if (parent.Name.Equals("object")) return null;
return classes.FirstOrDefault(c => c.FullName.Equals(parent.Name));
}

private List<CaDETClass> LinkSubclasses(List<CaDETClass> classes, CaDETClass c)
{
var subclasses = new List<CaDETClass>();
foreach(var subclass in classes)
{
if (subclass.Parent == null) continue;
if (subclass.Parent.FullName != null && subclass.Parent.FullName.Equals(c.FullName)) subclasses.Add(subclass);
else if (subclass.Parent.Name != null && subclass.Parent.Name.Equals(c.FullName)) subclasses.Add(subclass);
}
return subclasses;
}

private static CaDETClass LinkOuterClass(List<CaDETClass> classes, string containerName)
{
return classes.FirstOrDefault(c => c.FullName.Equals(containerName));
Expand Down
1 change: 1 addition & 0 deletions CodeModel/CodeParsers/ICodeParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ namespace CodeModel.CodeParsers
public interface ICodeParser
{
CaDETProject Parse(IEnumerable<string> sourceCode);
CaDETProject ParseWithPartial(IEnumerable<string> sourceCode);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public AnnotationConsistencyService(FullDataSetFactory fullDataSetFactory)
_fullDataSetFactory = fullDataSetFactory;
}

public Result<string> CheckMetricsSignificanceBetweenAnnotatorsForSeverity(int severity, IDictionary<string, string> projects, List<Annotator> annotators)
public Result<string> CheckMetricsSignificanceBetweenAnnotatorsForSeverity(string severity, IDictionary<string, string> projects, List<Annotator> annotators)
{
var instancesGroupedBySmells = _fullDataSetFactory.GetAnnotatedInstancesGroupedBySmells(projects, annotators, annotatorId: null);
IMetricsSignificanceTester tester = new AnovaTest();
Expand All @@ -42,7 +42,7 @@ public Result<string> CheckMetricsSignificanceInAnnotationsForAnnotator(int anno
return Result.Ok();
}

public Result<string> CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(int severity, IDictionary<string, string> projects, List<Annotator> annotators)
public Result<string> CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(string severity, IDictionary<string, string> projects, List<Annotator> annotators)
{
var instancesGroupedBySmells = _fullDataSetFactory.GetAnnotatedInstancesGroupedBySmells(projects, annotators, annotatorId: null);
IAnnotatorsConsistencyTester tester = new ManovaTest();
Expand All @@ -67,7 +67,7 @@ public Result<Dictionary<string, string>> CheckAnnotationConsistencyForAnnotator
return tester.TestConsistencyOfSingleAnnotator(annotatorId, instancesGroupedBySmells);
}

public Result<Dictionary<string, string>> CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(int projectId, int severity)
public Result<Dictionary<string, string>> CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(int projectId, string severity)
{
var instancesGroupedBySmells = _fullDataSetFactory.GetAnnotatedInstancesGroupedBySmells(projectId, annotatorId: null);
IAnnotatorsConsistencyTester tester = new ManovaTest();
Expand All @@ -81,7 +81,7 @@ public Result<Dictionary<string, Dictionary<string, string>>> CheckMetricsSignif
return tester.TestForSingleAnnotator(annotatorId, instancesGroupedBySmells);
}

public Result<Dictionary<string, Dictionary<string, string>>> CheckMetricsSignificanceBetweenAnnotatorsForSeverity(int projectId, int severity)
public Result<Dictionary<string, Dictionary<string, string>>> CheckMetricsSignificanceBetweenAnnotatorsForSeverity(int projectId, string severity)
{
var instancesGroupedBySmells = _fullDataSetFactory.GetAnnotatedInstancesGroupedBySmells(projectId, annotatorId: null);
IMetricsSignificanceTester tester = new AnovaTest();
Expand Down
27 changes: 15 additions & 12 deletions DataSetExplorer/Core/AnnotationConsistency/AnovaTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ namespace DataSetExplorer.Core.AnnotationConsistency
{
public class AnovaTest : IMetricsSignificanceTester
{
private readonly string _anovaScriptFile = "./AnnotationConsistency/scripts/anova_test.py";
private readonly string _pythonPath = "./AnnotationConsistency/venv/Scripts/python.exe";
private readonly string _anovaScriptFile = "./Core/AnnotationConsistency/scripts/anova_test.py";
private readonly string _pythonPath = "./Core/AnnotationConsistency/venv/Scripts/python.exe";
private string _annotatedInstancesFile;
private string _dependentVariable;
private string _independentVariable;
Expand All @@ -22,23 +22,26 @@ public class AnovaTest : IMetricsSignificanceTester

public Result<Dictionary<string, Dictionary<string, string>>> TestForSingleAnnotator(int annotatorId, List<SmellCandidateInstances> instancesGroupedBySmells)
{
return Test(annotatorId, instancesGroupedBySmells, TestCodeSmellForAnnotator);
}

public Result<Dictionary<string, Dictionary<string, string>>> TestBetweenAnnotators(int severity, List<SmellCandidateInstances> instancesGroupedBySmells)
{
return Test(severity, instancesGroupedBySmells, TestCodeSmellBetweenAnnotators);
var results = new Dictionary<string, Dictionary<string, string>>();
foreach (var codeSmellGroup in instancesGroupedBySmells)
{
var codeSmell = codeSmellGroup.CodeSmell.Name;
var metrics = codeSmellGroup.Instances.First().MetricFeatures.Keys.ToList();
var instances = codeSmellGroup.Instances;
results[codeSmell] = TestCodeSmellForAnnotator(annotatorId, instances, codeSmell, metrics);
}
return Result.Ok(results);
}

private Result<Dictionary<string, Dictionary<string, string>>> Test(int id, List<SmellCandidateInstances> instancesGroupedBySmells, TestCodeSmellDelegate testCodeSmell)
public Result<Dictionary<string, Dictionary<string, string>>> TestBetweenAnnotators(string severity, List<SmellCandidateInstances> instancesGroupedBySmells)
{
var results = new Dictionary<string, Dictionary<string, string>>();
foreach (var codeSmellGroup in instancesGroupedBySmells)
{
var codeSmell = codeSmellGroup.CodeSmell.Name;
var metrics = codeSmellGroup.Instances.First().MetricFeatures.Keys.ToList();
var instances = codeSmellGroup.Instances;
results[codeSmell] = testCodeSmell(id, instances, codeSmell, metrics);
results[codeSmell] = TestCodeSmellBetweenAnnotators(severity, instances, codeSmell, metrics);
}
return Result.Ok(results);
}
Expand All @@ -55,7 +58,7 @@ private Dictionary<string, string> TestCodeSmellForAnnotator(int annotatorId, Li
return results;
}

private Dictionary<string, string> TestCodeSmellBetweenAnnotators(int severity, List<Instance> instances, string codeSmell, List<CaDETMetric> metrics)
private Dictionary<string, string> TestCodeSmellBetweenAnnotators(string severity, List<Instance> instances, string codeSmell, List<CaDETMetric> metrics)
{
var results = new Dictionary<string, string>();
string exportedAnnotationsFile = ExportAnnotationsForSeverity(severity, instances, codeSmell);
Expand All @@ -75,7 +78,7 @@ private string ExportAnnotationsForAnnotator(int annotatorId, List<Instance> ins
return exportedAnnotationsFile;
}

private string ExportAnnotationsForSeverity(int severity, List<Instance> instances, string codeSmell)
private string ExportAnnotationsForSeverity(string severity, List<Instance> instances, string codeSmell)
{
var exportedAnnotationsFile = "MetricsSignificance_" + codeSmell + "_Severity_" + severity;
var exporter = new AnnotationConsistencyByMetricsExporter(_annotatedInstancesFolderPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ namespace DataSetExplorer.Core.AnnotationConsistency
{
public interface IAnnotationConsistencyService
{
Result<string> CheckMetricsSignificanceBetweenAnnotatorsForSeverity(int severity, IDictionary<string, string> projects, List<Annotator> annotators);
Result<string> CheckMetricsSignificanceBetweenAnnotatorsForSeverity(string severity, IDictionary<string, string> projects, List<Annotator> annotators);
Result<string> CheckMetricsSignificanceInAnnotationsForAnnotator(int annotatorId, IDictionary<string, string> projects, List<Annotator> annotators);
Result<string> CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(int severity, IDictionary<string, string> projects, List<Annotator> annotators);
Result<string> CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(string severity, IDictionary<string, string> projects, List<Annotator> annotators);
Result<string> CheckAnnotationConsistencyForAnnotator(int annotatorId, IDictionary<string, string> projects, List<Annotator> annotators);

Result<Dictionary<string, string>> CheckAnnotationConsistencyForAnnotator(int projectId, int annotatorId);
Result<Dictionary<string, string>> CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(int projectId, int severity);
Result<Dictionary<string, string>> CheckAnnotationConsistencyBetweenAnnotatorsForSeverity(int projectId, string severity);
Result<Dictionary<string, Dictionary<string, string>>> CheckMetricsSignificanceInAnnotationsForAnnotator(int projectId, int annotatorId);
Result<Dictionary<string, Dictionary<string, string>>> CheckMetricsSignificanceBetweenAnnotatorsForSeverity(int projectId, int severity);
Result<Dictionary<string, Dictionary<string, string>>> CheckMetricsSignificanceBetweenAnnotatorsForSeverity(int projectId, string severity);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace DataSetExplorer.Core.AnnotationConsistency
{
internal interface IAnnotatorsConsistencyTester
{
public Result<Dictionary<string, string>> TestConsistencyBetweenAnnotators(int severity, List<SmellCandidateInstances> instancesGroupedBySmells);
public Result<Dictionary<string, string>> TestConsistencyBetweenAnnotators(string severity, List<SmellCandidateInstances> instancesGroupedBySmells);

public Result<Dictionary<string, string>> TestConsistencyOfSingleAnnotator(int annotatorId, List<SmellCandidateInstances> instancesGroupedBySmells);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ internal interface IMetricsSignificanceTester
{
public Result<Dictionary<string, Dictionary<string, string>>> TestForSingleAnnotator(int annotatorId, List<SmellCandidateInstances> instancesGroupedBySmells);

public Result<Dictionary<string, Dictionary<string, string>>> TestBetweenAnnotators(int severity, List<SmellCandidateInstances> instancesGroupedBySmells);
public Result<Dictionary<string, Dictionary<string, string>>> TestBetweenAnnotators(string severity, List<SmellCandidateInstances> instancesGroupedBySmells);
}
}
Loading