diff --git a/scope/src/main/jastadd/ScopeTree.relast b/scope/src/main/jastadd/ScopeTree.relast
index 8ed72413754ad3fc998ac9d0e6e0f6a0caa4e435..3da708098f1cdcc38ff9eb5e5470f2242883970c 100644
--- a/scope/src/main/jastadd/ScopeTree.relast
+++ b/scope/src/main/jastadd/ScopeTree.relast
@@ -2,3 +2,5 @@ ScopeTree : Scope;
 abstract Element;
 Declaration:Element ::= <Name:String>;
 Scope:Element ::= Element*;
+
+rel Scope.inheritedScope* -> Scope;
diff --git a/scope/src/main/jastadd/Shadowing.jrag b/scope/src/main/jastadd/Shadowing.jrag
index 3ca64528596533602746ca50763fdab9af416a3d..8bd777b431711d498044c13495e64978e5029b21 100644
--- a/scope/src/main/jastadd/Shadowing.jrag
+++ b/scope/src/main/jastadd/Shadowing.jrag
@@ -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 {
diff --git a/scope4j/src/main/jastadd/ProgramToScopeTree.jrag b/scope4j/src/main/jastadd/ProgramToScopeTree.jrag
index d472e0d0ad48cb60634988e101e6d5f60f314c5d..05b0ea10e0ac4f9eecbb2eff28c7c26ad21cbbb4 100644
--- a/scope4j/src/main/jastadd/ProgramToScopeTree.jrag
+++ b/scope4j/src/main/jastadd/ProgramToScopeTree.jrag
@@ -1,8 +1,38 @@
 aspect ProgramToScopeTree {
   /** a relational nta collection attribute to compute the scope tree */
-  coll ScopeTree Program.scopeTree() [asScopeTree()] with addElement root Program;
-  TypeDecl contributes scope() when !isClassDecl() to Program.scopeTree();
-  ClassDecl contributes protectedScope() when !isInnerType() && !superclass().compilationUnit().fromSource() to Program.scopeTree();
+  syn lazy ScopeTree Program.scopeTree() {
+    ScopeTree tree = asScopeTree();
+
+    // 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;
+  }
+
+  /** 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;
@@ -12,19 +42,8 @@ aspect ProgramToScopeTree {
   coll TypeDeclScope ClassDecl.packageScope() [asPackageScope()] with addElement root Program;
 
   // collect all scopes
-  TypeDecl contributes scope() when !isClassDecl() to ASTNode.scope() for containingScope();
-  ClassDecl contributes protectedScope()
-      when !(!isInnerClass() && superclass().isClassDecl() && superclass().compilationUnit().fromSource())
-      to ASTNode.scope()
-      for containingScope();
-  ClassDecl contributes protectedScope()
-      when !isInnerClass() && superclass().isClassDecl() && superclass().compilationUnit().fromSource() && !hostPackage().equals(superclass().hostPackage())
-      to ClassDecl.protectedScope()
-      for superclass();
-  ClassDecl contributes protectedScope()
-      when !isInnerClass() && superclass().isClassDecl() && superclass().compilationUnit().fromSource() &&  hostPackage().equals(superclass().hostPackage())
-      to ClassDecl.packageScope()
-      for superclass();
+  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();
@@ -39,9 +58,8 @@ aspect ProgramToScopeTree {
 }
 
 /**
- * ascpect containing helper methods to construct (mostly empty) AST nodes of the scope tree
- * If it was not for the single line in asProtectedScope(), the rest of this aspect could have been generated
- *  automatically, which would have been much nicer!
+ * 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 {
 
@@ -62,19 +80,21 @@ aspect ScopeTreeConstructors {
     return scope;
   }
 
+  syn lazy TypeDeclScope ClassDecl.asScope() {
+    TypeDeclScope scope = new PrivateClassDeclScope();
+    scope.setTypeDecl(this);
+    return scope;
+  }
+
   syn lazy TypeDeclScope ClassDecl.asProtectedScope() {
-    TypeDeclScope scope = new TypeDeclScope();
+    TypeDeclScope scope = new ProtectedClassDeclScope();
     scope.setTypeDecl(this);
-    scope.addElement(packageScope()); // this irregular statement is necessary because of either a bug or a limitation in JastAdd collections
+    scope.addElement(packageScope());
     return scope;
   }
-  // the following commented statement unfortunately does not work, because during the contribution phase, the information
-  // which target should be contributed to is lost if there are multiple targets. Maybe I got it wrong, but I tried many things
-  // and JastAdd always wants to also add the contribution made in line 17ff to this target as well.
-  // ClassDecl contributes scope() to ClassDecl.protectedScope() for this;
 
   syn lazy TypeDeclScope ClassDecl.asPackageScope() {
-    TypeDeclScope scope = new TypeDeclScope();
+    TypeDeclScope scope = new PackageClassDeclScope();
     scope.setTypeDecl(this);
     scope.addElement(scope());
     return scope;
diff --git a/scope4j/src/main/jastadd/ProgramToScopeTree.relast b/scope4j/src/main/jastadd/ProgramToScopeTree.relast
index ef201525f26bee91ac385a13f75ff7e9ff1abe56..6d6cbf9ac7e4fd65a6df12cb675bda9a46fc1e73 100644
--- a/scope4j/src/main/jastadd/ProgramToScopeTree.relast
+++ b/scope4j/src/main/jastadd/ProgramToScopeTree.relast
@@ -5,6 +5,10 @@ abstract JavaScope : Scope;
 TypeDeclScope : JavaScope;
 rel TypeDeclScope.typeDecl -> TypeDecl;
 
+ProtectedClassDeclScope : TypeDeclScope;
+PackageClassDeclScope : TypeDeclScope;
+PrivateClassDeclScope : TypeDeclScope;
+
 BlockScope : JavaScope;
 rel BlockScope.block -> Block;
 
diff --git a/scope4j/src/test/java/org/extendj/InnerInheritanceTest.java b/scope4j/src/test/java/org/extendj/InnerInheritanceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b983b028001dee0f0d863e3bcd09098746042885
--- /dev/null
+++ b/scope4j/src/test/java/org/extendj/InnerInheritanceTest.java
@@ -0,0 +1,23 @@
+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());
+  }
+
+}
diff --git a/scope4j/src/test/java/org/extendj/InnerTest.java b/scope4j/src/test/java/org/extendj/InnerTest.java
index f07851f479bd3ca8711604597377be973c8a6f7e..d0ee15f843447579d5eb695ce68ed11f7150d9d9 100644
--- a/scope4j/src/test/java/org/extendj/InnerTest.java
+++ b/scope4j/src/test/java/org/extendj/InnerTest.java
@@ -35,10 +35,12 @@ public class InnerTest extends ScopeAnalysisTest {
 
     // anonymous class defined in other class
     assertShadow(findings, "fieldB", "ClassB", 5, "ClassB", 10);
-    // this finding is currently not found
-//    assertShadow(findings, "fieldB", 10, 4);
 
-    Assertions.assertEquals(10, findings.size());
+    // the anonymous class inherited a field
+    assertShadow(findings, "fieldB", "ClassB", 10, "ClassA", 4);
+
+
+    Assertions.assertEquals(11, findings.size());
   }
 
 }
diff --git a/scope4j/src/test/resources/innerInheritance/ClassA.java b/scope4j/src/test/resources/innerInheritance/ClassA.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc019b729a24c59a2ab1b747b04173e969e941cc
--- /dev/null
+++ b/scope4j/src/test/resources/innerInheritance/ClassA.java
@@ -0,0 +1,5 @@
+public class ClassA {
+
+  public int fieldA;
+
+}
diff --git a/scope4j/src/test/resources/innerInheritance/ClassB.java b/scope4j/src/test/resources/innerInheritance/ClassB.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f6755e216ec6b0780045d210e71bee8655e4a41
--- /dev/null
+++ b/scope4j/src/test/resources/innerInheritance/ClassB.java
@@ -0,0 +1,9 @@
+public class ClassB {
+
+  int fieldB;
+
+  class ClassC extends ClassA {
+    int fieldA;
+    int fieldB;
+  }
+}