diff --git a/src/rescript-editor-support/EditorSupportCommands.re b/src/rescript-editor-support/EditorSupportCommands.re index e84d71dc..1836b801 100644 --- a/src/rescript-editor-support/EditorSupportCommands.re +++ b/src/rescript-editor-support/EditorSupportCommands.re @@ -84,7 +84,8 @@ let dumpLocations = (state, ~package, ~file, ~extra, ~selectPos, uri) => { "definition", J.o( uriIsCurrentFile - ? [range] : [("uri", Json.String(uri2)), range], + ? [range] + : [("uri", Json.String(Uri2.toString(uri2))), range], ), ), ], @@ -121,13 +122,12 @@ let splitLineChar = pathWithPos => { let dump = files => { Shared.cacheTypeToString := true; let rootPath = Unix.getcwd(); - let emptyState = TopTypes.empty(); - let state = {...emptyState, rootUri: Utils.toUri(rootPath)}; + let state = TopTypes.empty(~rootUri=Uri2.fromPath(rootPath)); files |> List.iter(pathWithPos => { let (filePath, selectPos) = pathWithPos |> splitLineChar; let filePath = Files.maybeConcat(Unix.getcwd(), filePath); - let uri = Utils.toUri(filePath); + let uri = Uri2.fromPath(filePath); let result = switch (State.getFullFromCmt(~state, ~uri)) { | Error(message) => @@ -155,12 +155,11 @@ let autocomplete = (~currentFile, ~full, ~package, ~pos, ~state) => { let complete = (~pathWithPos, ~currentFile) => { let rootPath = Unix.getcwd(); - let emptyState = TopTypes.empty(); - let state = {...emptyState, rootUri: Utils.toUri(rootPath)}; + let state = TopTypes.empty(~rootUri=Uri2.fromPath(rootPath)); switch (pathWithPos |> splitLineChar) { | (filePath, Some(pos)) => let filePath = Files.maybeConcat(Unix.getcwd(), filePath); - let uri = Utils.toUri(filePath); + let uri = Uri2.fromPath(filePath); let result = switch (State.getFullFromCmt(~state, ~uri)) { | Error(message) => diff --git a/src/rescript-editor-support/Hover.re b/src/rescript-editor-support/Hover.re index b90ad170..fd1f0ca6 100644 --- a/src/rescript-editor-support/Hover.re +++ b/src/rescript-editor-support/Hover.re @@ -139,9 +139,7 @@ let newHover = (~rootUri, ~file: SharedTypes.file, ~getModule, loc) => { let (typeString, docstring) = t |> fromType(~docstring=None); [typeString, docstring]; | Some((docstring, {uri}, res)) => - let uri = - Utils.startsWith(uri, rootUri) - ? "" ++ Utils.sliceToEnd(uri, String.length(rootUri)) : uri; + let pathFromRoot = uri |> Uri2.pathFromRoot(~rootUri); let parts = switch (res) { @@ -167,7 +165,7 @@ let newHover = (~rootUri, ~file: SharedTypes.file, ~getModule, loc) => { [typeString, docstring]; }; - parts @ [Some(uri)]; + parts @ [Some(pathFromRoot)]; }; Some(String.concat("\n\n", parts |> Utils.filterMap(x => x))); diff --git a/src/rescript-editor-support/MessageHandlers.re b/src/rescript-editor-support/MessageHandlers.re index d98ac634..e92f35dc 100644 --- a/src/rescript-editor-support/MessageHandlers.re +++ b/src/rescript-editor-support/MessageHandlers.re @@ -27,7 +27,7 @@ let handlers: Ok(( state, Json.Object([ - ("uri", Json.String(uri)), + ("uri", Json.String(Uri2.toString(uri))), ("range", Protocol.rangeOfLoc(loc)), ]), )), @@ -164,7 +164,7 @@ let handlers: allReferences |> List.map(((fname, references)) => ( - fname, + fname |> Uri2.toString, J.l( references |> List.map(loc => @@ -195,6 +195,7 @@ let handlers: |> RJson.get("textDocument") |?> RJson.get("uri") |?> RJson.string; + let%try uri = Uri2.parse(uri) |> RResult.orError("Not a uri"); /* Log.log("<< codleens me please"); */ @@ -307,6 +308,7 @@ let handlers: |> RJson.get("textDocument") |?> RJson.get("uri") |?> RJson.string; + let%try uri = Uri2.parse(uri) |> RResult.orError("Not a uri"); let%try (file, _extra) = State.fileForUri(state, uri); open SharedTypes; diff --git a/src/rescript-editor-support/NewCompletions.re b/src/rescript-editor-support/NewCompletions.re index dd97521b..f4da1636 100644 --- a/src/rescript-editor-support/NewCompletions.re +++ b/src/rescript-editor-support/NewCompletions.re @@ -210,7 +210,7 @@ let getEnvWithOpens = let rec loop = opens => switch (opens) { | [env, ...rest] => - Log.log("Looking for env in " ++ env.Query.file.uri); + Log.log("Looking for env in " ++ Uri2.toString(env.Query.file.uri)); switch (Query.resolvePath(~env, ~getModule, ~path)) { | Some(x) => Some(x) | None => loop(rest) @@ -313,7 +313,7 @@ let localValueCompletions = (~pos, ~env: Query.queryEnv, suffix) => { }; let valueCompletions = (~env: Query.queryEnv, suffix) => { - Log.log(" - Completing in " ++ env.file.uri); + Log.log(" - Completing in " ++ Uri2.toString(env.file.uri)); let results = []; let results = if (suffix == "" || isCapitalized(suffix)) { @@ -450,7 +450,10 @@ let getItems = "Opens nows " ++ string_of_int(List.length(opens)) ++ " " - ++ String.concat(" ", opens |> List.map(e => e.Query.file.uri)), + ++ String.concat( + " ", + opens |> List.map(e => Uri2.toString(e.Query.file.uri)), + ), ); switch (parts) { @@ -488,7 +491,7 @@ let getItems = /* Log.log("Checking " ++ name); */ Utils.startsWith(name, suffix) && !String.contains(name, '-') ? Some(( - "wait for uri", + env.file.uri, {...emptyDeclared(name), item: FileModule(name)}, )) : None @@ -636,7 +639,7 @@ let computeCompletions = (~full, ~maybeText, ~package, ~pos, ~state) => { J.s( (docstring |? "No docs") ++ "\n\n" - ++ uri + ++ Uri2.toString(uri) ++ ":" ++ string_of_int(pos_lnum), ), diff --git a/src/rescript-editor-support/NotificationHandlers.re b/src/rescript-editor-support/NotificationHandlers.re index c7cb921c..612f5cdf 100644 --- a/src/rescript-editor-support/NotificationHandlers.re +++ b/src/rescript-editor-support/NotificationHandlers.re @@ -4,16 +4,17 @@ open TopTypes; module J = JsonShort; let getTextDocument = doc => { - let%opt uri = Json.get("uri", doc) |?> Json.string; + let%opt uri = Json.get("uri", doc) |?> Json.string |?> Uri2.parse; let%opt text = Json.get("text", doc) |?> Json.string; Some((uri, text)); }; -let watchedFileContentsMap = Hashtbl.create(100); - let reloadAllState = state => { Log.log("RELOADING ALL STATE"); - {...TopTypes.empty(), documentText: state.documentText}; + { + ...TopTypes.empty(~rootUri=state.rootUri), + documentText: state.documentText, + }; }; let notificationHandlers: @@ -27,7 +28,7 @@ let notificationHandlers: |> RResult.orError("Invalid params"); Hashtbl.replace(state.documentText, uri, text); - let%try path = Utils.parseUri(uri) |> RResult.orError("Invalid uri"); + let path = Uri2.toPath(uri); if (FindFiles.isSourceFile(path)) { let%try package = Packages.getPackage(uri, state); /* let name = FindFiles.getName(path); */ @@ -71,6 +72,7 @@ let notificationHandlers: open InfixResult; let%try doc = params |> RJson.get("textDocument"); let%try uri = RJson.get("uri", doc) |?> RJson.string; + let%try uri = Uri2.parse(uri) |> RResult.orError("Not a uri"); let%try changes = RJson.get("contentChanges", params) |?> RJson.array; let%try text = List.nth(changes, List.length(changes) - 1) @@ -83,41 +85,8 @@ let notificationHandlers: ), ( "workspace/didChangeWatchedFiles", - (state, params) => { - Log.log("Got a watched file change"); - let%try changes = RJson.get("changes", params); - let%try changes = RJson.array(changes); - open InfixResult; - let shouldReload = - changes - |> List.exists(change => - { - let%try uri = RJson.get("uri", change) |?> RJson.string; - let isRelevant = Utils.endsWith(uri, "/bsconfig.json"); - if (!isRelevant) { - Ok(false); - } else { - let%try path = - Utils.parseUri(uri) |> RResult.orError("Cannot parse URI"); - let%try contents = Files.readFileResult(path); - if (!Hashtbl.mem(watchedFileContentsMap, uri) - || Hashtbl.find(watchedFileContentsMap, uri) == contents) { - Ok(false); - } else { - Hashtbl.replace(watchedFileContentsMap, uri, contents); - Log.log("Reloading because a file changed: " ++ uri); - Ok(true); - }; - }; - } - |? false - ); - - if (shouldReload) { - Ok(reloadAllState(state)); - } else { - Ok(state); - }; + (state, _params) => { + Ok(state); }, ), ]; diff --git a/src/rescript-editor-support/Packages.re b/src/rescript-editor-support/Packages.re index 9a6780cf..16f1d6c7 100644 --- a/src/rescript-editor-support/Packages.re +++ b/src/rescript-editor-support/Packages.re @@ -149,8 +149,8 @@ let newBsPackage = rootPath => { }; }; -let findRoot = (uri, packagesByRoot) => { - let%opt path = Utils.parseUri(uri); +let findRoot = (~uri, packagesByRoot) => { + let path = Uri2.toPath(uri); let rec loop = path => if (path == "/") { None; @@ -164,7 +164,7 @@ let findRoot = (uri, packagesByRoot) => { loop(Filename.dirname(path)); }; -let getPackage = (uri, state) => +let getPackage = (~uri, state) => if (Hashtbl.mem(state.rootForUri, uri)) { Ok( Hashtbl.find( @@ -174,7 +174,7 @@ let getPackage = (uri, state) => ); } else { let%try root = - findRoot(uri, state.packagesByRoot) + findRoot(~uri, state.packagesByRoot) |> RResult.orError("No root directory found"); let%try package = switch (root) { diff --git a/src/rescript-editor-support/ProcessCmt.re b/src/rescript-editor-support/ProcessCmt.re index 631f2a50..571bfb18 100644 --- a/src/rescript-editor-support/ProcessCmt.re +++ b/src/rescript-editor-support/ProcessCmt.re @@ -574,7 +574,7 @@ and forStructure = (~env, items) => { let forCmt = ( ~moduleName, - uri, + ~uri, processDoc, {cmt_modname, cmt_annots}: Cmt_format.cmt_infos, ) => diff --git a/src/rescript-editor-support/Process_406.re b/src/rescript-editor-support/Process_406.re index 36ed796d..f5918f79 100644 --- a/src/rescript-editor-support/Process_406.re +++ b/src/rescript-editor-support/Process_406.re @@ -1,13 +1,13 @@ open SharedTypes; -let fileForCmt = (~moduleName, cmt, uri, processDoc) => { +let fileForCmt = (~moduleName, ~uri, cmt, processDoc) => { let%try infos = Shared.tryReadCmt(cmt); - Ok(ProcessCmt.forCmt(~moduleName, uri, processDoc, infos)); + Ok(ProcessCmt.forCmt(~moduleName, ~uri, processDoc, infos)); }; -let fullForCmt = (~moduleName, cmt, uri, processDoc) => { +let fullForCmt = (~moduleName, ~uri, cmt, processDoc) => { let%try infos = Shared.tryReadCmt(cmt); - let file = ProcessCmt.forCmt(~moduleName, uri, processDoc, infos); + let file = ProcessCmt.forCmt(~moduleName, ~uri, processDoc, infos); let extra = ProcessExtra.forCmt(~file, infos); Ok({file, extra}); }; diff --git a/src/rescript-editor-support/Process_406.rei b/src/rescript-editor-support/Process_406.rei index 37044257..e8fbabb1 100644 --- a/src/rescript-editor-support/Process_406.rei +++ b/src/rescript-editor-support/Process_406.rei @@ -1,7 +1,7 @@ let fileForCmt: - (~moduleName: string, string, string, string => string) => + (~moduleName: string, ~uri: Uri2.t, string, string => string) => result(SharedTypes.file, string); let fullForCmt: - (~moduleName: string, string, string, string => string) => + (~moduleName: string, ~uri: Uri2.t, string, string => string) => result(SharedTypes.full, string); diff --git a/src/rescript-editor-support/Protocol.re b/src/rescript-editor-support/Protocol.re index 07aa0e10..4679b0b3 100644 --- a/src/rescript-editor-support/Protocol.re +++ b/src/rescript-editor-support/Protocol.re @@ -11,6 +11,7 @@ let rPositionParams = params => { open RResult.InfixResult; let%try uri = RJson.get("textDocument", params) |?> RJson.get("uri") |?> RJson.string; + let%try uri = Uri2.parse(uri) |> RResult.orError("Not a uri"); let%try pos = RJson.get("position", params) |?> rgetPosition; Ok((uri, pos)); }; @@ -28,19 +29,17 @@ let rangeOfLoc = ({Location.loc_start, loc_end}) => J.o([("start", posOfLexing(loc_start)), ("end", posOfLexing(loc_end))]); let locationOfLoc = - (~fname=?, {Location.loc_start: {Lexing.pos_fname}} as loc) => + (~fname=?, {Location.loc_start: {Lexing.pos_fname}} as loc) => { + let uri = + switch (fname) { + | Some(x) => x + | None => Uri2.fromPath(pos_fname) + }; J.o([ ("range", rangeOfLoc(loc)), - ( - "uri", - J.s( - switch (fname) { - | Some(x) => x - | None => Utils.toUri(pos_fname) - }, - ), - ), + ("uri", J.s(Uri2.toString(uri))), ]); +}; let locationContains = ({Location.loc_start, loc_end}, pos) => Utils.tupleOfLexing(loc_start) <= pos diff --git a/src/rescript-editor-support/References.re b/src/rescript-editor-support/References.re index 42fe21d5..13407c0c 100644 --- a/src/rescript-editor-support/References.re +++ b/src/rescript-editor-support/References.re @@ -97,7 +97,7 @@ let definedForLoc = (~file, ~getModule, locKind) => { ++ " " ++ string_of_int(stamp) ++ " in file " - ++ file.uri, + ++ Uri2.toString(file.uri), ); let%opt declared = Query.declaredForTip(~stamps=file.stamps, stamp, tip); @@ -144,10 +144,10 @@ let alternateDeclared = (~file, ~pathsForModule, ~getUri, declared, tip) => { switch (paths) { | IntfAndImpl(_, intf, _, impl) => maybeLog("Have both!!"); - let intf = Utils.toUri(intf); - let impl = Utils.toUri(impl); - if (intf == file.uri) { - let%opt (file, extra) = getUri(impl) |> RResult.toOptionAndLog; + let intfUri = Uri2.fromPath(intf); + let implUri = Uri2.fromPath(impl); + if (intfUri == file.uri) { + let%opt (file, extra) = getUri(implUri) |> RResult.toOptionAndLog; let%opt declared = Query.declaredForExportedTip( ~stamps=file.stamps, @@ -157,7 +157,7 @@ let alternateDeclared = (~file, ~pathsForModule, ~getUri, declared, tip) => { ); Some((file, extra, declared)); } else { - let%opt (file, extra) = getUri(intf) |> RResult.toOptionAndLog; + let%opt (file, extra) = getUri(intfUri) |> RResult.toOptionAndLog; let%opt declared = Query.declaredForExportedTip( ~stamps=file.stamps, @@ -342,7 +342,7 @@ let allReferencesForLoc = | LModule(LocalReference(stamp, tip) | Definition(stamp, tip)) => maybeLog( "Finding references for " - ++ file.uri + ++ Uri2.toString(file.uri) ++ " and stamp " ++ string_of_int(stamp) ++ " and tip " @@ -377,7 +377,7 @@ let allReferencesForLoc = let%try (file, extra) = getUri(env.file.uri); maybeLog( "Finding references for (global) " - ++ env.file.uri + ++ Uri2.toString(env.file.uri) ++ " and stamp " ++ string_of_int(stamp) ++ " and tip " @@ -435,7 +435,7 @@ let resolveModuleDefinition = (~file, ~getModule, stamp) => { let%opt (file, declared) = resolveModuleReference(~file, ~getModule, md); let loc = switch (declared) { - | None => Utils.topLoc(file.uri) + | None => Utils.topLoc(Uri2.toPath(file.uri)) | Some(declared) => validateLoc(declared.name.loc, declared.extentLoc) }; Some((file.uri, loc)); @@ -455,7 +455,7 @@ let definition = (~file, ~getModule, stamp, tip) => { let loc = validateLoc(declared.name.loc, declared.extentLoc); let env = Query.fileEnv(file); let uri = Query.getSourceUri(~env, ~getModule, declared.modulePath); - maybeLog("Inner uri " ++ uri); + maybeLog("Inner uri " ++ Uri2.toString(uri)); Some((uri, loc)); }; }; @@ -496,7 +496,7 @@ let definitionForLoc = (~pathsForModule, ~file, ~getUri, ~getModule, loc) => { |> orLog("No paths found") |?> getSrc |> orLog("No src found"); - Some((Utils.toUri(src), Utils.topLoc(src))); + Some((Uri2.fromPath(src), Utils.topLoc(src))); | LModule(LocalReference(stamp, tip)) | Typed(_, LocalReference(stamp, tip)) => maybeLog("Local defn " ++ tipToString(tip)); diff --git a/src/rescript-editor-support/RescriptEditorSupport.re b/src/rescript-editor-support/RescriptEditorSupport.re index 872469b3..c6c3e451 100644 --- a/src/rescript-editor-support/RescriptEditorSupport.re +++ b/src/rescript-editor-support/RescriptEditorSupport.re @@ -1,5 +1,4 @@ open Infix; -open RResult; module J = JsonShort; module StringSet = Set.Make(String); let capabilities = @@ -17,9 +16,10 @@ let capabilities = ]); let getInitialState = params => { - let uri = - Json.get("rootUri", params) |?> Json.string |! "Must have a rootUri"; - let%try rootPath = uri |> Utils.parseUri |> resultOfOption("No root uri"); + let rootUri = + Json.get("rootUri", params) |?> Json.string |?> Uri2.parse; + let%try rootUri = rootUri |> RResult.orError("Not a uri"); + let rootPath = Uri2.toPath(rootUri); Files.mkdirp(rootPath /+ "node_modules" /+ ".lsp"); Log.setLocation(rootPath /+ "node_modules" /+ ".lsp" /+ "debug.log"); @@ -53,7 +53,7 @@ let getInitialState = params => { ]), ); - let state = {...TopTypes.empty(), rootUri: uri}; + let state = TopTypes.empty(~rootUri); Ok(state); }; diff --git a/src/rescript-editor-support/SharedTypes.re b/src/rescript-editor-support/SharedTypes.re index be08cc19..d503fed0 100644 --- a/src/rescript-editor-support/SharedTypes.re +++ b/src/rescript-editor-support/SharedTypes.re @@ -40,9 +40,8 @@ let getCmt = (~interface=true, p) => | IntfAndImpl(cint, _, cimpl, _) => interface ? cint : cimpl }; -/* TODO maybe track the loc's of these things */ type visibilityPath = - | File(string, string) + | File(Uri2.t, string) | NotVisible | IncludedModule(Path.t, visibilityPath) | ExportedModule(string, visibilityPath); @@ -166,7 +165,7 @@ let initStamps = () => { }; type file = { - uri: string, + uri: Uri2.t, stamps, moduleName: string, contents: moduleContents, diff --git a/src/rescript-editor-support/State.re b/src/rescript-editor-support/State.re index e46818cd..89cb38af 100644 --- a/src/rescript-editor-support/State.re +++ b/src/rescript-editor-support/State.re @@ -14,9 +14,9 @@ let converter = src => { }; let newDocsForCmt = (~moduleName, cmtCache, changed, cmt, src) => { - let uri = Utils.toUri(src |? cmt); + let uri = Uri2.fromPath(src |? cmt); let%opt file = - Process_406.fileForCmt(~moduleName, cmt, uri, converter(src)) + Process_406.fileForCmt(~moduleName, ~uri, cmt, converter(src)) |> RResult.toOptionAndLog; Hashtbl.replace(cmtCache, cmt, (changed, file)); Some(file); @@ -55,14 +55,18 @@ let updateContents = (uri, text, state) => { open Infix; let getFullFromCmt = (~state, ~uri) => { - let%try path = Utils.parseUri(uri) |> RResult.orError("Not a uri"); + let path = Uri2.toPath(uri); let%try package = Packages.getPackage(uri, state); let moduleName = BuildSystem.namespacedName(package.namespace, FindFiles.getName(path)); switch (Hashtbl.find_opt(package.pathsForModule, moduleName)) { | Some(paths) => - let cmt = SharedTypes.getCmt(~interface=Utils.endsWith(uri, "i"), paths); - let%try full = Process_406.fullForCmt(~moduleName, cmt, uri, x => x); + let cmt = + SharedTypes.getCmt( + ~interface=Utils.endsWith(path, "i"), + paths, + ); + let%try full = Process_406.fullForCmt(~moduleName, ~uri, cmt, x => x); Hashtbl.replace( package.interModuleDependencies, moduleName, @@ -105,7 +109,7 @@ let extraForModule = (state, ~package, modname) => let paths = Hashtbl.find(package.pathsForModule, modname); /* TODO do better? */ let%opt src = SharedTypes.getSrc(paths); - switch (getFullFromCmt(~state, ~uri=Utils.toUri(src))) { + switch (getFullFromCmt(~state, ~uri=Uri2.fromPath(src))) { | Ok((_package, {extra})) => Some(extra) | Error(_) => None }; diff --git a/src/rescript-editor-support/TopTypes.re b/src/rescript-editor-support/TopTypes.re index c80799ec..010834c5 100644 --- a/src/rescript-editor-support/TopTypes.re +++ b/src/rescript-editor-support/TopTypes.re @@ -1,5 +1,5 @@ /* Aliases to make the intents clearer */ -type uri = string; +type uri = Uri2.t; type filePath = string; type moduleName = string; @@ -24,8 +24,8 @@ type state = { cmtCache: Hashtbl.t(filePath, (float, SharedTypes.file)), }; -let empty = () => { - rootUri: "- uninitialized -", +let empty = (~rootUri) => { + rootUri, documentText: Hashtbl.create(5), packagesByRoot: Hashtbl.create(1), rootForUri: Hashtbl.create(30), diff --git a/src/rescript-editor-support/Uri2.re b/src/rescript-editor-support/Uri2.re new file mode 100644 index 00000000..97659bc1 --- /dev/null +++ b/src/rescript-editor-support/Uri2.re @@ -0,0 +1,76 @@ +module Uri: { + type t; + let fromPath: string => t; + let parse: string => option(t); + let pathFromRoot: (~rootUri: t, t) => string; + let toPath: t => string; + let toString: t => string; +} = { + type t = { + path: string, + uri: string, + }; + + let pathToUri = path => + if (Sys.os_type == "Unix") { + "file://" ++ path; + } else { + "file://" + ++ ( + Str.global_replace(Str.regexp_string("\\"), "/", path) + |> Str.substitute_first( + Str.regexp("^\\([A-Z]\\):"), + text => { + let name = Str.matched_group(1, text); + "/" ++ String.lowercase_ascii(name) ++ "%3A"; + }, + ) + ); + }; + + let fromPath = path => {path, uri: pathToUri(path)}; + + let parseWindowsUri = withoutScheme => { + withoutScheme + |> Str.substitute_first( + Str.regexp("^/\\([a-z]\\)%3A"), + text => { + let name = Str.matched_group(1, text); + String.uppercase_ascii(name) ++ ":"; + }, + ) + /* OCaml doesn't want to do a find & replace where the replacement is a single backslash. So this works */ + |> Str.split(Str.regexp_string("/")) + |> String.concat({|\|}); + }; + + let parseUri = uri => { + let withoutPct = Uri.pct_decode(uri); + if (Utils.startsWith(withoutPct, "file://")) { + let withoutScheme = + Utils.sliceToEnd(withoutPct, String.length("file://")); + + if (Sys.os_type == "Unix") { + Some(withoutScheme); + } else { + Some(parseWindowsUri(withoutScheme)); + }; + } else { + None; + }; + }; + + let parse = uri => + switch (parseUri(uri)) { + | Some(path) => Some({uri, path}) + | None => None + }; + let toPath = ({path}) => path; + let toString = ({uri}) => uri; + + let pathFromRoot = (~rootUri as {path: rootPath}, {path}) => + Utils.startsWith(path, rootPath) + ? "" ++ Utils.sliceToEnd(path, String.length(rootPath)) : path; +}; + +include Uri; diff --git a/src/rescript-editor-support/Utils.re b/src/rescript-editor-support/Utils.re index 8b4368c3..30da43ba 100644 --- a/src/rescript-editor-support/Utils.re +++ b/src/rescript-editor-support/Utils.re @@ -66,52 +66,6 @@ let locWithinLoc = (inner, outer) => { ); }; -let toUri = path => - if (Sys.os_type == "Unix") { - "file://" ++ path; - } else { - "file://" - ++ ( - Str.global_replace(Str.regexp_string("\\"), "/", path) - |> Str.substitute_first( - Str.regexp("^\\([A-Z]\\):"), - text => { - let name = Str.matched_group(1, text); - "/" ++ String.lowercase_ascii(name) ++ "%3A"; - }, - ) - ); - }; - -let parseWindowsUri = withoutScheme => { - withoutScheme - |> Str.substitute_first( - Str.regexp("^/\\([a-z]\\)%3A"), - text => { - let name = Str.matched_group(1, text); - String.uppercase_ascii(name) ++ ":"; - }, - ) - /* OCaml doesn't want to do a find & replace where the replacement is a single backslash. So this works */ - |> Str.split(Str.regexp_string("/")) - |> String.concat({|\|}); -}; - -let parseUri = uri => { - let withoutPct = Uri.pct_decode(uri); - if (startsWith(withoutPct, "file://")) { - let withoutScheme = sliceToEnd(withoutPct, String.length("file://")); - - if (Sys.os_type == "Unix") { - Some(withoutScheme); - } else { - Some(parseWindowsUri(withoutScheme)); - }; - } else { - None; - }; -}; - let endOfLocation = (loc, length) => Location.{ ...loc,