mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-22 17:48:56 +01:00
Split toPath and normalizedPath
Break up the concept of normalizing a path and trying to get the on disk path of a resource. Needed for handling case insensitivity
This commit is contained in:
@@ -119,7 +119,7 @@ async function goToProjectConfig(
|
||||
return;
|
||||
}
|
||||
|
||||
const file = client.normalizePath(resource);
|
||||
const file = client.toPath(resource);
|
||||
// TSServer errors when 'projectInfo' is invoked on a non js/ts file
|
||||
if (!file || !clientHost.handles(resource)) {
|
||||
vscode.window.showWarningMessage(
|
||||
|
||||
@@ -41,7 +41,7 @@ export function activate(
|
||||
void lazyClientHost.value;
|
||||
|
||||
context.subscriptions.push(new ManagedFileContextManager(resource => {
|
||||
return lazyClientHost.value.serviceClient.normalizePath(resource);
|
||||
return lazyClientHost.value.serviceClient.toPath(resource);
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ export abstract class TypeScriptBaseCodeLensProvider implements CodeLensProvider
|
||||
}
|
||||
|
||||
async provideCodeLenses(document: TextDocument, token: CancellationToken): Promise<CodeLens[]> {
|
||||
const filepath = this.client.normalizePath(document.uri);
|
||||
const filepath = this.client.toPath(document.uri);
|
||||
if (!filepath) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -77,14 +77,9 @@ class SyncedBuffer {
|
||||
}
|
||||
|
||||
public onContentChanged(events: TextDocumentContentChangeEvent[]): void {
|
||||
const filePath = this.client.normalizePath(this.document.uri);
|
||||
if (!filePath) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const { range, text } of events) {
|
||||
const args: Proto.ChangeRequestArgs = {
|
||||
file: filePath,
|
||||
file: this.filepath,
|
||||
line: range.start.line + 1,
|
||||
offset: range.start.character + 1,
|
||||
endLine: range.end.line + 1,
|
||||
@@ -166,7 +161,7 @@ export default class BufferSyncSupport {
|
||||
|
||||
this.diagnosticDelayer = new Delayer<any>(300);
|
||||
|
||||
this.syncedBuffers = new SyncedBufferMap(path => this.client.normalizePath(path));
|
||||
this.syncedBuffers = new SyncedBufferMap(path => this.client.normalizedPath(path));
|
||||
}
|
||||
|
||||
private readonly _onDelete = new EventEmitter<Uri>();
|
||||
@@ -203,7 +198,7 @@ export default class BufferSyncSupport {
|
||||
return;
|
||||
}
|
||||
const resource = document.uri;
|
||||
const filepath = this.client.normalizePath(resource);
|
||||
const filepath = this.client.normalizedPath(resource);
|
||||
if (!filepath) {
|
||||
return;
|
||||
}
|
||||
@@ -237,12 +232,14 @@ export default class BufferSyncSupport {
|
||||
|
||||
private onDidChangeTextDocument(e: TextDocumentChangeEvent): void {
|
||||
const syncedBuffer = this.syncedBuffers.get(e.document.uri);
|
||||
if (syncedBuffer) {
|
||||
syncedBuffer.onContentChanged(e.contentChanges);
|
||||
if (this.pendingGetErr) {
|
||||
this.pendingGetErr.token.cancel();
|
||||
this.pendingGetErr = undefined;
|
||||
}
|
||||
if (!syncedBuffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
syncedBuffer.onContentChanged(e.contentChanges);
|
||||
if (this.pendingGetErr) {
|
||||
this.pendingGetErr.token.cancel();
|
||||
this.pendingGetErr = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +262,7 @@ export default class BufferSyncSupport {
|
||||
}
|
||||
|
||||
for (const resource of handledResources) {
|
||||
const file = this.client.normalizePath(resource);
|
||||
const file = this.client.normalizedPath(resource);
|
||||
if (file) {
|
||||
this.pendingDiagnostics.set(file, Date.now());
|
||||
}
|
||||
@@ -281,7 +278,7 @@ export default class BufferSyncSupport {
|
||||
return;
|
||||
}
|
||||
|
||||
const file = this.client.normalizePath(resource);
|
||||
const file = this.client.normalizedPath(resource);
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
@@ -299,7 +296,7 @@ export default class BufferSyncSupport {
|
||||
}
|
||||
|
||||
public hasPendingDiagnostics(resource: Uri): boolean {
|
||||
const file = this.client.normalizePath(resource);
|
||||
const file = this.client.normalizedPath(resource);
|
||||
return !file || this.pendingDiagnostics.has(file);
|
||||
}
|
||||
|
||||
|
||||
@@ -275,7 +275,7 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider
|
||||
});
|
||||
}
|
||||
|
||||
const file = this.client.normalizePath(document.uri);
|
||||
const file = this.client.toPath(document.uri);
|
||||
if (!file) {
|
||||
return [];
|
||||
}
|
||||
@@ -332,7 +332,7 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const filepath = this.client.normalizePath(item.document.uri);
|
||||
const filepath = this.client.toPath(item.document.uri);
|
||||
if (!filepath) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export default class TypeScriptDefinitionProviderBase {
|
||||
position: Position,
|
||||
token: CancellationToken | boolean
|
||||
): Promise<Location[] | undefined> {
|
||||
const filepath = this.client.normalizePath(document.uri);
|
||||
const filepath = this.client.toPath(document.uri);
|
||||
if (!filepath) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -30,7 +30,7 @@ export default class TypeScriptDefinitionProviderBase {
|
||||
const response = await this.client.execute(definitionType, args, token);
|
||||
const locations: Proto.FileSpan[] = (response && response.body) || [];
|
||||
return locations.map(location =>
|
||||
typeConverters.Location.fromTextSpan(this.client.asUrl(location.file), location));
|
||||
typeConverters.Location.fromTextSpan(this.client.toResource(location.file), location));
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ class DirectiveCommentCompletionProvider implements vscode.CompletionItemProvide
|
||||
position: vscode.Position,
|
||||
_token: vscode.CancellationToken
|
||||
): vscode.CompletionItem[] {
|
||||
const file = this.client.normalizePath(document.uri);
|
||||
const file = this.client.toPath(document.uri);
|
||||
if (!file) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class TypeScriptDocumentHighlightProvider implements vscode.DocumentHighlightPro
|
||||
position: vscode.Position,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.DocumentHighlight[]> {
|
||||
const file = this.client.normalizePath(resource.uri);
|
||||
const file = this.client.toPath(resource.uri);
|
||||
if (!file) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class TypeScriptDocumentSymbolProvider implements vscode.DocumentSymbolProvider
|
||||
private readonly client: ITypeScriptServiceClient) { }
|
||||
|
||||
public async provideDocumentSymbols(resource: vscode.TextDocument, token: vscode.CancellationToken): Promise<any> { // todo@joh `any[]` temporary hack to make typescript happy...
|
||||
const filepath = this.client.normalizePath(resource.uri);
|
||||
const filepath = this.client.toPath(resource.uri);
|
||||
if (!filepath) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ export default class FileConfigurationManager {
|
||||
options: FormattingOptions,
|
||||
token: CancellationToken | undefined
|
||||
): Promise<void> {
|
||||
const file = this.client.normalizePath(document.uri);
|
||||
const file = this.client.toPath(document.uri);
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class TypeScriptFoldingProvider implements vscode.FoldingRangeProvider {
|
||||
_context: vscode.FoldingContext,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.FoldingRange[] | undefined> {
|
||||
const file = this.client.normalizePath(document.uri);
|
||||
const file = this.client.toPath(document.uri);
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ class TypeScriptFormattingProvider implements vscode.DocumentRangeFormattingEdit
|
||||
options: vscode.FormattingOptions,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.TextEdit[]> {
|
||||
const absPath = this.client.normalizePath(document.uri);
|
||||
const absPath = this.client.toPath(document.uri);
|
||||
if (!absPath) {
|
||||
return [];
|
||||
}
|
||||
@@ -72,7 +72,7 @@ class TypeScriptFormattingProvider implements vscode.DocumentRangeFormattingEdit
|
||||
options: vscode.FormattingOptions,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.TextEdit[]> {
|
||||
const filepath = this.client.normalizePath(document.uri);
|
||||
const filepath = this.client.toPath(document.uri);
|
||||
if (!filepath) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ class TypeScriptHoverProvider implements vscode.HoverProvider {
|
||||
position: vscode.Position,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.Hover | undefined> {
|
||||
const filepath = this.client.normalizePath(document.uri);
|
||||
const filepath = this.client.toPath(document.uri);
|
||||
if (!filepath) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ export default class TypeScriptImplementationsCodeLensProvider extends TypeScrip
|
||||
const locations = response.body
|
||||
.map(reference =>
|
||||
// Only take first line on implementation: https://github.com/Microsoft/vscode/issues/23924
|
||||
new vscode.Location(this.client.asUrl(reference.file),
|
||||
new vscode.Location(this.client.toResource(reference.file),
|
||||
reference.start.line === reference.end.line
|
||||
? typeConverters.Range.fromTextSpan(reference)
|
||||
: new vscode.Range(
|
||||
|
||||
@@ -54,7 +54,7 @@ class JsDocCompletionProvider implements CompletionItemProvider {
|
||||
position: Position,
|
||||
token: CancellationToken
|
||||
): Promise<CompletionItem[]> {
|
||||
const file = this.client.normalizePath(document.uri);
|
||||
const file = this.client.toPath(document.uri);
|
||||
if (!file) {
|
||||
return [];
|
||||
}
|
||||
@@ -130,7 +130,7 @@ class TryCompleteJsDocCommand implements Command {
|
||||
* if possible, otherwise falling back to a default comment format.
|
||||
*/
|
||||
public async execute(resource: Uri, start: Position): Promise<boolean> {
|
||||
const file = this.client.normalizePath(resource);
|
||||
const file = this.client.toPath(resource);
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ export class OrganizeImportsCodeActionProvider implements vscode.CodeActionProvi
|
||||
_context: vscode.CodeActionContext,
|
||||
token: vscode.CancellationToken
|
||||
): vscode.CodeAction[] {
|
||||
const file = this.client.normalizePath(document.uri);
|
||||
const file = this.client.toPath(document.uri);
|
||||
if (!file) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider {
|
||||
return [];
|
||||
}
|
||||
|
||||
const file = this.client.normalizePath(document.uri);
|
||||
const file = this.client.toPath(document.uri);
|
||||
if (!file) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const file = this.client.normalizePath(document.uri);
|
||||
const file = this.client.toPath(document.uri);
|
||||
if (!file) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ class TypeScriptReferenceSupport implements vscode.ReferenceProvider {
|
||||
options: vscode.ReferenceContext,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.Location[]> {
|
||||
const filepath = this.client.normalizePath(document.uri);
|
||||
const filepath = this.client.toPath(document.uri);
|
||||
if (!filepath) {
|
||||
return [];
|
||||
}
|
||||
@@ -36,7 +36,7 @@ class TypeScriptReferenceSupport implements vscode.ReferenceProvider {
|
||||
if (!options.includeDeclaration && has203Features && ref.isDefinition) {
|
||||
continue;
|
||||
}
|
||||
const url = this.client.asUrl(ref.file);
|
||||
const url = this.client.toResource(ref.file);
|
||||
const location = typeConverters.Location.fromTextSpan(url, ref);
|
||||
result.push(location);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class TypeScriptReferencesCodeLensProvider extends TypeScriptBaseCodeLensProvide
|
||||
|
||||
const locations = response.body.refs
|
||||
.map(reference =>
|
||||
typeConverters.Location.fromTextSpan(this.client.asUrl(reference.file), reference))
|
||||
typeConverters.Location.fromTextSpan(this.client.toResource(reference.file), reference))
|
||||
.filter(location =>
|
||||
// Exclude original definition from references
|
||||
!(location.uri.toString() === codeLens.document.toString() &&
|
||||
|
||||
@@ -20,7 +20,7 @@ class TypeScriptRenameProvider implements vscode.RenameProvider {
|
||||
newName: string,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.WorkspaceEdit | null> {
|
||||
const file = this.client.normalizePath(document.uri);
|
||||
const file = this.client.toPath(document.uri);
|
||||
if (!file) {
|
||||
return null;
|
||||
}
|
||||
@@ -55,7 +55,7 @@ class TypeScriptRenameProvider implements vscode.RenameProvider {
|
||||
) {
|
||||
const result = new vscode.WorkspaceEdit();
|
||||
for (const spanGroup of locations) {
|
||||
const resource = this.client.asUrl(spanGroup.file);
|
||||
const resource = this.client.toResource(spanGroup.file);
|
||||
if (resource) {
|
||||
for (const textSpan of spanGroup.locs) {
|
||||
result.replace(resource, typeConverters.Range.fromTextSpan(textSpan), newName);
|
||||
|
||||
@@ -22,7 +22,7 @@ class TypeScriptSignatureHelpProvider implements vscode.SignatureHelpProvider {
|
||||
position: vscode.Position,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.SignatureHelp | undefined> {
|
||||
const filepath = this.client.normalizePath(document.uri);
|
||||
const filepath = this.client.toPath(document.uri);
|
||||
if (!filepath) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ class TscTaskProvider implements vscode.TaskProvider {
|
||||
if (editor) {
|
||||
const document = editor.document;
|
||||
if (document && (document.languageId === 'typescript' || document.languageId === 'typescriptreact')) {
|
||||
return this.client.value.normalizePath(document.uri);
|
||||
return this.client.value.toPath(document.uri);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -54,12 +54,12 @@ export class UpdateImportsOnFileRenameHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
const newFile = this.client.normalizePath(newResource);
|
||||
const newFile = this.client.toPath(newResource);
|
||||
if (!newFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldFile = this.client.normalizePath(oldResource);
|
||||
const oldFile = this.client.toPath(oldResource);
|
||||
if (!oldFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class TypeScriptWorkspaceSymbolProvider implements vscode.WorkspaceSymbolProvide
|
||||
return [];
|
||||
}
|
||||
|
||||
const filepath = this.client.normalizePath(uri);
|
||||
const filepath = this.client.toPath(uri);
|
||||
if (!filepath) {
|
||||
return [];
|
||||
}
|
||||
@@ -56,7 +56,7 @@ class TypeScriptWorkspaceSymbolProvider implements vscode.WorkspaceSymbolProvide
|
||||
}
|
||||
const label = TypeScriptWorkspaceSymbolProvider.getLabel(item);
|
||||
result.push(new vscode.SymbolInformation(label, getSymbolKind(item), item.containerName || '',
|
||||
typeConverters.Location.fromTextSpan(this.client.asUrl(item.file), item)));
|
||||
typeConverters.Location.fromTextSpan(this.client.toResource(item.file), item)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ export default class TypeScriptServiceClientHost {
|
||||
}
|
||||
}, null, this.disposables);
|
||||
|
||||
this.versionStatus = new VersionStatus(resource => this.client.normalizePath(resource));
|
||||
this.versionStatus = new VersionStatus(resource => this.client.toPath(resource));
|
||||
this.disposables.push(this.versionStatus);
|
||||
|
||||
this.typingsStatus = new TypingsStatus(this.client);
|
||||
@@ -211,12 +211,12 @@ export default class TypeScriptServiceClientHost {
|
||||
return;
|
||||
}
|
||||
|
||||
(this.findLanguage(this.client.asUrl(body.configFile))).then(language => {
|
||||
(this.findLanguage(this.client.toResource(body.configFile))).then(language => {
|
||||
if (!language) {
|
||||
return;
|
||||
}
|
||||
if (body.diagnostics.length === 0) {
|
||||
language.configFileDiagnosticsReceived(this.client.asUrl(body.configFile), []);
|
||||
language.configFileDiagnosticsReceived(this.client.toResource(body.configFile), []);
|
||||
} else if (body.diagnostics.length >= 1) {
|
||||
workspace.openTextDocument(Uri.file(body.configFile)).then((document) => {
|
||||
let curly: [number, number, number] | undefined = undefined;
|
||||
@@ -246,10 +246,10 @@ export default class TypeScriptServiceClientHost {
|
||||
}
|
||||
if (diagnostic) {
|
||||
diagnostic.source = language.diagnosticSource;
|
||||
language.configFileDiagnosticsReceived(this.client.asUrl(body.configFile), [diagnostic]);
|
||||
language.configFileDiagnosticsReceived(this.client.toResource(body.configFile), [diagnostic]);
|
||||
}
|
||||
}, _error => {
|
||||
language.configFileDiagnosticsReceived(this.client.asUrl(body.configFile), [new Diagnostic(new Range(0, 0, 0, 0), body.diagnostics[0].text)]);
|
||||
language.configFileDiagnosticsReceived(this.client.toResource(body.configFile), [new Diagnostic(new Range(0, 0, 0, 0), body.diagnostics[0].text)]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -11,8 +11,25 @@ import { TypeScriptServiceConfiguration } from './utils/configuration';
|
||||
import Logger from './utils/logger';
|
||||
|
||||
export interface ITypeScriptServiceClient {
|
||||
normalizePath(resource: Uri): string | null;
|
||||
asUrl(filepath: string): Uri;
|
||||
/**
|
||||
* Convert a resource (VS Code) to a normalized path (TypeScript).
|
||||
*
|
||||
* Does not try handling case insensitivity.
|
||||
*/
|
||||
normalizedPath(resource: Uri): string | null;
|
||||
|
||||
/**
|
||||
* Map a resource to a normalized path
|
||||
*
|
||||
* This will attempt to handle case insensitivity.
|
||||
*/
|
||||
toPath(resource: Uri): string | null;
|
||||
|
||||
/**
|
||||
* Convert a path to a resource.
|
||||
*/
|
||||
toResource(filepath: string): Uri;
|
||||
|
||||
getWorkspaceRootForResource(resource: Uri): string | undefined;
|
||||
|
||||
onTsServerStarted: Event<API>;
|
||||
|
||||
@@ -618,7 +618,7 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
||||
}
|
||||
}
|
||||
|
||||
public normalizePath(resource: Uri): string | null {
|
||||
public normalizedPath(resource: Uri): string | null {
|
||||
if (this._apiVersion.gte(API.v213)) {
|
||||
if (resource.scheme === fileSchemes.walkThroughSnippet || resource.scheme === fileSchemes.untitled) {
|
||||
const dirName = path.dirname(resource.path);
|
||||
@@ -640,11 +640,15 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
||||
return result.replace(new RegExp('\\' + this.pathSeparator, 'g'), '/');
|
||||
}
|
||||
|
||||
public toPath(resource: Uri): string | null {
|
||||
return this.normalizedPath(resource);
|
||||
}
|
||||
|
||||
private get inMemoryResourcePrefix(): string {
|
||||
return this._apiVersion.gte(API.v270) ? '^' : '';
|
||||
}
|
||||
|
||||
public asUrl(filepath: string): Uri {
|
||||
public toResource(filepath: string): Uri {
|
||||
if (this._apiVersion.gte(API.v213)) {
|
||||
if (filepath.startsWith(TypeScriptServiceClient.WALK_THROUGH_SNIPPET_SCHEME_COLON) || (filepath.startsWith(fileSchemes.untitled + ':'))
|
||||
) {
|
||||
@@ -851,7 +855,7 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
||||
if (diagnosticEvent.body && diagnosticEvent.body.diagnostics) {
|
||||
this._onDiagnosticsReceived.fire({
|
||||
kind: getDignosticsKind(event),
|
||||
resource: this.asUrl(diagnosticEvent.body.file),
|
||||
resource: this.toResource(diagnosticEvent.body.file),
|
||||
diagnostics: diagnosticEvent.body.diagnostics
|
||||
});
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ export namespace WorkspaceEdit {
|
||||
const workspaceEdit = new vscode.WorkspaceEdit();
|
||||
for (const edit of edits) {
|
||||
for (const textChange of edit.textChanges) {
|
||||
workspaceEdit.replace(client.asUrl(edit.fileName),
|
||||
workspaceEdit.replace(client.toResource(edit.fileName),
|
||||
Range.fromTextSpan(textChange),
|
||||
textChange.newText);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user