Merge from vscode a416c77e56ef0314ae00633faa04878151610de8 (#8600)

* Merge from vscode a416c77e56ef0314ae00633faa04878151610de8

* distro

* fix tests

* fix tests
This commit is contained in:
Anthony Dresser
2019-12-07 17:19:16 -08:00
committed by GitHub
parent a7ff238653
commit d614116b63
155 changed files with 1982 additions and 1599 deletions

View File

@@ -19,6 +19,11 @@
"vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:search-result ./tsconfig.json"
},
"contributes": {
"configurationDefaults": {
"[search-result]": {
"editor.lineNumbers": "off"
}
},
"commands": [
{
"command": "searchResult.rerunSearch",
@@ -28,6 +33,15 @@
"light": "./src/media/refresh-light.svg",
"dark": "./src/media/refresh-dark.svg"
}
},
{
"command": "searchResult.rerunSearchWithContext",
"title": "%searchResult.rerunSearchWithContext.title%",
"category": "Search Result",
"icon": {
"light": "./src/media/refresh-light.svg",
"dark": "./src/media/refresh-dark.svg"
}
}
],
"menus": {
@@ -35,6 +49,7 @@
{
"command": "searchResult.rerunSearch",
"when": "editorLangId == search-result",
"alt": "searchResult.rerunSearchWithContext",
"group": "navigation"
}
]

View File

@@ -1,5 +1,6 @@
{
"displayName": "Search Result",
"description": "Provides syntax highlighting and language features for tabbed search results.",
"searchResult.rerunSearch.title": "Search Again"
"searchResult.rerunSearch.title": "Search Again",
"searchResult.rerunSearchWithContext.title": "Search Again (With Context)"
}

View File

@@ -7,81 +7,93 @@ import * as vscode from 'vscode';
import * as pathUtils from 'path';
const FILE_LINE_REGEX = /^(\S.*):$/;
const RESULT_LINE_REGEX = /^(\s+)(\d+):(\s+)(.*)$/;
const RESULT_LINE_REGEX = /^(\s+)(\d+)(:| )(\s+)(.*)$/;
const SEARCH_RESULT_SELECTOR = { language: 'search-result' };
const DIRECTIVES = ['# Query:', '# Flags:', '# Including:', '# Excluding:', '# ContextLines:'];
const FLAGS = ['RegExp', 'CaseSensitive', 'IgnoreExcludeSettings', 'WordMatch'];
let cachedLastParse: { version: number, parse: ParsedSearchResults } | undefined;
export function activate() {
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand('searchResult.rerunSearch', () => vscode.commands.executeCommand('search.action.rerunEditorSearch')),
vscode.commands.registerCommand('searchResult.rerunSearchWithContext', () => vscode.commands.executeCommand('search.action.rerunEditorSearchWithContext')),
vscode.commands.registerCommand('searchResult.rerunSearch', () => vscode.commands.executeCommand('search.action.rerunEditorSearch'));
vscode.languages.registerDocumentSymbolProvider(SEARCH_RESULT_SELECTOR, {
provideDocumentSymbols(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.DocumentSymbol[] {
const results = parseSearchResults(document, token)
.filter(isFileLine)
.map(line => new vscode.DocumentSymbol(
line.path,
'',
vscode.SymbolKind.File,
line.allLocations.map(({ originSelectionRange }) => originSelectionRange!).reduce((p, c) => p.union(c), line.location.originSelectionRange!),
line.location.originSelectionRange!,
));
vscode.languages.registerDocumentSymbolProvider(SEARCH_RESULT_SELECTOR, {
provideDocumentSymbols(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.DocumentSymbol[] {
const results = parseSearchResults(document, token)
.filter(isFileLine)
.map(line => new vscode.DocumentSymbol(
line.path,
'',
vscode.SymbolKind.File,
line.allLocations.map(({ originSelectionRange }) => originSelectionRange!).reduce((p, c) => p.union(c), line.location.originSelectionRange!),
line.location.originSelectionRange!,
));
return results;
}
});
vscode.languages.registerCompletionItemProvider(SEARCH_RESULT_SELECTOR, {
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
const line = document.lineAt(position.line);
if (position.line > 3) { return []; }
if (position.character === 0 || (position.character === 1 && line.text === '#')) {
const header = Array.from({ length: 4 }).map((_, i) => document.lineAt(i).text);
return ['# Query:', '# Flags:', '# Including:', '# Excluding:']
.filter(suggestion => header.every(line => line.indexOf(suggestion) === -1))
.map(flag => ({ label: flag, insertText: (flag.slice(position.character)) + ' ' }));
return results;
}
}),
if (line.text.indexOf('# Flags:') === -1) { return []; }
vscode.languages.registerCompletionItemProvider(SEARCH_RESULT_SELECTOR, {
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
return ['RegExp', 'CaseSensitive', 'IgnoreExcludeSettings', 'WordMatch']
.filter(flag => line.text.indexOf(flag) === -1)
.map(flag => ({ label: flag, insertText: flag + ' ' }));
}
}, '#');
const line = document.lineAt(position.line);
if (position.line > 3) { return []; }
if (position.character === 0 || (position.character === 1 && line.text === '#')) {
const header = Array.from({ length: DIRECTIVES.length }).map((_, i) => document.lineAt(i).text);
vscode.languages.registerDefinitionProvider(SEARCH_RESULT_SELECTOR, {
provideDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.DefinitionLink[] {
const lineResult = parseSearchResults(document, token)[position.line];
if (!lineResult) { return []; }
if (lineResult.type === 'file') {
// TODO: The multi-match peek UX isnt very smooth.
// return lineResult.allLocations.length > 1 ? lineResult.allLocations : [lineResult.location];
return [];
return DIRECTIVES
.filter(suggestion => header.every(line => line.indexOf(suggestion) === -1))
.map(flag => ({ label: flag, insertText: (flag.slice(position.character)) + ' ' }));
}
if (line.text.indexOf('# Flags:') === -1) { return []; }
return FLAGS
.filter(flag => line.text.indexOf(flag) === -1)
.map(flag => ({ label: flag, insertText: flag + ' ' }));
}
}, '#'),
return [lineResult.location];
}
});
vscode.languages.registerDefinitionProvider(SEARCH_RESULT_SELECTOR, {
provideDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.DefinitionLink[] {
const lineResult = parseSearchResults(document, token)[position.line];
if (!lineResult) { return []; }
if (lineResult.type === 'file') {
// TODO: The multi-match peek UX isnt very smooth.
// return lineResult.allLocations.length > 1 ? lineResult.allLocations : [lineResult.location];
return [];
}
vscode.languages.registerDocumentLinkProvider(SEARCH_RESULT_SELECTOR, {
async provideDocumentLinks(document: vscode.TextDocument, token: vscode.CancellationToken): Promise<vscode.DocumentLink[]> {
return parseSearchResults(document, token)
.filter(({ type }) => type === 'file')
.map(({ location }) => ({ range: location.originSelectionRange!, target: location.targetUri }));
}
});
const translateRangeSidewaysBy = (r: vscode.Range, n: number) =>
r.with({ start: new vscode.Position(r.start.line, Math.max(0, n - r.start.character)), end: new vscode.Position(r.end.line, Math.max(0, n - r.end.character)) });
vscode.window.onDidChangeActiveTextEditor(e => {
if (e?.document.languageId === 'search-result') {
// Clear the parse whenever we open a new editor.
// Conservative because things like the URI might remain constant even if the contents change, and re-parsing even large files is relatively fast.
cachedLastParse = undefined;
}
});
return [{
...lineResult.location,
targetSelectionRange: translateRangeSidewaysBy(lineResult.location.targetSelectionRange!, position.character - 1)
}];
}
}),
vscode.languages.registerDocumentLinkProvider(SEARCH_RESULT_SELECTOR, {
async provideDocumentLinks(document: vscode.TextDocument, token: vscode.CancellationToken): Promise<vscode.DocumentLink[]> {
return parseSearchResults(document, token)
.filter(({ type }) => type === 'file')
.map(({ location }) => ({ range: location.originSelectionRange!, target: location.targetUri }));
}
}),
vscode.window.onDidChangeActiveTextEditor(e => {
if (e?.document.languageId === 'search-result') {
// Clear the parse whenever we open a new editor.
// Conservative because things like the URI might remain constant even if the contents change, and re-parsing even large files is relatively fast.
cachedLastParse = undefined;
}
}),
{ dispose() { cachedLastParse = undefined; } }
);
}
@@ -160,13 +172,14 @@ function parseSearchResults(document: vscode.TextDocument, token: vscode.Cancell
const resultLine = RESULT_LINE_REGEX.exec(line);
if (resultLine) {
const [, indentation, _lineNumber, resultIndentation] = resultLine;
const [, indentation, _lineNumber, seperator, resultIndentation] = resultLine;
const lineNumber = +_lineNumber - 1;
const resultStart = (indentation + _lineNumber + ':' + resultIndentation).length;
const resultStart = (indentation + _lineNumber + seperator + resultIndentation).length;
const metadataOffset = (indentation + _lineNumber + seperator).length;
const location: vscode.LocationLink = {
targetRange: new vscode.Range(Math.max(lineNumber - 3, 0), 0, lineNumber + 3, line.length),
targetSelectionRange: new vscode.Range(lineNumber, 0, lineNumber, line.length),
targetSelectionRange: new vscode.Range(lineNumber, metadataOffset, lineNumber, metadataOffset),
targetUri: currentTarget,
originSelectionRange: new vscode.Range(i, resultStart, i, line.length),
};

View File

@@ -3,7 +3,7 @@
"scopeName": "text.searchResult",
"patterns": [
{
"match": "^# (Query|Flags|Including|Excluding): .*$",
"match": "^# (Query|Flags|Including|Excluding|ContextLines): .*$",
"name": "comment"
},
{