From 0b7e9e820c370e74c05b98e50759c4a911d901df Mon Sep 17 00:00:00 2001 From: Achal Talati Date: Wed, 19 Nov 2025 15:41:27 +0530 Subject: [PATCH] Fix invalid element references during completion resolution using ElementHandle which has additional text edits --- build.xml | 1 + patches/9005-draft.diff | 117 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 patches/9005-draft.diff diff --git a/build.xml b/build.xml index edf6999..a55df8e 100644 --- a/build.xml +++ b/build.xml @@ -74,6 +74,7 @@ patches/8974-draft.diff patches/8975.diff patches/8968.diff + patches/9005-draft.diff patches/disable-error-notification.diff patches/mvn-sh.diff patches/project-marker-jdk.diff diff --git a/patches/9005-draft.diff b/patches/9005-draft.diff new file mode 100644 index 0000000..79dc1aa --- /dev/null +++ b/patches/9005-draft.diff @@ -0,0 +1,117 @@ +diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionCollector.java b/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionCollector.java +index 83c9aa8bd5fe..b786b417e0a6 100644 +--- a/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionCollector.java ++++ b/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionCollector.java +@@ -549,6 +549,7 @@ public Completion createThisOrSuperConstructorItem(CompilationInfo info, Executa + @Override + public Completion createOverrideMethodItem(CompilationInfo info, ExecutableElement elem, ExecutableType type, int substitutionOffset, boolean implement) { + Completion item = createExecutableItem(info, elem, type, substitutionOffset, null, false, false, false, false, false, -1, false); ++ ElementHandle elemHandle = ElementHandle.create(elem); + CompletionCollector.Builder builder = CompletionCollector.newBuilder(item.getLabel()) + .kind(elementKind2CompletionItemKind(elem.getKind())) + .labelDetail(String.format("%s - %s", item.getLabelDetail(), implement ? "implement" : "override")) +@@ -558,16 +559,21 @@ public Completion createOverrideMethodItem(CompilationInfo info, ExecutableEleme + .textEdit(new TextEdit(substitutionOffset, substitutionOffset, EMPTY)) + .additionalTextEdits(() -> modify2TextEdits(JavaSource.forFileObject(info.getFileObject()), wc -> { + wc.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED); ++ ExecutableElement currentElem = elemHandle.resolve(wc); ++ if (currentElem == null) { ++ //cannot resolve? ++ return ; ++ } + TreePath tp = wc.getTreeUtilities().pathFor(substitutionOffset); + if (implement) { +- GeneratorUtils.generateAbstractMethodImplementation(wc, tp, elem, substitutionOffset); ++ GeneratorUtils.generateAbstractMethodImplementation(wc, tp, currentElem, substitutionOffset); + } else { +- GeneratorUtils.generateMethodOverride(wc, tp, elem, substitutionOffset); ++ GeneratorUtils.generateMethodOverride(wc, tp, currentElem, substitutionOffset); + } + })); +- ElementHandle handle = SUPPORTED_ELEMENT_KINDS.contains(elem.getKind().name()) ? ElementHandle.create(elem) : null; +- if (handle != null) { +- builder.documentation(getDocumentation(doc, offset, handle)); ++ ++ if (SUPPORTED_ELEMENT_KINDS.contains(elem.getKind().name())) { ++ builder.documentation(getDocumentation(doc, offset, elemHandle)); + } + return builder.build(); + } +@@ -593,6 +599,7 @@ public Completion createGetterSetterMethodItem(CompilationInfo info, VariableEle + sortParams.append(typeName); + } + labelDetail.append(") - generate"); ++ ElementHandle elemHandle = ElementHandle.create(elem); + Builder builder = CompletionCollector.newBuilder(name) + .kind(Completion.Kind.Method) + .labelDetail(labelDetail.toString()) +@@ -601,6 +608,10 @@ public Completion createGetterSetterMethodItem(CompilationInfo info, VariableEle + .textEdit(new TextEdit(substitutionOffset, substitutionOffset, EMPTY)) + .additionalTextEdits(() -> modify2TextEdits(JavaSource.forFileObject(info.getFileObject()), wc -> { + wc.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED); ++ VariableElement currentElem = elemHandle.resolve(wc); ++ if (currentElem == null) { ++ return; ++ } + TreePath tp = wc.getTreeUtilities().pathFor(substitutionOffset); + if (TreeUtilities.CLASS_TREE_KINDS.contains(tp.getLeaf().getKind())) { + if (Utilities.inAnonymousOrLocalClass(tp)) { +@@ -609,7 +620,7 @@ public Completion createGetterSetterMethodItem(CompilationInfo info, VariableEle + TypeElement te = (TypeElement)wc.getTrees().getElement(tp); + if (te != null) { + GeneratorUtilities gu = GeneratorUtilities.get(wc); +- MethodTree method = setter ? gu.createSetter(te, elem) : gu.createGetter(te, elem); ++ MethodTree method = setter ? gu.createSetter(te, currentElem) : gu.createGetter(te, currentElem); + ClassTree decl = GeneratorUtils.insertClassMember(wc, (ClassTree)tp.getLeaf(), method, substitutionOffset); + wc.rewrite(tp.getLeaf(), decl); + } +@@ -870,7 +881,13 @@ public Completion createInitializeAllConstructorItem(CompilationInfo info, boole + } + labelDetail.append(") - generate"); + sortParams.append(')'); +- ElementHandle parentPath = ElementHandle.create(parent); ++ ElementHandle parentHandle = ElementHandle.create(parent); ++ ElementHandle superConstructorHandle = superConstructor != null ? ElementHandle.create(superConstructor) : null; ++ List> fieldHandles = new ArrayList<>(); ++ for (VariableElement ve : fields) { ++ fieldHandles.add(ElementHandle.create(ve)); ++ } ++ + return CompletionCollector.newBuilder(simpleName) + .kind(Completion.Kind.Constructor) + .labelDetail(labelDetail.toString()) +@@ -879,23 +896,30 @@ public Completion createInitializeAllConstructorItem(CompilationInfo info, boole + .textEdit(new TextEdit(substitutionOffset, substitutionOffset, EMPTY)) + .additionalTextEdits(() -> modify2TextEdits(JavaSource.forFileObject(info.getFileObject()), wc -> { + wc.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED); ++ TypeElement currentParent = parentHandle.resolve(wc); ++ if (currentParent == null) { ++ return; ++ } ++ ExecutableElement currentSuperConstructor = superConstructorHandle != null ? superConstructorHandle.resolve(wc) : null; ++ + TreePath tp = wc.getTreeUtilities().pathFor(substitutionOffset); + if (TreeUtilities.CLASS_TREE_KINDS.contains(tp.getLeaf().getKind())) { + Element currentType = wc.getTrees().getElement(tp); + ElementHandle currentTypePath = + currentType != null ? ElementHandle.create(currentType) + : null; +- if (Objects.equals(parentPath, currentTypePath)) { ++ if (Objects.equals(parentHandle, currentTypePath)) { + ArrayList fieldElements = new ArrayList<>(); +- for (VariableElement fieldElement : fields) { ++ for (ElementHandle fieldHandle : fieldHandles) { ++ VariableElement fieldElement = fieldHandle.resolve(wc); + if (fieldElement != null && fieldElement.getKind().isField()) { + fieldElements.add((VariableElement)fieldElement); + } + } + ClassTree clazz = (ClassTree) tp.getLeaf(); + GeneratorUtilities gu = GeneratorUtilities.get(wc); +- MethodTree ctor = isDefault ? gu.createDefaultConstructor(parent, fieldElements, superConstructor) +- : gu.createConstructor(parent, fieldElements, superConstructor); ++ MethodTree ctor = isDefault ? gu.createDefaultConstructor(currentParent, fieldElements, currentSuperConstructor) ++ : gu.createConstructor(currentParent, fieldElements, currentSuperConstructor); + ClassTree decl = GeneratorUtils.insertClassMember(wc, clazz, ctor, substitutionOffset); + wc.rewrite(clazz, decl); + }