mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Vscode merge (#4582)
* Merge from vscode 37cb23d3dd4f9433d56d4ba5ea3203580719a0bd * fix issues with merges * bump node version in azpipe * replace license headers * remove duplicate launch task * fix build errors * fix build errors * fix tslint issues * working through package and linux build issues * more work * wip * fix packaged builds * working through linux build errors * wip * wip * wip * fix mac and linux file limits * iterate linux pipeline * disable editor typing * revert series to parallel * remove optimize vscode from linux * fix linting issues * revert testing change * add work round for new node * readd packaging for extensions * fix issue with angular not resolving decorator dependencies
This commit is contained in:
@@ -11,12 +11,19 @@ import { LinkedList } from 'vs/base/common/linkedList';
|
||||
|
||||
export class BracketSelectionRangeProvider implements SelectionRangeProvider {
|
||||
|
||||
provideSelectionRanges(model: ITextModel, position: Position): Promise<SelectionRange[]> {
|
||||
const bucket: SelectionRange[] = [];
|
||||
const ranges = new Map<string, LinkedList<Range>>();
|
||||
return new Promise(resolve => BracketSelectionRangeProvider._bracketsRightYield(resolve, 0, model, position, ranges))
|
||||
.then(() => new Promise(resolve => BracketSelectionRangeProvider._bracketsLeftYield(resolve, 0, model, position, ranges, bucket)))
|
||||
.then(() => bucket);
|
||||
async provideSelectionRanges(model: ITextModel, positions: Position[]): Promise<SelectionRange[][]> {
|
||||
const result: SelectionRange[][] = [];
|
||||
|
||||
for (const position of positions) {
|
||||
const bucket: SelectionRange[] = [];
|
||||
result.push(bucket);
|
||||
|
||||
const ranges = new Map<string, LinkedList<Range>>();
|
||||
await new Promise(resolve => BracketSelectionRangeProvider._bracketsRightYield(resolve, 0, model, position, ranges));
|
||||
await new Promise(resolve => BracketSelectionRangeProvider._bracketsLeftYield(resolve, 0, model, position, ranges, bucket));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static readonly _maxDuration = 30;
|
||||
|
||||
@@ -10,6 +10,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { EditorAction, IActionOptions, registerEditorAction, registerEditorContribution, ServicesAccessor, registerDefaultLanguageCommand } from 'vs/editor/browser/editorExtensions';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
@@ -21,6 +22,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { WordSelectionRangeProvider } from 'vs/editor/contrib/smartSelect/wordSelections';
|
||||
import { BracketSelectionRangeProvider } from 'vs/editor/contrib/smartSelect/bracketSelections';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { onUnexpectedExternalError } from 'vs/base/common/errors';
|
||||
|
||||
class SelectionRanges {
|
||||
|
||||
@@ -53,7 +55,7 @@ class SmartSelectController implements IEditorContribution {
|
||||
|
||||
private readonly _editor: ICodeEditor;
|
||||
|
||||
private _state?: SelectionRanges;
|
||||
private _state?: SelectionRanges[];
|
||||
private _selectionListener?: IDisposable;
|
||||
private _ignoreSelection: boolean = false;
|
||||
|
||||
@@ -74,7 +76,7 @@ class SmartSelectController implements IEditorContribution {
|
||||
return;
|
||||
}
|
||||
|
||||
const selection = this._editor.getSelection();
|
||||
const selections = this._editor.getSelections();
|
||||
const model = this._editor.getModel();
|
||||
|
||||
if (!modes.SelectionRangeRegistry.has(model)) {
|
||||
@@ -85,25 +87,27 @@ class SmartSelectController implements IEditorContribution {
|
||||
let promise: Promise<void> = Promise.resolve(undefined);
|
||||
|
||||
if (!this._state) {
|
||||
promise = provideSelectionRanges(model, selection.getPosition(), CancellationToken.None).then(ranges => {
|
||||
if (!arrays.isNonEmptyArray(ranges)) {
|
||||
promise = provideSelectionRanges(model, selections.map(s => s.getPosition()), CancellationToken.None).then(ranges => {
|
||||
if (!arrays.isNonEmptyArray(ranges) || ranges.length !== selections.length) {
|
||||
// invalid result
|
||||
return;
|
||||
}
|
||||
if (!this._editor.hasModel() || !this._editor.getSelection().equalsSelection(selection)) {
|
||||
if (!this._editor.hasModel() || !arrays.equals(this._editor.getSelections(), selections, (a, b) => a.equalsSelection(b))) {
|
||||
// invalid editor state
|
||||
return;
|
||||
}
|
||||
|
||||
ranges = ranges.filter(range => {
|
||||
// filter ranges inside the selection
|
||||
return range.containsPosition(selection.getStartPosition()) && range.containsPosition(selection.getEndPosition());
|
||||
});
|
||||
for (let i = 0; i < ranges.length; i++) {
|
||||
ranges[i] = ranges[i].filter(range => {
|
||||
// filter ranges inside the selection
|
||||
return range.containsPosition(selections[i].getStartPosition()) && range.containsPosition(selections[i].getEndPosition());
|
||||
});
|
||||
// prepend current selection
|
||||
ranges[i].unshift(selections[i]);
|
||||
}
|
||||
|
||||
// prepend current selection
|
||||
ranges.unshift(selection);
|
||||
|
||||
this._state = new SelectionRanges(0, ranges);
|
||||
this._state = ranges.map(ranges => new SelectionRanges(0, ranges));
|
||||
|
||||
// listen to caret move and forget about state
|
||||
dispose(this._selectionListener);
|
||||
@@ -121,11 +125,11 @@ class SmartSelectController implements IEditorContribution {
|
||||
// no state
|
||||
return;
|
||||
}
|
||||
this._state = this._state.mov(forward);
|
||||
const selection = this._state.ranges[this._state.index];
|
||||
this._state = this._state.map(state => state.mov(forward));
|
||||
const selections = this._state.map(state => Selection.fromPositions(state.ranges[state.index].getStartPosition(), state.ranges[state.index].getEndPosition()));
|
||||
this._ignoreSelection = true;
|
||||
try {
|
||||
this._editor.setSelection(selection);
|
||||
this._editor.setSelections(selections);
|
||||
} finally {
|
||||
this._ignoreSelection = false;
|
||||
}
|
||||
@@ -207,91 +211,95 @@ registerEditorAction(ShrinkSelectionAction);
|
||||
// word selection
|
||||
modes.SelectionRangeRegistry.register('*', new WordSelectionRangeProvider());
|
||||
|
||||
export function provideSelectionRanges(model: ITextModel, position: Position, token: CancellationToken): Promise<Range[] | undefined | null> {
|
||||
export function provideSelectionRanges(model: ITextModel, positions: Position[], token: CancellationToken): Promise<Range[][]> {
|
||||
|
||||
const provider = modes.SelectionRangeRegistry.orderedGroups(model);
|
||||
const providers = modes.SelectionRangeRegistry.all(model);
|
||||
|
||||
if (provider.length === 1) {
|
||||
if (providers.length === 1) {
|
||||
// add word selection and bracket selection when no provider exists
|
||||
provider.unshift([new BracketSelectionRangeProvider()]);
|
||||
}
|
||||
|
||||
interface RankedRange {
|
||||
rank: number;
|
||||
range: Range;
|
||||
providers.unshift(new BracketSelectionRangeProvider());
|
||||
}
|
||||
|
||||
let work: Promise<any>[] = [];
|
||||
let ranges: RankedRange[] = [];
|
||||
let rank = 0;
|
||||
let allRawRanges: Range[][] = [];
|
||||
|
||||
for (const group of provider) {
|
||||
rank += 1;
|
||||
for (const prov of group) {
|
||||
work.push(Promise.resolve(prov.provideSelectionRanges(model, position, token)).then(selectionRanges => {
|
||||
if (arrays.isNonEmptyArray(selectionRanges)) {
|
||||
for (const sel of selectionRanges) {
|
||||
if (Range.isIRange(sel.range) && Range.containsPosition(sel.range, position)) {
|
||||
ranges.push({ range: Range.lift(sel.range), rank });
|
||||
for (const provider of providers) {
|
||||
|
||||
work.push(Promise.resolve(provider.provideSelectionRanges(model, positions, token)).then(allProviderRanges => {
|
||||
if (arrays.isNonEmptyArray(allProviderRanges) && allProviderRanges.length === positions.length) {
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
if (!allRawRanges[i]) {
|
||||
allRawRanges[i] = [];
|
||||
}
|
||||
for (const oneProviderRanges of allProviderRanges[i]) {
|
||||
if (Range.isIRange(oneProviderRanges.range) && Range.containsPosition(oneProviderRanges.range, positions[i])) {
|
||||
allRawRanges[i].push(Range.lift(oneProviderRanges.range));
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}, onUnexpectedExternalError));
|
||||
}
|
||||
|
||||
return Promise.all(work).then(() => {
|
||||
|
||||
if (ranges.length === 0) {
|
||||
return [];
|
||||
}
|
||||
return allRawRanges.map(oneRawRanges => {
|
||||
|
||||
ranges.sort((a, b) => {
|
||||
if (Position.isBefore(a.range.getStartPosition(), b.range.getStartPosition())) {
|
||||
return 1;
|
||||
} else if (Position.isBefore(b.range.getStartPosition(), a.range.getStartPosition())) {
|
||||
return -1;
|
||||
} else if (Position.isBefore(a.range.getEndPosition(), b.range.getEndPosition())) {
|
||||
return -1;
|
||||
} else if (Position.isBefore(b.range.getEndPosition(), a.range.getEndPosition())) {
|
||||
return 1;
|
||||
} else {
|
||||
return b.rank - a.rank;
|
||||
if (oneRawRanges.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// sort all by start/end position
|
||||
oneRawRanges.sort((a, b) => {
|
||||
if (Position.isBefore(a.getStartPosition(), b.getStartPosition())) {
|
||||
return 1;
|
||||
} else if (Position.isBefore(b.getStartPosition(), a.getStartPosition())) {
|
||||
return -1;
|
||||
} else if (Position.isBefore(a.getEndPosition(), b.getEndPosition())) {
|
||||
return -1;
|
||||
} else if (Position.isBefore(b.getEndPosition(), a.getEndPosition())) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
// remove ranges that don't contain the former range or that are equal to the
|
||||
// former range
|
||||
let oneRanges: Range[] = [];
|
||||
let last: Range | undefined;
|
||||
for (const range of oneRawRanges) {
|
||||
if (!last || (Range.containsRange(range, last) && !Range.equalsRange(range, last))) {
|
||||
oneRanges.push(range);
|
||||
last = range;
|
||||
}
|
||||
}
|
||||
|
||||
// add ranges that expand trivia at line starts and ends whenever a range
|
||||
// wraps onto the a new line
|
||||
let oneRangesWithTrivia: Range[] = [oneRanges[0]];
|
||||
for (let i = 1; i < oneRanges.length; i++) {
|
||||
const prev = oneRanges[i - 1];
|
||||
const cur = oneRanges[i];
|
||||
if (cur.startLineNumber !== prev.startLineNumber || cur.endLineNumber !== prev.endLineNumber) {
|
||||
// add line/block range without leading/failing whitespace
|
||||
const rangeNoWhitespace = new Range(prev.startLineNumber, model.getLineFirstNonWhitespaceColumn(prev.startLineNumber), prev.endLineNumber, model.getLineLastNonWhitespaceColumn(prev.endLineNumber));
|
||||
if (rangeNoWhitespace.containsRange(prev) && !rangeNoWhitespace.equalsRange(prev)) {
|
||||
oneRangesWithTrivia.push(rangeNoWhitespace);
|
||||
}
|
||||
// add line/block range
|
||||
const rangeFull = new Range(prev.startLineNumber, 1, prev.endLineNumber, model.getLineMaxColumn(prev.endLineNumber));
|
||||
if (rangeFull.containsRange(prev) && !rangeFull.equalsRange(rangeNoWhitespace)) {
|
||||
oneRangesWithTrivia.push(rangeFull);
|
||||
}
|
||||
}
|
||||
oneRangesWithTrivia.push(cur);
|
||||
}
|
||||
return oneRangesWithTrivia;
|
||||
});
|
||||
|
||||
let result: Range[] = [];
|
||||
let last: Range | undefined;
|
||||
for (const { range } of ranges) {
|
||||
if (!last || (Range.containsRange(range, last) && !Range.equalsRange(range, last))) {
|
||||
result.push(range);
|
||||
last = range;
|
||||
}
|
||||
}
|
||||
|
||||
let result2: Range[] = [result[0]];
|
||||
for (let i = 1; i < result.length; i++) {
|
||||
const prev = result[i - 1];
|
||||
const cur = result[i];
|
||||
if (cur.startLineNumber !== prev.startLineNumber || cur.endLineNumber !== prev.endLineNumber) {
|
||||
// add line/block range without leading/failing whitespace
|
||||
const rangeNoWhitespace = new Range(prev.startLineNumber, model.getLineFirstNonWhitespaceColumn(prev.startLineNumber), prev.endLineNumber, model.getLineLastNonWhitespaceColumn(prev.endLineNumber));
|
||||
if (rangeNoWhitespace.containsRange(prev) && !rangeNoWhitespace.equalsRange(prev)) {
|
||||
result2.push(rangeNoWhitespace);
|
||||
}
|
||||
// add line/block range
|
||||
const rangeFull = new Range(prev.startLineNumber, 1, prev.endLineNumber, model.getLineMaxColumn(prev.endLineNumber));
|
||||
if (rangeFull.containsRange(prev) && !rangeFull.equalsRange(rangeNoWhitespace)) {
|
||||
result2.push(rangeFull);
|
||||
}
|
||||
}
|
||||
result2.push(cur);
|
||||
}
|
||||
|
||||
return result2;
|
||||
});
|
||||
}
|
||||
|
||||
registerDefaultLanguageCommand('_executeSelectionRangeProvider', function (model, position) {
|
||||
return provideSelectionRanges(model, position, CancellationToken.None);
|
||||
registerDefaultLanguageCommand('_executeSelectionRangeProvider', function (model, _position, args) {
|
||||
return provideSelectionRanges(model, args.positions, CancellationToken.None);
|
||||
});
|
||||
|
||||
@@ -79,7 +79,7 @@ suite('SmartSelect', () => {
|
||||
async function assertGetRangesToPosition(text: string[], lineNumber: number, column: number, ranges: Range[]): Promise<void> {
|
||||
let uri = URI.file('test.js');
|
||||
let model = modelService.createModel(text.join('\n'), new StaticLanguageSelector(mode.getLanguageIdentifier()), uri);
|
||||
let actual = await provideSelectionRanges(model, new Position(lineNumber, column), CancellationToken.None);
|
||||
let [actual] = await provideSelectionRanges(model, [new Position(lineNumber, column)], CancellationToken.None);
|
||||
let actualStr = actual!.map(r => new Range(r.startLineNumber, r.startColumn, r.endLineNumber, r.endColumn).toString());
|
||||
let desiredStr = ranges.reverse().map(r => String(r));
|
||||
|
||||
@@ -203,7 +203,9 @@ suite('SmartSelect', () => {
|
||||
|
||||
let model = modelService.createModel(value, new StaticLanguageSelector(mode.getLanguageIdentifier()), URI.parse('fake:lang'));
|
||||
let pos = model.getPositionAt(value.indexOf('|'));
|
||||
let ranges = await provider.provideSelectionRanges(model, pos, CancellationToken.None);
|
||||
let all = await provider.provideSelectionRanges(model, [pos], CancellationToken.None);
|
||||
let ranges = all![0];
|
||||
|
||||
modelService.destroyModel(model.uri);
|
||||
|
||||
assert.equal(expected.length, ranges!.length);
|
||||
|
||||
@@ -12,12 +12,16 @@ import { isUpperAsciiLetter, isLowerAsciiLetter } from 'vs/base/common/strings';
|
||||
|
||||
export class WordSelectionRangeProvider implements SelectionRangeProvider {
|
||||
|
||||
provideSelectionRanges(model: ITextModel, position: Position): SelectionRange[] {
|
||||
let result: SelectionRange[] = [];
|
||||
this._addInWordRanges(result, model, position);
|
||||
this._addWordRanges(result, model, position);
|
||||
this._addWhitespaceLine(result, model, position);
|
||||
result.push({ range: model.getFullModelRange(), kind: 'statement.all' });
|
||||
provideSelectionRanges(model: ITextModel, positions: Position[]): SelectionRange[][] {
|
||||
const result: SelectionRange[][] = [];
|
||||
for (const position of positions) {
|
||||
const bucket: SelectionRange[] = [];
|
||||
result.push(bucket);
|
||||
this._addInWordRanges(bucket, model, position);
|
||||
this._addWordRanges(bucket, model, position);
|
||||
this._addWhitespaceLine(bucket, model, position);
|
||||
bucket.push({ range: model.getFullModelRange(), kind: 'statement.all' });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user