Skip to content
Snippets Groups Projects
Commit 8a6ad345 authored by Johannes Mey's avatar Johannes Mey
Browse files

Merge branch 'visibilityscopes' into modelica

parents 8d3e2019 c31c3c87
No related branches found
No related tags found
No related merge requests found
Showing
with 538 additions and 121 deletions
......@@ -2,3 +2,5 @@ ScopeTree : Scope;
abstract Element;
Declaration:Element ::= <Name:String>;
Scope:Element ::= Element*;
rel Scope.inheritedScope* -> Scope;
......@@ -4,25 +4,26 @@ aspect Shadowing {
Declaration contributes new VariableShadowFinding(shadowed(), this) when isShadowing() to ScopeTree.variableShadowings();
Declaration contributes new MultipleDeclarationFinding(this) when isShadowingInSameScope() to ScopeTree.variableShadowings();
inh Declaration Declaration.shadowed();
eq Scope.getElement(int i).shadowed() = shadowed(getElement(i).asDeclaration());
syn Declaration Declaration.shadowed()= shadowed(asDeclaration());
inh Declaration Element.shadowed(Declaration shadower);
eq ScopeTree.getElement().shadowed(Declaration shadower) {
eq Scope.getElement().shadowed(Declaration shadower) = shadowedLocally(shadower);
syn Declaration Scope.shadowedLocally(Declaration shadower) {
// first look in the current scope
for (Declaration declaration : declarations()) {
if (declaration != shadower && declaration.getName().equals(shadower.getName())) {
return declaration;
}
}
return null;
}
eq Scope.getElement().shadowed(Declaration shadower) {
for (Declaration declaration : declarations()) {
if (declaration != shadower && declaration.getName().equals(shadower.getName())) {
return declaration;
// the look in the inherited scopes
for (Scope inherited : getInheritedScopeList()) {
Declaration shadowed = inherited.shadowedLocally(shadower);
if (shadowed != null) {
return shadowed;
}
}
return shadowed(shadower);
return (this instanceof ScopeTree) ? null : shadowed(shadower);
}
inh Declaration Declaration.shadowedInSameScope();
......@@ -39,8 +40,6 @@ aspect Shadowing {
syn boolean Declaration.isShadowing() = shadowed() != null;
syn boolean Declaration.isShadowingInSameScope() = shadowedInSameScope() != null;
}
aspect Statictics {
......
aspect ProgramToScopeTree {
/** a relational nta collection attribute to compute the scope tree */
syn lazy ScopeTree Program.scopeTree() {
ScopeTree tree = new ScopeTree();
tree.setProgram(this);
ScopeTree tree = asScopeTree();
for (CompilationUnit compilationUnit : getCompilationUnitList())
for (TypeDecl typeDecl : compilationUnit.getTypeDeclList())
tree.addElement(typeDecl.scope());
// add all classes
for (CompilationUnit cu : getCompilationUnitList()) {
for (TypeDecl typeDecl : cu.getTypeDeclList()) {
tree.addElement(typeDecl.isClassDecl() ? ((ClassDecl)typeDecl).protectedScope() : typeDecl.scope());
}
}
tree.updateInheritance(); // traverse the tree and add all inheritance relations
return tree;
}
/** a relational nta collection attribute to compute the scope tree */
/** helper method to add inheritance relations */
public void Scope.updateInheritance() {
for (Element element : getElementList()) {
if (element.isScope()) {
element.asScope().updateInheritance();
}
}
}
public void ProtectedClassDeclScope.updateInheritance() {
if (getTypeDecl().isClassDecl()) {
ClassDecl classDecl = (ClassDecl)getTypeDecl();
if(classDecl.superclass().isClassDecl() && classDecl.superclass().compilationUnit().fromSource()) {
addInheritedScope(((ClassDecl)classDecl.superclass()).asPackageScope());
}
}
super.updateInheritance();
}
/** a relational nta collection attribute to compute scopes */
coll Scope ASTNode.scope() [asScope()] with addElement root Program;
/** a relational nta collection attribute to compute a special scope containing visible fields and subtypes */
coll TypeDeclScope ClassDecl.protectedScope() [asProtectedScope()] with addElement root Program;
coll TypeDeclScope ClassDecl.packageScope() [asPackageScope()] with addElement root Program;
// collect all scopes
TypeDecl contributes scope() to ASTNode.scope() for containingScope();
TypeDecl contributes scope() when !isNestedType() && !isClassDecl() to ASTNode.scope() for containingScope();
ClassDecl contributes protectedScope() when isNestedType() to ASTNode.scope() for containingScope();
Block contributes scope() to ASTNode.scope() for containingScope();
ForStmt contributes scope() when !(getStmt() instanceof Block) to ASTNode.scope() for containingScope();
EnhancedForStmt contributes scope() when !(getStmt() instanceof Block) to ASTNode.scope() for containingScope();
// collect all elements
Declarator contributes asDeclaration() to ASTNode.scope() for containingScope();
Declarator contributes asDeclaration() when !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 ClassDecl.packageScope() for containingScope();
// field which is either protected or public -> protected scope
Declarator contributes asDeclaration() when isField() && !isPrivate() && (isProtected() || isPublic()) to ClassDecl.protectedScope() for containingScope();
ParameterDeclaration contributes asDeclaration() to ASTNode.scope() for containingScope();
}
Collection<Declaration> ClassDecl.createSuperClassFieldDeclarators() {
ArrayList<Declaration> result = new ArrayList<>();
TypeDecl supertype = superclass();
/**
* aspect containing helper methods to construct (mostly empty) AST nodes of the scope tree
* There are few parts added manually, but stubs could easily be generated from the mapping grammar
*/
aspect ScopeTreeConstructors {
System.out.println("supertype " + supertype.getID());
while (supertype.isClassDecl() && supertype != unknownType()) {
for (BodyDecl bodyDecl : supertype.getBodyDeclList()) {
if (bodyDecl instanceof FieldDecl) {
for (FieldDeclarator declarator : ((FieldDecl)bodyDecl).getDeclaratorList()) {
JavaDeclaration declaration = new JavaDeclaration(declarator.getID());
declaration.setDeclarator(declarator);
result.add(declaration);
}
}
}
supertype = ((ClassDecl)supertype).superclass();
}
return result;
syn lazy ScopeTree Program.asScopeTree() {
ScopeTree tree = new ScopeTree();
tree.setProgram(this);
return tree;
}
/** fallback attribute to ensure every AST element could pontentially be a scope */
......@@ -51,11 +77,26 @@ aspect ProgramToScopeTree {
syn lazy TypeDeclScope TypeDecl.asScope() {
TypeDeclScope scope = new TypeDeclScope();
scope.setTypeDecl(this);
if (isClassDecl()) {
for (Declaration declaration : ((ClassDecl)this).createSuperClassFieldDeclarators()) {
scope.addElement(declaration);
return scope;
}
syn lazy TypeDeclScope ClassDecl.asScope() {
TypeDeclScope scope = new PrivateClassDeclScope();
scope.setTypeDecl(this);
return scope;
}
syn lazy TypeDeclScope ClassDecl.asProtectedScope() {
TypeDeclScope scope = new ProtectedClassDeclScope();
scope.setTypeDecl(this);
scope.addElement(packageScope());
return scope;
}
syn lazy TypeDeclScope ClassDecl.asPackageScope() {
TypeDeclScope scope = new PackageClassDeclScope();
scope.setTypeDecl(this);
scope.addElement(scope());
return scope;
}
......@@ -77,8 +118,8 @@ aspect ProgramToScopeTree {
return scope;
}
syn lazy JavaDeclaration Declarator.asDeclaration() {
JavaDeclaration decl = new JavaDeclaration(getID());
syn lazy SimpleJavaDeclaration Declarator.asDeclaration() {
SimpleJavaDeclaration decl = new SimpleJavaDeclaration(getID());
decl.setDeclarator(this);
return decl;
}
......@@ -113,4 +154,8 @@ aspect ScopeGenerationAttributes {
eq EnhancedForStmt.getVariableDecl().containingScope() = (getStmt() instanceof Block) ? getStmt() : this;
eq ForStmt.getInitStmt().containingScope() = (getStmt() instanceof Block) ? getStmt() : this;
eq ForStmt.getUpdateStmt().containingScope() = (getStmt() instanceof Block) ? getStmt() : this;
// allow host package to be called from all AST nodes
inh String ASTNode.hostPackage();
eq Program.getCompilationUnit(int i).hostPackage() = getCompilationUnit(i).getPackageDecl();
}
// glue relation for the Java-based variable shadowing analysis
rel ScopeTree.Program -> Program;
TypeDeclScope : Scope;
abstract JavaScope : Scope;
TypeDeclScope : JavaScope;
rel TypeDeclScope.typeDecl -> TypeDecl;
BlockScope : Scope;
ProtectedClassDeclScope : TypeDeclScope;
PackageClassDeclScope : TypeDeclScope;
PrivateClassDeclScope : TypeDeclScope;
BlockScope : JavaScope;
rel BlockScope.block -> Block;
ForStmtScope : Scope;
ForStmtScope : JavaScope;
rel ForStmtScope.forStmt -> ForStmt;
EnhancedForStmtScope : Scope;
EnhancedForStmtScope : JavaScope;
rel EnhancedForStmtScope.enhancedForStmt -> EnhancedForStmt;
JavaDeclaration : Declaration;
rel JavaDeclaration.declarator -> Declarator;
abstract JavaDeclaration : Declaration ;
SimpleJavaDeclaration : JavaDeclaration;
rel SimpleJavaDeclaration.declarator -> Declarator;
JavaParameterDeclaration : Declaration;
JavaParameterDeclaration : JavaDeclaration;
rel JavaParameterDeclaration.parameterDeclaration -> ParameterDeclaration;
JavaInferredLambdaParameterDeclaration : Declaration;
JavaInferredLambdaParameterDeclaration : JavaDeclaration;
rel JavaInferredLambdaParameterDeclaration.inferredParameterDeclaration -> InferredParameterDeclaration;
aspect Shadow{
// --- toString ---
eq TypeDeclScope.toString() = getTypeDecl().getClass().getSimpleName() + "-Scope";
eq BlockScope.toString() = getBlock().getClass().getSimpleName() + "-Scope";
eq ForStmtScope.toString() = getForStmt().getClass().getSimpleName() + "-Scope";
eq EnhancedForStmtScope.toString() = getEnhancedForStmt().getClass().getSimpleName() + "-Scope";
eq JavaDeclaration.toString() = getDeclarator().getClass().getSimpleName() + ":" + super.toString();
eq SimpleJavaDeclaration.toString() = getDeclarator().getClass().getSimpleName() + ":" + super.toString();
eq JavaParameterDeclaration.toString() = getParameterDeclaration().getClass().getSimpleName() + ":" + super.toString();
eq JavaInferredLambdaParameterDeclaration.toString() = getInferredParameterDeclaration().getClass().getSimpleName() + ":" + super.toString();
public int TypeDeclScope.lineNumber(){
return getTypeDecl().lineNumber();
}
public int BlockScope.lineNumber(){
return getBlock().lineNumber();
}
public int ForStmtScope.lineNumber(){
return getForStmt().lineNumber();
}
public int EnhancedForStmtScope.lineNumber(){
return getEnhancedForStmt().lineNumber();
}
public int JavaDeclaration.lineNumber() {
return getDeclarator().lineNumber();
}
public int JavaParameterDeclaration.lineNumber() {
return getParameterDeclaration().lineNumber();
}
public int JavaInferredLambdaParameterDeclaration.lineNumber() {
return getInferredParameterDeclaration().lineNumber();
}
// --- lineNumber ---
syn int JavaScope.lineNumber();
eq TypeDeclScope.lineNumber() = getTypeDecl().lineNumber();
eq BlockScope.lineNumber() = getBlock().lineNumber();
eq ForStmtScope.lineNumber() = getForStmt().lineNumber();
eq EnhancedForStmtScope.lineNumber() = getEnhancedForStmt().lineNumber();
syn int JavaDeclaration.lineNumber();
eq SimpleJavaDeclaration.lineNumber() = getDeclarator().lineNumber();
eq JavaParameterDeclaration.lineNumber() = getParameterDeclaration().lineNumber();
eq JavaInferredLambdaParameterDeclaration.lineNumber() = getInferredParameterDeclaration().lineNumber();
public String TypeDeclScope.sourceFile() {
return getTypeDecl().sourceFile();
}
public String BlockScope.sourceFile() {
return getBlock().sourceFile();
}
public String ForStmtScope.sourceFile() {
return getForStmt().sourceFile();
}
public String EnhancedForStmtScope.sourceFile() {
return getEnhancedForStmt().sourceFile();
}
public String JavaDeclaration.sourceFile() {
return getDeclarator().sourceFile();
}
public String JavaParameterDeclaration.sourceFile() {
return getParameterDeclaration().sourceFile();
}
public String JavaInferredLambdaParameterDeclaration.sourceFile() {
return getInferredParameterDeclaration().sourceFile();
}
// --- sourceFile ---
syn String JavaScope.sourceFile();
eq TypeDeclScope.sourceFile() = getTypeDecl().sourceFile();
eq BlockScope.sourceFile() = getBlock().sourceFile();
eq ForStmtScope.sourceFile() = getForStmt().sourceFile();
eq EnhancedForStmtScope.sourceFile() = getEnhancedForStmt().sourceFile();
syn String JavaDeclaration.sourceFile();
eq SimpleJavaDeclaration.sourceFile() = getDeclarator().sourceFile();
eq JavaParameterDeclaration.sourceFile() = getParameterDeclaration().sourceFile();
eq JavaInferredLambdaParameterDeclaration.sourceFile() = getInferredParameterDeclaration().sourceFile();
// --- asJavaDeclaration ---
syn JavaDeclaration Declaration.asJavaDeclaration() = null;
eq JavaDeclaration.asJavaDeclaration() = this;
}
......@@ -137,7 +137,7 @@ public class ScopeAnalysis extends Frontend {
}
private Program readProgram(Collection<String> files) throws IOException {
System.out.println("Reading " + (files.size() > 10 ? files.size() + " files" : files.toString()));
Program program = new Program();
program.resetStatistics();
......
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 FieldsTest extends ScopeAnalysisTest {
@Test
void test() {
ScopeAnalysis scopeAnalysis = new ScopeAnalysis();
Set<AbstractFinding> findings = scopeAnalysis.analyze("src/test/resources/fields", true, false);
}
}
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 InnerInheritanceTest extends ScopeAnalysisTest {
@Test
void test() {
ScopeAnalysis scopeAnalysis = new ScopeAnalysis();
Set<AbstractFinding> findings = scopeAnalysis.analyze("src/test/resources/innerInheritance", true, true);
assertShadow(findings, "fieldA", "ClassB", 6, "ClassA", 3);
assertShadow(findings, "fieldB", "ClassB", 7, "ClassB", 3);
Assertions.assertEquals(2, findings.size());
}
}
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 InnerTest extends ScopeAnalysisTest {
@Test
void test() {
ScopeAnalysis scopeAnalysis = new ScopeAnalysis();
Set<AbstractFinding> findings = scopeAnalysis.analyze("src/test/resources/inner", true, true);
System.out.println(findings);
// anonymous class
assertShadow(findings, "fieldA", "ClassA", 11, "ClassA", 13);
assertShadow(findings, "fieldA", "ClassA", 13, "ClassA", 3);
// local inner class
assertShadow(findings, "fieldA", "ClassA", 27, "ClassA", 29);
assertShadow(findings, "fieldA", "ClassA", 29, "ClassA", 3);
assertShadow(findings, "changingVar", "ClassA", 25, "ClassA", 19);
// static member class
assertShadow(findings, "fieldA", "ClassA", 37, "ClassA", 35);
assertShadow(findings, "fieldA", "ClassA", 35, "ClassA", 3);
// member class
assertShadow(findings, "fieldA", "ClassA", 44, "ClassA", 42);
assertShadow(findings, "fieldA", "ClassA", 42, "ClassA", 3);
// anonymous class defined in other class
assertShadow(findings, "fieldB", "ClassB", 5, "ClassB", 10);
// the anonymous class inherited a field
assertShadow(findings, "fieldB", "ClassB", 10, "ClassA", 4);
Assertions.assertEquals(11, findings.size());
}
}
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 ProtectedTest extends ScopeAnalysisTest {
@Test
void test() {
ScopeAnalysis scopeAnalysis = new ScopeAnalysis();
Set<AbstractFinding> findings = scopeAnalysis.analyze("src/test/resources/protected_", true, true);
System.out.println(findings);
final String classA = "src/test/resources/protected_/one/ClassA.java";
final String classB = "src/test/resources/protected_/one/ClassB.java";
final String classC = "src/test/resources/protected_/one/ClassC.java";
final String classD = "src/test/resources/protected_/two/ClassD.java";
final String classE = "src/test/resources/protected_/two/ClassE.java";
// within class A
// A.A()
assertShadow(findings, "fPrivate", classA, 19, classA, 9);
assertShadow(findings, "fPackage", classA, 20, classA, 10);
assertShadow(findings, "fProtected", classA, 21, classA, 11);
assertShadow(findings, "fPublic", classA, 22, classA, 12);
// A.foo()
assertShadow(findings, "fPrivate", classA, 26, classA, 9);
assertShadow(findings, "fPackage", classA, 27, classA, 10);
assertShadow(findings, "fProtected", classA, 28, classA, 11);
assertShadow(findings, "fPublic", classA, 29, classA, 12);
// A.bar()
assertShadow(findings, "fPrivate", classA, 32, classA, 9);
assertShadow(findings, "fPackage", classA, 33, classA, 10);
assertShadow(findings, "fProtected", classA, 34, classA, 11);
assertShadow(findings, "fPublic", classA, 35, classA, 12);
// within class B
assertShadow(findings, "fPackage", classB, 14, classA, 10);
assertShadow(findings, "fProtected", classB, 15, classA, 11);
assertShadow(findings, "fPublic", classB, 16, classA, 12);
// B.B()
assertShadow(findings, "fPrivate", classB, 19, classB, 13);
assertShadow(findings, "fPackage", classB, 20, classB, 14);
assertShadow(findings, "fProtected", classB, 21, classB, 15);
assertShadow(findings, "fPublic", classB, 22, classB, 16);
// B.foo()
assertShadow(findings, "fPrivate", classB, 26, classB, 13);
assertShadow(findings, "fPackage", classB, 27, classB, 14);
assertShadow(findings, "fProtected", classB, 28, classB, 15);
assertShadow(findings, "fPublic", classB, 29, classB, 16);
// B.bar()
assertShadow(findings, "fPrivate", classB, 32, classB, 13);
assertShadow(findings, "fPackage", classB, 33, classB, 14);
assertShadow(findings, "fProtected", classB, 34, classB, 15);
assertShadow(findings, "fPublic", classB, 35, classB, 16);
// within class C
// C.C()
assertShadow(findings, "fPackage", classC, 20, classA, 10);
assertShadow(findings, "fProtected", classC, 21, classA, 11);
assertShadow(findings, "fPublic", classC, 22, classA, 12);
// C.foo()
assertShadow(findings, "fPackage", classC, 27, classA, 10);
assertShadow(findings, "fProtected", classC, 28, classA, 11);
assertShadow(findings, "fPublic", classC, 29, classA, 12);
// C.bar()
assertShadow(findings, "fPackage", classC, 33, classA, 10);
assertShadow(findings, "fProtected", classC, 34, classA, 11);
assertShadow(findings, "fPublic", classC, 35, classA, 12);
// within class D
assertNotShadow(findings, "fPackage", classD, 20, classA, 10);
assertShadow(findings, "fProtected", classD, 15, classA, 11);
assertShadow(findings, "fPublic", classD, 16, classA, 12);
// D.D()
assertNotShadow(findings, "fPrivate", classD, 19, classA, 9); // true, but not helpful
assertNotShadow(findings, "fPackage", classD, 20, classA, 10); // true, but not helpful
assertShadow(findings, "fProtected", classD, 21, classD, 15);
assertShadow(findings, "fPublic", classD, 22, classD, 16);
// D.foo()
assertNotShadow(findings, "fPrivate", classD, 26, classA, 9); // true, but not helpful
assertNotShadow(findings, "fPackage", classD, 27, classA, 10); // true, but not helpful
assertShadow(findings, "fProtected", classD, 28, classD, 15);
assertShadow(findings, "fPublic", classD, 29, classD, 16);
// D.bar()
assertNotShadow(findings, "fPrivate", classD, 32, classA, 9); // true, but not helpful
assertNotShadow(findings, "fPackage", classD, 33, classA, 10); // true, but not helpful
assertShadow(findings, "fProtected", classD, 34, classD, 15);
assertShadow(findings, "fPublic", classD, 35, classD, 16);
// within class E
// E.E()
assertNotShadow(findings, "fPackage", classE, 20, classA, 10);
assertShadow(findings, "fProtected", classE, 21, classA, 11);
assertShadow(findings, "fPublic", classE, 22, classA, 12);
// E.foo()
assertNotShadow(findings, "fPackage", classE, 27, classA, 10);
assertShadow(findings, "fProtected", classE, 28, classA, 11);
assertShadow(findings, "fPublic", classE, 29, classA, 12);
// E.bar()
assertNotShadow(findings, "fPackage", classE, 33, classA, 14);
assertShadow(findings, "fProtected", classE, 34, classA, 11);
assertShadow(findings, "fPublic", classE, 35, classA, 12);
Assertions.assertEquals(56, findings.size());
}
}
package org.extendj;
import org.extendj.ast.AbstractFinding;
import org.extendj.ast.Declaration;
import org.extendj.ast.MultipleDeclarationFinding;
import org.extendj.ast.VariableShadowFinding;
import org.extendj.ast.*;
import org.junit.jupiter.api.Assertions;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Supplier;
public abstract class ScopeAnalysisTest {
static void assertShadow(Set<AbstractFinding> findings, String name, int shadowerLine, int shadowedLine) {
private static void assertShadow(Set<AbstractFinding> findings,
BiFunction<JavaDeclaration, JavaDeclaration, Boolean> test,
Supplier<String> failMessage) {
for (AbstractFinding finding : findings) {
if (finding instanceof VariableShadowFinding) {
Declaration shadower = ((VariableShadowFinding)finding).getShadower();
Declaration shadowed = ((VariableShadowFinding)finding).getShadowed();
if (shadowed.getName().equals(name) && shadowed.lineNumber() == shadowedLine && shadower.lineNumber() == shadowerLine) {
JavaDeclaration shadower = ((VariableShadowFinding)finding).getShadower().asJavaDeclaration();
JavaDeclaration shadowed = ((VariableShadowFinding)finding).getShadowed().asJavaDeclaration();
if (test.apply(shadower, shadowed)) {
return;
}
}
}
Assertions.fail("No shadow finding found for name '" + name + "' in lines " + shadowerLine + " > " + shadowedLine);
Assertions.fail(failMessage.get());
}
static void assertShadow(Set<AbstractFinding> findings, String name, String shadowerSourceFile, int shadowerLine, String shadowedSourceFile, int shadowedLine) {
assertShadow(findings,
(shadower, shadowed) ->
shadowed.getName().equals(name) &&
shadowed.sourceFile().contains(shadowedSourceFile) &&
shadowed.lineNumber() == shadowedLine &&
shadower.sourceFile().contains(shadowerSourceFile) &&
shadower.lineNumber() == shadowerLine,
() -> "No shadow finding found for name '" + name + "' in " +shadowerSourceFile + ":" + shadowerLine + " > " + shadowedSourceFile + ":" + shadowedLine);
}
static void assertRedefinition(Set<AbstractFinding> findings, String name, int declLine) {
......@@ -33,4 +45,13 @@ public abstract class ScopeAnalysisTest {
}
Assertions.fail("No multi-decl finding found for name '" + name + "' in line " + declLine);
}
static void assertNotShadow(Set<AbstractFinding> findings, String name, String shadowerSourceFile, int shadowerLine, String shadowedSourceFile, int shadowedLine) {
try {
assertShadow(findings, name, shadowerSourceFile, shadowerLine, shadowedSourceFile, shadowedLine);
} catch (AssertionError e) {
return;
}
Assertions.fail("There should not be a shadow finding for name '" + name + "' in " + shadowerSourceFile + ":" + shadowerLine + " > " + shadowedSourceFile + ":" + shadowedLine);
}
}
......@@ -12,18 +12,15 @@ public class SimpleScopeTest extends ScopeAnalysisTest {
void test() {
ScopeAnalysis scopeAnalysis = new ScopeAnalysis();
Set<AbstractFinding> findings = scopeAnalysis.analyze("src/test/resources/simple", false, false);
Set<AbstractFinding> findings = scopeAnalysis.analyze("src/test/resources/simple", true, false);
assertShadow(findings, "localVarA", "ClassA", 19, "ClassA", 11);
assertShadow(findings, "localVarB", "ClassA", 33, "ClassA", 12);
assertShadow(findings, "localVarC", "ClassA", 24, "ClassA", 13);
assertShadow(findings, "fieldA", "ClassA", 29, "ClassA", 3);
assertShadow(findings, "fieldB", "ClassA", 36, "ClassA", 4);
Assertions.assertEquals(5, findings.size());
assertShadow(findings, "localVarA", 19, 11);
assertShadow(findings, "localVarB", 33, 12);
assertShadow(findings, "localVarC", 24, 13);
assertShadow(findings, "fieldA", 29, 3);
assertShadow(findings, "fieldB", 36, 4);
}
}
......@@ -13,15 +13,14 @@ public class SuperclassFieldsTest extends ScopeAnalysisTest {
void test() {
ScopeAnalysis scopeAnalysis = new ScopeAnalysis();
Set<AbstractFinding> findings = scopeAnalysis.analyze("src/test/resources/superclassFields", true, false);
Set<AbstractFinding> findings = scopeAnalysis.analyze("src/test/resources/superclassFields", false, false);
assertShadow(findings, "fieldC", 19, 3);
assertShadow(findings, "fieldB", 21, 4);
assertRedefinition(findings, "fieldB", 2);
assertRedefinition(findings, "fieldB", 4);
assertShadow(findings, "fieldC", "ClassB", 19, "ClassB", 3);
assertShadow(findings, "fieldB", "ClassB", 21, "ClassB", 2);
assertShadow(findings, "fieldB", "ClassB", 2, "ClassA", 4);
Assertions.assertEquals(4, findings.size());
Assertions.assertEquals(3, findings.size());
}
......
public abstract class ClassA {
public int publicField;
protected int protectedField;
int packageField;
private int privateField;
void n(int parameter) {
int member;
{
int memberInBlock;
}
}
}
public abstract class ClassA {
int fieldA;
int fieldB;
abstract void toBeDefined();
void method1() {
ClassA anonymous = new ClassA() {
void toBeDefined() {
int fieldA = 11;
}
int fieldA = 1;
};
}
void method2() {
final int finalVar = 1;
int changingVar = 0;
changingVar = 1; // changingVar is not-final and not-effective-final, thus can not be used in InnerA
class InnerA extends ClassA {
/* This variable shares the name, but actually could never reference the outer scope
We include it anyway, because a) it would obscure analysis for this edge-case, and b) warns for potentially
unwanted effects (as all shadowing-warnings do) */
int changingVar = 4;
void toBeDefined() {
int fieldA = 21 + changingVar + finalVar;
}
int fieldA = 2;
}
ClassA inner = new InnerA();
}
static class StaticMemberClass extends ClassA {
int fieldA = 3;
void toBeDefined() {
int fieldA = 31;
}
}
class MemberClass extends ClassA {
int fieldA = 4;
void toBeDefined() {
int fieldA = 41;
}
}
}
public class ClassB {
void anonymousClassFromOtherSourceFile() {
ClassA anonymous = new ClassA() {
void toBeDefined() {
int fieldB = 11;
}
/* false-negative. there should be two scopes: ClassA and this method of ClassB
* But there is only the method, thus, not shadowing of ClassA.fieldB is detected. */
int fieldB = 1;
}
}
}
public class ClassA {
public int fieldA;
}
public class ClassB {
int fieldB;
class ClassC extends ClassA {
int fieldA;
int fieldB;
}
}
/*
As of https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html, an underscore shall be added to
avoid conflicts with Java keywords.
*/
package protected_.one;
public class ClassA {
private int fPrivate = 0;
int fPackage = 0;
protected int fProtected = 0;
public int fPublic = 0;
protected ClassA() {
int fPrivate = 1;
int fPackage = 1;
int fProtected = 1;
int fPublic = 1;
}
void foo() {
int fPrivate = 2;
int fPackage = 2;
int fProtected = 2;
int fPublic = 2;
}
void bar(int fPrivate,
int fPackage,
int fProtected,
int fPublic) {
// empty
}
}
/*
As of https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html, an underscore shall be added to
avoid conflicts with Java keywords.
*/
package protected_.one;
class ClassB extends ClassA {
private int fPrivate = 0;
int fPackage = 0;
protected int fProtected = 0;
public int fPublic = 0;
ClassB() {
int fPrivate = 1;
int fPackage = 1;
int fProtected = 1;
int fPublic = 1;
}
void foo() {
int fPrivate = 2;
int fPackage = 2;
int fProtected = 2;
int fPublic = 2;
}
void bar(int fPrivate,
int fPackage,
int fProtected,
int fPublic) {
// empty
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment