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

Added various metrics and a rudimentary clone detection

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


Signed-off-by: default avatarEddie Groh <groh@fortiss.org>
parent d51455d9
No related branches found
No related tags found
1 merge request!210Setting up Metric extraction plugin for AF3 : Issue 4310
......@@ -15,4 +15,5 @@ Export-Package: org.fortiss.tooling.ext.quality.service
Import-Package: org.fortiss.af3.component.model,
org.fortiss.af3.component.utils,
org.fortiss.af3.project.model,
org.fortiss.af3.project.utils
org.fortiss.af3.project.utils,
org.fortiss.af3.rcp.application
......@@ -16,14 +16,23 @@
package org.fortiss.tooling.ext.quality.service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.ecore.EObject;
import org.fortiss.af3.component.model.InputPort;
import org.fortiss.af3.component.model.PortSpecification;
import org.fortiss.tooling.base.model.base.HierarchicElementBase;
import org.fortiss.tooling.base.model.element.IConnector;
import org.fortiss.tooling.base.model.element.IHierarchicElement;
import org.fortiss.tooling.kernel.model.INamedCommentedElement;
/**
* {@link IMetricProvider} to count the ratio of filled out comments of INamedCommentedElements.
* {@link IMetricProvider} to count the ratio of filled out comments of
* INamedCommentedElements.
*
* @author blaschke
*/
......@@ -36,15 +45,287 @@ public class MetricCommentProvider implements IMetricProvider<IHierarchicElement
@Override
public List<String> apply(IHierarchicElement topComponent) {
extractComment(topComponent);
for(IHierarchicElement child : topComponent.getContainedElements()) {
for (IHierarchicElement child : topComponent.getContainedElements()) {
apply(child);
}
return strings;
}
public void startRecursion(IHierarchicElement topElement) {
Set<IElementConsumer> consumers = new HashSet<MetricCommentProvider.IElementConsumer>();
consumers.add(new PortCounter());
consumers.add(new ConnectionCounter());
consumers.add(new ElementCounter());
consumers.add(new CommentCompleteness());
consumers.add(new CloneDetection());
traverse(topElement, consumers);
consumers.forEach(c -> c.printResult());
new PortCounter().printShare((HierarchicElementBase) topElement.getContainedElements().get(0));
}
public void traverse(IHierarchicElement currentElement, Set<IElementConsumer> consumers) {
consumers.forEach(c -> c.apply(currentElement));
for (IHierarchicElement child : currentElement.getContainedElements()) {
traverse(child, consumers);
}
}
public interface IElementConsumer {
public void apply(IHierarchicElement element);
public void printResult();
}
public abstract class MultiMethodDemo implements IElementConsumer {
@Override
public void apply(IHierarchicElement element) {
if (element instanceof INamedCommentedElement) {
consume((INamedCommentedElement) element);
} else {
consume(element);
}
}
public abstract void consume(IHierarchicElement element);
public abstract void consume(INamedCommentedElement element);
}
public class CloneDetection implements IElementConsumer {
private Map<Integer, List<IHierarchicElement>> map = new HashMap<>();
@Override
public void printResult() {
System.out.println("Stuff");
}
@Override
public void apply(IHierarchicElement element) {
if (!((INamedCommentedElement) element).getName().equals("DtB")) {
// return;
}
int hash = 1;
for (IConnector connector : element.getConnectors()) {
PortSpecification port = (PortSpecification) connector.getSpecifications().get(0);
hash = 31 * hash
+ (connector instanceof InputPort ? 1 : 2) * port.getType().getClass().hashCode();
}
map.putIfAbsent(hash, new ArrayList<>());
List<IHierarchicElement> elements = map.get(hash);
for (IHierarchicElement element_b : elements) {
List<String> element_a_input = new ArrayList<String>();
List<String> element_b_input = new ArrayList<String>();
List<String> element_a_output = new ArrayList<String>();
List<String> element_b_output = new ArrayList<String>();
for (IConnector connector : element.getConnectors()) {
PortSpecification port = (PortSpecification) connector.getSpecifications().get(0);
String type = port.getType().getClass().getSimpleName();
if (connector instanceof InputPort) {
element_a_input.add(type);
} else {
element_a_output.add(type);
}
}
for (IConnector connector : element_b.getConnectors()) {
PortSpecification port = (PortSpecification) connector.getSpecifications().get(0);
String type = port.getType().getClass().getSimpleName();
if (connector instanceof InputPort) {
element_b_input.add(type);
} else {
element_b_output.add(type);
}
}
boolean equals = true;
for (String type_a_input : element_a_input) {
if (!element_b_input.remove(type_a_input)) {
equals = false;
break;
}
}
for (String type_a_output : element_a_output) {
if (!element_b_output.remove(type_a_output)) {
equals = false;
break;
}
}
if (equals) {
System.out.println("Found duplicate: "+((INamedCommentedElement)element).getName() + ", " + ((INamedCommentedElement)element_b).getName());
break;
} else {
System.out.println("Same but not duplicate");
}
}
elements.add(element);
}
}
public class CommentCompleteness extends MultiMethodDemo {
private int total_amount;
private int with_comments;
public CommentCompleteness() {
total_amount = 0;
with_comments = 0;
}
@Override
public void printResult() {
System.out.println("[CommentCompleteness] Total:" + total_amount + " With:" + with_comments + " Ratio:"
+ (with_comments / (double) total_amount));
}
@Override
public void consume(IHierarchicElement element) {
total_amount++;
}
@Override
public void consume(INamedCommentedElement element) {
if (element.getComment() != "") {
with_comments++;
}
total_amount++;
}
}
public class Tuple<T1, T2> {
private T1 element1;
private T2 element2;
public Tuple(T1 element1, T2 element2) {
this.element1 = element1;
this.element2 = element2;
}
public T1 getElement1() {
return element1;
}
public T2 getElement2() {
return element2;
}
}
public abstract class CounterConsumer implements IElementConsumer {
protected int count;
public CounterConsumer() {
count = 0;
}
@Override
public void printResult() {
System.out.println("[" + this.getClass().getSimpleName() + "] Found " + count + " total");
}
public int getCount() {
return count;
}
public void printShare(HierarchicElementBase element) {
Set<Tuple<String, Integer>> counts = new HashSet<>();
this.apply(element);
counts.add(new Tuple<>("[Self]" + element.getName(), count));
count = 0;
for (IHierarchicElement child : element.getContainedElements()) {
HierarchicElementBase real_child = (HierarchicElementBase) child;
recursiveDescent(real_child, this);
counts.add(new Tuple<>(real_child.getName(), count));
count = 0;
}
double total = counts.stream().mapToInt(t -> t.getElement2()).sum();
System.out.println("[" + this.getClass().getSimpleName() + "] shares:");
for (Tuple<String, Integer> tuple : counts) {
System.out.println("\t " + String.format("%05.2f%%", tuple.element2 / total * 100) + ", "
+ tuple.element2 + ": " + tuple.element1);
}
}
protected void recursiveDescent(HierarchicElementBase element, CounterConsumer consumer) {
consumer.apply(element);
for (IHierarchicElement child : element.getContainedElements()) {
HierarchicElementBase real_child = (HierarchicElementBase) child;
recursiveDescent(real_child, consumer);
}
}
}
public class PortCounter extends CounterConsumer {
@Override
public void apply(IHierarchicElement element) {
count += element.getConnectors().size();
}
}
public class ConnectionCounter extends CounterConsumer {
@Override
public void apply(IHierarchicElement element) {
count += element.getConnections().size();
}
}
public class ElementCounter extends CounterConsumer {
@Override
public void apply(IHierarchicElement element) {
count++;
}
}
public Map<String, Integer> sizeMetrics(IHierarchicElement ele) {
return null;
// anzahl elemente im baum ab hierarchiebene ele
// anzahl ports ab ......
// anzahl channels.......
// completness von comments #eleMitComment/#ele
// kamelCase names
// State Automoton
// Annotations
// tooling.kernel -> tooling.body -> ext packages -> af3 -> rcp
}
/** */
private void extractComment(IHierarchicElement c) {
strings.add(((INamedCommentedElement)c).getComment());
strings.add(((INamedCommentedElement) c).getComment());
}
/** {@inheritDoc} */
......
......@@ -18,11 +18,9 @@ package test.org.fortiss.tooling.ext.quality.metric;
import static org.fortiss.af3.component.utils.ComponentArchitectureUtils.findFirstComponentArchitecture;
import static org.fortiss.af3.project.utils.TestCaseProjectUtils.loadTestProject;
import java.util.List;
import org.fortiss.af3.component.model.Component;
import org.fortiss.af3.project.model.FileProject;
import org.fortiss.tooling.ext.quality.AF3QualityActivator;
import org.fortiss.af3.rcp.application.AF3ApplicationActivator;
import org.fortiss.tooling.base.model.element.IHierarchicElement;
import org.fortiss.tooling.ext.quality.service.MetricCommentProvider;
import org.junit.Before;
import org.junit.Test;
......@@ -36,13 +34,17 @@ import org.junit.Test;
public class MetricTest {
/** Top component. */
private Component topComponent;
private IHierarchicElement topComponent;
/** Setup the test. */
@Before
public void setup() {
FileProject project = loadTestProject(AF3QualityActivator.PLUGIN_ID,
"test-data/StateAutomataConstraintsCheckerTestData.af3_23");
FileProject project = loadTestProject(AF3ApplicationActivator.PLUGIN_ID,
// "test-data/ACC.af3_23");
"test-data/carla_ff1_rover.af3_23");
// topComponent = (IHierarchicElement) project.getRootElements().get(2);
topComponent = findFirstComponentArchitecture(project).getTopComponent();
}
......@@ -50,7 +52,7 @@ public class MetricTest {
@Test
public void actionsConstraintCheck() {
MetricCommentProvider mcp = new MetricCommentProvider();
List<String> result = mcp.apply(topComponent);
System.out.println(result);
mcp.startRecursion(topComponent);
}
}
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