diff --git a/rascal-lsp/pom.xml b/rascal-lsp/pom.xml index 79a3ebb03..d37ea1096 100644 --- a/rascal-lsp/pom.xml +++ b/rascal-lsp/pom.xml @@ -64,7 +64,7 @@ org.rascalmpl rascal - 0.43.0-RC7 + 0.43.0-RC8 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 c599b067c..27f2f4c88 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 @@ -74,17 +74,18 @@ import analysis::diff::edits::AnnotatedTextEdits; private bool isQualifiedUse(loc use, Define _:<_, str id, _, _, _, _>) = size(id) != use.length; void rascalCheckCausesOverlappingDefinitions(set[Define] currentDefs, str newName, Tree tr, TModel tm, Renamer r) { - defUse = invert(tm.useDef); + useDef = getUseDef(tm); + defUse = invert(useDef); unescNewName = forceUnescapeNames(newName); reachable = rascalGetReflexiveModulePaths(tm).to; - usedModules = {d.top | loc d <- tm.useDef<1>}; + usedModules = {d.top | loc d <- useDef<1>}; usedModels = (m: tm | loc m <- usedModules, TModel tm := r.getConfig().tmodelForLoc(m)) + (tr.src.top: tm); newNameDefs = {nD | TModel tm <- range(usedModels), Define nD:<_, unescNewName, _, _, _, _> <- tm.defines}; curAndNewDefinitions = (d.defined: d | d <- currentDefs + newNameDefs); // temporary map for overloading checks maybeImplicitDefs = {n.names[-1].src | /QualifiedName n := tr}; bool isImplicitDef(Define d) - = (d.idRole is variableId && d.defined in tm.useDef<0>) // variable that's both a use and a def + = (d.idRole is variableId && d.defined in useDef<0>) // variable that's both a use and a def || (d.idRole is patternVariableId && d.defined in maybeImplicitDefs) // or pattern variable without a type ; @@ -304,7 +305,7 @@ private set[Define] tryGetCursorDefinitions(list[Tree] cursor, TModel(loc) getMo if (tm.definitions[c.src]?) { // Cursor at definition cursorDefs = {tm.definitions[c.src]}; - } else if (defs: {_, *_} := tm.useDef[c.src]) { + } else if (defs: {_, *_} := getUseDef(tm)[c.src]) { // Cursor at use cursorDefs = flatMapPerFile(defs, set[Define](loc f, set[loc] localDefs) { localTm = f.top == cursorLoc.top ? tm : getModel(f); @@ -404,7 +405,7 @@ void renameUses(set[Define] defs, str newName, TModel tm, Renamer r) { tm = getConditionallyAugmentedTModel(getModuleScopes(tm)[tm.modelName].top, defs, {augmentUses()}, r); definitions = { | d <- defs}; - useDefs = toMap(tm.useDef o definitions); + useDefs = toMap(getUseDef(tm) o definitions); for (loc u <- useDefs) { if (set[Define] ds:{_, *_} := useDefs[u], u notin defs.defined) { r.textEdit(replace(nameSuffix(u, ds, r), escName)); 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 be57c2e14..bea5292e6 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 @@ -68,6 +68,17 @@ bool isContainedInScope(loc l, loc scope, TModel tm) { loc getModuleFile(TModel tm) = getModuleScopes(tm)[tm.modelName].top; +@synopsis{ + Gets the use-def relation of TModel `tm`. Unlike `tm.useDef`, this function + guarantees that the range of the relation is a subset of the domain of + `tm.definitions`. Thus, unlike pairs in `tm.useDef`, if `` is a pair + in the relation, then `d` can safely be used to index `tm.definitions`. +} +rel[loc, loc] getUseDef(TModel tm) { + map[loc, loc] id2define = invertUnique(tm.define2id); + return { | <- tm.useDef}; +} + private set[str] reservedNames = getRascalReservedIdentifiers(); str forceUnescapeNames(str name) = replaceAll(name, "\\", ""); 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 af6fc60e6..e2a9c707a 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 @@ -79,7 +79,7 @@ set[Define] getFieldDefinitions(set[AType] containerTypes, str fieldName, TModel @synopsis{Collect all definitions for the field in ADT/collection/tuple by tree.} set[Define] getFieldDefinitions(Tree container, str fieldName, TModel tm, TModel(loc) getModel) { - if (defs:{_, *_} := tm.useDef[container.src]) { + if (defs:{_, *_} := getUseDef(tm)[container.src]) { return flatMapPerFile(defs, set[Define](loc f, set[loc] localContainerDefs) { fileTm = getModel(f); diff --git a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Modules.rsc b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Modules.rsc index 12eafe3f1..77733e74a 100644 --- a/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Modules.rsc +++ b/rascal-lsp/src/main/rascal/lsp/lang/rascal/lsp/refactor/rename/Modules.rsc @@ -136,8 +136,9 @@ void renameDefinitionUnchecked(Define d:<_, currentName, _, moduleId(), _, _>, l void renameAdditionalUses(set[Define] _:{<_, str moduleName, _, moduleId(), loc modDef, _>}, str newName, TModel tm, Renamer r) { // We get the module location from the uses. If there are no uses, this is skipped. // That's intended, since this function is only supposed to rename uses. - if ({loc u, *_} := tm.useDef<0>) { - for (/QualifiedName qn := r.getConfig().parseLoc(u.top), any(d <- tm.useDef[qn.src], d.top == modDef.top), + rel[loc, loc] useDef = getUseDef(tm); + if ({loc u, *_} := useDef<0>) { + for (/QualifiedName qn := r.getConfig().parseLoc(u.top), any(d <- useDef[qn.src], d.top == modDef.top), just() := qualifiedPrefix(qn)) { r.textEdit(replace(prefLoc, newName)); } 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 733c60aa8..3af12647d 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 @@ -54,9 +54,10 @@ TModel augmentFormalUses(Tree tr, TModel tm, TModel(loc) getModel) { | loc f <- getModuleFile(tm) + (tm.paths) , fileTm := getModel(f.top) }; + rel[loc, loc] useDef = getUseDef(tm); visit (tr) { case (Expression) `(<{Expression ","}* _> )`: { - funcKwDefs = keywordFormalDefs[tm.useDef[e.src]]; + funcKwDefs = keywordFormalDefs[useDef[e.src]]; // Only visit uses of our keyword arguments - do not go into nested calls top-down-break visit (kwArgs) { case (KeywordArgument[Expression]) ` = `: {