Skip to content

Commit

Permalink
steps to improve trace
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason3S committed Apr 11, 2024
1 parent 9073dcf commit 3e0fa92
Show file tree
Hide file tree
Showing 12 changed files with 168 additions and 8 deletions.
9 changes: 3 additions & 6 deletions packages/_server/src/server.mts
Expand Up @@ -51,7 +51,7 @@ import { createProgressNotifier } from './progressNotifier.mjs';
import type { PartialServerSideHandlers } from './serverApi.mjs';
import { createServerApi } from './serverApi.mjs';
import { createOnSuggestionsHandler } from './suggestionsServer.mjs';
import { traceWord } from './trace.js';
import { handleTraceRequest } from './trace.js';
import { defaultIsTextLikelyMinifiedOptions, isTextLikelyMinified } from './utils/analysis.mjs';
import { catchPromise } from './utils/catchPromise.mjs';
import { debounce as simpleDebounce } from './utils/debounce.mjs';
Expand Down Expand Up @@ -407,11 +407,8 @@ export function run(): void {
}

async function _handleGetWordTrace(req: Api.TraceWordRequest): Promise<Api.TraceWordResult> {
const { word, uri } = req;
log(`_handleGetWordTrace "${word}"`, uri);
const doc = documents.get(uri);
if (!doc) return { word, errors: 'Document Not Found.' };
return traceWord(docValidationController, doc, word);
log(`_handleGetWordTrace "${req.word}"`, req.uri);
return handleTraceRequest(docValidationController, req, (uri) => documents.get(uri));
}

async function getExcludedBy(uri: string): Promise<Api.ExcludeRef[]> {
Expand Down
22 changes: 21 additions & 1 deletion packages/_server/src/trace.ts
@@ -1,8 +1,9 @@
import { groupByField } from '@internal/common-utils';
import type { TextDocument } from 'vscode-languageserver-textdocument';
import { TextDocument } from 'vscode-languageserver-textdocument';

import type * as Api from './api.js';
import type { DocumentValidationController } from './DocumentValidationController.mjs';
import { readTextDocument, stat } from './vfs/index.mjs';

export async function traceWord(
docValidationController: DocumentValidationController,
Expand All @@ -24,6 +25,25 @@ export async function traceWord(
return { word, traces, splits };
}

export async function handleTraceRequest(
docValidationController: DocumentValidationController,
req: Api.TraceWordRequest,
getCachedDoc: (uri: string) => TextDocument | undefined,
): Promise<Api.TraceWordResult> {
const { word, uri } = req;
let doc = getCachedDoc(uri);
if (!doc) {
try {
const s = await stat(uri);
doc = s.isDirectory() ? TextDocument.create(uri, 'plaintext', 0, '') : await readTextDocument(uri);
} catch {
doc = undefined;
}
}
if (!doc) return { word, errors: 'Document Not Found.' };
return traceWord(docValidationController, doc, word);
}

function errorsToString(errors: Error[] | undefined): string | undefined {
if (!errors || !errors.length) return undefined;
return errors.map((e) => e.message).join('\n');
Expand Down
13 changes: 13 additions & 0 deletions packages/_server/src/utils/basename.mts
@@ -0,0 +1,13 @@
import type { URI } from 'vscode-uri';

import { toUrl } from './toUrl.mjs';

/**
* Get the basename of a URL
* @param url - the url to get the basename of
* @returns the basename of the url
*/
export function basename(url: string | URI | URL): string {
const u = toUrl(url);
return u.pathname.split('/').pop() || '';
}
20 changes: 20 additions & 0 deletions packages/_server/src/utils/basename.test.mts
@@ -0,0 +1,20 @@
import { describe, expect, test } from 'vitest';

import { basename } from './basename.mjs';

describe('calcFileTypes', () => {
test.each`
url | expected
${import.meta.url} | ${'basename.test.mts'}
${'./file.js'} | ${'file.js'}
${'./README.md'} | ${'README.md'}
${'./dir/'} | ${''}
${'./example.py'} | ${'example.py'}
`('basename $url', ({ url, expected }) => {
expect(basename(u(url))).toEqual(expected);
});
});

function u(url: string | URL): string {
return new URL(url, import.meta.url).toString();
}
8 changes: 8 additions & 0 deletions packages/_server/src/utils/calcFileTypes.mts
@@ -0,0 +1,8 @@
import { getLanguageIdsForBaseFilename } from 'cspell-lib';
import type { URI } from 'vscode-uri';

import { basename } from './basename.mjs';

export function calcFileTypes(url: string | URI | URL): string[] {
return getLanguageIdsForBaseFilename(basename(url));
}
20 changes: 20 additions & 0 deletions packages/_server/src/utils/calcFileTypes.test.mts
@@ -0,0 +1,20 @@
import { describe, expect, test } from 'vitest';

import { calcFileTypes } from './calcFileTypes.mjs';

describe('calcFileTypes', () => {
test.each`
url | expected
${import.meta.url} | ${['typescript']}
${'./file.js'} | ${['javascript']}
${'./README.md'} | ${['markdown']}
${'./dir/'} | ${[]}
${'./example.py'} | ${['python']}
`('calcFileTypes $url', ({ url, expected }) => {
expect(calcFileTypes(u(url))).toEqual(expected);
});
});

function u(url: string | URL): string {
return new URL(url, import.meta.url).toString();
}
9 changes: 9 additions & 0 deletions packages/_server/src/utils/toUrl.mts
@@ -0,0 +1,9 @@
import type { URI } from 'vscode-uri';

export function toUrl(url: URL | URI | string): URL {
if (typeof url === 'string') {
return new URL(url);
}
if (url instanceof URL) return url;
return new URL(url.toString());
}
2 changes: 2 additions & 0 deletions packages/_server/src/vfs/index.mts
@@ -0,0 +1,2 @@
export { readTextDocument } from './readTextDocument.mjs';
export { isDir, isFile, readTextFile, stat } from './vfs.mjs';
11 changes: 11 additions & 0 deletions packages/_server/src/vfs/readTextDocument.mts
@@ -0,0 +1,11 @@
import { TextDocument } from 'vscode-languageserver-textdocument';
import type { URI } from 'vscode-uri';

import { calcFileTypes } from '../utils/calcFileTypes.mjs';
import { readTextFile } from './vfs.mjs';

export async function readTextDocument(url: string | URI | URL): Promise<TextDocument> {
const content = await readTextFile(url);
const fileTypes = calcFileTypes(url);
return TextDocument.create(url.toString(), fileTypes[0] || 'plaintext', 0, content);
}
12 changes: 12 additions & 0 deletions packages/_server/src/vfs/readTextDocument.test.mts
@@ -0,0 +1,12 @@
import { describe, expect, test } from 'vitest';

import { readTextDocument } from './readTextDocument.mjs';

describe('readTextDocument', () => {
test('readTextDocument', async () => {
const doc = await readTextDocument(import.meta.url);
expect(doc.uri).toEqual(import.meta.url);
expect(doc.getText()).toContain("describe('readTextDocument'");
expect(doc.languageId).toEqual('typescript');
});
});
48 changes: 48 additions & 0 deletions packages/_server/src/vfs/vfs.mts
@@ -0,0 +1,48 @@
import type { VfsStat } from 'cspell-io';
import { getVirtualFS } from 'cspell-lib';
import type { URI } from 'vscode-uri';

import { toUrl } from '../utils/toUrl.mjs';

export async function stat(urlLike: URL | URI | string): Promise<VfsStat> {
const url = toUrl(urlLike);
const vfs = getVirtualFS();
const fs = vfs.getFS(url);
const stat = await fs.stat(url);
return stat;
}

export async function readTextFile(url: URL | URI | string): Promise<string> {
const _url = toUrl(url);
const vfs = getVirtualFS();
const fs = vfs.getFS(_url);
const f = await fs.readFile(_url);
return f.getText();
}

export async function isFile(url: URL | URI | string): Promise<boolean> {
try {
const statInfo = await stat(url);
return statInfo.isFile();
} catch {
return false;
}
}

export async function isDir(url: URL | URI | string): Promise<boolean> {
try {
const statInfo = await stat(url);
return statInfo.isDirectory();
} catch {
return false;
}
}

export async function exists(url: URL | URI | string): Promise<boolean> {
try {
await stat(url);
return true;
} catch {
return false;
}
}
2 changes: 1 addition & 1 deletion packages/client/src/repl/repl.mts
Expand Up @@ -343,7 +343,7 @@ class Repl implements vscode.Disposable, vscode.Pseudoterminal {
this.log('No word specified.');
return;
}
const result = await traceWord(word, vscode.window.activeTextEditor?.document.uri || this.#cwd, this.#dimensions?.columns || 80);
const result = await traceWord(word, this.#cwd, this.#dimensions?.columns || 80);
this.log('%s', result);
}

Expand Down

0 comments on commit 3e0fa92

Please sign in to comment.