diff --git a/CHANGELOG.md b/CHANGELOG.md index e957cdf72..8ab615cee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Code Lenses for functions (experimetal). `rescript.settings.codeLens: true`. Turned off by default. https://github.com/rescript-lang/rescript-vscode/pull/513 - Markdown code blocks tagged as `rescript` now get basic syntax highlighting. https://github.com/rescript-lang/rescript-vscode/pull/97 - Hover support for doc comments on v10 compiler `/** this is a doc comment */` +- Code action to convert type to module. https://github.com/rescript-lang/rescript-vscode/issues/430 #### :bug: Bug Fix diff --git a/analysis/src/CodeActions.ml b/analysis/src/CodeActions.ml index 844e25bce..9c5fd3125 100644 --- a/analysis/src/CodeActions.ml +++ b/analysis/src/CodeActions.ml @@ -5,13 +5,4 @@ let stringifyCodeActions codeActions = Printf.sprintf {|%s|} (codeActions |> List.map Protocol.stringifyCodeAction |> Protocol.array) -let make ~title ~kind ~uri ~newText ~range = - { - Protocol.title; - codeActionKind = kind; - edit = - { - documentChanges = - [{textDocument = {version = None; uri}; edits = [{newText; range}]}]; - }; - } +let make ~title ~kind ~edit = {Protocol.title; codeActionKind = kind; edit} diff --git a/analysis/src/Commands.ml b/analysis/src/Commands.ml index 5fcbca9ac..bc248473c 100644 --- a/analysis/src/Commands.ml +++ b/analysis/src/Commands.ml @@ -175,73 +175,9 @@ let references ~path ~pos ~debug = let rename ~path ~pos ~newName ~debug = let result = - match Cmt.fullFromPath ~path with + match Rename.command ~path ~pos ~newName ~debug with + | Some workspaceEdit -> workspaceEdit |> Protocol.stringifyWorkspaceEdit | None -> Protocol.null - | Some full -> ( - match References.getLocItem ~full ~pos ~debug with - | None -> Protocol.null - | Some locItem -> - let allReferences = References.allReferencesForLocItem ~full locItem in - let referencesToToplevelModules = - allReferences - |> Utils.filterMap (fun {References.uri = uri2; locOpt} -> - if locOpt = None then Some uri2 else None) - in - let referencesToItems = - allReferences - |> Utils.filterMap (function - | {References.uri = uri2; locOpt = Some loc} -> Some (uri2, loc) - | {locOpt = None} -> None) - in - let fileRenames = - referencesToToplevelModules - |> List.map (fun uri -> - let path = Uri.toPath uri in - let dir = Filename.dirname path in - let newPath = - Filename.concat dir (newName ^ Filename.extension path) - in - let newUri = Uri.fromPath newPath in - Protocol. - { - oldUri = uri |> Uri.toString; - newUri = newUri |> Uri.toString; - }) - in - let textDocumentEdits = - let module StringMap = Misc.StringMap in - let textEditsByUri = - referencesToItems - |> List.map (fun (uri, loc) -> (Uri.toString uri, loc)) - |> List.fold_left - (fun acc (uri, loc) -> - let textEdit = - Protocol. - {range = Utils.cmtLocToRange loc; newText = newName} - in - match StringMap.find_opt uri acc with - | None -> StringMap.add uri [textEdit] acc - | Some prevEdits -> - StringMap.add uri (textEdit :: prevEdits) acc) - StringMap.empty - in - StringMap.fold - (fun uri edits acc -> - let textDocumentEdit = - Protocol.{textDocument = {uri; version = None}; edits} - in - textDocumentEdit :: acc) - textEditsByUri [] - in - let fileRenamesString = - fileRenames |> List.map Protocol.stringifyRenameFile - in - let textDocumentEditsString = - textDocumentEdits |> List.map Protocol.stringifyTextDocumentEdit - in - "[\n" - ^ (fileRenamesString @ textDocumentEditsString |> String.concat ",\n") - ^ "\n]") in print_endline result @@ -383,15 +319,20 @@ let test ~path = |> List.iter (fun {Protocol.title; edit = {documentChanges}} -> Printf.printf "Hit: %s\n" title; documentChanges - |> List.iter (fun {Protocol.edits} -> - edits - |> List.iter (fun {Protocol.range; newText} -> - let indent = - String.make range.start.character ' ' - in - Printf.printf "%s\nnewText:\n%s<--here\n%s%s\n" - (Protocol.stringifyRange range) - indent indent newText))) + |> List.iter + (fun (documentChange : Protocol.documentChange) -> + match documentChange with + | TextDocumentEdit {edits} -> + edits + |> List.iter (fun {Protocol.range; newText} -> + let indent = + String.make range.start.character ' ' + in + Printf.printf + "%s\nnewText:\n%s<--here\n%s%s\n" + (Protocol.stringifyRange range) + indent indent newText) + | _ -> ())) | "dia" -> diagnosticSyntax ~path | "hin" -> let line_start = 0 in diff --git a/analysis/src/Protocol.ml b/analysis/src/Protocol.ml index a1440aa85..3f56ae125 100644 --- a/analysis/src/Protocol.ml +++ b/analysis/src/Protocol.ml @@ -41,13 +41,17 @@ type textDocumentEdit = { edits: textEdit list; } -type codeActionEdit = {documentChanges: textDocumentEdit list} +type documentChange = + | TextDocumentEdit of textDocumentEdit + | RenameFile of renameFile + +type workspaceEdit = {documentChanges: documentChange list} type codeActionKind = RefactorRewrite type codeAction = { title: string; codeActionKind: codeActionKind; - edit: codeActionEdit; + edit: workspaceEdit; } let null = "null" @@ -133,14 +137,19 @@ let codeActionKindToString kind = match kind with | RefactorRewrite -> "refactor.rewrite" -let stringifyCodeActionEdit cae = +let stringifyWorkspaceEdit we = Printf.sprintf {|{"documentChanges": %s}|} - (cae.documentChanges |> List.map stringifyTextDocumentEdit |> array) + (we.documentChanges + |> List.map (fun documentChange -> + match documentChange with + | TextDocumentEdit textEdit -> textEdit |> stringifyTextDocumentEdit + | RenameFile renameFile -> renameFile |> stringifyRenameFile) + |> array) let stringifyCodeAction ca = Printf.sprintf {|{"title": "%s", "kind": "%s", "edit": %s}|} ca.title (codeActionKindToString ca.codeActionKind) - (ca.edit |> stringifyCodeActionEdit) + (ca.edit |> stringifyWorkspaceEdit) let stringifyHint hint = Printf.sprintf diff --git a/analysis/src/Rename.ml b/analysis/src/Rename.ml new file mode 100644 index 000000000..231e538e0 --- /dev/null +++ b/analysis/src/Rename.ml @@ -0,0 +1,58 @@ +let command ~path ~pos ~newName ~debug = + match Cmt.fullFromPath ~path with + | None -> None + | Some full -> ( + match References.getLocItem ~full ~pos ~debug with + | None -> None + | Some locItem -> + let allReferences = References.allReferencesForLocItem ~full locItem in + let referencesToToplevelModules = + allReferences + |> Utils.filterMap (fun {References.uri = uri2; locOpt} -> + if locOpt = None then Some uri2 else None) + in + let referencesToItems = + allReferences + |> Utils.filterMap (function + | {References.uri = uri2; locOpt = Some loc} -> Some (uri2, loc) + | {locOpt = None} -> None) + in + let fileRenames = + referencesToToplevelModules + |> List.map (fun uri -> + let path = Uri.toPath uri in + let dir = Filename.dirname path in + let newPath = + Filename.concat dir (newName ^ Filename.extension path) + in + let newUri = Uri.fromPath newPath in + Protocol.RenameFile + {oldUri = uri |> Uri.toString; newUri = newUri |> Uri.toString}) + in + let textDocumentEdits = + let module StringMap = Misc.StringMap in + let textEditsByUri = + referencesToItems + |> List.map (fun (uri, loc) -> (Uri.toString uri, loc)) + |> List.fold_left + (fun acc (uri, loc) -> + let textEdit = + Protocol.{range = Utils.cmtLocToRange loc; newText = newName} + in + match StringMap.find_opt uri acc with + | None -> StringMap.add uri [textEdit] acc + | Some prevEdits -> + StringMap.add uri (textEdit :: prevEdits) acc) + StringMap.empty + in + StringMap.fold + (fun uri edits acc -> + let textDocumentEdit = + Protocol.TextDocumentEdit + {textDocument = {uri; version = None}; edits} + in + textDocumentEdit :: acc) + textEditsByUri [] + in + let documentChanges = fileRenames @ textDocumentEdits in + Some Protocol.{documentChanges}) diff --git a/analysis/src/Xform.ml b/analysis/src/Xform.ml index a402ca92e..6616fc873 100644 --- a/analysis/src/Xform.ml +++ b/analysis/src/Xform.ml @@ -110,9 +110,20 @@ module IfThenElse = struct | Some newExpr -> let range = rangeOfLoc newExpr.pexp_loc in let newText = printExpr ~range newExpr in + let uri = Uri.fromPath path |> Uri.toString in let codeAction = CodeActions.make ~title:"Replace with switch" ~kind:RefactorRewrite - ~uri:path ~newText ~range + ~edit: + { + documentChanges = + [ + TextDocumentEdit + { + textDocument = {version = None; uri}; + edits = [{newText; range}]; + }; + ]; + } in codeActions := codeAction :: !codeActions end @@ -174,9 +185,20 @@ module AddBracesToFn = struct | Some newStructureItem -> let range = rangeOfLoc newStructureItem.pstr_loc in let newText = printStructureItem ~range newStructureItem in + let uri = Uri.fromPath path |> Uri.toString in let codeAction = CodeActions.make ~title:"Add braces to function" ~kind:RefactorRewrite - ~uri:path ~newText ~range + ~edit: + { + documentChanges = + [ + TextDocumentEdit + { + textDocument = {version = None; uri}; + edits = [{newText; range}]; + }; + ]; + } in codeActions := codeAction :: !codeActions end @@ -249,14 +271,144 @@ module AddTypeAnnotation = struct ( rangeOfLoc locItem.loc, "(" ^ name ^ ": " ^ (typ |> Shared.typeToString) ^ ")" ) in + let uri = Uri.fromPath path |> Uri.toString in let codeAction = CodeActions.make ~title:"Add type annotation" ~kind:RefactorRewrite - ~uri:path ~newText ~range + ~edit: + { + documentChanges = + [ + TextDocumentEdit + { + textDocument = {version = None; uri}; + edits = [{newText; range}]; + }; + ]; + } in codeActions := codeAction :: !codeActions | _ -> ())) end +module TypeToModule = struct + (* Convert type definition into its own module *) + let mkIterator ~pos ~result ~newTypeName = + let changeTypeDecl (typ : Parsetree.type_declaration) ~txt = + let manifest = typ.ptype_manifest in + Ast_helper.Type.mk + {txt; loc = typ.ptype_name.loc} + ~loc:typ.ptype_loc ~attrs:typ.ptype_attributes ~params:typ.ptype_params + ~cstrs:typ.ptype_cstrs ~kind:typ.ptype_kind ~priv:typ.ptype_private + ?manifest + in + + let structure_item (iterator : Ast_iterator.iterator) + (si : Parsetree.structure_item) = + match si.pstr_desc with + | Pstr_type (Nonrecursive, firstypeDec :: rest) + when Loc.hasPos ~pos si.pstr_loc -> + let loc = si.pstr_loc in + let firsLetterOfModule = + String.get firstypeDec.ptype_name.txt 0 + |> Char.uppercase_ascii |> String.make 1 + in + let restName = + String.sub firstypeDec.ptype_name.txt 1 + (String.length firstypeDec.ptype_name.txt - 1) + in + let modName = firsLetterOfModule ^ restName in + let newFistType = changeTypeDecl firstypeDec ~txt:newTypeName in + let restStrucTypes = + Ast_helper.Str.type_ ~loc Nonrecursive ([newFistType] @ rest) + in + let pmb_expr = Ast_helper.Mod.structure ~loc [restStrucTypes] in + let mod_expr = + Parsetree.Pstr_module + { + pmb_name = {txt = modName; loc}; + pmb_expr; + pmb_attributes = []; + pmb_loc = loc; + } + in + let processTypeKind (typeDec : Parsetree.type_declaration) = + match typeDec.ptype_kind with + | Ptype_record [{pld_name = {loc; txt}}; _] -> Some (loc, txt) + | Ptype_variant [{pcd_name = {loc; txt}}; _] -> Some (loc, txt) + | _ -> None + in + let references = + let referencesInfo = + [firstypeDec] @ rest |> List.filter_map processTypeKind + in + [(firstypeDec.ptype_name.loc, newTypeName)] @ referencesInfo + in + result := Some (Ast_helper.Str.mk ~loc mod_expr, references, modName); + Ast_iterator.default_iterator.structure_item iterator si + | _ -> () + in + {Ast_iterator.default_iterator with structure_item} + + let xform ~path ~pos ~codeActions ~printStructureItem structure ~debug = + let result = ref None in + let newTypeName = "t" in + let iterator = mkIterator ~pos ~result ~newTypeName in + iterator.structure iterator structure; + match !result with + | None -> () + | Some (newStructureItem, references, modName) -> + let range = rangeOfLoc newStructureItem.pstr_loc in + let newText = printStructureItem ~range newStructureItem in + let uri = Uri.fromPath path |> Uri.toString in + let typeToModuleEdit = + Protocol.TextDocumentEdit + {textDocument = {version = None; uri}; edits = [{newText; range}]} + in + (* Before apply code action find all references and rename with new name *) + let relatedChanges = + references + |> List.filter_map (fun (loc, txt) -> + let range = rangeOfLoc loc in + let newName = modName ^ "." ^ txt in + match + Rename.command ~path + ~pos:(range.start.line, range.start.character) + ~newName ~debug + with + | Some workspaceEdit -> + let result = + workspaceEdit.documentChanges + |> List.map + (fun (documentChange : Protocol.documentChange) -> + match documentChange with + | TextDocumentEdit textEdit -> + let textDocument = textEdit.textDocument in + let edits = + if textDocument.uri = uri then + textEdit.edits + |> List.filter + (fun (textEdit : Protocol.textEdit) -> + (* Ignore some text edit because it refers to the type that will be moved to its own module *) + textEdit.range <> range) + else textEdit.edits + in + Protocol.TextDocumentEdit {textDocument; edits} + | _ -> documentChange) + in + Some result + | None -> None) + |> List.flatten + in + let edit : Protocol.workspaceEdit = + {documentChanges = [typeToModuleEdit] @ relatedChanges} + in + let codeAction = + CodeActions.make ~title:"Move type definition into its own module" + ~kind:RefactorRewrite ~edit + in + codeActions := codeAction :: !codeActions +end + let indent n text = let spaces = String.make n ' ' in let len = String.length text in @@ -310,5 +462,7 @@ let extractCodeActions ~path ~pos ~currentFile ~debug = AddTypeAnnotation.xform ~path ~pos ~full ~structure ~codeActions ~debug; IfThenElse.xform ~pos ~codeActions ~printExpr ~path structure; AddBracesToFn.xform ~pos ~codeActions ~path ~printStructureItem structure; + TypeToModule.xform ~path ~pos ~codeActions ~printStructureItem structure + ~debug; !codeActions | _ -> [] diff --git a/analysis/tests/src/Xform.res b/analysis/tests/src/Xform.res index 52baad9d8..15ed72964 100644 --- a/analysis/tests/src/Xform.res +++ b/analysis/tests/src/Xform.res @@ -65,3 +65,42 @@ let bar = () => { } Inner.foo(1) } + +type readState = New | Unread | Read +//^xfm + +type refState = readState + +type account = + | None + | Instagram(string) + | Facebook(string, int) +//^xfm + +type person = { + "age": int, + "name": string +} +//^xfm + +type user = { + name: string, + age: int, +} and response = Yes | No +//^xfm + +type myType = This | That +//^xfm + +let fun1 = (x: myType) => x + +let fun2 = b => b ? This : That + +let fun3 = b => b ? {name: "Lhs", age: 2} : {name: "Rhs", age: 3} + +let fun4 = b => b ? Yes : No + +let me: person = { + "age": 5, + "name": "Big ReScript" +} \ No newline at end of file diff --git a/analysis/tests/src/expected/Cross.res.txt b/analysis/tests/src/expected/Cross.res.txt index b045e8a02..013485cfa 100644 --- a/analysis/tests/src/expected/Cross.res.txt +++ b/analysis/tests/src/expected/Cross.res.txt @@ -18,18 +18,15 @@ References src/Cross.res 9:31 ] Rename src/Cross.res 18:13 RenameWithInterfacePrime -[ -{ +{"documentChanges": [{ "kind": "rename", "oldUri": "RenameWithInterface.resi", "newUri": "RenameWithInterfacePrime.resi" -}, -{ +}, { "kind": "rename", "oldUri": "RenameWithInterface.res", "newUri": "RenameWithInterfacePrime.res" -}, -{ +}, { "textDocument": { "version": null, "uri": "Cross.res" @@ -41,12 +38,10 @@ Rename src/Cross.res 18:13 RenameWithInterfacePrime "range": {"start": {"line": 21, "character": 8}, "end": {"line": 21, "character": 27}}, "newText": "RenameWithInterfacePrime" }] - } -] + }]} Rename src/Cross.res 21:28 xPrime -[ -{ +{"documentChanges": [{ "textDocument": { "version": null, "uri": "RenameWithInterface.resi" @@ -55,8 +50,7 @@ Rename src/Cross.res 21:28 xPrime "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, "newText": "xPrime" }] - }, -{ + }, { "textDocument": { "version": null, "uri": "RenameWithInterface.res" @@ -65,8 +59,7 @@ Rename src/Cross.res 21:28 xPrime "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, "newText": "xPrime" }] - }, -{ + }, { "textDocument": { "version": null, "uri": "Cross.res" @@ -78,8 +71,7 @@ Rename src/Cross.res 21:28 xPrime "range": {"start": {"line": 21, "character": 28}, "end": {"line": 21, "character": 29}}, "newText": "xPrime" }] - } -] + }]} TypeDefinition src/Cross.res 24:5 {"uri": "TypeDefinition.res", "range": {"start": {"line": 2, "character": 0}, "end": {"line": 2, "character": 28}}} diff --git a/analysis/tests/src/expected/Rename.res.txt b/analysis/tests/src/expected/Rename.res.txt index 5cd2adfee..6b6d6cc68 100644 --- a/analysis/tests/src/expected/Rename.res.txt +++ b/analysis/tests/src/expected/Rename.res.txt @@ -1,6 +1,5 @@ Rename src/Rename.res 0:4 y -[ -{ +{"documentChanges": [{ "textDocument": { "version": null, "uri": "Rename.res" @@ -15,12 +14,10 @@ Rename src/Rename.res 0:4 y "range": {"start": {"line": 7, "character": 8}, "end": {"line": 7, "character": 9}}, "newText": "y" }] - } -] + }]} Rename src/Rename.res 9:19 yy -[ -{ +{"documentChanges": [{ "textDocument": { "version": null, "uri": "Rename.res" @@ -32,6 +29,5 @@ Rename src/Rename.res 9:19 yy "range": {"start": {"line": 9, "character": 19}, "end": {"line": 9, "character": 21}}, "newText": "yy" }] - } -] + }]} diff --git a/analysis/tests/src/expected/RenameWithInterface.res.txt b/analysis/tests/src/expected/RenameWithInterface.res.txt index a13988fa9..10c866089 100644 --- a/analysis/tests/src/expected/RenameWithInterface.res.txt +++ b/analysis/tests/src/expected/RenameWithInterface.res.txt @@ -1,6 +1,5 @@ Rename src/RenameWithInterface.res 0:4 y -[ -{ +{"documentChanges": [{ "textDocument": { "version": null, "uri": "RenameWithInterface.resi" @@ -9,8 +8,7 @@ Rename src/RenameWithInterface.res 0:4 y "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, "newText": "y" }] - }, -{ + }, { "textDocument": { "version": null, "uri": "RenameWithInterface.res" @@ -19,8 +17,7 @@ Rename src/RenameWithInterface.res 0:4 y "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, "newText": "y" }] - }, -{ + }, { "textDocument": { "version": null, "uri": "Cross.res" @@ -32,6 +29,5 @@ Rename src/RenameWithInterface.res 0:4 y "range": {"start": {"line": 21, "character": 28}, "end": {"line": 21, "character": 29}}, "newText": "y" }] - } -] + }]} diff --git a/analysis/tests/src/expected/RenameWithInterface.resi.txt b/analysis/tests/src/expected/RenameWithInterface.resi.txt index 2a1dabb44..4a9c40d36 100644 --- a/analysis/tests/src/expected/RenameWithInterface.resi.txt +++ b/analysis/tests/src/expected/RenameWithInterface.resi.txt @@ -1,6 +1,5 @@ Rename src/RenameWithInterface.resi 0:4 y -[ -{ +{"documentChanges": [{ "textDocument": { "version": null, "uri": "RenameWithInterface.resi" @@ -9,8 +8,7 @@ Rename src/RenameWithInterface.resi 0:4 y "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, "newText": "y" }] - }, -{ + }, { "textDocument": { "version": null, "uri": "RenameWithInterface.res" @@ -19,8 +17,7 @@ Rename src/RenameWithInterface.resi 0:4 y "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, "newText": "y" }] - }, -{ + }, { "textDocument": { "version": null, "uri": "Cross.res" @@ -32,6 +29,5 @@ Rename src/RenameWithInterface.resi 0:4 y "range": {"start": {"line": 21, "character": 28}, "end": {"line": 21, "character": 29}}, "newText": "y" }] - } -] + }]} diff --git a/analysis/tests/src/expected/Xform.res.txt b/analysis/tests/src/expected/Xform.res.txt index d298604ae..504ca9bcf 100644 --- a/analysis/tests/src/expected/Xform.res.txt +++ b/analysis/tests/src/expected/Xform.res.txt @@ -99,3 +99,72 @@ newText: } } +Xform src/Xform.res 68:2 +Hit: Move type definition into its own module +{"start": {"line": 68, "character": 0}, "end": {"line": 68, "character": 36}} +newText: +<--here +module ReadState = { + type t = New | Unread | Read +} +{"start": {"line": 71, "character": 16}, "end": {"line": 71, "character": 25}} +newText: + <--here + ReadState.t + +Xform src/Xform.res 76:2 +Hit: Move type definition into its own module +{"start": {"line": 73, "character": 0}, "end": {"line": 76, "character": 25}} +newText: +<--here +module Account = { + type t = + | None + | Instagram(string) + | Facebook(string, int) +} + +Xform src/Xform.res 82:2 + +Xform src/Xform.res 88:2 +Hit: Move type definition into its own module +{"start": {"line": 85, "character": 0}, "end": {"line": 88, "character": 25}} +newText: +<--here +module User = { + type t = { + name: string, + age: int, + } + and response = Yes | No +} +{"start": {"line": 98, "character": 21}, "end": {"line": 98, "character": 25}} +newText: + <--here + User.name +{"start": {"line": 98, "character": 45}, "end": {"line": 98, "character": 49}} +newText: + <--here + User.name +{"start": {"line": 100, "character": 20}, "end": {"line": 100, "character": 23}} +newText: + <--here + User.Yes + +Xform src/Xform.res 91:2 +Hit: Move type definition into its own module +{"start": {"line": 91, "character": 0}, "end": {"line": 91, "character": 25}} +newText: +<--here +module MyType = { + type t = This | That +} +{"start": {"line": 94, "character": 15}, "end": {"line": 94, "character": 21}} +newText: + <--here + MyType.t +{"start": {"line": 96, "character": 20}, "end": {"line": 96, "character": 24}} +newText: + <--here + MyType.This + diff --git a/server/src/server.ts b/server/src/server.ts index 130aa604e..a5d33c034 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -531,7 +531,7 @@ function rename(msg: p.RequestMessage) { // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename let params = msg.params as p.RenameParams; let filePath = fileURLToPath(params.textDocument.uri); - let documentChanges: (p.RenameFile | p.TextDocumentEdit)[] | null = + let result: WorkspaceEdit | null = utils.runAnalysisAfterSanityCheck(filePath, [ "rename", filePath, @@ -539,10 +539,6 @@ function rename(msg: p.RequestMessage) { params.position.character, params.newName, ]); - let result: WorkspaceEdit | null = null; - if (documentChanges !== null) { - result = { documentChanges }; - } let response: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id,