mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-30 16:50:30 -04:00
Merge from vscode b8c2e7108b3cae7aa2782112da654bedd8bb3a52 (#4808)
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { LinkDetector } from 'vs/workbench/contrib/debug/browser/linkDetector';
|
||||
import { RGBA, Color } from 'vs/base/common/color';
|
||||
|
||||
/**
|
||||
* @param text The content to stylize.
|
||||
@@ -15,6 +16,8 @@ export function handleANSIOutput(text: string, linkDetector: LinkDetector): HTML
|
||||
const textLength: number = text.length;
|
||||
|
||||
let styleNames: string[] = [];
|
||||
let customFgColor: RGBA | undefined;
|
||||
let customBgColor: RGBA | undefined;
|
||||
let currentPos: number = 0;
|
||||
let buffer: string = '';
|
||||
|
||||
@@ -48,45 +51,33 @@ export function handleANSIOutput(text: string, linkDetector: LinkDetector): HTML
|
||||
if (sequenceFound) {
|
||||
|
||||
// Flush buffer with previous styles.
|
||||
appendStylizedStringToContainer(root, buffer, styleNames, linkDetector);
|
||||
appendStylizedStringToContainer(root, buffer, styleNames, linkDetector, customFgColor, customBgColor);
|
||||
|
||||
buffer = '';
|
||||
|
||||
/*
|
||||
* Certain ranges that are matched here do not contain real graphics rendition sequences. For
|
||||
* the sake of having a simpler expression, they have been included anyway.
|
||||
*/
|
||||
if (ansiSequence.match(/^(?:[349][0-7]|10[0-7]|[013]|4|[34]9)(?:;(?:[349][0-7]|10[0-7]|[013]|4|[34]9))*;?m$/)) {
|
||||
* Certain ranges that are matched here do not contain real graphics rendition sequences. For
|
||||
* the sake of having a simpler expression, they have been included anyway.
|
||||
*/
|
||||
if (ansiSequence.match(/^(?:[34][0-8]|9[0-7]|10[0-7]|[013]|4|[34]9)(?:;[349][0-7]|10[0-7]|[013]|[245]|[34]9)?(?:;[012]?[0-9]?[0-9])*;?m$/)) {
|
||||
|
||||
const styleCodes: number[] = ansiSequence.slice(0, -1) // Remove final 'm' character.
|
||||
.split(';') // Separate style codes.
|
||||
.filter(elem => elem !== '') // Filter empty elems as '34;m' -> ['34', ''].
|
||||
.map(elem => parseInt(elem, 10)); // Convert to numbers.
|
||||
const styleCodes: number[] = ansiSequence.slice(0, -1) // Remove final 'm' character.
|
||||
.split(';') // Separate style codes.
|
||||
.filter(elem => elem !== '') // Filter empty elems as '34;m' -> ['34', ''].
|
||||
.map(elem => parseInt(elem, 10)); // Convert to numbers.
|
||||
|
||||
for (let code of styleCodes) {
|
||||
if (code === 0) {
|
||||
styleNames = [];
|
||||
} else if (code === 1) {
|
||||
styleNames.push('code-bold');
|
||||
} else if (code === 3) {
|
||||
styleNames.push('code-italic');
|
||||
} else if (code === 4) {
|
||||
styleNames.push('code-underline');
|
||||
} else if (code === 39 || (code >= 30 && code <= 37) || (code >= 90 && code <= 97)) {
|
||||
// Remove all previous foreground colour codes
|
||||
styleNames = styleNames.filter(style => !style.match(/^code-foreground-\d+$/));
|
||||
if (styleCodes[0] === 38 || styleCodes[0] === 48) {
|
||||
// Advanced color code - can't be combined with formatting codes like simple colors can
|
||||
// Ignores invalid colors and additional info beyond what is necessary
|
||||
const colorType = (styleCodes[0] === 38) ? 'foreground' : 'background';
|
||||
|
||||
if (code !== 39) {
|
||||
styleNames.push('code-foreground-' + code);
|
||||
}
|
||||
} else if (code === 49 || (code >= 40 && code <= 47) || (code >= 100 && code <= 107)) {
|
||||
// Remove all previous background colour codes
|
||||
styleNames = styleNames.filter(style => !style.match(/^code-background-\d+$/));
|
||||
|
||||
if (code !== 49) {
|
||||
styleNames.push('code-background-' + code);
|
||||
}
|
||||
if (styleCodes[1] === 5) {
|
||||
set8BitColor(styleCodes, colorType);
|
||||
} else if (styleCodes[1] === 2) {
|
||||
set24BitColor(styleCodes, colorType);
|
||||
}
|
||||
} else {
|
||||
setBasicFormatters(styleCodes);
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -96,23 +87,121 @@ export function handleANSIOutput(text: string, linkDetector: LinkDetector): HTML
|
||||
} else {
|
||||
currentPos = startPos;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (sequenceFound === false) {
|
||||
buffer += text.charAt(currentPos);
|
||||
currentPos++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Flush remaining text buffer if not empty.
|
||||
if (buffer) {
|
||||
appendStylizedStringToContainer(root, buffer, styleNames, linkDetector);
|
||||
appendStylizedStringToContainer(root, buffer, styleNames, linkDetector, customFgColor, customBgColor);
|
||||
}
|
||||
|
||||
return root;
|
||||
|
||||
/**
|
||||
* Change the foreground or background color by clearing the current color
|
||||
* and adding the new one.
|
||||
* @param newClass If string or number, new class will be
|
||||
* `code-(foreground or background)-newClass`. If `undefined`, no new class
|
||||
* will be added.
|
||||
* @param colorType If `'foreground'`, will change the foreground color, if
|
||||
* `'background'`, will change the background color.
|
||||
* @param customColor If provided, this custom color will be used instead of
|
||||
* a class-defined color.
|
||||
*/
|
||||
function changeColor(newClass: string | number | undefined, colorType: 'foreground' | 'background', customColor?: RGBA): void {
|
||||
styleNames = styleNames.filter(style => !style.match(new RegExp(`^code-${colorType}-(\\d+|custom)$`)));
|
||||
if (newClass) {
|
||||
styleNames.push(`code-${colorType}-${newClass}`);
|
||||
}
|
||||
if (colorType === 'foreground') {
|
||||
customFgColor = customColor;
|
||||
} else {
|
||||
customBgColor = customColor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate and set basic ANSI formatting. Supports bold, italic, underline,
|
||||
* normal foreground and background colors, and bright foreground and
|
||||
* background colors. Not to be used for codes containing advanced colors.
|
||||
* Will ignore invalid codes.
|
||||
* @param styleCodes Array of ANSI basic styling numbers, which will be
|
||||
* applied in order. New colors and backgrounds clear old ones; new formatting
|
||||
* does not.
|
||||
* @see {@link https://en.wikipedia.org/wiki/ANSI_escape_code }
|
||||
*/
|
||||
function setBasicFormatters(styleCodes: number[]): void {
|
||||
for (let code of styleCodes) {
|
||||
if (code === 0) {
|
||||
styleNames = [];
|
||||
} else if (code === 1) {
|
||||
styleNames.push('code-bold');
|
||||
} else if (code === 3) {
|
||||
styleNames.push('code-italic');
|
||||
} else if (code === 4) {
|
||||
styleNames.push('code-underline');
|
||||
} else if ((code >= 30 && code <= 37) || (code >= 90 && code <= 97)) {
|
||||
changeColor(code, 'foreground');
|
||||
} else if ((code >= 40 && code <= 47) || (code >= 100 && code <= 107)) {
|
||||
changeColor(code, 'background');
|
||||
} else if (code === 39) {
|
||||
changeColor(undefined, 'foreground');
|
||||
} else if (code === 49) {
|
||||
changeColor(undefined, 'background');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate and set styling for complicated 24-bit ANSI color codes.
|
||||
* @param styleCodes Full list of integer codes that make up the full ANSI
|
||||
* sequence, including the two defining codes and the three RGB codes.
|
||||
* @param colorType If `'foreground'`, will set foreground color, if
|
||||
* `'background'`, will set background color.
|
||||
* @see {@link https://en.wikipedia.org/wiki/ANSI_escape_code#24-bit }
|
||||
*/
|
||||
function set24BitColor(styleCodes: number[], colorType: 'foreground' | 'background'): void {
|
||||
if (styleCodes.length >= 5 &&
|
||||
styleCodes[2] >= 0 && styleCodes[2] <= 255 &&
|
||||
styleCodes[3] >= 0 && styleCodes[3] <= 255 &&
|
||||
styleCodes[4] >= 0 && styleCodes[4] <= 255) {
|
||||
const customColor = new RGBA(styleCodes[2], styleCodes[3], styleCodes[4]);
|
||||
changeColor('custom', colorType, customColor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate and set styling for advanced 8-bit ANSI color codes.
|
||||
* @param styleCodes Full list of integer codes that make up the ANSI
|
||||
* sequence, including the two defining codes and the one color code.
|
||||
* @param colorType If `'foreground'`, will set foreground color, if
|
||||
* `'background'`, will set background color.
|
||||
* @see {@link https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit }
|
||||
*/
|
||||
function set8BitColor(styleCodes: number[], colorType: 'foreground' | 'background'): void {
|
||||
let colorNumber = styleCodes[2];
|
||||
const color = calcANSI8bitColor(colorNumber);
|
||||
|
||||
if (color) {
|
||||
changeColor('custom', colorType, color);
|
||||
} else if (colorNumber >= 0 && colorNumber <= 15) {
|
||||
// Need to map to one of the four basic color ranges (30-37, 90-97, 40-47, 100-107)
|
||||
colorNumber += 30;
|
||||
if (colorNumber >= 38) {
|
||||
// Bright colors
|
||||
colorNumber += 52;
|
||||
}
|
||||
if (colorType === 'background') {
|
||||
colorNumber += 10;
|
||||
}
|
||||
changeColor(colorNumber, colorType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,8 +209,17 @@ export function handleANSIOutput(text: string, linkDetector: LinkDetector): HTML
|
||||
* @param stringContent The text content to be appended.
|
||||
* @param cssClasses The list of CSS styles to apply to the text content.
|
||||
* @param linkDetector The {@link LinkDetector} responsible for generating links from {@param stringContent}.
|
||||
* @param customTextColor If provided, will apply custom color with inline style.
|
||||
* @param customBackgroundColor If provided, will apply custom color with inline style.
|
||||
*/
|
||||
export function appendStylizedStringToContainer(root: HTMLElement, stringContent: string, cssClasses: string[], linkDetector: LinkDetector): void {
|
||||
export function appendStylizedStringToContainer(
|
||||
root: HTMLElement,
|
||||
stringContent: string,
|
||||
cssClasses: string[],
|
||||
linkDetector: LinkDetector,
|
||||
customTextColor?: RGBA,
|
||||
customBackgroundColor?: RGBA
|
||||
): void {
|
||||
if (!root || !stringContent) {
|
||||
return;
|
||||
}
|
||||
@@ -129,5 +227,55 @@ export function appendStylizedStringToContainer(root: HTMLElement, stringContent
|
||||
const container = linkDetector.handleLinks(stringContent);
|
||||
|
||||
container.className = cssClasses.join(' ');
|
||||
if (customTextColor) {
|
||||
container.style.color =
|
||||
Color.Format.CSS.formatRGB(new Color(customTextColor));
|
||||
}
|
||||
if (customBackgroundColor) {
|
||||
container.style.backgroundColor =
|
||||
Color.Format.CSS.formatRGB(new Color(customBackgroundColor));
|
||||
}
|
||||
|
||||
root.appendChild(container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the color from the color set defined in the ANSI 8-bit standard.
|
||||
* Standard and high intensity colors are not defined in the standard as specific
|
||||
* colors, so these and invalid colors return `undefined`.
|
||||
* @see {@link https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit } for info.
|
||||
* @param colorNumber The number (ranging from 16 to 255) referring to the color
|
||||
* desired.
|
||||
*/
|
||||
export function calcANSI8bitColor(colorNumber: number): RGBA | undefined {
|
||||
if (colorNumber % 1 !== 0) {
|
||||
// Should be integer
|
||||
// {{SQL CARBON EDIT}} @todo anthonydresser this is necessary because we don't use strict null checks
|
||||
return undefined;
|
||||
} if (colorNumber >= 16 && colorNumber <= 231) {
|
||||
// Converts to one of 216 RGB colors
|
||||
colorNumber -= 16;
|
||||
|
||||
let blue: number = colorNumber % 6;
|
||||
colorNumber = (colorNumber - blue) / 6;
|
||||
let green: number = colorNumber % 6;
|
||||
colorNumber = (colorNumber - green) / 6;
|
||||
let red: number = colorNumber;
|
||||
|
||||
// red, green, blue now range on [0, 5], need to map to [0,255]
|
||||
const convFactor: number = 255 / 5;
|
||||
blue = Math.round(blue * convFactor);
|
||||
green = Math.round(green * convFactor);
|
||||
red = Math.round(red * convFactor);
|
||||
|
||||
return new RGBA(red, green, blue);
|
||||
} else if (colorNumber >= 232 && colorNumber <= 255) {
|
||||
// Converts to a grayscale value
|
||||
colorNumber -= 232;
|
||||
const colorLevel: number = Math.round(colorNumber / 23 * 255);
|
||||
return new RGBA(colorLevel, colorLevel, colorLevel);
|
||||
} else {
|
||||
// {{SQL CARBON EDIT}} @todo anthonydresser this is necessary because we don't use strict null checks
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
import * as assert from 'assert';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { appendStylizedStringToContainer, handleANSIOutput } from 'vs/workbench/contrib/debug/browser/debugANSIHandling';
|
||||
import { appendStylizedStringToContainer, handleANSIOutput, calcANSI8bitColor } from 'vs/workbench/contrib/debug/browser/debugANSIHandling';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { workbenchInstantiationService } from 'vs/workbench/test/workbenchTestServices';
|
||||
import { LinkDetector } from 'vs/workbench/contrib/debug/browser/linkDetector';
|
||||
import { Color, RGBA } from 'vs/base/common/color';
|
||||
|
||||
suite('Debug - ANSI Handling', () => {
|
||||
test('appendStylizedStringToContainer', () => {
|
||||
|
||||
@@ -349,7 +349,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
|
||||
private resolveWorkspaceFolderExtensionConfig(workspaceFolder: IWorkspaceFolder): Promise<IExtensionsConfigContent | null> {
|
||||
const extensionsJsonUri = workspaceFolder.toResource(EXTENSIONS_CONFIG);
|
||||
|
||||
return Promise.resolve(this.fileService.resolveFile(extensionsJsonUri)
|
||||
return Promise.resolve(this.fileService.resolve(extensionsJsonUri)
|
||||
.then(() => this.fileService.resolveContent(extensionsJsonUri))
|
||||
.then(content => <IExtensionsConfigContent>json.parse(content.value), err => null));
|
||||
}
|
||||
|
||||
@@ -2555,7 +2555,7 @@ export class OpenExtensionsFolderAction extends Action {
|
||||
run(): Promise<void> {
|
||||
const extensionsHome = URI.file(this.environmentService.extensionsPath);
|
||||
|
||||
return Promise.resolve(this.fileService.resolveFile(extensionsHome)).then(file => {
|
||||
return Promise.resolve(this.fileService.resolve(extensionsHome)).then(file => {
|
||||
let itemToShow: URI;
|
||||
if (file.children && file.children.length > 0) {
|
||||
itemToShow = file.children[0].resource;
|
||||
|
||||
@@ -90,7 +90,7 @@ CommandsRegistry.registerCommand({
|
||||
const terminalService = accessor.get(IExternalTerminalService);
|
||||
const resources = getMultiSelectedResources(resource, accessor.get(IListService), editorService);
|
||||
|
||||
return fileService.resolveFiles(resources.map(r => ({ resource: r }))).then(stats => {
|
||||
return fileService.resolveAll(resources.map(r => ({ resource: r }))).then(stats => {
|
||||
const directoriesToOpen = distinct(stats.filter(data => data.success).map(({ stat }) => stat!.isDirectory ? stat!.resource.fsPath : paths.dirname(stat!.resource.fsPath)));
|
||||
return directoriesToOpen.map(dir => {
|
||||
if (configurationService.getValue<IExternalTerminalConfiguration>().terminal.explorerKind === 'integrated') {
|
||||
|
||||
@@ -114,12 +114,12 @@ export class FileEditorTracker extends Disposable implements IWorkbenchContribut
|
||||
private onFileOperation(e: FileOperationEvent): void {
|
||||
|
||||
// Handle moves specially when file is opened
|
||||
if (e.operation === FileOperation.MOVE && e.target) {
|
||||
if (e.isOperation(FileOperation.MOVE)) {
|
||||
this.handleMovedFileInOpenedEditors(e.resource, e.target.resource);
|
||||
}
|
||||
|
||||
// Handle deletes
|
||||
if (e.operation === FileOperation.DELETE || e.operation === FileOperation.MOVE) {
|
||||
if (e.isOperation(FileOperation.DELETE) || e.isOperation(FileOperation.MOVE)) {
|
||||
this.handleDeletes(e.resource, false, e.target ? e.target.resource : undefined);
|
||||
}
|
||||
}
|
||||
@@ -176,7 +176,7 @@ export class FileEditorTracker extends Disposable implements IWorkbenchContribut
|
||||
// flag.
|
||||
let checkExists: Promise<boolean>;
|
||||
if (isExternal) {
|
||||
checkExists = timeout(100).then(() => this.fileService.existsFile(resource));
|
||||
checkExists = timeout(100).then(() => this.fileService.exists(resource));
|
||||
} else {
|
||||
checkExists = Promise.resolve(false);
|
||||
}
|
||||
@@ -360,7 +360,7 @@ export class FileEditorTracker extends Disposable implements IWorkbenchContribut
|
||||
// Handle no longer visible out of workspace resources
|
||||
this.activeOutOfWorkspaceWatchers.forEach(resource => {
|
||||
if (!visibleOutOfWorkspacePaths.get(resource)) {
|
||||
this.fileService.unwatchFileChanges(resource);
|
||||
this.fileService.unwatch(resource);
|
||||
this.activeOutOfWorkspaceWatchers.delete(resource);
|
||||
}
|
||||
});
|
||||
@@ -368,7 +368,7 @@ export class FileEditorTracker extends Disposable implements IWorkbenchContribut
|
||||
// Handle newly visible out of workspace resources
|
||||
visibleOutOfWorkspacePaths.forEach(resource => {
|
||||
if (!this.activeOutOfWorkspaceWatchers.get(resource)) {
|
||||
this.fileService.watchFileChanges(resource);
|
||||
this.fileService.watch(resource);
|
||||
this.activeOutOfWorkspaceWatchers.set(resource, resource);
|
||||
}
|
||||
});
|
||||
@@ -378,7 +378,7 @@ export class FileEditorTracker extends Disposable implements IWorkbenchContribut
|
||||
super.dispose();
|
||||
|
||||
// Dispose watchers if any
|
||||
this.activeOutOfWorkspaceWatchers.forEach(resource => this.fileService.unwatchFileChanges(resource));
|
||||
this.activeOutOfWorkspaceWatchers.forEach(resource => this.fileService.unwatch(resource));
|
||||
this.activeOutOfWorkspaceWatchers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,7 +503,7 @@ class PasteFileAction extends BaseErrorReportingAction {
|
||||
throw new Error(nls.localize('fileIsAncestor', "File to paste is an ancestor of the destination folder"));
|
||||
}
|
||||
|
||||
return this.fileService.resolveFile(fileToPaste).then(fileToPasteStat => {
|
||||
return this.fileService.resolve(fileToPaste).then(fileToPasteStat => {
|
||||
|
||||
// Find target
|
||||
let target: ExplorerItem;
|
||||
@@ -516,7 +516,7 @@ class PasteFileAction extends BaseErrorReportingAction {
|
||||
const targetFile = findValidPasteFileTarget(target, { resource: fileToPaste, isDirectory: fileToPasteStat.isDirectory, allowOverwirte: pasteShouldMove });
|
||||
|
||||
// Copy File
|
||||
const promise = pasteShouldMove ? this.fileService.moveFile(fileToPaste, targetFile) : this.fileService.copyFile(fileToPaste, targetFile);
|
||||
const promise = pasteShouldMove ? this.fileService.move(fileToPaste, targetFile) : this.fileService.copy(fileToPaste, targetFile);
|
||||
return promise.then<ITextEditor | undefined>(stat => {
|
||||
if (pasteShouldMove) {
|
||||
// Cut is done. Make sure to clear cut state.
|
||||
|
||||
@@ -300,7 +300,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
|
||||
// Set side input
|
||||
if (resources.length) {
|
||||
return fileService.resolveFiles(resources.map(resource => ({ resource }))).then(resolved => {
|
||||
return fileService.resolveAll(resources.map(resource => ({ resource }))).then(resolved => {
|
||||
const editors = resolved.filter(r => r.stat && r.success && !r.stat.isDirectory).map(r => ({
|
||||
resource: r.stat!.resource
|
||||
}));
|
||||
|
||||
@@ -608,7 +608,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
|
||||
const droppedResources = extractResources(originalEvent, true);
|
||||
|
||||
// Check for dropped external files to be folders
|
||||
return this.fileService.resolveFiles(droppedResources).then(result => {
|
||||
return this.fileService.resolveAll(droppedResources).then(result => {
|
||||
|
||||
// Pass focus to window
|
||||
this.windowService.focusWindow();
|
||||
@@ -649,7 +649,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
|
||||
if (resources && resources.length > 0) {
|
||||
|
||||
// Resolve target to check for name collisions and ask user
|
||||
return this.fileService.resolveFile(target.resource).then(targetStat => {
|
||||
return this.fileService.resolve(target.resource).then(targetStat => {
|
||||
|
||||
// Check for name collisions
|
||||
const targetNames = new Set<string>();
|
||||
@@ -695,7 +695,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
|
||||
|
||||
return revertPromise.then(() => {
|
||||
const copyTarget = joinPath(target.resource, basename(sourceFile));
|
||||
return this.fileService.copyFile(sourceFile, copyTarget, true).then(stat => {
|
||||
return this.fileService.copy(sourceFile, copyTarget, true).then(stat => {
|
||||
|
||||
// if we only add one file, just open it directly
|
||||
if (resources.length === 1) {
|
||||
@@ -794,7 +794,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
|
||||
// Reuse duplicate action if user copies
|
||||
if (isCopy) {
|
||||
|
||||
return this.fileService.copyFile(source.resource, findValidPasteFileTarget(target, { resource: source.resource, isDirectory: source.isDirectory, allowOverwirte: false })).then(stat => {
|
||||
return this.fileService.copy(source.resource, findValidPasteFileTarget(target, { resource: source.resource, isDirectory: source.isDirectory, allowOverwirte: false })).then(stat => {
|
||||
if (!stat.isDirectory) {
|
||||
return this.editorService.openEditor({ resource: stat.resource, options: { pinned: true } }).then(() => undefined);
|
||||
}
|
||||
|
||||
@@ -249,7 +249,7 @@ export class ExplorerItem {
|
||||
// Resolve metadata only when the mtime is needed since this can be expensive
|
||||
// Mtime is only used when the sort order is 'modified'
|
||||
const resolveMetadata = explorerService.sortOrder === 'modified';
|
||||
promise = fileService.resolveFile(this.resource, { resolveSingleChildDescendants: true, resolveMetadata }).then(stat => {
|
||||
promise = fileService.resolve(this.resource, { resolveSingleChildDescendants: true, resolveMetadata }).then(stat => {
|
||||
const resolved = ExplorerItem.create(stat, this);
|
||||
ExplorerItem.mergeLocalWithDisk(resolved, this);
|
||||
this._isDirectoryResolved = true;
|
||||
|
||||
@@ -40,7 +40,6 @@ export class ExplorerService implements IExplorerService {
|
||||
private editable: { stat: ExplorerItem, data: IEditableData } | undefined;
|
||||
private _sortOrder: SortOrder;
|
||||
private cutItems: ExplorerItem[] | undefined;
|
||||
private fileSystemProviderSchemes = new Set<string>();
|
||||
|
||||
constructor(
|
||||
@IFileService private fileService: IFileService,
|
||||
@@ -99,14 +98,7 @@ export class ExplorerService implements IExplorerService {
|
||||
this.disposables.push(this.fileService.onAfterOperation(e => this.onFileOperation(e)));
|
||||
this.disposables.push(this.fileService.onFileChanges(e => this.onFileChanges(e)));
|
||||
this.disposables.push(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(this.configurationService.getValue<IFilesConfiguration>())));
|
||||
this.disposables.push(this.fileService.onDidChangeFileSystemProviderRegistrations(e => {
|
||||
if (e.added && this.fileSystemProviderSchemes.has(e.scheme)) {
|
||||
// A file system provider got re-registered, we should update all file stats since they might change (got read-only)
|
||||
this._onDidChangeItem.fire(undefined);
|
||||
} else {
|
||||
this.fileSystemProviderSchemes.add(e.scheme);
|
||||
}
|
||||
}));
|
||||
this.disposables.push(this.fileService.onDidChangeFileSystemProviderRegistrations(() => this._onDidChangeItem.fire(undefined)));
|
||||
this.disposables.push(model.onDidChangeRoots(() => this._onDidChangeRoots.fire()));
|
||||
|
||||
return model;
|
||||
@@ -159,7 +151,7 @@ export class ExplorerService implements IExplorerService {
|
||||
const workspaceFolder = this.contextService.getWorkspaceFolder(resource);
|
||||
const rootUri = workspaceFolder ? workspaceFolder.uri : this.roots[0].resource;
|
||||
const root = this.roots.filter(r => r.resource.toString() === rootUri.toString()).pop()!;
|
||||
return this.fileService.resolveFile(rootUri, options).then(stat => {
|
||||
return this.fileService.resolve(rootUri, options).then(stat => {
|
||||
|
||||
// Convert to model
|
||||
const modelStat = ExplorerItem.create(stat, undefined, options.resolveTo);
|
||||
@@ -190,8 +182,8 @@ export class ExplorerService implements IExplorerService {
|
||||
|
||||
private onFileOperation(e: FileOperationEvent): void {
|
||||
// Add
|
||||
if (e.operation === FileOperation.CREATE || e.operation === FileOperation.COPY) {
|
||||
const addedElement = e.target!;
|
||||
if (e.isOperation(FileOperation.CREATE) || e.isOperation(FileOperation.COPY)) {
|
||||
const addedElement = e.target;
|
||||
const parentResource = dirname(addedElement.resource)!;
|
||||
const parents = this.model.findAll(parentResource);
|
||||
|
||||
@@ -201,7 +193,7 @@ export class ExplorerService implements IExplorerService {
|
||||
parents.forEach(p => {
|
||||
// We have to check if the parent is resolved #29177
|
||||
const resolveMetadata = this.sortOrder === `modified`;
|
||||
const thenable: Promise<IFileStat | undefined> = p.isDirectoryResolved ? Promise.resolve(undefined) : this.fileService.resolveFile(p.resource, { resolveMetadata });
|
||||
const thenable: Promise<IFileStat | undefined> = p.isDirectoryResolved ? Promise.resolve(undefined) : this.fileService.resolve(p.resource, { resolveMetadata });
|
||||
thenable.then(stat => {
|
||||
if (stat) {
|
||||
const modelStat = ExplorerItem.create(stat, p.parent);
|
||||
@@ -220,9 +212,9 @@ export class ExplorerService implements IExplorerService {
|
||||
}
|
||||
|
||||
// Move (including Rename)
|
||||
else if (e.operation === FileOperation.MOVE) {
|
||||
else if (e.isOperation(FileOperation.MOVE)) {
|
||||
const oldResource = e.resource;
|
||||
const newElement = e.target!;
|
||||
const newElement = e.target;
|
||||
const oldParentResource = dirname(oldResource);
|
||||
const newParentResource = dirname(newElement.resource);
|
||||
|
||||
@@ -254,7 +246,7 @@ export class ExplorerService implements IExplorerService {
|
||||
}
|
||||
|
||||
// Delete
|
||||
else if (e.operation === FileOperation.DELETE) {
|
||||
else if (e.isOperation(FileOperation.DELETE)) {
|
||||
const modelElements = this.model.findAll(e.resource);
|
||||
modelElements.forEach(element => {
|
||||
if (element.parent) {
|
||||
|
||||
@@ -191,7 +191,7 @@ export class OpenFileHandler extends QuickOpenHandler {
|
||||
workspaceFolders[0].uri.with({ path: detildifiedQuery }) :
|
||||
URI.file(detildifiedQuery);
|
||||
|
||||
return this.fileService.resolveFile(resource).then(
|
||||
return this.fileService.resolve(resource).then(
|
||||
stat => stat.isDirectory ? undefined : resource,
|
||||
error => undefined);
|
||||
}
|
||||
|
||||
@@ -365,7 +365,7 @@ const searchInFolderCommand: ICommandHandler = (accessor, resource?: URI) => {
|
||||
|
||||
return openSearchView(viewletService, panelService, configurationService, true).then(searchView => {
|
||||
if (resources && resources.length && searchView) {
|
||||
return fileService.resolveFiles(resources.map(resource => ({ resource }))).then(results => {
|
||||
return fileService.resolveAll(resources.map(resource => ({ resource }))).then(results => {
|
||||
const folders: URI[] = [];
|
||||
|
||||
results.forEach(result => {
|
||||
|
||||
@@ -1200,7 +1200,7 @@ export class SearchView extends ViewletPanel {
|
||||
// Validate folderQueries
|
||||
const folderQueriesExistP =
|
||||
query.folderQueries.map(fq => {
|
||||
return this.fileService.existsFile(fq.folder);
|
||||
return this.fileService.exists(fq.folder);
|
||||
});
|
||||
|
||||
return Promise.resolve(folderQueriesExistP).then(existResults => {
|
||||
|
||||
@@ -164,7 +164,7 @@ async function createSnippetFile(scope: string, defaultPath: URI, windowService:
|
||||
}
|
||||
|
||||
async function createLanguageSnippetFile(pick: ISnippetPick, fileService: IFileService) {
|
||||
if (await fileService.existsFile(URI.file(pick.filepath))) {
|
||||
if (await fileService.exists(URI.file(pick.filepath))) {
|
||||
return;
|
||||
}
|
||||
const contents = [
|
||||
|
||||
@@ -121,11 +121,11 @@ function watch(service: IFileService, resource: URI, callback: (type: FileChange
|
||||
}
|
||||
}
|
||||
});
|
||||
service.watchFileChanges(resource);
|
||||
service.watch(resource);
|
||||
return {
|
||||
dispose() {
|
||||
listener.dispose();
|
||||
service.unwatchFileChanges(resource);
|
||||
service.unwatch(resource);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -277,7 +277,7 @@ class SnippetsService implements ISnippetsService {
|
||||
private _initWorkspaceFolderSnippets(workspace: IWorkspace, bucket: IDisposable[]): Promise<any> {
|
||||
let promises = workspace.folders.map(folder => {
|
||||
const snippetFolder = folder.toResource('.vscode');
|
||||
return this._fileService.existsFile(snippetFolder).then(value => {
|
||||
return this._fileService.exists(snippetFolder).then(value => {
|
||||
if (value) {
|
||||
this._initFolderSnippets(SnippetSource.Workspace, snippetFolder, bucket);
|
||||
} else {
|
||||
@@ -305,7 +305,7 @@ class SnippetsService implements ISnippetsService {
|
||||
if (type === FileChangeType.DELETED) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return this._fileService.resolveFile(folder).then(stat => {
|
||||
return this._fileService.resolve(folder).then(stat => {
|
||||
for (const entry of stat.children || []) {
|
||||
disposables.push(this._addSnippetFile(entry.resource, source));
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ export function getHashedRemotesFromConfig(text: string, stripEndingDotGit: bool
|
||||
export function getHashedRemotesFromUri(workspaceUri: URI, fileService: IFileService, stripEndingDotGit: boolean = false): Promise<string[]> {
|
||||
const path = workspaceUri.path;
|
||||
const uri = workspaceUri.with({ path: `${path !== '/' ? path : ''}/.git/config` });
|
||||
return fileService.existsFile(uri).then(exists => {
|
||||
return fileService.exists(uri).then(exists => {
|
||||
if (!exists) {
|
||||
return [];
|
||||
}
|
||||
@@ -364,7 +364,7 @@ export class WorkspaceStats implements IWorkbenchContribution {
|
||||
return Promise.resolve(tags);
|
||||
}
|
||||
|
||||
return this.fileService.resolveFiles(folders.map(resource => ({ resource }))).then((files: IResolveFileResult[]) => {
|
||||
return this.fileService.resolveAll(folders.map(resource => ({ resource }))).then((files: IResolveFileResult[]) => {
|
||||
const names = (<IFileStat[]>[]).concat(...files.map(result => result.success ? (result.stat!.children || []) : [])).map(c => c.name);
|
||||
const nameSet = names.reduce((s, n) => s.add(n.toLowerCase()), new Set());
|
||||
|
||||
@@ -437,7 +437,7 @@ export class WorkspaceStats implements IWorkbenchContribution {
|
||||
function getFilePromises(filename: string, fileService: IFileService, contentHandler: (content: IContent) => void): Promise<void>[] {
|
||||
return !nameSet.has(filename) ? [] : (folders as URI[]).map(workspaceUri => {
|
||||
const uri = workspaceUri.with({ path: `${workspaceUri.path !== '/' ? workspaceUri.path : ''}/${filename}` });
|
||||
return fileService.existsFile(uri).then(exists => {
|
||||
return fileService.exists(uri).then(exists => {
|
||||
if (!exists) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -620,7 +620,7 @@ export class WorkspaceStats implements IWorkbenchContribution {
|
||||
Promise.all<string[]>(workspaceUris.map(workspaceUri => {
|
||||
const path = workspaceUri.path;
|
||||
const uri = workspaceUri.with({ path: `${path !== '/' ? path : ''}/.git/config` });
|
||||
return this.fileService.existsFile(uri).then(exists => {
|
||||
return this.fileService.exists(uri).then(exists => {
|
||||
if (!exists) {
|
||||
return [];
|
||||
}
|
||||
@@ -666,7 +666,7 @@ export class WorkspaceStats implements IWorkbenchContribution {
|
||||
const path = workspaceUri.path;
|
||||
return workspaceUri.with({ path: `${path !== '/' ? path : ''}/node_modules` });
|
||||
});
|
||||
return this.fileService.resolveFiles(uris.map(resource => ({ resource }))).then(
|
||||
return this.fileService.resolveAll(uris.map(resource => ({ resource }))).then(
|
||||
results => {
|
||||
const names = (<IFileStat[]>[]).concat(...results.map(result => result.success ? (result.stat!.children || []) : [])).map(c => c.name);
|
||||
const referencesAzure = WorkspaceStats.searchArray(names, /azure/i);
|
||||
@@ -689,7 +689,7 @@ export class WorkspaceStats implements IWorkbenchContribution {
|
||||
return Promise.all(workspaceUris.map(workspaceUri => {
|
||||
const path = workspaceUri.path;
|
||||
const uri = workspaceUri.with({ path: `${path !== '/' ? path : ''}/pom.xml` });
|
||||
return this.fileService.existsFile(uri).then(exists => {
|
||||
return this.fileService.exists(uri).then(exists => {
|
||||
if (!exists) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2318,7 +2318,7 @@ class TaskService extends Disposable implements ITaskService {
|
||||
let openTaskFile = (workspaceFolder: IWorkspaceFolder): void => {
|
||||
let resource = workspaceFolder.toResource('.vscode/tasks.json');
|
||||
let configFileCreated = false;
|
||||
this.fileService.resolveFile(resource).then((stat) => stat, () => undefined).then((stat) => {
|
||||
this.fileService.resolve(resource).then((stat) => stat, () => undefined).then((stat) => {
|
||||
if (stat) {
|
||||
return stat.resource;
|
||||
}
|
||||
@@ -2375,7 +2375,7 @@ class TaskService extends Disposable implements ITaskService {
|
||||
}
|
||||
|
||||
let stats = this.contextService.getWorkspace().folders.map<Promise<IFileStat | undefined>>((folder) => {
|
||||
return this.fileService.resolveFile(folder.toResource('.vscode/tasks.json')).then(stat => stat, () => undefined);
|
||||
return this.fileService.resolve(folder.toResource('.vscode/tasks.json')).then(stat => stat, () => undefined);
|
||||
});
|
||||
|
||||
let createLabel = nls.localize('TaskService.createJsonFile', 'Create tasks.json file from template');
|
||||
|
||||
@@ -230,7 +230,7 @@ export class ProcessRunnerDetector {
|
||||
}
|
||||
|
||||
private tryDetectGulp(workspaceFolder: IWorkspaceFolder, list: boolean): Promise<DetectorResult> {
|
||||
return Promise.resolve(this.fileService.resolveFile(workspaceFolder.toResource('gulpfile.js'))).then((stat) => { // TODO@Dirk (https://github.com/Microsoft/vscode/issues/29454)
|
||||
return Promise.resolve(this.fileService.resolve(workspaceFolder.toResource('gulpfile.js'))).then((stat) => { // TODO@Dirk (https://github.com/Microsoft/vscode/issues/29454)
|
||||
let config = ProcessRunnerDetector.detectorConfig('gulp');
|
||||
let process = new LineProcess('gulp', [config.arg, '--no-color'], true, { cwd: this._cwd });
|
||||
return this.runDetection(process, 'gulp', true, config.matcher, ProcessRunnerDetector.DefaultProblemMatchers, list);
|
||||
@@ -240,7 +240,7 @@ export class ProcessRunnerDetector {
|
||||
}
|
||||
|
||||
private tryDetectGrunt(workspaceFolder: IWorkspaceFolder, list: boolean): Promise<DetectorResult> {
|
||||
return Promise.resolve(this.fileService.resolveFile(workspaceFolder.toResource('Gruntfile.js'))).then((stat) => { // TODO@Dirk (https://github.com/Microsoft/vscode/issues/29454)
|
||||
return Promise.resolve(this.fileService.resolve(workspaceFolder.toResource('Gruntfile.js'))).then((stat) => { // TODO@Dirk (https://github.com/Microsoft/vscode/issues/29454)
|
||||
let config = ProcessRunnerDetector.detectorConfig('grunt');
|
||||
let process = new LineProcess('grunt', [config.arg, '--no-color'], true, { cwd: this._cwd });
|
||||
return this.runDetection(process, 'grunt', true, config.matcher, ProcessRunnerDetector.DefaultProblemMatchers, list);
|
||||
@@ -255,10 +255,10 @@ export class ProcessRunnerDetector {
|
||||
let process = new LineProcess('jake', [config.arg], true, { cwd: this._cwd });
|
||||
return this.runDetection(process, 'jake', true, config.matcher, ProcessRunnerDetector.DefaultProblemMatchers, list);
|
||||
};
|
||||
return Promise.resolve(this.fileService.resolveFile(workspaceFolder.toResource('Jakefile'))).then((stat) => { // TODO@Dirk (https://github.com/Microsoft/vscode/issues/29454)
|
||||
return Promise.resolve(this.fileService.resolve(workspaceFolder.toResource('Jakefile'))).then((stat) => { // TODO@Dirk (https://github.com/Microsoft/vscode/issues/29454)
|
||||
return run();
|
||||
}, (err: any) => {
|
||||
return this.fileService.resolveFile(workspaceFolder.toResource('Jakefile.js')).then((stat) => { // TODO@Dirk (https://github.com/Microsoft/vscode/issues/29454)
|
||||
return this.fileService.resolve(workspaceFolder.toResource('Jakefile.js')).then((stat) => { // TODO@Dirk (https://github.com/Microsoft/vscode/issues/29454)
|
||||
return run();
|
||||
}, (err: any) => {
|
||||
return null;
|
||||
|
||||
@@ -305,7 +305,7 @@ export class TerminalLinkHandler {
|
||||
uri = URI.file(linkUrl);
|
||||
}
|
||||
|
||||
return this._fileService.resolveFile(uri).then(stat => {
|
||||
return this._fileService.resolve(uri).then(stat => {
|
||||
if (stat.isDirectory) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -416,7 +416,7 @@ export abstract class TerminalService implements ITerminalService {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
const current = potentialPaths.shift();
|
||||
return this._fileService.existsFile(URI.file(current!)).then(exists => {
|
||||
return this._fileService.exists(URI.file(current!)).then(exists => {
|
||||
if (!exists) {
|
||||
return this._validateShellPaths(label, potentialPaths);
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ export class TerminalService extends BrowserTerminalService implements ITerminal
|
||||
const interval = setInterval(() => {
|
||||
if (!running) {
|
||||
running = true;
|
||||
this._fileService.existsFile(path).then(exists => {
|
||||
this._fileService.exists(path).then(exists => {
|
||||
running = false;
|
||||
|
||||
if (!exists) {
|
||||
|
||||
@@ -69,7 +69,7 @@ export class WelcomePageContribution implements IWorkbenchContribution {
|
||||
if (openWithReadme) {
|
||||
return Promise.all(contextService.getWorkspace().folders.map(folder => {
|
||||
const folderUri = folder.uri;
|
||||
return fileService.resolveFile(folderUri)
|
||||
return fileService.resolve(folderUri)
|
||||
.then(folder => {
|
||||
const files = folder.children ? folder.children.map(child => child.name) : [];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user