Skip to content

Commit

Permalink
Merge pull request #730 from uni-bremen-agst/704-generate-a-codecity-…
Browse files Browse the repository at this point in the history
…via-git-repository

704 generate a codecity via git repository

Closes #704
  • Loading branch information
koschke authored Jun 6, 2024
2 parents 5b3c093 + 31c6ec4 commit c8a765a
Show file tree
Hide file tree
Showing 140 changed files with 2,359 additions and 88 deletions.
26 changes: 22 additions & 4 deletions Assets/SEE/Controls/Actions/ShowCodeAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,10 +254,28 @@ public static CodeWindow ShowVCSDiff(GraphElementRef graphElementRef, DiffCity c
public static CodeWindow ShowCode(GraphElementRef graphElementRef)
{
GraphElement graphElement = graphElementRef.Elem;
// File name of source code file to read from it
(string filename, string absolutePlatformPath) = GetPath(graphElement);
CodeWindow codeWindow = GetOrCreateCodeWindow(graphElementRef, filename);
codeWindow.EnterFromFile(absolutePlatformPath);
CodeWindow codeWindow;
if (graphElement.TryGetCommitID(out string commitID))
{
codeWindow = GetOrCreateCodeWindow(graphElementRef, graphElement.Filename);
if (!graphElement.TryGetRepositoryPath(out string repositoryPath))
{
string message = $"Selected {GetName(graphElement)} has no repository path.";
ShowNotification.Error("No repository path", message, log: false);
throw new InvalidOperationException(message);
}
IVersionControl vcs = VersionControlFactory.GetVersionControl(VCSKind.Git, repositoryPath);
string[] fileContent = vcs.Show(graphElement.ID, commitID).
Split("\\n", StringSplitOptions.RemoveEmptyEntries);
codeWindow.EnterFromText(fileContent);
}
else
{
(string filename, string absolutePlatformPath) = GetPath(graphElement);
codeWindow = GetOrCreateCodeWindow(graphElementRef, filename);
// File name of source code file to read from it
codeWindow.EnterFromFile(absolutePlatformPath);
}

// Pass line number to automatically scroll to it, if it exists
if (graphElement.SourceLine is { } line)
Expand Down
4 changes: 2 additions & 2 deletions Assets/SEE/DataModel/DG/Graph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -938,7 +938,7 @@ private void GatherRoots()
/// The name of a node metric that reflects the node's depth within the node hierarchy.
/// It is equivalent to the node attribute <see cref="Level"/>.
/// </summary>
public const string MetricLevel = "Metric.Level";
public const string MetricLevel = Metrics.Prefix + "Level";

/// <summary>
/// Sets the metric <see cref="MetricLevel"/> of each node to its Level.
Expand Down Expand Up @@ -1019,7 +1019,7 @@ void MergeNodeAttributes(Node targetNode, Node sourceNode)
targetNode.SetInt(attribute.Key, attribute.Value);
}
// Level may change when merging two graphs into one
else if (value != attribute.Value && attribute.Key != "Metric.Level")
else if (value != attribute.Value && attribute.Key != Metrics.Prefix + "Level")
{
throw new InvalidOperationException($"Node attribute {attribute.Key} differs in nodes "
+ $"{targetNode} and {sourceNode}");
Expand Down
2 changes: 1 addition & 1 deletion Assets/SEE/DataModel/DG/IO/JaCoCoImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ static void AddMetrics(XmlReader xmlReader, Node nodeToAddMetrics)
int missed = int.Parse(xmlReader.GetAttribute("missed")!, CultureInfo.InvariantCulture.NumberFormat);
int covered = int.Parse(xmlReader.GetAttribute("covered")!, CultureInfo.InvariantCulture.NumberFormat);

string metricNamePrefix = JaCoCo.Prefix + "." + xmlReader.GetAttribute("type");
string metricNamePrefix = JaCoCo.Prefix + xmlReader.GetAttribute("type");

nodeToAddMetrics.SetInt(metricNamePrefix + "_missed", missed);
nodeToAddMetrics.SetInt(metricNamePrefix + "_covered", covered);
Expand Down
74 changes: 43 additions & 31 deletions Assets/SEE/DataModel/DG/StandardNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ public enum NumericAttributeNames
IssuesTotal
}

/// <summary>
/// Provides a common prefix for all metrics.
/// </summary>
public static class Metrics
{
/// <summary>
/// Prefix for all metrics.
/// </summary>
public const string Prefix = "Metric.";
}


/// <summary>
/// Provides an extension <see cref="Name(NumericAttributeNames)"/> for <see cref="NumericAttributeNames"/>.
/// </summary>
Expand All @@ -35,18 +47,18 @@ public static string Name(this NumericAttributeNames numericAttributeName)
{
return numericAttributeName switch
{
NumericAttributeNames.NumberOfTokens => "Metric.Number_of_Tokens",
NumericAttributeNames.CloneRate => "Metric.Clone_Rate",
NumericAttributeNames.LOC => "Metric.Lines.LOC",
NumericAttributeNames.Complexity => "Metric.Complexity",
NumericAttributeNames.ArchitectureViolations => "Metric.Architecture_Violations",
NumericAttributeNames.Clone => "Metric.Clone",
NumericAttributeNames.Cycle => "Metric.Cycle",
NumericAttributeNames.DeadCode => "Metric.Dead_Code",
NumericAttributeNames.Metric => "Metric.Metric",
NumericAttributeNames.Style => "Metric.Style",
NumericAttributeNames.Universal => "Metric.Universal",
NumericAttributeNames.IssuesTotal => "Metric.IssuesTotal",
NumericAttributeNames.NumberOfTokens => Metrics.Prefix + "Number_of_Tokens",
NumericAttributeNames.CloneRate => Metrics.Prefix + "Clone_Rate",
NumericAttributeNames.LOC => Metrics.Prefix + "Lines.LOC",
NumericAttributeNames.Complexity => Metrics.Prefix + "Complexity",
NumericAttributeNames.ArchitectureViolations => Metrics.Prefix + "Architecture_Violations",
NumericAttributeNames.Clone => Metrics.Prefix + "Clone",
NumericAttributeNames.Cycle => Metrics.Prefix + "Cycle",
NumericAttributeNames.DeadCode => Metrics.Prefix + "Dead_Code",
NumericAttributeNames.Metric => Metrics.Prefix + "Metric",
NumericAttributeNames.Style => Metrics.Prefix + "Style",
NumericAttributeNames.Universal => Metrics.Prefix + "Universal",
NumericAttributeNames.IssuesTotal => Metrics.Prefix + "IssuesTotal",
_ => throw new System.Exception("Unknown attribute name " + numericAttributeName)
};
}
Expand All @@ -61,32 +73,32 @@ public static class JaCoCo
/// <summary>
/// The prefix of each JaCoCo metric.
/// </summary>
public const string Prefix = "Metric.JaCoCo";
public const string Prefix = Metrics.Prefix + "JaCoCo.";
/// <summary>
/// The number of instructions that were not executed.
/// </summary>
public const string InstructionMissed = "Metric.JaCoCo.INSTRUCTION_missed";
public const string InstructionMissed = Prefix + "INSTRUCTION_missed";
/// <summary>
/// The number of instructions that were executed.
/// </summary>
public const string InstructionCovered = "Metric.JaCoCo.INSTRUCTION_covered";
public const string InstructionCovered = Prefix + "INSTRUCTION_covered";
/// <summary>
/// InstructionCovered / (InstructionCovered + InstructionMissed).
/// </summary>
public const string PercentageOfInstructionCovered = "Metric.JaCoCo.INSTRUCTION_percentage";
public const string PercentageOfInstructionCovered = Prefix + "INSTRUCTION_percentage";

/// <summary>
/// The number of branches (conditional statement constitute branches) that were not executed.
/// </summary>
public const string BranchMissed = "Metric.JaCoCo.BRANCH_missed";
public const string BranchMissed = Prefix + "BRANCH_missed";
/// <summary>
/// The number of branches (conditional statement constitute branches) that were executed.
/// </summary>
public const string BranchCovered = "Metric.JaCoCo.BRANCH_covered";
public const string BranchCovered = Prefix + "BRANCH_covered";
/// <summary>
/// BranchCovered / (BranchMissed + BranchCovered).
/// </summary>
public const string PercentageOfBranchCovered = "Metric.JaCoCo.BRANCH_percentage";
public const string PercentageOfBranchCovered = Prefix + "BRANCH_percentage";

/// <summary>
/// Cyclomatic complexity is defined for each non-abstract method and is also
Expand All @@ -95,19 +107,19 @@ public static class JaCoCo
/// in (linear) combination, generate all possible paths through a method.
/// This metric counts the missed such paths.
/// </summary>
public const string ComplexityMissed = "Metric.JaCoCo.COMPLEXITY_missed";
public const string ComplexityMissed = Prefix + "COMPLEXITY_missed";
/// <summary>
/// Cyclomatic complexity is defined for each non-abstract method and is also
/// aggregated from methods to classes, packages, and groups they are contained.
/// McCabe1996 cyclomatic complexity is the minimum number of paths that can,
/// in (linear) combination, generate all possible paths through a method.
/// This metric counts the covered such paths.
/// </summary>
public const string ComplexityCovered = "Metric.JaCoCo.COMPLEXITY_covered";
public const string ComplexityCovered = Prefix + "COMPLEXITY_covered";
/// <summary>
/// ComplexityCovered / (ComplexityMissed + ComplexityCovered).
/// </summary>
public const string PercentageOfComplexityCovered = "Metric.JaCoCo.COMPLEXITY_percentage";
public const string PercentageOfComplexityCovered = Prefix + "COMPLEXITY_percentage";

/// <summary>
/// This metric is defined for all class files that have been compiled with debug information,
Expand All @@ -116,19 +128,19 @@ public static class JaCoCo
/// this line has been executed.
/// This metric counts the number of such lines missed.
/// </summary>
public const string LineMissed = "Metric.JaCoCo.LINE_missed";
public const string LineMissed = Prefix + "LINE_missed";
/// <summary>
/// This metric is defined for all class files that have been compiled with debug information,
/// such that coverage information for individual lines can be calculated.
/// A source line is considered executed when at least one instruction that is assigned to
/// this line has been executed
/// This metric counts the number of such lines covered.
/// </summary>
public const string LineCovered = "Metric.JaCoCo.LINE_covered";
public const string LineCovered = Prefix + "LINE_covered";
/// <summary>
/// LineCovered / (LineMissed + LineCovered).
/// </summary>
public const string PercentageOfLineCovered = "Metric.JaCoCo.LINE_percentage";
public const string PercentageOfLineCovered = Prefix + "LINE_percentage";

/// <summary>
/// A method is considered as executed when at least one of its instructions has been executed.
Expand All @@ -137,36 +149,36 @@ public static class JaCoCo
/// like implicit and thus generated default constructors or initializers for constants.
/// This metric counts the number of missed methods.
/// </summary>
public const string MethodMissed = "Metric.JaCoCo.METHOD_missed";
public const string MethodMissed = Prefix + "METHOD_missed";
/// <summary>
/// A method is considered as executed when at least one of its instructions has been executed.
/// As JaCoCo works on byte code level also constructors and static initializers are counted as methods.
/// Some of these methods may not have a direct correspondence in Java source code,
/// like implicit and thus generated default constructors or initializers for constants.
/// This metric counts the number of covered methods.
/// </summary>
public const string MethodCovered = "Metric.JaCoCo.METHOD_covered";
public const string MethodCovered = Prefix + "METHOD_covered";
/// <summary>
/// MethodCovered / (MethodMissed + MethodCovered).
/// </summary>
public const string PercentageOfMethodCovered = "Metric.JaCoCo.METHOD_percentage";
public const string PercentageOfMethodCovered = Prefix + "METHOD_percentage";

/// <summary>
/// A class is considered as executed when at least one of its methods has been executed.
/// Note that JaCoCo considers constructors as well as static initializers as methods.
/// This metric counts the number of missed classes.
/// </summary>
public const string ClassMissed = "Metric.JaCoCo.CLASS_missed";
public const string ClassMissed = Prefix + "CLASS_missed";
/// <summary>
/// A class is considered as executed when at least one of its methods has been executed.
/// Note that JaCoCo considers constructors as well as static initializers as methods.
/// This metric counts the number of covered classes.
/// </summary>
public const string ClassCovered = "Metric.JaCoCo.CLASS_covered";
public const string ClassCovered = Prefix + "CLASS_covered";
/// <summary>
/// ClassCovered / (ClassMissed + ClassCovered).
/// </summary>
public const string PercentageOfClassCovered = "Metric.JaCoCo.CLASS_percentage";
public const string PercentageOfClassCovered = Prefix + "CLASS_percentage";
}

/// <summary>
Expand Down
74 changes: 74 additions & 0 deletions Assets/SEE/DataModel/DG/VCSExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
namespace SEE.DataModel.DG
{
/// <summary>
/// Provides convenience extension properties for the VCS related attributes.
/// </summary>
public static class VCSExtensions
{
/// <summary>
/// The attribute name for the commitID..
/// </summary>
public const string CommitIDAttribute = "CommitID";

/// <summary>
/// Returns the commit ID of the <paramref name="graph"/>.
/// </summary>
/// <param name="graph">graph whose commit ID is requested</param>
public static bool TryGetCommitID(this Graph graph, out string commitID)
{
return graph.TryGetString(CommitIDAttribute, out commitID);
}

/// <summary>
/// Sets the commit ID of the <paramref name="graph"/> to <paramref name="value"/>
/// </summary>
/// <param name="graph">graph whose commit ID is to be set</param>
/// <param name="value">value to be set</param>
public static void CommitID(this Graph graph, string value)
{
graph.SetString(CommitIDAttribute, value);
}

/// <summary>
/// Returns the commit ID of the <paramref name="graphElement"/>.
/// </summary>
/// <param name="graphElement">graph element whose commit ID is requested</param>
public static bool TryGetCommitID(this GraphElement graphElement, out string commitID)
{
return graphElement.ItsGraph.TryGetString(CommitIDAttribute, out commitID);
}

/// <summary>
/// The attribute name for the repository path.
/// </summary>
public const string RepositoryPathAttribute = "RepositoryPath";

/// <summary>
/// Returns the repository path of the <paramref name="graph"/>.
/// </summary>
/// <param name="graph">graph whose repository path is requested</param>
public static bool TryGetRepositoryPath(this Graph graph, out string repositoryPath)
{
return graph.TryGetString(RepositoryPathAttribute, out repositoryPath);
}

/// <summary>
/// Sets the repository path of the <paramref name="graph"/> to <paramref name="value"/>
/// </summary>
/// <param name="graph">graph whose repository path is to be set</param>
/// <param name="value">value to be set</param>
public static void RepositoryPath(this Graph graph, string value)
{
graph.SetString(RepositoryPathAttribute, value);
}

/// <summary>
/// Returns the repository path of the <paramref name="graphElement"/>.
/// </summary>
/// <param name="graphElement">graph element whose repository path is requested</param>
public static bool TryGetRepositoryPath(this GraphElement graphElement, out string repositoryPath)
{
return graphElement.ItsGraph.TryGetString(RepositoryPathAttribute, out repositoryPath);
}
}
}
11 changes: 11 additions & 0 deletions Assets/SEE/DataModel/DG/VCSExtensions.cs.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 80930361a53496148bfe4cb7cedd976e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
4 changes: 2 additions & 2 deletions Assets/SEE/Game/Charts/AxisContentDropdown.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ private void UpdateInternal()
/// <returns>either entry or entry with the ChartManager.MetricPrefix</returns>
private string GetEntry(string entry)
{
return entry.Equals(specialEntry) ? entry : ChartManager.MetricPrefix + entry;
return entry.Equals(specialEntry) ? entry : DataModel.DG.Metrics.Prefix + entry;
}

/// <summary>
Expand Down Expand Up @@ -126,7 +126,7 @@ private void FillDropDown()
{
// Add all node metrics without their prefix
string[] options = chartContent.AllMetricNames.ToArray();
int metricPrefixLength = ChartManager.MetricPrefix.Length;
int metricPrefixLength = DataModel.DG.Metrics.Prefix.Length;
for (int i = 0; i < options.Length; i++)
{
options[i] = options[i].Remove(0, metricPrefixLength);
Expand Down
2 changes: 1 addition & 1 deletion Assets/SEE/Game/Charts/ChartContent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ private void GetAllNumericAttributes()
Debug.LogWarning("There are no nodes for showing metrics.\n");
}
#endif
foreach (string cname in Attributable.NumericAttributeNames.Where(cname => cname.StartsWith(ChartManager.MetricPrefix)))
foreach (string cname in Attributable.NumericAttributeNames.Where(cname => cname.StartsWith(Metrics.Prefix)))
{
AllMetricNames.Add(cname);
}
Expand Down
6 changes: 0 additions & 6 deletions Assets/SEE/Game/Charts/ChartManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using SEE.Controls;
using SEE.DataModel;
using SEE.GO;
using SEE.Utils;
using UnityEngine;
Expand All @@ -32,11 +31,6 @@ namespace SEE.Game.Charts
/// </summary>
public class ChartManager : MonoBehaviour
{
/// <summary>
/// The prefix of the name of a metric shown in a chart.
/// </summary>
public const string MetricPrefix = "Metric.";

/// <summary>
/// The instance of the <see cref="ChartManager" />, to ensure there will be only one.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion Assets/SEE/Game/City/SEECity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ public virtual async UniTask LoadDataAsync()
{
try
{
using (LoadingSpinner.ShowDeterminate($"Loading city \"{gameObject.name}\"...",
using (LoadingSpinner.ShowDeterminate($"Loading city \"{gameObject.name}\"...\n",
out Action<float> reportProgress))
{
void ReportProgress(float x)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ internal class AverageCommentDensity : Metric
/// <summary>
/// We will try to get this attribute for each node. Should be the comment density for each node.
/// </summary>
private const string attributeName = "Metric.Comment.Density";
private const string attributeName = SEE.DataModel.DG.Metrics.Prefix + "Comment.Density";

/// <summary>
/// Calculates the average comment density for the nodes of the given <paramref name="city"/>.
Expand Down
Loading

0 comments on commit c8a765a

Please sign in to comment.