mirror of
https://github.com/Microsoft/vscode
synced 2024-09-19 18:48:00 +00:00
Use case-insensitive synced buffer map on case-insensitive file systems
Fixes #51183 Fixes #50505
This commit is contained in:
parent
488030350d
commit
c40a2fd096
|
@ -11,6 +11,8 @@ import { Delayer } from '../utils/async';
|
||||||
import { disposeAll } from '../utils/dispose';
|
import { disposeAll } from '../utils/dispose';
|
||||||
import * as languageModeIds from '../utils/languageModeIds';
|
import * as languageModeIds from '../utils/languageModeIds';
|
||||||
import API from '../utils/api';
|
import API from '../utils/api';
|
||||||
|
import { memoize } from '../utils/memoize';
|
||||||
|
import { getTempFile } from '../utils/temp';
|
||||||
|
|
||||||
enum BufferKind {
|
enum BufferKind {
|
||||||
TypeScript = 1,
|
TypeScript = 1,
|
||||||
|
@ -69,6 +71,10 @@ class SyncedBuffer {
|
||||||
this.client.execute('open', args, false);
|
this.client.execute('open', args, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get resource(): Uri {
|
||||||
|
return this.document.uri;
|
||||||
|
}
|
||||||
|
|
||||||
public get lineCount(): number {
|
public get lineCount(): number {
|
||||||
return this.document.lineCount;
|
return this.document.lineCount;
|
||||||
}
|
}
|
||||||
|
@ -126,6 +132,10 @@ class SyncedBufferMap {
|
||||||
return file ? this._map.get(file) : undefined;
|
return file ? this._map.get(file) : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getForPath(filePath: string): SyncedBuffer | undefined {
|
||||||
|
return this.get(Uri.file(filePath));
|
||||||
|
}
|
||||||
|
|
||||||
public set(resource: Uri, buffer: SyncedBuffer) {
|
public set(resource: Uri, buffer: SyncedBuffer) {
|
||||||
const file = this.toKey(resource);
|
const file = this.toKey(resource);
|
||||||
if (file) {
|
if (file) {
|
||||||
|
@ -149,7 +159,8 @@ class SyncedBufferMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
private toKey(resource: Uri): string | null {
|
private toKey(resource: Uri): string | null {
|
||||||
return this._normalizePath(resource);
|
const key = this._normalizePath(resource);
|
||||||
|
return key ? key.toLowerCase() : key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +189,7 @@ export default class BufferSyncSupport {
|
||||||
|
|
||||||
this.diagnosticDelayer = new Delayer<any>(300);
|
this.diagnosticDelayer = new Delayer<any>(300);
|
||||||
|
|
||||||
this.syncedBuffers = new SyncedBufferMap(path => this.client.normalizedPath(path));
|
this.syncedBuffers = new SyncedBufferMap(path => this.normalizePath(path));
|
||||||
|
|
||||||
this.updateConfiguration();
|
this.updateConfiguration();
|
||||||
workspace.onDidChangeConfiguration(() => this.updateConfiguration(), null);
|
workspace.onDidChangeConfiguration(() => this.updateConfiguration(), null);
|
||||||
|
@ -202,6 +213,14 @@ export default class BufferSyncSupport {
|
||||||
return this.syncedBuffers.has(resource);
|
return this.syncedBuffers.has(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public toResource(filePath: string): Uri {
|
||||||
|
const buffer = this.syncedBuffers.getForPath(filePath);
|
||||||
|
if (buffer) {
|
||||||
|
return buffer.resource;
|
||||||
|
}
|
||||||
|
return Uri.file(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
public reOpenDocuments(): void {
|
public reOpenDocuments(): void {
|
||||||
for (const buffer of this.syncedBuffers.allBuffers) {
|
for (const buffer of this.syncedBuffers.allBuffers) {
|
||||||
buffer.open();
|
buffer.open();
|
||||||
|
@ -376,4 +395,40 @@ export default class BufferSyncSupport {
|
||||||
return this._validateTypeScript;
|
return this._validateTypeScript;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private normalizePath(path: Uri): string | null {
|
||||||
|
const key = this.client.normalizedPath(path);
|
||||||
|
if (!key) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.isCaseInsensitivePath(key) ? key.toLowerCase() : key;
|
||||||
|
}
|
||||||
|
|
||||||
|
private isCaseInsensitivePath(path: string) {
|
||||||
|
if (isWindowsPath(path)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return path[0] === '/' && this.onIsCaseInsenitiveFileSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@memoize
|
||||||
|
private get onIsCaseInsenitiveFileSystem() {
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.platform !== 'darwin') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const temp = getTempFile('typescript-case-check');
|
||||||
|
fs.writeFileSync(temp, '');
|
||||||
|
return fs.existsSync(temp.toUpperCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isWindowsPath(path: string): boolean {
|
||||||
|
return /^[a-zA-Z]:\\/.test(path);
|
||||||
|
}
|
||||||
|
|
|
@ -663,9 +663,7 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const resource = Uri.file(filepath);
|
return this.bufferSyncSupport.toResource(filepath);
|
||||||
|
|
||||||
return resource;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getWorkspaceRootForResource(resource: Uri): string | undefined {
|
public getWorkspaceRootForResource(resource: Uri): string | undefined {
|
||||||
|
@ -976,7 +974,7 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.apiVersion.gte(API.v222)) {
|
if (this.apiVersion.gte(API.v222)) {
|
||||||
this.cancellationPipeName = electron.getTempFile(`tscancellation-${electron.makeRandomHexString(20)}`);
|
this.cancellationPipeName = electron.getTempSock('tscancellation');
|
||||||
args.push('--cancellationPipeName', this.cancellationPipeName + '*');
|
args.push('--cancellationPipeName', this.cancellationPipeName + '*');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,25 +3,21 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import Logger from './logger';
|
||||||
|
import { getTempFile, makeRandomHexString } from './temp';
|
||||||
import path = require('path');
|
import path = require('path');
|
||||||
import os = require('os');
|
import os = require('os');
|
||||||
import net = require('net');
|
import net = require('net');
|
||||||
import cp = require('child_process');
|
import cp = require('child_process');
|
||||||
import Logger from './logger';
|
|
||||||
|
|
||||||
export interface IForkOptions {
|
export interface IForkOptions {
|
||||||
cwd?: string;
|
cwd?: string;
|
||||||
execArgv?: string[];
|
execArgv?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeRandomHexString(length: number): string {
|
export function getTempSock(prefix: string): string {
|
||||||
let chars = ['0', '1', '2', '3', '4', '5', '6', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
|
const fullName = `vscode-${prefix}-${makeRandomHexString(20)}`;
|
||||||
let result = '';
|
return getTempFile(fullName + '.sock');
|
||||||
for (let i = 0; i < length; i++) {
|
|
||||||
const idx = Math.floor(chars.length * Math.random());
|
|
||||||
result += chars[idx];
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function generatePipeName(): string {
|
function generatePipeName(): string {
|
||||||
|
@ -38,12 +34,6 @@ function getPipeName(name: string): string {
|
||||||
return path.join(os.tmpdir(), fullName + '.sock');
|
return path.join(os.tmpdir(), fullName + '.sock');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTempFile(name: string): string {
|
|
||||||
const fullName = 'vscode-' + name;
|
|
||||||
return path.join(os.tmpdir(), fullName + '.sock');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function generatePatchedEnv(
|
function generatePatchedEnv(
|
||||||
env: any,
|
env: any,
|
||||||
stdInPipeName: string,
|
stdInPipeName: string,
|
||||||
|
@ -131,7 +121,7 @@ export function fork(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create the process
|
// Create the process
|
||||||
logger.info('Forking TSServer', `PATH: ${newEnv['PATH']}`);
|
logger.info('Forking TSServer', `PATH: ${newEnv['PATH']} `);
|
||||||
|
|
||||||
const bootstrapperPath = require.resolve('./electronForkStart');
|
const bootstrapperPath = require.resolve('./electronForkStart');
|
||||||
childProcess = cp.fork(bootstrapperPath, [modulePath].concat(args), {
|
childProcess = cp.fork(bootstrapperPath, [modulePath].concat(args), {
|
||||||
|
|
21
extensions/typescript-language-features/src/utils/temp.ts
Normal file
21
extensions/typescript-language-features/src/utils/temp.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import path = require('path');
|
||||||
|
import os = require('os');
|
||||||
|
|
||||||
|
export function makeRandomHexString(length: number): string {
|
||||||
|
let chars = ['0', '1', '2', '3', '4', '5', '6', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
|
||||||
|
let result = '';
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
const idx = Math.floor(chars.length * Math.random());
|
||||||
|
result += chars[idx];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTempFile(name: string): string {
|
||||||
|
return path.join(os.tmpdir(), name);
|
||||||
|
}
|
Loading…
Reference in a new issue