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..a920f1b6c 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,17 @@ 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]? && MStatus::ignored() in ms.status[mname]) { + // If a module is annotated with `@ignoreCompiler`, silently skip it + // 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 \'\'"; + } return tm; } @@ -395,7 +405,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..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) = getModuleScopes(tm)[tm.modelName].top; +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/Constructors.rsc b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Constructors.rsc index 94ade97c3..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 = getModuleScopes(tm)[tm.modelName]; + 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 {}; } 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/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/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 ' ";