Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# RefactorLizar
The RefactorLizar project is a library for analyzing and refactoring model-based analyses.


## Contributing
### Pull Requests
Each pull request title follows the format:
`<type>(<scope>): <subject>`
#### Type
Must be one of the following:

feat: A new feature
fix: A bug fix
docs: Documentation only changes
style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
refactor: A code change that neither fixes a bug nor adds a feature
perf: A code change that improves performance
test: Adding missing or correcting existing tests
chore: Changes to the build process or auxiliary tools and libraries such as documentation generation

[from] (https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#commits)
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,14 @@ public Report analyze(

protected abstract Report fullAnalysis(
ModularLanguage language, SimulatorModel simulatorModel, Settings settings);

@Override
public String getDescription() {
return "MISSING";
}

@Override
public String getName() {
return "MISSING";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public class Report {
private Map<String, Set<String>> featureScatterings = Collections.emptyMap();
private Map<String, Set<String>> languageBlobs = Collections.emptyMap();

public Report(String text, String description, boolean smellFound) {
this.text = text;
public Report(String title, String description, boolean smellFound) {
this.text = title;
this.description = description;
solutions = Collections.emptyList();
this.smellFound = smellFound;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package edu.kit.kastel.sdq.case4lang.refactorlizar.analyzer.api;

import edu.kit.kastel.sdq.case4lang.refactorlizar.model.ModularLanguage;
import edu.kit.kastel.sdq.case4lang.refactorlizar.model.SimulatorModel;

public interface Solution {

String getHeadline();

String getDescription();

void apply();
void apply(ModularLanguage language, SimulatorModel simulatorModel);
}
21 changes: 21 additions & 0 deletions bad-smells-ma/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@


plugins {
id 'edu.kit.kastel.sdq.case4lang.refactorlizar.java-conventions'
}
dependencies {
implementation project(":"+project.commons)
implementation project(":commons-analyzer")
implementation project(":core")
}
allprojects {
repositories {
maven { url 'https://jitpack.io' }
}
}
description = 'badsmells-ma'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package edu.kit.kastel.sdq.case4lang.refactorlizar.analyzer.broken_modularity;

import edu.kit.kastel.sdq.case4lang.refactorlizar.analyzer.api.AbstractAnalyzer;
import edu.kit.kastel.sdq.case4lang.refactorlizar.analyzer.api.Report;
import edu.kit.kastel.sdq.case4lang.refactorlizar.commons.Settings;
import edu.kit.kastel.sdq.case4lang.refactorlizar.model.ModularLanguage;
import edu.kit.kastel.sdq.case4lang.refactorlizar.model.SimulatorModel;
import java.util.List;
import java.util.stream.Collectors;
import spoon.reflect.declaration.CtType;
import spoon.reflect.reference.CtTypeReference;

public class WrongDependencyDirection extends AbstractAnalyzer {

@Override
protected void checkSettings(Settings settings) {}

@Override
protected Report fullAnalysis(
ModularLanguage language, SimulatorModel simulatorModel, Settings settings) {
var types = getLanguageTypes(language);
StringBuilder sb = new StringBuilder();
int counter = 0;
for (CtType<?> ctType : types) {
List<CtTypeReference<?>> col =
ctType.getReferencedTypes().stream()
.filter(
v ->
isSimulatorType(simulatorModel, v)
&& isLanguageType(language, v))
.collect(Collectors.toList());
col.remove(ctType.getReference());
for (CtTypeReference<?> dependency : col) {
sb.append(ctType.getQualifiedName())
.append(" -> ")
.append(dependency.getQualifiedName())
.append("\n");
counter++;
}
}
return new Report("WrongDependencyDirection", sb.toString(), counter > 0);
}

private boolean isLanguageType(ModularLanguage language, CtTypeReference<?> v) {
return language.getTypeWithQualifiedName(v.getQualifiedName()) == null;
}

private boolean isSimulatorType(SimulatorModel simulatorModel, CtTypeReference<?> v) {
return simulatorModel.getTypeWithQualifiedName(v.getQualifiedName()) != null;
}

private List<CtType<?>> getLanguageTypes(ModularLanguage language) {
return language.getComponents().stream()
.flatMap(c -> c.getTypes().stream())
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package edu.kit.kastel.sdq.case4lang.refactorlizar.analyzer.deficient_encapsulation;

import com.google.common.collect.Lists;
import edu.kit.kastel.sdq.case4lang.refactorlizar.analyzer.api.AbstractAnalyzer;
import edu.kit.kastel.sdq.case4lang.refactorlizar.analyzer.api.Report;
import edu.kit.kastel.sdq.case4lang.refactorlizar.commons.Settings;
import edu.kit.kastel.sdq.case4lang.refactorlizar.model.Component;
import edu.kit.kastel.sdq.case4lang.refactorlizar.model.ModularLanguage;
import edu.kit.kastel.sdq.case4lang.refactorlizar.model.SimulatorModel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtType;
import spoon.reflect.declaration.CtTypedElement;
import spoon.reflect.reference.CtTypeReference;

public class DataClumbs extends AbstractAnalyzer {

@Override
public String getDescription() {
return "null";
}

@Override
public String getName() {
return "dataclumbs";
}

@Override
protected void checkSettings(Settings settings) {}

@Override
protected Report fullAnalysis(
ModularLanguage language, SimulatorModel simulatorModel, Settings settings) {
Map<List<CtTypeReference<?>>, Integer> map = new HashMap<>();
Set<CtType<?>> types = getAllTypes(simulatorModel);
for (CtType<?> ctType : types) {
for (CtMethod<?> method : ctType.getMethods()) {
if (method.getParameters().size() < 2) {
continue;
}
List<List<CtTypeReference<?>>> tuples = createTuples(method);
// unwanted pairs like (a,a) and (b,b) are removed
tuples.removeIf(v -> v.get(0).equals(v.get(1)));
for (List<CtTypeReference<?>> tuple : tuples) {
tuple = new ArrayList<>(tuple);
tuple.sort(
((o1, o2) -> o1.getQualifiedName().compareTo(o2.getQualifiedName())));
if (map.containsKey(tuple)) {
map.put(tuple, map.get(tuple) + 1);
} else {
map.put(tuple, 1);
}
}
}
}
// we still have (a,b) and (b,a) pairs included as 2 values so we have 3 as cutoff for now
map.values().removeIf(i -> i < 3);
map.keySet()
.removeIf(
v ->
!(isLanguageType(language, v.get(0).getQualifiedName())
|| isLanguageType(language, v.get(1).getQualifiedName())));
List<Entry<List<CtTypeReference<?>>, Integer>> result =
map.entrySet().stream()
.sorted((o1, o2) -> o2.getValue().compareTo(o1.getValue()))
.limit(20)
.collect(Collectors.toList());

StringBuilder sb = new StringBuilder();
for (Entry<List<CtTypeReference<?>>, Integer> entry : result) {
// resugar the report to be more readable
for (CtType<?> type : types) {
for (CtMethod<?> method : type.getMethods()) {
if (method.getParameters().stream()
.map(CtTypedElement::getType)
.collect(Collectors.toSet())
.containsAll(entry.getKey())) {
sb.append(
method.getDeclaringType().getQualifiedName()
+ "#"
+ method.getSimpleName())
.append("\n");
}
}
}
sb.append("\n");
sb.append(
entry.getKey().stream()
.map(CtTypeReference::getQualifiedName)
.collect(Collectors.joining(", "))
+ " "
+ entry.getValue()
+ "\n");
sb.append("\n");
sb.append("\n");
}
return new Report(getName(), sb.toString(), sb.length() > 0);
}

private boolean isLanguageType(ModularLanguage language, String fqName) {
return language.getTypeWithQualifiedName(fqName) != null;
}

private ArrayList<List<CtTypeReference<?>>> createTuples(CtMethod<?> method) {
return new ArrayList<>(
Lists.cartesianProduct(
method.getParameters().stream()
.map(CtTypedElement::getType)
.collect(Collectors.toList()),
method.getParameters().stream()
.map(CtTypedElement::getType)
.collect(Collectors.toList())));
}

private Set<CtType<?>> getAllTypes(SimulatorModel simulatorModel) {
return simulatorModel.getComponents().stream()
.map(Component::getTypes)
.flatMap(Collection::stream)
.collect(Collectors.toSet());
}
}
Loading