Skip to content

Commit

Permalink
#135 remove dummy generation
Browse files Browse the repository at this point in the history
  • Loading branch information
Masrepus committed Jul 3, 2020
1 parent db25058 commit 14ebd01
Show file tree
Hide file tree
Showing 9 changed files with 26 additions and 180 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -216,11 +216,6 @@ public RecordDeclaration handleClassOrInterfaceDeclaration(
classInterDecl.getExtendedTypes().stream()
.map(this.lang::getTypeAsGoodAsPossible)
.collect(Collectors.toList()));
if (recordDeclaration.getSuperClasses().isEmpty()) {
List<Type> superClasses = new ArrayList<>();
superClasses.add(TypeParser.createFrom(Object.class.getName(), true));
recordDeclaration.setSuperClasses(superClasses);
}
recordDeclaration.setImplementedInterfaces(
classInterDecl.getImplementedTypes().stream()
.map(this.lang::getTypeAsGoodAsPossible)
Expand Down
30 changes: 6 additions & 24 deletions src/main/java/de/fraunhofer/aisec/cpg/passes/ImportResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ public class ImportResolver extends Pass {

private List<RecordDeclaration> records = new ArrayList<>();
private Map<String, Declaration> importables = new HashMap<>();
private Map<String, Declaration> unknownTypes = new HashMap<>();

@Override
@Nullable
Expand All @@ -57,7 +56,6 @@ public void setLang(LanguageFrontend lang) {}
public void cleanup() {
records.clear();
importables.clear();
unknownTypes.clear();
}

@Override
Expand All @@ -72,13 +70,6 @@ public void accept(TranslationResult result) {
Set<ValueDeclaration> staticImports = getStaticImports(record);
record.setStaticImports(staticImports);
}

if (!unknownTypes.isEmpty()) {
// Get the translation unit holding all unknown declarations, or create a new one if necessary
TranslationUnitDeclaration unknownDeclarations = getUnknownDeclarationsTU(result);
unknownDeclarations.getDeclarations().addAll(unknownTypes.values());
importables.putAll(unknownTypes);
}
}

private Set<ValueDeclaration> getStaticImports(RecordDeclaration record) {
Expand All @@ -93,7 +84,7 @@ private Set<ValueDeclaration> getStaticImports(RecordDeclaration record) {
if (!matcher.matches()) {
continue;
}
Declaration base = getOrCreateDeclaration(matcher.group("base"));
Declaration base = importables.get((matcher.group("base")));
Set<ValueDeclaration> members = new HashSet<>();
if (base instanceof RecordDeclaration) {
members = getOrCreateMembers((RecordDeclaration) base, matcher.group("member"));
Expand All @@ -104,7 +95,7 @@ private Set<ValueDeclaration> getStaticImports(RecordDeclaration record) {
}

for (String asteriskImport : partitioned.get(true)) {
Declaration base = getOrCreateDeclaration(asteriskImport.replace(".*", ""));
Declaration base = importables.get(asteriskImport.replace(".*", ""));
if (base instanceof RecordDeclaration) {
RecordDeclaration baseRecord = (RecordDeclaration) base;
staticImports.addAll(
Expand All @@ -129,19 +120,10 @@ private Set<ValueDeclaration> getStaticImports(RecordDeclaration record) {
}

private Set<Declaration> getDeclarationsForTypeNames(List<String> targetTypes) {
return targetTypes.stream().map(this::getOrCreateDeclaration).collect(Collectors.toSet());
}

private Declaration getOrCreateDeclaration(String name) {
if (importables.containsKey(name)) {
return importables.get(name);
} else {
// Create stubs for unknown imports
if (!unknownTypes.containsKey(name)) {
unknownTypes.put(name, NodeBuilder.newRecordDeclaration(name, "class", ""));
}
return unknownTypes.get(name);
}
return targetTypes.stream()
.map(importables::get)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
}

private Set<ValueDeclaration> getOrCreateMembers(EnumDeclaration base, String name) {
Expand Down
27 changes: 0 additions & 27 deletions src/main/java/de/fraunhofer/aisec/cpg/passes/Pass.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@

import de.fraunhofer.aisec.cpg.TranslationResult;
import de.fraunhofer.aisec.cpg.frontends.LanguageFrontend;
import de.fraunhofer.aisec.cpg.graph.NodeBuilder;
import de.fraunhofer.aisec.cpg.graph.TranslationUnitDeclaration;
import java.util.Optional;
import java.util.function.Consumer;
import org.checkerframework.checker.nullness.qual.Nullable;

Expand Down Expand Up @@ -60,30 +57,6 @@ public void setLang(@Nullable LanguageFrontend lang) {

public abstract void cleanup();

/**
* Get the {@link TranslationUnitDeclaration} that is to be used for grouping unknown
* declarations, e.g. dummy {@link de.fraunhofer.aisec.cpg.graph.RecordDeclaration} nodes. This TU
* should be unique, thus this method ensures that a new one is only created if needed.
*
* @param result The {@link TranslationResult} that should contain this translation unit
* @return The {@link TranslationUnitDeclaration} used for dummy declarations
*/
TranslationUnitDeclaration getUnknownDeclarationsTU(TranslationResult result) {
Optional<TranslationUnitDeclaration> unknownDeclarations =
result.getTranslationUnits().stream()
.filter(tu -> tu.getName().equals("unknown declarations"))
.findFirst();
if (unknownDeclarations.isPresent()) {
return unknownDeclarations.get();
} else {
TranslationUnitDeclaration declaration =
NodeBuilder.newTranslationUnitDeclaration("unknown declarations", "");
declaration.setImplicit(true);
result.getTranslationUnits().add(declaration);
return declaration;
}
}

/**
* Specifies, whether this pass supports this particular language frontend. This defaults to
* <code>true</code> and needs to be overridden if a different behaviour is wanted.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import de.fraunhofer.aisec.cpg.TranslationResult;
import de.fraunhofer.aisec.cpg.frontends.LanguageFrontend;
import de.fraunhofer.aisec.cpg.graph.*;
import de.fraunhofer.aisec.cpg.graph.type.Type;
import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker;
import java.util.*;
import java.util.stream.Collectors;
Expand All @@ -55,7 +56,6 @@ public class TypeHierarchyResolver extends Pass {

private Map<String, RecordDeclaration> recordMap = new HashMap<>();
private List<EnumDeclaration> enums = new ArrayList<>();
private Map<String, RecordDeclaration> unknownTypes = new HashMap<>();

@Override
public LanguageFrontend getLang() {
Expand Down Expand Up @@ -92,13 +92,6 @@ public void accept(TranslationResult translationResult) {
enumDecl.setSuperTypeDeclarations(allSupertypes);
}

if (!unknownTypes.isEmpty()) {
// Get the translation unit holding all unknown declarations, or create a new one if necessary
TranslationUnitDeclaration unknownDeclarations = getUnknownDeclarationsTU(translationResult);
unknownDeclarations.getDeclarations().addAll(unknownTypes.values());
recordMap.putAll(unknownTypes);
}

translationResult.getTranslationUnits().forEach(this::refreshType);
}

Expand Down Expand Up @@ -133,20 +126,9 @@ private List<MethodDeclaration> getAllMethodsFromSupertypes(
private Set<RecordDeclaration> findSupertypeRecords(RecordDeclaration record) {
Set<RecordDeclaration> superTypeDeclarations =
record.getSuperTypes().stream()
.map(
t -> {
if (recordMap.containsKey(t.getTypeName())) {
return recordMap.get(t.getTypeName());
} else {
if (!unknownTypes.containsKey(t.getTypeName())) {
RecordDeclaration dummy =
NodeBuilder.newRecordDeclaration(t.getTypeName(), "class", "");
dummy.setImplicit(true);
unknownTypes.put(t.getTypeName(), dummy);
}
return unknownTypes.get(t.getTypeName());
}
})
.map(Type::getTypeName)
.map(recordMap::get)
.filter(Objects::nonNull)
.collect(Collectors.toSet());

record.setSuperTypeDeclarations(superTypeDeclarations);
Expand All @@ -166,7 +148,5 @@ private void analyzeOverridingMethods(
}

@Override
public void cleanup() {
this.unknownTypes.clear();
}
public void cleanup() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ public class VariableUsageResolver extends Pass {
private static final Logger log = LoggerFactory.getLogger(VariableUsageResolver.class);
private Map<Type, List<Type>> superTypesMap = new HashMap<>();
private Map<Type, RecordDeclaration> recordMap = new HashMap<>();
private Set<RecordDeclaration> unknownRecords = new HashSet<>();
private Map<Type, EnumDeclaration> enumMap = new HashMap<>();
private TranslationUnitDeclaration currTu;
private ScopedWalker walker;
Expand Down Expand Up @@ -112,10 +111,6 @@ public void accept(TranslationResult result) {
walker.registerHandler(this::resolveLocalVarUsage);
walker.iterate(tu);
}
if (!unknownRecords.isEmpty()) {
TranslationUnitDeclaration unknownDeclarations = getUnknownDeclarationsTU(result);
unknownDeclarations.getDeclarations().addAll(unknownRecords);
}
}

private void findRecordsAndEnums(Node node, RecordDeclaration curClass) {
Expand Down Expand Up @@ -182,7 +177,11 @@ private Set<ValueDeclaration> resolveFunctionPtr(
if (containingClass == null) {
targets.add(handleUnknownMethod(functionName, reference.getType()));
} else {
targets.add(handleUnknownClassMethod(containingClass, functionName, reference.getType()));
MethodDeclaration resolved =
handleUnknownClassMethod(containingClass, functionName, reference.getType());
if (resolved != null) {
targets.add(resolved);
}
}
return targets;
}
Expand Down Expand Up @@ -367,12 +366,7 @@ private ValueDeclaration resolveMember(

private FieldDeclaration handleUnknownField(Type base, String name, Type type) {
if (!recordMap.containsKey(base)) {
RecordDeclaration dummy =
NodeBuilder.newRecordDeclaration(
base.getTypeName(), Type.UNKNOWN_TYPE_STRING, Type.UNKNOWN_TYPE_STRING);
dummy.setImplicit(true);
recordMap.put(base, dummy);
unknownRecords.add(dummy);
return null;
}
// fields.putIfAbsent(base, new ArrayList<>());
List<FieldDeclaration> declarations = recordMap.get(base).getFields();
Expand All @@ -393,12 +387,7 @@ private FieldDeclaration handleUnknownField(Type base, String name, Type type) {

private MethodDeclaration handleUnknownClassMethod(Type base, String name, Type type) {
if (!recordMap.containsKey(base)) {
RecordDeclaration dummy =
NodeBuilder.newRecordDeclaration(
base.getTypeName(), Type.UNKNOWN_TYPE_STRING, Type.UNKNOWN_TYPE_STRING);
dummy.setImplicit(true);
recordMap.put(base, dummy);
unknownRecords.add(dummy);
return null;
}
RecordDeclaration containingRecord = recordMap.get(base);
List<MethodDeclaration> declarations = containingRecord.getMethods();
Expand Down
5 changes: 1 addition & 4 deletions src/test/java/de/fraunhofer/aisec/cpg/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,7 @@ public static List<TranslationUnitDeclaration> analyze(
public static TranslationUnitDeclaration analyzeAndGetFirstTU(
List<File> files, Path topLevel, boolean usePasses) throws Exception {
List<TranslationUnitDeclaration> translationUnits = analyze(files, topLevel, usePasses);
return translationUnits.stream()
.filter(t -> !t.getName().equals("unknown declarations"))
.findFirst()
.orElseThrow();
return translationUnits.stream().findFirst().orElseThrow();
}

/**
Expand Down
34 changes: 7 additions & 27 deletions src/test/java/de/fraunhofer/aisec/cpg/TypeTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -674,21 +674,7 @@ void getCommonTypeTestJava() throws Exception {
Path topLevel = Path.of("src", "test", "resources", "compiling", "hierarchy", "multistep");
TestUtils.analyze("java", topLevel, true);

Type root = TypeParser.createFrom("Root", true);
Type level0 = TypeParser.createFrom("Level0", true);
Type level1 = TypeParser.createFrom("Level1", true);
Type level1b = TypeParser.createFrom("Level1B", true);
Type level2 = TypeParser.createFrom("Level2", true);

getCommonTypeTestGeneral();

// Check unrelated type behavior: Everything is a java.lang.Object!
Type unrelated = TypeParser.createFrom("Unrelated", true);
Type javaObject = TypeParser.createFrom(Object.class.getName(), true);
for (Type t : List.of(root, level0, level1, level1b, level2)) {
assertEquals(
Optional.of(javaObject), TypeManager.getInstance().getCommonType(List.of(unrelated, t)));
}
}

@Test
Expand All @@ -698,20 +684,7 @@ void getCommonTypeTestCpp() throws Exception {
Path topLevel = Path.of("src", "test", "resources", "compiling", "hierarchy", "multistep");
TestUtils.analyze("simple_inheritance.cpp", topLevel, true);

Type root = TypeParser.createFrom("Root", true);
Type level0 = TypeParser.createFrom("Level0", true);
Type level1 = TypeParser.createFrom("Level1", true);
Type level1b = TypeParser.createFrom("Level1B", true);
Type level2 = TypeParser.createFrom("Level2", true);

getCommonTypeTestGeneral();

// Check unrelated type behavior: No common root class
Type unrelated = TypeParser.createFrom("Unrelated", true);
for (Type t : List.of(root, level0, level1, level1b, level2)) {
assertEquals(
Optional.empty(), TypeManager.getInstance().getCommonType(List.of(unrelated, t)));
}
}

@Test
Expand Down Expand Up @@ -807,5 +780,12 @@ void getCommonTypeTestGeneral() {
// Level1 and Level2 have Level1 as common ancestor
assertEquals(
Optional.of(level1), TypeManager.getInstance().getCommonType(List.of(level1, level2)));

// Check unrelated type behavior: No common root class
Type unrelated = TypeParser.createFrom("Unrelated", true);
for (Type t : List.of(root, level0, level1, level1b, level2)) {
assertEquals(
Optional.empty(), TypeManager.getInstance().getCommonType(List.of(unrelated, t)));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
import de.fraunhofer.aisec.cpg.helpers.Util;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -116,44 +115,4 @@ void testAsteriskImport() throws Exception {
assertNotEquals(nonStatic.getMember(), nonStaticField);
assertTrue(nonStatic.getMember().isImplicit());
}

@Test
void testDummyGeneration() throws Exception {
List<TranslationUnitDeclaration> result =
TestUtils.analyze("java", topLevel.resolve("dummies"), true);
assertEquals(
1, result.stream().filter(t -> t.getName().equals("unknown declarations")).count());
List<RecordDeclaration> records = Util.subnodesOfType(result, RecordDeclaration.class);

RecordDeclaration dummyRecord = TestUtils.findByUniqueName(records, "a.b.c.SomeClass");
assertEquals(
1, dummyRecord.getFields().stream().filter(f -> f.getName().equals("someMethod")).count());
List<MethodDeclaration> dummyMethods =
dummyRecord.getMethods().stream()
.filter(m -> m.getName().equals("someMethod"))
.collect(Collectors.toList());
Map<Integer, List<MethodDeclaration>> dummiesByNumberOfParams =
dummyMethods.stream().collect(Collectors.groupingBy(m -> m.getParameters().size()));

assertTrue(dummiesByNumberOfParams.containsKey(1));
assertEquals(1, dummiesByNumberOfParams.get(1).size());
MethodDeclaration dummy1 = dummiesByNumberOfParams.get(1).get(0);

assertTrue(dummiesByNumberOfParams.containsKey(4));
assertEquals(1, dummiesByNumberOfParams.get(4).size());
MethodDeclaration dummy4 = dummiesByNumberOfParams.get(4).get(0);

RecordDeclaration mainRecord = TestUtils.findByUniqueName(records, "GenerateDummies");
MethodDeclaration main = TestUtils.findByUniqueName(mainRecord.getMethods(), "main");
for (CallExpression call : Util.subnodesOfType(main, CallExpression.class)) {
switch (call.getSignature().size()) {
case 1:
assertEquals(call.getInvokes(), List.of(dummy1));
break;
case 4:
assertEquals(call.getInvokes(), List.of(dummy4));
break;
}
}
}
}
9 changes: 0 additions & 9 deletions src/test/resources/staticImports/dummies/GenerateDummies.java

This file was deleted.

0 comments on commit 14ebd01

Please sign in to comment.