Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Sync core for full web support #40

Merged
merged 6 commits into from Jun 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -11,8 +11,8 @@
"@lerna-lite/cli": "latest",
"@lerna-lite/publish": "latest",
"@types/node": "latest",
"@volar/source-map": "1.6.9",
"@volar/language-service": "1.6.9",
"@volar/source-map": "1.7.0",
"@volar/language-service": "1.7.0",
"typescript": "latest",
"vscode-languageserver-protocol": "^3.17.3"
}
Expand Down
3 changes: 2 additions & 1 deletion packages/css/package.json
Expand Up @@ -13,7 +13,8 @@
"directory": "packages/css"
},
"dependencies": {
"vscode-css-languageservice": "^6.2.3"
"vscode-css-languageservice": "^6.2.3",
"vscode-uri": "^3.0.7"
},
"devDependencies": {
"vscode-languageserver-textdocument": "^1.0.8"
Expand Down
42 changes: 30 additions & 12 deletions packages/css/src/index.ts
@@ -1,7 +1,8 @@
import type { CodeAction, Diagnostic, LocationLink, Service } from '@volar/language-service';
import * as path from 'path';
import { posix as path } from 'path';
import * as css from 'vscode-css-languageservice';
import type { TextDocument } from 'vscode-languageserver-textdocument';
import { URI, Utils } from 'vscode-uri';

export interface Provide {
'css/stylesheet': (document: TextDocument) => css.Stylesheet | undefined;
Expand All @@ -19,16 +20,39 @@ export default (): Service<Provide> => (context): ReturnType<Service<Provide>> =
let inited = false;

const stylesheets = new WeakMap<TextDocument, [number, css.Stylesheet]>();
const fileSystemProvider: css.FileSystemProvider = {
stat: async uri => await context.env.fs?.stat(uri) ?? {
type: css.FileType.Unknown,
ctime: 0,
mtime: 0,
size: 0,
},
readDirectory: async (uri) => context.env.fs?.readDirectory(uri) ?? [],
};
const documentContext: css.DocumentContext = {
resolveReference(ref, base) {
if (ref.match(/^\w[\w\d+.-]*:/)) {
// starts with a schema
return ref;
}
if (ref[0] === '/') { // resolve absolute path against the current workspace folder
return base + ref;
}
const baseUri = URI.parse(base);
const baseUriDir = baseUri.path.endsWith('/') ? baseUri : Utils.dirname(baseUri);
return Utils.resolvePath(baseUriDir, ref).toString(true);
},
};
const cssLs = css.getCSSLanguageService({
fileSystemProvider: context.env.fileSystemProvider,
fileSystemProvider,
clientCapabilities: context.env.clientCapabilities,
});
const scssLs = css.getSCSSLanguageService({
fileSystemProvider: context.env.fileSystemProvider,
fileSystemProvider,
clientCapabilities: context.env.clientCapabilities,
});
const lessLs = css.getLESSLanguageService({
fileSystemProvider: context.env.fileSystemProvider,
fileSystemProvider,
clientCapabilities: context.env.clientCapabilities,
});
const postcssLs: css.LanguageService = {
Expand All @@ -55,9 +79,7 @@ export default (): Service<Provide> => (context): ReturnType<Service<Provide>> =
return worker(document, async (stylesheet, cssLs) => {

const settings = await context.env.getConfiguration?.<css.LanguageSettings>(document.languageId);
const cssResult = context.env.documentContext
? await cssLs.doComplete2(document, position, stylesheet, context.env.documentContext, settings?.completion)
: await cssLs.doComplete(document, position, stylesheet, settings?.completion);
const cssResult = await cssLs.doComplete2(document, position, stylesheet, documentContext, settings?.completion);

return cssResult;
});
Expand Down Expand Up @@ -128,11 +150,7 @@ export default (): Service<Provide> => (context): ReturnType<Service<Provide>> =

async provideDocumentLinks(document) {
return await worker(document, (stylesheet, cssLs) => {

if (!context.env.documentContext)
return;

return cssLs.findDocumentLinks2(document, stylesheet, context.env.documentContext);
return cssLs.findDocumentLinks2(document, stylesheet, documentContext);
});
},

Expand Down
3 changes: 2 additions & 1 deletion packages/html/package.json
Expand Up @@ -13,7 +13,8 @@
"directory": "packages/html"
},
"dependencies": {
"vscode-html-languageservice": "^5.0.4"
"vscode-html-languageservice": "^5.0.4",
"vscode-uri": "^3.0.7"
},
"devDependencies": {
"vscode-languageserver-textdocument": "^1.0.8"
Expand Down
41 changes: 29 additions & 12 deletions packages/html/src/index.ts
Expand Up @@ -2,13 +2,15 @@ import type { Service, DocumentSymbol, SymbolKind } from '@volar/language-servic
import * as html from 'vscode-html-languageservice';
import type { TextDocument } from 'vscode-languageserver-textdocument';
import * as path from 'path';
import { URI, Utils } from 'vscode-uri';

const parserLs = html.getLanguageService();
const htmlDocuments = new WeakMap<TextDocument, [number, html.HTMLDocument]>();

export interface Provide {
'html/htmlDocument': (document: TextDocument) => html.HTMLDocument | undefined;
'html/languageService': () => html.LanguageService;
'html/documentContext': () => html.DocumentContext;
'html/updateCustomData': (extraData: html.IHTMLDataProvider[]) => void;
}

Expand Down Expand Up @@ -44,8 +46,31 @@ export default (options: {
let customData: html.IHTMLDataProvider[] = [];
let extraData: html.IHTMLDataProvider[] = [];

const fileSystemProvider: html.FileSystemProvider = {
stat: async uri => await context.env.fs?.stat(uri) ?? {
type: html.FileType.Unknown,
ctime: 0,
mtime: 0,
size: 0,
},
readDirectory: async (uri) => context.env.fs?.readDirectory(uri) ?? [],
};
const documentContext: html.DocumentContext = {
resolveReference(ref, base) {
if (ref.match(/^\w[\w\d+.-]*:/)) {
// starts with a schema
return ref;
}
if (ref[0] === '/') { // resolve absolute path against the current workspace folder
return base + ref;
}
const baseUri = URI.parse(base);
const baseUriDir = baseUri.path.endsWith('/') ? baseUri : Utils.dirname(baseUri);
return Utils.resolvePath(baseUriDir, ref).toString(true);
},
};
const htmlLs = html.getLanguageService({
fileSystemProvider: context.env.fileSystemProvider,
fileSystemProvider,
clientCapabilities: context.env.clientCapabilities,
});

Expand All @@ -62,6 +87,7 @@ export default (options: {
}
},
'html/languageService': () => htmlLs,
'html/documentContext': () => documentContext,
'html/updateCustomData': updateExtraCustomData,
},

Expand All @@ -72,12 +98,7 @@ export default (options: {

const configs = await context.env.getConfiguration?.<html.CompletionConfiguration>('html.completion');

if (context.env.documentContext) {
return htmlLs.doComplete2(document, position, htmlDocument, context.env.documentContext, configs);
}
else {
return htmlLs.doComplete(document, position, htmlDocument, configs);
}
return htmlLs.doComplete2(document, position, htmlDocument, documentContext, configs);
});
},

Expand Down Expand Up @@ -114,11 +135,7 @@ export default (options: {

provideDocumentLinks(document) {
return worker(document, () => {

if (!context.env.documentContext)
return;

return htmlLs.findDocumentLinks(document, context.env.documentContext);
return htmlLs.findDocumentLinks(document, documentContext);
});
},

Expand Down
3 changes: 2 additions & 1 deletion packages/json/package.json
Expand Up @@ -13,7 +13,8 @@
"directory": "packages/json"
},
"dependencies": {
"vscode-json-languageservice": "^5.2.0"
"vscode-json-languageservice": "^5.2.0",
"vscode-uri": "^3.0.7"
},
"devDependencies": {
"vscode-languageserver-textdocument": "^1.0.8"
Expand Down
21 changes: 20 additions & 1 deletion packages/json/src/index.ts
@@ -1,6 +1,7 @@
import type { Service, Diagnostic } from '@volar/language-service';
import * as json from 'vscode-json-languageservice';
import type { TextDocument } from 'vscode-languageserver-textdocument';
import { URI, Utils } from 'vscode-uri';

export interface Provide {
'json/jsonDocument': (document: TextDocument) => json.JSONDocument | undefined;
Expand All @@ -16,7 +17,25 @@ export default (settings?: json.LanguageSettings): Service<Provide> => (context)
return { triggerCharacters } as any;
}
const jsonDocuments = new WeakMap<TextDocument, [number, json.JSONDocument]>();
const jsonLs = json.getLanguageService({ schemaRequestService: context.env.schemaRequestService });
const workspaceContext: json.WorkspaceContextService = {
resolveRelativePath: (ref: string, base: string) => {
if (ref.match(/^\w[\w\d+.-]*:/)) {
// starts with a schema
return ref;
}
if (ref[0] === '/') { // resolve absolute path against the current workspace folder
return base + ref;
}
const baseUri = URI.parse(base);
const baseUriDir = baseUri.path.endsWith('/') ? baseUri : Utils.dirname(baseUri);
return Utils.resolvePath(baseUriDir, ref).toString(true);
},
};
const jsonLs = json.getLanguageService({
schemaRequestService: async (uri) => await context.env.fs?.readFile(uri) ?? '',
workspaceContext,
clientCapabilities: context.env.clientCapabilities,
});

if (settings) {
jsonLs.configure(settings);
Expand Down
6 changes: 2 additions & 4 deletions packages/pug/src/index.ts
Expand Up @@ -33,7 +33,7 @@ export default (): Service<Provide> => (context, modules): ReturnType<Service<Pr

provideCompletionItems(document, position, _) {
return worker(document, (pugDocument) => {
return pugLs.doComplete(pugDocument, position, context.env.documentContext, /** TODO: CompletionConfiguration */);
return pugLs.doComplete(pugDocument, position, htmlService.provide['html/documentContext'](), /** TODO: CompletionConfiguration */);
});
},

Expand Down Expand Up @@ -74,9 +74,7 @@ export default (): Service<Provide> => (context, modules): ReturnType<Service<Pr

provideDocumentLinks(document) {
return worker(document, (pugDocument) => {
if (context.env.documentContext) {
return pugLs.findDocumentLinks(pugDocument, context.env.documentContext);
}
return pugLs.findDocumentLinks(pugDocument, htmlService.provide['html/documentContext']());
});
},

Expand Down
23 changes: 7 additions & 16 deletions packages/tsconfig/src/index.ts
@@ -1,4 +1,4 @@
import type { DocumentLink, Service } from '@volar/language-service';
import type { DocumentLink, FileType, Service } from '@volar/language-service';
import * as jsonc from 'jsonc-parser';
import { minimatch } from 'minimatch';
import type { TextDocument } from 'vscode-languageserver-textdocument';
Expand Down Expand Up @@ -52,7 +52,7 @@ export default (): Service => (contextOrNull): ReturnType<Service> => {
},

async resolveDocumentLink(link) {

const data: OpenExtendsLinkCommandArgs = link.data;
if (data) {
const tsconfigPath = await getTsconfigPath(Utils.dirname(URI.parse(data.resourceUri)), data.extendsValue);
Expand Down Expand Up @@ -153,14 +153,9 @@ export default (): Service => (contextOrNull): ReturnType<Service> => {
const moduleBasePath = baseCandidate.split('/').slice(0, sepIndex).join('/');
while (true) {
const moduleAbsoluteUrl = Utils.joinPath(currentUri, 'node_modules', moduleBasePath);
let moduleStat: Awaited<ReturnType<NonNullable<typeof ctx.env.fileSystemProvider>['stat']>> | undefined;
try {
moduleStat = await ctx.env.fileSystemProvider?.stat(moduleAbsoluteUrl.toString());
} catch (err) {
// noop
}
const moduleStat = await ctx.env.fs?.stat(moduleAbsoluteUrl.toString());

if (moduleStat && moduleStat.type === 2 /* Directory */) {
if (moduleStat && moduleStat.type === 2 satisfies FileType.Directory) {
for (const uriCandidate of pathCandidates
.map((relativePath) => relativePath.split('/').slice(sepIndex).join('/'))
// skip empty paths within module
Expand Down Expand Up @@ -214,12 +209,8 @@ export default (): Service => (contextOrNull): ReturnType<Service> => {
}

async function exists(resource: URI): Promise<boolean> {
try {
const stat = await ctx.env.fileSystemProvider?.stat(resource.toString());
// stat.type is an enum flag
return !!(stat?.type === 1);
} catch {
return false;
}
const stat = await ctx.env.fs?.stat(resource.toString());
// stat.type is an enum flag
return stat?.type === 1 satisfies FileType.File;
}
};
4 changes: 2 additions & 2 deletions packages/typescript/package.json
Expand Up @@ -14,12 +14,12 @@
},
"devDependencies": {
"@types/semver": "^7.3.13",
"@volar/typescript": "1.6.9",
"vscode-languageserver-textdocument": "^1.0.8"
"@volar/typescript": "1.7.0"
},
"dependencies": {
"semver": "^7.3.8",
"typescript-auto-import-cache": "^0.3.0",
"vscode-languageserver-textdocument": "^1.0.8",
"vscode-nls": "^5.2.0",
"vscode-uri": "^3.0.7"
},
Expand Down
11 changes: 3 additions & 8 deletions packages/typescript/src/features/formatting.ts
Expand Up @@ -2,13 +2,11 @@ import type * as vscode from '@volar/language-service';
import { getFormatCodeSettings } from '../configs/getFormatCodeSettings';
import { safeCall } from '../shared';
import { SharedContext } from '../types';
import type { TextDocument } from 'vscode-languageserver-textdocument';

export function register(ctx: SharedContext) {
return {
onRange: async (uri: string, range: vscode.Range | undefined, options: vscode.FormattingOptions): Promise<vscode.TextEdit[]> => {

const document = ctx.getTextDocument(uri);
if (!document) return [];
onRange: async (document: TextDocument, range: vscode.Range | undefined, options: vscode.FormattingOptions): Promise<vscode.TextEdit[]> => {

const fileName = ctx.env.uriToFileName(document.uri);
const tsOptions = await getFormatCodeSettings(ctx, document, options);
Expand All @@ -35,10 +33,7 @@ export function register(ctx: SharedContext) {

return result;
},
onType: async (uri: string, options: vscode.FormattingOptions, position: vscode.Position, key: string): Promise<vscode.TextEdit[]> => {

const document = ctx.getTextDocument(uri);
if (!document) return [];
onType: async (document: TextDocument, options: vscode.FormattingOptions, position: vscode.Position, key: string): Promise<vscode.TextEdit[]> => {

const fileName = ctx.env.uriToFileName(document.uri);
const tsOptions = await getFormatCodeSettings(ctx, document, options);
Expand Down