diff --git a/scope4j/src/main/jastadd/ProgramToScopeTree.jrag b/scope4j/src/main/jastadd/ProgramToScopeTree.jrag
index 20955beb656d2e069117ebe68a13a1522aa5c377..6bd575cb2424d020b5ad12ce170e64eca288d3f6 100644
--- a/scope4j/src/main/jastadd/ProgramToScopeTree.jrag
+++ b/scope4j/src/main/jastadd/ProgramToScopeTree.jrag
@@ -83,8 +83,8 @@ aspect ScopeTreeConstructors {
     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;
   }
diff --git a/scope4j/src/main/jastadd/ProgramToScopeTree.relast b/scope4j/src/main/jastadd/ProgramToScopeTree.relast
index a1d84e0153fe227e592e61c3a456e9553462c79e..ef201525f26bee91ac385a13f75ff7e9ff1abe56 100644
--- a/scope4j/src/main/jastadd/ProgramToScopeTree.relast
+++ b/scope4j/src/main/jastadd/ProgramToScopeTree.relast
@@ -1,23 +1,25 @@
 // 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;
+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;
diff --git a/scope4j/src/main/jastadd/Shadow.jadd b/scope4j/src/main/jastadd/Shadow.jadd
index 644a178f4dba9057f6ab1617f8360e82b6f8f493..0caf2f5f46964f4fa319576dbe5c50e2ca074fe3 100644
--- a/scope4j/src/main/jastadd/Shadow.jadd
+++ b/scope4j/src/main/jastadd/Shadow.jadd
@@ -1,55 +1,37 @@
 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;
 }
diff --git a/scope4j/src/test/java/org/extendj/ScopeAnalysisTest.java b/scope4j/src/test/java/org/extendj/ScopeAnalysisTest.java
index 95d479ce7b90b3d7deb7684ea36c07c3dba1777a..32936e35476af347224087c70d4ec66e07ca0090 100644
--- a/scope4j/src/test/java/org/extendj/ScopeAnalysisTest.java
+++ b/scope4j/src/test/java/org/extendj/ScopeAnalysisTest.java
@@ -1,25 +1,46 @@
 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, int shadowerLine, int shadowedLine) {
+    assertShadow(findings,
+        (shadower, shadowed) ->
+            shadowed.getName().equals(name) &&
+                shadowed.lineNumber() == shadowedLine &&
+                shadower.lineNumber() == shadowerLine,
+        () -> "No shadow finding found for name '" + name + "' in lines " + shadowerLine + " > " + shadowedLine);
+  }
+
+  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().equals(shadowedSourceFile) &&
+                shadowed.lineNumber() == shadowedLine &&
+                shadower.sourceFile().equals(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 +54,22 @@ 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, int shadowerLine, int shadowedLine) {
+    try {
+      assertShadow(findings, name, shadowerLine, shadowedLine);
+    } catch (AssertionError e) {
+      return;
+    }
+    Assertions.fail("There should not be a shadow finding for name '" + name + "' in lines " + shadowerLine + " > " + shadowedLine);
+  }
+
+  static void assertNotShadow(Set<AbstractFinding> findings, String name, String shadowerSourceFile, int shadowerLine, String shadowedSourceFile, int shadowedLine) {
+    try {
+      assertShadow(findings, name, shadowerLine, shadowedLine);
+    } catch (AssertionError e) {
+      return;
+    }
+    Assertions.fail("There should not be a shadow finding for name '" + name + "' in " + shadowerSourceFile + ":" + shadowerLine + " > " + shadowedSourceFile + ":" + shadowedLine);
+  }
 }