Private members are never inherited, and package-private members are only sometimes inherited, the Java import analysis needs to account for that.
diff --git a/java/java.source.base/src/org/netbeans/modules/java/source/pretty/ImportAnalysis2.java b/java/java.source.base/src/org/netbeans/modules/java/source/pretty/ImportAnalysis2.java
index 1119a4c..8eb0641 100644
--- a/java/java.source.base/src/org/netbeans/modules/java/source/pretty/ImportAnalysis2.java
+++ b/java/java.source.base/src/org/netbeans/modules/java/source/pretty/ImportAnalysis2.java
@@ -187,7 +187,7 @@
 
     public void enterVisibleThroughClasses(ClassTree clazz) {
         Set<Element> visible = visibleThroughClasses.getFirst();
-        visible.addAll(overlay.getAllVisibleThrough(model, elements, currentFQN.getFQN(), clazz, modle));
+        visible.addAll(overlay.getAllVisibleThrough(model, elements, currentFQN.getFQN(), clazz, pack, modle));
     }
 
     public void classLeft() {
@@ -367,7 +367,7 @@
             return make.Identifier(element.getSimpleName());
         }
 
-        if (getPackageOf(element) != null && getPackageOf(element).isUnnamed()) {
+        if (overlay.packageOf(element) != null && overlay.packageOf(element).isUnnamed()) {
             if (orig.getExpression().getKind() == Kind.MEMBER_SELECT) {
                 return make.MemberSelect(resolveImport((MemberSelectTree) orig.getExpression(), element.getEnclosingElement()),
                                          element.getSimpleName());
@@ -452,12 +452,6 @@
         return false;
     }
 
-    private PackageElement getPackageOf(Element el) {
-        while ((el != null) && (el.getKind() != ElementKind.PACKAGE)) el = el.getEnclosingElement();
-
-        return (PackageElement) el;
-    }
-
     private Map<String, Element> getUsedImplicitlyImportedClasses() {
         if (usedImplicitlyImportedClassesCache != null) {
             return usedImplicitlyImportedClassesCache;
diff --git a/java/java.source.base/src/org/netbeans/modules/java/source/save/ElementOverlay.java b/java/java.source.base/src/org/netbeans/modules/java/source/save/ElementOverlay.java
index 7692df5..3d992c0 100644
--- a/java/java.source.base/src/org/netbeans/modules/java/source/save/ElementOverlay.java
+++ b/java/java.source.base/src/org/netbeans/modules/java/source/save/ElementOverlay.java
@@ -389,7 +389,7 @@
                this.packages.size();
     }
 
-    public Collection<? extends Element> getAllVisibleThrough(ASTService ast, Elements elements, String what, ClassTree tree, ModuleElement modle) {
+    public Collection<? extends Element> getAllVisibleThrough(ASTService ast, Elements elements, String what, ClassTree tree, Element currentPackage, ModuleElement modle) {
         Collection<Element> result = new ArrayList<Element>();
         Element current = what != null ? resolve(ast, elements, what, modle) : null;
 
@@ -408,30 +408,50 @@
                 }
             }
         } else {
-            result.addAll(getAllMembers(ast, elements, current));
+            result.addAll(getAllMembers(ast, elements, current, currentPackage, false));
         }
 
         return result;
     }
 
-    private Collection<? extends Element> getAllMembers(ASTService ast, Elements elements, Element el) {
+    private Collection<? extends Element> getAllMembers(ASTService ast, Elements elements, Element el, Element currentPackage, boolean inherited) {
         List<Element> result = new ArrayList<Element>();
 
-        result.addAll(el.getEnclosedElements());
+        el.getEnclosedElements()
+          .stream()
+          .filter(encl -> !inherited || //include all members from the current class
+                          encl.getModifiers().contains(Modifier.PUBLIC) || //public members are inherited
+                          encl.getModifiers().contains(Modifier.PROTECTED) || //protected memebers are inherited
+                          (!encl.getModifiers().contains(Modifier.PRIVATE) && //private member are never inherited
+                           resolvedPackageOf(ast, elements, encl) == currentPackage)) //package-private members are inherited only inside the same package
+          .forEach(result::add);
 
         for (Element parent : getAllSuperElements(ast, elements, el)) {
             if (!el.equals(parent)) {
-                result.addAll(getAllMembers(ast, elements, parent));
+                result.addAll(getAllMembers(ast, elements, parent, currentPackage, true));
             }
         }
 
         return result;
     }
 
+    private Element resolvedPackageOf(ASTService ast, Elements elements, Element el) {
+        ModuleElement modle = moduleOf(elements, el);
+        PackageElement pack = packageOf(el);
+
+        return resolve(ast, elements, pack.getQualifiedName().toString(), modle);
+    }
+
     public PackageElement unnamedPackage(ASTService ast, Elements elements, ModuleElement modle) {
         return (PackageElement) resolve(ast, elements, "", modle);
     }
     
+    public PackageElement packageOf(Element el) {
+        while ((el != null) && (el.getKind() != ElementKind.PACKAGE)) el = el.getEnclosingElement();
+
+        return (PackageElement) el;
+    }
+
     public ModuleElement moduleOf(Elements elements, Element el) {
         if (el instanceof TypeElementWrapper)
             return moduleOf(elements, ((TypeElementWrapper) el).delegateTo);
diff --git a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/ImportAnalysis2Test.java b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/ImportAnalysis2Test.java
index 3671dbc..9bd4c9a 100644
--- a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/ImportAnalysis2Test.java
+++ b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/ImportAnalysis2Test.java
@@ -1577,6 +1577,354 @@
         assertEquals(golden, res);
     }
 
+    public void testVisibleThroughClassesPrivateNotInherited() throws Exception {
+        beginTx();
+        File testA = new File(getWorkDir(), "api/A.java");
+        assertTrue(testA.getParentFile().mkdirs());
+        TestUtilities.copyStringToFile(testA,
+            """
+            package api;
+            public class A {
+                public static void test() {}
+                public static void test(int i) {}
+            }
+            """
+            );
+        testFile = new File(getWorkDir(), "hierbas/del/litoral/Test.java");
+        assertTrue(testFile.getParentFile().mkdirs());
+        TestUtilities.copyStringToFile(testFile,
+                """
+                package hierbas.del.litoral;
+                import static api.A.*;
+                public class Test extends Base {
+                    public static void t() {
+                    }
+                }
+                class Base {
+                    private static void test() {}
+                    private static void test(int i) {}
+                }
+                """
+            );
+        String golden =
+            """
+            package hierbas.del.litoral;
+            import static api.A.*;
+            public class Test extends Base {
+                public static void t() {
+                    test();
+                    test(1);
+                }
+            }
+            class Base {
+                private static void test() {}
+                private static void test(int i) {}
+            }
+            """;
+
+        ClasspathInfo cpInfo = ClasspathInfoAccessor.getINSTANCE().create (BootClassPathUtil.getBootClassPath(), ClassPath.EMPTY, ClassPath.EMPTY, ClassPath.EMPTY, ClassPath.EMPTY, ClassPathSupport.createClassPath(getSourcePath()), ClassPath.EMPTY, null, true, false, false, true, false, null);
+        JavaSource src = JavaSource.create(cpInfo, FileUtil.toFileObject(testFile));
+        Task<WorkingCopy> task = new Task<WorkingCopy>() {
+
+            public void run(WorkingCopy workingCopy) throws IOException {
+                workingCopy.toPhase(Phase.RESOLVED);
+                TreeMaker make = workingCopy.getTreeMaker();
+                ClassTree clazz = (ClassTree) workingCopy.getCompilationUnit().getTypeDecls().get(0);
+                MethodTree testMethodDeclaration = (MethodTree) clazz.getMembers().get(1);
+                TypeElement aClass = workingCopy.getElements().getTypeElement("api.A");
+                ExecutableElement testMethod = aClass.getEnclosedElements().stream().filter(el -> el.getKind() == ElementKind.METHOD).map(el -> ((ExecutableElement) el)).filter(el -> el.getSimpleName().contentEquals("test") && el.getParameters().isEmpty()).findAny().orElseThrow();
+                MethodInvocationTree invocation1 = make.MethodInvocation(List.of(), make.QualIdent(testMethod), List.of());
+                ExecutableElement testMethod2 = aClass.getEnclosedElements().stream().filter(el -> el.getKind() == ElementKind.METHOD).map(el -> ((ExecutableElement) el)).filter(el -> el.getSimpleName().contentEquals("test") && el.getParameters().size() == 1).findAny().orElseThrow();
+                MethodInvocationTree invocation2 = make.MethodInvocation(List.of(), make.QualIdent(testMethod2), List.of(make.Literal(1)));
+                workingCopy.rewrite(testMethodDeclaration.getBody(), make.addBlockStatement(make.addBlockStatement(testMethodDeclaration.getBody(), make.ExpressionStatement(invocation1)), make.ExpressionStatement(invocation2)));
+            }
+
+        };
+        src.runModificationTask(task).commit();
+        String res = TestUtilities.copyFileToString(testFile);
+        //System.err.println(res);
+        assertEquals(golden, res);
+    }
+
+    public void testVisibleThroughClassesPackageNotInherited() throws Exception {
+        beginTx();
+        File testA = new File(getWorkDir(), "api/A.java");
+        assertTrue(testA.getParentFile().mkdirs());
+        TestUtilities.copyStringToFile(testA,
+            """
+            package api;
+            public class A {
+                public static void test() {}
+                public static void test(int i) {}
+            }
+            """
+            );
+        File testB = new File(getWorkDir(), "api/B.java");
+        TestUtilities.copyStringToFile(testB,
+            """
+            package api;
+            public class B {
+                static void test() {}
+                static void test(int i) {}
+            }
+            """
+            );
+        testFile = new File(getWorkDir(), "hierbas/del/litoral/Test.java");
+        assertTrue(testFile.getParentFile().mkdirs());
+        TestUtilities.copyStringToFile(testFile,
+                """
+                package hierbas.del.litoral;
+                import static api.A.*;
+                public class Test extends api.B {
+                    public static void t() {
+                    }
+                }
+                """
+            );
+        String golden =
+            """
+            package hierbas.del.litoral;
+            import static api.A.*;
+            public class Test extends api.B {
+                public static void t() {
+                    test();
+                    test(1);
+                }
+            }
+            """;
+
+        ClasspathInfo cpInfo = ClasspathInfoAccessor.getINSTANCE().create (BootClassPathUtil.getBootClassPath(), ClassPath.EMPTY, ClassPath.EMPTY, ClassPath.EMPTY, ClassPath.EMPTY, ClassPathSupport.createClassPath(getSourcePath()), ClassPath.EMPTY, null, true, false, false, true, false, null);
+        JavaSource src = JavaSource.create(cpInfo, FileUtil.toFileObject(testFile));
+        Task<WorkingCopy> task = new Task<WorkingCopy>() {
+
+            public void run(WorkingCopy workingCopy) throws IOException {
+                workingCopy.toPhase(Phase.RESOLVED);
+                TreeMaker make = workingCopy.getTreeMaker();
+                ClassTree clazz = (ClassTree) workingCopy.getCompilationUnit().getTypeDecls().get(0);
+                MethodTree testMethodDeclaration = (MethodTree) clazz.getMembers().get(1);
+                TypeElement aClass = workingCopy.getElements().getTypeElement("api.A");
+                ExecutableElement testMethod = aClass.getEnclosedElements().stream().filter(el -> el.getKind() == ElementKind.METHOD).map(el -> ((ExecutableElement) el)).filter(el -> el.getSimpleName().contentEquals("test") && el.getParameters().isEmpty()).findAny().orElseThrow();
+                MethodInvocationTree invocation1 = make.MethodInvocation(List.of(), make.QualIdent(testMethod), List.of());
+                ExecutableElement testMethod2 = aClass.getEnclosedElements().stream().filter(el -> el.getKind() == ElementKind.METHOD).map(el -> ((ExecutableElement) el)).filter(el -> el.getSimpleName().contentEquals("test") && el.getParameters().size() == 1).findAny().orElseThrow();
+                MethodInvocationTree invocation2 = make.MethodInvocation(List.of(), make.QualIdent(testMethod2), List.of(make.Literal(1)));
+                workingCopy.rewrite(testMethodDeclaration.getBody(), make.addBlockStatement(make.addBlockStatement(testMethodDeclaration.getBody(), make.ExpressionStatement(invocation1)), make.ExpressionStatement(invocation2)));
+            }
+
+        };
+        src.runModificationTask(task).commit();
+        String res = TestUtilities.copyFileToString(testFile);
+        //System.err.println(res);
+        assertEquals(golden, res);
+    }
+
+    public void testVisibleThroughClassesPackageInherited() throws Exception {
+        beginTx();
+        File testA = new File(getWorkDir(), "api/A.java");
+        assertTrue(testA.getParentFile().mkdirs());
+        TestUtilities.copyStringToFile(testA,
+            """
+            package api;
+            public class A {
+                public static void test() {}
+                public static void test(int i) {}
+            }
+            """
+            );
+        testFile = new File(getWorkDir(), "hierbas/del/litoral/Test.java");
+        assertTrue(testFile.getParentFile().mkdirs());
+        TestUtilities.copyStringToFile(testFile,
+                """
+                package hierbas.del.litoral;
+                import static api.A.*;
+                public class Test extends Base {
+                    public static void t() {
+                    }
+                }
+                class Base {
+                    static void test() {}
+                    static void test(int i) {}
+                }
+                """
+            );
+        String golden =
+            """
+            package hierbas.del.litoral;
+            import api.A;
+            import static api.A.*;
+            public class Test extends Base {
+                public static void t() {
+                    A.test();
+                    A.test(1);
+                }
+            }
+            class Base {
+                static void test() {}
+                static void test(int i) {}
+            }
+            """;
+
+        ClasspathInfo cpInfo = ClasspathInfoAccessor.getINSTANCE().create (BootClassPathUtil.getBootClassPath(), ClassPath.EMPTY, ClassPath.EMPTY, ClassPath.EMPTY, ClassPath.EMPTY, ClassPathSupport.createClassPath(getSourcePath()), ClassPath.EMPTY, null, true, false, false, true, false, null);
+        JavaSource src = JavaSource.create(cpInfo, FileUtil.toFileObject(testFile));
+        Task<WorkingCopy> task = new Task<WorkingCopy>() {
+
+            public void run(WorkingCopy workingCopy) throws IOException {
+                workingCopy.toPhase(Phase.RESOLVED);
+                TreeMaker make = workingCopy.getTreeMaker();
+                ClassTree clazz = (ClassTree) workingCopy.getCompilationUnit().getTypeDecls().get(0);
+                MethodTree testMethodDeclaration = (MethodTree) clazz.getMembers().get(1);
+                TypeElement aClass = workingCopy.getElements().getTypeElement("api.A");
+                ExecutableElement testMethod = aClass.getEnclosedElements().stream().filter(el -> el.getKind() == ElementKind.METHOD).map(el -> ((ExecutableElement) el)).filter(el -> el.getSimpleName().contentEquals("test") && el.getParameters().isEmpty()).findAny().orElseThrow();
+                MethodInvocationTree invocation1 = make.MethodInvocation(List.of(), make.QualIdent(testMethod), List.of());
+                ExecutableElement testMethod2 = aClass.getEnclosedElements().stream().filter(el -> el.getKind() == ElementKind.METHOD).map(el -> ((ExecutableElement) el)).filter(el -> el.getSimpleName().contentEquals("test") && el.getParameters().size() == 1).findAny().orElseThrow();
+                MethodInvocationTree invocation2 = make.MethodInvocation(List.of(), make.QualIdent(testMethod2), List.of(make.Literal(1)));
+                workingCopy.rewrite(testMethodDeclaration.getBody(), make.addBlockStatement(make.addBlockStatement(testMethodDeclaration.getBody(), make.ExpressionStatement(invocation1)), make.ExpressionStatement(invocation2)));
+            }
+
+        };
+        src.runModificationTask(task).commit();
+        String res = TestUtilities.copyFileToString(testFile);
+        //System.err.println(res);
+        assertEquals(golden, res);
+    }
+
+    public void testVisibleThroughClassesProtectedPublicInherited() throws Exception {
+        beginTx();
+        File testA = new File(getWorkDir(), "api/A.java");
+        assertTrue(testA.getParentFile().mkdirs());
+        TestUtilities.copyStringToFile(testA,
+            """
+            package api;
+            public class A {
+                public static void test() {}
+                public static void test(int i) {}
+            }
+            """
+            );
+        File testB = new File(getWorkDir(), "api/B.java");
+        TestUtilities.copyStringToFile(testB,
+            """
+            package api;
+            public class B {
+                protected static void test() {}
+                public static void test(int i) {}
+            }
+            """
+            );
+        testFile = new File(getWorkDir(), "hierbas/del/litoral/Test.java");
+        assertTrue(testFile.getParentFile().mkdirs());
+        TestUtilities.copyStringToFile(testFile,
+                """
+                package hierbas.del.litoral;
+                import static api.A.*;
+                public class Test extends api.B {
+                    public static void t() {
+                    }
+                }
+                """
+            );
+        String golden =
+            """
+            package hierbas.del.litoral;
+            import api.A;
+            import static api.A.*;
+            public class Test extends api.B {
+                public static void t() {
+                    A.test();
+                    A.test(1);
+                }
+            }
+            """;
+
+        ClasspathInfo cpInfo = ClasspathInfoAccessor.getINSTANCE().create (BootClassPathUtil.getBootClassPath(), ClassPath.EMPTY, ClassPath.EMPTY, ClassPath.EMPTY, ClassPath.EMPTY, ClassPathSupport.createClassPath(getSourcePath()), ClassPath.EMPTY, null, true, false, false, true, false, null);
+        JavaSource src = JavaSource.create(cpInfo, FileUtil.toFileObject(testFile));
+        Task<WorkingCopy> task = new Task<WorkingCopy>() {
+
+            public void run(WorkingCopy workingCopy) throws IOException {
+                workingCopy.toPhase(Phase.RESOLVED);
+                TreeMaker make = workingCopy.getTreeMaker();
+                ClassTree clazz = (ClassTree) workingCopy.getCompilationUnit().getTypeDecls().get(0);
+                MethodTree testMethodDeclaration = (MethodTree) clazz.getMembers().get(1);
+                TypeElement aClass = workingCopy.getElements().getTypeElement("api.A");
+                ExecutableElement testMethod = aClass.getEnclosedElements().stream().filter(el -> el.getKind() == ElementKind.METHOD).map(el -> ((ExecutableElement) el)).filter(el -> el.getSimpleName().contentEquals("test") && el.getParameters().isEmpty()).findAny().orElseThrow();
+                MethodInvocationTree invocation1 = make.MethodInvocation(List.of(), make.QualIdent(testMethod), List.of());
+                ExecutableElement testMethod2 = aClass.getEnclosedElements().stream().filter(el -> el.getKind() == ElementKind.METHOD).map(el -> ((ExecutableElement) el)).filter(el -> el.getSimpleName().contentEquals("test") && el.getParameters().size() == 1).findAny().orElseThrow();
+                MethodInvocationTree invocation2 = make.MethodInvocation(List.of(), make.QualIdent(testMethod2), List.of(make.Literal(1)));
+                workingCopy.rewrite(testMethodDeclaration.getBody(), make.addBlockStatement(make.addBlockStatement(testMethodDeclaration.getBody(), make.ExpressionStatement(invocation1)), make.ExpressionStatement(invocation2)));
+            }
+
+        };
+        src.runModificationTask(task).commit();
+        String res = TestUtilities.copyFileToString(testFile);
+        //System.err.println(res);
+        assertEquals(golden, res);
+    }
+
+    public void testVisibleThroughClassesCurrentClassPrivate() throws Exception {
+        beginTx();
+        File testA = new File(getWorkDir(), "api/A.java");
+        assertTrue(testA.getParentFile().mkdirs());
+        TestUtilities.copyStringToFile(testA,
+            """
+            package api;
+            public class A {
+                public static void test() {}
+                public static void test(int i) {}
+            }
+            """
+            );
+        testFile = new File(getWorkDir(), "hierbas/del/litoral/Test.java");
+        assertTrue(testFile.getParentFile().mkdirs());
+        TestUtilities.copyStringToFile(testFile,
+                """
+                package hierbas.del.litoral;
+                import static api.A.*;
+                public class Test extends api.B {
+                    public static void t() {
+                    }
+                    private static void test() {}
+                    private static void test(int i) {}
+                }
+                """
+            );
+        String golden =
+            """
+            package hierbas.del.litoral;
+            import api.A;
+            import static api.A.*;
+            public class Test extends api.B {
+                public static void t() {
+                    A.test();
+                    A.test(1);
+                }
+                private static void test() {}
+                private static void test(int i) {}
+            }
+            """;
+
+        ClasspathInfo cpInfo = ClasspathInfoAccessor.getINSTANCE().create (BootClassPathUtil.getBootClassPath(), ClassPath.EMPTY, ClassPath.EMPTY, ClassPath.EMPTY, ClassPath.EMPTY, ClassPathSupport.createClassPath(getSourcePath()), ClassPath.EMPTY, null, true, false, false, true, false, null);
+        JavaSource src = JavaSource.create(cpInfo, FileUtil.toFileObject(testFile));
+        Task<WorkingCopy> task = new Task<WorkingCopy>() {
+
+            public void run(WorkingCopy workingCopy) throws IOException {
+                workingCopy.toPhase(Phase.RESOLVED);
+                TreeMaker make = workingCopy.getTreeMaker();
+                ClassTree clazz = (ClassTree) workingCopy.getCompilationUnit().getTypeDecls().get(0);
+                MethodTree testMethodDeclaration = (MethodTree) clazz.getMembers().get(1);
+                TypeElement aClass = workingCopy.getElements().getTypeElement("api.A");
+                ExecutableElement testMethod = aClass.getEnclosedElements().stream().filter(el -> el.getKind() == ElementKind.METHOD).map(el -> ((ExecutableElement) el)).filter(el -> el.getSimpleName().contentEquals("test") && el.getParameters().isEmpty()).findAny().orElseThrow();
+                MethodInvocationTree invocation1 = make.MethodInvocation(List.of(), make.QualIdent(testMethod), List.of());
+                ExecutableElement testMethod2 = aClass.getEnclosedElements().stream().filter(el -> el.getKind() == ElementKind.METHOD).map(el -> ((ExecutableElement) el)).filter(el -> el.getSimpleName().contentEquals("test") && el.getParameters().size() == 1).findAny().orElseThrow();
+                MethodInvocationTree invocation2 = make.MethodInvocation(List.of(), make.QualIdent(testMethod2), List.of(make.Literal(1)));
+                workingCopy.rewrite(testMethodDeclaration.getBody(), make.addBlockStatement(make.addBlockStatement(testMethodDeclaration.getBody(), make.ExpressionStatement(invocation1)), make.ExpressionStatement(invocation2)));
+            }
+
+        };
+        src.runModificationTask(task).commit();
+        String res = TestUtilities.copyFileToString(testFile);
+        //System.err.println(res);
+        assertEquals(golden, res);
+    }
+
     //TODO: non-public classes not imported by module imports!
 
     String getGoldenPckg() {