Skip to content
Snippets Groups Projects
Commit 4708b508 authored by Eddie Groh's avatar Eddie Groh
Browse files

Added lines of codes, comments and nesting level metrics

Issue-Ref: 4310
Issue-Url: af3#4310



Signed-off-by: default avatarEddie Groh <groh@fortiss.org>
parent 52f37bd5
No related branches found
No related tags found
1 merge request!210Setting up Metric extraction plugin for AF3 : Issue 4310
...@@ -5,27 +5,15 @@ ...@@ -5,27 +5,15 @@
<?import javafx.scene.chart.NumberAxis?> <?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.chart.PieChart?> <?import javafx.scene.chart.PieChart?>
<?import javafx.scene.chart.ScatterChart?> <?import javafx.scene.chart.ScatterChart?>
<?import javafx.scene.control.Button?> <?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.SplitPane?> <?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.Tab?> <?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?> <?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?> <?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?> <?import javafx.scene.layout.BorderPane?>
<SplitPane fx:id="metricsSplitPane" dividerPositions="0.07035175879396985" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" orientation="VERTICAL" prefHeight="400.0" prefWidth="1035.0" xmlns="http://javafx.com/javafx/20.0.1" xmlns:fx="http://javafx.com/fxml/1"> <SplitPane fx:id="metricsSplitPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" orientation="VERTICAL" prefHeight="400.0" prefWidth="1035.0" xmlns="http://javafx.com/javafx/20.0.1" xmlns:fx="http://javafx.com/fxml/1">
<items> <items>
<BorderPane maxHeight="-Infinity" minHeight="-Infinity" prefHeight="25.0" prefWidth="626.0">
<center>
<Label fx:id="topLabel" alignment="CENTER" contentDisplay="CENTER" prefHeight="51.0" prefWidth="500.0" textAlignment="CENTER" BorderPane.alignment="CENTER" />
</center>
<left>
<Button fx:id="refreshButton" mnemonicParsing="false" onAction="#onRefreshMetricsSubmit" text="Refresh Metrics" BorderPane.alignment="CENTER" />
</left>
<top>
<SplitPane BorderPane.alignment="CENTER" />
</top>
</BorderPane>
<TabPane prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE"> <TabPane prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE">
<tabs> <tabs>
<Tab text="Pie and Spider"> <Tab text="Pie and Spider">
...@@ -34,7 +22,14 @@ ...@@ -34,7 +22,14 @@
<children> <children>
<SplitPane dividerPositions="0.5" layoutX="56.0" layoutY="-19.0" prefHeight="134.0" prefWidth="1033.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <SplitPane dividerPositions="0.5" layoutX="56.0" layoutY="-19.0" prefHeight="134.0" prefWidth="1033.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items> <items>
<PieChart fx:id="pieChart" prefHeight="184.0" prefWidth="1033.0" /> <BorderPane prefHeight="200.0" prefWidth="200.0">
<center>
<PieChart fx:id="pieChart" prefHeight="184.0" prefWidth="1033.0" BorderPane.alignment="CENTER" />
</center>
<top>
<ChoiceBox fx:id="choiceBox" onAction="#onChoiceBoxChange" prefWidth="150.0" BorderPane.alignment="CENTER" />
</top>
</BorderPane>
<BorderPane fx:id="borderPane" prefHeight="158.0" prefWidth="81.0" /> <BorderPane fx:id="borderPane" prefHeight="158.0" prefWidth="81.0" />
</items> </items>
</SplitPane> </SplitPane>
......
...@@ -28,8 +28,6 @@ import static org.fortiss.tooling.kernel.ui.util.SelectionUtils.checkAndPickFirs ...@@ -28,8 +28,6 @@ import static org.fortiss.tooling.kernel.ui.util.SelectionUtils.checkAndPickFirs
import static org.fortiss.tooling.kernel.utils.EcoreUtils.getFirstParentWithType; import static org.fortiss.tooling.kernel.utils.EcoreUtils.getFirstParentWithType;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.List;
import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EObject;
...@@ -41,6 +39,7 @@ import org.fortiss.tooling.common.ui.javafx.layout.CompositeFXControllerBase; ...@@ -41,6 +39,7 @@ import org.fortiss.tooling.common.ui.javafx.layout.CompositeFXControllerBase;
import org.fortiss.tooling.common.ui.javafx.style.FillStyle; import org.fortiss.tooling.common.ui.javafx.style.FillStyle;
import org.fortiss.tooling.common.ui.javafx.style.FontStyle; import org.fortiss.tooling.common.ui.javafx.style.FontStyle;
import org.fortiss.tooling.common.ui.javafx.style.LineStyle; import org.fortiss.tooling.common.ui.javafx.style.LineStyle;
import org.fortiss.tooling.ext.quality.data.MetricDataManager;
import org.fortiss.tooling.ext.quality.data.MetricKey; import org.fortiss.tooling.ext.quality.data.MetricKey;
import org.fortiss.tooling.ext.quality.data.MetricTreeNode; import org.fortiss.tooling.ext.quality.data.MetricTreeNode;
import org.fortiss.tooling.ext.quality.service.ModelQualityService; import org.fortiss.tooling.ext.quality.service.ModelQualityService;
...@@ -59,8 +58,7 @@ import javafx.scene.Node; ...@@ -59,8 +58,7 @@ import javafx.scene.Node;
import javafx.scene.chart.PieChart; import javafx.scene.chart.PieChart;
import javafx.scene.chart.ScatterChart; import javafx.scene.chart.ScatterChart;
import javafx.scene.chart.XYChart; import javafx.scene.chart.XYChart;
import javafx.scene.control.Button; import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane; import javafx.scene.control.SplitPane;
import javafx.scene.layout.BorderPane; import javafx.scene.layout.BorderPane;
...@@ -77,13 +75,9 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan ...@@ -77,13 +75,9 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan
/** The {@link IProjectRootElement} in which the selected element is contained in. */ /** The {@link IProjectRootElement} in which the selected element is contained in. */
private IProjectRootElement currentRootElement; private IProjectRootElement currentRootElement;
/** The refresh {@link Button} to refresh the metrics. */ /** a choiceBox */
@FXML @FXML
private Button refreshButton; private ChoiceBox<MetricKey> choiceBox;
/** The central top {@link Label} to display short messages. */
@FXML
private Label topLabel;
/** The bottom {@link BorderPane} for the spiderchart */ /** The bottom {@link BorderPane} for the spiderchart */
@FXML @FXML
...@@ -97,9 +91,6 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan ...@@ -97,9 +91,6 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan
@FXML @FXML
private ScatterChart<Number, Number> scatterChart; private ScatterChart<Number, Number> scatterChart;
/** Time format when displaying updating time. */
private final DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("HH:mm:ss");
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public String getFXMLLocation() { public String getFXMLLocation() {
...@@ -109,9 +100,15 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan ...@@ -109,9 +100,15 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void initialize() { public void initialize() {
// Not used choiceBox.getItems().addAll(MetricKey.values());
} }
/**
* The last IHierachicElement which the user has clicked. Might be null when no or invalid
* Object is selected
*/
private IHierarchicElement lastSelectedElement;
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) { public void selectionChanged(IWorkbenchPart part, ISelection selection) {
...@@ -119,15 +116,15 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan ...@@ -119,15 +116,15 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan
ModelQualityService.getInstance(); ModelQualityService.getInstance();
var manager = ModelQualityService.metricDataManagerInstance; var manager = ModelQualityService.metricDataManagerInstance;
if(manager == null) { if(manager == null) {
topLabel.setText( // topLabel.setText("No Metrics were available at " +
"No Metrics were available at " + timeFormat.format(LocalDateTime.now())); // timeFormat.format(LocalDateTime.now()));
return; return;
} }
EObject selected = checkAndPickFirst(selection, EObject.class); EObject selected = checkAndPickFirst(selection, EObject.class);
if(selected == null) { if(selected == null) {
topLabel.setText("Nothing selected"); // topLabel.setText("Nothing selected");
return; return;
} }
...@@ -140,12 +137,12 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan ...@@ -140,12 +137,12 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan
if(currentRootElement == null) { if(currentRootElement == null) {
// There was no root element for the selected element. (Usually should be the // There was no root element for the selected element. (Usually should be the
// FileProject.) This is not displayed here. // FileProject.) This is not displayed here.
topLabel.setText("No root found"); // topLabel.setText("No root found");
return; return;
} }
if(!(currentRootElement instanceof IHierarchicElement)) { if(!(currentRootElement instanceof IHierarchicElement)) {
topLabel.setText("Root is not an IHierarchicElement"); // topLabel.setText("Root is not an IHierarchicElement");
return; return;
} }
...@@ -153,15 +150,36 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan ...@@ -153,15 +150,36 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan
var root_provider = manager.getRootNodes().get(currentRootElement); var root_provider = manager.getRootNodes().get(currentRootElement);
if(root_provider == null) { if(root_provider == null) {
topLabel.setText("No Metric found for this project, did you export metrics?"); // topLabel.setText("No Metric found for this project, did you export metrics?");
return; return;
} }
var element = (IHierarchicElement)selected; lastSelectedElement = (IHierarchicElement)selected;
var node = manager.getHierarchicLookupTable().get(element); } else {
// topLabel.setText("Selected is not an IHierarchicElement");
}
updateCharts();
}
/**
* Is triggered when the refresh button is pressed.
*/
public void onChoiceBoxChange() {
updateCharts();
}
/**
* Updates the chart in the metric view
*/
private void updateCharts() {
if(lastSelectedElement != null) {
MetricDataManager manager = ModelQualityService.metricDataManagerInstance;
MetricTreeNode node = manager.getHierarchicLookupTable().get(lastSelectedElement);
if(node != null) { if(node != null) {
topLabel.setText("Text"); // topLabel.setText("Text");
if(!node.getChildren().isEmpty()) { if(!node.getChildren().isEmpty()) {
...@@ -171,9 +189,7 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan ...@@ -171,9 +189,7 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan
// Create PieChart and add data // Create PieChart and add data
pieChart.getData().clear(); pieChart.getData().clear();
for(var child : node.getChildren()) { for(var child : node.getChildren()) {
Double value = child.getStoredMetrics().get(choiceBox.getValue());
Double value = child.getStoredMetrics()
.get(MetricKey.NUMBER_OF_TOTAL_CODE_CONSTANTS);
if(value != null) { if(value != null) {
PieChart.Data slice = new PieChart.Data(child.getName(), value); PieChart.Data slice = new PieChart.Data(child.getName(), value);
pieChart.getData().add(slice); pieChart.getData().add(slice);
...@@ -205,27 +221,16 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan ...@@ -205,27 +221,16 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan
} }
} }
} else { // Return, otherwise the data will be cleared
borderPane.setCenter(null); return;
pieChart.getData().clear();
} }
} else { } else {
topLabel.setText("Element not in metrics"); // topLabel.setText("Element not in metrics");
} }
} else {
topLabel.setText("Selected is not an IHierarchicElement");
} }
borderPane.setCenter(null);
} pieChart.getData().clear();
/**
* Is triggered when the refresh button is pressed.
*/
public void onRefreshMetricsSubmit() {
LocalDateTime currentTime = LocalDateTime.now();
topLabel.setText("View was updated at " + timeFormat.format(currentTime));
} }
/** /**
......
...@@ -38,6 +38,8 @@ public enum MetricKey { ...@@ -38,6 +38,8 @@ public enum MetricKey {
NUMBER_OF_CHANNELS(false), NUMBER_OF_CHANNELS(false),
/** Safety level of the element */ /** Safety level of the element */
SAFETY_LEVEL(false, true), SAFETY_LEVEL(false, true),
/** How deeply nested the corresponding element is */
NESTING_LEVEL(false),
// //
// Metrics which are collected over all children nodes // Metrics which are collected over all children nodes
...@@ -64,7 +66,13 @@ public enum MetricKey { ...@@ -64,7 +66,13 @@ public enum MetricKey {
NUMBER_OF_TOTAL_CODE_CONSTANTS(true), NUMBER_OF_TOTAL_CODE_CONSTANTS(true),
/** Cyclomatic complexity number as sum over all components */ /** Cyclomatic complexity number as sum over all components */
NUMBER_OF_TOTAL_CODE_CYCLOMATIC_COMPLEXITY(true); NUMBER_OF_TOTAL_CODE_CYCLOMATIC_COMPLEXITY(true),
/** Counts the Lines of Code (LoC) in the component and its sub-components */
NUMBER_OF_TOTAL_CODE_LINES(true),
/** Representation of the total amount of comment blocks in all code specifications */
NUMBER_OF_TOTAL_CODE_COMMENTS(true);
/** Metrics which are a combination from the data of multiple nodes */ /** Metrics which are a combination from the data of multiple nodes */
private static List<MetricKey> collectorKeys = new ArrayList<>(); private static List<MetricKey> collectorKeys = new ArrayList<>();
......
...@@ -126,7 +126,7 @@ public class ModelQualityService extends EObjectAwareServiceBase<IMetricProvider ...@@ -126,7 +126,7 @@ public class ModelQualityService extends EObjectAwareServiceBase<IMetricProvider
// Get first element, there should not be any other elements // Get first element, there should not be any other elements
IHierarchicElement firstElement = elements.get(0); IHierarchicElement firstElement = elements.get(0);
MetricTreeNode root_node = new MetricTreeNode(); MetricTreeNode root_node = new MetricTreeNode();
recursivlyCollectMetrics(root_node, firstElement); recursivlyCollectMetrics(root_node, firstElement, 0);
root_nodes.put(rootElement, root_node); root_nodes.put(rootElement, root_node);
} }
} }
...@@ -139,12 +139,16 @@ public class ModelQualityService extends EObjectAwareServiceBase<IMetricProvider ...@@ -139,12 +139,16 @@ public class ModelQualityService extends EObjectAwareServiceBase<IMetricProvider
* to which the data is collected * to which the data is collected
* @param currentElement * @param currentElement
* element to collect the data from * element to collect the data from
* @param recursionLevel
* parameter which indicates the current recursion level, used for metric
*/ */
private void recursivlyCollectMetrics(MetricTreeNode node, IHierarchicElement currentElement) { private void recursivlyCollectMetrics(MetricTreeNode node, IHierarchicElement currentElement,
int recursionLevel) {
var manager = metricDataManagerInstance; var manager = metricDataManagerInstance;
collectMetrics(node, currentElement); collectMetrics(node, currentElement);
node.getStoredMetrics().put(MetricKey.NESTING_LEVEL, (double)recursionLevel);
// Check if any of the specifications is an IHierarchicElement // Check if any of the specifications is an IHierarchicElement
// This is for example the case with an StateAutomaton // This is for example the case with an StateAutomaton
...@@ -161,9 +165,9 @@ public class ModelQualityService extends EObjectAwareServiceBase<IMetricProvider ...@@ -161,9 +165,9 @@ public class ModelQualityService extends EObjectAwareServiceBase<IMetricProvider
// Add reference from the element to this, so the lookups works as expected // Add reference from the element to this, so the lookups works as expected
manager.getHierarchicLookupTable().put(specificationElement, node); manager.getHierarchicLookupTable().put(specificationElement, node);
// Skip the specification element to get a more useful tree structure // Skip the specification element to get a more useful tree structure
recursivlyCollectMetrics(node, containedElements.get(0)); recursivlyCollectMetrics(node, containedElements.get(0), recursionLevel);
} else { } else {
recursivlyCollectMetrics(node, specificationElement); recursivlyCollectMetrics(node, specificationElement, recursionLevel);
} }
// Add reference from the element to this, so the lookups works as expected // Add reference from the element to this, so the lookups works as expected
manager.getHierarchicLookupTable().put(currentElement, node); manager.getHierarchicLookupTable().put(currentElement, node);
...@@ -173,7 +177,7 @@ public class ModelQualityService extends EObjectAwareServiceBase<IMetricProvider ...@@ -173,7 +177,7 @@ public class ModelQualityService extends EObjectAwareServiceBase<IMetricProvider
for(IHierarchicElement containedElement : currentElement.getContainedElements()) { for(IHierarchicElement containedElement : currentElement.getContainedElements()) {
MetricTreeNode child = new MetricTreeNode(); MetricTreeNode child = new MetricTreeNode();
node.getChildren().add(child); node.getChildren().add(child);
recursivlyCollectMetrics(child, containedElement); recursivlyCollectMetrics(child, containedElement, recursionLevel++);
for(MetricKey key : MetricKey.getCollectorKeys()) { for(MetricKey key : MetricKey.getCollectorKeys()) {
var childMetrics = child.getStoredMetrics(); var childMetrics = child.getStoredMetrics();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment