From 37cc6846b832ac47c63e2bd65bfdf0caf8984edc Mon Sep 17 00:00:00 2001 From: Johannes Mey <johannes.mey@tu-dresden.de> Date: Sat, 4 Jan 2020 21:24:24 +0100 Subject: [PATCH] detect interface hiding, albeit only interface->class, not for sub-interfaces (but this is prohibited by java anyway and extendj collects all implemented superinterfaces automatically) --- .../src/main/jastadd/ProgramToScopeTree.jrag | 14 +++++++-- .../test/java/org/extendj/InterfaceTest.java | 30 +++++++++++++++++++ .../src/test/resources/interface/ClassA.java | 5 ++++ .../test/resources/interface/InterfaceA.java | 5 ++++ .../test/resources/interface/InterfaceB.java | 5 ++++ 5 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 scope4j/src/test/java/org/extendj/InterfaceTest.java create mode 100644 scope4j/src/test/resources/interface/ClassA.java create mode 100644 scope4j/src/test/resources/interface/InterfaceA.java create mode 100644 scope4j/src/test/resources/interface/InterfaceB.java diff --git a/scope4j/src/main/jastadd/ProgramToScopeTree.jrag b/scope4j/src/main/jastadd/ProgramToScopeTree.jrag index 26f0fba..b1dc8e2 100644 --- a/scope4j/src/main/jastadd/ProgramToScopeTree.jrag +++ b/scope4j/src/main/jastadd/ProgramToScopeTree.jrag @@ -35,6 +35,12 @@ aspect ProgramToScopeTree { addInheritedScope(superDecl.asProtectedScope()); } } + for (InterfaceDecl interfaceDecl : classDecl.implementedInterfaces()) { + System.out.println(classDecl.implementedInterfaces()); + if (interfaceDecl.compilationUnit().fromSource()) { + addInheritedScope(interfaceDecl.asPackageScope()); + } + } } super.updateInheritance(); } @@ -53,11 +59,11 @@ aspect ProgramToScopeTree { EnhancedForStmt contributes scope() when !(getStmt() instanceof Block) to ASTNode.scope() for containingScope(); // collect all elements - Declarator contributes asDeclaration() when /* is NOT in interface || */ !isField() || isPrivate() to ASTNode.scope() for containingScope(); + Declarator contributes asDeclaration() when !inInterface() && (!isField() || isPrivate()) to ASTNode.scope() for containingScope(); // field which is neither private, protected, nor public -> package-private scope Declarator contributes asDeclaration() when isField() && !isPrivate() && !(isProtected() || isPublic()) to TypeDecl.packageScope() for containingScope(); // field which is either protected or public -> protected scope - Declarator contributes asDeclaration() when /* is in interface && */ isField() && !isPrivate() && (isProtected() || isPublic()) to TypeDecl.protectedScope() for containingScope(); + Declarator contributes asDeclaration() when isField() && !isPrivate() && (isProtected() || isPublic() || inInterface()) to TypeDecl.protectedScope() for containingScope(); ParameterDeclaration contributes asDeclaration() to ASTNode.scope() for containingScope(); } @@ -156,4 +162,8 @@ aspect ScopeGenerationAttributes { // allow host package to be called from all AST nodes inh String ASTNode.hostPackage(); eq Program.getCompilationUnit(int i).hostPackage() = getCompilationUnit(i).getPackageDecl(); + + inh boolean Declarator.inInterface(); + eq TypeDecl.getChild().inInterface() = false; + eq InterfaceDecl.getChild().inInterface() = true; } diff --git a/scope4j/src/test/java/org/extendj/InterfaceTest.java b/scope4j/src/test/java/org/extendj/InterfaceTest.java new file mode 100644 index 0000000..070ac2e --- /dev/null +++ b/scope4j/src/test/java/org/extendj/InterfaceTest.java @@ -0,0 +1,30 @@ +package org.extendj; + +import org.extendj.ast.AbstractFinding; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Set; + +public class InterfaceTest extends ScopeAnalysisTest { + + @Test + void test() { + + + final String classA = "src/test/resources/interface/ClassA.java"; + final String interfaceA = "src/test/resources/interface/InterfaceA.java"; + final String interfaceB = "src/test/resources/interface/InterfaceB.java"; + final String interfaceAorB = "src/test/resources/interface/Interface"; + + ScopeAnalysis scopeAnalysis = new ScopeAnalysis(); + Set<AbstractFinding> findings = scopeAnalysis.analyze("src/test/resources/interface", true, true); + + assertShadow(findings, "fieldA", classA, 2, interfaceA, 2); + assertShadow(findings, "fieldB", classA, 3, interfaceB, 3); + assertShadow(findings, "fieldC", classA, 4, interfaceAorB, 4); + + Assertions.assertEquals(3, findings.size()); + } + +} diff --git a/scope4j/src/test/resources/interface/ClassA.java b/scope4j/src/test/resources/interface/ClassA.java new file mode 100644 index 0000000..0a91b8a --- /dev/null +++ b/scope4j/src/test/resources/interface/ClassA.java @@ -0,0 +1,5 @@ +public class ClassA implements InterfaceA { + int fieldA = 1; + int fieldB = 1; + int fieldC = 1; +} diff --git a/scope4j/src/test/resources/interface/InterfaceA.java b/scope4j/src/test/resources/interface/InterfaceA.java new file mode 100644 index 0000000..481e0e6 --- /dev/null +++ b/scope4j/src/test/resources/interface/InterfaceA.java @@ -0,0 +1,5 @@ +public interface InterfaceA extends InterfaceB { + int fieldA = 1; + + int fieldC = 1; +} diff --git a/scope4j/src/test/resources/interface/InterfaceB.java b/scope4j/src/test/resources/interface/InterfaceB.java new file mode 100644 index 0000000..ca9fb45 --- /dev/null +++ b/scope4j/src/test/resources/interface/InterfaceB.java @@ -0,0 +1,5 @@ +public interface InterfaceB { + + int fieldB = 2; + int fieldC = 2; +} -- GitLab