diff --git a/rascal-lsp/src/main/rascal/lang/rascal/lsp/refactor/Rename.rsc b/rascal-lsp/src/main/rascal/lang/rascal/lsp/refactor/Rename.rsc index 5b56660b..b7e11922 100644 --- a/rascal-lsp/src/main/rascal/lang/rascal/lsp/refactor/Rename.rsc +++ b/rascal-lsp/src/main/rascal/lang/rascal/lsp/refactor/Rename.rsc @@ -85,22 +85,22 @@ private set[IllegalRenameReason] rascalCheckLegalName(str name, set[IdRole] role if ({fieldId(), *_} := roles) asType = <#NonterminalLabel, "constructor field name">; if (size(syntaxRoles & roles) > 0) asType = <#Nonterminal, "non-terminal name">; - if (!tryParseAs(asType.as, escName)) return {invalidName(escName, asType.desc)}; + if (tryParseAs(asType.as, escName) is nothing) return {invalidName(escName, asType.desc)}; return {}; } private void rascalCheckLegalName(str name, Symbol sym) { escName = rascalEscapeName(name); g = grammar(#start[Module]); - if (!tryParseAs(type(sym, g.rules), escName)) { + if (tryParseAs(type(sym, g.rules), escName) is nothing) { throw illegalRename("\'\' is not a valid name at this position", {invalidName(escName, "")}); } } -private set[IllegalRenameReason] rascalCheckDefinitionsOutsideWorkspace(WorkspaceInfo ws, set[loc] defs) = +private set[IllegalRenameReason] rascalCheckDefinitionsOutsideWorkspace(TModel ws, set[loc] defs) = { definitionsOutsideWorkspace(d) | set[loc] d <- groupRangeByDomain({ | loc d <- defs, f := d.top, f notin ws.sourceFiles}) }; -private set[IllegalRenameReason] rascalCheckCausesDoubleDeclarations(WorkspaceInfo ws, set[loc] currentDefs, set[Define] newDefs, str newName) { +private set[IllegalRenameReason] rascalCheckCausesDoubleDeclarations(TModel ws, set[loc] currentDefs, set[Define] newDefs, str newName) { // Is newName already resolvable from a scope where is currently declared? rel[loc old, loc new] doubleDeclarations = { | <- (currentDefs * newDefs) , isContainedIn(cD, nD.scope) @@ -128,8 +128,8 @@ private set[IllegalRenameReason] rascalCheckCausesDoubleDeclarations(WorkspaceIn return {doubleDeclaration(old, doubleDeclarations[old]) | old <- (doubleDeclarations + doubleFieldDeclarations + doubleTypeParamDeclarations).old}; } -private set[IllegalRenameReason] rascalCheckCausesCaptures(WorkspaceInfo ws, start[Module] m, set[loc] currentDefs, set[loc] currentUses, set[Define] newDefs) { - set[Define] rascalFindImplicitDefinitions(WorkspaceInfo ws, start[Module] m, set[Define] newDefs) { +private set[IllegalRenameReason] rascalCheckCausesCaptures(TModel ws, start[Module] m, set[loc] currentDefs, set[loc] currentUses, set[Define] newDefs) { + set[Define] rascalFindImplicitDefinitions(TModel ws, start[Module] m, set[Define] newDefs) { set[loc] maybeImplicitDefs = {l | /QualifiedName n := m, just(l) := rascalLocationOfName(n)}; return {def | Define def <- newDefs, (def.idRole is variableId && def.defined in ws.useDef<0>) || (def.idRole is patternVariableId && def.defined in maybeImplicitDefs)}; @@ -170,7 +170,7 @@ private set[IllegalRenameReason] rascalCheckCausesCaptures(WorkspaceInfo ws, sta return allCaptures == {} ? {} : {captureChange(allCaptures)}; } -private set[IllegalRenameReason] rascalCollectIllegalRenames(WorkspaceInfo ws, start[Module] m, set[loc] currentDefs, set[loc] currentUses, str newName) { +private set[IllegalRenameReason] rascalCollectIllegalRenames(TModel ws, start[Module] m, set[loc] currentDefs, set[loc] currentUses, str newName) { set[Define] newNameDefs = {def | Define def:<_, newName, _, _, _, _> <- ws.defines}; return @@ -221,7 +221,7 @@ Maybe[loc] rascalLocationOfName(Nonterminal nt) = just(nt.src); Maybe[loc] rascalLocationOfName(NonterminalLabel l) = just(l.src); default Maybe[loc] rascalLocationOfName(Tree t) = nothing(); -private tuple[set[IllegalRenameReason] reasons, list[TextEdit] edits] computeTextEdits(WorkspaceInfo ws, start[Module] m, set[RenameLocation] defs, set[RenameLocation] uses, str name, ChangeAnnotationRegister registerChangeAnnotation) { +private tuple[set[IllegalRenameReason] reasons, list[TextEdit] edits] computeTextEdits(TModel ws, start[Module] m, set[RenameLocation] defs, set[RenameLocation] uses, str name, ChangeAnnotationRegister registerChangeAnnotation) { if (reasons := rascalCollectIllegalRenames(ws, m, defs.l, uses.l, name), reasons != {}) { return ; } @@ -245,10 +245,10 @@ private tuple[set[IllegalRenameReason] reasons, list[TextEdit] edits] computeTex , rel[Maybe[ChangeAnnotationId] ann, bool isDef] renameOpts := renames[nameOfUseDef[l]]]>; } -private tuple[set[IllegalRenameReason] reasons, list[TextEdit] edits] computeTextEdits(WorkspaceInfo ws, loc moduleLoc, set[RenameLocation] defs, set[RenameLocation] uses, str name, ChangeAnnotationRegister registerChangeAnnotation) = +private tuple[set[IllegalRenameReason] reasons, list[TextEdit] edits] computeTextEdits(TModel ws, loc moduleLoc, set[RenameLocation] defs, set[RenameLocation] uses, str name, ChangeAnnotationRegister registerChangeAnnotation) = computeTextEdits(ws, parseModuleWithSpacesCached(moduleLoc), defs, uses, name, registerChangeAnnotation); -private bool rascalIsFunctionLocalDefs(WorkspaceInfo ws, set[loc] defs) { +private bool rascalIsFunctionLocalDefs(TModel ws, set[loc] defs) { for (d <- defs) { if (Define fun: <_, _, _, _, _, defType(afunc(_, _, _))> <- ws.defines && isContainedIn(ws.definitions[d].scope, fun.defined)) { @@ -259,14 +259,14 @@ private bool rascalIsFunctionLocalDefs(WorkspaceInfo ws, set[loc] defs) { return true; } -private bool rascalIsFunctionLocal(WorkspaceInfo ws, cursor(def(), cursorLoc, _)) = +private bool rascalIsFunctionLocal(TModel ws, cursor(def(), cursorLoc, _)) = rascalIsFunctionLocalDefs(ws, rascalGetOverloadedDefs(ws, {cursorLoc}, rascalMayOverloadSameName)); -private bool rascalIsFunctionLocal(WorkspaceInfo ws, cursor(use(), cursorLoc, _)) = +private bool rascalIsFunctionLocal(TModel ws, cursor(use(), cursorLoc, _)) = rascalIsFunctionLocalDefs(ws, rascalGetOverloadedDefs(ws, getDefs(ws, cursorLoc), rascalMayOverloadSameName)); -private bool rascalIsFunctionLocal(WorkspaceInfo _, cursor(typeParam(), _, _)) = true; +private bool rascalIsFunctionLocal(TModel _, cursor(typeParam(), _, _)) = true; private default bool rascalIsFunctionLocal(_, _) = false; -Maybe[AType] rascalAdtCommonKeywordFieldType(WorkspaceInfo ws, str fieldName, Define _:<_, _, _, _, _, DefInfo defInfo>) { +Maybe[AType] rascalAdtCommonKeywordFieldType(TModel ws, str fieldName, Define _:<_, _, _, _, _, DefInfo defInfo>) { if (defInfo.commonKeywordFields? && kwf:(KeywordFormal) ` = ` <- defInfo.commonKeywordFields && "" == fieldName) { @@ -286,7 +286,7 @@ Maybe[AType] rascalConsFieldType(str fieldName, Define _:<_, _, _, constructorId return nothing(); } -private CursorKind rascalGetDataFieldCursorKind(WorkspaceInfo ws, loc container, loc cursorLoc, str cursorName) { +private CursorKind rascalGetDataFieldCursorKind(TModel ws, loc container, loc cursorLoc, str cursorName) { for (Define dt <- rascalGetADTDefinitions(ws, container) && AType adtType := dt.defInfo.atype) { if (just(fieldType) := rascalAdtCommonKeywordFieldType(ws, cursorName, dt)) { @@ -313,7 +313,7 @@ private CursorKind rascalGetDataFieldCursorKind(WorkspaceInfo ws, loc container, throw illegalRename("Cannot rename \'\'; it is not defined in this workspace", {definitionsOutsideWorkspace(fromDefs)}); } -private CursorKind rascalGetCursorKind(WorkspaceInfo ws, loc cursorLoc, str cursorName, rel[loc l, CursorKind kind] locsContainingCursor, rel[loc field, loc container] fields, rel[loc kw, loc container] keywords) { +private CursorKind rascalGetCursorKind(TModel ws, loc cursorLoc, str cursorName, rel[loc l, CursorKind kind] locsContainingCursor, rel[loc field, loc container] fields, rel[loc kw, loc container] keywords) { loc c = min(locsContainingCursor.l); switch (locsContainingCursor[c]) { case {moduleName(), *_}: { @@ -384,7 +384,7 @@ private CursorKind rascalGetCursorKind(WorkspaceInfo ws, loc cursorLoc, str curs throw unsupportedRename("Could not retrieve information for \'\' at ."); } -private Cursor rascalGetCursor(WorkspaceInfo ws, Tree cursorT) { +private Cursor rascalGetCursor(TModel ws, Tree cursorT) { loc cursorLoc = cursorT.src; str cursorName = ""; @@ -436,10 +436,16 @@ private Cursor rascalGetCursor(WorkspaceInfo ws, Tree cursorT) { return cursor(kind, min(locsContainingCursor.l), cursorName); } -private set[Name] rascalNameToEquivalentNames(str name) = { - [Name] name, - startsWith(name, "\\") ? [Name] name : [Name] "\\" -}; +private set[Tree] rascalNameToEquivalentNames(str name) { + set[Tree] equivs = {t + | T <- {#Name, #Nonterminal, #NonterminalLabel} + , just(Tree t) := tryParseAs(T, name) + }; + + if (!startsWith(name, "\\") && just(en) := tryParseAs(#Name, "\\")) equivs += en; + + return equivs; +} private bool rascalContainsName(loc l, str name) { m = parseModuleWithSpacesCached(l); @@ -449,6 +455,44 @@ private bool rascalContainsName(loc l, str name) { return false; } +private set[TModel] rascalTModels(set[loc] fs, PathConfig pcfg) { + RascalCompilerConfig ccfg = rascalCompilerConfig(pcfg)[verbose = false] + [logPathConfig = false]; + ms = rascalTModelForLocs(toList(fs), ccfg, dummy_compile1); + + set[TModel] tmodels = {}; + for (modName <- ms.moduleLocs) { + = getTModelForModule(modName, ms); + if (!found) throw unexpectedFailure("Cannot read TModel for module \'\'\n"); + tmodels += convertTModel2PhysicalLocs(tm); + } + return tmodels; +} + +ProjectFiles preloadFiles(set[loc] workspaceFolders, loc cursorLoc) { + return { < + max([f | f <- workspaceFolders, isPrefixOf(f, cursorLoc)]), + true, + cursorLoc.top + > }; +} + +ProjectFiles allWorkspaceFiles(set[loc] workspaceFolders, str cursorName, bool(loc, str) containsName, PathConfig(loc) getPathConfig) { + return { + // If we do not find any occurrences of the name under the cursor in a module, + // we are not interested in loading the model, but we still want to inform the + // renaming framework about the existence of the file. + + | folder <- workspaceFolders + , PathConfig pcfg := getPathConfig(folder) + , srcFolder <- pcfg.srcs + , file <- find(srcFolder, "rsc") + }; +} + +set[TModel] tmodelsForProjectFiles(ProjectFiles projectFiles, set[TModel](set[loc], PathConfig) tmodelsForFiles, PathConfig(loc) getPathConfig) = + ({} | it + tmodelsForFiles(projectFiles[pf, true], pcfg) | pf <- projectFiles.projectFolder, pcfg := getPathConfig(pf)); + @synopsis{ Rename the Rascal symbol under the cursor. Renames all related (overloaded) definitions and uses of those definitions. Renaming is not supported for some symbols. @@ -518,66 +562,24 @@ private bool rascalContainsName(loc l, str name) { } Edits rascalRenameSymbol(Tree cursorT, set[loc] workspaceFolders, str newName, PathConfig(loc) getPathConfig) = job("renaming to ", Edits(void(str, int) step) { + + step("checking validity of new name", 1); loc cursorLoc = cursorT.src; str cursorName = ""; rascalCheckLegalName(newName, typeOf(cursorT)); - step("collecting workspace information", 1); - WorkspaceInfo ws = workspaceInfo( - // Get path config - getPathConfig, - // Preload - ProjectFiles() { - return { < - max([f | f <- workspaceFolders, isPrefixOf(f, cursorLoc)]), - cursorLoc.top, - true - > }; - }, - // Full load - ProjectFiles() { - return { - // If we do not find any occurrences of the name under the cursor in a module, - // we are not interested in loading the model, but we still want to inform the - // renaming framework about the existence of the file. - - | folder <- workspaceFolders - , PathConfig pcfg := getPathConfig(folder) - , srcFolder <- pcfg.srcs - , file <- find(srcFolder, "rsc") - }; - }, - // Load TModel for loc - set[TModel](ProjectFiles projectFiles) { - set[TModel] tmodels = {}; - - for (projectFolder <- projectFiles.projectFolder, \files := projectFiles[projectFolder]) { - PathConfig pcfg = getPathConfig(projectFolder); - RascalCompilerConfig ccfg = rascalCompilerConfig(pcfg)[verbose = false] - [logPathConfig = false]; - for ( <- \files) { - ms = rascalTModelForLocs([file], ccfg, dummy_compile1); - for (modName <- ms.moduleLocs) { - = getTModelForModule(modName, ms); - if (!found) throw unexpectedFailure("Cannot read TModel for module \'\'\n"); - tmodels += convertTModel2PhysicalLocs(tm); - } - } - } - return tmodels; - } - ); - step("preloading minimal workspace information", 1); - ws = preLoad(ws); + set[TModel] localTmodelsForFiles(ProjectFiles projectFiles) = tmodelsForProjectFiles(projectFiles, rascalTModels, getPathConfig); + + TModel ws = loadLocs(tmodel(), preloadFiles(workspaceFolders, cursorLoc), localTmodelsForFiles); step("analyzing name at cursor", 1); cur = rascalGetCursor(ws, cursorT); step("loading required type information", 1); if (!rascalIsFunctionLocal(ws, cur)) { - ws = loadWorkspace(ws); + ws = loadLocs(ws, allWorkspaceFiles(workspaceFolders, cursorName, rascalContainsName, getPathConfig), localTmodelsForFiles); } step("collecting uses of \'\'", 1); @@ -597,7 +599,7 @@ Edits rascalRenameSymbol(Tree cursorT, set[loc] workspaceFolders, str newName, P return id; }; - = rascalGetDefsUses(ws, cur, rascalMayOverloadSameName, registerChangeAnnotation); + = rascalGetDefsUses(ws, cur, rascalMayOverloadSameName, registerChangeAnnotation, getPathConfig); rel[loc file, RenameLocation defines] defsPerFile = { | d <- defs}; rel[loc file, RenameLocation uses] usesPerFile = { | u <- uses}; diff --git a/rascal-lsp/src/main/rascal/lang/rascal/lsp/refactor/Util.rsc b/rascal-lsp/src/main/rascal/lang/rascal/lsp/refactor/Util.rsc index e51a1fda..4569b6ff 100644 --- a/rascal-lsp/src/main/rascal/lang/rascal/lsp/refactor/Util.rsc +++ b/rascal-lsp/src/main/rascal/lang/rascal/lsp/refactor/Util.rsc @@ -83,12 +83,11 @@ start[Module] parseModuleWithSpacesCached(loc l) { @synopsis{ Try to parse string `name` as reified type `begin` and return whether this succeeded. } -bool tryParseAs(type[&T <: Tree] begin, str name, bool allowAmbiguity = false) { +Maybe[&T <: Tree] tryParseAs(type[&T <: Tree] begin, str name, bool allowAmbiguity = false) { try { - parse(begin, name, allowAmbiguity = allowAmbiguity); - return true; + return just(parse(begin, name, allowAmbiguity = allowAmbiguity)); } catch ParseError(_): { - return false; + return nothing(); } } diff --git a/rascal-lsp/src/main/rascal/lang/rascal/lsp/refactor/WorkspaceInfo.rsc b/rascal-lsp/src/main/rascal/lang/rascal/lsp/refactor/WorkspaceInfo.rsc index defeeb52..025957d7 100644 --- a/rascal-lsp/src/main/rascal/lang/rascal/lsp/refactor/WorkspaceInfo.rsc +++ b/rascal-lsp/src/main/rascal/lang/rascal/lsp/refactor/WorkspaceInfo.rsc @@ -71,70 +71,46 @@ alias MayOverloadFun = bool(set[loc] defs, map[loc, Define] defines); alias FileRenamesF = rel[loc old, loc new](str newName); alias RenameLocation = tuple[loc l, Maybe[ChangeAnnotationId] annotation]; alias DefsUsesRenames = tuple[set[RenameLocation] defs, set[RenameLocation] uses, FileRenamesF renames]; -alias ProjectFiles = rel[loc projectFolder, loc file, bool loadModel]; - -/** - * This is a subset of the fields from analysis::typepal::TModel, specifically tailored to refactorings. - * WorkspaceInfo comes with a set of functions that allow (incrementally) loading information from multiple TModels, and doing (cached) queries on this data. - */ -data WorkspaceInfo ( - // Instance fields - // Read-only - rel[loc use, loc def] useDef = {}, - set[Define] defines = {}, - set[loc] sourceFiles = {}, - map[loc, Define] definitions = (), - map[loc, AType] facts = (), - Scopes scopes = (), - Paths paths = {}, - set[loc] projects = {} -) = workspaceInfo( - PathConfig(loc) getPathConfig, - ProjectFiles() preloadFiles, - ProjectFiles() allFiles, - set[TModel](ProjectFiles) tmodelsForLocs +alias ProjectFiles = rel[loc projectFolder, bool loadModel, loc file]; + +// Extend the TModel to include some workspace information. +data TModel ( + set[loc] projects = {}, + set[loc] sourceFiles = {} ); set[RenameLocation] annotateLocs(set[loc] locs, Maybe[ChangeAnnotationId] annotationId = nothing()) = { | l <- locs}; -WorkspaceInfo loadLocs(WorkspaceInfo ws, ProjectFiles projectFiles) { - for (tm <- ws.tmodelsForLocs(projectFiles)) { - ws = loadTModel(ws, tm); +TModel loadLocs(TModel wsTM, ProjectFiles projectFiles, set[TModel](ProjectFiles projectFiles) tmodelsForFiles) { + for (modTM <- tmodelsForFiles(projectFiles)) { + wsTM = appendTModel(wsTM, modTM); } // In addition to data from the TModel, we keep track of which projects/modules we loaded. - ws.sourceFiles += projectFiles.file; - ws.projects += projectFiles.projectFolder; - - return ws; -} - -WorkspaceInfo preLoad(WorkspaceInfo ws) { - return loadLocs(ws, ws.preloadFiles()); -} + wsTM.sourceFiles += projectFiles.file; + wsTM.projects += projectFiles.projectFolder; -WorkspaceInfo loadWorkspace(WorkspaceInfo ws) { - return loadLocs(ws, ws.allFiles()); + return wsTM; } -WorkspaceInfo loadTModel(WorkspaceInfo ws, TModel tm) { +TModel appendTModel(TModel to, TModel from) { try { - throwAnyErrors(tm); + throwAnyErrors(from); } catch set[Message] errors: { throw unsupportedRename("Cannot rename: some files in workspace have errors.\n", issues={<(error.at ? |unknown:///|), error.msg> | error <- errors}); } - ws.useDef += tm.useDef; - ws.defines += tm.defines; - ws.definitions += tm.definitions; - ws.facts += tm.facts; - ws.scopes += tm.scopes; - ws.paths += tm.paths; + to.useDef += from.useDef; + to.defines += from.defines; + to.definitions += from.definitions; + to.facts += from.facts; + to.scopes += from.scopes; + to.paths += from.paths; - return ws; + return to; } -loc getProjectFolder(WorkspaceInfo ws, loc l) { +loc getProjectFolder(TModel ws, loc l) { if (project <- ws.projects, isPrefixOf(project, l)) { return project; } @@ -143,27 +119,27 @@ loc getProjectFolder(WorkspaceInfo ws, loc l) { } @memo{maximumSize(1), expireAfter(minutes=5)} -rel[loc, loc] defUse(WorkspaceInfo ws) = invert(ws.useDef); +rel[loc, loc] defUse(TModel ws) = invert(ws.useDef); @memo{maximumSize(1), expireAfter(minutes=5)} -map[AType, set[loc]] factsInvert(WorkspaceInfo ws) = invert(ws.facts); +map[AType, set[loc]] factsInvert(TModel ws) = invert(ws.facts); -set[loc] getUses(WorkspaceInfo ws, loc def) = defUse(ws)[def]; +set[loc] getUses(TModel ws, loc def) = defUse(ws)[def]; -set[loc] getUses(WorkspaceInfo ws, set[loc] defs) = defUse(ws)[defs]; +set[loc] getUses(TModel ws, set[loc] defs) = defUse(ws)[defs]; -set[loc] getDefs(WorkspaceInfo ws, loc use) = ws.useDef[use]; +set[loc] getDefs(TModel ws, loc use) = ws.useDef[use]; -Maybe[AType] getFact(WorkspaceInfo ws, loc l) = l in ws.facts ? just(ws.facts[l]) : nothing(); +Maybe[AType] getFact(TModel ws, loc l) = l in ws.facts ? just(ws.facts[l]) : nothing(); @memo{maximumSize(1), expireAfter(minutes=5)} -set[loc] getModuleScopes(WorkspaceInfo ws) = invert(ws.scopes)[|global-scope:///|]; +set[loc] getModuleScopes(TModel ws) = invert(ws.scopes)[|global-scope:///|]; @memo{maximumSize(1), expireAfter(minutes=5)} -map[loc, loc] getModuleScopePerFile(WorkspaceInfo ws) = (scope.top: scope | loc scope <- getModuleScopes(ws)); +map[loc, loc] getModuleScopePerFile(TModel ws) = (scope.top: scope | loc scope <- getModuleScopes(ws)); @memo{maximumSize(1), expireAfter(minutes=5)} -rel[loc from, loc to] rascalGetTransitiveReflexiveModulePaths(WorkspaceInfo ws) { +rel[loc from, loc to] rascalGetTransitiveReflexiveModulePaths(TModel ws) { rel[loc from, loc to] moduleI = ident(getModuleScopes(ws)); rel[loc from, loc to] imports = (ws.paths)[importPath()]; rel[loc from, loc to] extends = (ws.paths)[extendPath()]; @@ -174,10 +150,10 @@ rel[loc from, loc to] rascalGetTransitiveReflexiveModulePaths(WorkspaceInfo ws) } @memo{maximumSize(1), expireAfter(minutes=5)} -rel[loc from, loc to] rascalGetTransitiveReflexiveScopes(WorkspaceInfo ws) = toRel(ws.scopes)*; +rel[loc from, loc to] rascalGetTransitiveReflexiveScopes(TModel ws) = toRel(ws.scopes)*; @memo{maximumSize(10), expireAfter(minutes=5)} -set[loc] rascalReachableModules(WorkspaceInfo ws, set[loc] froms) { +set[loc] rascalReachableModules(TModel ws, set[loc] froms) { rel[loc from, loc scope] fromScopes = {}; for (from <- froms) { if (scope <- ws.scopes<1>, isContainedIn(from, scope)) { @@ -193,9 +169,9 @@ set[loc] rascalReachableModules(WorkspaceInfo ws, set[loc] froms) { } @memo{maximumSize(1), expireAfter(minutes=5)} -rel[loc, Define] definitionsRel(WorkspaceInfo ws) = toRel(ws.definitions); +rel[loc, Define] definitionsRel(TModel ws) = toRel(ws.definitions); -set[Define] rascalReachableDefs(WorkspaceInfo ws, set[loc] defs) { +set[Define] rascalReachableDefs(TModel ws, set[loc] defs) { rel[loc from, loc to] modulePaths = rascalGetTransitiveReflexiveModulePaths(ws); rel[loc from, loc to] scopes = rascalGetTransitiveReflexiveScopes(ws); rel[loc from, Define define] reachableDefs = @@ -214,7 +190,7 @@ set[Define] rascalReachableDefs(WorkspaceInfo ws, set[loc] defs) { return reachableDefs.define; // We are only interested in reached defines; not *from where* they were reached } -set[loc] rascalGetOverloadedDefs(WorkspaceInfo ws, set[loc] defs, MayOverloadFun mayOverloadF) { +set[loc] rascalGetOverloadedDefs(TModel ws, set[loc] defs, MayOverloadFun mayOverloadF) { if (defs == {}) return {}; set[Define] overloadedDefs = definitionsRel(ws)[defs]; @@ -330,7 +306,7 @@ bool rascalMayOverloadSameName(set[loc] defs, map[loc, Define] definitions) { return false; } -set[Define] rascalGetADTDefinitions(WorkspaceInfo ws, loc lhs) { +set[Define] rascalGetADTDefinitions(TModel ws, loc lhs) { set[loc] fromDefs = (ws.definitions[lhs]? || lhs in ws.useDef<1>) ? {lhs} : getDefs(ws, lhs) @@ -357,7 +333,7 @@ set[Define] rascalGetADTDefinitions(WorkspaceInfo ws, loc lhs) { return {}; } -set[RenameLocation] rascalGetKeywordFormalUses(WorkspaceInfo ws, set[loc] defs, str cursorName) { +set[RenameLocation] rascalGetKeywordFormalUses(TModel ws, set[loc] defs, str cursorName) { set[RenameLocation] uses = {}; for (d <- defs @@ -394,7 +370,7 @@ set[loc] rascalGetKeywordArgs(\default(_, {KeywordArgument[Pattern] ","}+ keywor | kwArg <- keywordArgs , "" == cursorName}; -set[RenameLocation] rascalGetKeywordFieldUses(WorkspaceInfo ws, set[loc] defs, str cursorName) { +set[RenameLocation] rascalGetKeywordFieldUses(TModel ws, set[loc] defs, str cursorName) { set[RenameLocation] uses = annotateLocs(getUses(ws, defs)); set[Define] reachableDefs = rascalReachableDefs(ws, defs); @@ -418,7 +394,7 @@ set[RenameLocation] rascalGetKeywordFieldUses(WorkspaceInfo ws, set[loc] defs, s return uses; } -private set[RenameLocation] rascalGetExceptUses(WorkspaceInfo ws, set[loc] defs) { +private set[RenameLocation] rascalGetExceptUses(TModel ws, set[loc] defs) { constructorDefs = {d | l <- defs, Define d: <_, _, _, constructorId(), _, _> := ws.definitions[l]}; if (constructorDefs == {}) return {}; @@ -446,7 +422,7 @@ private set[RenameLocation] rascalGetExceptUses(WorkspaceInfo ws, set[loc] defs) return uses; } -DefsUsesRenames rascalGetDefsUses(WorkspaceInfo ws, cursor(use(), l, cursorName), MayOverloadFun mayOverloadF, ChangeAnnotationRegister registerChangeAnnotation) { +DefsUsesRenames rascalGetDefsUses(TModel ws, cursor(use(), l, cursorName), MayOverloadFun mayOverloadF, ChangeAnnotationRegister registerChangeAnnotation, PathConfig(loc) getPathConfig) { set[loc] defs = rascalGetOverloadedDefs(ws, getDefs(ws, l), mayOverloadF); set[RenameLocation] uses = annotateLocs(getUses(ws, defs)); @@ -454,7 +430,7 @@ DefsUsesRenames rascalGetDefsUses(WorkspaceInfo ws, cursor(use(), l, cursorName) if (keywordFormalId() in roles) { uses += rascalGetKeywordFormalUses(ws, defs, cursorName); uses += rascalGetKeywordFieldUses(ws, defs, cursorName); - uses += rascalGetHasUses(ws, defs, cursorName, registerChangeAnnotation); + uses += rascalGetHasUses(ws, defs, cursorName, registerChangeAnnotation, getPathConfig); } else if (constructorId() in roles) { uses += rascalGetExceptUses(ws, defs); } @@ -462,7 +438,7 @@ DefsUsesRenames rascalGetDefsUses(WorkspaceInfo ws, cursor(use(), l, cursorName) return ; } -DefsUsesRenames rascalGetDefsUses(WorkspaceInfo ws, cursor(def(), l, cursorName), MayOverloadFun mayOverloadF, ChangeAnnotationRegister registerChangeAnnotation) { +DefsUsesRenames rascalGetDefsUses(TModel ws, cursor(def(), l, cursorName), MayOverloadFun mayOverloadF, ChangeAnnotationRegister registerChangeAnnotation, PathConfig(loc) getPathConfig) { set[loc] initialUses = getUses(ws, l); set[loc] initialDefs = {l} + {*ds | u <- initialUses, ds := getDefs(ws, u)}; set[loc] defs = rascalGetOverloadedDefs(ws, initialDefs, mayOverloadF); @@ -472,7 +448,7 @@ DefsUsesRenames rascalGetDefsUses(WorkspaceInfo ws, cursor(def(), l, cursorName) if (roles & {keywordFormalId(), fieldId()} != {}) { uses += rascalGetKeywordFormalUses(ws, defs, cursorName); uses += rascalGetKeywordFieldUses(ws, defs, cursorName); - uses += rascalGetHasUses(ws, defs, cursorName, registerChangeAnnotation); + uses += rascalGetHasUses(ws, defs, cursorName, registerChangeAnnotation, getPathConfig); } else if (constructorId() in roles) { uses += rascalGetExceptUses(ws, defs); } @@ -480,20 +456,20 @@ DefsUsesRenames rascalGetDefsUses(WorkspaceInfo ws, cursor(def(), l, cursorName) return ; } -DefsUsesRenames rascalGetDefsUses(WorkspaceInfo ws, cursor(exceptConstructor(), l, cursorName), MayOverloadFun mayOverloadF, ChangeAnnotationRegister registerChangeAnnotation) { +DefsUsesRenames rascalGetDefsUses(TModel ws, cursor(exceptConstructor(), l, cursorName), MayOverloadFun mayOverloadF, ChangeAnnotationRegister registerChangeAnnotation, PathConfig(loc) getPathConfig) { if (f <- ws.facts , isContainedIn(l, f) , aprod(prod(_, [*_, conditional(AType nontermType, /\a-except(cursorName)) ,*_])) := ws.facts[f] , Define currentCons:<_, _, _, constructorId(), _, _> <- ws.defines , isContainedIn(currentCons.defined, f) , Define exceptCons:<_, cursorName, _, constructorId(), _, defType(acons(nontermType, _, _))> <- rascalReachableDefs(ws, {currentCons.defined})) { - return rascalGetDefsUses(ws, cursor(def(), exceptCons.defined, cursorName), mayOverloadF, registerChangeAnnotation); + return rascalGetDefsUses(ws, cursor(def(), exceptCons.defined, cursorName), mayOverloadF, registerChangeAnnotation, getPathConfig); } return <{}, {}, NO_RENAMES>; } -DefsUsesRenames rascalGetDefsUses(WorkspaceInfo ws, cursor(typeParam(), cursorLoc, cursorName), MayOverloadFun _, ChangeAnnotationRegister _) { +DefsUsesRenames rascalGetDefsUses(TModel ws, cursor(typeParam(), cursorLoc, cursorName), MayOverloadFun _, ChangeAnnotationRegister _, PathConfig(loc) getPathConfig) { set[loc] getFormals(afunc(_, _, _), rel[loc, AType] facts) = {l | <- facts, f.alabel != ""}; set[loc] getFormals(aadt(_, _, _), rel[loc, AType] facts) { perName = { | <- facts, f.alabel == ""}; @@ -549,7 +525,7 @@ Maybe[tuple[loc, set[loc]]] rascalGetHasLocs(str fieldName, (Expression) `` on value of ", "Due to the dynamic nature of these names, please review these suggested changes.", true))> | loc l <- rascalReachableModules(ws, defs) @@ -558,7 +534,7 @@ set[RenameLocation] rascalGetHasUses(WorkspaceInfo ws, set[loc] defs, str cursor }; } -DefsUsesRenames rascalGetDefsUses(WorkspaceInfo ws, cursor(dataField(loc adtLoc, AType fieldType), cursorLoc, cursorName), MayOverloadFun mayOverloadF, ChangeAnnotationRegister registerChangeAnnotation) { +DefsUsesRenames rascalGetDefsUses(TModel ws, cursor(dataField(loc adtLoc, AType fieldType), cursorLoc, cursorName), MayOverloadFun mayOverloadF, ChangeAnnotationRegister registerChangeAnnotation, PathConfig(loc) getPathConfig) { set[loc] initialDefs = {}; if (cursorLoc in ws.useDef<0>) { initialDefs = getDefs(ws, cursorLoc); @@ -579,14 +555,14 @@ DefsUsesRenames rascalGetDefsUses(WorkspaceInfo ws, cursor(dataField(loc adtLoc, set[loc] defs = rascalGetOverloadedDefs(ws, initialDefs, mayOverloadF); set[RenameLocation] uses = annotateLocs(getUses(ws, defs)) + rascalGetKeywordFieldUses(ws, defs, cursorName); - set[RenameLocation] hasUses = rascalGetHasUses(ws, defs, cursorName, registerChangeAnnotation); + set[RenameLocation] hasUses = rascalGetHasUses(ws, defs, cursorName, registerChangeAnnotation, getPathConfig); return ; } bool debug = false; -DefsUsesRenames rascalGetDefsUses(WorkspaceInfo ws, cursor(cursorKind, cursorLoc, cursorName), MayOverloadFun mayOverloadF, ChangeAnnotationRegister registerChangeAnnotation) { +DefsUsesRenames rascalGetDefsUses(TModel ws, cursor(cursorKind, cursorLoc, cursorName), MayOverloadFun mayOverloadF, ChangeAnnotationRegister registerChangeAnnotation, PathConfig(loc) getPathConfig) { if (cursorKind is dataKeywordField || cursorKind is dataCommonKeywordField) { set[RenameLocation] defs = {}; set[RenameLocation] uses = {}; @@ -607,7 +583,7 @@ DefsUsesRenames rascalGetDefsUses(WorkspaceInfo ws, cursor(cursorKind, cursorLoc uses += us; } - uses += rascalGetHasUses(ws, adtDefs, cursorName, registerChangeAnnotation); + uses += rascalGetHasUses(ws, adtDefs, cursorName, registerChangeAnnotation, getPathConfig); return ; } @@ -615,7 +591,7 @@ DefsUsesRenames rascalGetDefsUses(WorkspaceInfo ws, cursor(cursorKind, cursorLoc fail; } -DefsUsesRenames rascalGetDefsUses(WorkspaceInfo ws, cursor(collectionField(), cursorLoc, cursorName), MayOverloadFun _, ChangeAnnotationRegister _) { +DefsUsesRenames rascalGetDefsUses(TModel ws, cursor(collectionField(), cursorLoc, cursorName), MayOverloadFun _, ChangeAnnotationRegister _, PathConfig(loc) getPathConfig) { bool isTupleField(AType fieldType) = fieldType.alabel == ""; lrel[loc, AType] factsBySize = sort(toRel(ws.facts), isShorterTuple); @@ -690,7 +666,7 @@ Maybe[tuple[loc, set[loc], bool]] rascalGetKeywordLocs(str fieldName, d:(Declara default Maybe[tuple[loc, set[loc], bool]] rascalGetKeywordLocs(str _, Tree _) = nothing(); -private DefsUsesRenames rascalGetFieldDefsUses(WorkspaceInfo ws, set[loc] reachableModules, AType containerType, AType fieldType, str cursorName) { +private DefsUsesRenames rascalGetFieldDefsUses(TModel ws, set[loc] reachableModules, AType containerType, AType fieldType, str cursorName) { set[loc] containerFacts = {f | f <- factsInvert(ws)[containerType], f.top in reachableModules}; rel[loc file, loc u] factsByModule = groupBy(containerFacts, loc(loc l) { return l.top; }); @@ -717,7 +693,7 @@ private DefsUsesRenames rascalGetFieldDefsUses(WorkspaceInfo ws, set[loc] reacha return ; } -DefsUsesRenames rascalGetDefsUses(WorkspaceInfo ws, cursor(moduleName(), cursorLoc, cursorName), MayOverloadFun _, ChangeAnnotationRegister registerChangeAnnotation) { +DefsUsesRenames rascalGetDefsUses(TModel ws, cursor(moduleName(), cursorLoc, cursorName), MayOverloadFun _, ChangeAnnotationRegister registerChangeAnnotation, PathConfig(loc) getPathConfig) { loc moduleFile = |unknown:///|; if (d <- ws.useDef[cursorLoc], amodule(_) := ws.facts[d]) { // Cursor is at an import @@ -734,7 +710,7 @@ DefsUsesRenames rascalGetDefsUses(WorkspaceInfo ws, cursor(moduleName(), cursorL } } - modName = getModuleName(moduleFile, ws.getPathConfig(getProjectFolder(ws, moduleFile))); + modName = getModuleName(moduleFile, getPathConfig(getProjectFolder(ws, moduleFile))); defs = {parseModuleWithSpacesCached(moduleFile).top.header.name.names[-1].src};