Skip to content

Commit

Permalink
Merge pull request #17 from wkillerud/fix/root-imports
Browse files Browse the repository at this point in the history
fix: root imports for scoped npm packages
  • Loading branch information
wkillerud authored Aug 10, 2022
2 parents 33bb60a + eb4a8da commit b3d7360
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 79 deletions.
3 changes: 3 additions & 0 deletions .vscodeignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ npm-debug.log*
# Configuration
.github/
.vscode/
.husky/
.editorconfig
.eslintrc.json
.gitattributes
Expand All @@ -26,9 +27,11 @@ node_modules/
.nyc_output/
coverage/
fixtures/
dist/test/
src/
types/
patches/
CONTRIBUTING.md
CHANGELOG.md

# Build artifacts
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "some-sass",
"displayName": "Some Sass",
"description": "Provides code suggestions, documentation and code navigation for modern SCSS",
"version": "2.6.0",
"version": "2.6.1",
"publisher": "SomewhatStationery",
"license": "MIT",
"engines": {
Expand Down Expand Up @@ -156,8 +156,9 @@
"prepare": "husky install",
"lint-staged": "lint-staged",
"vscode:prepublish": "npm run build",
"build": "webpack --mode production --devtool hidden-source-map",
"dev": "webpack --mode development --watch",
"clean": "rimraf dist",
"build": "npm run clean && webpack --mode production --devtool hidden-source-map",
"dev": "npm run clean && webpack --mode development --watch",
"lint": "eslint \"src/**/*.ts\" --cache",
"test": "npm run test:clean && npm run test:compile && npm run test:unit",
"test:clean": "rimraf out",
Expand Down
45 changes: 45 additions & 0 deletions patches/vscode-css-languageservice+6.0.1.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
diff --git a/node_modules/vscode-css-languageservice/lib/esm/services/cssNavigation.js b/node_modules/vscode-css-languageservice/lib/esm/services/cssNavigation.js
index 63b64d7..be64b1d 100644
--- a/node_modules/vscode-css-languageservice/lib/esm/services/cssNavigation.js
+++ b/node_modules/vscode-css-languageservice/lib/esm/services/cssNavigation.js
@@ -370,9 +370,14 @@ function toTwoDigitHex(n) {
return r.length !== 2 ? '0' + r : r;
}
function getModuleNameFromPath(path) {
- // If a scoped module (starts with @) then get up until second instance of '/', otherwise get until first instance of '/'
+ // If a scoped module (starts with @) then get up until second instance of '/', or to the end of the string for root-level imports.
if (path[0] === '@') {
- return path.substring(0, path.indexOf('/', path.indexOf('/') + 1));
+ const secondSlash = path.indexOf('/', path.indexOf('/') + 1);
+ if (secondSlash === -1) {
+ return path;
+ }
+ return path.substring(0, path.indexOf('/', path.indexOf('/') + 1));
}
- return path.substring(0, path.indexOf('/'));
+ // Otherwise get until first instance of '/'
+ return path.substring(0, path.indexOf('/'));
}
diff --git a/node_modules/vscode-css-languageservice/lib/umd/services/cssNavigation.js b/node_modules/vscode-css-languageservice/lib/umd/services/cssNavigation.js
index 3a42b53..d6725fd 100644
--- a/node_modules/vscode-css-languageservice/lib/umd/services/cssNavigation.js
+++ b/node_modules/vscode-css-languageservice/lib/umd/services/cssNavigation.js
@@ -382,10 +382,15 @@
return r.length !== 2 ? '0' + r : r;
}
function getModuleNameFromPath(path) {
- // If a scoped module (starts with @) then get up until second instance of '/', otherwise get until first instance of '/'
+ // If a scoped module (starts with @) then get up until second instance of '/', or to the end of the string for root-level imports.
if (path[0] === '@') {
- return path.substring(0, path.indexOf('/', path.indexOf('/') + 1));
+ const secondSlash = path.indexOf('/', path.indexOf('/') + 1);
+ if (secondSlash === -1) {
+ return path;
+ }
+ return path.substring(0, path.indexOf('/', path.indexOf('/') + 1));
}
- return path.substring(0, path.indexOf('/'));
+ // Otherwise get until first instance of '/'
+ return path.substring(0, path.indexOf('/'));
}
});
78 changes: 3 additions & 75 deletions src/server/parser/document.ts
Original file line number Diff line number Diff line change
@@ -1,63 +1,9 @@
import { dirname, join } from "path";
import type { DocumentContext } from "vscode-css-languageservice";
import { URI } from "vscode-uri";
import { FileSystemProvider } from "../../shared/file-system";
import type { NodeFileSystem } from "../../shared/node-file-system";

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
* See https://github.com/microsoft/vscode/blob/main/LICENSE.txt for license information.
*--------------------------------------------------------------------------------------------*/
function getModuleNameFromPath(path: string) {
// If a scoped module (starts with @) then get up until second instance of '/', otherwise get until first isntance of '/'
if (path.startsWith("@")) {
return path.slice(0, Math.max(0, path.indexOf("/", path.indexOf("/") + 1)));
}

return path.slice(0, Math.max(0, path.indexOf("/")));
}

function resolvePathToModule(
moduleName: string,
relativeTo: string,
fs: FileSystemProvider,
): string | undefined {
// Resolve the module relative to the document. We can't use `require` here as the code is webpacked.
// fsPath use is OK here since we never reach this function unless the URI is a file://.
const documentFolder = dirname(URI.parse(relativeTo).fsPath);

// Assume this path exists. If not, let VS Code deal with the "404" and have the user fix a typo or install node_modules.
const packPath = join(
documentFolder,
"node_modules",
moduleName,
"package.json",
);

if (Object.prototype.hasOwnProperty.call(fs, "existsSync")) {
if ((fs as NodeFileSystem).existsSync(packPath)) {
return URI.file(packPath).toString();
}
}

return undefined;
}

function resolve(from: string, to: string): string {
const resolvedUrl = new URL(to, new URL(from, "resolve://"));
if (resolvedUrl.protocol === "resolve:") {
// `from` is a relative URL.
const { pathname, search, hash } = resolvedUrl;
return pathname + search + hash;
}
return resolvedUrl.toString();
}
import { URI, Utils } from "vscode-uri";

export function buildDocumentContext(
documentUri: string,
workspaceRoot: URI,
fs: FileSystemProvider,
): DocumentContext {
function getRootFolder(): string | undefined {
let folderURI = workspaceRoot.toString();
Expand All @@ -83,26 +29,8 @@ export function buildDocumentContext(
return folderUri + ref.slice(1);
}
}

// Following [css-loader](https://github.com/webpack-contrib/css-loader#url)
// and [sass-loader's](https://github.com/webpack-contrib/sass-loader#imports)
// convention, if an import path starts with ~ then use node module resolution
// *unless* it starts with "~/" as this refers to the user's home directory.
if (ref.startsWith("~") && ref[1] !== "/") {
ref = ref.slice(1);
if (base.startsWith("file://")) {
const moduleName = getModuleNameFromPath(ref);
const modulePath = resolvePathToModule(moduleName, base, fs);
if (modulePath) {
const pathWithinModule = ref.slice(
Math.max(0, moduleName.length + 1),
);
return resolve(modulePath, pathWithinModule);
}
}
}

return resolve(base, ref);
base = base.substr(0, base.lastIndexOf("/") + 1);
return Utils.resolvePath(URI.parse(base), ref).toString();
},
};
}
2 changes: 1 addition & 1 deletion src/server/parser/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ async function findDocumentSymbols(
const links = await ls.findDocumentLinks2(
document,
ast,
buildDocumentContext(document.uri, workspaceRoot, fs),
buildDocumentContext(document.uri, workspaceRoot),
);

const text = document.getText();
Expand Down

0 comments on commit b3d7360

Please sign in to comment.