From 1f91cb4829deabb6ed216a155371428cfaf7c488 Mon Sep 17 00:00:00 2001 From: Toine Hartman Date: Thu, 17 Apr 2025 13:51:36 +0200 Subject: [PATCH 1/5] Improve handling of ignored modules. --- .../main/rascal/lsp/lang/rascal/lsp/refactor/Rename.rsc | 9 ++++++++- .../rascal/lsp/lang/rascal/tests/rename/Performance.rsc | 7 +++++++ .../rascal/lsp/lang/rascal/tests/rename/TestUtils.rsc | 8 ++++---- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/Rename.rsc b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/Rename.rsc index 4044a098c..d52eb1aba 100644 --- a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/Rename.rsc +++ b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/Rename.rsc @@ -244,7 +244,14 @@ public Edits rascalRenameSymbol(loc cursorLoc, list[Tree] cursor, str newName, s ms = rascalTModelForNames([mname], ccfg, dummy_compile1); = getTModelForModule(mname, ms); - if (!found) throw "No TModel for module \'\'"; + if (!found) { + if (ms.status[mname]?) { + // If a module is annotated with `@ignoreCompiler`, silently skip it + if (MStatus::ignored() in ms.status[mname]) return tmodel(); + throw "No TModel for module \'\'"; + } + throw "No TModel for module \'\'"; + } return tm; } diff --git a/rascal-lsp/src/main/rascal/lsp/lang/rascal/tests/rename/Performance.rsc b/rascal-lsp/src/main/rascal/lsp/lang/rascal/tests/rename/Performance.rsc index a54d1a8ce..f5f99b41b 100644 --- a/rascal-lsp/src/main/rascal/lsp/lang/rascal/tests/rename/Performance.rsc +++ b/rascal-lsp/src/main/rascal/lsp/lang/rascal/tests/rename/Performance.rsc @@ -77,3 +77,10 @@ test bool incrementalTypeCheck() { remove(procLoc); return res; } + +test bool ignoredModule() = testRenameOccurrences({ + byText("Ignored", " + 'import Main; + 'int quz() = foo();", {}, annotations = "@ignoreCompiler{For test purposes.}"), + byText("Main", "int foo() = 8;", {0}) +}); diff --git a/rascal-lsp/src/main/rascal/lsp/lang/rascal/tests/rename/TestUtils.rsc b/rascal-lsp/src/main/rascal/lsp/lang/rascal/tests/rename/TestUtils.rsc index 49fd0b017..15c4ae4d0 100644 --- a/rascal-lsp/src/main/rascal/lsp/lang/rascal/tests/rename/TestUtils.rsc +++ b/rascal-lsp/src/main/rascal/lsp/lang/rascal/tests/rename/TestUtils.rsc @@ -58,7 +58,7 @@ import util::Util; //// Fixtures and utility functions -data TestModule = byText(str name, str body, set[int] nameOccs, str newName = name, set[int] skipCursors = {}) +data TestModule = byText(str name, str body, set[int] nameOccs, str newName = name, set[int] skipCursors = {}, str annotations = "") | byLoc(str name, loc file, set[int] nameOccs, str newName = name, set[int] skipCursors = {}); data RenameException @@ -131,7 +131,7 @@ bool testProject(set[TestModule] modules, str testName, bool(set[TestModule] mod } pcfg = getTestPathConfig(testDir); - modulesByLocation = {mByLoc | m <- modules, mByLoc := (m is byLoc ? m : byLoc(m.name, storeTestModule(testDir, m.name, m.body), m.nameOccs, newName = m.newName, skipCursors = m.skipCursors))}; + modulesByLocation = {mByLoc | m <- modules, mByLoc := (m is byLoc ? m : byLoc(m.name, storeTestModule(testDir, m.name, m.body, annotations = m.annotations), m.nameOccs, newName = m.newName, skipCursors = m.skipCursors))}; for (m <- modulesByLocation) { try { @@ -378,9 +378,9 @@ private tuple[loc, list[Tree]] findCursor(loc f, str id, int occ) { return ; } -private loc storeTestModule(loc dir, str name, str body) { +private loc storeTestModule(loc dir, str name, str body, str annotations = "") { str moduleStr = " - 'module + ' module ' "; From 96f93a08a8733199dc60d8c6dfc9f208a387141c Mon Sep 17 00:00:00 2001 From: Toine Hartman Date: Thu, 29 Jan 2026 16:54:05 +0100 Subject: [PATCH 2/5] Do not throw an exception on ignored modules. --- .../rascal/lsp/lang/rascal/lsp/refactor/Rename.rsc | 10 ++++++++-- .../lsp/lang/rascal/lsp/refactor/rename/Common.rsc | 2 +- .../lang/rascal/lsp/refactor/rename/Constructors.rsc | 2 +- .../lsp/lang/rascal/lsp/refactor/rename/Fields.rsc | 3 +-- .../lsp/lang/rascal/lsp/refactor/rename/Parameters.rsc | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/Rename.rsc b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/Rename.rsc index d52eb1aba..b63066bed 100644 --- a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/Rename.rsc +++ b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/Rename.rsc @@ -247,7 +247,13 @@ public Edits rascalRenameSymbol(loc cursorLoc, list[Tree] cursor, str newName, s if (!found) { if (ms.status[mname]?) { // If a module is annotated with `@ignoreCompiler`, silently skip it - if (MStatus::ignored() in ms.status[mname]) return tmodel(); + if (MStatus::ignored() in ms.status[mname]) { + // We just need a way to map the TModel back to the module location, so let's artificially add that + return tmodel() + [modelName = mname] + [moduleLocs = (mname: l)] + ; + } throw "No TModel for module \'\'"; } throw "No TModel for module \'\'"; @@ -402,7 +408,7 @@ private loc nameSuffix(loc l, set[Define] defs, Renamer r) { void renameUses(set[Define] defs, str newName, TModel tm, Renamer r) { escName = normalizeEscaping(newName); - tm = getConditionallyAugmentedTModel(getModuleScopes(tm)[tm.modelName].top, defs, {augmentUses()}, r); + tm = getConditionallyAugmentedTModel(getModuleFile(tm), defs, {augmentUses()}, r); definitions = { | d <- defs}; useDefs = toMap(tm.useDef o definitions); diff --git a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Common.rsc b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Common.rsc index 7f22da2cb..418bc5a64 100644 --- a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Common.rsc +++ b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Common.rsc @@ -66,7 +66,7 @@ bool isContainedInScope(loc l, loc scope, TModel tm) { return any(loc fromScope <- reachableFrom, isContainedIn(l, fromScope)); } -loc getModuleFile(TModel tm) = getModuleScopes(tm)[tm.modelName].top; +loc getModuleFile(TModel tm) = tm.moduleLocs[tm.modelName] when tm.moduleLocs[tm.modelName]?; private set[str] reservedNames = getRascalReservedIdentifiers(); diff --git a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Constructors.rsc b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Constructors.rsc index 94ade97c3..0a6e92a1d 100644 --- a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Constructors.rsc +++ b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Constructors.rsc @@ -67,7 +67,7 @@ set[Define] findAdditionalConstructorDefinitions(set[Define] cursorDefs, Tree tr return {}; } - loc localScope = getModuleScopes(tm)[tm.modelName]; + loc localScope = getModuleFile(tm); if (!any(Define d <- cursorDefs, isContainedInScope(d.defined, localScope, tm) || isContainedInScope(localScope, d.scope, tm))) { return {}; } diff --git a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Fields.rsc b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Fields.rsc index e25bdb0e3..b3bd01449 100644 --- a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Fields.rsc +++ b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Fields.rsc @@ -167,8 +167,7 @@ bool isUnsupportedCursor(list[Tree] _: [*_, Name n1, *_, (Expression) ` has `: { eFieldDefs = getFieldDefinitions(e, "", tm, r.getConfig().tmodelForLoc); diff --git a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Parameters.rsc b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Parameters.rsc index c0d7a75a5..55b4b037a 100644 --- a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Parameters.rsc +++ b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Parameters.rsc @@ -51,7 +51,7 @@ tuple[set[loc], set[loc], set[loc]] findOccurrenceFilesUnchecked(set[Define] _:{ TModel augmentFormalUses(Tree tr, TModel tm, TModel(loc) getModel) { rel[loc funcDef, str kwName, loc kwLoc] keywordFormalDefs = { *(fileTm.defines)[keywordFormalId()] - | loc f <- getModuleFile(tm) + (tm.paths) + | loc f <- tr.src + (tm.paths) , fileTm := getModel(f.top) }; visit (tr) { From 83eb3266acfb30595cfc2378c8db1c3b232efe44 Mon Sep 17 00:00:00 2001 From: Toine Hartman Date: Thu, 29 Jan 2026 17:14:43 +0100 Subject: [PATCH 3/5] Remove position information in module file loc. --- .../main/rascal/lsp/lang/rascal/lsp/refactor/rename/Common.rsc | 2 +- .../rascal/lsp/lang/rascal/lsp/refactor/rename/Parameters.rsc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Common.rsc b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Common.rsc index 418bc5a64..1c32b1f11 100644 --- a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Common.rsc +++ b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Common.rsc @@ -66,7 +66,7 @@ bool isContainedInScope(loc l, loc scope, TModel tm) { return any(loc fromScope <- reachableFrom, isContainedIn(l, fromScope)); } -loc getModuleFile(TModel tm) = tm.moduleLocs[tm.modelName] when tm.moduleLocs[tm.modelName]?; +loc getModuleFile(TModel tm) = tm.moduleLocs[tm.modelName].top when tm.moduleLocs[tm.modelName]?; private set[str] reservedNames = getRascalReservedIdentifiers(); diff --git a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Parameters.rsc b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Parameters.rsc index 55b4b037a..c0d7a75a5 100644 --- a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Parameters.rsc +++ b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Parameters.rsc @@ -51,7 +51,7 @@ tuple[set[loc], set[loc], set[loc]] findOccurrenceFilesUnchecked(set[Define] _:{ TModel augmentFormalUses(Tree tr, TModel tm, TModel(loc) getModel) { rel[loc funcDef, str kwName, loc kwLoc] keywordFormalDefs = { *(fileTm.defines)[keywordFormalId()] - | loc f <- tr.src + (tm.paths) + | loc f <- getModuleFile(tm) + (tm.paths) , fileTm := getModel(f.top) }; visit (tr) { From 04194590d4997d19a0accb429a371235086be4b3 Mon Sep 17 00:00:00 2001 From: Toine Hartman Date: Thu, 29 Jan 2026 17:37:49 +0100 Subject: [PATCH 4/5] Fix constructor scope resolution. --- .../lsp/lang/rascal/lsp/refactor/rename/Constructors.rsc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Constructors.rsc b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Constructors.rsc index 0a6e92a1d..fc7c7afdb 100644 --- a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Constructors.rsc +++ b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Constructors.rsc @@ -67,7 +67,11 @@ set[Define] findAdditionalConstructorDefinitions(set[Define] cursorDefs, Tree tr return {}; } - loc localScope = getModuleFile(tm); + scopes = getModuleScopes(tm); + if (!scopes[tm.modelName]?) { + return {}; + } + loc localScope = scopes[tm.modelName]; if (!any(Define d <- cursorDefs, isContainedInScope(d.defined, localScope, tm) || isContainedInScope(localScope, d.scope, tm))) { return {}; } From 380b475cd767ab98acd047b167a2fb520ab081c1 Mon Sep 17 00:00:00 2001 From: Toine Hartman Date: Fri, 30 Jan 2026 14:58:18 +0100 Subject: [PATCH 5/5] Test ignored modules. --- .../rascal/tests/rename/ModuleAnnotations.rsc | 43 +++++++++++++++++++ .../lang/rascal/tests/rename/Performance.rsc | 7 --- 2 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 rascal-lsp/src/main/rascal/lsp/lang/rascal/tests/rename/ModuleAnnotations.rsc diff --git a/rascal-lsp/src/main/rascal/lsp/lang/rascal/tests/rename/ModuleAnnotations.rsc b/rascal-lsp/src/main/rascal/lsp/lang/rascal/tests/rename/ModuleAnnotations.rsc new file mode 100644 index 000000000..d59eac188 --- /dev/null +++ b/rascal-lsp/src/main/rascal/lsp/lang/rascal/tests/rename/ModuleAnnotations.rsc @@ -0,0 +1,43 @@ +@license{ +Copyright (c) 2018-2025, NWO-I CWI and Swat.engineering +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +} +module lang::rascal::tests::rename::ModuleAnnotations + +import lang::rascal::tests::rename::TestUtils; + +test bool useInIgnoredModule() = testRenameOccurrences({ + byText("Ignored", " + 'import Main; + 'int quz() = foo();", {}, annotations = "@ignoreCompiler{For test purposes.}"), + byText("Main", "int foo() = 8;", {0}) +}); + +test bool defInIgnoredModule() = testRenameOccurrences({ + byText("Main", " + 'import Ignored; + 'int quz() = foo();", {}), + byText("Main", "int foo() = 8;", {}, annotations = "@ignoreCompiler{For test purposes.}") +}); diff --git a/rascal-lsp/src/main/rascal/lsp/lang/rascal/tests/rename/Performance.rsc b/rascal-lsp/src/main/rascal/lsp/lang/rascal/tests/rename/Performance.rsc index f5f99b41b..a54d1a8ce 100644 --- a/rascal-lsp/src/main/rascal/lsp/lang/rascal/tests/rename/Performance.rsc +++ b/rascal-lsp/src/main/rascal/lsp/lang/rascal/tests/rename/Performance.rsc @@ -77,10 +77,3 @@ test bool incrementalTypeCheck() { remove(procLoc); return res; } - -test bool ignoredModule() = testRenameOccurrences({ - byText("Ignored", " - 'import Main; - 'int quz() = foo();", {}, annotations = "@ignoreCompiler{For test purposes.}"), - byText("Main", "int foo() = 8;", {0}) -});