diff --git a/.vscode/launch.json b/.vscode/launch.json index 322d91bce37..19582ae095a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -74,6 +74,21 @@ "request": "launch", "program": "${workspaceRoot}/src/vs/languages/css/common/buildscripts/generate_browserjs.js", "stopOnEntry": false + }, + { + "name": "Debug monaco", + "type": "node", + "request": "launch", + "program": "${workspaceRoot}/build/lib/monaco.js", + "stopOnEntry": false, + "args": [ + ], + "cwd": "${workspaceRoot}/build/lib" + // , + + // "port": 5870, + // "sourceMaps": true, + // "outDir": "${workspaceRoot}/out" } ] } \ No newline at end of file diff --git a/build/gulpfile.common.js b/build/gulpfile.common.js index 23b1480a418..926167f0ac8 100644 --- a/build/gulpfile.common.js +++ b/build/gulpfile.common.js @@ -33,17 +33,11 @@ exports.loaderConfig = function (emptyPaths) { var result = { paths: { 'vs': 'out-build/vs', - 'vs/extensions': 'extensions', 'vscode': 'empty:' }, - 'vs/text': { - paths: { - 'vs/extensions': 'extensions' - } - } + nodeModules: emptyPaths||[] }; - (emptyPaths || []).forEach(function(m) { result.paths[m] = 'empty:'; }); return result; }; @@ -55,7 +49,6 @@ function loader(bundledFileHeader) { 'out-build/vs/loader.js', 'out-build/vs/css.js', 'out-build/vs/nls.js', - 'out-build/vs/text.js' ], { base: 'out-build' }) .pipe(es.through(function(data) { if (isFirst) { diff --git a/build/gulpfile.editor.js b/build/gulpfile.editor.js index 00c87bed8fd..868e7dc0cd9 100644 --- a/build/gulpfile.editor.js +++ b/build/gulpfile.editor.js @@ -34,8 +34,7 @@ var editorResources = [ var editorOtherSources = [ 'out-build/vs/css.js', - 'out-build/vs/nls.js', - 'out-build/vs/text.js' + 'out-build/vs/nls.js' ]; var BUNDLED_FILE_HEADER = [ diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index eb6a10ae45f..667b6ae1293 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -48,7 +48,6 @@ var indentationFilter = [ '!**/vs/base/common/marked/raw.marked.js', '!**/vs/base/common/winjs.base.raw.js', '!**/vs/base/node/terminateProcess.sh', - '!**/vs/text.js', '!**/vs/nls.js', '!**/vs/css.js', '!**/vs/loader.js', diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 2be526d67a4..7ccea5317a6 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -32,7 +32,7 @@ var baseModules = [ 'applicationinsights', 'assert', 'child_process', 'chokidar', 'crypto', 'emmet', 'events', 'fs', 'getmac', 'glob', 'graceful-fs', 'http', 'http-proxy-agent', 'https', 'https-proxy-agent', 'iconv-lite', 'electron', 'net', - 'os', 'path', 'readline', 'sax', 'semver', 'stream', 'string_decoder', 'url', + 'os', 'path', 'pty.js', 'readline', 'sax', 'semver', 'stream', 'string_decoder', 'url', 'term.js', 'vscode-textmate', 'winreg', 'yauzl', 'native-keymap', 'zlib', 'minimist' ]; @@ -68,6 +68,7 @@ var vscodeResources = [ 'out-build/vs/workbench/parts/html/browser/webview.html', 'out-build/vs/workbench/parts/markdown/**/*.md', 'out-build/vs/workbench/parts/tasks/**/*.json', + 'out-build/vs/workbench/parts/terminal/electron-browser/terminalProcess.js', 'out-build/vs/workbench/services/files/**/*.exe', 'out-build/vs/workbench/services/files/**/*.md', '!**/test/**' diff --git a/build/lib/monaco-editor.d.ts b/build/lib/monaco-editor.d.ts new file mode 100644 index 00000000000..ed68d9a56a6 --- /dev/null +++ b/build/lib/monaco-editor.d.ts @@ -0,0 +1,3387 @@ + +declare module monaco.editor { + + export function create(domElement: HTMLElement, options: IEditorConstructionOptions, services?: any): ICodeEditor; + export function createDiffEditor(domElement: HTMLElement, options: IDiffEditorConstructionOptions, services?: any): IDiffEditor; + export function createModel(value: string, mode: string | ILanguage | IMode, associatedResource?: any | string): IModel; + export function getOrCreateMode(modeId: string): TPromise; + export function createCustomMode(description: ILanguage): TPromise; + export function colorize(text: string, modeId: string, options: IColorizerOptions): TPromise; + export function colorizeElement(domNode: HTMLElement, options: IColorizerElementOptions): TPromise; + // export function colorizeLine(line: string, tokens: ViewLineToken[], tabSize?: number): string; + export function colorizeModelLine(model: IModel, lineNumber: number, tabSize?: number): string; + export function registerWorkerParticipant(modeId: string, moduleName: string, ctorName: string): void; + export function configureMode(modeId: string, options: any): void; + + export interface IColorizerOptions { + tabSize?: number; + } + + export interface IColorizerElementOptions extends IColorizerOptions { + theme?: string; + mimeType?: string; + } + + export interface IEditorConstructionOptions extends ICodeEditorWidgetCreationOptions { + value?: string; + /** + * A mode name (such as text/javascript, etc.) or an IMonarchLanguage + */ + mode?: any; + enableTelemetry?: boolean; + } + + export interface IDiffEditorConstructionOptions extends IDiffEditorOptions { + } +} + +declare module monaco { + + interface Thenable { + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: (value: R) => TResult | Thenable, onrejected?: (reason: any) => TResult | Thenable): Thenable; + then(onfulfilled?: (value: R) => TResult | Thenable, onrejected?: (reason: any) => void): Thenable; + } + + export interface IDisposable { + dispose(): void; + } + + + + // --- Generic promise + export interface TValueCallback { + (value: T): void; + } + + + export interface ProgressCallback { + (progress: any): any; + } + + + export class TPromise { + + constructor(init: (complete: TValueCallback, error: (err: any) => void, progress: ProgressCallback) => void, oncancel?: any); + + public then(success?: (value: V) => TPromise, error?: (err: any) => TPromise, progress?: ProgressCallback): TPromise; + public then(success?: (value: V) => TPromise, error?: (err: any) => TPromise | U, progress?: ProgressCallback): TPromise; + public then(success?: (value: V) => TPromise, error?: (err: any) => U, progress?: ProgressCallback): TPromise; + public then(success?: (value: V) => TPromise, error?: (err: any) => void, progress?: ProgressCallback): TPromise; + public then(success?: (value: V) => TPromise | U, error?: (err: any) => TPromise, progress?: ProgressCallback): TPromise; + public then(success?: (value: V) => TPromise | U, error?: (err: any) => TPromise | U, progress?: ProgressCallback): TPromise; + public then(success?: (value: V) => TPromise | U, error?: (err: any) => U, progress?: ProgressCallback): TPromise; + public then(success?: (value: V) => TPromise | U, error?: (err: any) => void, progress?: ProgressCallback): TPromise; + public then(success?: (value: V) => U, error?: (err: any) => TPromise, progress?: ProgressCallback): TPromise; + public then(success?: (value: V) => U, error?: (err: any) => TPromise | U, progress?: ProgressCallback): TPromise; + public then(success?: (value: V) => U, error?: (err: any) => U, progress?: ProgressCallback): TPromise; + public then(success?: (value: V) => U, error?: (err: any) => void, progress?: ProgressCallback): TPromise; + + public done(success?: (value: V) => void, error?: (err: any) => any, progress?: ProgressCallback): void; + public cancel(): void; + + public static as(value: ValueType): TPromise; + public static is(value: any): value is TPromise; + public static timeout(delay: number): TPromise; + public static join(promises: TPromise[]): TPromise; + public static join(promises: Thenable[]): Thenable; + public static join(promises: { [n: string]: TPromise }): TPromise<{ [n: string]: ValueType }>; + public static any(promises: TPromise[]): TPromise<{ key: string; value: TPromise; }>; + public static wrapError(error: any): TPromise; + } + + /** + * Uniform Resource Identifier (Uri) http://tools.ietf.org/html/rfc3986. + * This class is a simple parser which creates the basic component paths + * (http://tools.ietf.org/html/rfc3986#section-3) with minimal validation + * and encoding. + * + * foo://example.com:8042/over/there?name=ferret#nose + * \_/ \______________/\_________/ \_________/ \__/ + * | | | | | + * scheme authority path query fragment + * | _____________________|__ + * / \ / \ + * urn:example:animal:ferret:nose + * + * + */ + export class Uri { + constructor(); + /** + * scheme is the 'http' part of 'http://www.msft.com/some/path?query#fragment'. + * The part before the first colon. + */ + scheme: string; + /** + * authority is the 'www.msft.com' part of 'http://www.msft.com/some/path?query#fragment'. + * The part between the first double slashes and the next slash. + */ + authority: string; + /** + * path is the '/some/path' part of 'http://www.msft.com/some/path?query#fragment'. + */ + path: string; + /** + * query is the 'query' part of 'http://www.msft.com/some/path?query#fragment'. + */ + query: string; + /** + * fragment is the 'fragment' part of 'http://www.msft.com/some/path?query#fragment'. + */ + fragment: string; + /** + * Returns a string representing the corresponding file system path of this Uri. + * Will handle UNC paths and normalize windows drive letters to lower-case. Also + * uses the platform specific path separator. Will *not* validate the path for + * invalid characters and semantics. Will *not* look at the scheme of this Uri. + */ + fsPath: string; + with(scheme: string, authority: string, path: string, query: string, fragment: string): Uri; + withScheme(value: string): Uri; + withAuthority(value: string): Uri; + withPath(value: string): Uri; + withQuery(value: string): Uri; + withFragment(value: string): Uri; + static parse(value: string): Uri; + static file(path: string): Uri; + static create(scheme?: string, authority?: string, path?: string, query?: string, fragment?: string): Uri; + /** + * + * @param skipEncoding Do not encode the result, default is `false` + */ + toString(skipEncoding?: boolean): string; + toJSON(): any; + static revive(data: any): Uri; + } + + + export class EmitterEvent { + constructor(eventType?: string, data?: any); + getType(): string; + getData(): any; + } + + export interface BulkListenerCallback { + (value: EmitterEvent[]): void; + } + + + /** + * Virtual Key Codes, the value does not hold any inherent meaning. + * Inspired somewhat from https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx + * But these are "more general", as they should work across browsers & OS`s. + */ + export enum KeyCode { + /** + * Placed first to cover the 0 value of the enum. + */ + Unknown = 0, + Backspace = 1, + Tab = 2, + Enter = 3, + Shift = 4, + Ctrl = 5, + Alt = 6, + PauseBreak = 7, + CapsLock = 8, + Escape = 9, + Space = 10, + PageUp = 11, + PageDown = 12, + End = 13, + Home = 14, + LeftArrow = 15, + UpArrow = 16, + RightArrow = 17, + DownArrow = 18, + Insert = 19, + Delete = 20, + KEY_0 = 21, + KEY_1 = 22, + KEY_2 = 23, + KEY_3 = 24, + KEY_4 = 25, + KEY_5 = 26, + KEY_6 = 27, + KEY_7 = 28, + KEY_8 = 29, + KEY_9 = 30, + KEY_A = 31, + KEY_B = 32, + KEY_C = 33, + KEY_D = 34, + KEY_E = 35, + KEY_F = 36, + KEY_G = 37, + KEY_H = 38, + KEY_I = 39, + KEY_J = 40, + KEY_K = 41, + KEY_L = 42, + KEY_M = 43, + KEY_N = 44, + KEY_O = 45, + KEY_P = 46, + KEY_Q = 47, + KEY_R = 48, + KEY_S = 49, + KEY_T = 50, + KEY_U = 51, + KEY_V = 52, + KEY_W = 53, + KEY_X = 54, + KEY_Y = 55, + KEY_Z = 56, + Meta = 57, + ContextMenu = 58, + F1 = 59, + F2 = 60, + F3 = 61, + F4 = 62, + F5 = 63, + F6 = 64, + F7 = 65, + F8 = 66, + F9 = 67, + F10 = 68, + F11 = 69, + F12 = 70, + F13 = 71, + F14 = 72, + F15 = 73, + F16 = 74, + F17 = 75, + F18 = 76, + F19 = 77, + NumLock = 78, + ScrollLock = 79, + /** + * Used for miscellaneous characters; it can vary by keyboard. + * For the US standard keyboard, the ';:' key + */ + US_SEMICOLON = 80, + /** + * For any country/region, the '+' key + * For the US standard keyboard, the '=+' key + */ + US_EQUAL = 81, + /** + * For any country/region, the ',' key + * For the US standard keyboard, the ',<' key + */ + US_COMMA = 82, + /** + * For any country/region, the '-' key + * For the US standard keyboard, the '-_' key + */ + US_MINUS = 83, + /** + * For any country/region, the '.' key + * For the US standard keyboard, the '.>' key + */ + US_DOT = 84, + /** + * Used for miscellaneous characters; it can vary by keyboard. + * For the US standard keyboard, the '/?' key + */ + US_SLASH = 85, + /** + * Used for miscellaneous characters; it can vary by keyboard. + * For the US standard keyboard, the '`~' key + */ + US_BACKTICK = 86, + /** + * Used for miscellaneous characters; it can vary by keyboard. + * For the US standard keyboard, the '[{' key + */ + US_OPEN_SQUARE_BRACKET = 87, + /** + * Used for miscellaneous characters; it can vary by keyboard. + * For the US standard keyboard, the '\|' key + */ + US_BACKSLASH = 88, + /** + * Used for miscellaneous characters; it can vary by keyboard. + * For the US standard keyboard, the ']}' key + */ + US_CLOSE_SQUARE_BRACKET = 89, + /** + * Used for miscellaneous characters; it can vary by keyboard. + * For the US standard keyboard, the ''"' key + */ + US_QUOTE = 90, + /** + * Used for miscellaneous characters; it can vary by keyboard. + */ + OEM_8 = 91, + /** + * Either the angle bracket key or the backslash key on the RT 102-key keyboard. + */ + OEM_102 = 92, + NUMPAD_0 = 93, + NUMPAD_1 = 94, + NUMPAD_2 = 95, + NUMPAD_3 = 96, + NUMPAD_4 = 97, + NUMPAD_5 = 98, + NUMPAD_6 = 99, + NUMPAD_7 = 100, + NUMPAD_8 = 101, + NUMPAD_9 = 102, + NUMPAD_MULTIPLY = 103, + NUMPAD_ADD = 104, + NUMPAD_SEPARATOR = 105, + NUMPAD_SUBTRACT = 106, + NUMPAD_DECIMAL = 107, + NUMPAD_DIVIDE = 108, + /** + * Placed last to cover the length of the enum. + */ + MAX_VALUE = 109, + } + + export class KeyMod { + static CtrlCmd: number; + static Shift: number; + static Alt: number; + static WinCtrl: number; + static chord(firstPart: number, secondPart: number): number; + } + + export interface IHTMLContentElementCode { + language: string; + value: string; + } + + export interface IHTMLContentElement { + /** + * supports **bold**, __italics__, and [[actions]] + */ + formattedText?: string; + text?: string; + className?: string; + style?: string; + customStyle?: any; + tagName?: string; + children?: IHTMLContentElement[]; + isText?: boolean; + role?: string; + markdown?: string; + code?: IHTMLContentElementCode; + } + + + export interface IAction extends IDisposable { + id: string; + label: string; + tooltip: string; + class: string; + enabled: boolean; + checked: boolean; + run(event?: any): TPromise; + } + + + export interface IKeyboardEvent { + browserEvent: Event; + target: HTMLElement; + ctrlKey: boolean; + shiftKey: boolean; + altKey: boolean; + metaKey: boolean; + keyCode: KeyCode; + clone(): IKeyboardEvent; + asKeybinding(): number; + equals(keybinding: number): boolean; + preventDefault(): void; + stopPropagation(): void; + } + export interface IMouseEvent { + browserEvent: MouseEvent; + leftButton: boolean; + middleButton: boolean; + rightButton: boolean; + target: HTMLElement; + detail: number; + posx: number; + posy: number; + ctrlKey: boolean; + shiftKey: boolean; + altKey: boolean; + metaKey: boolean; + timestamp: number; + preventDefault(): void; + stopPropagation(): void; + } + + export interface IScrollEvent { + scrollTop: number; + scrollLeft: number; + scrollWidth: number; + scrollHeight: number; + scrollTopChanged: boolean; + scrollLeftChanged: boolean; + scrollWidthChanged: boolean; + scrollHeightChanged: boolean; + } + + + /** + * A position in the editor. This interface is suitable for serialization. + */ + export interface IPosition { + /** + * line number (starts at 1) + */ + lineNumber: number; + /** + * column (the first character in a line is between column 1 and column 2) + */ + column: number; + } + + /** + * A range in the editor. This interface is suitable for serialization. + */ + export interface IRange { + /** + * Line number on which the range starts (starts at 1). + */ + startLineNumber: number; + /** + * Column on which the range starts in line `startLineNumber` (starts at 1). + */ + startColumn: number; + /** + * Line number on which the range ends. + */ + endLineNumber: number; + /** + * Column on which the range ends in line `endLineNumber`. + */ + endColumn: number; + } + + /** + * The direction of a selection. + */ + export enum SelectionDirection { + /** + * The selection starts above where it ends. + */ + LTR = 0, + /** + * The selection starts below where it ends. + */ + RTL = 1, + } + + /** + * A selection in the editor. + * The selection is a range that has an orientation. + */ + export interface ISelection { + /** + * The line number on which the selection has started. + */ + selectionStartLineNumber: number; + /** + * The column on `selectionStartLineNumber` where the selection has started. + */ + selectionStartColumn: number; + /** + * The line number on which the selection has ended. + */ + positionLineNumber: number; + /** + * The column on `positionLineNumber` where the selection has ended. + */ + positionColumn: number; + } + + /** + * A position in the editor. + */ + export class Position { + lineNumber: number; + column: number; + constructor(lineNumber: number, column: number); + /** + * Test if this position equals other position + */ + equals(other: IPosition): boolean; + static equals(a: IPosition, b: IPosition): boolean; + /** + * Test if this position is before other position. If the two positions are equal, the result will be false. + */ + isBefore(other: IPosition): boolean; + static isBefore(a: IPosition, b: IPosition): boolean; + /** + * Test if this position is before other position. If the two positions are equal, the result will be true. + */ + isBeforeOrEqual(other: IPosition): boolean; + static isBeforeOrEqual(a: IPosition, b: IPosition): boolean; + /** + * Clone this position. + */ + clone(): Position; + toString(): string; + static lift(pos: IPosition): Position; + static isIPosition(obj: any): obj is IPosition; + static asEmptyRange(position: IPosition): IRange; + static startPosition(range: IRange): IPosition; + static endPosition(range: IRange): IPosition; + } + + /** + * A range in the editor. + */ + export class Range { + startLineNumber: number; + startColumn: number; + endLineNumber: number; + endColumn: number; + constructor(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number); + /** + * Test if this range is empty. + */ + isEmpty(): boolean; + /** + * Test if position is in this range. If the position is at the edges, will return true. + */ + containsPosition(position: IPosition): boolean; + /** + * Test if range is in this range. If the range is equal to this range, will return true. + */ + containsRange(range: IRange): boolean; + /** + * A reunion of the two ranges. The smallest position will be used as the start point, and the largest one as the end point. + */ + plusRange(range: IRange): Range; + /** + * A intersection of the two ranges. + */ + intersectRanges(range: IRange): Range; + /** + * Test if this range equals other. + */ + equalsRange(other: IRange): boolean; + /** + * Return the end position (which will be after or equal to the start position) + */ + getEndPosition(): Position; + /** + * Return the start position (which will be before or equal to the end position) + */ + getStartPosition(): Position; + /** + * Clone this range. + */ + cloneRange(): Range; + /** + * Transform to a user presentable string representation. + */ + toString(): string; + /** + * Create a new range using this range's start position, and using endLineNumber and endColumn as the end position. + */ + setEndPosition(endLineNumber: number, endColumn: number): Range; + /** + * Create a new range using this range's end position, and using startLineNumber and startColumn as the start position. + */ + setStartPosition(startLineNumber: number, startColumn: number): Range; + collapseToStart(): Range; + static lift(range: IRange): Range; + static isIRange(obj: any): obj is IRange; + static isEmpty(range: IRange): boolean; + static containsPosition(range: IRange, position: IPosition): boolean; + static containsRange(range: IRange, otherRange: IRange): boolean; + static areIntersectingOrTouching(a: IRange, b: IRange): boolean; + static intersectRanges(a: IRange, b: IRange): Range; + static plusRange(a: IRange, b: IRange): Range; + static equalsRange(a: IRange, b: IRange): boolean; + /** + * A function that compares ranges, useful for sorting ranges + * It will first compare ranges on the startPosition and then on the endPosition + */ + static compareRangesUsingStarts(a: IRange, b: IRange): number; + /** + * A function that compares ranges, useful for sorting ranges + * It will first compare ranges on the endPosition and then on the startPosition + */ + static compareRangesUsingEnds(a: IRange, b: IRange): number; + static spansMultipleLines(range: IRange): boolean; + static collapseToStart(range: IRange): IRange; + } + + /** + * A selection in the editor. + */ + export class Selection extends Range { + selectionStartLineNumber: number; + selectionStartColumn: number; + positionLineNumber: number; + positionColumn: number; + constructor(selectionStartLineNumber: number, selectionStartColumn: number, positionLineNumber: number, positionColumn: number); + /** + * Clone this selection. + */ + clone(): Selection; + toString(): string; + /** + * Test if equals other selection. + */ + equalsSelection(other: ISelection): boolean; + /** + * Get directions (LTR or RTL). + */ + getDirection(): SelectionDirection; + /** + * Create a new selection with a different `positionLineNumber` and `positionColumn`. + */ + setEndPosition(endLineNumber: number, endColumn: number): Selection; + /** + * Create a new selection with a different `selectionStartLineNumber` and `selectionStartColumn`. + */ + setStartPosition(startLineNumber: number, startColumn: number): Selection; + static createSelection(selectionStartLineNumber: number, selectionStartColumn: number, positionLineNumber: number, positionColumn: number): Selection; + static liftSelection(sel: ISelection): Selection; + static selectionsEqual(a: ISelection, b: ISelection): boolean; + static selectionsArrEqual(a: ISelection[], b: ISelection[]): boolean; + static isISelection(obj: any): boolean; + static createWithDirection(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, direction: SelectionDirection): Selection; + } +} + + +declare module monaco.editor { + + /** + * A Monarch language definition + */ + export interface ILanguage { + /** + * unique name to identify the language. + */ + name: string; + /** + * map from string to ILanguageRule[] + */ + tokenizer: Object; + /** + * nice display name + */ + displayName?: string; + /** + * is the language case insensitive? + */ + ignoreCase?: boolean; + /** + * used to insert/delete line comments in the editor + */ + lineComment?: string; + /** + * used to insert/delete block comments in the editor + */ + blockCommentStart?: string; + /** + * used to insert/delete block comments in the editor + */ + blockCommentEnd?: string; + /** + * if no match in the tokenizer assign this token class (default 'source') + */ + defaultToken?: string; + /** + * for example [['{','}','delimiter.curly']] + */ + brackets?: ILanguageBracket[]; + /** + * start symbol in the tokenizer (by default the first entry is used) + */ + start?: string; + /** + * attach this to every token class (by default '.' + name) + */ + tokenPostfix?: string; + /** + * for example [['"','"']] + */ + autoClosingPairs?: string[][]; + /** + * word definition regular expression + */ + wordDefinition?: RegExp; + /** + * characters that could potentially cause outdentation + */ + outdentTriggers?: string; + } + + /** + * This interface can be shortened as an array, ie. ['{','}','delimiter.curly'] + */ + export interface ILanguageBracket { + /** + * open bracket + */ + open: string; + /** + * closeing bracket + */ + close: string; + /** + * token class + */ + token: string; + } + + export interface IMode { + + } + + export enum ScrollbarVisibility { + Auto = 1, + Hidden = 2, + Visible = 3, + } + + + /** + * Configuration options for editor scrollbars + */ + export interface IEditorScrollbarOptions { + /** + * The size of arrows (if displayed). + * Defaults to 11. + */ + arrowSize?: number; + /** + * Render vertical scrollbar. + * Accepted values: 'auto', 'visible', 'hidden'. + * Defaults to 'auto'. + */ + vertical?: string; + /** + * Render horizontal scrollbar. + * Accepted values: 'auto', 'visible', 'hidden'. + * Defaults to 'auto'. + */ + horizontal?: string; + /** + * Cast horizontal and vertical shadows when the content is scrolled. + * Defaults to false. + */ + useShadows?: boolean; + /** + * Render arrows at the top and bottom of the vertical scrollbar. + * Defaults to false. + */ + verticalHasArrows?: boolean; + /** + * Render arrows at the left and right of the horizontal scrollbar. + * Defaults to false. + */ + horizontalHasArrows?: boolean; + /** + * Listen to mouse wheel events and react to them by scrolling. + * Defaults to true. + */ + handleMouseWheel?: boolean; + /** + * Height in pixels for the horizontal scrollbar. + * Defaults to 10 (px). + */ + horizontalScrollbarSize?: number; + /** + * Width in pixels for the vertical scrollbar. + * Defaults to 10 (px). + */ + verticalScrollbarSize?: number; + verticalSliderSize?: number; + horizontalSliderSize?: number; + } + + export enum WrappingIndent { + None = 0, + Same = 1, + Indent = 2, + } + + /** + * Configuration options for the editor. + */ + export interface IEditorOptions { + experimentalScreenReader?: boolean; + ariaLabel?: string; + /** + * Render vertical lines at the specified columns. + * Defaults to empty array. + */ + rulers?: number[]; + /** + * A string containing the word separators used when doing word navigation. + * Defaults to `~!@#$%^&*()-=+[{]}\\|;:\'",.<>/? + */ + wordSeparators?: string; + /** + * Enable Linux primary clipboard. + * Defaults to true. + */ + selectionClipboard?: boolean; + /** + * Control the rendering of line numbers. + * If it is a function, it will be invoked when rendering a line number and the return value will be rendered. + * Otherwise, if it is a truey, line numbers will be rendered normally (equivalent of using an identity function). + * Otherwise, line numbers will not be rendered. + * Defaults to true. + */ + lineNumbers?: any; + /** + * Should the corresponding line be selected when clicking on the line number? + * Defaults to true. + */ + selectOnLineNumbers?: boolean; + /** + * Control the width of line numbers, by reserving horizontal space for rendering at least an amount of digits. + * Defaults to 5. + */ + lineNumbersMinChars?: number; + /** + * Enable the rendering of the glyph margin. + * Defaults to false. + */ + glyphMargin?: boolean; + /** + * The width reserved for line decorations (in px). + * Line decorations are placed between line numbers and the editor content. + * Defaults to 10. + */ + lineDecorationsWidth?: number; + /** + * When revealing the cursor, a virtual padding (px) is added to the cursor, turning it into a rectangle. + * This virtual padding ensures that the cursor gets revealed before hitting the edge of the viewport. + * Defaults to 30 (px). + */ + revealHorizontalRightPadding?: number; + /** + * Render the editor selection with rounded borders. + * Defaults to true. + */ + roundedSelection?: boolean; + /** + * Theme to be used for rendering. Consists of two parts, the UI theme and the syntax theme, + * separated by a space. + * The current available UI themes are: 'vs' (default), 'vs-dark', 'hc-black' + * The syntax themes are contributed. The default is 'default-theme' + */ + theme?: string; + /** + * Should the editor be read only. + * Defaults to false. + */ + readOnly?: boolean; + /** + * Control the behavior and rendering of the scrollbars. + */ + scrollbar?: IEditorScrollbarOptions; + /** + * The number of vertical lanes the overview ruler should render. + * Defaults to 2. + */ + overviewRulerLanes?: number; + /** + * Control the cursor blinking animation. + * Defaults to 'blink'. + */ + cursorBlinking?: string; + /** + * Control the cursor style, either 'block' or 'line'. + * Defaults to 'line'. + */ + cursorStyle?: string; + /** + * Enable font ligatures. + * Defaults to false. + */ + fontLigatures?: boolean; + /** + * Should the cursor be hidden in the overview ruler. + * Defaults to false. + */ + hideCursorInOverviewRuler?: boolean; + /** + * Enable that scrolling can go one screen size after the last line. + * Defaults to true. + */ + scrollBeyondLastLine?: boolean; + /** + * Enable that the editor will install an interval to check if its container dom node size has changed. + * Enabling this might have a severe performance impact. + * Defaults to false. + */ + automaticLayout?: boolean; + /** + * Control the wrapping strategy of the editor. + * Using -1 means no wrapping whatsoever. + * Using 0 means viewport width wrapping (ajusts with the resizing of the editor). + * Using a positive number means wrapping after a fixed number of characters. + * Defaults to 300. + */ + wrappingColumn?: number; + /** + * Control indentation of wrapped lines. Can be: 'none', 'same' or 'indent'. + * Defaults to 'none'. + */ + wrappingIndent?: string; + /** + * Configure word wrapping characters. A break will be introduced before these characters. + * Defaults to '{([+'. + */ + wordWrapBreakBeforeCharacters?: string; + /** + * Configure word wrapping characters. A break will be introduced after these characters. + * Defaults to ' \t})]?|&,;'. + */ + wordWrapBreakAfterCharacters?: string; + /** + * Configure word wrapping characters. A break will be introduced after these characters only if no `wordWrapBreakBeforeCharacters` or `wordWrapBreakAfterCharacters` were found. + * Defaults to '.'. + */ + wordWrapBreakObtrusiveCharacters?: string; + /** + * Control what pressing Tab does. + * If it is false, pressing Tab or Shift-Tab will be handled by the editor. + * If it is true, pressing Tab or Shift-Tab will move the browser focus. + * Defaults to false. + */ + tabFocusMode?: boolean; + /** + * Performance guard: Stop rendering a line after x characters. + * Defaults to 10000 if wrappingColumn is -1. Defaults to -1 if wrappingColumn is >= 0. + * Use -1 to never stop rendering + */ + stopRenderingLineAfter?: number; + /** + * Enable hover. + * Defaults to true. + */ + hover?: boolean; + /** + * Enable custom contextmenu. + * Defaults to true. + */ + contextmenu?: boolean; + /** + * A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events. + * Defaults to 1. + */ + mouseWheelScrollSensitivity?: number; + /** + * Enable quick suggestions (shaddow suggestions) + * Defaults to true. + */ + quickSuggestions?: boolean; + /** + * Quick suggestions show delay (in ms) + * Defaults to 500 (ms) + */ + quickSuggestionsDelay?: number; + /** + * Render icons in suggestions box. + * Defaults to true. + */ + iconsInSuggestions?: boolean; + /** + * Enable auto closing brackets. + * Defaults to true. + */ + autoClosingBrackets?: boolean; + /** + * Enable format on type. + * Defaults to false. + */ + formatOnType?: boolean; + /** + * Enable the suggestion box to pop-up on trigger characters. + * Defaults to true. + */ + suggestOnTriggerCharacters?: boolean; + /** + * Accept suggestions on ENTER. + * Defaults to true. + */ + acceptSuggestionOnEnter?: boolean; + /** + * Enable selection highlight. + * Defaults to true. + */ + selectionHighlight?: boolean; + /** + * Show lines before classes and methods (based on outline info). + * Defaults to false. + */ + outlineMarkers?: boolean; + /** + * Show reference infos (a.k.a. code lenses) for modes that support it + * Defaults to true. + */ + referenceInfos?: boolean; + /** + * Enable code folding + * Defaults to true. + */ + folding?: boolean; + /** + * Enable rendering of leading whitespace. + * Defaults to false. + */ + renderWhitespace?: boolean; + /** + * Enable rendering of indent guides. + * Defaults to true. + */ + indentGuides?: boolean; + /** + * Inserting and deleting whitespace follows tab stops. + */ + useTabStops?: boolean; + /** + * The font family + */ + fontFamily?: string; + /** + * The font size + */ + fontSize?: number; + /** + * The line height + */ + lineHeight?: number; + } + + /** + * Configuration options for the diff editor. + */ + export interface IDiffEditorOptions extends IEditorOptions { + /** + * Allow the user to resize the diff editor split view. + * Defaults to true. + */ + enableSplitViewResizing?: boolean; + /** + * Render the differences in two side-by-side editors. + * Defaults to true. + */ + renderSideBySide?: boolean; + /** + * Compute the diff by ignoring leading/trailing whitespace + * Defaults to true. + */ + ignoreTrimWhitespace?: boolean; + /** + * Original model should be editable? + * Defaults to false. + */ + originalEditable?: boolean; + } + + export class InternalEditorScrollbarOptions { + _internalEditorScrollbarOptionsBrand: void; + arrowSize: number; + vertical: ScrollbarVisibility; + horizontal: ScrollbarVisibility; + useShadows: boolean; + verticalHasArrows: boolean; + horizontalHasArrows: boolean; + handleMouseWheel: boolean; + horizontalScrollbarSize: number; + horizontalSliderSize: number; + verticalScrollbarSize: number; + verticalSliderSize: number; + mouseWheelScrollSensitivity: number; + constructor(source: { + arrowSize: number; + vertical: ScrollbarVisibility; + horizontal: ScrollbarVisibility; + useShadows: boolean; + verticalHasArrows: boolean; + horizontalHasArrows: boolean; + handleMouseWheel: boolean; + horizontalScrollbarSize: number; + horizontalSliderSize: number; + verticalScrollbarSize: number; + verticalSliderSize: number; + mouseWheelScrollSensitivity: number; + }); + equals(other: InternalEditorScrollbarOptions): boolean; + clone(): InternalEditorScrollbarOptions; + } + + export class EditorWrappingInfo { + _editorWrappingInfoBrand: void; + isViewportWrapping: boolean; + wrappingColumn: number; + wrappingIndent: WrappingIndent; + wordWrapBreakBeforeCharacters: string; + wordWrapBreakAfterCharacters: string; + wordWrapBreakObtrusiveCharacters: string; + constructor(source: { + isViewportWrapping: boolean; + wrappingColumn: number; + wrappingIndent: WrappingIndent; + wordWrapBreakBeforeCharacters: string; + wordWrapBreakAfterCharacters: string; + wordWrapBreakObtrusiveCharacters: string; + }); + equals(other: EditorWrappingInfo): boolean; + clone(): EditorWrappingInfo; + } + + export class InternalEditorViewOptions { + _internalEditorViewOptionsBrand: void; + theme: string; + canUseTranslate3d: boolean; + experimentalScreenReader: boolean; + rulers: number[]; + ariaLabel: string; + lineNumbers: any; + selectOnLineNumbers: boolean; + glyphMargin: boolean; + revealHorizontalRightPadding: number; + roundedSelection: boolean; + overviewRulerLanes: number; + cursorBlinking: string; + cursorStyle: TextEditorCursorStyle; + hideCursorInOverviewRuler: boolean; + scrollBeyondLastLine: boolean; + editorClassName: string; + stopRenderingLineAfter: number; + renderWhitespace: boolean; + indentGuides: boolean; + scrollbar: InternalEditorScrollbarOptions; + constructor(source: { + theme: string; + canUseTranslate3d: boolean; + experimentalScreenReader: boolean; + rulers: number[]; + ariaLabel: string; + lineNumbers: any; + selectOnLineNumbers: boolean; + glyphMargin: boolean; + revealHorizontalRightPadding: number; + roundedSelection: boolean; + overviewRulerLanes: number; + cursorBlinking: string; + cursorStyle: TextEditorCursorStyle; + hideCursorInOverviewRuler: boolean; + scrollBeyondLastLine: boolean; + editorClassName: string; + stopRenderingLineAfter: number; + renderWhitespace: boolean; + indentGuides: boolean; + scrollbar: InternalEditorScrollbarOptions; + }); + equals(other: InternalEditorViewOptions): boolean; + createChangeEvent(newOpts: InternalEditorViewOptions): IViewConfigurationChangedEvent; + clone(): InternalEditorViewOptions; + } + + export interface IViewConfigurationChangedEvent { + theme: boolean; + canUseTranslate3d: boolean; + experimentalScreenReader: boolean; + rulers: boolean; + ariaLabel: boolean; + lineNumbers: boolean; + selectOnLineNumbers: boolean; + glyphMargin: boolean; + revealHorizontalRightPadding: boolean; + roundedSelection: boolean; + overviewRulerLanes: boolean; + cursorBlinking: boolean; + cursorStyle: boolean; + hideCursorInOverviewRuler: boolean; + scrollBeyondLastLine: boolean; + editorClassName: boolean; + stopRenderingLineAfter: boolean; + renderWhitespace: boolean; + indentGuides: boolean; + scrollbar: boolean; + } + + export class EditorContribOptions { + selectionClipboard: boolean; + hover: boolean; + contextmenu: boolean; + quickSuggestions: boolean; + quickSuggestionsDelay: number; + iconsInSuggestions: boolean; + formatOnType: boolean; + suggestOnTriggerCharacters: boolean; + acceptSuggestionOnEnter: boolean; + selectionHighlight: boolean; + outlineMarkers: boolean; + referenceInfos: boolean; + folding: boolean; + constructor(source: { + selectionClipboard: boolean; + hover: boolean; + contextmenu: boolean; + quickSuggestions: boolean; + quickSuggestionsDelay: number; + iconsInSuggestions: boolean; + formatOnType: boolean; + suggestOnTriggerCharacters: boolean; + acceptSuggestionOnEnter: boolean; + selectionHighlight: boolean; + outlineMarkers: boolean; + referenceInfos: boolean; + folding: boolean; + }); + equals(other: EditorContribOptions): boolean; + clone(): EditorContribOptions; + } + + /** + * Internal configuration options (transformed or computed) for the editor. + */ + export class InternalEditorOptions { + _internalEditorOptionsBrand: void; + lineHeight: number; + readOnly: boolean; + wordSeparators: string; + autoClosingBrackets: boolean; + useTabStops: boolean; + tabFocusMode: boolean; + layoutInfo: EditorLayoutInfo; + fontInfo: FontInfo; + viewInfo: InternalEditorViewOptions; + wrappingInfo: EditorWrappingInfo; + contribInfo: EditorContribOptions; + constructor(source: { + lineHeight: number; + readOnly: boolean; + wordSeparators: string; + autoClosingBrackets: boolean; + useTabStops: boolean; + tabFocusMode: boolean; + layoutInfo: EditorLayoutInfo; + fontInfo: FontInfo; + viewInfo: InternalEditorViewOptions; + wrappingInfo: EditorWrappingInfo; + contribInfo: EditorContribOptions; + }); + equals(other: InternalEditorOptions): boolean; + createChangeEvent(newOpts: InternalEditorOptions): IConfigurationChangedEvent; + clone(): InternalEditorOptions; + } + + /** + * An event describing that the configuration of the editor has changed. + */ + export interface IConfigurationChangedEvent { + lineHeight: boolean; + readOnly: boolean; + wordSeparators: boolean; + autoClosingBrackets: boolean; + useTabStops: boolean; + tabFocusMode: boolean; + layoutInfo: boolean; + fontInfo: boolean; + viewInfo: IViewConfigurationChangedEvent; + wrappingInfo: boolean; + contribInfo: boolean; + } + + /** + * An event describing that one or more supports of a mode have changed. + */ + export interface IModeSupportChangedEvent { + tokenizationSupport: boolean; + richEditSupport: boolean; + } + + /** + * Vertical Lane in the overview ruler of the editor. + */ + export enum OverviewRulerLane { + Left = 1, + Center = 2, + Right = 4, + Full = 7, + } + + /** + * Options for rendering a model decoration in the overview ruler. + */ + export interface IModelDecorationOverviewRulerOptions { + /** + * CSS color to render in the overview ruler. + * e.g.: rgba(100, 100, 100, 0.5) + */ + color: string; + /** + * CSS color to render in the overview ruler. + * e.g.: rgba(100, 100, 100, 0.5) + */ + darkColor: string; + /** + * The position in the overview ruler. + */ + position: OverviewRulerLane; + } + + /** + * Options for a model decoration. + */ + export interface IModelDecorationOptions { + /** + * Customize the growing behaviour of the decoration when typing at the edges of the decoration. + * Defaults to TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges + */ + stickiness?: TrackedRangeStickiness; + /** + * CSS class name describing the decoration. + */ + className?: string; + /** + * Message to be rendered when hovering over the decoration. + */ + hoverMessage?: string; + /** + * Array of IHTMLContentElements to render as the decoration message. + */ + htmlMessage?: IHTMLContentElement[]; + /** + * Should the decoration expand to encompass a whole line. + */ + isWholeLine?: boolean; + /** + * @deprecated : Use `overviewRuler` instead + */ + showInOverviewRuler?: string; + /** + * If set, render this decoration in the overview ruler. + */ + overviewRuler?: IModelDecorationOverviewRulerOptions; + /** + * If set, the decoration will be rendered in the glyph margin with this CSS class name. + */ + glyphMarginClassName?: string; + /** + * If set, the decoration will be rendered in the lines decorations with this CSS class name. + */ + linesDecorationsClassName?: string; + /** + * If set, the decoration will be rendered inline with the text with this CSS class name. + * Please use this only for CSS rules that must impact the text. For example, use `className` + * to have a background color decoration. + */ + inlineClassName?: string; + } + + /** + * New model decorations. + */ + export interface IModelDeltaDecoration { + /** + * Range that this decoration covers. + */ + range: IRange; + /** + * Options associated with this decoration. + */ + options: IModelDecorationOptions; + } + + /** + * A decoration in the model. + */ + export interface IModelDecoration { + /** + * Identifier for a decoration. + */ + id: string; + /** + * Identifier for a decoration's owener. + */ + ownerId: number; + /** + * Range that this decoration covers. + */ + range: Range; + /** + * Options associated with this decoration. + */ + options: IModelDecorationOptions; + } + + /** + * Word inside a model. + */ + export interface IWordAtPosition { + /** + * The word. + */ + word: string; + /** + * The column where the word starts. + */ + startColumn: number; + /** + * The column where the word ends. + */ + endColumn: number; + } + + /** + * End of line character preference. + */ + export enum EndOfLinePreference { + /** + * Use the end of line character identified in the text buffer. + */ + TextDefined = 0, + /** + * Use line feed (\n) as the end of line character. + */ + LF = 1, + /** + * Use carriage return and line feed (\r\n) as the end of line character. + */ + CRLF = 2, + } + + /** + * The default end of line to use when instantiating models. + */ + export enum DefaultEndOfLine { + /** + * Use line feed (\n) as the end of line character. + */ + LF = 1, + /** + * Use carriage return and line feed (\r\n) as the end of line character. + */ + CRLF = 2, + } + + /** + * End of line character preference. + */ + export enum EndOfLineSequence { + /** + * Use line feed (\n) as the end of line character. + */ + LF = 0, + /** + * Use carriage return and line feed (\r\n) as the end of line character. + */ + CRLF = 1, + } + + /** + * And identifier for a single edit operation. + */ + export interface ISingleEditOperationIdentifier { + /** + * Identifier major + */ + major: number; + /** + * Identifier minor + */ + minor: number; + } + + /** + * A builder and helper for edit operations for a command. + */ + export interface IEditOperationBuilder { + /** + * Add a new edit operation (a replace operation). + * @param range The range to replace (delete). May be empty to represent a simple insert. + * @param text The text to replace with. May be null to represent a simple delete. + */ + addEditOperation(range: Range, text: string): void; + /** + * Track `selection` when applying edit operations. + * A best effort will be made to not grow/expand the selection. + * An empty selection will clamp to a nearby character. + * @param selection The selection to track. + * @param trackPreviousOnEmpty If set, and the selection is empty, indicates whether the selection + * should clamp to the previous or the next character. + * @return A unique identifer. + */ + trackSelection(selection: Selection, trackPreviousOnEmpty?: boolean): string; + } + + /** + * A helper for computing cursor state after a command. + */ + export interface ICursorStateComputerData { + /** + * Get the inverse edit operations of the added edit operations. + */ + getInverseEditOperations(): IIdentifiedSingleEditOperation[]; + /** + * Get a previously tracked selection. + * @param id The unique identifier returned by `trackSelection`. + * @return The selection. + */ + getTrackedSelection(id: string): Selection; + } + + /** + * A command that modifies text / cursor state on a model. + */ + export interface ICommand { + /** + * Get the edit operations needed to execute this command. + * @param model The model the command will execute on. + * @param builder A helper to collect the needed edit operations and to track selections. + */ + getEditOperations(model: ITokenizedModel, builder: IEditOperationBuilder): void; + /** + * Compute the cursor state after the edit operations were applied. + * @param model The model the commad has executed on. + * @param helper A helper to get inverse edit operations and to get previously tracked selections. + * @return The cursor state after the command executed. + */ + computeCursorState(model: ITokenizedModel, helper: ICursorStateComputerData): Selection; + } + + /** + * A single edit operation, that has an identifier. + */ + export interface IIdentifiedSingleEditOperation { + /** + * An identifier associated with this single edit operation. + */ + identifier: ISingleEditOperationIdentifier; + /** + * The range to replace. This can be empty to emulate a simple insert. + */ + range: Range; + /** + * The text to replace with. This can be null to emulate a simple delete. + */ + text: string; + /** + * This indicates that this operation has "insert" semantics. + * i.e. forceMoveMarkers = true => if `range` is collapsed, all markers at the position will be moved. + */ + forceMoveMarkers: boolean; + /** + * This indicates that this operation is inserting automatic whitespace + * that can be removed on next model edit operation if `config.trimAutoWhitespace` is true. + */ + isAutoWhitespaceEdit?: boolean; + } + + /** + * A callback that can compute the cursor state after applying a series of edit operations. + */ + export interface ICursorStateComputer { + /** + * A callback that can compute the resulting cursors state after some edit operations have been executed. + */ + (inverseEditOperations: IIdentifiedSingleEditOperation[]): Selection[]; + } + + export interface ITextModelResolvedOptions { + tabSize: number; + insertSpaces: boolean; + defaultEOL: DefaultEndOfLine; + trimAutoWhitespace: boolean; + } + + export interface ITextModelCreationOptions { + tabSize: number; + insertSpaces: boolean; + detectIndentation: boolean; + trimAutoWhitespace: boolean; + defaultEOL: DefaultEndOfLine; + } + + export interface ITextModelUpdateOptions { + tabSize?: number; + insertSpaces?: boolean; + trimAutoWhitespace?: boolean; + } + + export interface IModelOptionsChangedEvent { + tabSize: boolean; + insertSpaces: boolean; + trimAutoWhitespace: boolean; + } + + /** + * A textual read-only model. + */ + export interface ITextModel { + getOptions(): ITextModelResolvedOptions; + /** + * Get the current version id of the model. + * Anytime a change happens to the model (even undo/redo), + * the version id is incremented. + */ + getVersionId(): number; + /** + * Get the alternative version id of the model. + * This alternative version id is not always incremented, + * it will return the same values in the case of undo-redo. + */ + getAlternativeVersionId(): number; + /** + * Replace the entire text buffer value contained in this model. + */ + setValue(newValue: string): void; + /** + * Replace the entire text buffer value contained in this model. + */ + setValueFromRawText(newValue: IRawText): void; + /** + * Get the text stored in this model. + * @param eol The end of line character preference. Defaults to `EndOfLinePreference.TextDefined`. + * @param preserverBOM Preserve a BOM character if it was detected when the model was constructed. + * @return The text. + */ + getValue(eol?: EndOfLinePreference, preserveBOM?: boolean): string; + getValueLength(eol?: EndOfLinePreference, preserveBOM?: boolean): number; + toRawText(): IRawText; + equals(other: IRawText): boolean; + /** + * Get the text in a certain range. + * @param range The range describing what text to get. + * @param eol The end of line character preference. This will only be used for multiline ranges. Defaults to `EndOfLinePreference.TextDefined`. + * @return The text. + */ + getValueInRange(range: IRange, eol?: EndOfLinePreference): string; + /** + * Get the length of text in a certain range. + * @param range The range describing what text length to get. + * @return The text length. + */ + getValueLengthInRange(range: IRange): number; + /** + * Get the number of lines in the model. + */ + getLineCount(): number; + /** + * Get the text for a certain line. + */ + getLineContent(lineNumber: number): string; + /** + * Get the text for all lines. + */ + getLinesContent(): string[]; + /** + * Get the end of line character predominantly used in the text buffer. + * @return EOL char sequence (e.g.: '\n' or '\r\n'). + */ + getEOL(): string; + setEOL(eol: EndOfLineSequence): void; + /** + * Get the minimum legal column for line at `lineNumber` + */ + getLineMinColumn(lineNumber: number): number; + /** + * Get the maximum legal column for line at `lineNumber` + */ + getLineMaxColumn(lineNumber: number): number; + /** + * Returns the column before the first non whitespace character for line at `lineNumber`. + * Returns 0 if line is empty or contains only whitespace. + */ + getLineFirstNonWhitespaceColumn(lineNumber: number): number; + /** + * Returns the column after the last non whitespace character for line at `lineNumber`. + * Returns 0 if line is empty or contains only whitespace. + */ + getLineLastNonWhitespaceColumn(lineNumber: number): number; + /** + * Create a valid position, + */ + validatePosition(position: IPosition): Position; + /** + * Advances the given position by the given offest (negative offsets are also accepted) + * and returns it as a new valid position. + * + * If the offset and position are such that their combination goes beyond the beginning or + * end of the model, throws an exception. + * + * If the ofsset is such that the new position would be in the middle of a multi-byte + * line terminator, throws an exception. + */ + modifyPosition(position: IPosition, offset: number): Position; + /** + * Create a valid range. + */ + validateRange(range: IRange): Range; + /** + * Get a range covering the entire model + */ + getFullModelRange(): Range; + /** + * Returns iff the model was disposed or not. + */ + isDisposed(): boolean; + } + + export interface IReadOnlyModel extends ITextModel { + /** + * Gets the resource associated with this editor model. + */ + uri: Uri; + getModeId(): string; + /** + * Get the word under or besides `position`. + * @param position The position to look for a word. + * @param skipSyntaxTokens Ignore syntax tokens, as identified by the mode. + * @return The word under or besides `position`. Might be null. + */ + getWordAtPosition(position: IPosition): IWordAtPosition; + /** + * Get the word under or besides `position` trimmed to `position`.column + * @param position The position to look for a word. + * @param skipSyntaxTokens Ignore syntax tokens, as identified by the mode. + * @return The word under or besides `position`. Will never be null. + */ + getWordUntilPosition(position: IPosition): IWordAtPosition; + } + + /** + * A model that is tokenized. + */ + export interface ITokenizedModel extends ITextModel { + /** + * Get the current language mode associated with the model. + */ + getMode(): IMode; + /** + * Set the current language mode associated with the model. + */ + setMode(newMode: IMode | TPromise): void; + /** + * Get the word under or besides `position`. + * @param position The position to look for a word. + * @param skipSyntaxTokens Ignore syntax tokens, as identified by the mode. + * @return The word under or besides `position`. Might be null. + */ + getWordAtPosition(position: IPosition): IWordAtPosition; + /** + * Get the word under or besides `position` trimmed to `position`.column + * @param position The position to look for a word. + * @param skipSyntaxTokens Ignore syntax tokens, as identified by the mode. + * @return The word under or besides `position`. Will never be null. + */ + getWordUntilPosition(position: IPosition): IWordAtPosition; + } + + /** + * A model that can track markers. + */ + export interface ITextModelWithMarkers extends ITextModel { + } + + export enum TrackedRangeStickiness { + AlwaysGrowsWhenTypingAtEdges = 0, + NeverGrowsWhenTypingAtEdges = 1, + GrowsOnlyWhenTypingBefore = 2, + GrowsOnlyWhenTypingAfter = 3, + } + + /** + * A model that can track ranges. + */ + export interface ITextModelWithTrackedRanges extends ITextModel { + } + + /** + * A model that can have decorations. + */ + export interface ITextModelWithDecorations { + /** + * Perform a minimum ammount of operations, in order to transform the decorations + * identified by `oldDecorations` to the decorations described by `newDecorations` + * and returns the new identifiers associated with the resulting decorations. + * + * @param oldDecorations Array containing previous decorations identifiers. + * @param newDecorations Array describing what decorations should result after the call. + * @param ownerId Identifies the editor id in which these decorations should appear. If no `ownerId` is provided, the decorations will appear in all editors that attach this model. + * @return An array containing the new decorations identifiers. + */ + deltaDecorations(oldDecorations: string[], newDecorations: IModelDeltaDecoration[], ownerId?: number): string[]; + /** + * Get the options associated with a decoration. + * @param id The decoration id. + * @return The decoration options or null if the decoration was not found. + */ + getDecorationOptions(id: string): IModelDecorationOptions; + /** + * Get the range associated with a decoration. + * @param id The decoration id. + * @return The decoration range or null if the decoration was not found. + */ + getDecorationRange(id: string): Range; + /** + * Gets all the decorations for the line `lineNumber` as an array. + * @param lineNumber The line number + * @param ownerId If set, it will ignore decorations belonging to other owners. + * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors). + * @return An array with the decorations + */ + getLineDecorations(lineNumber: number, ownerId?: number, filterOutValidation?: boolean): IModelDecoration[]; + /** + * Gets all the decorations for the lines between `startLineNumber` and `endLineNumber` as an array. + * @param startLineNumber The start line number + * @param endLineNumber The end line number + * @param ownerId If set, it will ignore decorations belonging to other owners. + * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors). + * @return An array with the decorations + */ + getLinesDecorations(startLineNumber: number, endLineNumber: number, ownerId?: number, filterOutValidation?: boolean): IModelDecoration[]; + /** + * Gets all the deocorations in a range as an array. Only `startLineNumber` and `endLineNumber` from `range` are used for filtering. + * So for now it returns all the decorations on the same line as `range`. + * @param range The range to search in + * @param ownerId If set, it will ignore decorations belonging to other owners. + * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors). + * @return An array with the decorations + */ + getDecorationsInRange(range: IRange, ownerId?: number, filterOutValidation?: boolean): IModelDecoration[]; + /** + * Gets all the decorations as an array. + * @param ownerId If set, it will ignore decorations belonging to other owners. + * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors). + */ + getAllDecorations(ownerId?: number, filterOutValidation?: boolean): IModelDecoration[]; + } + + /** + * An editable text model. + */ + export interface IEditableTextModel extends ITextModelWithMarkers { + normalizeIndentation(str: string): string; + getOneIndent(): string; + updateOptions(newOpts: ITextModelUpdateOptions): void; + detectIndentation(defaultInsertSpaces: boolean, defaultTabSize: number): void; + /** + * Push a stack element onto the undo stack. This acts as an undo/redo point. + * The idea is to use `pushEditOperations` to edit the model and then to + * `pushStackElement` to create an undo/redo stop point. + */ + pushStackElement(): void; + /** + * Push edit operations, basically editing the model. This is the preferred way + * of editing the model. The edit operations will land on the undo stack. + * @param beforeCursorState The cursor state before the edit operaions. This cursor state will be returned when `undo` or `redo` are invoked. + * @param editOperations The edit operations. + * @param cursorStateComputer A callback that can compute the resulting cursors state after the edit operations have been executed. + * @return The cursor state returned by the `cursorStateComputer`. + */ + pushEditOperations(beforeCursorState: Selection[], editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer): Selection[]; + /** + * Edit the model without adding the edits to the undo stack. + * This can have dire consequences on the undo stack! See @pushEditOperations for the preferred way. + * @param operations The edit operations. + * @return The inverse edit operations, that, when applied, will bring the model back to the previous state. + */ + applyEdits(operations: IIdentifiedSingleEditOperation[]): IIdentifiedSingleEditOperation[]; + } + + /** + * A model. + */ + export interface IModel extends IReadOnlyModel, IEditableTextModel, ITextModelWithMarkers, ITokenizedModel, ITextModelWithTrackedRanges, ITextModelWithDecorations, IEditorModel { + onDidChangeRawContent(listener: (e: IModelContentChangedEvent) => void): IDisposable; + onDidChangeContent(listener: (e: IModelContentChangedEvent2) => void): IDisposable; + onDidChangeModeSupport(listener: (e: IModeSupportChangedEvent) => void): IDisposable; + onDidChangeDecorations(listener: (e: IModelDecorationsChangedEvent) => void): IDisposable; + onDidChangeOptions(listener: (e: IModelOptionsChangedEvent) => void): IDisposable; + onDidChangeMode(listener: (e: IModelModeChangedEvent) => void): IDisposable; + onWillDispose(listener: () => void): IDisposable; + addBulkListener(listener: BulkListenerCallback): IDisposable; + /** + * A unique identifier associated with this model. + */ + id: string; + /** + * Destroy this model. This will unbind the model from the mode + * and make all necessary clean-up to release this object to the GC. + */ + dispose(): void; + /** + * Search the model. + * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true. + * @param searchOnlyEditableRange Limit the searching to only search inside the editable range of the model. + * @param isRegex Used to indicate that `searchString` is a regular expression. + * @param matchCase Force the matching to match lower/upper case exactly. + * @param wholeWord Force the matching to match entire words only. + * @param limitResultCount Limit the number of results + * @return The ranges where the matches are. It is empty if not matches have been found. + */ + findMatches(searchString: string, searchOnlyEditableRange: boolean, isRegex: boolean, matchCase: boolean, wholeWord: boolean, limitResultCount?: number): Range[]; + /** + * Search the model. + * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true. + * @param searchScope Limit the searching to only search inside this range. + * @param isRegex Used to indicate that `searchString` is a regular expression. + * @param matchCase Force the matching to match lower/upper case exactly. + * @param wholeWord Force the matching to match entire words only. + * @param limitResultCount Limit the number of results + * @return The ranges where the matches are. It is empty if no matches have been found. + */ + findMatches(searchString: string, searchScope: IRange, isRegex: boolean, matchCase: boolean, wholeWord: boolean, limitResultCount?: number): Range[]; + /** + * Search the model for the next match. Loops to the beginning of the model if needed. + * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true. + * @param searchStart Start the searching at the specified position. + * @param isRegex Used to indicate that `searchString` is a regular expression. + * @param matchCase Force the matching to match lower/upper case exactly. + * @param wholeWord Force the matching to match entire words only. + * @return The range where the next match is. It is null if no next match has been found. + */ + findNextMatch(searchString: string, searchStart: IPosition, isRegex: boolean, matchCase: boolean, wholeWord: boolean): Range; + /** + * Search the model for the previous match. Loops to the end of the model if needed. + * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true. + * @param searchStart Start the searching at the specified position. + * @param isRegex Used to indicate that `searchString` is a regular expression. + * @param matchCase Force the matching to match lower/upper case exactly. + * @param wholeWord Force the matching to match entire words only. + * @return The range where the previous match is. It is null if no previous match has been found. + */ + findPreviousMatch(searchString: string, searchStart: IPosition, isRegex: boolean, matchCase: boolean, wholeWord: boolean): Range; + } + + /** + * An event describing that the current mode associated with a model has changed. + */ + export interface IModelModeChangedEvent { + /** + * Previous mode + */ + oldMode: IMode; + /** + * New mode + */ + newMode: IMode; + } + + /** + * An event describing a change in the text of a model. + */ + export interface IModelContentChangedEvent2 { + /** + * The range that got replaced. + */ + range: IRange; + /** + * The length of the range that got replaced. + */ + rangeLength: number; + /** + * The new text for the range. + */ + text: string; + /** + * The (new) end-of-line character. + */ + eol: string; + /** + * The new version id the model has transitioned to. + */ + versionId: number; + /** + * Flag that indicates that this event was generated while undoing. + */ + isUndoing: boolean; + /** + * Flag that indicates that this event was generated while redoing. + */ + isRedoing: boolean; + } + + /** + * An event describing a change in the text of a model. + */ + export interface IModelContentChangedEvent { + /** + * The event type. It can be used to detect the actual event type: + * EditorCommon.EventType.ModelContentChangedFlush => IModelContentChangedFlushEvent + * EditorCommon.EventType.ModelContentChangedLinesDeleted => IModelContentChangedLineChangedEvent + * EditorCommon.EventType.ModelContentChangedLinesInserted => IModelContentChangedLinesDeletedEvent + * EditorCommon.EventType.ModelContentChangedLineChanged => IModelContentChangedLinesInsertedEvent + */ + changeType: string; + /** + * The new version id the model has transitioned to. + */ + versionId: number; + /** + * Flag that indicates that this event was generated while undoing. + */ + isUndoing: boolean; + /** + * Flag that indicates that this event was generated while redoing. + */ + isRedoing: boolean; + } + + export interface IRawText { + length: number; + lines: string[]; + BOM: string; + EOL: string; + options: ITextModelResolvedOptions; + } + + /** + * An event describing that a model has been reset to a new value. + */ + export interface IModelContentChangedFlushEvent extends IModelContentChangedEvent { + /** + * The new text content of the model. + */ + detail: IRawText; + } + + /** + * An event describing that a line has changed in a model. + */ + export interface IModelContentChangedLineChangedEvent extends IModelContentChangedEvent { + /** + * The line that has changed. + */ + lineNumber: number; + /** + * The new value of the line. + */ + detail: string; + } + + /** + * An event describing that line(s) have been deleted in a model. + */ + export interface IModelContentChangedLinesDeletedEvent extends IModelContentChangedEvent { + /** + * At what line the deletion began (inclusive). + */ + fromLineNumber: number; + /** + * At what line the deletion stopped (inclusive). + */ + toLineNumber: number; + } + + /** + * An event describing that line(s) have been inserted in a model. + */ + export interface IModelContentChangedLinesInsertedEvent extends IModelContentChangedEvent { + /** + * Before what line did the insertion begin + */ + fromLineNumber: number; + /** + * `toLineNumber` - `fromLineNumber` + 1 denotes the number of lines that were inserted + */ + toLineNumber: number; + /** + * The text that was inserted + */ + detail: string; + } + + /** + * Decoration data associated with a model decorations changed event. + */ + export interface IModelDecorationsChangedEventDecorationData { + id: string; + ownerId: number; + range: IRange; + isForValidation: boolean; + options: IModelDecorationOptions; + } + + /** + * An event describing that model decorations have changed. + */ + export interface IModelDecorationsChangedEvent { + /** + * A summary with ids of decorations that have changed. + */ + ids: string[]; + /** + * Lists of details + */ + addedOrChangedDecorations: IModelDecorationsChangedEventDecorationData[]; + removedDecorations: string[]; + oldOptions: { + [decorationId: string]: IModelDecorationOptions; + }; + oldRanges: { + [decorationId: string]: IRange; + }; + } + + /** + * An event describing that a range of lines has been tokenized + */ + export interface IModelTokensChangedEvent { + /** + * The start of the range (inclusive) + */ + fromLineNumber: number; + /** + * The end of the range (inclusive) + */ + toLineNumber: number; + } + + export enum CursorChangeReason { + NotSet = 0, + ContentFlush = 1, + RecoverFromMarkers = 2, + Explicit = 3, + Paste = 4, + Undo = 5, + Redo = 6, + } + + /** + * An event describing that the cursor position has changed. + */ + export interface ICursorPositionChangedEvent { + /** + * Primary cursor's position. + */ + position: Position; + /** + * Primary cursor's view position + */ + viewPosition: Position; + /** + * Secondary cursors' position. + */ + secondaryPositions: Position[]; + /** + * Secondary cursors' view position. + */ + secondaryViewPositions: Position[]; + /** + * Reason. + */ + reason: CursorChangeReason; + /** + * Source of the call that caused the event. + */ + source: string; + /** + * Is the primary cursor in the editable range? + */ + isInEditableRange: boolean; + } + + /** + * An event describing that the cursor selection has changed. + */ + export interface ICursorSelectionChangedEvent { + /** + * The primary selection. + */ + selection: Selection; + /** + * The primary selection in view coordinates. + */ + viewSelection: Selection; + /** + * The secondary selections. + */ + secondarySelections: Selection[]; + /** + * The secondary selections in view coordinates. + */ + secondaryViewSelections: Selection[]; + /** + * Source of the call that caused the event. + */ + source: string; + /** + * Reason. + */ + reason: CursorChangeReason; + } + + export interface IModelChangedEvent { + oldModelUrl: string; + newModelUrl: string; + } + + /** + * A description for the overview ruler position. + */ + export class OverviewRulerPosition { + _overviewRulerPositionBrand: void; + /** + * Width of the overview ruler + */ + width: number; + /** + * Height of the overview ruler + */ + height: number; + /** + * Top position for the overview ruler + */ + top: number; + /** + * Right position for the overview ruler + */ + right: number; + constructor(source: { + width: number; + height: number; + top: number; + right: number; + }); + equals(other: OverviewRulerPosition): boolean; + clone(): OverviewRulerPosition; + } + + /** + * The internal layout details of the editor. + */ + export class EditorLayoutInfo { + _editorLayoutInfoBrand: void; + /** + * Full editor width. + */ + width: number; + /** + * Full editor height. + */ + height: number; + /** + * Left position for the glyph margin. + */ + glyphMarginLeft: number; + /** + * The width of the glyph margin. + */ + glyphMarginWidth: number; + /** + * The height of the glyph margin. + */ + glyphMarginHeight: number; + /** + * Left position for the line numbers. + */ + lineNumbersLeft: number; + /** + * The width of the line numbers. + */ + lineNumbersWidth: number; + /** + * The height of the line numbers. + */ + lineNumbersHeight: number; + /** + * Left position for the line decorations. + */ + decorationsLeft: number; + /** + * The width of the line decorations. + */ + decorationsWidth: number; + /** + * The height of the line decorations. + */ + decorationsHeight: number; + /** + * Left position for the content (actual text) + */ + contentLeft: number; + /** + * The width of the content (actual text) + */ + contentWidth: number; + /** + * The height of the content (actual height) + */ + contentHeight: number; + /** + * The width of the vertical scrollbar. + */ + verticalScrollbarWidth: number; + /** + * The height of the horizontal scrollbar. + */ + horizontalScrollbarHeight: number; + /** + * The position of the overview ruler. + */ + overviewRuler: OverviewRulerPosition; + constructor(source: { + width: number; + height: number; + glyphMarginLeft: number; + glyphMarginWidth: number; + glyphMarginHeight: number; + lineNumbersLeft: number; + lineNumbersWidth: number; + lineNumbersHeight: number; + decorationsLeft: number; + decorationsWidth: number; + decorationsHeight: number; + contentLeft: number; + contentWidth: number; + contentHeight: number; + verticalScrollbarWidth: number; + horizontalScrollbarHeight: number; + overviewRuler: OverviewRulerPosition; + }); + equals(other: EditorLayoutInfo): boolean; + clone(): EditorLayoutInfo; + } + + /** + * Options for creating the editor. + */ + export interface ICodeEditorWidgetCreationOptions extends IEditorOptions { + model?: IModel; + } + + /** + * An editor model. + */ + export interface IEditorModel { + } + + /** + * An editor view state. + */ + export interface IEditorViewState { + } + + export interface IDimension { + width: number; + height: number; + } + + /** + * Conditions describing action enablement + */ + export interface IActionEnablement { + /** + * The action is enabled only if text in the editor is focused (e.g. blinking cursor). + * Warning: This condition will be disabled if the action is marked to be displayed in the context menu + * Defaults to false. + */ + textFocus?: boolean; + /** + * The action is enabled only if the editor or its widgets have focus (e.g. focus is in find widget). + * Defaults to false. + */ + widgetFocus?: boolean; + /** + * The action is enabled only if the editor is not in read only mode. + * Defaults to false. + */ + writeableEditor?: boolean; + /** + * The action is enabled only if the cursor position is over tokens of a certain kind. + * Defaults to no tokens required. + */ + tokensAtPosition?: string[]; + /** + * The action is enabled only if the cursor position is over a word (i.e. not whitespace). + * Defaults to false. + */ + wordAtPosition?: boolean; + } + + /** + * A (serializable) state of the cursors. + */ + export interface ICursorState { + inSelectionMode: boolean; + selectionStart: IPosition; + position: IPosition; + } + + /** + * A (serializable) state of the view. + */ + export interface IViewState { + scrollTop: number; + scrollTopWithoutViewZones: number; + scrollLeft: number; + } + + /** + * A (serializable) state of the code editor. + */ + export interface ICodeEditorViewState extends IEditorViewState { + cursorState: ICursorState[]; + viewState: IViewState; + contributionsState: { + [id: string]: any; + }; + } + + /** + * Type of hit element with the mouse in the editor. + */ + export enum MouseTargetType { + /** + * Mouse is on top of an unknown element. + */ + UNKNOWN = 0, + /** + * Mouse is on top of the textarea used for input. + */ + TEXTAREA = 1, + /** + * Mouse is on top of the glyph margin + */ + GUTTER_GLYPH_MARGIN = 2, + /** + * Mouse is on top of the line numbers + */ + GUTTER_LINE_NUMBERS = 3, + /** + * Mouse is on top of the line decorations + */ + GUTTER_LINE_DECORATIONS = 4, + /** + * Mouse is on top of the whitespace left in the gutter by a view zone. + */ + GUTTER_VIEW_ZONE = 5, + /** + * Mouse is on top of text in the content. + */ + CONTENT_TEXT = 6, + /** + * Mouse is on top of empty space in the content (e.g. after line text or below last line) + */ + CONTENT_EMPTY = 7, + /** + * Mouse is on top of a view zone in the content. + */ + CONTENT_VIEW_ZONE = 8, + /** + * Mouse is on top of a content widget. + */ + CONTENT_WIDGET = 9, + /** + * Mouse is on top of the decorations overview ruler. + */ + OVERVIEW_RULER = 10, + /** + * Mouse is on top of a scrollbar. + */ + SCROLLBAR = 11, + /** + * Mouse is on top of an overlay widget. + */ + OVERLAY_WIDGET = 12, + } + + /** + * A model for the diff editor. + */ + export interface IDiffEditorModel extends IEditorModel { + /** + * Original model. + */ + original: IModel; + /** + * Modified model. + */ + modified: IModel; + } + + /** + * (Serializable) View state for the diff editor. + */ + export interface IDiffEditorViewState extends IEditorViewState { + original: ICodeEditorViewState; + modified: ICodeEditorViewState; + } + + /** + * A change + */ + export interface IChange { + originalStartLineNumber: number; + originalEndLineNumber: number; + modifiedStartLineNumber: number; + modifiedEndLineNumber: number; + } + + /** + * A character level change. + */ + export interface ICharChange extends IChange { + originalStartColumn: number; + originalEndColumn: number; + modifiedStartColumn: number; + modifiedEndColumn: number; + } + + /** + * A line change + */ + export interface ILineChange extends IChange { + charChanges: ICharChange[]; + } + + export const KEYBINDING_CONTEXT_EDITOR_TEXT_FOCUS: string; + + export const KEYBINDING_CONTEXT_EDITOR_FOCUS: string; + + export const KEYBINDING_CONTEXT_EDITOR_HAS_MULTIPLE_SELECTIONS: string; + + export const KEYBINDING_CONTEXT_EDITOR_HAS_NON_EMPTY_SELECTION: string; + + export const KEYBINDING_CONTEXT_EDITOR_LANGUAGE_ID: string; + + export class BareFontInfo { + _bareFontInfoBrand: void; + fontFamily: string; + fontSize: number; + lineHeight: number; + constructor(opts: { + fontFamily: string; + fontSize: number; + lineHeight: number; + }); + getId(): string; + } + + export class FontInfo extends BareFontInfo { + _editorStylingBrand: void; + typicalHalfwidthCharacterWidth: number; + typicalFullwidthCharacterWidth: number; + spaceWidth: number; + maxDigitWidth: number; + constructor(opts: { + fontFamily: string; + fontSize: number; + lineHeight: number; + typicalHalfwidthCharacterWidth: number; + typicalFullwidthCharacterWidth: number; + spaceWidth: number; + maxDigitWidth: number; + }); + equals(other: FontInfo): boolean; + clone(): FontInfo; + } + + export interface INewScrollPosition { + scrollLeft?: number; + scrollTop?: number; + } + + /** + * Description of an action contribution + */ + export interface IActionDescriptor { + /** + * An unique identifier of the contributed action. + */ + id: string; + /** + * A label of the action that will be presented to the user. + */ + label: string; + /** + * An array of keybindings for the action. + */ + keybindings?: number[]; + keybindingContext?: string; + /** + * A set of enablement conditions. + */ + enablement?: IActionEnablement; + /** + * Control if the action should show up in the context menu and where. + * Built-in groups: + * 1_goto/* => e.g. 1_goto/1_peekDefinition + * 2_change/* => e.g. 2_change/2_format + * 3_edit/* => e.g. 3_edit/1_copy + * 4_tools/* => e.g. 4_tools/1_commands + * You can also create your own group. + * Defaults to null (don't show in context menu). + */ + contextMenuGroupId?: string; + /** + * Method that will be executed when the action is triggered. + * @param editor The editor instance is passed in as a convinience + */ + run: (editor: ICommonCodeEditor) => TPromise; + } + + /** + * An editor. + */ + export interface IEditor { + onDidChangeModelRawContent(listener: (e: IModelContentChangedEvent) => void): IDisposable; + onDidChangeModelContent(listener: (e: IModelContentChangedEvent2) => void): IDisposable; + onDidChangeModelMode(listener: (e: IModelModeChangedEvent) => void): IDisposable; + onDidChangeModelOptions(listener: (e: IModelOptionsChangedEvent) => void): IDisposable; + onDidChangeConfiguration(listener: (e: IConfigurationChangedEvent) => void): IDisposable; + onDidChangeCursorPosition(listener: (e: ICursorPositionChangedEvent) => void): IDisposable; + onDidChangeCursorSelection(listener: (e: ICursorSelectionChangedEvent) => void): IDisposable; + onDidDispose(listener: () => void): IDisposable; + dispose(): void; + getId(): string; + /** + * Get the editor type. Current supported types: + * EditorCommon.EditorType.ICodeEditor => ICodeEditor; + * EditorCommon.EditorType.IDiffEditor => IDiffEditor; + * This is to avoid an instanceof check + */ + getEditorType(): string; + /** + * Update the editor's options after the editor has been created. + */ + updateOptions(newOptions: IEditorOptions): void; + /** + * Instructs the editor to remeasure its container. This method should + * be called when the container of the editor gets resized. + */ + layout(dimension?: IDimension): void; + /** + * Brings browser focus to the editor text + */ + focus(): void; + /** + * Returns true if this editor has keyboard focus (e.g. cursor is blinking). + */ + isFocused(): boolean; + /** + * Add a new action to this editor. + */ + addAction(descriptor: IActionDescriptor): void; + /** + * Returns all actions associated with this editor. + */ + getActions(): IAction[]; + /** + * Saves current view state of the editor in a serializable object. + */ + saveViewState(): IEditorViewState; + /** + * Restores the view state of the editor from a serializable object generated by `saveViewState`. + */ + restoreViewState(state: IEditorViewState): void; + /** + * Given a position, returns a column number that takes tab-widths into account. + */ + getVisibleColumnFromPosition(position: IPosition): number; + /** + * Returns the primary position of the cursor. + */ + getPosition(): Position; + /** + * Set the primary position of the cursor. This will remove any secondary cursors. + * @param position New primary cursor's position + */ + setPosition(position: IPosition): void; + /** + * Scroll vertically as necessary and reveal a line. + */ + revealLine(lineNumber: number): void; + /** + * Scroll vertically as necessary and reveal a line centered vertically. + */ + revealLineInCenter(lineNumber: number): void; + /** + * Scroll vertically as necessary and reveal a line centered vertically only if it lies outside the viewport. + */ + revealLineInCenterIfOutsideViewport(lineNumber: number): void; + /** + * Scroll vertically or horizontally as necessary and reveal a position. + */ + revealPosition(position: IPosition): void; + /** + * Scroll vertically or horizontally as necessary and reveal a position centered vertically. + */ + revealPositionInCenter(position: IPosition): void; + /** + * Scroll vertically or horizontally as necessary and reveal a position centered vertically only if it lies outside the viewport. + */ + revealPositionInCenterIfOutsideViewport(position: IPosition): void; + /** + * Returns the primary selection of the editor. + */ + getSelection(): Selection; + /** + * Returns all the selections of the editor. + */ + getSelections(): Selection[]; + /** + * Set the primary selection of the editor. This will remove any secondary cursors. + * @param selection The new selection + */ + setSelection(selection: IRange): void; + setSelection(selection: Range): void; + setSelection(selection: ISelection): void; + setSelection(selection: Selection): void; + /** + * Set the selections for all the cursors of the editor. + * Cursors will be removed or added, as necessary. + */ + setSelections(selections: ISelection[]): void; + /** + * Scroll vertically as necessary and reveal lines. + */ + revealLines(startLineNumber: number, endLineNumber: number): void; + /** + * Scroll vertically as necessary and reveal lines centered vertically. + */ + revealLinesInCenter(lineNumber: number, endLineNumber: number): void; + /** + * Scroll vertically as necessary and reveal lines centered vertically only if it lies outside the viewport. + */ + revealLinesInCenterIfOutsideViewport(lineNumber: number, endLineNumber: number): void; + /** + * Scroll vertically or horizontally as necessary and reveal a range. + */ + revealRange(range: IRange): void; + /** + * Scroll vertically or horizontally as necessary and reveal a range centered vertically. + */ + revealRangeInCenter(range: IRange): void; + /** + * Scroll vertically or horizontally as necessary and reveal a range centered vertically only if it lies outside the viewport. + */ + revealRangeInCenterIfOutsideViewport(range: IRange): void; + /** + * Directly trigger a handler or an editor action. + * @param source The source of the call. + * @param handlerId The id of the handler or the id of a contribution. + * @param payload Extra data to be sent to the handler. + */ + trigger(source: string, handlerId: string, payload: any): void; + /** + * Gets the current model attached to this editor. + */ + getModel(): IEditorModel; + /** + * Sets the current model attached to this editor. + * If the previous model was created by the editor via the value key in the options + * literal object, it will be destroyed. Otherwise, if the previous model was set + * via setModel, or the model key in the options literal object, the previous model + * will not be destroyed. + * It is safe to call setModel(null) to simply detach the current model from the editor. + */ + setModel(model: IEditorModel): void; + } + + /** + * An editor contribution that gets created every time a new editor gets created and gets disposed when the editor gets disposed. + */ + export interface IEditorContribution { + /** + * Get a unique identifier for this contribution. + */ + getId(): string; + /** + * Dispose this contribution. + */ + dispose(): void; + /** + * Store view state. + */ + saveViewState?(): any; + /** + * Restore view state. + */ + restoreViewState?(state: any): void; + } + + export interface ICommonCodeEditor extends IEditor { + onDidChangeModel(listener: (e: IModelChangedEvent) => void): IDisposable; + onDidChangeModelModeSupport(listener: (e: IModeSupportChangedEvent) => void): IDisposable; + onDidChangeModelDecorations(listener: (e: IModelDecorationsChangedEvent) => void): IDisposable; + onDidFocusEditorText(listener: () => void): IDisposable; + onDidBlurEditorText(listener: () => void): IDisposable; + onDidFocusEditor(listener: () => void): IDisposable; + onDidBlurEditor(listener: () => void): IDisposable; + /** + * Returns true if this editor or one of its widgets has keyboard focus. + */ + hasWidgetFocus(): boolean; + /** + * Get a contribution of this editor. + * @id Unique identifier of the contribution. + * @return The contribution or null if contribution not found. + */ + getContribution(id: string): IEditorContribution; + /** + * Type the getModel() of IEditor. + */ + getModel(): IModel; + /** + * Returns the current editor's configuration + */ + getConfiguration(): InternalEditorOptions; + /** + * Get value of the current model attached to this editor. + * @see IModel.getValue + */ + getValue(options?: { + preserveBOM: boolean; + lineEnding: string; + }): string; + /** + * Set the value of the current model attached to this editor. + * @see IModel.setValue + */ + setValue(newValue: string): void; + /** + * Get the scrollWidth of the editor's viewport. + */ + getScrollWidth(): number; + /** + * Get the scrollLeft of the editor's viewport. + */ + getScrollLeft(): number; + /** + * Get the scrollHeight of the editor's viewport. + */ + getScrollHeight(): number; + /** + * Get the scrollTop of the editor's viewport. + */ + getScrollTop(): number; + /** + * Change the scrollLeft of the editor's viewport. + */ + setScrollLeft(newScrollLeft: number): void; + /** + * Change the scrollTop of the editor's viewport. + */ + setScrollTop(newScrollTop: number): void; + /** + * Change the scroll position of the editor's viewport. + */ + setScrollPosition(position: INewScrollPosition): void; + /** + * Get an action that is a contribution to this editor. + * @id Unique identifier of the contribution. + * @return The action or null if action not found. + */ + getAction(id: string): IAction; + /** + * Execute a command on the editor. + * @param source The source of the call. + * @param command The command to execute + */ + executeCommand(source: string, command: ICommand): void; + /** + * Execute a command on the editor. + * @param source The source of the call. + * @param command The command to execute + */ + executeEdits(source: string, edits: IIdentifiedSingleEditOperation[]): boolean; + /** + * Execute multiple (concommitent) commands on the editor. + * @param source The source of the call. + * @param command The commands to execute + */ + executeCommands(source: string, commands: ICommand[]): void; + /** + * Get all the decorations on a line (filtering out decorations from other editors). + */ + getLineDecorations(lineNumber: number): IModelDecoration[]; + /** + * All decorations added through this call will get the ownerId of this editor. + * @see IModel.deltaDecorations + */ + deltaDecorations(oldDecorations: string[], newDecorations: IModelDeltaDecoration[]): string[]; + /** + * Get the layout info for the editor. + */ + getLayoutInfo(): EditorLayoutInfo; + } + + export interface ICommonDiffEditor extends IEditor { + onDidUpdateDiff(listener: () => void): IDisposable; + /** + * Type the getModel() of IEditor. + */ + getModel(): IDiffEditorModel; + getOriginalEditor(): ICommonCodeEditor; + getModifiedEditor(): ICommonCodeEditor; + getLineChanges(): ILineChange[]; + /** + * @see ICodeEditor.getValue + */ + getValue(options?: { + preserveBOM: boolean; + lineEnding: string; + }): string; + } + + export var EditorType: { + ICodeEditor: string; + IDiffEditor: string; + }; + + export var EventType: { + Disposed: string; + ConfigurationChanged: string; + ModelDispose: string; + ModelChanged: string; + ModelTokensChanged: string; + ModelModeChanged: string; + ModelModeSupportChanged: string; + ModelOptionsChanged: string; + ModelRawContentChanged: string; + ModelContentChanged2: string; + ModelRawContentChangedFlush: string; + ModelRawContentChangedLinesDeleted: string; + ModelRawContentChangedLinesInserted: string; + ModelRawContentChangedLineChanged: string; + EditorTextBlur: string; + EditorTextFocus: string; + EditorFocus: string; + EditorBlur: string; + ModelDecorationsChanged: string; + CursorPositionChanged: string; + CursorSelectionChanged: string; + CursorRevealRange: string; + CursorScrollRequest: string; + ViewFocusGained: string; + ViewFocusLost: string; + ViewFocusChanged: string; + ViewScrollChanged: string; + ViewZonesChanged: string; + ViewLayoutChanged: string; + ContextMenu: string; + MouseDown: string; + MouseUp: string; + MouseMove: string; + MouseLeave: string; + KeyDown: string; + KeyUp: string; + EditorLayout: string; + DiffUpdated: string; + }; + + export var Handler: { + ExecuteCommand: string; + ExecuteCommands: string; + CursorLeft: string; + CursorLeftSelect: string; + CursorWordLeft: string; + CursorWordStartLeft: string; + CursorWordEndLeft: string; + CursorWordLeftSelect: string; + CursorWordStartLeftSelect: string; + CursorWordEndLeftSelect: string; + CursorRight: string; + CursorRightSelect: string; + CursorWordRight: string; + CursorWordStartRight: string; + CursorWordEndRight: string; + CursorWordRightSelect: string; + CursorWordStartRightSelect: string; + CursorWordEndRightSelect: string; + CursorUp: string; + CursorUpSelect: string; + CursorDown: string; + CursorDownSelect: string; + CursorPageUp: string; + CursorPageUpSelect: string; + CursorPageDown: string; + CursorPageDownSelect: string; + CursorHome: string; + CursorHomeSelect: string; + CursorEnd: string; + CursorEndSelect: string; + ExpandLineSelection: string; + CursorTop: string; + CursorTopSelect: string; + CursorBottom: string; + CursorBottomSelect: string; + CursorColumnSelectLeft: string; + CursorColumnSelectRight: string; + CursorColumnSelectUp: string; + CursorColumnSelectPageUp: string; + CursorColumnSelectDown: string; + CursorColumnSelectPageDown: string; + AddCursorDown: string; + AddCursorUp: string; + CursorUndo: string; + MoveTo: string; + MoveToSelect: string; + ColumnSelect: string; + CreateCursor: string; + LastCursorMoveToSelect: string; + JumpToBracket: string; + Type: string; + ReplacePreviousChar: string; + Paste: string; + Tab: string; + Indent: string; + Outdent: string; + DeleteLeft: string; + DeleteRight: string; + DeleteWordLeft: string; + DeleteWordStartLeft: string; + DeleteWordEndLeft: string; + DeleteWordRight: string; + DeleteWordStartRight: string; + DeleteWordEndRight: string; + DeleteAllLeft: string; + DeleteAllRight: string; + RemoveSecondaryCursors: string; + CancelSelection: string; + Cut: string; + Undo: string; + Redo: string; + WordSelect: string; + WordSelectDrag: string; + LastCursorWordSelect: string; + LineSelect: string; + LineSelectDrag: string; + LastCursorLineSelect: string; + LastCursorLineSelectDrag: string; + LineInsertBefore: string; + LineInsertAfter: string; + LineBreakInsert: string; + SelectAll: string; + ScrollLineUp: string; + ScrollLineDown: string; + ScrollPageUp: string; + ScrollPageDown: string; + }; + + export enum TextEditorCursorStyle { + Line = 1, + Block = 2, + Underline = 3, + } + + + /** + * A view zone is a full horizontal rectangle that 'pushes' text down. + * The editor reserves space for view zones when rendering. + */ + export interface IViewZone { + /** + * The line number after which this zone should appear. + * Use 0 to place a view zone before the first line number. + */ + afterLineNumber: number; + /** + * The column after which this zone should appear. + * If not set, the maxLineColumn of `afterLineNumber` will be used. + */ + afterColumn?: number; + /** + * Suppress mouse down events. + * If set, the editor will attach a mouse down listener to the view zone and .preventDefault on it. + * Defaults to false + */ + suppressMouseDown?: boolean; + /** + * The height in lines of the view zone. + * If specified, `heightInPx` will be used instead of this. + * If neither `heightInPx` nor `heightInLines` is specified, a default of `heightInLines` = 1 will be chosen. + */ + heightInLines?: number; + /** + * The height in px of the view zone. + * If this is set, the editor will give preference to it rather than `heightInLines` above. + * If neither `heightInPx` nor `heightInLines` is specified, a default of `heightInLines` = 1 will be chosen. + */ + heightInPx?: number; + /** + * The dom node of the view zone + */ + domNode: HTMLElement; + /** + * Callback which gives the relative top of the view zone as it appears (taking scrolling into account). + */ + onDomNodeTop?: (top: number) => void; + /** + * Callback which gives the height in pixels of the view zone. + */ + onComputedHeight?: (height: number) => void; + } + + /** + * An accessor that allows for zones to be added or removed. + */ + export interface IViewZoneChangeAccessor { + /** + * Create a new view zone. + * @param zone Zone to create + * @return A unique identifier to the view zone. + */ + addZone(zone: IViewZone): number; + /** + * Remove a zone + * @param id A unique identifier to the view zone, as returned by the `addZone` call. + */ + removeZone(id: number): void; + /** + * Change a zone's position. + * The editor will rescan the `afterLineNumber` and `afterColumn` properties of a view zone. + */ + layoutZone(id: number): void; + } + + /** + * A positioning preference for rendering content widgets. + */ + export enum ContentWidgetPositionPreference { + /** + * Place the content widget exactly at a position + */ + EXACT = 0, + /** + * Place the content widget above a position + */ + ABOVE = 1, + /** + * Place the content widget below a position + */ + BELOW = 2, + } + + /** + * A position for rendering content widgets. + */ + export interface IContentWidgetPosition { + /** + * Desired position for the content widget. + * `preference` will also affect the placement. + */ + position: IPosition; + /** + * Placement preference for position, in order of preference. + */ + preference: ContentWidgetPositionPreference[]; + } + + /** + * A content widget renders inline with the text and can be easily placed 'near' an editor position. + */ + export interface IContentWidget { + /** + * Render this content widget in a location where it could overflow the editor's view dom node. + */ + allowEditorOverflow?: boolean; + /** + * Get a unique identifier of the content widget. + */ + getId(): string; + /** + * Get the dom node of the content widget. + */ + getDomNode(): HTMLElement; + /** + * Get the placement of the content widget. + * If null is returned, the content widget will be placed off screen. + */ + getPosition(): IContentWidgetPosition; + } + + /** + * A positioning preference for rendering overlay widgets. + */ + export enum OverlayWidgetPositionPreference { + /** + * Position the overlay widget in the top right corner + */ + TOP_RIGHT_CORNER = 0, + /** + * Position the overlay widget in the bottom right corner + */ + BOTTOM_RIGHT_CORNER = 1, + /** + * Position the overlay widget in the top center + */ + TOP_CENTER = 2, + } + + /** + * A position for rendering overlay widgets. + */ + export interface IOverlayWidgetPosition { + /** + * The position preference for the overlay widget. + */ + preference: OverlayWidgetPositionPreference; + } + + /** + * An overlay widgets renders on top of the text. + */ + export interface IOverlayWidget { + /** + * Get a unique identifier of the overlay widget. + */ + getId(): string; + /** + * Get the dom node of the overlay widget. + */ + getDomNode(): HTMLElement; + /** + * Get the placement of the overlay widget. + * If null is returned, the overlay widget is responsible to place itself. + */ + getPosition(): IOverlayWidgetPosition; + } + + /** + * Target hit with the mouse in the editor. + */ + export interface IMouseTarget { + /** + * The target element + */ + element: Element; + /** + * The target type + */ + type: MouseTargetType; + /** + * The 'approximate' editor position + */ + position: Position; + /** + * Desired mouse column (e.g. when position.column gets clamped to text length -- clicking after text on a line). + */ + mouseColumn: number; + /** + * The 'approximate' editor range + */ + range: Range; + /** + * Some extra detail. + */ + detail: any; + } + + /** + * A mouse event originating from the editor. + */ + export interface IEditorMouseEvent { + event: IMouseEvent; + target: IMouseTarget; + } + + /** + * A rich code editor. + */ + export interface ICodeEditor extends ICommonCodeEditor { + onMouseUp(listener: (e: IEditorMouseEvent) => void): IDisposable; + onMouseDown(listener: (e: IEditorMouseEvent) => void): IDisposable; + onContextMenu(listener: (e: IEditorMouseEvent) => void): IDisposable; + onMouseMove(listener: (e: IEditorMouseEvent) => void): IDisposable; + onMouseLeave(listener: (e: IEditorMouseEvent) => void): IDisposable; + onKeyUp(listener: (e: IKeyboardEvent) => void): IDisposable; + onKeyDown(listener: (e: IKeyboardEvent) => void): IDisposable; + onDidLayoutChange(listener: (e: EditorLayoutInfo) => void): IDisposable; + onDidScrollChange(listener: (e: IScrollEvent) => void): IDisposable; + /** + * Returns the editor's dom node + */ + getDomNode(): HTMLElement; + /** + * Add a content widget. Widgets must have unique ids, otherwise they will be overwritten. + */ + addContentWidget(widget: IContentWidget): void; + /** + * Layout/Reposition a content widget. This is a ping to the editor to call widget.getPosition() + * and update appropiately. + */ + layoutContentWidget(widget: IContentWidget): void; + /** + * Remove a content widget. + */ + removeContentWidget(widget: IContentWidget): void; + /** + * Add an overlay widget. Widgets must have unique ids, otherwise they will be overwritten. + */ + addOverlayWidget(widget: IOverlayWidget): void; + /** + * Layout/Reposition an overlay widget. This is a ping to the editor to call widget.getPosition() + * and update appropiately. + */ + layoutOverlayWidget(widget: IOverlayWidget): void; + /** + * Remove an overlay widget. + */ + removeOverlayWidget(widget: IOverlayWidget): void; + /** + * Change the view zones. View zones are lost when a new model is attached to the editor. + */ + changeViewZones(callback: (accessor: IViewZoneChangeAccessor) => void): void; + /** + * Returns the range that is currently centered in the view port. + */ + getCenteredRangeInViewport(): Range; + /** + * Get the horizontal position (left offset) for the column w.r.t to the beginning of the line. + * This method works only if the line `lineNumber` is currently rendered (in the editor's viewport). + * Use this method with caution. + */ + getOffsetForColumn(lineNumber: number, column: number): number; + /** + * Force an editor render now. + */ + render(): void; + /** + * Get the vertical position (top offset) for the line w.r.t. to the first line. + */ + getTopForLineNumber(lineNumber: number): number; + /** + * Get the vertical position (top offset) for the position w.r.t. to the first line. + */ + getTopForPosition(lineNumber: number, column: number): number; + /** + * Get the visible position for `position`. + * The result position takes scrolling into account and is relative to the top left corner of the editor. + * Explanation 1: the results of this method will change for the same `position` if the user scrolls the editor. + * Explanation 2: the results of this method will not change if the container of the editor gets repositioned. + * Warning: the results of this method are innacurate for positions that are outside the current editor viewport. + */ + getScrolledVisiblePosition(position: IPosition): { + top: number; + left: number; + height: number; + }; + /** + * Apply the same font settings as the editor to `target`. + */ + applyFontInfo(target: HTMLElement): void; + } + + /** + * A rich diff editor. + */ + export interface IDiffEditor extends ICommonDiffEditor { + /** + * @see ICodeEditor.getDomNode + */ + getDomNode(): HTMLElement; + } + +} \ No newline at end of file diff --git a/build/lib/monaco-editor.d.ts.recipe b/build/lib/monaco-editor.d.ts.recipe new file mode 100644 index 00000000000..6bec60236b9 --- /dev/null +++ b/build/lib/monaco-editor.d.ts.recipe @@ -0,0 +1,92 @@ + +declare module monaco.editor { + + export function create(domElement: HTMLElement, options: IEditorConstructionOptions, services?: any): ICodeEditor; + export function createDiffEditor(domElement: HTMLElement, options: IDiffEditorConstructionOptions, services?: any): IDiffEditor; + export function createModel(value:string, mode:string|ILanguage|IMode, associatedResource?:any|string): IModel; + export function getOrCreateMode(modeId: string): TPromise; + export function createCustomMode(description:ILanguage): TPromise; + export function colorize(text: string, modeId: string, options: IColorizerOptions): TPromise; + export function colorizeElement(domNode: HTMLElement, options: IColorizerElementOptions): TPromise; +// export function colorizeLine(line: string, tokens: ViewLineToken[], tabSize?: number): string; + export function colorizeModelLine(model: IModel, lineNumber: number, tabSize?: number): string; + export function registerWorkerParticipant(modeId:string, moduleName:string, ctorName:string): void; + export function configureMode(modeId: string, options: any): void; + + export interface IColorizerOptions { + tabSize?: number; + } + + export interface IColorizerElementOptions extends IColorizerOptions { + theme?: string; + mimeType?: string; + } + + export interface IEditorConstructionOptions extends ICodeEditorWidgetCreationOptions { + value?: string; + /** + * A mode name (such as text/javascript, etc.) or an IMonarchLanguage + */ + mode?: any; + enableTelemetry?: boolean; + } + + export interface IDiffEditorConstructionOptions extends IDiffEditorOptions { + } +} + +declare module monaco { + + interface Thenable { + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: (value: R) => TResult | Thenable, onrejected?: (reason: any) => TResult | Thenable): Thenable; + then(onfulfilled?: (value: R) => TResult | Thenable, onrejected?: (reason: any) => void): Thenable; + } + + export interface IDisposable { + dispose(): void; + } + +#include(vs/base/common/winjs.base.d.ts): TValueCallback, ProgressCallback, TPromise + +#include(vs/base/common/uri): URI + +#include(vs/base/common/eventEmitter): EmitterEvent, BulkListenerCallback + +#include(vs/base/common/keyCodes): KeyCode, KeyMod + +#include(vs/base/common/htmlContent): IHTMLContentElementCode, IHTMLContentElement + +#include(vs/base/common/actions): IAction + +#include(vs/base/browser/keyboardEvent): IKeyboardEvent +#include(vs/base/browser/mouseEvent): IMouseEvent +#include(vs/editor/common/editorCommon): IScrollEvent + +#include(vs/editor/common/editorCommon): IPosition, IRange, SelectionDirection, ISelection +#include(vs/editor/common/core/position): Position +#include(vs/editor/common/core/range): Range +#include(vs/editor/common/core/selection): Selection +} + + +declare module monaco.editor { + +#include(vs/editor/common/modes/monarch/monarchTypes): ILanguage, ILanguageBracket + + export interface IMode { + + } + +#include(vs/base/browser/ui/scrollbar/scrollableElementOptions): ScrollbarVisibility + +#includeAll(vs/editor/common/editorCommon): IPosition, IRange, ISelection, SelectionDirection, IScrollEvent + +#includeAll(vs/editor/browser/editorBrowser): + +} \ No newline at end of file diff --git a/build/lib/monaco.js b/build/lib/monaco.js new file mode 100644 index 00000000000..cd1f3484393 --- /dev/null +++ b/build/lib/monaco.js @@ -0,0 +1,242 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +"use strict"; +// PREREQUISITE: +// SET VSCODE_BUILD_DECLARATION_FILES=1 +// run gulp watch once +var fs = require('fs'); +var ts = require('typescript'); +var path = require('path'); +var SRC = path.join(__dirname, '../../src'); +var OUT = path.join(__dirname, '../../out'); +function moduleIdToPath(moduleId) { + if (/\.d\.ts/.test(moduleId)) { + return path.join(SRC, moduleId); + } + return path.join(OUT, moduleId) + '.d.ts'; +} +var SOURCE_FILE_MAP = {}; +function getSourceFile(moduleId) { + if (!SOURCE_FILE_MAP[moduleId]) { + var filePath = moduleIdToPath(moduleId); + var fileContents = fs.readFileSync(filePath).toString(); + var sourceFile = ts.createSourceFile(filePath, fileContents, ts.ScriptTarget.ES5); + SOURCE_FILE_MAP[moduleId] = sourceFile; + } + return SOURCE_FILE_MAP[moduleId]; +} +function isDeclaration(a) { + return (a.kind === ts.SyntaxKind.InterfaceDeclaration + || a.kind === ts.SyntaxKind.EnumDeclaration + || a.kind === ts.SyntaxKind.ClassDeclaration + || a.kind === ts.SyntaxKind.TypeAliasDeclaration + || a.kind === ts.SyntaxKind.FunctionDeclaration); +} +function visitTopLevelDeclarations(sourceFile, visitor) { + var stop = false; + var visit = function (node) { + if (stop) { + return; + } + switch (node.kind) { + case ts.SyntaxKind.InterfaceDeclaration: + case ts.SyntaxKind.EnumDeclaration: + case ts.SyntaxKind.ClassDeclaration: + case ts.SyntaxKind.VariableStatement: + case ts.SyntaxKind.TypeAliasDeclaration: + case ts.SyntaxKind.FunctionDeclaration: + stop = visitor(node); + } + // if (node.kind !== ts.SyntaxKind.SourceFile) { + // if (getNodeText(sourceFile, node).indexOf('Handler') >= 0) { + // console.log('FOUND TEXT IN NODE: ' + ts.SyntaxKind[node.kind]); + // console.log(getNodeText(sourceFile, node)); + // } + // } + if (stop) { + return; + } + ts.forEachChild(node, visit); + }; + visit(sourceFile); +} +function getAllTopLevelDeclarations(sourceFile) { + var all = []; + visitTopLevelDeclarations(sourceFile, function (node) { + if (node.kind === ts.SyntaxKind.InterfaceDeclaration) { + var interfaceDeclaration = node; + var triviaStart = interfaceDeclaration.pos; + var triviaEnd = interfaceDeclaration.name.pos; + var triviaText = getNodeText(sourceFile, { pos: triviaStart, end: triviaEnd }); + if (triviaText.indexOf('@internal') === -1) { + all.push(node); + } + } + else { + var nodeText = getNodeText(sourceFile, node); + if (nodeText.indexOf('@internal') === -1) { + all.push(node); + } + } + return false /*continue*/; + }); + return all; +} +function getTopLevelDeclaration(sourceFile, typeName) { + var result = null; + visitTopLevelDeclarations(sourceFile, function (node) { + if (isDeclaration(node)) { + if (node.name.text === typeName) { + result = node; + return true /*stop*/; + } + return false /*continue*/; + } + // node is ts.VariableStatement + if (getNodeText(sourceFile, node).indexOf(typeName) >= 0) { + result = node; + return true /*stop*/; + } + return false /*continue*/; + }); + if (result === null) { + console.log('COULD NOT FIND ' + typeName + '!'); + } + return result; +} +function getNodeText(sourceFile, node) { + return sourceFile.getFullText().substring(node.pos, node.end); +} +function getMassagedTopLevelDeclarationText(sourceFile, declaration) { + var result = getNodeText(sourceFile, declaration); + if (declaration.kind === ts.SyntaxKind.InterfaceDeclaration || declaration.kind === ts.SyntaxKind.ClassDeclaration) { + var interfaceDeclaration = declaration; + var members = interfaceDeclaration.members; + members.forEach(function (member) { + try { + var memberText = getNodeText(sourceFile, member); + if (memberText.indexOf('@internal') >= 0 || memberText.indexOf('private') >= 0) { + // console.log('BEFORE: ', result); + result = result.replace(memberText, ''); + } + } + catch (err) { + } + }); + } + result = result.replace(/export default/g, 'export'); + result = result.replace(/export declare/g, 'export'); + return result; +} +function format(text) { + var options = getDefaultOptions(); + // Parse the source text + var sourceFile = ts.createSourceFile('file.ts', text, ts.ScriptTarget.Latest, /*setParentPointers*/ true); + // Get the formatting edits on the input sources + var edits = ts.formatting.formatDocument(sourceFile, getRuleProvider(options), options); + // Apply the edits on the input code + return applyEdits(text, edits); + function getRuleProvider(options) { + // Share this between multiple formatters using the same options. + // This represents the bulk of the space the formatter uses. + var ruleProvider = new ts.formatting.RulesProvider(); + ruleProvider.ensureUpToDate(options); + return ruleProvider; + } + function applyEdits(text, edits) { + // Apply edits in reverse on the existing text + var result = text; + for (var i = edits.length - 1; i >= 0; i--) { + var change = edits[i]; + var head = result.slice(0, change.span.start); + var tail = result.slice(change.span.start + change.span.length); + result = head + change.newText + tail; + } + return result; + } + function getDefaultOptions() { + return { + IndentSize: 4, + TabSize: 4, + NewLineCharacter: '\r\n', + ConvertTabsToSpaces: true, + IndentStyle: ts.IndentStyle.Block, + InsertSpaceAfterCommaDelimiter: true, + InsertSpaceAfterSemicolonInForStatements: true, + InsertSpaceBeforeAndAfterBinaryOperators: true, + InsertSpaceAfterKeywordsInControlFlowStatements: true, + InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false, + InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, + InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: true, + PlaceOpenBraceOnNewLineForFunctions: false, + PlaceOpenBraceOnNewLineForControlBlocks: false, + }; + } +} +var recipe = fs.readFileSync(path.join(__dirname, './monaco-editor.d.ts.recipe')).toString(); +var lines = recipe.split(/\r\n|\n|\r/); +var result = []; +lines.forEach(function (line) { + var m1 = line.match(/^\s*#include\(([^\)]*)\)\:(.*)$/); + if (m1) { + console.log('HANDLING META: ' + line); + var moduleId = m1[1]; + var sourceFile_1 = getSourceFile(moduleId); + var typeNames = m1[2].split(/,/); + typeNames.forEach(function (typeName) { + typeName = typeName.trim(); + if (typeName.length === 0) { + return; + } + var declaration = getTopLevelDeclaration(sourceFile_1, typeName); + result.push(getMassagedTopLevelDeclarationText(sourceFile_1, declaration)); + }); + return; + } + var m2 = line.match(/^\s*#includeAll\(([^\)]*)\)\:(.*)$/); + if (m2) { + console.log('HANDLING META: ' + line); + var moduleId = m2[1]; + var sourceFile_2 = getSourceFile(moduleId); + var typeNames = m2[2].split(/,/); + var typesToExcludeMap_1 = {}; + var typesToExcludeArr_1 = []; + typeNames.forEach(function (typeName) { + typeName = typeName.trim(); + if (typeName.length === 0) { + return; + } + typesToExcludeMap_1[typeName] = true; + typesToExcludeArr_1.push(typeName); + }); + getAllTopLevelDeclarations(sourceFile_2).forEach(function (declaration) { + if (isDeclaration(declaration)) { + if (typesToExcludeMap_1[declaration.name.text]) { + return; + } + } + else { + // node is ts.VariableStatement + var nodeText = getNodeText(sourceFile_2, declaration); + for (var i = 0; i < typesToExcludeArr_1.length; i++) { + if (nodeText.indexOf(typesToExcludeArr_1[i]) >= 0) { + return; + } + } + } + result.push(getMassagedTopLevelDeclarationText(sourceFile_2, declaration)); + }); + return; + } + result.push(line); +}); +var resultTxt = result.join('\n'); +resultTxt = resultTxt.replace(/\beditorCommon\./g, ''); +resultTxt = resultTxt.replace(/\bEventboolean): void { + let stop = false; + + let visit = (node: ts.Node): void => { + if (stop) { + return; + } + + switch (node.kind) { + case ts.SyntaxKind.InterfaceDeclaration: + case ts.SyntaxKind.EnumDeclaration: + case ts.SyntaxKind.ClassDeclaration: + case ts.SyntaxKind.VariableStatement: + case ts.SyntaxKind.TypeAliasDeclaration: + case ts.SyntaxKind.FunctionDeclaration: + stop = visitor(node); + } + + // if (node.kind !== ts.SyntaxKind.SourceFile) { + // if (getNodeText(sourceFile, node).indexOf('Handler') >= 0) { + // console.log('FOUND TEXT IN NODE: ' + ts.SyntaxKind[node.kind]); + // console.log(getNodeText(sourceFile, node)); + // } + // } + + if (stop) { + return; + } + ts.forEachChild(node, visit); + }; + + visit(sourceFile); +} + + +function getAllTopLevelDeclarations(sourceFile:ts.SourceFile): TSTopLevelDeclare[] { + let all:TSTopLevelDeclare[] = []; + visitTopLevelDeclarations(sourceFile, (node) => { + if (node.kind === ts.SyntaxKind.InterfaceDeclaration) { + let interfaceDeclaration = node; + let triviaStart = interfaceDeclaration.pos; + let triviaEnd = interfaceDeclaration.name.pos; + let triviaText = getNodeText(sourceFile, { pos: triviaStart, end: triviaEnd }); + if (triviaText.indexOf('@internal') === -1) { + all.push(node); + } + } else { + let nodeText = getNodeText(sourceFile, node); + if (nodeText.indexOf('@internal') === -1) { + all.push(node); + } + } + return false /*continue*/; + }); + return all; +} + + +function getTopLevelDeclaration(sourceFile:ts.SourceFile, typeName:string): TSTopLevelDeclare { + let result:TSTopLevelDeclare = null; + visitTopLevelDeclarations(sourceFile, (node) => { + if (isDeclaration(node)) { + if (node.name.text === typeName) { + result = node; + return true /*stop*/; + } + return false /*continue*/; + } + // node is ts.VariableStatement + if (getNodeText(sourceFile, node).indexOf(typeName) >= 0) { + result = node; + return true /*stop*/; + } + return false /*continue*/; + }); + if (result === null) { + console.log('COULD NOT FIND ' + typeName + '!'); + } + return result; +} + + +function getNodeText(sourceFile:ts.SourceFile, node:{pos:number; end:number;}): string { + return sourceFile.getFullText().substring(node.pos, node.end); +} + + +function getMassagedTopLevelDeclarationText(sourceFile:ts.SourceFile, declaration: TSTopLevelDeclare): string { + let result = getNodeText(sourceFile, declaration); + if (declaration.kind === ts.SyntaxKind.InterfaceDeclaration || declaration.kind === ts.SyntaxKind.ClassDeclaration) { + let interfaceDeclaration = declaration; + + let members:ts.NodeArray = interfaceDeclaration.members; + members.forEach((member) => { + try { + let memberText = getNodeText(sourceFile, member); + if (memberText.indexOf('@internal') >= 0 || memberText.indexOf('private') >= 0) { + // console.log('BEFORE: ', result); + result = result.replace(memberText, ''); + // console.log('AFTER: ', result); + } + } catch (err) { + // life.. + } + }); + } + result = result.replace(/export default/g, 'export'); + result = result.replace(/export declare/g, 'export'); + return result; +} + +function format(text:string): string { + let options = getDefaultOptions(); + + // Parse the source text + let sourceFile = ts.createSourceFile('file.ts', text, ts.ScriptTarget.Latest, /*setParentPointers*/ true); + + // Get the formatting edits on the input sources + let edits = (ts).formatting.formatDocument(sourceFile, getRuleProvider(options), options); + + // Apply the edits on the input code + return applyEdits(text, edits); + + function getRuleProvider(options: ts.FormatCodeOptions) { + // Share this between multiple formatters using the same options. + // This represents the bulk of the space the formatter uses. + let ruleProvider = new (ts).formatting.RulesProvider(); + ruleProvider.ensureUpToDate(options); + return ruleProvider; + } + + function applyEdits(text: string, edits: ts.TextChange[]): string { + // Apply edits in reverse on the existing text + let result = text; + for (let i = edits.length - 1; i >= 0; i--) { + let change = edits[i]; + let head = result.slice(0, change.span.start); + let tail = result.slice(change.span.start + change.span.length); + result = head + change.newText + tail; + } + return result; + } + + function getDefaultOptions(): ts.FormatCodeOptions { + return { + IndentSize: 4, + TabSize: 4, + NewLineCharacter: '\r\n', + ConvertTabsToSpaces: true, + IndentStyle: ts.IndentStyle.Block, + + InsertSpaceAfterCommaDelimiter: true, + InsertSpaceAfterSemicolonInForStatements: true, + InsertSpaceBeforeAndAfterBinaryOperators: true, + InsertSpaceAfterKeywordsInControlFlowStatements: true, + InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false, + InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, + InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: true, + PlaceOpenBraceOnNewLineForFunctions: false, + PlaceOpenBraceOnNewLineForControlBlocks: false, + }; + } +} + +var recipe = fs.readFileSync(path.join(__dirname, './monaco-editor.d.ts.recipe')).toString(); +var lines = recipe.split(/\r\n|\n|\r/); +var result = []; + +lines.forEach(line => { + + let m1 = line.match(/^\s*#include\(([^\)]*)\)\:(.*)$/); + if (m1) { + console.log('HANDLING META: ' + line); + let moduleId = m1[1]; + let sourceFile = getSourceFile(moduleId); + + let typeNames = m1[2].split(/,/); + typeNames.forEach((typeName) => { + typeName = typeName.trim(); + if (typeName.length === 0) { + return; + } + let declaration = getTopLevelDeclaration(sourceFile, typeName); + result.push(getMassagedTopLevelDeclarationText(sourceFile, declaration)); + }); + return; + } + + let m2 = line.match(/^\s*#includeAll\(([^\)]*)\)\:(.*)$/); + if (m2) { + console.log('HANDLING META: ' + line); + let moduleId = m2[1]; + let sourceFile = getSourceFile(moduleId); + + let typeNames = m2[2].split(/,/); + let typesToExcludeMap: {[typeName:string]:boolean;} = {}; + let typesToExcludeArr: string[] = []; + typeNames.forEach((typeName) => { + typeName = typeName.trim(); + if (typeName.length === 0) { + return; + } + typesToExcludeMap[typeName] = true; + typesToExcludeArr.push(typeName); + }); + + getAllTopLevelDeclarations(sourceFile).forEach((declaration) => { + if (isDeclaration(declaration)) { + if (typesToExcludeMap[declaration.name.text]) { + return; + } + } else { + // node is ts.VariableStatement + let nodeText = getNodeText(sourceFile, declaration); + for (let i = 0; i < typesToExcludeArr.length; i++) { + if (nodeText.indexOf(typesToExcludeArr[i]) >= 0) { + return; + } + } + } + result.push(getMassagedTopLevelDeclarationText(sourceFile, declaration)); + }); + return; + } + + result.push(line); +}); + +let resultTxt = result.join('\n'); +resultTxt = resultTxt.replace(/\beditorCommon\./g, ''); +resultTxt = resultTxt.replace(/\bEvent + + begin + (var)\s*(\() + beginCaptures + + 1 + + name + support.function.misc.css + + 2 + + name + punctuation.section.function.css + + + end + (\)) + endCaptures + + 1 + + name + punctuation.section.function.css + + + patterns + + + include + #variable-name + + + match \!\s*important @@ -797,6 +831,10 @@ meta.property-name.css patterns + + include + #variable-name + match (-(webkit|moz|o|ms|khtml)-)?(zoom|z-index|y|x|writing-mode|wrap|wrap-through|wrap-inside|wrap-flow|wrap-before|wrap-after|word-wrap|word-spacing|word-break|word|will-change|width|widows|white-space-collapse|white-space|white|weight|volume|voice-volume|voice-stress|voice-rate|voice-pitch-range|voice-pitch|voice-family|voice-duration|voice-balance|voice|visibility|vertical-align|vector-effect|variant|user-zoom|user-select|up|unicode-(bidi|range)|trim|translate|transition-timing-function|transition-property|transition-duration|transition-delay|transition|transform-style|transform-origin|transform-box|transform|touch-action|top-width|top-style|top-right-radius|top-left-radius|top-color|top|timing-function|text-wrap|text-underline-position|text-transform|text-spacing|text-space-trim|text-space-collapse|text-size-adjust|text-shadow|text-replace|text-rendering|text-overflow|text-outline|text-orientation|text-justify|text-indent|text-height|text-emphasis-style|text-emphasis-skip|text-emphasis-position|text-emphasis-color|text-emphasis|text-decoration-style|text-decoration-stroke|text-decoration-skip|text-decoration-line|text-decoration-fill|text-decoration-color|text-decoration|text-combine-upright|text-anchor|text-align-last|text-align-all|text-align|text|target-position|target-new|target-name|target|table-layout|tab-size|system|symbols|suffix|style-type|style-position|style-image|style|stroke-width|stroke-opacity|stroke-miterlimit|stroke-linejoin|stroke-linecap|stroke-dashoffset|stroke-dasharray|stroke|string-set|stretch|stress|stop-opacity|stop-color|stacking-strategy|stacking-shift|stacking-ruby|stacking|src|speed|speech-rate|speech|speak-punctuation|speak-numeral|speak-header|speak-as|speak|span|spacing|space-collapse|space|solid-opacity|solid-color|sizing|size-adjust|size|shape-rendering|shape-padding|shape-outside|shape-margin|shape-inside|shape-image-threshold|shadow|scroll-snap-type|scroll-snap-points-y|scroll-snap-points-x|scroll-snap-destination|scroll-snap-coordinate|scroll-behavior|scale|ry|rx|respond-to|rule-width|rule-style|rule-color|rule|ruby-span|ruby-position|ruby-overhang|ruby-merge|ruby-align|ruby|rows|rotation-point|rotation|rotate|role|right-width|right-style|right-color|right|richness|rest-before|rest-after|rest|resource|resolution|resize|reset|replace|repeat|rendering-intent|region-fragment|rate|range|radius|r|quotes|punctuation-trim|punctuation|property|profile|presentation-level|presentation|prefix|position|pointer-events|point|play-state|play-during|play-count|pitch-range|pitch|phonemes|perspective-origin|perspective|pause-before|pause-after|pause|page-policy|page-break-inside|page-break-before|page-break-after|page|padding-top|padding-right|padding-left|padding-inline-start|padding-inline-end|padding-bottom|padding-block-start|padding-block-end|padding|pad|pack|overhang|overflow-y|overflow-x|overflow-wrap|overflow-style|overflow-inline|overflow-block|overflow|outline-width|outline-style|outline-offset|outline-color|outline|orphans|origin|orientation|orient|ordinal-group|order|opacity|offset-start|offset-inline-start|offset-inline-end|offset-end|offset-block-start|offset-block-end|offset-before|offset-after|offset|object-position|object-fit|numeral|new|negative|nav-up|nav-right|nav-left|nav-index|nav-down|nav|name|move-to|motion-rotation|motion-path|motion-offset|motion|model|mix-blend-mode|min-zoom|min-width|min-inline-size|min-height|min-block-size|min|max-zoom|max-width|max-lines|max-inline-size|max-height|max-block-size|max|mask-type|mask-size|mask-repeat|mask-position|mask-origin|mask-mode|mask-image|mask-composite|mask-clip|mask-border-width|mask-border-source|mask-border-slice|mask-border-repeat|mask-border-outset|mask-border-mode|mask-border|mask|marquee-style|marquee-speed|marquee-play-count|marquee-loop|marquee-direction|marquee|marks|marker-start|marker-side|marker-mid|marker-end|marker|margin-top|margin-right|margin-left|margin-inline-start|margin-inline-end|margin-bottom|margin-block-start|margin-block-end|margin|list-style-type|list-style-position|list-style-image|list-style|list|lines|line-stacking-strategy|line-stacking-shift|line-stacking-ruby|line-stacking|line-snap|line-height|line-grid|line-break|line|lighting-color|level|letter-spacing|length|left-width|left-style|left-color|left|label|kerning|justify-self|justify-items|justify-content|justify|iteration-count|isolation|inline-size|inline-box-align|initial-value|initial-size|initial-letter-wrap|initial-letter-align|initial-letter|initial-before-align|initial-before-adjust|initial-after-align|initial-after-adjust|index|indent|increment|image-rendering|image-resolution|image-orientation|image|icon|hyphens|hyphenate-limit-zone|hyphenate-limit-lines|hyphenate-limit-last|hyphenate-limit-chars|hyphenate-character|hyphenate|height|header|hanging-punctuation|grid-template-rows|grid-template-columns|grid-template-areas|grid-template|grid-row-start|grid-row-gap|grid-row-end|grid-row|grid-rows|grid-gap|grid-column-start|grid-column-gap|grid-column-end|grid-column|grid-columns|grid-auto-rows|grid-auto-flow|grid-auto-columns|grid-area|grid|glyph-orientation-vertical|glyph-orientation-horizontal|gap|font-weight|font-variant-position|font-variant-numeric|font-variant-ligatures|font-variant-east-asian|font-variant-caps|font-variant-alternates|font-variant|font-synthesis|font-style|font-stretch|font-size-adjust|font-size|font-language-override|font-kerning|font-feature-settings|font-family|font|flow-into|flow-from|flow|flood-opacity|flood-color|float-offset|float|flex-wrap|flex-shrink|flex-grow|flex-group|flex-flow|flex-direction|flex-basis|flex|fit-position|fit|filter|fill-rule|fill-opacity|fill|family|fallback|enable-background|empty-cells|emphasis|elevation|duration|drop-initial-value|drop-initial-size|drop-initial-before-align|drop-initial-before-adjust|drop-initial-after-align|drop-initial-after-adjust|drop|down|dominant-baseline|display-role|display-model|display|direction|delay|decoration-break|decoration|cy|cx|cursor|cue-before|cue-after|cue|crop|counter-set|counter-reset|counter-increment|counter|count|corner-shape|corners|continue|content|contain|columns|column-width|column-span|column-rule-width|column-rule-style|column-rule-color|column-rule|column-gap|column-fill|column-count|column-break-before|column-break-after|column|color-rendering|color-profile|color-interpolation-filters|color-interpolation|color-adjust|color|collapse|clip-rule|clip-path|clip|clear|character|caret-shape|caret-color|caret|caption-side|buffered-rendering|break-inside|break-before|break-after|break|box-suppress|box-snap|box-sizing|box-shadow|box-pack|box-orient|box-ordinal-group|box-lines|box-flex-group|box-flex|box-direction|box-decoration-break|box-align|box|bottom-width|bottom-style|bottom-right-radius|bottom-left-radius|bottom-color|bottom|border-width|border-top-width|border-top-style|border-top-right-radius|border-top-left-radius|border-top-color|border-top|border-style|border-spacing|border-right-width|border-right-style|border-right-color|border-right|border-radius|border-limit|border-length|border-left-width|border-left-style|border-left-color|border-left|border-inline-start-width|border-inline-start-style|border-inline-start-color|border-inline-start|border-inline-end-width|border-inline-end-style|border-inline-end-color|border-inline-end|border-image-width|border-image-transform|border-image-source|border-image-slice|border-image-repeat|border-image-outset|border-image|border-color|border-collapse|border-clip-top|border-clip-right|border-clip-left|border-clip-bottom|border-clip|border-bottom-width|border-bottom-style|border-bottom-right-radius|border-bottom-left-radius|border-bottom-color|border-bottom|border-block-start-width|border-block-start-style|border-block-start-color|border-block-start|border-block-end-width|border-block-end-style|border-block-end-color|border-block-end|border|bookmark-target|bookmark-level|bookmark-label|bookmark|block-size|binding|bidi|before|baseline-shift|baseline|balance|background-size|background-repeat|background-position-y|background-position-x|background-position-inline|background-position-block|background-position|background-origin|background-image|background-color|background-clip|background-blend-mode|background-attachment|background|backface-visibility|backdrop-filter|azimuth|attachment|appearance|animation-timing-function|animation-play-state|animation-name|animation-iteration-count|animation-fill-mode|animation-duration|animation-direction|animation-delay|animation|alt|all|alignment-baseline|alignment-adjust|alignment|align-last|align-self|align-items|align-content|align|after|adjust|additive-symbols) @@ -1129,6 +1167,13 @@ + variable-name + + match + \-\-[^:\),]+ + name + support.type.property-name.variable.css + scopeName source.css diff --git a/extensions/html/package.json b/extensions/html/package.json index 1e7ea9c1173..b126b1f8f48 100644 --- a/extensions/html/package.json +++ b/extensions/html/package.json @@ -6,7 +6,7 @@ "contributes": { "languages": [{ "id": "html", - "extensions": [ ".html", ".htm", ".shtml", ".xhtml", ".mdoc", ".jsp", ".asp", ".aspx", ".jshtm" ], + "extensions": [ ".html", ".htm", ".shtml", ".xhtml", ".mdoc", ".jsp", ".asp", ".aspx", ".jshtm", ".vue" ], "aliases": [ "HTML", "htm", "html", "xhtml" ], "mimetypes": ["text/html", "text/x-jshtm", "text/template", "text/ng-template", "application/xhtml+xml"] }], diff --git a/extensions/ini/package.json b/extensions/ini/package.json index dfaa9ecd88c..882bb0c2325 100644 --- a/extensions/ini/package.json +++ b/extensions/ini/package.json @@ -6,7 +6,7 @@ "contributes": { "languages": [{ "id": "ini", - "extensions": [ ".ini", ".properties", ".gitconfig" ], + "extensions": [ ".desktop", ".ini", ".properties", ".gitconfig" ], "filenames": ["config", ".gitattributes", ".gitconfig", "gitconfig", ".editorconfig"], "aliases": [ "Ini", "ini" ], "configuration": "./ini.configuration.json" @@ -17,4 +17,4 @@ "path": "./syntaxes/Ini.plist" }] } -} \ No newline at end of file +} diff --git a/extensions/jade/syntaxes/Jade.tmLanguage b/extensions/jade/syntaxes/Jade.tmLanguage index d7c3dd0d6ac..9b7b23d3792 100644 --- a/extensions/jade/syntaxes/Jade.tmLanguage +++ b/extensions/jade/syntaxes/Jade.tmLanguage @@ -1,5 +1,5 @@ - + fileTypes @@ -186,34 +186,7 @@ begin - ^(\s*):(markdown)(?=\(|$)$ - beginCaptures - - 2 - - name - constant.language.name.markdown.filter.jade - - - end - ^(?!(\1\s)|\s*$) - name - text.markdown.filter.jade - patterns - - - include - #filter_args - - - include - text.html.markdown - - - - - begin - ^(\s*):(sass)(?=\(|$)$ + ^(\s*):(sass)(?=\(|$) beginCaptures 2 @@ -230,7 +203,7 @@ include - #filter_args + #tag_attributes include @@ -240,7 +213,7 @@ begin - ^(\s*):(less)(?=\(|$)$ + ^(\s*):(less)(?=\(|$) beginCaptures 2 @@ -257,7 +230,7 @@ include - #filter_args + #tag_attributes include @@ -267,7 +240,7 @@ begin - ^(\s*):(stylus)(?=\(|$)$ + ^(\s*):(stylus)(?=\(|$) beginCaptures 2 @@ -282,7 +255,7 @@ include - #filter_args + #tag_attributes include @@ -309,7 +282,7 @@ include - #filter_args + #tag_attributes include @@ -332,8 +305,6 @@ Generic Jade filter. end ^(?!(\1\s)|\s*$) - name - text.generic.filter.jade patterns @@ -353,13 +324,13 @@ match - \w + [\w-] name constant.language.name.generic.filter.jade include - #filter_args + #tag_attributes match @@ -779,73 +750,6 @@ - filter_args - - begin - \G(\() - captures - - 1 - - name - meta.args.filter.jade - - 2 - - name - invalid.illegal.extra.args.filter.jade - - - end - (\))(.*?$) - name - args.filter.jade - patterns - - - begin - ([^\s(),=]+)(=?) - beginCaptures - - 1 - - name - entity.other.attribute-name.tag.jade - - 2 - - name - punctuation.separator.key-value.jade - - - contentName - string.value.args.filter.jade - end - ((?=\))|,|$) - patterns - - - include - #filter_args_paren - - - - - - filter_args_paren - - begin - \( - end - \)|$ - patterns - - - include - #filter_args_paren - - - flow_control begin diff --git a/extensions/javascript/src/features/jsonContributions.ts b/extensions/javascript/src/features/jsonContributions.ts index 1926b38fab7..e33ff6d1e91 100644 --- a/extensions/javascript/src/features/jsonContributions.ts +++ b/extensions/javascript/src/features/jsonContributions.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {Location, getLocation, createScanner, SyntaxKind} from 'jsonc-parser'; +import {Location, getLocation, createScanner, SyntaxKind, ScanError} from 'jsonc-parser'; import {basename} from 'path'; import {BowerJSONContribution} from './bowerJSONContribution'; import {PackageJSONContribution} from './packageJSONContribution'; @@ -122,10 +122,7 @@ export class JSONCompletionItemProvider implements CompletionItemProvider { if (location.isAtPropertyKey) { let addValue = !location.previousNode || !location.previousNode.columnOffset; - let scanner = createScanner(document.getText(), true); - scanner.setPosition(offset); - scanner.scan(); - let isLast = scanner.getToken() === SyntaxKind.CloseBraceToken || scanner.getToken() === SyntaxKind.EOF; + let isLast = this.isLast(document, position); collectPromise = this.jsonContribution.collectPropertySuggestions(fileName, location, currentWord, addValue, isLast, collector); } else { if (location.path.length === 0) { @@ -153,4 +150,14 @@ export class JSONCompletionItemProvider implements CompletionItemProvider { } return text.substring(i+1, position.character); } + + private isLast(document: TextDocument, position: Position):boolean { + let scanner = createScanner(document.getText(), true); + scanner.setPosition(document.offsetAt(position)); + let nextToken = scanner.scan(); + if (nextToken === SyntaxKind.StringLiteral && scanner.getTokenError() === ScanError.UnexpectedEndOfString) { + nextToken= scanner.scan(); + } + return nextToken === SyntaxKind.CloseBraceToken || nextToken === SyntaxKind.EOF; + } } \ No newline at end of file diff --git a/extensions/json/server/src/jsonCompletion.ts b/extensions/json/server/src/jsonCompletion.ts index 6d0c75fce1f..103869f3fdb 100644 --- a/extensions/json/server/src/jsonCompletion.ts +++ b/extensions/json/server/src/jsonCompletion.ts @@ -438,10 +438,10 @@ export class JSONCompletion { type = array.length > 0 ? array[0] : null; } if (!type) { - return CompletionItemKind.Text; + return CompletionItemKind.Value; } switch (type) { - case 'string': return CompletionItemKind.Text; + case 'string': return CompletionItemKind.Value; case 'object': return CompletionItemKind.Module; case 'property': return CompletionItemKind.Property; default: return CompletionItemKind.Value; diff --git a/extensions/less/syntaxes/LESS.tmLanguage b/extensions/less/syntaxes/LESS.tmLanguage index 14f3d043a7f..068ea8cbdd5 100644 --- a/extensions/less/syntaxes/LESS.tmLanguage +++ b/extensions/less/syntaxes/LESS.tmLanguage @@ -376,7 +376,7 @@ match - @[a-zA-Z0-9_-][\w-]* + (@[a-zA-Z0-9_-][\w-]*)|(\-\-[^:\),]+) name variable.other.less diff --git a/extensions/node-debug/node-debug.azure.json b/extensions/node-debug/node-debug.azure.json index 63c268656a8..42803d6028a 100644 --- a/extensions/node-debug/node-debug.azure.json +++ b/extensions/node-debug/node-debug.azure.json @@ -1,6 +1,6 @@ { "account": "monacobuild", "container": "debuggers", - "zip": "48428c0/node-debug.zip", + "zip": "73e0456/node-debug.zip", "output": "" } diff --git a/extensions/perl/syntaxes/Perl.plist b/extensions/perl/syntaxes/Perl.plist index 7b6ee3888dd..9b608d3030e 100644 --- a/extensions/perl/syntaxes/Perl.plist +++ b/extensions/perl/syntaxes/Perl.plist @@ -56,7 +56,7 @@ comment string.regexp.compile.perl end - ((([egimosxradlupc]*)))(?=(\s+\S|\s*[;\,\#\{\}\)]|$)) + ((([egimosxradlupc]*)))(?=(\s+\S|\s*[;\,\#\{\}\)]|\s*$)) endCaptures 1 @@ -309,7 +309,7 @@ comment string.regexp.find-m.perl end - ((([egimosxradlupc]*)))(?=(\s+\S|\s*[;\,\#\{\}\)]|$)) + ((([egimosxradlupc]*)))(?=(\s+\S|\s*[;\,\#\{\}\)]|\s*$)) endCaptures 1 @@ -595,7 +595,7 @@ comment string.regexp.replace.perl end - ((([egimosxradlupc]*)))(?=(\s+\S|\s*[;\,\#\{\}\)\]>]|$)) + ((([egimosxradlupc]*)))(?=(\s+\S|\s*[;\,\#\{\}\)\]>]|\s*$)) endCaptures 1 @@ -1161,7 +1161,7 @@ contentName string.regexp.find.perl end - ((\1([egimosxradlupc]*)))(?=(\s+\S|\s*[;\,\#\{\}\)]|$)) + ((\1([egimosxradlupc]*)))(?=(\s+\S|\s*[;\,\#\{\}\)]|\s*$)) endCaptures 1 diff --git a/extensions/perl/test/colorize-fixtures/test2.pl b/extensions/perl/test/colorize-fixtures/test2.pl new file mode 100644 index 00000000000..0a089b3b21a --- /dev/null +++ b/extensions/perl/test/colorize-fixtures/test2.pl @@ -0,0 +1,31 @@ +die("[$sheet->{label}] Unexpected sheet format.") unless ( + $sheet->{"$date_col$row"} =~ /CALL_DATE/i && + $sheet->{"$pixel_cols[4]$row"} =~ /Home_Bind_Count/i + ); + + $row++; + while ($row < $sheet->{maxrow}) { + $row++; + $total_lines++; + + my $date = $sheet->{"$date_col$row"}; + next unless $date; + (warning "Unexpected date format: '$date'"), next unless ($date =~ /^2\d\d\d-\d\d-\d\d$/); + + my $phone = trim($sheet->{"$phone_col$row"}); + (warning "Unexpected phone format: '$phone'."), next unless ($phone =~ /^\d{10}$/); + + info $phone; + next if ($date gt $date_to || $date lt $date_from); + + my @pixels = (0) x 5; + for (1..4) { + $pixels[$_] = trim($sheet->{"$pixel_cols[4]$row"}); + (warning "Pixel $_ is not a number in the row # $row."), next unless looks_like_number($pixels[$_]); + }; + + for (1..4) { + add_phone_activity($date, $phone, "pixel-$_", $pixels[$_]) if $pixels[$_]; + }; + $parsed_lines++; + }; \ No newline at end of file diff --git a/extensions/perl/test/colorize-results/test2_pl.json b/extensions/perl/test/colorize-results/test2_pl.json new file mode 100644 index 00000000000..9a1b078ea65 --- /dev/null +++ b/extensions/perl/test/colorize-results/test2_pl.json @@ -0,0 +1,3313 @@ +[ + { + "c": "die", + "t": "control.keyword.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": "(", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "\"", + "t": "begin.definition.double.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "[", + "t": "double.perl.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "$", + "t": "definition.double.global.other.perl.punctuation.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "sheet", + "t": "double.global.other.perl.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "->{label}] Unexpected sheet format.", + "t": "double.perl.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "\"", + "t": "definition.double.end.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": ") ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "unless", + "t": "control.keyword.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " (", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "sheet", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "->", + "t": "comparison.keyword.operator.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.operator rgb(212, 212, 212)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.operator rgb(0, 0, 0)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.operator rgb(212, 212, 212)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.operator rgb(0, 0, 0)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.operator rgb(212, 212, 212)" + } + }, + { + "c": "{", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "\"", + "t": "begin.definition.double.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "$", + "t": "definition.double.global.other.perl.punctuation.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "date_col$row", + "t": "double.global.other.perl.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "\"", + "t": "definition.double.end.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "} =~ ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "/", + "t": "definition.find.perl.punctuation.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "CALL_DATE", + "t": "find.perl.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "/", + "t": "definition.find.perl.punctuation.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "i", + "t": "control.definition.find.keyword.perl.punctuation.regexp.regexp-option.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " &&", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "sheet", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "->", + "t": "comparison.keyword.operator.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.operator rgb(212, 212, 212)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.operator rgb(0, 0, 0)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.operator rgb(212, 212, 212)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.operator rgb(0, 0, 0)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.operator rgb(212, 212, 212)" + } + }, + { + "c": "{", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "\"", + "t": "begin.definition.double.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "$", + "t": "definition.double.global.other.perl.punctuation.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "pixel_cols", + "t": "double.global.other.perl.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "[4]", + "t": "double.perl.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "$", + "t": "definition.double.global.other.perl.punctuation.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "row", + "t": "double.global.other.perl.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "\"", + "t": "definition.double.end.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "} =~ ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "/", + "t": "definition.find.perl.punctuation.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "Home_Bind_Count", + "t": "find.perl.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "/", + "t": "definition.find.perl.punctuation.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "i", + "t": "control.definition.find.keyword.perl.punctuation.regexp.regexp-option.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": ");", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "row", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "++;", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "while", + "t": "control.keyword.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " (", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "row", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " < ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "sheet", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "->", + "t": "comparison.keyword.operator.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.operator rgb(212, 212, 212)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.operator rgb(0, 0, 0)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.operator rgb(212, 212, 212)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.operator rgb(0, 0, 0)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.operator rgb(212, 212, 212)" + } + }, + { + "c": "{", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "maxrow", + "t": "bareword.constant.other.perl", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "}) {", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "row", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "++;", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "total_lines", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "++;", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "my", + "t": "modifier.perl.storage", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.storage.modifier rgb(86, 156, 214)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.storage.modifier rgb(0, 0, 255)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.storage.modifier rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.storage.modifier rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.storage.modifier rgb(86, 156, 214)" + } + }, + { + "c": " ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "date", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " = ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "sheet", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "->", + "t": "comparison.keyword.operator.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.operator rgb(212, 212, 212)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.operator rgb(0, 0, 0)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.operator rgb(212, 212, 212)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.operator rgb(0, 0, 0)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.operator rgb(212, 212, 212)" + } + }, + { + "c": "{", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "\"", + "t": "begin.definition.double.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "$", + "t": "definition.double.global.other.perl.punctuation.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "date_col$row", + "t": "double.global.other.perl.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "\"", + "t": "definition.double.end.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "};", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "next", + "t": "control.keyword.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "unless", + "t": "control.keyword.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "date", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": ";", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "(warning ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "\"", + "t": "begin.definition.double.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "Unexpected date format: '", + "t": "double.perl.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "$", + "t": "definition.double.global.other.perl.punctuation.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "date", + "t": "double.global.other.perl.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "'", + "t": "double.perl.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "\"", + "t": "definition.double.end.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "), ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "next", + "t": "control.keyword.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "unless", + "t": "control.keyword.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " (", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "date", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " =~ ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "/", + "t": "definition.find.perl.punctuation.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "^2", + "t": "find.perl.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "\\d\\d\\d", + "t": "character.constant.escape.find.perl.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "-", + "t": "find.perl.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "\\d\\d", + "t": "character.constant.escape.find.perl.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "-", + "t": "find.perl.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "\\d\\d", + "t": "character.constant.escape.find.perl.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "$", + "t": "anchor.control.find.keyword.perl.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": "/", + "t": "definition.find.perl.punctuation.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": ");", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "my", + "t": "modifier.perl.storage", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.storage.modifier rgb(86, 156, 214)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.storage.modifier rgb(0, 0, 255)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.storage.modifier rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.storage.modifier rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.storage.modifier rgb(86, 156, 214)" + } + }, + { + "c": " ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "phone", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " = trim(", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "sheet", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "->", + "t": "comparison.keyword.operator.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.operator rgb(212, 212, 212)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.operator rgb(0, 0, 0)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.operator rgb(212, 212, 212)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.operator rgb(0, 0, 0)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.operator rgb(212, 212, 212)" + } + }, + { + "c": "{", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "\"", + "t": "begin.definition.double.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "$", + "t": "definition.double.global.other.perl.punctuation.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "phone_col$row", + "t": "double.global.other.perl.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "\"", + "t": "definition.double.end.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "});", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "(warning ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "\"", + "t": "begin.definition.double.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "Unexpected phone format: '", + "t": "double.perl.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "$", + "t": "definition.double.global.other.perl.punctuation.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "phone", + "t": "double.global.other.perl.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "'.", + "t": "double.perl.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "\"", + "t": "definition.double.end.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "), ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "next", + "t": "control.keyword.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "unless", + "t": "control.keyword.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " (", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "phone", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " =~ ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "/", + "t": "definition.find.perl.punctuation.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "^", + "t": "find.perl.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "\\d", + "t": "character.constant.escape.find.perl.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "{10}", + "t": "find.perl.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": "$", + "t": "anchor.control.find.keyword.perl.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": "/", + "t": "definition.find.perl.punctuation.regexp.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string.regexp rgb(209, 105, 105)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string.regexp rgb(129, 31, 63)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string.regexp rgb(209, 105, 105)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string.regexp rgb(129, 31, 63)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string.regexp rgb(209, 105, 105)" + } + }, + { + "c": ");", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "info ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "phone", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": ";", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "next", + "t": "control.keyword.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "if", + "t": "control.keyword.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " (", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "date", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "gt", + "t": "function.perl.support", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "date_to", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " || ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "date", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "lt", + "t": "function.perl.support", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "date_from", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": ");", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "my", + "t": "modifier.perl.storage", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.storage.modifier rgb(86, 156, 214)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.storage.modifier rgb(0, 0, 255)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.storage.modifier rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.storage.modifier rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.storage.modifier rgb(86, 156, 214)" + } + }, + { + "c": " ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "@", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "pixels", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " = (0) ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "x", + "t": "function.perl.support", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "5", + "t": "entity.function.name.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.entity.name.function rgb(220, 220, 170)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.entity.name.function rgb(121, 94, 38)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.entity.name.function rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": ";", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "for", + "t": "control.keyword.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " (1..4) {", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "pixels", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "[", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.other.perl.predefined.punctuation.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "_", + "t": "other.perl.predefined.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "] = trim(", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "sheet", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "->", + "t": "comparison.keyword.operator.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.operator rgb(212, 212, 212)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.operator rgb(0, 0, 0)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.operator rgb(212, 212, 212)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.operator rgb(0, 0, 0)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.operator rgb(212, 212, 212)" + } + }, + { + "c": "{", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "\"", + "t": "begin.definition.double.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "$", + "t": "definition.double.global.other.perl.punctuation.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "pixel_cols", + "t": "double.global.other.perl.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "[4]", + "t": "double.perl.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "$", + "t": "definition.double.global.other.perl.punctuation.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "row", + "t": "double.global.other.perl.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "\"", + "t": "definition.double.end.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "});", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "(warning ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "\"", + "t": "begin.definition.double.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "Pixel ", + "t": "double.perl.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "$", + "t": "definition.double.other.perl.predefined.punctuation.quoted.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "_", + "t": "double.other.perl.predefined.quoted.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": " is not a number in the row # ", + "t": "double.perl.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "$", + "t": "definition.double.global.other.perl.punctuation.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "row", + "t": "double.global.other.perl.quoted.readwrite.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": ".", + "t": "double.perl.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "\"", + "t": "definition.double.end.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "), ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "next", + "t": "control.keyword.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "unless", + "t": "control.keyword.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " looks_like_number(", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "pixels", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "[", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.other.perl.predefined.punctuation.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "_", + "t": "other.perl.predefined.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "]);", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "};", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "for", + "t": "control.keyword.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " (1..4) {", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "add_phone_activity(", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "date", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": ", ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "phone", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": ", ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "\"", + "t": "begin.definition.double.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "pixel-", + "t": "double.perl.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "$", + "t": "definition.double.other.perl.predefined.punctuation.quoted.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "_", + "t": "double.other.perl.predefined.quoted.string.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": "\"", + "t": "definition.double.end.perl.punctuation.quoted.string", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.string rgb(206, 145, 120)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.string rgb(163, 21, 21)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.string rgb(206, 145, 120)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.string rgb(163, 21, 21)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.string rgb(206, 145, 120)" + } + }, + { + "c": ", ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "pixels", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "[", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.other.perl.predefined.punctuation.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "_", + "t": "other.perl.predefined.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "]) ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "if", + "t": "control.keyword.perl", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.keyword.control rgb(197, 134, 192)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.keyword.control rgb(175, 0, 219)", + "dark_vs": ".vs-dark.vscode-theme-defaults-themes-dark_vs-json .token.keyword.control rgb(86, 156, 214)", + "light_vs": ".vs.vscode-theme-defaults-themes-light_vs-json .token.keyword.control rgb(0, 0, 255)", + "hc_black": ".hc-black.vscode-theme-defaults-themes-hc_black-json .token.keyword.control rgb(86, 156, 214)" + } + }, + { + "c": " ", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "pixels", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "[", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.other.perl.predefined.punctuation.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "_", + "t": "other.perl.predefined.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "];", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "};", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "even-tab.leading-tabs.meta", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "$", + "t": "definition.global.other.perl.punctuation.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "parsed_lines", + "t": "global.other.perl.readwrite.variable", + "r": { + "dark_plus": ".vs-dark.vscode-theme-defaults-themes-dark_plus-json .token.variable rgb(156, 220, 254)", + "light_plus": ".vs.vscode-theme-defaults-themes-light_plus-json .token.variable rgb(0, 16, 128)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "++;", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": " ", + "t": "leading-tabs.meta.odd-tab", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + }, + { + "c": "};", + "t": "", + "r": { + "dark_plus": ".vs-dark .token rgb(212, 212, 212)", + "light_plus": ".vs .token rgb(0, 0, 0)", + "dark_vs": ".vs-dark .token rgb(212, 212, 212)", + "light_vs": ".vs .token rgb(0, 0, 0)", + "hc_black": ".hc-black .token rgb(255, 255, 255)" + } + } +] \ No newline at end of file diff --git a/extensions/rust/rust.configuration.json b/extensions/rust/rust.configuration.json index e4656d0babb..34396c3121e 100644 --- a/extensions/rust/rust.configuration.json +++ b/extensions/rust/rust.configuration.json @@ -12,8 +12,7 @@ ["{", "}"], ["[", "]"], ["(", ")"], - ["\"", "\""], - ["'", "'"] + ["\"", "\""] ], "surroundingPairs": [ ["{", "}"], @@ -22,4 +21,4 @@ ["\"", "\""], ["'", "'"] ] -} \ No newline at end of file +} diff --git a/extensions/shellscript/package.json b/extensions/shellscript/package.json index cf263f1557d..635196d327c 100644 --- a/extensions/shellscript/package.json +++ b/extensions/shellscript/package.json @@ -7,7 +7,8 @@ "languages": [{ "id": "shellscript", "aliases": ["Shell Script (Bash)", "shellscript", "bash", "sh", "zsh"], - "extensions": [".sh", ".bash", ".bashrc", ".bash_profile", ".bash_login", ".profile", ".bash_logout", ".zsh", ".zshrc", ".zprofile", ".zlogin", ".zlogout", ".zshenv"], + "extensions": [".sh", ".bash", ".bashrc", ".bash_profile", ".bash_login", ".ebuild", ".install", ".profile", ".bash_logout", ".zsh", ".zshrc", ".zprofile", ".zlogin", ".zlogout", ".zshenv"], + "filenames": ["PKGBUILD"], "firstLine": "^#!.*\\b(bash|zsh|sh|tcsh)|^#\\s*-\\*-[^*]*mode:\\s*shell-script[^*]*-\\*-", "configuration": "./shellscript.configuration.json", "mimetypes": ["text/x-shellscript"] @@ -18,4 +19,4 @@ "path": "./syntaxes/Shell-Unix-Bash.tmLanguage" }] } -} \ No newline at end of file +} diff --git a/extensions/typescript/server/typescript/package.json b/extensions/typescript/server/typescript/package.json index 76494c27056..fb3cc4f7736 100644 --- a/extensions/typescript/server/typescript/package.json +++ b/extensions/typescript/server/typescript/package.json @@ -4,7 +4,7 @@ "name": "Microsoft Corp." }, "homepage": "http://typescriptlang.org/", - "version": "1.8.9", + "version": "1.8.10", "license": "Apache-2.0", "description": "TypeScript is a language for application scale JavaScript development", "keywords": [ @@ -19,7 +19,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/Microsoft/TypeScript.git" + "url": "git+https://github.com/Microsoft/TypeScript.git" }, "main": "./lib/typescript.js", "typings": "./lib/typescript.d.ts", @@ -58,11 +58,12 @@ "os": false, "path": false }, - "gitHead": "9ef75534e0fd5f92bef86b520dff768c11a2df4d", - "_id": "typescript@1.8.9", - "_shasum": "b3b3a74059fd31cbd3ecad95d62465939e7ed5fa", + "gitHead": "794c57478ec2a44ee15fb3e245a4c5d2d1612375", + "_id": "typescript@1.8.10", + "_shasum": "b475d6e0dff0bf50f296e5ca6ef9fbb5c7320f1e", "_from": "typescript@latest", - "_npmVersion": "2.0.0", + "_npmVersion": "2.14.2", + "_nodeVersion": "5.9.0", "_npmUser": { "name": "typescript", "email": "typescript@microsoft.com" @@ -74,13 +75,14 @@ } ], "dist": { - "shasum": "b3b3a74059fd31cbd3ecad95d62465939e7ed5fa", - "tarball": "http://registry.npmjs.org/typescript/-/typescript-1.8.9.tgz" + "shasum": "b475d6e0dff0bf50f296e5ca6ef9fbb5c7320f1e", + "tarball": "https://registry.npmjs.org/typescript/-/typescript-1.8.10.tgz" }, "_npmOperationalInternal": { "host": "packages-12-west.internal.npmjs.com", - "tmp": "tmp/typescript-1.8.9.tgz_1458169371557_0.7292261146940291" + "tmp": "tmp/typescript-1.8.10.tgz_1460493736776_0.9304528103675693" }, "directories": {}, - "_resolved": "https://registry.npmjs.org/typescript/-/typescript-1.8.9.tgz" + "_resolved": "https://registry.npmjs.org/typescript/-/typescript-1.8.10.tgz", + "readme": "ERROR: No README data found!" } diff --git a/extensions/typescript/src/utils/projectStatus.ts b/extensions/typescript/src/utils/projectStatus.ts index 6600a805d41..8dc39cc28e4 100644 --- a/extensions/typescript/src/utils/projectStatus.ts +++ b/extensions/typescript/src/utils/projectStatus.ts @@ -100,7 +100,7 @@ export function create(client: ITypescriptServiceClient, isOpen:(path:string)=>P projectHinted[configFileName] = true; item.hide(); - return vscode.workspace.openTextDocument(vscode.Uri.parse('untitled:' + join(vscode.workspace.rootPath, 'jsconfig.json'))) + return vscode.workspace.openTextDocument(vscode.Uri.parse('untitled:' + encodeURIComponent(join(vscode.workspace.rootPath, 'jsconfig.json')))) .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Three)) .then(editor => editor.edit(builder => builder.insert(new vscode.Position(0, 0), defaultConfig))); } diff --git a/extensions/vscode-api-tests/src/commands.test.ts b/extensions/vscode-api-tests/src/commands.test.ts index 5ffd6fd2ac7..495de2d1d96 100644 --- a/extensions/vscode-api-tests/src/commands.test.ts +++ b/extensions/vscode-api-tests/src/commands.test.ts @@ -40,23 +40,6 @@ suite('commands namespace tests', () => { }, done); }); - test('api-command: workbench.html.preview', function () { - - let registration = workspace.registerTextDocumentContentProvider('speciale', { - provideTextDocumentContent(uri) { - return `content of URI ${uri.toString()}`; - } - }); - - let virtualDocumentUri = Uri.parse('speciale://authority/path'); - - return commands.executeCommand('vscode.previewHtml', virtualDocumentUri).then(success => { - assert.ok(success); - registration.dispose(); - }); - - }); - test('editorCommand with extra args', function () { let args: IArguments; @@ -77,4 +60,46 @@ suite('commands namespace tests', () => { }); }); + + test('api-command: vscode.previewHtm', function () { + + let registration = workspace.registerTextDocumentContentProvider('speciale', { + provideTextDocumentContent(uri) { + return `content of URI ${uri.toString()}`; + } + }); + + let virtualDocumentUri = Uri.parse('speciale://authority/path'); + + return commands.executeCommand('vscode.previewHtml', virtualDocumentUri).then(success => { + assert.ok(success); + registration.dispose(); + }); + + }); + + test('api-command: vscode.diff', function () { + + let registration = workspace.registerTextDocumentContentProvider('sc', { + provideTextDocumentContent(uri) { + return `content of URI ${uri.toString()}#${Math.random()}`; + } + }); + + + let a = commands.executeCommand('vscode.diff', Uri.parse('sc:a'), Uri.parse('sc:b'), 'DIFF').then(value => { + assert.ok(value === void 0); + registration.dispose(); + }); + + let b = commands.executeCommand('vscode.diff', Uri.parse('sc:a'), Uri.parse('sc:b')).then(value => { + assert.ok(value === void 0); + registration.dispose(); + }); + + let c = commands.executeCommand('vscode.diff').then(() => assert.ok(false), () => assert.ok(true)); + let d = commands.executeCommand('vscode.diff', 1, 2, 3).then(() => assert.ok(false), () => assert.ok(true)); + + return Promise.all([a, b, c]); + }); }); diff --git a/extensions/vscode-api-tests/src/languages.test.ts b/extensions/vscode-api-tests/src/languages.test.ts index dc2d933e4c1..fe6200c00a3 100644 --- a/extensions/vscode-api-tests/src/languages.test.ts +++ b/extensions/vscode-api-tests/src/languages.test.ts @@ -79,6 +79,55 @@ suite('languages namespace tests', () => { collection.dispose(); }); + test('diagnostics collection, set with dupliclated tuples', function () { + let collection = languages.createDiagnosticCollection('test'); + let uri = Uri.parse('sc:hightower'); + collection.set([ + [uri, [new Diagnostic(new Range(0, 0, 0, 1), 'message-1')]], + [Uri.parse('some:thing'), [new Diagnostic(new Range(0, 0, 1, 1), 'something')]], + [uri, [new Diagnostic(new Range(0, 0, 0, 1), 'message-2')]], + ]); + + let array = collection.get(uri); + assert.equal(array.length, 2); + let [first, second] = array; + assert.equal(first.message, 'message-1'); + assert.equal(second.message, 'message-2'); + + // clear + collection.delete(uri); + assert.ok(!collection.has(uri)); + + // bad tuple clears 1/2 + collection.set([ + [uri, [new Diagnostic(new Range(0, 0, 0, 1), 'message-1')]], + [Uri.parse('some:thing'), [new Diagnostic(new Range(0, 0, 1, 1), 'something')]], + [uri, undefined] + ]); + assert.ok(!collection.has(uri)); + + // clear + collection.delete(uri); + assert.ok(!collection.has(uri)); + + // bad tuple clears 2/2 + collection.set([ + [uri, [new Diagnostic(new Range(0, 0, 0, 1), 'message-1')]], + [Uri.parse('some:thing'), [new Diagnostic(new Range(0, 0, 1, 1), 'something')]], + [uri, undefined], + [uri, [new Diagnostic(new Range(0, 0, 0, 1), 'message-2')]], + [uri, [new Diagnostic(new Range(0, 0, 0, 1), 'message-3')]], + ]); + + array = collection.get(uri); + assert.equal(array.length, 2); + [first, second] = array; + assert.equal(first.message, 'message-2'); + assert.equal(second.message, 'message-3'); + + collection.dispose(); + }); + test('diagnostics & CodeActionProvider', function (done) { class D2 extends Diagnostic { diff --git a/extensions/vscode-api-tests/src/workspace.test.ts b/extensions/vscode-api-tests/src/workspace.test.ts index 6a7e09de9b3..47c7616650a 100644 --- a/extensions/vscode-api-tests/src/workspace.test.ts +++ b/extensions/vscode-api-tests/src/workspace.test.ts @@ -294,6 +294,23 @@ suite('workspace-namespace', () => { }); }); + test('registerTextDocumentContentProvider, empty doc', function () { + + let registration = workspace.registerTextDocumentContentProvider('foo', { + provideTextDocumentContent(uri) { + return ''; + } + }); + + const uri = Uri.parse('foo:doc/empty'); + + return workspace.openTextDocument(uri).then(doc => { + assert.equal(doc.getText(), ''); + assert.equal(doc.uri.toString(), uri.toString()); + registration.dispose(); + }); + }); + test('registerTextDocumentContentProvider, change event', function () { let callCount = 0; diff --git a/gulpfile.js b/gulpfile.js index f84aaa3fe03..d860732e44c 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -25,10 +25,12 @@ var sourcemaps = require('gulp-sourcemaps'); var _ = require('underscore'); var assign = require('object-assign'); var quiet = !!process.env['VSCODE_BUILD_QUIET']; +var declaration = !!process.env['VSCODE_BUILD_DECLARATION_FILES']; var rootDir = path.join(__dirname, 'src'); var tsOptions = { target: 'ES5', + declaration: declaration, module: 'amd', verbose: !quiet, preserveConstEnums: true, diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 73aeae4a6eb..f6a3d7f0e1b 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -340,6 +340,11 @@ "from": "preserve@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz" }, + "pty.js": { + "version": "0.3.0", + "from": "https://github.com/Tyriar/pty.js/tarball/fffbf86eb9e8051b5b2be4ba9c7b07faa018ce8d", + "resolved": "https://github.com/Tyriar/pty.js/tarball/fffbf86eb9e8051b5b2be4ba9c7b07faa018ce8d" + }, "randomatic": { "version": "1.1.5", "from": "randomatic@>=1.1.3 <2.0.0", @@ -390,20 +395,25 @@ "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, + "term.js": { + "version": "0.0.7", + "from": "https://github.com/jeremyramin/term.js/tarball/master", + "resolved": "https://github.com/jeremyramin/term.js/tarball/master" + }, "typechecker": { "version": "2.0.8", "from": "typechecker@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/typechecker/-/typechecker-2.0.8.tgz" }, "vscode-debugprotocol": { - "version": "1.8.0", - "from": "vscode-debugprotocol@1.8.0", - "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.8.0.tgz" + "version": "1.9.0", + "from": "vscode-debugprotocol@1.9.0", + "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.9.0.tgz" }, "vscode-textmate": { - "version": "1.0.11", - "from": "vscode-textmate@1.0.11", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-1.0.11.tgz" + "version": "1.1.0", + "from": "vscode-textmate@1.1.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-1.1.0.tgz" }, "windows-mutex": { "version": "0.2.0", diff --git a/package.json b/package.json index 4066a293192..d2ca5071e13 100644 --- a/package.json +++ b/package.json @@ -27,10 +27,12 @@ "iconv-lite": "0.4.13", "minimist": "^1.2.0", "native-keymap": "0.1.2", + "pty.js": "https://github.com/Tyriar/pty.js/tarball/prebuilt", "sax": "1.1.2", "semver": "4.3.6", - "vscode-debugprotocol": "1.8.0", - "vscode-textmate": "1.0.11", + "term.js": "https://github.com/jeremyramin/term.js/tarball/master", + "vscode-debugprotocol": "1.9.0", + "vscode-textmate": "1.1.0", "winreg": "1.2.0", "yauzl": "2.3.1" }, diff --git a/resources/linux/bin/code.sh b/resources/linux/bin/code.sh index ce8e5728759..77fa49722f7 100755 --- a/resources/linux/bin/code.sh +++ b/resources/linux/bin/code.sh @@ -3,8 +3,6 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. -ARGS=$@ - # If root, ensure that --user-data-dir is specified if [ "$(id -u)" = "0" ]; then while test $# -gt 0 @@ -35,5 +33,5 @@ fi ELECTRON="$VSCODE_PATH/@@NAME@@" CLI="$VSCODE_PATH/resources/app/out/cli.js" -ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 "$ELECTRON" "$CLI" $ARGS +ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@" exit $? \ No newline at end of file diff --git a/resources/linux/debian/postinst.template b/resources/linux/debian/postinst.template index 24540c9ba2b..c09d4c6123a 100755 --- a/resources/linux/debian/postinst.template +++ b/resources/linux/debian/postinst.template @@ -12,6 +12,11 @@ ln -s /usr/share/@@NAME@@/bin/@@NAME@@ /usr/bin/@@NAME@@ # developers would prefer a terminal editor as the default. update-alternatives --install /usr/bin/editor editor /usr/bin/@@NAME@@ 0 +# Install the desktop entry +if hash desktop-file-install 2>/dev/null; then + desktop-file-install /usr/share/applications/@@NAME@@.desktop +fi + if [ "@@NAME@@" != "code-oss" ]; then # Remove the legacy bin command if this is the stable build if [ "@@NAME@@" = "code" ]; then diff --git a/resources/linux/debian/postrm.template b/resources/linux/debian/postrm.template index 1dfa892a0ea..c43a2b16ae3 100755 --- a/resources/linux/debian/postrm.template +++ b/resources/linux/debian/postrm.template @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/bash # # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. diff --git a/resources/linux/rpm/code.spec.template b/resources/linux/rpm/code.spec.template index 65bc8dfbf16..800f4a209ca 100644 --- a/resources/linux/rpm/code.spec.template +++ b/resources/linux/rpm/code.spec.template @@ -8,7 +8,7 @@ Packager: Visual Studio Code Team License: MIT URL: https://code.visualstudio.com/ Icon: @@NAME@@.xpm -Requires: git +Requires: git, glibc >= 2.15 AutoReq: 0 %description diff --git a/scripts/code-cli.sh b/scripts/code-cli.sh index 17bd0929f62..2719ec4d4b7 100755 --- a/scripts/code-cli.sh +++ b/scripts/code-cli.sh @@ -31,7 +31,7 @@ function code() { VSCODE_DEV=1 \ ELECTRON_ENABLE_LOGGING=1 \ ELECTRON_ENABLE_STACK_DUMPING=1 \ - "$ELECTRON" "$CLI" . $@ + "$ELECTRON" "$CLI" . "$@" } code "$@" diff --git a/src/buildfile.js b/src/buildfile.js index f4f3fb62212..4b08c4ff7c6 100644 --- a/src/buildfile.js +++ b/src/buildfile.js @@ -12,5 +12,5 @@ exports.standaloneLanguages = require('./vs/editor/standalone-languages/buildfil exports.standaloneLanguages2 = require('./vs/languages/buildfile-editor-languages').collectModules(); exports.entrypoint = function (name) { - return [{ name: name, include: [], exclude: ['vs/css', 'vs/nls', 'vs/text'] }]; + return [{ name: name, include: [], exclude: ['vs/css', 'vs/nls'] }]; }; diff --git a/src/main.js b/src/main.js index 2009f835604..25d6dbd1a27 100644 --- a/src/main.js +++ b/src/main.js @@ -65,7 +65,8 @@ function getNLSConfiguration() { } } - locale = locale || app.getLocale(); + var appLocale = app.getLocale(); + locale = locale || appLocale; // Language tags are case insensitve however an amd loader is case sensitive // To make this work on case preserving & insensitive FS we do the following: // the language bundles have lower case language tags and we always lower case @@ -78,23 +79,38 @@ function getNLSConfiguration() { if (process.env['VSCODE_DEV']) { return { locale: locale, availableLanguages: {} }; } + // We have a built version so we have extracted nls file. Try to find // the right file to use. - while (locale) { - var candidate = path.join(__dirname, 'vs', 'code', 'electron-main', 'main.nls.') + locale + '.js'; - if (fs.existsSync(candidate)) { - return { locale: initialLocale, availableLanguages: { '*': locale } }; - } else { - var index = locale.lastIndexOf('-'); - if (index > 0) { - locale = locale.substring(0, index); - } else { - locale = null; - } - } + + // Check if we have an English locale. If so fall to default since that is our + // English translation (we don't ship *.nls.en.json files) + if (locale && (locale == 'en' || locale.startsWith('en-'))) { + return { locale: locale, availableLanguages: {} }; } - return { locale: initialLocale, availableLanguages: {} }; + function resolveLocale(locale) { + while (locale) { + var candidate = path.join(__dirname, 'vs', 'code', 'electron-main', 'main.nls.') + locale + '.js'; + if (fs.existsSync(candidate)) { + return { locale: initialLocale, availableLanguages: { '*': locale } }; + } else { + var index = locale.lastIndexOf('-'); + if (index > 0) { + locale = locale.substring(0, index); + } else { + locale = null; + } + } + } + return null; + } + + var resolvedLocale = resolveLocale(locale); + if (!resolvedLocale && appLocale && appLocale !== locale) { + resolvedLocale = resolveLocale(appLocale); + } + return resolvedLocale ? resolvedLocale : { locale: initialLocale, availableLanguages: {} }; } // Update cwd based on environment and platform diff --git a/src/typings/pty.js.d.ts b/src/typings/pty.js.d.ts new file mode 100644 index 00000000000..cc726238aa2 --- /dev/null +++ b/src/typings/pty.js.d.ts @@ -0,0 +1,23 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'pty.js' { + export function fork(file: string, args: string[], options: any): Terminal; + export function spawn(file: string, args: string[], options: any): Terminal; + export function createTerminal(file: string, args: string[], options: any): Terminal; + + export interface Terminal { + /** + * The title of the active process. + */ + process: string; + + on(event: string, callback: (data: any) => void): void; + + resize(columns: number, rows: number): void; + + write(data: string): void; + } +} \ No newline at end of file diff --git a/src/typings/term.js.d.ts b/src/typings/term.js.d.ts new file mode 100644 index 00000000000..faa6d112d7a --- /dev/null +++ b/src/typings/term.js.d.ts @@ -0,0 +1,17 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'term.js' { + function init(options: any): TermJsTerminal; + + // There seems to be no way to export this so it can be referenced outside of this file when a + // module is a function. + interface TermJsTerminal { + on(event: string, callback: (data: any) => void): void; + resize(columns: number, rows: number): void; + } + + export = init; +} \ No newline at end of file diff --git a/src/vs/base/browser/browser.ts b/src/vs/base/browser/browser.ts index 99fda39e773..f0b00dd77ae 100644 --- a/src/vs/base/browser/browser.ts +++ b/src/vs/base/browser/browser.ts @@ -14,9 +14,12 @@ class ZoomManager { public static INSTANCE = new ZoomManager(); private _zoomLevel: number = 0; + private _pixelRatioCache: number = 0; + private _pixelRatioComputed: boolean = false; private _onDidChangeZoomLevel: Emitter = new Emitter(); public onDidChangeZoomLevel:Event = this._onDidChangeZoomLevel.event; + public getZoomLevel(): number { return this._zoomLevel; } @@ -27,13 +30,36 @@ class ZoomManager { } this._zoomLevel = zoomLevel; + this._pixelRatioComputed = false; this._onDidChangeZoomLevel.fire(this._zoomLevel); } + + public getPixelRatio(): number { + if (!this._pixelRatioComputed) { + this._pixelRatioCache = this._computePixelRatio(); + this._pixelRatioComputed = true; + } + return this._pixelRatioCache; + } + + private _computePixelRatio(): number { + let ctx = document.createElement('canvas').getContext('2d'); + let dpr = window.devicePixelRatio || 1; + let bsr = (ctx).webkitBackingStorePixelRatio || + (ctx).mozBackingStorePixelRatio || + (ctx).msBackingStorePixelRatio || + (ctx).oBackingStorePixelRatio || + (ctx).backingStorePixelRatio || 1; + return dpr / bsr; + } } export function getZoomLevel(): number { return ZoomManager.INSTANCE.getZoomLevel(); } +export function getPixelRatio(): number { + return ZoomManager.INSTANCE.getPixelRatio(); +} export function setZoomLevel(zoomLevel:number): void { ZoomManager.INSTANCE.setZoomLevel(zoomLevel); } diff --git a/src/vs/base/browser/ui/actionbar/actionbar.ts b/src/vs/base/browser/ui/actionbar/actionbar.ts index 8c9d5b6315c..9c124c8275d 100644 --- a/src/vs/base/browser/ui/actionbar/actionbar.ts +++ b/src/vs/base/browser/ui/actionbar/actionbar.ts @@ -15,7 +15,7 @@ import {IAction, IActionRunner, Action, ActionRunner} from 'vs/base/common/actio import DOM = require('vs/base/browser/dom'); import {EventType as CommonEventType} from 'vs/base/common/events'; import types = require('vs/base/common/types'); -import {IEventEmitter, EventEmitter, IEmitterEvent} from 'vs/base/common/eventEmitter'; +import {IEventEmitter, EventEmitter, EmitterEvent} from 'vs/base/common/eventEmitter'; import {Gesture, EventType} from 'vs/base/browser/touch'; import {StandardKeyboardEvent} from 'vs/base/browser/keyboardEvent'; import {CommonKeybindings} from 'vs/base/common/keyCodes'; @@ -33,7 +33,7 @@ export interface IActionItem extends IEventEmitter { export class BaseActionItem extends EventEmitter implements IActionItem { public builder: Builder; - public _callOnDispose: Function[]; + public _callOnDispose: lifecycle.IDisposable[]; public _context: any; public _action: IAction; @@ -48,7 +48,7 @@ export class BaseActionItem extends EventEmitter implements IActionItem { this._action = action; if (action instanceof Action) { - let l = (action).addBulkListener((events: IEmitterEvent[]) => { + let l = (action).addBulkListener2((events: EmitterEvent[]) => { if (!this.builder) { // we have not been rendered yet, so there @@ -56,7 +56,7 @@ export class BaseActionItem extends EventEmitter implements IActionItem { return; } - events.forEach((event: IEmitterEvent) => { + events.forEach((event: EmitterEvent) => { switch (event.getType()) { case Action.ENABLED: @@ -170,7 +170,7 @@ export class BaseActionItem extends EventEmitter implements IActionItem { // implement in subclass } - public _updateUnknown(event: IEmitterEvent): void { + public _updateUnknown(event: EmitterEvent): void { // can implement in subclass } @@ -187,7 +187,7 @@ export class BaseActionItem extends EventEmitter implements IActionItem { this.gesture = null; } - lifecycle.cAll(this._callOnDispose); + this._callOnDispose = lifecycle.dispose(this._callOnDispose); } } @@ -333,13 +333,13 @@ export class ProgressItem extends BaseActionItem { error.textContent = '!'; $(error).addClass('tag', 'error'); - this.callOnDispose.push(this.addListener(CommonEventType.BEFORE_RUN, () => { + this.callOnDispose.push(this.addListener2(CommonEventType.BEFORE_RUN, () => { $(progress).addClass('active'); $(done).removeClass('active'); $(error).removeClass('active'); })); - this.callOnDispose.push(this.addListener(CommonEventType.RUN, (result) => { + this.callOnDispose.push(this.addListener2(CommonEventType.RUN, (result) => { $(progress).removeClass('active'); if (result.error) { $(done).removeClass('active'); @@ -358,7 +358,6 @@ export class ProgressItem extends BaseActionItem { } public dispose(): void { - lifecycle.cAll(this.callOnDispose); super.dispose(); } } @@ -570,7 +569,7 @@ export class ActionBar extends EventEmitter implements IActionRunner { item.actionRunner = this._actionRunner; item.setActionContext(this.context); - this.addEmitter(item); + this.addEmitter2(item); item.render(actionItemElement); if (index === null || index < 0 || index >= this.actionsList.children.length) { diff --git a/src/vs/base/browser/ui/list/listView.ts b/src/vs/base/browser/ui/list/listView.ts index 72a72ee37e0..efaf86b1a4f 100644 --- a/src/vs/base/browser/ui/list/listView.ts +++ b/src/vs/base/browser/ui/list/listView.ts @@ -9,10 +9,9 @@ import { Gesture } from 'vs/base/browser/touch'; import * as DOM from 'vs/base/browser/dom'; import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; import { ScrollbarVisibility } from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; -import { RangeMap, IRange } from './rangeMap'; +import { RangeMap, IRange, relativeComplement, each } from './rangeMap'; import { IDelegate, IRenderer } from './list'; import { RowCache, IRow } from './rowCache'; -import { LcsDiff, ISequence } from 'vs/base/common/diff/diff'; interface IItemRange { item: IItem; @@ -28,13 +27,6 @@ interface IItem { row: IRow; } -function toSequence(itemRanges: IItemRange[]): ISequence { - return { - getLength: () => itemRanges.length, - getElementHash: i => `${ itemRanges[i].item.id }:${ itemRanges[i].range.start }:${ itemRanges[i].range.end }` - }; -} - const MouseEventTypes = [ 'click', 'dblclick', @@ -53,16 +45,12 @@ export class ListView implements IDisposable { private rangeMap: RangeMap; private cache: RowCache; private renderers: { [templateId: string]: IRenderer; }; - private lastRenderTop: number; private lastRenderHeight: number; - private _domNode: HTMLElement; private gesture: Gesture; private rowsContainer: HTMLElement; private scrollableElement: ScrollableElement; - - private toDispose: IDisposable[]; constructor( @@ -110,7 +98,9 @@ export class ListView implements IDisposable { } splice(start: number, deleteCount: number, ...elements: T[]): T[] { - const before = this.getRenderedItemRanges(); + const previousRenderRange = this.getRenderRange(this.lastRenderTop, this.lastRenderHeight); + each(previousRenderRange, i => this.removeItemFromDOM(this.items[i])); + const inserted = elements.map>(element => ({ id: String(this.itemId++), element, @@ -120,21 +110,11 @@ export class ListView implements IDisposable { })); this.rangeMap.splice(start, deleteCount, ...inserted); + const deleted = this.items.splice(start, deleteCount, ...inserted); - const after = this.getRenderedItemRanges(); - const lcs = new LcsDiff(toSequence(before), toSequence(after), null); - const diffs = lcs.ComputeDiff(); - - for (const diff of diffs) { - for (let i = 0; i < diff.originalLength; i++) { - this.removeItemFromDOM(before[diff.originalStart + i].item); - } - - for (let i = 0; i < diff.modifiedLength; i++) { - this.insertItemInDOM(after[diff.modifiedStart + i].item, after[0].index + diff.modifiedStart + i); - } - } + const renderRange = this.getRenderRange(this.lastRenderTop, this.lastRenderHeight); + each(renderRange, i => this.insertItemInDOM(this.items[i], i)); const scrollHeight = this.getContentHeight(); this.rowsContainer.style.height = `${ scrollHeight }px`; @@ -180,52 +160,18 @@ export class ListView implements IDisposable { // Render private render(renderTop: number, renderHeight: number): void { - const renderBottom = renderTop + renderHeight; - const thisRenderBottom = this.lastRenderTop + this.lastRenderHeight; - let i: number, stop: number; + const previousRenderRange = this.getRenderRange(this.lastRenderTop, this.lastRenderHeight); + const renderRange = this.getRenderRange(renderTop, renderHeight); - // when view scrolls down, start rendering from the renderBottom - for (i = this.rangeMap.indexAfter(renderBottom) - 1, stop = this.rangeMap.indexAt(Math.max(thisRenderBottom, renderTop)); i >= stop; i--) { - this.insertItemInDOM(this.items[i], i); - } + const rangesToInsert = relativeComplement(renderRange, previousRenderRange); + const rangesToRemove = relativeComplement(previousRenderRange, renderRange); - // when view scrolls up, start rendering from either this.renderTop or renderBottom - for (i = Math.min(this.rangeMap.indexAt(this.lastRenderTop), this.rangeMap.indexAfter(renderBottom)) - 1, stop = this.rangeMap.indexAt(renderTop); i >= stop; i--) { - this.insertItemInDOM(this.items[i], i); - } - - // when view scrolls down, start unrendering from renderTop - for (i = this.rangeMap.indexAt(this.lastRenderTop), stop = Math.min(this.rangeMap.indexAt(renderTop), this.rangeMap.indexAfter(thisRenderBottom)); i < stop; i++) { - this.removeItemFromDOM(this.items[i]); - } - - // when view scrolls up, start unrendering from either renderBottom this.renderTop - for (i = Math.max(this.rangeMap.indexAfter(renderBottom), this.rangeMap.indexAt(this.lastRenderTop)), stop = this.rangeMap.indexAfter(thisRenderBottom); i < stop; i++) { - this.removeItemFromDOM(this.items[i]); - } + rangesToInsert.forEach(range => each(range, i => this.insertItemInDOM(this.items[i], i))); + rangesToRemove.forEach(range => each(range, i => this.removeItemFromDOM(this.items[i]))); this.rowsContainer.style.transform = `translate3d(0px, -${ renderTop }px, 0px)`; this.lastRenderTop = renderTop; - this.lastRenderHeight = renderBottom - renderTop; - } - - private getRenderedItemRanges(): IItemRange[] { - const result: IItemRange[] = []; - const renderBottom = this.lastRenderTop + this.lastRenderHeight; - - let start = this.lastRenderTop; - let index = this.rangeMap.indexAt(start); - let item = this.items[index]; - let end = -1; - - while (item && start <= renderBottom) { - end = start + item.size; - result.push({ item, index, range: { start, end }}); - start = end; - item = this.items[++index]; - } - - return result; + this.lastRenderHeight = renderHeight; } // DOM operations @@ -304,6 +250,13 @@ export class ListView implements IDisposable { return -1; } + private getRenderRange(renderTop: number, renderHeight: number): IRange { + return { + start: this.rangeMap.indexAt(renderTop), + end: this.rangeMap.indexAfter(renderTop + renderHeight - 1) + }; + } + // Dispose dispose() { diff --git a/src/vs/base/browser/ui/list/rangeMap.ts b/src/vs/base/browser/ui/list/rangeMap.ts index 6036ca411de..d4a459de83c 100644 --- a/src/vs/base/browser/ui/list/rangeMap.ts +++ b/src/vs/base/browser/ui/list/rangeMap.ts @@ -36,6 +36,32 @@ export function intersect(one: IRange, other: IRange): IRange { return { start, end }; } +export function isEmpty(range: IRange): boolean { + return range.end - range.start <= 0; +} + +export function relativeComplement(one: IRange, other: IRange): IRange[] { + const result: IRange[] = []; + const first = { start: one.start, end: Math.min(other.start, one.end) }; + const second = { start: Math.max(other.end, one.start), end: one.end }; + + if (!isEmpty(first)) { + result.push(first); + } + + if (!isEmpty(second)) { + result.push(second); + } + + return result; +} + +export function each(range: IRange, fn: (index : number) => void): void { + for (let i = range.start; i < range.end; i++) { + fn(i); + } +} + /** * Returns the intersection between a ranged group and a range. * Returns `[]` if the intersection is empty. diff --git a/src/vs/base/browser/ui/sash/sash.ts b/src/vs/base/browser/ui/sash/sash.ts index 7f0a32190c9..c4159fe0099 100644 --- a/src/vs/base/browser/ui/sash/sash.ts +++ b/src/vs/base/browser/ui/sash/sash.ts @@ -125,7 +125,7 @@ export class Sash extends EventEmitter { this.emit('start', startEvent); let $window = $(window); - let containerCssClass = `${this.getOrientation()}-cursor-container${isMacintosh ? '-mac' : ''}`; + let containerCSSClass = `${this.getOrientation()}-cursor-container${isMacintosh ? '-mac' : ''}`; let lastCurrentX = startX; let lastCurrentY = startY; @@ -151,12 +151,12 @@ export class Sash extends EventEmitter { this.emit('end'); $window.off('mousemove'); - document.body.classList.remove(containerCssClass); + document.body.classList.remove(containerCSSClass); $(DOM.getElementsByTagName('iframe')).style('pointer-events', 'auto'); }); - document.body.classList.add(containerCssClass); + document.body.classList.add(containerCSSClass); } private onTouchStart(event: GestureEvent): void { diff --git a/src/vs/base/browser/ui/toolbar/toolbar.ts b/src/vs/base/browser/ui/toolbar/toolbar.ts index a1763a663dc..d5bb261ca43 100644 --- a/src/vs/base/browser/ui/toolbar/toolbar.ts +++ b/src/vs/base/browser/ui/toolbar/toolbar.ts @@ -14,7 +14,6 @@ import types = require('vs/base/common/types'); import {Action, IActionRunner, IAction} from 'vs/base/common/actions'; import {ActionBar, ActionsOrientation, IActionItemProvider, BaseActionItem} from 'vs/base/browser/ui/actionbar/actionbar'; import {IContextMenuProvider, DropdownMenu, IActionProvider, ILabelRenderer, IDropdownMenuOptions} from 'vs/base/browser/ui/dropdown/dropdown'; -import {ListenerUnbind} from 'vs/base/common/eventEmitter'; export const CONTEXT = 'context.toolbar'; @@ -162,7 +161,7 @@ class ToggleMenuAction extends Action { export class DropdownMenuActionItem extends BaseActionItem { private menuActionsOrProvider: any; private dropdownMenu: DropdownMenu; - private toUnbind: ListenerUnbind; + private toUnbind: IDisposable; private contextMenuProvider: IContextMenuProvider; private actionItemProvider: IActionItemProvider; private clazz: string; @@ -214,7 +213,7 @@ export class DropdownMenuActionItem extends BaseActionItem { }; // Reemit events for running actions - this.toUnbind = this.addEmitter(this.dropdownMenu); + this.toUnbind = this.addEmitter2(this.dropdownMenu); } public show(): void { @@ -224,7 +223,7 @@ export class DropdownMenuActionItem extends BaseActionItem { } public dispose(): void { - this.toUnbind(); + this.toUnbind.dispose(); this.dropdownMenu.dispose(); super.dispose(); diff --git a/src/vs/base/buildfile.js b/src/vs/base/buildfile.js index 72bbfe455b4..b1084628968 100644 --- a/src/vs/base/buildfile.js +++ b/src/vs/base/buildfile.js @@ -8,9 +8,9 @@ exports.collectModules = function() { return [{ name: 'vs/base/common/worker/workerServer', - exclude: [ 'vs/css', 'vs/nls', 'vs/text' ] + exclude: [ 'vs/css', 'vs/nls' ] }, { name: 'vs/base/common/worker/simpleWorker', - exclude: [ 'vs/css', 'vs/nls', 'vs/text' ] + exclude: [ 'vs/css', 'vs/nls' ] }]; }; diff --git a/src/vs/base/common/actions.ts b/src/vs/base/common/actions.ts index 58f9b721b0f..840d99fec32 100644 --- a/src/vs/base/common/actions.ts +++ b/src/vs/base/common/actions.ts @@ -5,7 +5,7 @@ 'use strict'; import {TPromise} from 'vs/base/common/winjs.base'; -import { IEventEmitter, EventEmitter, ListenerCallback, IBulkListenerCallback, ListenerUnbind } from 'vs/base/common/eventEmitter'; +import { IEventEmitter, EventEmitter } from 'vs/base/common/eventEmitter'; import {IDisposable} from 'vs/base/common/lifecycle'; import * as Events from 'vs/base/common/events'; @@ -199,74 +199,6 @@ export class Action extends EventEmitter implements IAction { } } -class ProxyAction extends Action implements IEventEmitter { - - constructor(private delegate: Action, private runHandler: (e: any) => void) { - super(delegate.id, delegate.label, delegate.class, delegate.enabled, null); - } - - public get id(): string { - return this.delegate.id; - } - - public get label(): string { - return this.delegate.label; - } - - public set label(value: string) { - this.delegate.label = value; - } - - public get class(): string { - return this.delegate.class; - } - - public set class(value: string) { - this.delegate.class = value; - } - - public get enabled(): boolean { - return this.delegate.enabled; - } - - public set enabled(value: boolean) { - this.delegate.enabled = value; - } - - public get checked(): boolean { - return this.delegate.checked; - } - - public set checked(value: boolean) { - this.delegate.checked = value; - } - - public run(event?: any): TPromise { - this.runHandler(event); - return this.delegate.run(event); - } - - public addListener(eventType: string, listener: ListenerCallback): ListenerUnbind { - return this.delegate.addListener(eventType, listener); - } - - public addBulkListener(listener: IBulkListenerCallback): ListenerUnbind { - return this.delegate.addBulkListener(listener); - } - - public addEmitter(eventEmitter: IEventEmitter, emitterType?: string): ListenerUnbind { - return this.delegate.addEmitter(eventEmitter, emitterType); - } - - public addEmitterTypeListener(eventType: string, emitterType: string, listener: ListenerCallback): ListenerUnbind { - return this.delegate.addEmitterTypeListener(eventType, emitterType, listener); - } - - public emit(eventType: string, data?: any): void { - this.delegate.emit(eventType, data); - } -} - export interface IRunEvent { action: IAction; result?: any; diff --git a/src/vs/base/common/async.ts b/src/vs/base/common/async.ts index e69567ee792..4e1030aa48d 100644 --- a/src/vs/base/common/async.ts +++ b/src/vs/base/common/async.ts @@ -2,18 +2,27 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ + 'use strict'; import * as errors from 'vs/base/common/errors'; -import { Promise, TPromise, ValueCallback, ErrorCallback, ProgressCallback } from 'vs/base/common/winjs.base'; import * as platform from 'vs/base/common/platform'; -import {CancellationToken, CancellationTokenSource} from 'vs/base/common/cancellation'; -import {Disposable} from 'vs/base/common/lifecycle'; +import { Promise, TPromise, ValueCallback, ErrorCallback, ProgressCallback } from 'vs/base/common/winjs.base'; +import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; +import { Disposable } from 'vs/base/common/lifecycle'; function isThenable(obj: any): obj is Thenable { return obj && typeof (>obj).then === 'function'; } +export function toThenable(arg: T | Thenable): Thenable { + if (isThenable(arg)) { + return arg; + } else { + return TPromise.as(arg); + } +} + export function asWinJsPromise(callback: (token: CancellationToken) => T | Thenable): TPromise { let source = new CancellationTokenSource(); return new TPromise((resolve, reject) => { @@ -28,6 +37,14 @@ export function asWinJsPromise(callback: (token: CancellationToken) => T | Th }); } +/** + * Hook a cancellation token to a WinJS Promise + */ +export function wireCancellationToken(token: CancellationToken, promise: TPromise): Thenable { + token.onCancellationRequested(() => promise.cancel()); + return promise; +} + export interface ITask { (): T; } @@ -47,9 +64,15 @@ export interface ITask { * var throttler = new Throttler(); * var letters = []; * - * function letterReceived(l) { + * function deliver() { + * const lettersToDeliver = letters; + * letters = []; + * return makeTheTrip(lettersToDeliver); + * } + * + * function onLetterReceived(l) { * letters.push(l); - * throttler.queue(() => { return makeTheTrip(); }); + * throttler.queue(deliver); * } */ export class Throttler { @@ -64,7 +87,7 @@ export class Throttler { this.queuedPromiseFactory = null; } - public queue(promiseFactory: ITask>): TPromise { + queue(promiseFactory: ITask>): TPromise { if (this.activePromise) { this.queuedPromiseFactory = promiseFactory; @@ -145,7 +168,7 @@ export class Delayer { this.task = null; } - public trigger(task: ITask, delay: number = this.defaultDelay): TPromise { + trigger(task: ITask, delay: number = this.defaultDelay): TPromise { this.task = task; this.cancelTimeout(); @@ -172,11 +195,11 @@ export class Delayer { return this.completionPromise; } - public isTriggered(): boolean { + isTriggered(): boolean { return this.timeout !== null; } - public cancel(): void { + cancel(): void { this.cancelTimeout(); if (this.completionPromise) { @@ -210,7 +233,7 @@ export class ThrottledDelayer extends Delayer> { this.throttler = new Throttler(); } - public trigger(promiseFactory: ITask>, delay?: number): Promise { + trigger(promiseFactory: ITask>, delay?: number): Promise { return super.trigger(() => this.throttler.queue(promiseFactory), delay); } } @@ -231,7 +254,7 @@ export class PeriodThrottledDelayer extends ThrottledDelayer { this.periodThrottler = new Throttler(); } - public trigger(promiseFactory: ITask>, delay?: number): Promise { + trigger(promiseFactory: ITask>, delay?: number): Promise { return super.trigger(() => { return this.periodThrottler.queue(() => { return Promise.join([ @@ -399,8 +422,8 @@ export class Limiter { this.runningPromises = 0; } - public queue(promiseFactory: ITask): Promise; - public queue(promiseFactory: ITask>): TPromise { + queue(promiseFactory: ITask): Promise; + queue(promiseFactory: ITask>): TPromise { return new TPromise((c, e, p) => { this.outstandingPromises.push({ factory: promiseFactory, @@ -438,19 +461,19 @@ export class TimeoutTimer extends Disposable { this._token = -1; } - public dispose(): void { + dispose(): void { this.cancel(); super.dispose(); } - public cancel(): void { + cancel(): void { if (this._token !== -1) { platform.clearTimeout(this._token); this._token = -1; } } - public cancelAndSet(runner: () => void, timeout:number): void { + cancelAndSet(runner: () => void, timeout:number): void { this.cancel(); this._token = platform.setTimeout(() => { this._token = -1; @@ -458,7 +481,7 @@ export class TimeoutTimer extends Disposable { }, timeout); } - public setIfNotSet(runner: () => void, timeout: number): void { + setIfNotSet(runner: () => void, timeout: number): void { if (this._token !== -1) { // timer is already set return; @@ -479,19 +502,19 @@ export class IntervalTimer extends Disposable { this._token = -1; } - public dispose(): void { + dispose(): void { this.cancel(); super.dispose(); } - public cancel(): void { + cancel(): void { if (this._token !== -1) { platform.clearInterval(this._token); this._token = -1; } } - public cancelAndSet(runner: () => void, interval:number): void { + cancelAndSet(runner: () => void, interval:number): void { this.cancel(); this._token = platform.setInterval(() => { runner(); @@ -516,7 +539,7 @@ export class RunOnceScheduler { /** * Dispose RunOnceScheduler */ - public dispose(): void { + dispose(): void { this.cancel(); this.runner = null; } @@ -524,7 +547,7 @@ export class RunOnceScheduler { /** * Cancel current scheduled runner (if any). */ - public cancel(): void { + cancel(): void { if (this.isScheduled()) { platform.clearTimeout(this.timeoutToken); this.timeoutToken = -1; @@ -534,21 +557,14 @@ export class RunOnceScheduler { /** * Replace runner. If there is a runner already scheduled, the new runner will be called. */ - public setRunner(runner: () => void): void { + setRunner(runner: () => void): void { this.runner = runner; } - /** - * Set timeout. This change will only impact new schedule calls. - */ - public setTimeout(timeout: number): void { - this.timeout = timeout; - } - /** * Cancel previous runner (if any) & schedule a new runner. */ - public schedule(): void { + schedule(delay = this.timeout): void { this.cancel(); this.timeoutToken = platform.setTimeout(this.timeoutHandler, this.timeout); } @@ -556,7 +572,7 @@ export class RunOnceScheduler { /** * Returns true if scheduled. */ - public isScheduled(): boolean { + isScheduled(): boolean { return this.timeoutToken !== -1; } diff --git a/src/vs/base/common/errors.ts b/src/vs/base/common/errors.ts index 0bdcb986ad6..24ac4ae2794 100644 --- a/src/vs/base/common/errors.ts +++ b/src/vs/base/common/errors.ts @@ -380,8 +380,10 @@ export function illegalState(name?: string): Error { } } -export function readonly(): Error { - return new Error('readonly property cannot be changed'); +export function readonly(name?: string): Error { + return name + ? new Error(`readonly property '${name} cannot be changed'`) + : new Error('readonly property cannot be changed'); } export function loaderError(err: Error): Error { diff --git a/src/vs/base/common/eventEmitter.ts b/src/vs/base/common/eventEmitter.ts index 6244c03be62..bb5fcb8a319 100644 --- a/src/vs/base/common/eventEmitter.ts +++ b/src/vs/base/common/eventEmitter.ts @@ -5,23 +5,16 @@ 'use strict'; import Errors = require('vs/base/common/errors'); -import Lifecycle = require('vs/base/common/lifecycle'); +import {IDisposable} from 'vs/base/common/lifecycle'; -export interface IEmitterEvent { - getType():string; - getData():any; -} - -export class EmitterEvent implements IEmitterEvent { +export class EmitterEvent { private _type:string; private _data:any; - private _emitterType:string; - constructor(eventType:string=null, data:any=null, emitterType:string=null) { + constructor(eventType:string=null, data:any=null) { this._type = eventType; this._data = data; - this._emitterType = emitterType; } public getType():string { @@ -31,37 +24,21 @@ export class EmitterEvent implements IEmitterEvent { public getData():any { return this._data; } - - public getEmitterType():string { - return this._emitterType; - } } export interface ListenerCallback { (value:any):void; } -export interface IBulkListenerCallback { - (value:IEmitterEvent[]):void; +export interface BulkListenerCallback { + (value:EmitterEvent[]):void; } -export interface ListenerUnbind { - ():void; -} - -export interface IEventEmitter extends Lifecycle.IDisposable { - addListener(eventType:string, listener:ListenerCallback):ListenerUnbind; - addListener2(eventType:string, listener:ListenerCallback):Lifecycle.IDisposable; - addOneTimeListener(eventType:string, listener:ListenerCallback):ListenerUnbind; - - addBulkListener(listener:IBulkListenerCallback):ListenerUnbind; - addBulkListener2(listener:IBulkListenerCallback):Lifecycle.IDisposable; - - addEmitter(eventEmitter:IEventEmitter, emitterType?:string):ListenerUnbind; - addEmitter2(eventEmitter:IEventEmitter, emitterType?:string):Lifecycle.IDisposable; - - addEmitterTypeListener(eventType:string, emitterType:string, listener:ListenerCallback):ListenerUnbind; - emit(eventType:string, data?:any):void; +export interface IEventEmitter extends IDisposable { + addListener2(eventType:string, listener:ListenerCallback):IDisposable; + addOneTimeDisposableListener(eventType:string, listener:ListenerCallback):IDisposable; + addBulkListener2(listener:BulkListenerCallback):IDisposable; + addEmitter2(eventEmitter:IEventEmitter):IDisposable; } export interface IListenersMap { @@ -99,7 +76,7 @@ export class EventEmitter implements IEventEmitter { this._allowedEventTypes = null; } - public addListener(eventType:string, listener:ListenerCallback):ListenerUnbind { + private addListener(eventType:string, listener:ListenerCallback):IDisposable { if (eventType === '*') { throw new Error('Use addBulkListener(listener) to register your listener!'); } @@ -115,73 +92,56 @@ export class EventEmitter implements IEventEmitter { } var bound = this; - return () => { - if (!bound) { - // Already called - return; - } - - bound._removeListener(eventType, listener); - - // Prevent leakers from holding on to the event emitter - bound = null; - listener = null; - }; - } - - public addListener2(eventType:string, listener:ListenerCallback):Lifecycle.IDisposable { - var dispose = this.addListener(eventType, listener); return { - dispose: dispose + dispose: () => { + if (!bound) { + // Already called + return; + } + + bound._removeListener(eventType, listener); + + // Prevent leakers from holding on to the event emitter + bound = null; + listener = null; + } }; } - public on(eventType:string, listener:ListenerCallback):ListenerUnbind { + public addListener2(eventType:string, listener:ListenerCallback):IDisposable { return this.addListener(eventType, listener); } - public addOneTimeListener(eventType:string, listener:ListenerCallback):ListenerUnbind { - var unbind:ListenerUnbind = this.addListener(eventType, function(value:any) { - unbind(); + private addOneTimeListener(eventType:string, listener:ListenerCallback):IDisposable { + var unbind = this.addListener(eventType, (value:any) => { + unbind.dispose(); listener(value); }); return unbind; } - public addOneTimeDisposableListener(eventType:string, listener:ListenerCallback):Lifecycle.IDisposable { - var dispose = this.addOneTimeListener(eventType, listener); - return { - dispose: dispose - }; + public addOneTimeDisposableListener(eventType:string, listener:ListenerCallback):IDisposable { + return this.addOneTimeListener(eventType, listener); } - public addBulkListener(listener:IBulkListenerCallback):ListenerUnbind { + protected addBulkListener(listener:BulkListenerCallback):IDisposable { this._bulkListeners.push(listener); - return () => { - this._removeBulkListener(listener); - }; - } - - public addBulkListener2(listener:IBulkListenerCallback):Lifecycle.IDisposable { - var dispose = this.addBulkListener(listener); return { - dispose: dispose + dispose: () => { + this._removeBulkListener(listener); + } }; } - public addEmitter(eventEmitter:IEventEmitter, emitterType:string=null):ListenerUnbind { - return eventEmitter.addBulkListener((events:IEmitterEvent[]):void => { - var newEvents = events; + public addBulkListener2(listener:BulkListenerCallback):IDisposable { + return this.addBulkListener(listener); + } - if (emitterType) { - // If the emitter has an emitterType, recreate events - newEvents = []; - for (var i = 0, len = events.length; i < len; i++) { - newEvents.push(new EmitterEvent(events[i].getType(), events[i].getData(), emitterType)); - } - } + private addEmitter(eventEmitter:IEventEmitter):IDisposable { + return eventEmitter.addBulkListener2((events:EmitterEvent[]):void => { + var newEvents = events; if (this._deferredCnt === 0) { this._emitEvents(newEvents); @@ -192,23 +152,8 @@ export class EventEmitter implements IEventEmitter { }); } - public addEmitter2(eventEmitter:IEventEmitter, emitterType?:string):Lifecycle.IDisposable { - var dispose = this.addEmitter(eventEmitter, emitterType); - return { - dispose: dispose - }; - } - - public addEmitterTypeListener(eventType:string, emitterType:string, listener:ListenerCallback):ListenerUnbind { - if (emitterType) { - if (eventType === '*') { - throw new Error('Bulk listeners cannot specify an emitter type'); - } - - return this.addListener(eventType + '/' + emitterType, listener); - } else { - return this.addListener(eventType, listener); - } + public addEmitter2(eventEmitter:IEventEmitter):IDisposable { + return this.addEmitter(eventEmitter); } private _removeListener(eventType:string, listener:ListenerCallback): void { @@ -224,7 +169,7 @@ export class EventEmitter implements IEventEmitter { } } - private _removeBulkListener(listener:IBulkListenerCallback): void { + private _removeBulkListener(listener:BulkListenerCallback): void { for (var i = 0, len = this._bulkListeners.length; i < len; i++) { if (this._bulkListeners[i] === listener) { this._bulkListeners.splice(i, 1); @@ -257,9 +202,6 @@ export class EventEmitter implements IEventEmitter { var e = events[i]; this._emitToSpecificTypeListeners(e.getType(), e.getData()); - if (e.getEmitterType()) { - this._emitToSpecificTypeListeners(e.getType() + '/' + e.getEmitterType(), e.getData()); - } } } diff --git a/src/vs/editor/common/core/idGenerator.ts b/src/vs/base/common/idGenerator.ts similarity index 87% rename from src/vs/editor/common/core/idGenerator.ts rename to src/vs/base/common/idGenerator.ts index 6a66c7da582..34ce058ff84 100644 --- a/src/vs/editor/common/core/idGenerator.ts +++ b/src/vs/base/common/idGenerator.ts @@ -14,7 +14,9 @@ export class IdGenerator { this._lastId = 0; } - public generate(): string { + public nextId(): string { return this._prefix + (++this._lastId); } } + +export const defaultGenerator = new IdGenerator('id#'); \ No newline at end of file diff --git a/src/vs/base/common/json.ts b/src/vs/base/common/json.ts index 6b578d2c8a9..ef62924c4e0 100644 --- a/src/vs/base/common/json.ts +++ b/src/vs/base/common/json.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import nls = require('vs/nls'); +import {localize} from 'vs/nls'; export enum ScanError { None, @@ -35,19 +35,50 @@ export enum SyntaxKind { EOF } +/** + * The scanner object, representing a JSON scanner at a position in the input string. + */ export interface JSONScanner { + /** + * Sets the scan position to a new offset. A call to 'scan' is needed to get the first token. + */ + setPosition(pos: number); + /** + * Read the next token. Returns the tolen code. + */ scan(): SyntaxKind; + /** + * Returns the current scan position, which is after the last read token. + */ getPosition(): number; + /** + * Returns the last read token. + */ getToken(): SyntaxKind; + /** + * Returns the last read token value. The value for strings is the decoded string content. For numbers its of type number, for boolean it's true or false. + */ getTokenValue(): string; + /** + * The start offset of the last read token. + */ getTokenOffset(): number; + /** + * The length of the last read token. + */ getTokenLength(): number; + /** + * An error code of the last scan. + */ getTokenError(): ScanError; } - +/** + * Creates a JSON scanner on the given text. + * If ignoreTrivia is set, whitespaces or comments are ignored. + */ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONScanner { - var pos = 0, + let pos = 0, len = text.length, value:string = '', tokenOffset = 0, @@ -55,10 +86,10 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca scanError:ScanError = ScanError.None; function scanHexDigits(count: number, exact?: boolean): number { - var digits = 0; - var value = 0; + let digits = 0; + let value = 0; while (digits < count || !exact) { - var ch = text.charCodeAt(pos); + let ch = text.charCodeAt(pos); if (ch >= CharacterCodes._0 && ch <= CharacterCodes._9) { value = value * 16 + ch - CharacterCodes._0; } @@ -80,8 +111,16 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca return value; } + function setPosition(newPosition: number) { + pos = newPosition; + value = ''; + tokenOffset = 0; + token = SyntaxKind.Unknown; + scanError = ScanError.None; + } + function scanNumber(): string { - var start = pos; + let start = pos; if (text.charCodeAt(pos) === CharacterCodes._0) { pos++; } else { @@ -99,10 +138,10 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca } } else { scanError = ScanError.UnexpectedEndOfNumber; - return text.substring(start, end); + return text.substring(start, pos); } } - var end = pos; + let end = pos; if (pos < text.length && (text.charCodeAt(pos) === CharacterCodes.E || text.charCodeAt(pos) === CharacterCodes.e)) { pos++; if (pos < text.length && text.charCodeAt(pos) === CharacterCodes.plus || text.charCodeAt(pos) === CharacterCodes.minus) { @@ -123,7 +162,7 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca function scanString(): string { - var result = '', + let result = '', start = pos; while (true) { @@ -132,7 +171,7 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca scanError = ScanError.UnexpectedEndOfString; break; } - var ch = text.charCodeAt(pos); + let ch = text.charCodeAt(pos); if (ch === CharacterCodes.doubleQuote) { result += text.substring(start, pos); pos++; @@ -172,7 +211,7 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca result += '\t'; break; case CharacterCodes.u: - var ch = scanHexDigits(4, true); + let ch = scanHexDigits(4, true); if (ch >= 0) { result += String.fromCharCode(ch); } else { @@ -208,7 +247,7 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca return token = SyntaxKind.EOF; } - var code = text.charCodeAt(pos); + let code = text.charCodeAt(pos); // trivia: whitespace if (isWhiteSpace(code)) { do { @@ -260,7 +299,7 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca // comments case CharacterCodes.slash: - var start = pos - 1; + let start = pos - 1; // Single-line comment if (text.charCodeAt(pos + 1) === CharacterCodes.slash) { pos += 2; @@ -280,10 +319,10 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) { pos += 2; - var safeLength = len - 1; // For lookahead. - var commentClosed = false; + let safeLength = len - 1; // For lookahead. + let commentClosed = false; while (pos < safeLength) { - var ch = text.charCodeAt(pos); + let ch = text.charCodeAt(pos); if (ch === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) { pos += 2; @@ -371,7 +410,7 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca function scanNextNonTrivia():SyntaxKind { - var result : SyntaxKind; + let result : SyntaxKind; do { result = scanNext(); } while (result >= SyntaxKind.LineCommentTrivia && result <= SyntaxKind.Trivia); @@ -379,6 +418,7 @@ export function createScanner(text:string, ignoreTrivia:boolean = false):JSONSca } return { + setPosition: setPosition, getPosition: () => pos, scan: ignoreTrivia ? scanNextNonTrivia : scanNext, getToken: () => token, @@ -403,10 +443,6 @@ function isDigit(ch: number): boolean { return ch >= CharacterCodes._0 && ch <= CharacterCodes._9; } -export function isLetter(ch: number): boolean { - return ch >= CharacterCodes.a && ch <= CharacterCodes.z || ch >= CharacterCodes.A && ch <= CharacterCodes.Z; -} - enum CharacterCodes { nullCharacter = 0, maxAsciiCharacter = 0x7F, @@ -552,7 +588,7 @@ enum CharacterCodes { */ export function stripComments(text:string, replaceCh?:string):string { - var _scanner = createScanner(text), + let _scanner = createScanner(text), parts: string[] = [], kind:SyntaxKind, offset = 0, @@ -579,23 +615,421 @@ export function stripComments(text:string, replaceCh?:string):string { return parts.join(''); } -export function parse(text:string, errors: string[] = []) : any { - var noMatch = Object(); - var _scanner = createScanner(text, true); +export interface ParseError { + error: ParseErrorCode; +} - function scanNext() : SyntaxKind { - var token = _scanner.scan(); - while (token === SyntaxKind.Unknown) { - handleError(nls.localize('UnknownSymbol', 'Invalid symbol')); - token = _scanner.scan(); +export enum ParseErrorCode { + InvalidSymbol, + InvalidNumberFormat, + PropertyNameExpected, + ValueExpected, + ColonExpected, + CommaExpected, + CloseBraceExpected, + CloseBracketExpected, + EndOfFileExpected +} + +export function getParseErrorMessage(errorCode: ParseErrorCode) : string { + switch (errorCode) { + case ParseErrorCode.InvalidSymbol: return localize('error.invalidSymbol', 'Invalid symbol'); + case ParseErrorCode.InvalidNumberFormat: return localize('error.invalidNumberFormat', 'Invalid number format'); + case ParseErrorCode.PropertyNameExpected: return localize('error.propertyNameExpected', 'Property name expected'); + case ParseErrorCode.ValueExpected: return localize('error.valueExpected', 'Value expected'); + case ParseErrorCode.ColonExpected: return localize('error.colonExpected', 'Colon expected'); + case ParseErrorCode.CommaExpected: return localize('error.commaExpected', 'Comma expected'); + case ParseErrorCode.CloseBraceExpected: return localize('error.closeBraceExpected', 'Closing brace expected'); + case ParseErrorCode.CloseBracketExpected: return localize('error.closeBracketExpected', 'Closing bracket expected'); + case ParseErrorCode.EndOfFileExpected: return localize('error.endOfFileExpected', 'End of file expected'); + default: + return ''; + } +} + +export type NodeType = "object" | "array" | "property" | "string" | "number" | "boolean" | "null"; + +function getLiteralNodeType(value: any) : NodeType { + switch (typeof value) { + case 'boolean': return 'boolean'; + case 'number': return 'number'; + case 'string': return 'string'; + default: return 'null'; + } +} + +export interface Node { + type: NodeType; + value?: any; + offset: number; + length: number; + columnOffset?: number; + parent?: Node; + children?: Node[]; +} + +export type Segment = string | number; +export type JSONPath = Segment[]; + +export interface Location { + /** + * The previous property key or literal value (string, number, boolean or null) or undefined. + */ + previousNode?: Node; + /** + * The path describing the location in the JSON document. The path consists of a sequence strings + * representing an object property or numbers for array indices. + */ + path: JSONPath; + /** + * Matches the locations path against a pattern consisting of strings (for properties) and numbers (for array indices). + * '*' will match a single segment, of any property name or index. + * '**' will match a sequece of segments or no segment, of any property name or index. + */ + matches: (patterns: JSONPath) => boolean; + /** + * If set, the location's offset is at a property key. + */ + isAtPropertyKey: boolean; +} + + +/** + * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index. + */ +export function getLocation(text:string, position: number) : Location { + let segments: any[] = []; // strings or numbers + let earlyReturnException = new Object(); + let previousNode : Node = void 0; + const previousNodeInst : Node = { + value: void 0, + offset: void 0, + length: void 0, + type: void 0 + }; + let isAtPropertyKey = false; + function setPreviousNode(value: string, offset: number, length: number, type: NodeType) { + previousNodeInst.value = value; + previousNodeInst.offset = offset; + previousNodeInst.length = length; + previousNodeInst.type = type; + previousNodeInst.columnOffset = void 0; + previousNode = previousNodeInst; + } + try { + + visit(text, { + onObjectBegin: (offset: number, length: number) => { + if (position <= offset) { + throw earlyReturnException; + } + previousNode = void 0; + isAtPropertyKey = position > offset; + segments.push(''); // push a placeholder (will be replaced or removed) + }, + onObjectProperty: (name: string, offset: number, length: number) => { + if (position < offset) { + throw earlyReturnException; + } + setPreviousNode(name, offset, length, 'property'); + segments[segments.length - 1] = name; + if (position <= offset + length) { + throw earlyReturnException; + } + }, + onObjectEnd: (offset: number, length: number) => { + if (position <= offset) { + throw earlyReturnException; + } + previousNode = void 0; + segments.pop(); + }, + onArrayBegin: (offset: number, length: number) => { + if (position <= offset) { + throw earlyReturnException; + } + previousNode = void 0; + segments.push(0); + }, + onArrayEnd: (offset: number, length: number) => { + if (position <= offset) { + throw earlyReturnException; + } + previousNode = void 0; + segments.pop(); + }, + onLiteralValue: (value: any, offset: number, length: number) => { + if (position < offset) { + throw earlyReturnException; + } + setPreviousNode(value, offset, length, getLiteralNodeType(value)); + + if (position <= offset + length) { + throw earlyReturnException; + } + }, + onSeparator: (sep: string, offset: number, length: number) => { + if (position <= offset) { + throw earlyReturnException; + } + if (sep === ':' && previousNode.type === 'property') { + previousNode.columnOffset = offset; + isAtPropertyKey = false; + previousNode = void 0; + } else if (sep === ',') { + let last = segments[segments.length - 1]; + if (typeof last === 'number') { + segments[segments.length - 1] = last + 1; + } else { + isAtPropertyKey = true; + segments[segments.length - 1] = ''; + } + previousNode = void 0; + } + } + }); + } catch (e) { + if (e !== earlyReturnException) { + throw e; } - return token; } - function handleError(message:string, skipUntilAfter: SyntaxKind[] = [], skipUntil: SyntaxKind[] = []) : void { - errors.push(message); + if (segments[segments.length - 1] === '') { + segments.pop(); + } + return { + path: segments, + previousNode, + isAtPropertyKey, + matches: (pattern: string[]) => { + let k = 0; + for (let i = 0; k < pattern.length && i < segments.length; i++) { + if (pattern[k] === segments[i] || pattern[k] === '*') { + k++; + } else if (pattern[k] !== '**') { + return false; + } + } + return k === pattern.length; + } + }; +} + +export interface ParseOptions { + disallowComments?: boolean; +} + +/** + * Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result. + * Therefore always check the errors list to find out if the input was valid. + */ +export function parse(text:string, errors: ParseError[] = [], options?: ParseOptions) : any { + let currentProperty : string = null; + let currentParent : any = []; + let previousParents : any[] = []; + + function onValue(value: any) { + if (Array.isArray(currentParent)) { + ( currentParent).push(value); + } else if (currentProperty) { + currentParent[currentProperty] = value; + } + } + + let visitor : JSONVisitor = { + onObjectBegin: () => { + let object = {}; + onValue(object); + previousParents.push(currentParent); + currentParent = object; + currentProperty = null; + }, + onObjectProperty: (name: string) => { + currentProperty = name; + }, + onObjectEnd: () => { + currentParent = previousParents.pop(); + }, + onArrayBegin: () => { + let array = []; + onValue(array); + previousParents.push(currentParent); + currentParent = array; + currentProperty = null; + }, + onArrayEnd: () => { + currentParent = previousParents.pop(); + }, + onLiteralValue: onValue, + onError:(error:ParseErrorCode) => { + errors.push({error: error}); + } + }; + visit(text, visitor, options); + return currentParent[0]; +} + + +/** + * Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result. + */ +export function parseTree(text:string, errors: ParseError[] = [], options?: ParseOptions) : Node { + let currentParent : Node = { type: 'array', offset: -1, length: -1, children: [] }; // artificial root + + function ensurePropertyComplete(endOffset:number) { + if (currentParent.type === 'property') { + currentParent.length = endOffset - currentParent.offset; + currentParent = currentParent.parent; + } + } + + function onValue(valueNode: Node) : Node { + currentParent.children.push(valueNode); + ensurePropertyComplete(valueNode.offset + valueNode.length); + return valueNode; + } + + let visitor : JSONVisitor = { + onObjectBegin: (offset: number) => { + currentParent = onValue({ type: 'object', offset, length: -1, parent: currentParent, children: [] }); + }, + onObjectProperty: (name: string, offset: number, length: number) => { + currentParent = onValue({ type: 'property', offset, length: -1, parent: currentParent, children: [] }); + currentParent.children.push({ type: 'string', value: name, offset, length, parent: currentParent}); + }, + onObjectEnd: (offset: number, length: number) => { + ensurePropertyComplete(offset); + currentParent.length = offset + length - currentParent.offset; + currentParent = currentParent.parent; + }, + onArrayBegin: (offset: number, length: number) => { + currentParent = onValue({ type: 'array', offset, length: -1, parent: currentParent, children: [] }); + }, + onArrayEnd: (offset: number, length: number) => { + currentParent.length = offset + length - currentParent.offset; + currentParent = currentParent.parent; + }, + onLiteralValue: (value: any, offset: number, length: number) => { + onValue({ type: getLiteralNodeType(value), offset, length, parent: currentParent, value }); + }, + onSeparator: (sep: string, offset: number, length: number) => { + if (currentParent.type === 'property') { + if (sep === ':') { + currentParent.columnOffset = offset; + } else if (sep === ',') { + ensurePropertyComplete(offset); + } + } + }, + onError:(error:ParseErrorCode) => { + errors.push({error: error}); + } + }; + visit(text, visitor, options); + + let result = currentParent.children[0]; + if (result) { + delete result.parent; + } + return result; +} + +export function findNodeAtLocation(root: Node, path: JSONPath) : Node { + if (!root) { + return void 0; + } + let node = root; + for (let segment of path) { + if (typeof segment === 'string') { + if (node.type !== 'object') { + return void 0; + } + let found = false; + for (let propertyNode of node.children) { + if (propertyNode.children[0].value === segment) { + node = propertyNode.children[1]; + found = true; + break; + } + } + if (!found) { + return void 0; + } + } else { + let index = segment; + if (node.type !== 'array' || index < 0 || index >= node.children.length) { + return void 0; + } + node = node.children[index]; + } + } + return node; +} + +export function getNodeValue(node: Node) : any { + if (node.type === 'array') { + return node.children.map(getNodeValue); + } else if (node.type === 'object') { + let obj = {}; + for (let prop of node.children) { + obj[prop.children[0].value] = getNodeValue(prop.children[1]); + } + return obj; + } + return node.value; +} + + +/** + * Parses the given text and invokes the visitor functions for each object, array and literal reached. + */ +export function visit(text:string, visitor: JSONVisitor, options?: ParseOptions) : any { + + let _scanner = createScanner(text, false); + + function toNoArgVisit(visitFunction: (offset: number, length: number) => void) : () => void { + return visitFunction ? () => visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength()) : () => true; + } + function toOneArgVisit(visitFunction: (arg: T, offset: number, length: number) => void) : (arg: T) => void { + return visitFunction ? (arg: T) => visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength()) : () => true; + } + + let onObjectBegin = toNoArgVisit(visitor.onObjectBegin), + onObjectProperty = toOneArgVisit(visitor.onObjectProperty), + onObjectEnd = toNoArgVisit(visitor.onObjectEnd), + onArrayBegin = toNoArgVisit(visitor.onArrayBegin), + onArrayEnd = toNoArgVisit(visitor.onArrayEnd), + onLiteralValue = toOneArgVisit(visitor.onLiteralValue), + onSeparator = toOneArgVisit(visitor.onSeparator), + onError = toOneArgVisit(visitor.onError); + + let disallowComments = options && options.disallowComments; + function scanNext() : SyntaxKind { + while (true) { + let token = _scanner.scan(); + switch (token) { + case SyntaxKind.LineCommentTrivia: + case SyntaxKind.BlockCommentTrivia: + if (disallowComments) { + handleError(ParseErrorCode.InvalidSymbol); + } + break; + case SyntaxKind.Unknown: + handleError(ParseErrorCode.InvalidSymbol); + break; + case SyntaxKind.Trivia: + case SyntaxKind.LineBreakTrivia: + break; + default: + return token; + } + } + } + + function handleError(error:ParseErrorCode, skipUntilAfter: SyntaxKind[] = [], skipUntil: SyntaxKind[] = []) : void { + onError(error); if (skipUntilAfter.length + skipUntil.length > 0) { - var token = _scanner.getToken(); + let token = _scanner.getToken(); while (token !== SyntaxKind.EOF) { if (skipUntilAfter.indexOf(token) !== -1) { scanNext(); @@ -608,156 +1042,189 @@ export function parse(text:string, errors: string[] = []) : any { } } - function parseString() : any { + function parseString(isValue: boolean) : boolean { if (_scanner.getToken() !== SyntaxKind.StringLiteral) { - return noMatch; + return false; + } + let value = _scanner.getTokenValue(); + if (isValue) { + onLiteralValue(value); + } else { + onObjectProperty(value); } - var value = _scanner.getTokenValue(); scanNext(); - return value; + return true; } - function parseLiteral() : any { - var value : any; + function parseLiteral() : boolean { switch (_scanner.getToken()) { case SyntaxKind.NumericLiteral: + let value = 0; try { value = JSON.parse(_scanner.getTokenValue()); if (typeof value !== 'number') { - handleError(nls.localize('InvalidNumberFormat', 'Invalid number format')); + handleError(ParseErrorCode.InvalidNumberFormat); value = 0; } } catch (e) { - value = 0; + handleError(ParseErrorCode.InvalidNumberFormat); } + onLiteralValue(value); break; case SyntaxKind.NullKeyword: - value = null; + onLiteralValue(null); break; case SyntaxKind.TrueKeyword: - value = true; + onLiteralValue(true); break; case SyntaxKind.FalseKeyword: - value = false; + onLiteralValue(false); break; default: - return noMatch; + return false; } scanNext(); - return value; + return true; } - function parseProperty(result: any) : any { - var key = parseString(); - if (key === noMatch) { - handleError(nls.localize('PropertyExpected', 'Property name expected'), [], [SyntaxKind.CloseBraceToken, SyntaxKind.CommaToken] ); + function parseProperty() : boolean { + if (!parseString(false)) { + handleError(ParseErrorCode.PropertyNameExpected, [], [SyntaxKind.CloseBraceToken, SyntaxKind.CommaToken] ); return false; } if (_scanner.getToken() === SyntaxKind.ColonToken) { + onSeparator(':'); scanNext(); // consume colon - var value = parseValue(); - if (value !== noMatch) { - result[key] = value; - } else { - handleError(nls.localize('ValueExpected', 'Value expected'), [], [SyntaxKind.CloseBraceToken, SyntaxKind.CommaToken] ); + if (!parseValue()) { + handleError(ParseErrorCode.ValueExpected, [], [SyntaxKind.CloseBraceToken, SyntaxKind.CommaToken] ); } } else { - handleError(nls.localize('ColonExpected', 'Colon expected'), [], [SyntaxKind.CloseBraceToken, SyntaxKind.CommaToken] ); + handleError(ParseErrorCode.ColonExpected, [], [SyntaxKind.CloseBraceToken, SyntaxKind.CommaToken] ); } return true; } - function parseObject() : any { + function parseObject() : boolean { if (_scanner.getToken() !== SyntaxKind.OpenBraceToken) { - return noMatch; + return false; } - var obj = {}; + onObjectBegin(); scanNext(); // consume open brace - var needsComma = false; + let needsComma = false; while (_scanner.getToken() !== SyntaxKind.CloseBraceToken && _scanner.getToken() !== SyntaxKind.EOF) { if (_scanner.getToken() === SyntaxKind.CommaToken) { if (!needsComma) { - handleError(nls.localize('ValueExpected', 'Value expected'), [], [] ); + handleError(ParseErrorCode.ValueExpected, [], [] ); } + onSeparator(','); scanNext(); // consume comma } else if (needsComma) { - handleError(nls.localize('CommaExpected', 'Comma expected'), [], [] ); + handleError(ParseErrorCode.CommaExpected, [], [] ); } - var propertyParsed = parseProperty(obj); - if (!propertyParsed) { - handleError(nls.localize('ValueExpected', 'Value expected'), [], [SyntaxKind.CloseBraceToken, SyntaxKind.CommaToken] ); + if (!parseProperty()) { + handleError(ParseErrorCode.ValueExpected, [], [SyntaxKind.CloseBraceToken, SyntaxKind.CommaToken] ); } needsComma = true; } - + onObjectEnd(); if (_scanner.getToken() !== SyntaxKind.CloseBraceToken) { - handleError(nls.localize('CloseBraceExpected', 'Closing brace expected'), [SyntaxKind.CloseBraceToken], []); + handleError(ParseErrorCode.CloseBraceExpected, [SyntaxKind.CloseBraceToken], []); } else { scanNext(); // consume close brace } - return obj; + return true; } - function parseArray() : any { + function parseArray() : boolean { if (_scanner.getToken() !== SyntaxKind.OpenBracketToken) { - return noMatch; + return false; } - var arr: any[] = []; + onArrayBegin(); scanNext(); // consume open bracket - var needsComma = false; + let needsComma = false; while (_scanner.getToken() !== SyntaxKind.CloseBracketToken && _scanner.getToken() !== SyntaxKind.EOF) { if (_scanner.getToken() === SyntaxKind.CommaToken) { if (!needsComma) { - handleError(nls.localize('ValeExpected', 'Value expected'), [], [] ); + handleError(ParseErrorCode.ValueExpected, [], [] ); } + onSeparator(','); scanNext(); // consume comma } else if (needsComma) { - handleError(nls.localize('CommaExpected', 'Comma expected'), [], [] ); + handleError(ParseErrorCode.CommaExpected, [], [] ); } - var value = parseValue(); - if (value === noMatch) { - handleError(nls.localize('ValueExpected', 'Value expected'), [], [SyntaxKind.CloseBracketToken, SyntaxKind.CommaToken] ); - } else { - arr.push(value); + if (!parseValue()) { + handleError(ParseErrorCode.ValueExpected, [], [SyntaxKind.CloseBracketToken, SyntaxKind.CommaToken] ); } needsComma = true; } - + onArrayEnd(); if (_scanner.getToken() !== SyntaxKind.CloseBracketToken) { - handleError(nls.localize('CloseBracketExpected', 'Closing bracket expected'), [SyntaxKind.CloseBracketToken], []); + handleError(ParseErrorCode.CloseBracketExpected, [SyntaxKind.CloseBracketToken], []); } else { scanNext(); // consume close bracket } - return arr; + return true; } - function parseValue() : any { - var result = parseArray(); - if (result !== noMatch) { - return result; - } - result = parseObject(); - if (result !== noMatch) { - return result; - } - result = parseString(); - if (result !== noMatch) { - return result; - } - return parseLiteral(); + function parseValue() : boolean { + return parseArray() || parseObject() || parseString(true) || parseLiteral(); } scanNext(); - var value = parseValue(); - if (value === noMatch) { - handleError(nls.localize('ValueExpected', 'Value expected'), [], []); - return void 0; + if (_scanner.getToken() === SyntaxKind.EOF) { + return true; + } + if (!parseValue()) { + handleError(ParseErrorCode.ValueExpected, [], []); + return false; } if (_scanner.getToken() !== SyntaxKind.EOF) { - handleError(nls.localize('EOFExpected', 'End of content expected'), [], []); + handleError(ParseErrorCode.EndOfFileExpected, [], []); } - return value; + return true; +} + +export interface JSONVisitor { + /** + * Invoked when an open brace is encountered and an object is started. The offset and length represent the location of the open brace. + */ + onObjectBegin?: (offset:number, length:number) => void; + + /** + * Invoked when a property is encountered. The offset and length represent the location of the property name. + */ + onObjectProperty?: (property: string, offset:number, length:number) => void; + + /** + * Invoked when a closing brace is encountered and an object is completed. The offset and length represent the location of the closing brace. + */ + onObjectEnd?: (offset:number, length:number) => void; + + /** + * Invoked when an open bracket is encountered. The offset and length represent the location of the open bracket. + */ + onArrayBegin?: (offset:number, length:number) => void; + + /** + * Invoked when a closing bracket is encountered. The offset and length represent the location of the closing bracket. + */ + onArrayEnd?: (offset:number, length:number) => void; + + /** + * Invoked when a literal value is encountered. The offset and length represent the location of the literal value. + */ + onLiteralValue?: (value: any, offset:number, length:number) => void; + + /** + * Invoked when a comma or colon separator is encountered. The offset and length represent the location of the separator. + */ + onSeparator?: (charcter: string, offset:number, length:number) => void; + + /** + * Invoked on an error. + */ + onError?: (error: ParseErrorCode, offset:number, length:number) => void; } diff --git a/src/vs/base/common/jsonEdit.ts b/src/vs/base/common/jsonEdit.ts new file mode 100644 index 00000000000..b02004fd88d --- /dev/null +++ b/src/vs/base/common/jsonEdit.ts @@ -0,0 +1,108 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { ParseError, Node, parseTree, findNodeAtLocation, JSONPath, Segment } from 'vs/base/common/json'; +import { Edit, FormattingOptions, format, applyEdit } from 'vs/base/common/jsonFormatter'; + +export function removeProperty(text: string, path: JSONPath, formattingOptions: FormattingOptions) : Edit[] { + return setProperty(text, path, void 0, formattingOptions); +} + +export function setProperty(text: string, path: JSONPath, value: any, formattingOptions: FormattingOptions, getInsertionIndex?: (properties: string[]) => number) : Edit[] { + let errors: ParseError[] = []; + let root = parseTree(text, errors); + let parent: Node = void 0; + + let lastSegment: Segment = void 0; + while (path.length > 0) { + lastSegment = path.pop(); + parent = findNodeAtLocation(root, path); + if (parent === void 0 && value !== void 0) { + if (typeof lastSegment === 'string') { + value = { [lastSegment]: value }; + } else { + value = [ value ]; + } + } else { + break; + } + } + + if (!parent) { + // empty document + if (value === void 0) { // delete + throw new Error('Can not delete in empty document'); + } + return withFormatting(text, { offset: root ? root.offset : 0, length: root ? root.length : 0, content: JSON.stringify(value) }, formattingOptions); + } else if (parent.type === 'object' && typeof lastSegment === 'string') { + let existing = findNodeAtLocation(parent, [ lastSegment ]); + if (existing !== void 0) { + if (value === void 0) { // delete + let propertyIndex = parent.children.indexOf(existing.parent); + let removeBegin : number; + let removeEnd = existing.parent.offset + existing.parent.length; + if (propertyIndex > 0) { + // remove the comma of the previous node + let previous = parent.children[propertyIndex - 1]; + removeBegin = previous.offset + previous.length; + } else { + removeBegin = parent.offset + 1; + if (parent.children.length > 1) { + // remove the comma of the next node + let next = parent.children[1]; + removeEnd = next.offset; + } + } + return withFormatting(text, { offset: removeBegin, length: removeEnd - removeBegin, content: '' }, formattingOptions); + } else { + // set value of existing property + return [{ offset: existing.offset, length: existing.length, content: JSON.stringify(value) }]; + } + } else { + if (value === void 0) { // delete + throw new Error(`Property ${lastSegment} does not exist.`); + } + let newProperty = `${JSON.stringify(lastSegment)}: ${JSON.stringify(value)}`; + let index = getInsertionIndex ? getInsertionIndex(parent.children.map(p => p.children[0].value)) : parent.children.length; + let edit: Edit; + if (index > 0) { + let previous = parent.children[index - 1]; + edit = { offset: previous.offset + previous.length, length: 0, content: ',' + newProperty}; + } else if (parent.children.length === 0) { + edit = { offset: parent.offset + 1, length: 0, content: newProperty}; + } else { + edit = { offset: parent.offset + 1, length: 0, content: newProperty + ','}; + } + return withFormatting(text, edit, formattingOptions); + } + } else if (parent.type === 'array' && typeof lastSegment === 'number') { + throw new Error('Array modification not supported yet'); + } else { + throw new Error(`Can not add ${typeof lastSegment !== 'number' ? 'index' : 'property' } to parent of type ${parent.type}`); + } +} + +function withFormatting(text:string, edit: Edit, formattingOptions: FormattingOptions) : Edit[] { + // apply the edit + let newText = applyEdit(text, edit); + + // format the new text + let begin = edit.offset; + let end = edit.offset + edit.content.length; + let edits = format(newText, { offset: begin, length: end - begin }, formattingOptions); + + // apply the formatting edits and track the begin and end offsets of the changes + for (let i = edits.length - 1; i >= 0; i--) { + let edit = edits[i]; + newText = applyEdit(newText, edit); + begin = Math.min(begin, edit.offset); + end = Math.max(end, edit.offset + edit.length); + end += edit.content.length - edit.length; + } + // create a single edit with all changes + let editLength = text.length - (newText.length - end) - begin; + return [{ offset: begin, length: editLength, content: newText.substring(begin, end) }]; +} \ No newline at end of file diff --git a/src/vs/base/common/jsonFormatter.ts b/src/vs/base/common/jsonFormatter.ts new file mode 100644 index 00000000000..686ecd48b0c --- /dev/null +++ b/src/vs/base/common/jsonFormatter.ts @@ -0,0 +1,214 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import Json = require('./json'); + +export interface FormattingOptions { + /** + * If indentation is based on spaces (`insertSpaces` = true), then what is the number of spaces that make an indent? + */ + tabSize: number; + /** + * Is indentation based on spaces? + */ + insertSpaces: boolean; + /** + * The default end of line line character + */ + eol: string; +} + +export interface Edit { + offset: number; + length: number; + content: string; +} + +export function applyEdit(text: string, edit: Edit) : string { + return text.substring(0, edit.offset) + edit.content + text.substring(edit.offset + edit.length); +} + +export function applyEdits(text: string, edits: Edit[]) : string { + for (let i = edits.length - 1; i >= 0; i--) { + text = applyEdit(text, edits[i]); + } + return text; +} + +export function format(documentText: string, range: { offset: number, length: number}, options: FormattingOptions): Edit[] { + let initialIndentLevel: number; + let value: string; + let rangeStart: number; + let rangeEnd: number; + if (range) { + rangeStart = range.offset; + rangeEnd = rangeStart + range.length; + while (rangeStart > 0 && !isEOL(documentText, rangeStart - 1)) { + rangeStart--; + } + let scanner = Json.createScanner(documentText, true); + scanner.setPosition(rangeEnd); + scanner.scan(); + rangeEnd = scanner.getPosition(); + + value = documentText.substring(rangeStart, rangeEnd); + initialIndentLevel = computeIndentLevel(value, 0, options); + } else { + value = documentText; + rangeStart = 0; + rangeEnd = documentText.length; + initialIndentLevel = 0; + } + let eol = getEOL(options, documentText); + + let lineBreak = false; + let indentLevel = 0; + let indentValue: string; + if (options.insertSpaces) { + indentValue = repeat(' ', options.tabSize); + } else { + indentValue = '\t'; + } + + let scanner = Json.createScanner(value, false); + + function newLineAndIndent(): string { + return eol + repeat(indentValue, initialIndentLevel + indentLevel); + } + function scanNext(): Json.SyntaxKind { + let token = scanner.scan(); + lineBreak = false; + while (token === Json.SyntaxKind.Trivia || token === Json.SyntaxKind.LineBreakTrivia) { + lineBreak = lineBreak || (token === Json.SyntaxKind.LineBreakTrivia); + token = scanner.scan(); + } + return token; + } + let editOperations: Edit[] = []; + function addEdit(text: string, startOffset: number, endOffset: number) { + if (documentText.substring(startOffset, endOffset) !== text) { + editOperations.push({ offset: startOffset, length: endOffset - startOffset, content: text }); + } + } + + let firstToken = scanNext(); + if (firstToken !== Json.SyntaxKind.EOF) { + let firstTokenStart = scanner.getTokenOffset() + rangeStart; + let initialIndent = repeat(indentValue, initialIndentLevel); + addEdit(initialIndent, rangeStart, firstTokenStart); + } + + while (firstToken !== Json.SyntaxKind.EOF) { + let firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + rangeStart; + let secondToken = scanNext(); + + let replaceContent = ''; + while (!lineBreak && (secondToken === Json.SyntaxKind.LineCommentTrivia || secondToken === Json.SyntaxKind.BlockCommentTrivia)) { + // comments on the same line: keep them on the same line, but ignore them otherwise + let commentTokenStart = scanner.getTokenOffset() + rangeStart; + addEdit(' ', firstTokenEnd, commentTokenStart); + firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + rangeStart; + replaceContent = secondToken === Json.SyntaxKind.LineCommentTrivia ? newLineAndIndent() : ''; + secondToken = scanNext(); + } + + if (secondToken === Json.SyntaxKind.CloseBraceToken) { + if (firstToken !== Json.SyntaxKind.OpenBraceToken) { + indentLevel--; + replaceContent = newLineAndIndent(); + } + } else if (secondToken === Json.SyntaxKind.CloseBracketToken) { + if (firstToken !== Json.SyntaxKind.OpenBracketToken) { + indentLevel--; + replaceContent = newLineAndIndent(); + } + } else if (secondToken !== Json.SyntaxKind.EOF) { + switch (firstToken) { + case Json.SyntaxKind.OpenBracketToken: + case Json.SyntaxKind.OpenBraceToken: + indentLevel++; + replaceContent = newLineAndIndent(); + break; + case Json.SyntaxKind.CommaToken: + case Json.SyntaxKind.LineCommentTrivia: + replaceContent = newLineAndIndent(); + break; + case Json.SyntaxKind.BlockCommentTrivia: + if (lineBreak) { + replaceContent = newLineAndIndent(); + } else { + // symbol following comment on the same line: keep on same line, separate with ' ' + replaceContent = ' '; + } + break; + case Json.SyntaxKind.ColonToken: + replaceContent = ' '; + break; + case Json.SyntaxKind.NullKeyword: + case Json.SyntaxKind.TrueKeyword: + case Json.SyntaxKind.FalseKeyword: + case Json.SyntaxKind.NumericLiteral: + if (secondToken === Json.SyntaxKind.NullKeyword || secondToken === Json.SyntaxKind.FalseKeyword || secondToken === Json.SyntaxKind.NumericLiteral) { + replaceContent = ' '; + } + break; + } + if (lineBreak && (secondToken === Json.SyntaxKind.LineCommentTrivia || secondToken === Json.SyntaxKind.BlockCommentTrivia)) { + replaceContent = newLineAndIndent(); + } + + } + let secondTokenStart = scanner.getTokenOffset() + rangeStart; + addEdit(replaceContent, firstTokenEnd, secondTokenStart); + firstToken = secondToken; + } + return editOperations; +} + +function repeat(s: string, count: number): string { + let result = ''; + for (let i = 0; i < count; i++) { + result += s; + } + return result; +} + +function computeIndentLevel(content: string, offset: number, options: FormattingOptions): number { + let i = 0; + let nChars = 0; + let tabSize = options.tabSize || 4; + while (i < content.length) { + let ch = content.charAt(i); + if (ch === ' ') { + nChars++; + } else if (ch === '\t') { + nChars += tabSize; + } else { + break; + } + i++; + } + return Math.floor(nChars / tabSize); +} + +function getEOL(options: FormattingOptions, text: string): string { + for (let i = 0; i < text.length; i++) { + let ch = text.charAt(i); + if (ch === '\r') { + if (i + 1 < text.length && text.charAt(i+1) === '\n') { + return '\r\n'; + } + return '\r'; + } else if (ch === '\n') { + return '\n'; + } + } + return (options && options.eol) || '\n'; +} + +function isEOL(text: string, offset: number) { + return '\r\n'.indexOf(text.charAt(offset)) !== -1; +} \ No newline at end of file diff --git a/src/vs/base/common/lifecycle.ts b/src/vs/base/common/lifecycle.ts index 12268356fde..0ad5adb3487 100644 --- a/src/vs/base/common/lifecycle.ts +++ b/src/vs/base/common/lifecycle.ts @@ -37,32 +37,6 @@ export function toDisposable(...fns: (() => void)[]): IDisposable { return combinedDisposable(fns.map(fn => ({ dispose: fn }))); } -function callAll(arg: any): any { - if (!arg) { - return null; - } else if (typeof arg === 'function') { - arg(); - return null; - } else if (Array.isArray(arg)) { - while (arg.length > 0) { - arg.pop()(); - } - return arg; - } else { - return null; - } -} - -export interface CallAll { - (fn: Function): Function; - (fn: Function[]): Function[]; -} - -/** - * Calls all functions that are being passed to it. - */ -export const cAll: CallAll = callAll; - export abstract class Disposable implements IDisposable { private _toDispose: IDisposable[]; diff --git a/src/vs/base/common/winjs.base.d.ts b/src/vs/base/common/winjs.base.d.ts index 860c2c9b9ac..2b29355a65b 100644 --- a/src/vs/base/common/winjs.base.d.ts +++ b/src/vs/base/common/winjs.base.d.ts @@ -95,6 +95,7 @@ export declare class TPromise { public static is(value: any): value is TPromise; public static timeout(delay:number):TPromise; public static join(promises:TPromise[]):TPromise; + public static join(promises:Thenable[]):Thenable; public static join(promises: {[n:string]:TPromise}):TPromise<{[n:string]:ValueType}>; public static any(promises:TPromise[]):TPromise<{ key:string; value:TPromise;}>; public static wrapError(error:any):TPromise; diff --git a/src/vs/base/common/worker/simpleWorker.ts b/src/vs/base/common/worker/simpleWorker.ts index b786c8fe5f2..27d03229491 100644 --- a/src/vs/base/common/worker/simpleWorker.ts +++ b/src/vs/base/common/worker/simpleWorker.ts @@ -157,9 +157,10 @@ class SimpleWorkerProtocol { export class SimpleWorkerClient extends Disposable { private _worker:IWorker; - private _onModuleLoaded:TPromise; + private _onModuleLoaded:TPromise; private _protocol: SimpleWorkerProtocol; private _proxy: T; + private _lazyProxy: TPromise; private _lastRequestTimestamp = -1; constructor(workerFactory:IWorkerFactory, moduleId:string, ctor:any) { @@ -190,13 +191,30 @@ export class SimpleWorkerClient extends Disposable { loaderConfiguration = (window).requirejs.s.contexts._.config; } + let lazyProxyFulfill : (v:T)=>void = null; + let lazyProxyReject: (err:any)=>void = null; + + this._lazyProxy = new TPromise((c, e, p) => { + lazyProxyFulfill = c; + lazyProxyReject = e; + }, () => { /* no cancel */ }); + // Send initialize message this._onModuleLoaded = this._protocol.sendMessage(INITIALIZE, [ this._worker.getId(), moduleId, loaderConfiguration ]); - this._onModuleLoaded.then(null, (e) => this._onError('Worker failed to load ' + moduleId, e)); + this._onModuleLoaded.then((availableMethods:string[]) => { + let proxy = {}; + for (let i = 0; i < availableMethods.length; i++) { + proxy[availableMethods[i]] = createProxyMethod(availableMethods[i], proxyMethodRequest); + } + lazyProxyFulfill(proxy); + }, (e) => { + lazyProxyReject(e); + this._onError('Worker failed to load ' + moduleId, e); + }); // Create proxy to loaded code let proxyMethodRequest = (method:string, args:any[]):TPromise => { @@ -211,10 +229,13 @@ export class SimpleWorkerClient extends Disposable { }; this._proxy = {}; - for (let prop in ctor.prototype) { - if (ctor.prototype.hasOwnProperty(prop)) { - if (typeof ctor.prototype[prop] === 'function') { - this._proxy[prop] = createProxyMethod(prop, proxyMethodRequest); + if (ctor) { + // console.warn('deprecated'); + for (let prop in ctor.prototype) { + if (ctor.prototype.hasOwnProperty(prop)) { + if (typeof ctor.prototype[prop] === 'function') { + this._proxy[prop] = createProxyMethod(prop, proxyMethodRequest); + } } } } @@ -224,6 +245,10 @@ export class SimpleWorkerClient extends Disposable { return this._proxy; } + public getProxyObject(): TPromise { + return this._lazyProxy; + } + public getLastRequestTimestamp(): number { return this._lastRequestTimestamp; } @@ -323,7 +348,15 @@ export class SimpleWorkerServer { require([moduleId], (...result:any[]) => { let handlerModule = result[0]; this._requestHandler = handlerModule.create(); - cc(null); + + let methods: string[] = []; + for (let prop in this._requestHandler) { + if (typeof this._requestHandler[prop] === 'function') { + methods.push(prop); + } + } + + cc(methods); }, ee); return r; diff --git a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts index 4527892af4e..9485bff2531 100644 --- a/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts +++ b/src/vs/base/parts/quickopen/browser/quickOpenWidget.ts @@ -80,7 +80,7 @@ export class QuickOpenWidget implements IModelProvider { private visible: boolean; private isLoosingFocus: boolean; private callbacks: IQuickOpenCallbacks; - private toUnbind: { (): void; }[]; + private toUnbind: IDisposable[]; private currentInputToken: string; private quickNavigateConfiguration: IQuickNavigateConfiguration; private container: HTMLElement; @@ -111,7 +111,7 @@ export class QuickOpenWidget implements IModelProvider { this.builder = $().div((div: Builder) => { // Eventing - div.on(DOM.EventType.KEY_UP, (e: KeyboardEvent) => { + div.on(DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => { let keyboardEvent: StandardKeyboardEvent = new StandardKeyboardEvent(e); if (keyboardEvent.keyCode === KeyCode.Escape) { DOM.EventHelper.stop(e, true); @@ -141,7 +141,6 @@ export class QuickOpenWidget implements IModelProvider { this.inputElement.setAttribute('aria-haspopup', 'false'); this.inputElement.setAttribute('aria-autocomplete', 'list'); - // Listen to some keys on key-down for faster type feedback DOM.addDisposableListener(this.inputBox.inputElement, DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => { let keyboardEvent: StandardKeyboardEvent = new StandardKeyboardEvent(e); @@ -157,17 +156,8 @@ export class QuickOpenWidget implements IModelProvider { this.navigateInTree(keyboardEvent.keyCode, keyboardEvent.shiftKey); } - // Bug in IE 9: onInput is not fired for Backspace or Delete keys - else if (browser.isIE9 && (keyboardEvent.keyCode === KeyCode.Backspace || keyboardEvent.keyCode === KeyCode.Delete)) { - this.onType(); - } - }); - - DOM.addDisposableListener(this.inputBox.inputElement, DOM.EventType.KEY_UP, (e: KeyboardEvent) => { - let keyboardEvent: StandardKeyboardEvent = new StandardKeyboardEvent(e); - // Select element on Enter - if (keyboardEvent.keyCode === KeyCode.Enter) { + else if (keyboardEvent.keyCode === KeyCode.Enter) { DOM.EventHelper.stop(e, true); let focus = this.tree.getFocus(); @@ -175,6 +165,11 @@ export class QuickOpenWidget implements IModelProvider { this.elementSelected(focus, e); } } + + // Bug in IE 9: onInput is not fired for Backspace or Delete keys + else if (browser.isIE9 && (keyboardEvent.keyCode === KeyCode.Backspace || keyboardEvent.keyCode === KeyCode.Delete)) { + this.onType(); + } }); DOM.addDisposableListener(this.inputBox.inputElement, DOM.EventType.INPUT, (e: Event) => { @@ -203,11 +198,11 @@ export class QuickOpenWidget implements IModelProvider { this.treeElement = this.tree.getHTMLElement(); // Handle Focus and Selection event - this.toUnbind.push(this.tree.addListener(EventType.FOCUS, (event: IFocusEvent) => { + this.toUnbind.push(this.tree.addListener2(EventType.FOCUS, (event: IFocusEvent) => { this.elementFocused(event.focus, event); })); - this.toUnbind.push(this.tree.addListener(EventType.SELECTION, (event: ISelectionEvent) => { + this.toUnbind.push(this.tree.addListener2(EventType.SELECTION, (event: ISelectionEvent) => { if (event.selection && event.selection.length > 0) { this.elementSelected(event.selection[0], event); } @@ -840,9 +835,7 @@ export class QuickOpenWidget implements IModelProvider { } public dispose(): void { - while (this.toUnbind.length) { - this.toUnbind.pop()(); - } + this.toUnbind = dispose(this.toUnbind); this.progressBar.dispose(); this.inputBox.dispose(); diff --git a/src/vs/base/parts/tree/browser/tree.ts b/src/vs/base/parts/tree/browser/tree.ts index 2915e3c4f9a..c20a5bba7af 100644 --- a/src/vs/base/parts/tree/browser/tree.ts +++ b/src/vs/base/parts/tree/browser/tree.ts @@ -14,6 +14,8 @@ import { ScrollbarVisibility } from 'vs/base/browser/ui/scrollbar/scrollableElem export interface ITree extends Events.IEventEmitter { + emit(eventType:string, data?:any):void; + /** * Returns the tree's DOM element. */ diff --git a/src/vs/base/parts/tree/browser/treeImpl.ts b/src/vs/base/parts/tree/browser/treeImpl.ts index d75bd92cbfd..a614cd10ae9 100644 --- a/src/vs/base/parts/tree/browser/treeImpl.ts +++ b/src/vs/base/parts/tree/browser/treeImpl.ts @@ -76,8 +76,8 @@ export class Tree extends Events.EventEmitter implements _.ITree { this.view.setModel(this.model); - this.addEmitter(this.model); - this.addEmitter(this.view); + this.addEmitter2(this.model); + this.addEmitter2(this.view); } public getHTMLElement(): HTMLElement { diff --git a/src/vs/base/parts/tree/browser/treeModel.ts b/src/vs/base/parts/tree/browser/treeModel.ts index 5dbb33dc5a7..1b80259f5aa 100644 --- a/src/vs/base/parts/tree/browser/treeModel.ts +++ b/src/vs/base/parts/tree/browser/treeModel.ts @@ -81,13 +81,13 @@ export class Lock { var lock = this.getLock(item); if (lock) { - var unbindListener: Events.ListenerUnbind; + var unbindListener: IDisposable; return new WinJS.Promise((c, e) => { - unbindListener = lock.addOneTimeListener('unlock', () => { + unbindListener = lock.addOneTimeDisposableListener('unlock', () => { return this.run(item, fn).then(c, e); }); - }, () => unbindListener()); + }, () => { unbindListener.dispose(); }); } var result: WinJS.Promise; diff --git a/src/vs/base/parts/tree/browser/treeView.ts b/src/vs/base/parts/tree/browser/treeView.ts index 4dc7492aaae..612cc6d1b72 100644 --- a/src/vs/base/parts/tree/browser/treeView.ts +++ b/src/vs/base/parts/tree/browser/treeView.ts @@ -401,7 +401,7 @@ export class TreeView extends HeightMap { private static currentExternalDragAndDropData: _.IDragAndDropData = null; private context: IViewContext; - private modelListeners: { (): void; }[]; + private modelListeners: Lifecycle.IDisposable[]; private model: Model.TreeModel; private viewListeners: Lifecycle.IDisposable[]; @@ -663,7 +663,7 @@ export class TreeView extends HeightMap { this.releaseModel(); this.model = newModel; - this.modelListeners.push(this.model.addBulkListener((e) => this.onModelEvents(e))); + this.modelListeners.push(this.model.addBulkListener2((e) => this.onModelEvents(e))); } private onModelEvents(events:any[]): void { @@ -1588,9 +1588,7 @@ export class TreeView extends HeightMap { private releaseModel(): void { if (this.model) { - while (this.modelListeners.length) { - this.modelListeners.pop()(); - } + this.modelListeners = Lifecycle.dispose(this.modelListeners); this.model = null; } } diff --git a/src/vs/base/parts/tree/test/browser/treeModel.test.ts b/src/vs/base/parts/tree/test/browser/treeModel.test.ts index 8a797e1bab8..de245ea490a 100644 --- a/src/vs/base/parts/tree/test/browser/treeModel.test.ts +++ b/src/vs/base/parts/tree/test/browser/treeModel.test.ts @@ -1302,23 +1302,23 @@ suite('TreeModel - Dynamic data model', () => { model.collapse('father'); var times = 0; - var listener = dataModel.addListener('getChildren', (element) => { + var listener = dataModel.addListener2('getChildren', (element) => { times++; assert.equal(element, 'grandfather'); }); model.refresh('grandfather').done(() => { assert.equal(times, 1); - listener(); + listener.dispose(); - listener = dataModel.addListener('getChildren', (element) => { + listener = dataModel.addListener2('getChildren', (element) => { times++; assert.equal(element, 'father'); }); model.expand('father').done(() => { assert.equal(times, 2); - listener(); + listener.dispose(); done(); }); }); @@ -1351,8 +1351,8 @@ suite('TreeModel - Dynamic data model', () => { var getTimes = 0; var gotTimes = 0; - var getListener = dataModel.addListener('getChildren', (element) => { getTimes++; }); - var gotListener = dataModel.addListener('gotChildren', (element) => { gotTimes++; }); + var getListener = dataModel.addListener2('getChildren', (element) => { getTimes++; }); + var gotListener = dataModel.addListener2('gotChildren', (element) => { gotTimes++; }); var p1 = model.refresh('father'); assert.equal(getTimes, 1); @@ -1373,8 +1373,8 @@ suite('TreeModel - Dynamic data model', () => { assert.equal(nav.next().id, 'sister'); assert.equal(nav.next() && false, null); - getListener(); - gotListener(); + getListener.dispose(); + gotListener.dispose(); done(); }); }); @@ -1399,10 +1399,10 @@ suite('TreeModel - Dynamic data model', () => { counter.listen(model, 'item:refresh', (e) => { refreshTimes++; }); var getTimes = 0; - var getListener = dataModel.addListener('getChildren', (element) => { getTimes++; }); + var getListener = dataModel.addListener2('getChildren', (element) => { getTimes++; }); var gotTimes = 0; - var gotListener = dataModel.addListener('gotChildren', (element) => { gotTimes++; }); + var gotListener = dataModel.addListener2('gotChildren', (element) => { gotTimes++; }); var p1, p2; @@ -1455,8 +1455,8 @@ suite('TreeModel - Dynamic data model', () => { assert.equal(nav.next().id, 'son'); assert.equal(nav.next() && false, null); - getListener(); - gotListener(); + getListener.dispose(); + gotListener.dispose(); done(); }); }); @@ -1479,8 +1479,8 @@ suite('TreeModel - Dynamic data model', () => { var getTimes = 0; var gotTimes = 0; - var getListener = dataModel.addListener('getChildren', (element) => { getTimes++; }); - var gotListener = dataModel.addListener('gotChildren', (element) => { gotTimes++; }); + var getListener = dataModel.addListener2('getChildren', (element) => { getTimes++; }); + var gotListener = dataModel.addListener2('gotChildren', (element) => { gotTimes++; }); var p1, p2; @@ -1521,8 +1521,8 @@ suite('TreeModel - Dynamic data model', () => { assert.equal(nav.next().id, 'son'); assert.equal(nav.next() && false, null); - getListener(); - gotListener(); + getListener.dispose(); + gotListener.dispose(); done(); }); }); diff --git a/src/vs/base/test/common/eventEmitter.test.ts b/src/vs/base/test/common/eventEmitter.test.ts index 19dcc0e6c9e..ff206fbc94a 100644 --- a/src/vs/base/test/common/eventEmitter.test.ts +++ b/src/vs/base/test/common/eventEmitter.test.ts @@ -21,7 +21,7 @@ suite('EventEmitter', () => { test('add listener, emit other event type', function () { var didCall = false; - eventEmitter.addListener('eventType1', function (e) { + eventEmitter.addListener2('eventType1', function (e) { didCall = true; }); eventEmitter.emit('eventType2', {}); @@ -30,7 +30,7 @@ suite('EventEmitter', () => { test('add listener, emit event', function () { var didCall = false; - eventEmitter.addListener('eventType', function (e) { + eventEmitter.addListener2('eventType', function (e) { didCall = true; }); eventEmitter.emit('eventType', {}); @@ -39,11 +39,11 @@ suite('EventEmitter', () => { test('add 2 listeners, emit event', function () { var didCallFirst = false; - eventEmitter.addListener('eventType', function (e) { + eventEmitter.addListener2('eventType', function (e) { didCallFirst = true; }); var didCallSecond = false; - eventEmitter.addListener('eventType', function (e) { + eventEmitter.addListener2('eventType', function (e) { didCallSecond = true; }); eventEmitter.emit('eventType', {}); @@ -53,22 +53,22 @@ suite('EventEmitter', () => { test('add 1 listener, remove it, emit event', function () { var didCall = false; - var remove = eventEmitter.addListener('eventType', function (e) { + var remove = eventEmitter.addListener2('eventType', function (e) { didCall = true; }); - remove(); + remove.dispose(); eventEmitter.emit('eventType', {}); assert(!didCall); }); test('add 2 listeners, emit event, remove one while processing', function () { var firstCallCount = 0; - var remove1 = eventEmitter.addListener('eventType', function (e) { + var remove1 = eventEmitter.addListener2('eventType', function (e) { firstCallCount++; - remove1(); + remove1.dispose(); }); var secondCallCount = 0; - eventEmitter.addListener('eventType', function (e) { + eventEmitter.addListener2('eventType', function (e) { secondCallCount++; }); eventEmitter.emit('eventType', {}); @@ -79,7 +79,7 @@ suite('EventEmitter', () => { test('event object is assert', function () { var data: any; - eventEmitter.addListener('eventType', function (e) { + eventEmitter.addListener2('eventType', function (e) { data = e.data; }); eventEmitter.emit('eventType', { data: 5 }); @@ -88,7 +88,7 @@ suite('EventEmitter', () => { test('deferred emit', function () { var calledCount = 0; - eventEmitter.addListener('eventType', function (e) { + eventEmitter.addListener2('eventType', function (e) { calledCount++; }); eventEmitter.deferredEmit(function () { @@ -103,11 +103,11 @@ suite('EventEmitter', () => { test('deferred emit maintains events order', function () { var order = 0; - eventEmitter.addListener('eventType2', function (e) { + eventEmitter.addListener2('eventType2', function (e) { order++; assert.equal(order, 1); }); - eventEmitter.addListener('eventType1', function (e) { + eventEmitter.addListener2('eventType1', function (e) { order++; assert.equal(order, 2); }); @@ -120,7 +120,7 @@ suite('EventEmitter', () => { test('deferred emit maintains events order for bulk listeners', function () { var count = 0; - eventEmitter.addBulkListener(function (events) { + eventEmitter.addBulkListener2(function (events) { assert.equal(events[0].getType(), 'eventType2'); assert.equal(events[1].getType(), 'eventType1'); count++; @@ -134,7 +134,7 @@ suite('EventEmitter', () => { test('emit notifies bulk listeners', function () { var count = 0; - eventEmitter.addBulkListener(function (events) { + eventEmitter.addBulkListener2(function (events) { count++; }); eventEmitter.emit('eventType', {}); @@ -145,13 +145,13 @@ suite('EventEmitter', () => { var emitter = new EventEmitter(); var eventBus = new EventEmitter(); - eventBus.addEmitter(emitter, 'emitter1'); + eventBus.addEmitter2(emitter); var didCallFirst = false; - eventBus.addListener('eventType', function (e) { + eventBus.addListener2('eventType', function (e) { didCallFirst = true; }); var didCallSecond = false; - eventBus.addListener('eventType/emitter1', function (e) { + eventBus.addListener2('eventType', function (e) { didCallSecond = true; }); @@ -166,17 +166,13 @@ suite('EventEmitter', () => { var emitter2 = new EventEmitter(); var eventBus = new EventEmitter(); - eventBus.addEmitter(emitter1, 'emitter1'); - eventBus.addEmitter(emitter2, 'emitter2'); - eventBus.addListener('eventType1', function (e) { + eventBus.addEmitter2(emitter1); + eventBus.addEmitter2(emitter2); + eventBus.addListener2('eventType1', function (e) { assert(true); callCnt++; }); - eventBus.addListener('eventType1/emitter1', function (e) { - assert(true); - callCnt++; - }); - eventBus.addEmitterTypeListener('eventType1', 'emitter1', function (e) { + eventBus.addListener2('eventType1', function (e) { assert(true); callCnt++; }); @@ -196,12 +192,12 @@ suite('EventEmitter', () => { var emitter3 = new EventEmitter(); var emitter4 = new EventEmitter(); - emitter2.addEmitter(emitter1); - emitter3.addEmitter(emitter2); - emitter4.addEmitter(emitter3); + emitter2.addEmitter2(emitter1); + emitter3.addEmitter2(emitter2); + emitter4.addEmitter2(emitter3); var didCall = false; - emitter4.addListener('eventType', function (e) { + emitter4.addListener2('eventType', function (e) { didCall = true; }); @@ -213,16 +209,16 @@ suite('EventEmitter', () => { var emitter = new EventEmitter(); var actualCallOrder: string[] = []; - emitter.addListener('foo', function() { + emitter.addListener2('foo', function() { actualCallOrder.push('listener1-foo'); emitter.emit('bar'); }); - emitter.addListener('foo', function() { + emitter.addListener2('foo', function() { actualCallOrder.push('listener2-foo'); }); - emitter.addListener('bar', function() { + emitter.addListener2('bar', function() { actualCallOrder.push('listener2-bar'); }); @@ -239,7 +235,7 @@ suite('EventEmitter', () => { var emitter = new EventEmitter(); var actualCallOrder: string[] = []; - emitter.addListener('foo', function() { + emitter.addListener2('foo', function() { actualCallOrder.push('listener1-foo'); emitter.deferredEmit(() => { emitter.emit('bar'); @@ -247,10 +243,10 @@ suite('EventEmitter', () => { }); - emitter.addListener('foo', function() { + emitter.addListener2('foo', function() { actualCallOrder.push('listener2-foo'); }); - emitter.addListener('bar', function() { + emitter.addListener2('bar', function() { actualCallOrder.push('listener2-bar'); }); @@ -269,16 +265,16 @@ suite('EventEmitter', () => { var emitter = new OrderGuaranteeEventEmitter(); var actualCallOrder: string[] = []; - emitter.addListener('foo', function() { + emitter.addListener2('foo', function() { actualCallOrder.push('listener1-foo'); emitter.emit('bar'); }); - emitter.addListener('foo', function() { + emitter.addListener2('foo', function() { actualCallOrder.push('listener2-foo'); }); - emitter.addListener('bar', function() { + emitter.addListener2('bar', function() { actualCallOrder.push('listener2-bar'); }); @@ -295,7 +291,7 @@ suite('EventEmitter', () => { var emitter = new OrderGuaranteeEventEmitter(); var actualCallOrder: string[] = []; - emitter.addListener('foo', function() { + emitter.addListener2('foo', function() { actualCallOrder.push('listener1-foo'); emitter.deferredEmit(() => { emitter.emit('bar'); @@ -303,10 +299,10 @@ suite('EventEmitter', () => { }); - emitter.addListener('foo', function() { + emitter.addListener2('foo', function() { actualCallOrder.push('listener2-foo'); }); - emitter.addListener('bar', function() { + emitter.addListener2('bar', function() { actualCallOrder.push('listener2-bar'); }); diff --git a/src/vs/base/test/common/json.test.ts b/src/vs/base/test/common/json.test.ts index d0dd7e06a46..a84fc71f411 100644 --- a/src/vs/base/test/common/json.test.ts +++ b/src/vs/base/test/common/json.test.ts @@ -5,7 +5,8 @@ 'use strict'; import * as assert from 'assert'; -import { SyntaxKind, createScanner, parse } from 'vs/base/common/json'; +import { SyntaxKind, createScanner, parse, getLocation, Node, ParseError, parseTree, ParseErrorCode, + getParseErrorMessage, ParseOptions, Segment, findNodeAtLocation, getNodeValue } from 'vs/base/common/json'; function assertKinds(text:string, ...kinds:SyntaxKind[]):void { var _json = createScanner(text); @@ -17,24 +18,60 @@ function assertKinds(text:string, ...kinds:SyntaxKind[]):void { } -function assertValidParse(input:string, expected:any) : void { - var errors : string[] = []; - var actual = parse(input, errors); +function assertValidParse(input:string, expected:any, options?: ParseOptions) : void { + var errors : {error: ParseErrorCode}[] = []; + var actual = parse(input, errors, options); if (errors.length !== 0) { - assert(false, errors[0]); + assert(false, getParseErrorMessage(errors[0].error)); } assert.deepEqual(actual, expected); } -function assertInvalidParse(input:string, expected:any) : void { - var errors : string[] = []; - var actual = parse(input, errors); +function assertInvalidParse(input:string, expected:any, options?: ParseOptions) : void { + var errors : {error: ParseErrorCode}[] = []; + var actual = parse(input, errors, options); assert(errors.length > 0); assert.deepEqual(actual, expected); } +function assertTree(input:string, expected:any) : void { + var errors : ParseError[] = []; + var actual = parseTree(input, errors); + + assert.equal(errors.length, 0); + let checkParent = (node: Node) => { + if (node.children) { + for (let child of node.children) { + assert.equal(node, child.parent); + delete child.parent; // delete to avoid recursion in deep equal + checkParent(child); + } + } + } + checkParent(actual); + + assert.deepEqual(actual, expected); +} + +function assertNodeAtLocation(input:Node, segments: Segment[], expected: any) { + let actual = findNodeAtLocation(input, segments); + assert.deepEqual(actual ? getNodeValue(actual) : void 0, expected); +} + + +function assertLocation(input:string, expectedSegments: Segment[], expectedNodeType: string, expectedCompleteProperty: boolean) : void { + var errors : {error: ParseErrorCode}[] = []; + var offset = input.indexOf('|'); + input = input.substring(0, offset) + input.substring(offset+1, input.length); + var actual = getLocation(input, offset); + assert(actual); + assert.deepEqual(actual.path, expectedSegments, input); + assert.equal(actual.previousNode && actual.previousNode.type, expectedNodeType, input); + assert.equal(actual.isAtPropertyKey, expectedCompleteProperty, input); +} + suite('JSON', () => { test('tokens', () => { assertKinds('{', SyntaxKind.OpenBraceToken); @@ -147,7 +184,7 @@ suite('JSON', () => { assertValidParse('23e3', 23e3); assertValidParse('1.2E+3', 1.2E+3); assertValidParse('1.2E-3', 1.2E-3); - + assertValidParse('1.2E-3 // comment', 1.2E-3); }); test('parse: objects', () => { @@ -157,6 +194,9 @@ suite('JSON', () => { assertValidParse('{ "hello": [], "world": {} }', { hello: [], world: {} }); assertValidParse('{ "a": false, "b": true, "c": [ 7.4 ] }', { a: false, b: true, c: [ 7.4 ]}); assertValidParse('{ "lineComment": "//", "blockComment": ["/*", "*/"], "brackets": [ ["{", "}"], ["[", "]"], ["(", ")"] ] }', { lineComment: '//', blockComment: ["/*", "*/"], brackets: [ ["{", "}"], ["[", "]"], ["(", ")"] ] }); + assertValidParse('{ "hello": [], "world": {} }', { hello: [], world: {} }); + assertValidParse('{ "hello": { "again": { "inside": 5 }, "world": 1 }}', { hello: { again: { inside: 5 }, world: 1 }}); + assertValidParse('{ "foo": /*hello*/true }', { foo: true }); }); test('parse: arrays', () => { @@ -183,4 +223,105 @@ suite('JSON', () => { assertInvalidParse('[ ,1, 2, 3 ]', [ 1, 2, 3 ]); assertInvalidParse('[ ,1, 2, 3, ]', [ 1, 2, 3 ]); }); + + test('parse: disallow commments', () => { + let options = { disallowComments: true }; + + assertValidParse('[ 1, 2, null, "foo" ]', [ 1, 2, null, "foo"], options); + assertValidParse('{ "hello": [], "world": {} }', { hello: [], world: {} }, options); + + assertInvalidParse('{ "foo": /*comment*/ true }', { foo: true }, options); + }); + + test('location: properties', () => { + assertLocation('|{ "foo": "bar" }', [], void 0, false); + assertLocation('{| "foo": "bar" }', [], void 0, true); + assertLocation('{ |"foo": "bar" }', ["foo" ], "property", true); + assertLocation('{ "foo|": "bar" }', [ "foo" ], "property", true); + assertLocation('{ "foo"|: "bar" }', ["foo" ], "property", true); + assertLocation('{ "foo": "bar"| }', ["foo" ], "string", false); + assertLocation('{ "foo":| "bar" }', ["foo" ], void 0, false); + assertLocation('{ "foo": {"bar|": 1, "car": 2 } }', ["foo", "bar" ], "property", true); + assertLocation('{ "foo": {"bar": 1|, "car": 3 } }', ["foo", "bar" ], "number", false); + assertLocation('{ "foo": {"bar": 1,| "car": 4 } }', ["foo"], void 0, true); + assertLocation('{ "foo": {"bar": 1, "ca|r": 5 } }', ["foo", "car" ], "property", true); + assertLocation('{ "foo": {"bar": 1, "car": 6| } }', ["foo", "car" ], "number", false); + assertLocation('{ "foo": {"bar": 1, "car": 7 }| }', ["foo"], void 0, false); + assertLocation('{ "foo": {"bar": 1, "car": 8 },| "goo": {} }', [], void 0, true); + assertLocation('{ "foo": {"bar": 1, "car": 9 }, "go|o": {} }', ["goo" ], "property", true); + assertLocation('{ "dep": {"bar": 1, "car": |', ["dep", "car" ], void 0, false); + assertLocation('{ "dep": {"bar": 1,, "car": |', ["dep", "car" ], void 0, false); + assertLocation('{ "dep": {"bar": "na", "dar": "ma", "car": | } }', ["dep", "car" ], void 0, false); + }); + + test('location: arrays', () => { + assertLocation('|["foo", null ]', [], void 0, false); + assertLocation('[|"foo", null ]', [0], "string", false); + assertLocation('["foo"|, null ]', [0], "string", false); + assertLocation('["foo",| null ]', [1], void 0, false); + assertLocation('["foo", |null ]', [1], "null", false); + assertLocation('["foo", null,| ]', [2], void 0, false); + assertLocation('["foo", null,,| ]', [3], void 0, false); + assertLocation('[["foo", null,, ],|', [1], void 0, false); + }); + + test('tree: literals', () => { + assertTree('true', { type: 'boolean', offset: 0, length: 4, value: true }); + assertTree('false', { type: 'boolean', offset: 0, length: 5, value: false }); + assertTree('null', { type: 'null', offset: 0, length: 4, value: null }); + assertTree('23', { type: 'number', offset: 0, length: 2, value: 23 }); + assertTree('-1.93e-19', { type: 'number', offset: 0, length: 9, value: -1.93e-19 }); + assertTree('"hello"', { type: 'string', offset: 0, length: 7, value: 'hello' }); + }); + + test('tree: arrays', () => { + assertTree('[]', { type: 'array', offset: 0, length: 2, children: [] }); + assertTree('[ 1 ]', { type: 'array', offset: 0, length: 5, children: [{ type: 'number', offset: 2, length: 1, value: 1 }] }); + assertTree('[ 1,"x"]', { type: 'array', offset: 0, length: 8, children: [ + { type: 'number', offset: 2, length: 1, value: 1 }, + { type: 'string', offset: 4, length: 3, value: 'x' } + ]}); + assertTree('[[]]', { type: 'array', offset: 0, length: 4, children: [ + { type: 'array', offset: 1, length: 2, children: []} + ]}); + }); + + test('tree: objects', () => { + assertTree('{ }', { type: 'object', offset: 0, length: 3, children: [] }); + assertTree('{ "val": 1 }', { type: 'object', offset: 0, length: 12, children: [ + { type: 'property', offset: 2, length: 8, columnOffset: 7, children: [ + { type: 'string', offset: 2, length: 5, value: 'val' }, + { type: 'number', offset: 9, length: 1, value: 1 } + ]} + ]}); + assertTree('{"id": "$", "v": [ null, null] }', + { type: 'object', offset: 0, length: 32, children: [ + { type: 'property', offset: 1, length: 9, columnOffset: 5, children: [ + { type: 'string', offset: 1, length: 4, value: 'id' }, + { type: 'string', offset: 7, length: 3, value: '$' } + ]}, + { type: 'property', offset: 12, length: 19, columnOffset: 15, children: [ + { type: 'string', offset: 12, length: 3, value: 'v' }, + { type: 'array', offset: 17, length: 13, children: [ + { type: 'null', offset: 19, length: 4, value: null }, + { type: 'null', offset: 25, length: 4, value: null } + ]} + ]} + ]} + ); + }); + + test('tree: find location', () => { + let root = parseTree('{ "key1": { "key11": [ "val111", "val112" ] }, "key2": [ { "key21": false, "key22": 221 }, null, [{}] ] }'); + assertNodeAtLocation(root, [ "key1"], { key11: [ 'val111', 'val112' ]}); + assertNodeAtLocation(root, [ "key1", "key11"], [ 'val111', 'val112' ]); + assertNodeAtLocation(root, [ "key1", "key11", 0], 'val111'); + assertNodeAtLocation(root, [ "key1", "key11", 1], 'val112'); + assertNodeAtLocation(root, [ "key1", "key11", 2], void 0); + assertNodeAtLocation(root, [ "key2", 0, "key21"], false); + assertNodeAtLocation(root, [ "key2", 0, "key22"], 221); + assertNodeAtLocation(root, [ "key2", 1], null); + assertNodeAtLocation(root, [ "key2", 2], [{}]); + assertNodeAtLocation(root, [ "key2", 2, 0], {}); + }); }); diff --git a/src/vs/base/test/common/jsonEdit.test.ts b/src/vs/base/test/common/jsonEdit.test.ts new file mode 100644 index 00000000000..6593efb4df1 --- /dev/null +++ b/src/vs/base/test/common/jsonEdit.test.ts @@ -0,0 +1,105 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import json = require('vs/base/common/json'); +import {FormattingOptions, Edit} from 'vs/base/common/jsonFormatter'; +import {setProperty, removeProperty} from 'vs/base/common/jsonEdit'; +import assert = require('assert'); + +suite('JSON - edits', () => { + + function assertEdit(content: string, edits: Edit[], expected: string) { + assert(edits); + let lastEditOffset = content.length; + for (let i = edits.length - 1; i >= 0; i--) { + let edit = edits[i]; + assert(edit.offset >= 0 && edit.length >= 0 && edit.offset + edit.length <= content.length) + assert(typeof edit.content === 'string'); + assert(lastEditOffset >= edit.offset + edit.length); // make sure all edits are ordered + lastEditOffset = edit.offset; + content = content.substring(0, edit.offset) + edit.content + content.substring(edit.offset + edit.length); + } + assert.equal(content, expected); + } + + let formatterOptions : FormattingOptions = { + insertSpaces: true, + tabSize: 2, + eol: '\n' + } + + test('set property', () => { + let content = '{\n "x": "y"\n}'; + let edits = setProperty(content, ['x'], 'bar', formatterOptions); + assertEdit(content, edits, '{\n "x": "bar"\n}'); + + content = 'true'; + edits = setProperty(content, [], 'bar', formatterOptions); + assertEdit(content, edits, '"bar"'); + }); + + test('insert property', () => { + let content = "{}"; + let edits = setProperty(content, ['foo'], 'bar', formatterOptions); + assertEdit(content, edits, '{\n "foo": "bar"\n}'); + + edits = setProperty(content, ['foo', 'foo2'], 'bar', formatterOptions); + assertEdit(content, edits, '{\n "foo": {\n "foo2": "bar"\n }\n}'); + + content = "{\n}"; + edits = setProperty(content, ['foo'], 'bar', formatterOptions); + assertEdit(content, edits, '{\n "foo": "bar"\n}'); + + content = " {\n }"; + edits = setProperty(content, ['foo'], 'bar', formatterOptions); + assertEdit(content, edits, ' {\n "foo": "bar"\n }'); + + content = '{\n "x": "y"\n}'; + edits = setProperty(content, ['foo'], 'bar', formatterOptions); + assertEdit(content, edits, '{\n "x": "y",\n "foo": "bar"\n}'); + + edits = setProperty(content, ['x'], 'bar', formatterOptions); + assertEdit(content, edits, '{\n "x": "bar"\n}'); + + content = '{\n "x": {\n "a": 1,\n "b": true\n }\n}\n'; + edits = setProperty(content, ['x'], 'bar', formatterOptions); + assertEdit(content, edits, '{\n "x": "bar"\n}\n'); + + edits = setProperty(content, ['x', 'b'], 'bar', formatterOptions); + assertEdit(content, edits, '{\n "x": {\n "a": 1,\n "b": "bar"\n }\n}\n'); + + edits = setProperty(content, ['x', 'c'], 'bar', formatterOptions, () => 0); + assertEdit(content, edits, '{\n "x": {\n "c": "bar",\n "a": 1,\n "b": true\n }\n}\n'); + + edits = setProperty(content, ['x', 'c'], 'bar', formatterOptions, () => 1); + assertEdit(content, edits, '{\n "x": {\n "a": 1,\n "c": "bar",\n "b": true\n }\n}\n'); + + edits = setProperty(content, ['x', 'c'], 'bar', formatterOptions, () => 2); + assertEdit(content, edits, '{\n "x": {\n "a": 1,\n "b": true,\n "c": "bar"\n }\n}\n'); + + content = ''; + edits = setProperty(content, ['foo', 0], 'bar', formatterOptions); + assertEdit(content, edits, '{\n "foo": [\n "bar"\n ]\n}'); + + content = '//comment'; + edits = setProperty(content, ['foo', 0], 'bar', formatterOptions); + assertEdit(content, edits, '{\n "foo": [\n "bar"\n ]\n} //comment\n'); + }); + + test('remove property', () => { + let content = '{\n "x": "y"\n}'; + let edits = removeProperty(content, ['x'], formatterOptions); + assertEdit(content, edits, '{}'); + + content = '{\n "x": "y", "a": []\n}'; + edits = removeProperty(content, ['x'], formatterOptions); + assertEdit(content, edits, '{\n "a": []\n}'); + + content = '{\n "x": "y", "a": []\n}'; + edits = removeProperty(content, ['a'], formatterOptions); + assertEdit(content, edits, '{\n "x": "y"\n}'); + }); +}); \ No newline at end of file diff --git a/src/vs/languages/json/test/common/formatter.test.ts b/src/vs/base/test/common/jsonFormatter.test.ts similarity index 80% rename from src/vs/languages/json/test/common/formatter.test.ts rename to src/vs/base/test/common/jsonFormatter.test.ts index af2fae7f8a5..1f493917b48 100644 --- a/src/vs/languages/json/test/common/formatter.test.ts +++ b/src/vs/base/test/common/jsonFormatter.test.ts @@ -4,46 +4,33 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import EditorCommon = require('vs/editor/common/editorCommon'); -import {Range} from 'vs/editor/common/core/range'; -import {Model} from 'vs/editor/common/model/model'; -import ModesTestUtils = require('vs/editor/test/common/modesTestUtils'); -import Formatter = require('vs/languages/json/common/features/jsonFormatter'); -import MirrorModel = require('vs/editor/common/model/mirrorModel'); +import Formatter = require('vs/base/common/jsonFormatter'); import assert = require('assert'); suite('JSON - formatter', () => { - function format(unformatted: string, expected: string, insertSpaces = true) { - var range : EditorCommon.IRange = null; - - var mirrorModel = MirrorModel.createTestMirrorModelFromString(unformatted); - - var rangeStart = unformatted.indexOf('|'); - var rangeEnd = unformatted.lastIndexOf('|'); + function format(content: string, expected: string, insertSpaces = true) { + let range = void 0; + var rangeStart = content.indexOf('|'); + var rangeEnd = content.lastIndexOf('|'); if (rangeStart !== -1 && rangeEnd !== -1) { - unformatted = unformatted.substring(0, rangeStart) + unformatted.substring(rangeStart + 1, rangeEnd) + unformatted.substring(rangeEnd + 1); - - var startPos = mirrorModel.getPositionFromOffset(rangeStart); - var endPos = mirrorModel.getPositionFromOffset(rangeEnd); - range = { startLineNumber: startPos.lineNumber, startColumn: startPos.column, endLineNumber: endPos.lineNumber, endColumn: endPos.column }; - mirrorModel = MirrorModel.createTestMirrorModelFromString(unformatted); + content = content.substring(0, rangeStart) + content.substring(rangeStart + 1, rangeEnd) + content.substring(rangeEnd + 1); + range = { offset: rangeStart, length: rangeEnd - rangeStart }; } - var operations = Formatter.format(mirrorModel, range, { tabSize: 2, insertSpaces: insertSpaces }); + var edits = Formatter.format(content, range, { tabSize: 2, insertSpaces: insertSpaces, eol: '\n' }); - var model = new Model(unformatted, Model.DEFAULT_CREATION_OPTIONS, null); - model.pushEditOperations([], operations.map(o => { - return { - range: Range.lift(o.range), - text: o.text, - identifier: null, - forceMoveMarkers: false - }; - }), () => []); - var newContent = model.getValue(EditorCommon.EndOfLinePreference.LF); - assert.equal(newContent, expected); - model.dispose(); + let lastEditOffset = content.length; + for (let i = edits.length - 1; i >= 0; i--) { + let edit = edits[i]; + assert(edit.offset >= 0 && edit.length >= 0 && edit.offset + edit.length <= content.length) + assert(typeof edit.content === 'string'); + assert(lastEditOffset >= edit.offset + edit.length); // make sure all edits are ordered + lastEditOffset = edit.offset; + content = content.substring(0, edit.offset) + edit.content + content.substring(edit.offset + edit.length); + } + + assert.equal(content, expected); } test('object - single property', () => { diff --git a/src/vs/code/buildfile.js b/src/vs/code/buildfile.js index d722dc5e6fa..960acabd281 100644 --- a/src/vs/code/buildfile.js +++ b/src/vs/code/buildfile.js @@ -6,7 +6,7 @@ function createModuleDescription(name, exclude) { var result= {}; - var excludes = ['vs/css', 'vs/nls', 'vs/text']; + var excludes = ['vs/css', 'vs/nls']; result.name= name; if (Array.isArray(exclude) && exclude.length > 0) { excludes = excludes.concat(exclude); diff --git a/src/vs/code/electron-main/menus.ts b/src/vs/code/electron-main/menus.ts index 74cb9d3e79a..619486409e6 100644 --- a/src/vs/code/electron-main/menus.ts +++ b/src/vs/code/electron-main/menus.ts @@ -409,10 +409,6 @@ export class VSCodeMenu { // Files let files = recentList.files; - if (platform.isMacintosh && recentList.files.length > 0) { - files = recentList.files.filter(f => recentList.folders.indexOf(f) < 0); // TODO@Ben migration (remove in the future) - } - if (files.length > 0) { openRecentMenu.append(__separator__()); @@ -793,7 +789,7 @@ function __separator__(): Electron.MenuItem { function mnemonicLabel(label: string): string { if (platform.isMacintosh) { - return label.replace(/&&/g, ''); // no mnemonic support on mac + return label.replace(/\(&&\w\)|&&/g, ''); // no mnemonic support on mac/linux } return label.replace(/&&/g, '&'); diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 2fde7589e29..da7be6d1d7a 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -112,7 +112,6 @@ export interface IWindowConfiguration extends ICommandLineArguments { crashReporter: Electron.CrashReporterStartOptions; extensionsGallery: { serviceUrl: string; - cacheUrl: string; itemUrl: string; }; extensionTips: { [id: string]: string; }; diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index 8bf3c942a9c..f55f87d46e4 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -789,10 +789,6 @@ export class WindowsManager implements IWindowsService { files = arrays.distinct(files); folders = arrays.distinct(folders); - if (platform.isMacintosh && files.length > 0) { - files = files.filter(f => folders.indexOf(f) < 0); // TODO@Ben migration (remove in the future) - } - // Make sure it is bounded files = files.slice(0, 10); folders = folders.slice(0, 10); diff --git a/src/vs/code/node/argv.ts b/src/vs/code/node/argv.ts index 85beec2aa4d..0f213db11c8 100644 --- a/src/vs/code/node/argv.ts +++ b/src/vs/code/node/argv.ts @@ -94,6 +94,7 @@ ${ indent }-r, --reuse-window Force opening a file or folder in the last acti ${ indent } window. ${ indent }--user-data-dir Specifies the directory that user data is kept in, ${ indent } useful when running as root. +${ indent }--verbose Print verbose output (implies --wait). ${ indent }-v, --version Print version. ${ indent }-w, --wait Wait for the window to be closed before returning. ${ indent }--list-extensions List the installed extensions. diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index 85a09102b76..9f1dad5878a 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -35,14 +35,23 @@ export function main(args: string[]): TPromise { }); delete env['ATOM_SHELL_INTERNAL_RUN_AS_NODE']; - const child = spawn(process.execPath, args, { - detached: true, - stdio: 'ignore', - env - }); + let options = { + detacted: true, + env, + }; + if (!argv.verbose) { + options['stdio'] = 'ignore'; + } - if (argv.wait) { - return new TPromise(c => child.once('exit', ()=> c(null))); + const child = spawn(process.execPath, args, options); + + if (argv.verbose) { + child.stdout.on('data', (data) => console.log(data.toString('utf8').trim())); + child.stderr.on('data', (data) => console.log(data.toString('utf8').trim())); + } + + if (argv.wait || argv.verbose) { + return new TPromise(c => child.once('exit', () => c(null))); } } diff --git a/src/vs/css.js b/src/vs/css.js index 710116c0651..eaa5d6d8e47 100644 --- a/src/vs/css.js +++ b/src/vs/css.js @@ -13,8 +13,6 @@ *--------------------------------------------------------------------------------------------- *--------------------------------------------------------------------------------------------- *--------------------------------------------------------------------------------------------*/ -/// -/// 'use strict'; var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; @@ -100,7 +98,7 @@ var CSSLoaderPlugin; this._insertLinkNode(linkNode); }; return BrowserCSSLoader; - })(); + }()); /** * Prior to IE10, IE could not go above 31 stylesheets in a page * http://blogs.msdn.com/b/ieinternals/archive/2011/05/14/internet-explorer-stylesheet-rule-selector-import-sheet-limit-maximum.aspx @@ -201,7 +199,7 @@ var CSSLoaderPlugin; } }; return IE9CSSLoader; - })(BrowserCSSLoader); + }(BrowserCSSLoader)); var IE8CSSLoader = (function (_super) { __extends(IE8CSSLoader, _super); function IE8CSSLoader() { @@ -214,7 +212,7 @@ var CSSLoaderPlugin; }; }; return IE8CSSLoader; - })(IE9CSSLoader); + }(IE9CSSLoader)); var NodeCSSLoader = (function () { function NodeCSSLoader() { this.fs = require.nodeRequire('fs'); @@ -229,7 +227,7 @@ var CSSLoaderPlugin; }; NodeCSSLoader.BOM_CHAR_CODE = 65279; return NodeCSSLoader; - })(); + }()); // ------------------------------ Finally, the plugin var CSSPlugin = (function () { function CSSPlugin(cssLoader) { @@ -279,7 +277,7 @@ var CSSLoaderPlugin; }; CSSPlugin.BUILD_MAP = {}; return CSSPlugin; - })(); + }()); CSSLoaderPlugin.CSSPlugin = CSSPlugin; var Utilities = (function () { function Utilities() { @@ -411,7 +409,7 @@ var CSSLoaderPlugin; }); }; return Utilities; - })(); + }()); CSSLoaderPlugin.Utilities = Utilities; (function () { var cssLoader = null; diff --git a/src/vs/editor/browser/controller/mouseHandler.ts b/src/vs/editor/browser/controller/mouseHandler.ts index ad6558a40a2..b5692ea543a 100644 --- a/src/vs/editor/browser/controller/mouseHandler.ts +++ b/src/vs/editor/browser/controller/mouseHandler.ts @@ -77,10 +77,10 @@ class EventGateKeeper extends Disposable { } class MousePosition { - public position: editorCommon.IEditorPosition; + public position: Position; public mouseColumn: number; - constructor(position:editorCommon.IEditorPosition, mouseColumn:number) { + constructor(position:Position, mouseColumn:number) { this.position = position; this.mouseColumn = mouseColumn; } @@ -316,7 +316,7 @@ class MouseDownOperation extends Disposable { private _mouseMoveMonitor:GlobalMouseMoveMonitor; private _mouseDownThenMoveEventHandler: EventGateKeeper; - private _currentSelection: editorCommon.IEditorSelection; + private _currentSelection: Selection; private _mouseState: MouseDownState; private _onScrollTimeout: TimeoutTimer; @@ -523,7 +523,7 @@ class MouseDownState { private _startedOnLineNumbers: boolean; public get startedOnLineNumbers(): boolean { return this._startedOnLineNumbers; } - private _lastMouseDownPosition: editorCommon.IEditorPosition; + private _lastMouseDownPosition: Position; private _lastMouseDownPositionEqualCount: number; private _lastMouseDownCount: number; private _lastSetMouseDownCountTime: number; @@ -555,7 +555,7 @@ class MouseDownState { this._startedOnLineNumbers = startedOnLineNumbers; } - public trySetCount(setMouseDownCount:number, newMouseDownPosition:editorCommon.IEditorPosition): void { + public trySetCount(setMouseDownCount:number, newMouseDownPosition:Position): void { // a. Invalidate multiple clicking if too much time has passed (will be hit by IE because the detail field of mouse events contains garbage in IE10) let currentTime = (new Date()).getTime(); if (currentTime - this._lastSetMouseDownCountTime > MouseDownState.CLEAR_MOUSE_DOWN_COUNT_TIME) { diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index d6d8615c3f9..5e83dd54db9 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -6,7 +6,7 @@ import {Position} from 'vs/editor/common/core/position'; import {Range as EditorRange} from 'vs/editor/common/core/range'; -import {EditorLayoutInfo, IEditorPosition, IEditorRange, IPosition, MouseTargetType} from 'vs/editor/common/editorCommon'; +import {EditorLayoutInfo, IPosition, MouseTargetType} from 'vs/editor/common/editorCommon'; import {ClassNames, IMouseTarget, IViewZoneData} from 'vs/editor/browser/editorBrowser'; import {IDomNodePosition} from 'vs/base/browser/dom'; import {ViewContext} from 'vs/editor/common/view/viewContext'; @@ -28,11 +28,11 @@ class MouseTarget implements IMouseTarget { public element: Element; public type: MouseTargetType; public mouseColumn: number; - public position: IEditorPosition; - public range: IEditorRange; + public position: Position; + public range: EditorRange; public detail: any; - constructor(element: Element, type: MouseTargetType, mouseColumn:number = 0, position:IEditorPosition = null, range: IEditorRange = null, detail: any = null) { + constructor(element: Element, type: MouseTargetType, mouseColumn:number = 0, position:Position = null, range: EditorRange = null, detail: any = null) { this.element = element; this.type = type; this.mouseColumn = mouseColumn; @@ -194,13 +194,6 @@ export class MouseTargetFactory { var t = e.target; var path = this.getClassNamePathTo(t, this._viewHelper.viewDomNode); - // Is it a cursor ? - var lineNumberAttribute = t.hasAttribute && t.hasAttribute('lineNumber') ? t.getAttribute('lineNumber') : null; - var columnAttribute = t.hasAttribute && t.hasAttribute('column') ? t.getAttribute('column') : null; - if (lineNumberAttribute && columnAttribute) { - return this.createMouseTargetFromViewCursor(t, parseInt(lineNumberAttribute, 10), parseInt(columnAttribute, 10), mouseColumn); - } - // Is it a content widget? if (REGEX.IS_CHILD_OF_CONTENT_WIDGETS.test(path) || REGEX.IS_CHILD_OF_OVERFLOWING_CONTENT_WIDGETS.test(path)) { return this.createMouseTargetFromContentWidgetsChild(t, mouseColumn); @@ -211,6 +204,13 @@ export class MouseTargetFactory { return this.createMouseTargetFromOverlayWidgetsChild(t, mouseColumn); } + // Is it a cursor ? + var lineNumberAttribute = t.hasAttribute && t.hasAttribute('lineNumber') ? t.getAttribute('lineNumber') : null; + var columnAttribute = t.hasAttribute && t.hasAttribute('column') ? t.getAttribute('column') : null; + if (lineNumberAttribute && columnAttribute) { + return this.createMouseTargetFromViewCursor(t, parseInt(lineNumberAttribute, 10), parseInt(columnAttribute, 10), mouseColumn); + } + // Is it the textarea cover? if (REGEX.IS_TEXTAREA_COVER.test(path)) { if (this._context.configuration.editor.viewInfo.glyphMargin) { @@ -541,9 +541,9 @@ export class MouseTargetFactory { if (viewZoneWhitespace) { var viewZoneMiddle = viewZoneWhitespace.verticalOffset + viewZoneWhitespace.height / 2, lineCount = this._context.model.getLineCount(), - positionBefore: IEditorPosition = null, - position: IEditorPosition, - positionAfter: IEditorPosition = null; + positionBefore: Position = null, + position: Position, + positionAfter: Position = null; if (viewZoneWhitespace.afterLineNumber !== lineCount) { // There are more lines after this view zone @@ -575,7 +575,7 @@ export class MouseTargetFactory { return null; } - private _getFullLineRangeAtCoord(mouseVerticalOffset: number): { range: IEditorRange; isAfterLines: boolean; } { + private _getFullLineRangeAtCoord(mouseVerticalOffset: number): { range: EditorRange; isAfterLines: boolean; } { if (this._viewHelper.isAfterLines(mouseVerticalOffset)) { // Below the last line var lineNumber = this._context.model.getLineCount(); diff --git a/src/vs/editor/browser/editorBrowser.ts b/src/vs/editor/browser/editorBrowser.ts index 03951ce0f96..457ae7831cc 100644 --- a/src/vs/editor/browser/editorBrowser.ts +++ b/src/vs/editor/browser/editorBrowser.ts @@ -10,17 +10,28 @@ import {IKeyboardEvent} from 'vs/base/browser/keyboardEvent'; import {IMouseEvent} from 'vs/base/browser/mouseEvent'; import {IInstantiationService, IConstructorSignature1} from 'vs/platform/instantiation/common/instantiation'; import * as editorCommon from 'vs/editor/common/editorCommon'; +import {Position} from 'vs/editor/common/core/position'; +import {Range} from 'vs/editor/common/core/range'; +/** + * @internal + */ export interface IContentWidgetData { widget: IContentWidget; position: IContentWidgetPosition; } +/** + * @internal + */ export interface IOverlayWidgetData { widget: IOverlayWidget; position: IOverlayWidgetPosition; } +/** + * @internal + */ export interface ICodeEditorHelper { getScrollWidth(): number; getScrollLeft(): number; @@ -35,6 +46,9 @@ export interface ICodeEditorHelper { getOffsetForColumn(lineNumber:number, column:number): number; } +/** + * @internal + */ export interface IView extends IDisposable { domNode: HTMLElement; @@ -43,7 +57,7 @@ export interface IView extends IDisposable { createOverviewRuler(cssClassName:string, minimumHeight:number, maximumHeight:number): IOverviewRuler; getCodeEditorHelper(): ICodeEditorHelper; - getCenteredRangeInViewport(): editorCommon.IEditorRange; + getCenteredRangeInViewport(): Range; change(callback:(changeAccessor:IViewZoneChangeAccessor) => any): boolean; getWhitespaces(): editorCommon.IEditorWhitespace[]; @@ -67,16 +81,22 @@ export interface IView extends IDisposable { removeOverlayWidget(widgetData: IOverlayWidgetData): void; } +/** + * @internal + */ export interface IViewZoneData { viewZoneId: number; - positionBefore:editorCommon.IEditorPosition; - positionAfter:editorCommon.IEditorPosition; - position: editorCommon.IEditorPosition; + positionBefore:Position; + positionAfter:Position; + position: Position; afterLineNumber: number; } +/** + * @internal + */ export interface IMouseDispatchData { - position: editorCommon.IEditorPosition; + position: Position; /** * Desired mouse column (e.g. when position.column gets clamped to text length -- clicking after text on a line). */ @@ -91,10 +111,13 @@ export interface IMouseDispatchData { shiftKey: boolean; } +/** + * @internal + */ export interface IViewController { dispatchMouse(data:IMouseDispatchData); - moveTo(source:string, position:editorCommon.IEditorPosition): void; + moveTo(source:string, position:Position): void; paste(source:string, text:string, pasteOnNewLine:boolean): void; type(source: string, text: string): void; @@ -110,6 +133,9 @@ export interface IViewController { emitMouseDown(e:IEditorMouseEvent): void; } +/** + * @internal + */ export var ClassNames = { TEXTAREA_COVER: 'textAreaCover', TEXTAREA: 'inputarea', @@ -129,8 +155,11 @@ export var ClassNames = { VIEW_ZONES: 'view-zones' }; +/** + * @internal + */ export interface IViewportInfo { - visibleRange: editorCommon.IEditorRange; + visibleRange: Range; width:number; height:number; deltaTop:number; @@ -323,7 +352,7 @@ export interface IMouseTarget { /** * The 'approximate' editor position */ - position: editorCommon.IEditorPosition; + position: Position; /** * Desired mouse column (e.g. when position.column gets clamped to text length -- clicking after text on a line). */ @@ -331,7 +360,7 @@ export interface IMouseTarget { /** * The 'approximate' editor range */ - range: editorCommon.IEditorRange; + range: Range; /** * Some extra detail. */ @@ -345,10 +374,14 @@ export interface IEditorMouseEvent { target: IMouseTarget; } +/** + * @internal + */ export type ISimpleEditorContributionCtor = IConstructorSignature1; /** * An editor contribution descriptor that will be used to construct editor contributions + * @internal */ export interface IEditorContributionDescriptor { /** @@ -357,108 +390,15 @@ export interface IEditorContributionDescriptor { createInstance(instantiationService:IInstantiationService, editor:ICodeEditor): editorCommon.IEditorContribution; } -export class ColorZone { - _colorZoneBrand: void; - from: number; - to: number; - colorId: number; - position: editorCommon.OverviewRulerLane; - - constructor(from:number, to:number, colorId:number, position: editorCommon.OverviewRulerLane) { - this.from = from|0; - this.to = to|0; - this.colorId = colorId|0; - this.position = position|0; - } -} - -/** - * A zone in the overview ruler - */ -export class OverviewRulerZone { - _overviewRulerZoneBrand: void; - - startLineNumber: number; - endLineNumber: number; - position: editorCommon.OverviewRulerLane; - forceHeight: number; - - private _color: string; - private _darkColor: string; - - private _colorZones: ColorZone[]; - - constructor( - startLineNumber: number, endLineNumber: number, - position: editorCommon.OverviewRulerLane, - forceHeight: number, - color: string, darkColor: string - ) { - this.startLineNumber = startLineNumber; - this.endLineNumber = endLineNumber; - this.position = position; - this.forceHeight = forceHeight; - this._color = color; - this._darkColor = darkColor; - this._colorZones = null; - } - - public getColor(useDarkColor:boolean): string { - if (useDarkColor) { - return this._darkColor; - } - return this._color; - } - - public equals(other:OverviewRulerZone): boolean { - return ( - this.startLineNumber === other.startLineNumber - && this.endLineNumber === other.endLineNumber - && this.position === other.position - && this.forceHeight === other.forceHeight - && this._color === other._color - && this._darkColor === other._darkColor - ); - } - - public compareTo(other:OverviewRulerZone): number { - if (this.startLineNumber === other.startLineNumber) { - if (this.endLineNumber === other.endLineNumber) { - if (this.forceHeight === other.forceHeight) { - if (this.position === other.position) { - if (this._darkColor === other._darkColor) { - if (this._color === other._color) { - return 0; - } - return this._color < other._color ? -1 : 1; - } - return this._darkColor < other._darkColor ? -1 : 1; - } - return this.position - other.position; - } - return this.forceHeight - other.forceHeight; - } - return this.endLineNumber - other.endLineNumber; - } - return this.startLineNumber - other.startLineNumber; - } - - public setColorZones(colorZones:ColorZone[]): void { - this._colorZones = colorZones; - } - - public getColorZones(): ColorZone[] { - return this._colorZones; - } -} /** * An overview ruler + * @internal */ export interface IOverviewRuler { getDomNode(): HTMLElement; dispose(): void; - setZones(zones:OverviewRulerZone[]): void; + setZones(zones:editorCommon.OverviewRulerZone[]): void; setLayout(position:editorCommon.OverviewRulerPosition): void; } /** @@ -466,6 +406,16 @@ export interface IOverviewRuler { */ export interface ICodeEditor extends editorCommon.ICommonCodeEditor { + onMouseUp(listener: (e:IEditorMouseEvent)=>void): IDisposable; + onMouseDown(listener: (e:IEditorMouseEvent)=>void): IDisposable; + onContextMenu(listener: (e:IEditorMouseEvent)=>void): IDisposable; + onMouseMove(listener: (e:IEditorMouseEvent)=>void): IDisposable; + onMouseLeave(listener: (e:IEditorMouseEvent)=>void): IDisposable; + onKeyUp(listener: (e:IKeyboardEvent)=>void): IDisposable; + onKeyDown(listener: (e:IKeyboardEvent)=>void): IDisposable; + onDidLayoutChange(listener: (e:editorCommon.EditorLayoutInfo)=>void): IDisposable; + onDidScrollChange(listener: (e:editorCommon.IScrollEvent)=>void): IDisposable; + /** * Returns the editor's dom node */ @@ -507,10 +457,11 @@ export interface ICodeEditor extends editorCommon.ICommonCodeEditor { /** * Returns the range that is currently centered in the view port. */ - getCenteredRangeInViewport(): editorCommon.IEditorRange; + getCenteredRangeInViewport(): Range; /** * Get the view zones. + * @internal */ getWhitespaces(): editorCommon.IEditorWhitespace[]; @@ -547,9 +498,13 @@ export interface ICodeEditor extends editorCommon.ICommonCodeEditor { /** * Set the model ranges that will be hidden in the view. + * @internal */ setHiddenAreas(ranges:editorCommon.IRange[]): void; + /** + * @internal + */ setAriaActiveDescendant(id:string): void; /** diff --git a/src/vs/editor/browser/standalone/simpleServices.ts b/src/vs/editor/browser/standalone/simpleServices.ts index 476f75b976b..d673ee1348f 100644 --- a/src/vs/editor/browser/standalone/simpleServices.ts +++ b/src/vs/editor/browser/standalone/simpleServices.ts @@ -24,6 +24,7 @@ import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {ICodeEditor, IDiffEditor} from 'vs/editor/browser/editorBrowser'; +import {Selection} from 'vs/editor/common/core/selection'; export class SimpleEditor implements IEditor { @@ -39,7 +40,7 @@ export class SimpleEditor implements IEditor { public getId():string { return 'editor'; } public getControl():editorCommon.IEditor { return this._widget; } - public getSelection():editorCommon.IEditorSelection { return this._widget.getSelection(); } + public getSelection():Selection { return this._widget.getSelection(); } public focus():void { this._widget.focus(); } public withTypedEditor(codeEditorCallback:(editor:ICodeEditor)=>T, diffEditorCallback:(editor:IDiffEditor)=>T): T { @@ -139,7 +140,7 @@ export class SimpleEditorService implements IEditorService { private findModel(editor:editorCommon.ICommonCodeEditor, data:IResourceInput): editorCommon.IModel { var model = editor.getModel(); - if(model.getAssociatedResource().toString() !== data.resource.toString()) { + if(model.uri.toString() !== data.resource.toString()) { return null; } @@ -303,4 +304,8 @@ export class SimpleConfigurationService extends ConfigurationService { }); } + setUserConfiguration(key: any, value: any) : Thenable { + return TPromise.as(null); + } + } diff --git a/src/vs/editor/browser/standalone/standaloneCodeEditor.ts b/src/vs/editor/browser/standalone/standaloneCodeEditor.ts index 756d8c0ac82..fe3fcf843aa 100644 --- a/src/vs/editor/browser/standalone/standaloneCodeEditor.ts +++ b/src/vs/editor/browser/standalone/standaloneCodeEditor.ts @@ -24,7 +24,7 @@ import {RemoteTelemetryServiceHelper} from 'vs/platform/telemetry/common/remoteT import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {DefaultConfig} from 'vs/editor/common/config/defaultConfig'; import {IActionDescriptor, ICodeEditorWidgetCreationOptions, IDiffEditorOptions, IModel, IModelChangedEvent, EventType} from 'vs/editor/common/editorCommon'; -import {IMode} from 'vs/editor/common/modes'; +import {HoverProvider, IMode} from 'vs/editor/common/modes'; import {ModesRegistry} from 'vs/editor/common/modes/modesRegistry'; import {ILanguage} from 'vs/editor/common/modes/monarch/monarchTypes'; import {ICodeEditorService} from 'vs/editor/common/services/codeEditorService'; @@ -38,6 +38,11 @@ import {SimpleEditorService, StandaloneKeybindingService} from 'vs/editor/browse import {IEditorContextViewService, IEditorOverrideServices, ensureDynamicPlatformServices, ensureStaticPlatformServices, getOrCreateStaticServices} from 'vs/editor/browser/standalone/standaloneServices'; import {CodeEditorWidget} from 'vs/editor/browser/widget/codeEditorWidget'; import {DiffEditorWidget} from 'vs/editor/browser/widget/diffEditorWidget'; +import * as modes from 'vs/editor/common/modes'; +import {EditorModelManager} from 'vs/editor/common/services/editorWorkerServiceImpl'; +import {SimpleWorkerClient} from 'vs/base/common/worker/simpleWorker'; +import {DefaultWorkerFactory} from 'vs/base/worker/defaultWorkerFactory'; +import {StandaloneWorker} from 'vs/editor/browser/standalone/standaloneWorker'; // Set defaults for standalone editor DefaultConfig.editor.wrappingIndent = 'none'; @@ -101,7 +106,7 @@ class StandaloneEditor extends CodeEditorWidget { if (model) { let e: IModelChangedEvent = { oldModelUrl: null, - newModelUrl: model.getAssociatedResource().toString() + newModelUrl: model.uri.toString() }; this.emit(EventType.ModelChanged, e); } @@ -457,6 +462,87 @@ export function createCustomMode(language:ILanguage): TPromise { return modeService.getOrCreateMode(modeId); } +export function registerTokensProvider(languageId:string, support:modes.ITokenizationSupport2): IDisposable { + startup.initStaticServicesIfNecessary(); + let staticPlatformServices = ensureStaticPlatformServices(null); + + return staticPlatformServices.modeService.registerTokenizationSupport2(languageId, support); +} + +export function registerHoverProvider(languageId:string, support:HoverProvider): IDisposable { + return modes.HoverProviderRegistry.register(languageId, support); +} + +interface IMonacoWebWorkerState { + myProxy:StandaloneWorker; + foreignProxy:T; + modelMananger: EditorModelManager; +} + +export class MonacoWebWorker { + + private _loaded: TPromise>; + private _client: SimpleWorkerClient; + + constructor(modelService: IModelService, opts:IWebWorkerOptions) { + this._client = new SimpleWorkerClient(new DefaultWorkerFactory(), 'vs/editor/browser/standalone/standaloneWorker', null); + + this._loaded = this._client.getProxyObject().then((proxy) => { + + let proxyMethodRequest = (method:string, args:any[]): TPromise => { + return proxy.fmr(method, args); + }; + + let createProxyMethod = (method:string, proxyMethodRequest:(method:string, args:any[])=>TPromise): Function => { + return function () { + let args = Array.prototype.slice.call(arguments, 0); + return proxyMethodRequest(method, args); + }; + }; + + const manager = new EditorModelManager(proxy, modelService, true); + + return proxy.loadModule(opts.moduleId).then((foreignMethods): IMonacoWebWorkerState => { + + let foreignProxy = {}; + for (let i = 0; i < foreignMethods.length; i++) { + foreignProxy[foreignMethods[i]] = createProxyMethod(foreignMethods[i], proxyMethodRequest); + } + + return { + myProxy: proxy, + foreignProxy: foreignProxy, + modelMananger: manager + }; + }); + }); + } + + public dispose(): void { + console.log('TODO: I should dispose now'); + } + + public getProxy(): TPromise { + return this._loaded.then(data => data.foreignProxy); + } + + public withSyncedResources(resources: URI[]): TPromise { + return this._loaded.then(data => data.modelMananger.withSyncedResources(resources)); + } +} + +export interface IWebWorkerOptions { + moduleId: string; +} + +export function createWebWorker(opts:IWebWorkerOptions): MonacoWebWorker { + startup.initStaticServicesIfNecessary(); + let staticPlatformServices = ensureStaticPlatformServices(null); + let modelService = staticPlatformServices.modelService; + + return new MonacoWebWorker(modelService, opts); +} + export function registerMonarchStandaloneLanguage(language:ILanguageExtensionPoint, defModule:string): void { ModesRegistry.registerLanguage(language); @@ -501,6 +587,10 @@ export function registerStandaloneLanguage(language:ILanguageExtensionPoint, def }); } +export function registerStandaloneLanguage2(language:ILanguageExtensionPoint, defModule:string): void { + ModesRegistry.registerLanguage(language); +} + export function registerStandaloneSchema(uri:string, schema:IJSONSchema) { let schemaRegistry = Registry.as(Extensions.JSONContribution); schemaRegistry.registerSchema(uri, schema); diff --git a/src/vs/editor/browser/standalone/standaloneEditor.ts b/src/vs/editor/browser/standalone/standaloneEditor.ts index 409bedae472..1a04ef24923 100644 --- a/src/vs/editor/browser/standalone/standaloneEditor.ts +++ b/src/vs/editor/browser/standalone/standaloneEditor.ts @@ -7,12 +7,15 @@ import 'vs/editor/standalone-languages/all'; import './standaloneSchemas'; import 'vs/css!./media/standalone-tokens'; +import {Emitter} from 'vs/base/common/event'; import {IJSONSchema} from 'vs/base/common/jsonSchema'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {ClassNames, ContentWidgetPositionPreference, OverlayWidgetPositionPreference} from 'vs/editor/browser/editorBrowser'; import {Colorizer} from 'vs/editor/browser/standalone/colorizer'; import * as standaloneCodeEditor from 'vs/editor/browser/standalone/standaloneCodeEditor'; import {ILanguageDef} from 'vs/editor/standalone-languages/types'; +// import {ModesRegistry} from 'vs/editor/common/modes/modesRegistry'; +import {ExtensionsRegistry} from 'vs/platform/extensions/common/extensionsRegistry'; var global:any = self; if (!global.Monaco) { @@ -77,3 +80,34 @@ if (!Monaco.Languages) { Monaco.Languages = {}; } Monaco.Languages.register = standaloneCodeEditor.registerStandaloneLanguage; +Monaco.Languages.register2 = standaloneCodeEditor.registerStandaloneLanguage2; +Monaco.Languages.onLanguage = (languageId:string, callback:()=>void) => { + let isDisposed = false; + ExtensionsRegistry.registerOneTimeActivationEventListener('onLanguage:' + languageId, () => { + if (!isDisposed) { + callback(); + } + }); + return { + dispose: () => { isDisposed = true; } + }; +}; +Monaco.createWebWorker = standaloneCodeEditor.createWebWorker; +Monaco.Languages.registerTokensProvider = standaloneCodeEditor.registerTokensProvider; +Monaco.Languages.registerHoverProvider = standaloneCodeEditor.registerHoverProvider; +Monaco.Emitter = Emitter; +// let handlePlugin = (plugin) => { +// if (Array.isArray(plugin.languages)) { +// ModesRegistry.registerLanguages(plugin.languages); +// } +// if (plugin.activate) { +// try { +// plugin.activate(); +// } catch(err) { +// console.error(err); +// } +// } +// }; +// let MonacoPlugins = this.MonacoPlugins || []; +// MonacoPlugins.forEach(handlePlugin); +// this.MonacoPlugins = { push: handlePlugin }; \ No newline at end of file diff --git a/src/vs/editor/browser/standalone/standaloneServices.ts b/src/vs/editor/browser/standalone/standaloneServices.ts index d8aabae64ba..ad5e4422e85 100644 --- a/src/vs/editor/browser/standalone/standaloneServices.ts +++ b/src/vs/editor/browser/standalone/standaloneServices.ts @@ -26,7 +26,7 @@ import {IMessageService} from 'vs/platform/message/common/message'; import {IProgressService} from 'vs/platform/progress/common/progress'; import {IRequestService} from 'vs/platform/request/common/request'; import {ISearchService} from 'vs/platform/search/common/search'; -import {IStorageService} from 'vs/platform/storage/common/storage'; +import {IStorageService, NullStorageService} from 'vs/platform/storage/common/storage'; import {ITelemetryService, NullTelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {MainThreadService} from 'vs/platform/thread/common/mainThreadService'; import {IThreadService} from 'vs/platform/thread/common/thread'; @@ -86,6 +86,7 @@ export interface IStaticServices { codeEditorService: ICodeEditorService; editorWorkerService: IEditorWorkerService; eventService: IEventService; + storageService: IStorageService; instantiationService: IInstantiationService; } @@ -197,6 +198,7 @@ export function getOrCreateStaticServices(services?: IEditorOverrideServices): I codeEditorService: codeEditorService, editorWorkerService: editorWorkerService, eventService: eventService, + storageService: services.storageService || NullStorageService, instantiationService: void 0 }; diff --git a/src/vs/editor/browser/standalone/standaloneWorker.ts b/src/vs/editor/browser/standalone/standaloneWorker.ts new file mode 100644 index 00000000000..5114dbb024f --- /dev/null +++ b/src/vs/editor/browser/standalone/standaloneWorker.ts @@ -0,0 +1,226 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import URI from 'vs/base/common/uri'; +import {ErrorCallback, TPromise, ValueCallback} from 'vs/base/common/winjs.base'; +import {IRequestHandler} from 'vs/base/common/worker/simpleWorker'; +import {Range} from 'vs/editor/common/core/range'; +import * as editorCommon from 'vs/editor/common/editorCommon'; +import {MirrorModel2} from 'vs/editor/common/model/mirrorModel2'; +import {WordHelper} from 'vs/editor/common/model/textModelWithTokensHelpers'; +import {IRawModelData} from 'vs/editor/common/services/editorSimpleWorkerCommon'; +import {Emitter} from 'vs/base/common/event'; + +class MirrorModel extends MirrorModel2 { + + public get uri(): URI { + return this._uri; + } + + public get version(): number { + return this._versionId; + } + + public getLinesContent(): string[] { + return this._lines.slice(0); + } + + public getLineCount(): number { + return this._lines.length; + } + + public getLineContent(lineNumber:number): string { + return this._lines[lineNumber - 1]; + } + + public getWordAtPosition(position:editorCommon.IPosition, wordDefinition:RegExp): Range { + + let wordAtText = WordHelper._getWordAtText( + position.column, + WordHelper.ensureValidWordDefinition(wordDefinition), + this._lines[position.lineNumber - 1], + 0 + ); + + if (wordAtText) { + return new Range(position.lineNumber, wordAtText.startColumn, position.lineNumber, wordAtText.endColumn); + } + + return null; + } + + public getWordUntilPosition(position: editorCommon.IPosition, wordDefinition:RegExp): editorCommon.IWordAtPosition { + var wordAtPosition = this.getWordAtPosition(position, wordDefinition); + if (!wordAtPosition) { + return { + word: '', + startColumn: position.column, + endColumn: position.column + }; + } + return { + word: this._lines[position.lineNumber - 1].substring(wordAtPosition.startColumn - 1, position.column - 1), + startColumn: wordAtPosition.startColumn, + endColumn: position.column + }; + } + + private _getAllWords(wordDefinition:RegExp): string[] { + var result:string[] = []; + this._lines.forEach((line) => { + this._wordenize(line, wordDefinition).forEach((info) => { + result.push(line.substring(info.start, info.end)); + }); + }); + return result; + } + + public getAllUniqueWords(wordDefinition:RegExp, skipWordOnce?:string) : string[] { + var foundSkipWord = false; + var uniqueWords = {}; + return this._getAllWords(wordDefinition).filter((word) => { + if (skipWordOnce && !foundSkipWord && skipWordOnce === word) { + foundSkipWord = true; + return false; + } else if (uniqueWords[word]) { + return false; + } else { + uniqueWords[word] = true; + return true; + } + }); + } + +// // TODO@Joh, TODO@Alex - remove these and make sure the super-things work + private _wordenize(content:string, wordDefinition:RegExp): editorCommon.IWordRange[] { + var result:editorCommon.IWordRange[] = []; + var match:RegExpExecArray; + while (match = wordDefinition.exec(content)) { + if (match[0].length === 0) { + // it did match the empty string + break; + } + result.push({ start: match.index, end: match.index + match[0].length }); + } + return result; + } + + public getValueInRange(range:editorCommon.IRange): string { + if (range.startLineNumber === range.endLineNumber) { + return this._lines[range.startLineNumber - 1].substring(range.startColumn - 1, range.endColumn - 1); + } + + var lineEnding = this._eol, + startLineIndex = range.startLineNumber - 1, + endLineIndex = range.endLineNumber - 1, + resultLines:string[] = []; + + resultLines.push(this._lines[startLineIndex].substring(range.startColumn - 1)); + for (var i = startLineIndex + 1; i < endLineIndex; i++) { + resultLines.push(this._lines[i]); + } + resultLines.push(this._lines[endLineIndex].substring(0, range.endColumn - 1)); + + return resultLines.join(lineEnding); + } +} + +this.Monaco = this.Monaco || {}; +var Monaco = this.Monaco; + +this.monaco = this.monaco || {}; +var monaco = this.monaco; + +export class StandaloneWorker /*extends EditorSimpleWorker*/ implements IRequestHandler { + _requestHandlerTrait: any; + + private _models:{[uri:string]:MirrorModel;}; + private _foreignModule: any; + + constructor() { + // super(); + this._models = Object.create(null); + this._foreignModule = null; + + + Monaco.TPromise = TPromise; + Monaco.Emitter = Emitter; + + let that = this; + monaco.worker = { + get mirrorModels () { + let all: MirrorModel[] = []; + Object.keys(that._models).forEach((key) => all.push(that._models[key])); + return all; + } + }; + } + + public acceptNewModel(data:IRawModelData): void { + this._models[data.url] = new MirrorModel(URI.parse(data.url), data.value.lines, data.value.EOL, data.versionId); + } + + public acceptModelChanged(strURL: string, events: editorCommon.IModelContentChangedEvent2[]): void { + if (!this._models[strURL]) { + return; + } + let model = this._models[strURL]; + model.onEvents(events); + } + + public acceptRemovedModel(strURL: string): void { + if (!this._models[strURL]) { + return; + } + delete this._models[strURL]; + } + + public loadModule(moduleId:string): TPromise { + let cc: ValueCallback; + let ee: ErrorCallback; + let r = new TPromise((c, e, p) => { + cc = c; + ee = e; + }); + + require([moduleId], (foreignModule) => { + this._foreignModule = foreignModule.create(); + + let methods: string[] = []; + for (let prop in this._foreignModule) { + if (typeof this._foreignModule[prop] === 'function') { + methods.push(prop); + } + } + + cc(methods); + + }, ee); + + return r; + } + + // foreign method request + public fmr(method:string, args:any[]): TPromise { + if (!this._foreignModule || typeof this._foreignModule[method] !== 'function') { + return TPromise.wrapError(new Error('Missing requestHandler or method: ' + method)); + } + + try { + return TPromise.as(this._foreignModule[method].apply(this._foreignModule, args)); + } catch (e) { + return TPromise.wrapError(e); + } + } +} + +/** + * Called on the worker side + */ +export function create(): IRequestHandler { + return new StandaloneWorker(); +} diff --git a/src/vs/editor/browser/view/viewController.ts b/src/vs/editor/browser/view/viewController.ts index 766e5ec2da7..9edf83723f6 100644 --- a/src/vs/editor/browser/view/viewController.ts +++ b/src/vs/editor/browser/view/viewController.ts @@ -4,13 +4,14 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {IEventEmitter} from 'vs/base/common/eventEmitter'; +import {EventEmitter} from 'vs/base/common/eventEmitter'; import {IKeyboardEvent} from 'vs/base/browser/keyboardEvent'; import {Position} from 'vs/editor/common/core/position'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {IEditorMouseEvent, IViewController, IMouseDispatchData} from 'vs/editor/browser/editorBrowser'; import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; import {IViewModel} from 'vs/editor/common/viewModel/viewModel'; +import {Range} from 'vs/editor/common/core/range'; export interface TriggerCursorHandler { (source:string, handlerId:string, payload:any): void; @@ -20,13 +21,13 @@ export class ViewController implements IViewController { private viewModel:IViewModel; private triggerCursorHandler:TriggerCursorHandler; - private outgoingEventBus:IEventEmitter; + private outgoingEventBus:EventEmitter; private keybindingService:IKeybindingService; constructor( viewModel:IViewModel, triggerCursorHandler:TriggerCursorHandler, - outgoingEventBus:IEventEmitter, + outgoingEventBus:EventEmitter, keybindingService:IKeybindingService ) { this.viewModel = viewModel; @@ -59,7 +60,7 @@ export class ViewController implements IViewController { this.keybindingService.executeCommand(editorCommon.Handler.Cut, {}); } - private _validateViewColumn(viewPosition:editorCommon.IEditorPosition): editorCommon.IEditorPosition { + private _validateViewColumn(viewPosition:Position): Position { var minColumn = this.viewModel.getLineMinColumn(viewPosition.lineNumber); if (viewPosition.column < minColumn) { return new Position(viewPosition.lineNumber, minColumn); @@ -133,7 +134,7 @@ export class ViewController implements IViewController { } } - public moveTo(source:string, viewPosition:editorCommon.IEditorPosition): void { + public moveTo(source:string, viewPosition:Position): void { viewPosition = this._validateViewColumn(viewPosition); this.triggerCursorHandler(source, editorCommon.Handler.MoveTo, { position: this.convertViewToModelPosition(viewPosition), @@ -141,7 +142,7 @@ export class ViewController implements IViewController { }); } - private moveToSelect(source:string, viewPosition:editorCommon.IEditorPosition): void { + private moveToSelect(source:string, viewPosition:Position): void { viewPosition = this._validateViewColumn(viewPosition); this.triggerCursorHandler(source, editorCommon.Handler.MoveToSelect, { position: this.convertViewToModelPosition(viewPosition), @@ -149,7 +150,7 @@ export class ViewController implements IViewController { }); } - private columnSelect(source:string, viewPosition:editorCommon.IEditorPosition, mouseColumn:number): void { + private columnSelect(source:string, viewPosition:Position, mouseColumn:number): void { viewPosition = this._validateViewColumn(viewPosition); this.triggerCursorHandler(source, editorCommon.Handler.ColumnSelect, { position: this.convertViewToModelPosition(viewPosition), @@ -158,7 +159,7 @@ export class ViewController implements IViewController { }); } - private createCursor(source:string, viewPosition:editorCommon.IEditorPosition, wholeLine:boolean): void { + private createCursor(source:string, viewPosition:Position, wholeLine:boolean): void { viewPosition = this._validateViewColumn(viewPosition); this.triggerCursorHandler(source, editorCommon.Handler.CreateCursor, { position: this.convertViewToModelPosition(viewPosition), @@ -167,7 +168,7 @@ export class ViewController implements IViewController { }); } - private lastCursorMoveToSelect(source:string, viewPosition:editorCommon.IEditorPosition): void { + private lastCursorMoveToSelect(source:string, viewPosition:Position): void { viewPosition = this._validateViewColumn(viewPosition); this.triggerCursorHandler(source, editorCommon.Handler.LastCursorMoveToSelect, { position: this.convertViewToModelPosition(viewPosition), @@ -175,28 +176,28 @@ export class ViewController implements IViewController { }); } - private wordSelect(source:string, viewPosition:editorCommon.IEditorPosition): void { + private wordSelect(source:string, viewPosition:Position): void { viewPosition = this._validateViewColumn(viewPosition); this.triggerCursorHandler(source, editorCommon.Handler.WordSelect, { position: this.convertViewToModelPosition(viewPosition) }); } - private wordSelectDrag(source:string, viewPosition:editorCommon.IEditorPosition): void { + private wordSelectDrag(source:string, viewPosition:Position): void { viewPosition = this._validateViewColumn(viewPosition); this.triggerCursorHandler(source, editorCommon.Handler.WordSelectDrag, { position: this.convertViewToModelPosition(viewPosition) }); } - private lastCursorWordSelect(source:string, viewPosition:editorCommon.IEditorPosition): void { + private lastCursorWordSelect(source:string, viewPosition:Position): void { viewPosition = this._validateViewColumn(viewPosition); this.triggerCursorHandler(source, editorCommon.Handler.LastCursorWordSelect, { position: this.convertViewToModelPosition(viewPosition) }); } - private lineSelect(source:string, viewPosition:editorCommon.IEditorPosition): void { + private lineSelect(source:string, viewPosition:Position): void { viewPosition = this._validateViewColumn(viewPosition); this.triggerCursorHandler(source, editorCommon.Handler.LineSelect, { position: this.convertViewToModelPosition(viewPosition), @@ -204,7 +205,7 @@ export class ViewController implements IViewController { }); } - private lineSelectDrag(source:string, viewPosition:editorCommon.IEditorPosition): void { + private lineSelectDrag(source:string, viewPosition:Position): void { viewPosition = this._validateViewColumn(viewPosition); this.triggerCursorHandler(source, editorCommon.Handler.LineSelectDrag, { position: this.convertViewToModelPosition(viewPosition), @@ -212,7 +213,7 @@ export class ViewController implements IViewController { }); } - private lastCursorLineSelect(source:string, viewPosition:editorCommon.IEditorPosition): void { + private lastCursorLineSelect(source:string, viewPosition:Position): void { viewPosition = this._validateViewColumn(viewPosition); this.triggerCursorHandler(source, editorCommon.Handler.LastCursorLineSelect, { position: this.convertViewToModelPosition(viewPosition), @@ -220,7 +221,7 @@ export class ViewController implements IViewController { }); } - private lastCursorLineSelectDrag(source:string, viewPosition:editorCommon.IEditorPosition): void { + private lastCursorLineSelectDrag(source:string, viewPosition:Position): void { viewPosition = this._validateViewColumn(viewPosition); this.triggerCursorHandler(source, editorCommon.Handler.LastCursorLineSelectDrag, { position: this.convertViewToModelPosition(viewPosition), @@ -234,11 +235,11 @@ export class ViewController implements IViewController { // ---------------------- - private convertViewToModelPosition(viewPosition:editorCommon.IEditorPosition): editorCommon.IEditorPosition { + private convertViewToModelPosition(viewPosition:Position): Position { return this.viewModel.convertViewPositionToModelPosition(viewPosition.lineNumber, viewPosition.column); } - private convertViewToModelRange(viewRange:editorCommon.IRange): editorCommon.IEditorRange { + private convertViewToModelRange(viewRange:editorCommon.IRange): Range { return this.viewModel.convertViewRangeToModelRange(viewRange); } diff --git a/src/vs/editor/browser/view/viewEventDispatcher.ts b/src/vs/editor/browser/view/viewEventDispatcher.ts index 4218859b696..bf20e901f1d 100644 --- a/src/vs/editor/browser/view/viewEventDispatcher.ts +++ b/src/vs/editor/browser/view/viewEventDispatcher.ts @@ -4,14 +4,14 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {EmitterEvent, IEmitterEvent} from 'vs/base/common/eventEmitter'; +import {EmitterEvent} from 'vs/base/common/eventEmitter'; import {IViewEventBus, IViewEventHandler} from 'vs/editor/common/view/viewContext'; export class ViewEventDispatcher implements IViewEventBus { private _eventHandlerGateKeeper:(callback:()=>void)=>void; private _eventHandlers:IViewEventHandler[]; - private _eventQueue:IEmitterEvent[]; + private _eventQueue:EmitterEvent[]; private _isConsumingQueue:boolean; constructor(eventHandlerGateKeeper:(callback:()=>void)=>void) { @@ -53,7 +53,7 @@ export class ViewEventDispatcher implements IViewEventBus { } } - public emitMany(events:IEmitterEvent[]): void { + public emitMany(events:EmitterEvent[]): void { if (this._eventQueue) { this._eventQueue = this._eventQueue.concat(events); } else { diff --git a/src/vs/editor/browser/view/viewImpl.ts b/src/vs/editor/browser/view/viewImpl.ts index 574c007fee2..8d9c69f9d39 100644 --- a/src/vs/editor/browser/view/viewImpl.ts +++ b/src/vs/editor/browser/view/viewImpl.ts @@ -5,7 +5,7 @@ 'use strict'; import {onUnexpectedError} from 'vs/base/common/errors'; -import {EventEmitter, IEmitterEvent, IEventEmitter, ListenerUnbind} from 'vs/base/common/eventEmitter'; +import {EventEmitter, EmitterEvent, IEventEmitter} from 'vs/base/common/eventEmitter'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import * as timer from 'vs/base/common/timer'; import * as browser from 'vs/base/browser/browser'; @@ -49,7 +49,7 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp private eventDispatcher:ViewEventDispatcher; - private listenersToRemove:ListenerUnbind[]; + private listenersToRemove:IDisposable[]; private listenersToDispose:IDisposable[]; private layoutProvider: LayoutProvider; @@ -82,7 +82,7 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp private _isDisposed: boolean; private handleAccumulatedModelEventsTimeout:number; - private accumulatedModelEvents: IEmitterEvent[]; + private accumulatedModelEvents: EmitterEvent[]; private _renderAnimationFrame: IDisposable; private _keybindingService: IKeybindingService; @@ -148,7 +148,7 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp // This delayed processing of incoming model events acts as a guard against undesired/unexpected recursion. this.handleAccumulatedModelEventsTimeout = -1; this.accumulatedModelEvents = []; - this.listenersToRemove.push(model.addBulkListener((events:IEmitterEvent[]) => { + this.listenersToRemove.push(model.addBulkListener2((events:EmitterEvent[]) => { this.accumulatedModelEvents = this.accumulatedModelEvents.concat(events); if (this.handleAccumulatedModelEventsTimeout === -1) { this.handleAccumulatedModelEventsTimeout = setTimeout(() => { @@ -457,14 +457,7 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp return false; } public onScrollChanged(e:editorCommon.IScrollEvent): boolean { - this.outgoingEventBus.emit('scroll', { - scrollTop: this.layoutProvider.getScrollTop(), - scrollLeft: this.layoutProvider.getScrollLeft() - }); - this.outgoingEventBus.emit('scrollSize', { - scrollWidth: this.layoutProvider.getScrollWidth(), - scrollHeight: this.layoutProvider.getScrollHeight() - }); + this.outgoingEventBus.emit('scroll', e); return false; } public onViewFocusChanged(isFocused:boolean): boolean { @@ -494,11 +487,7 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp this.eventDispatcher.removeEventHandler(this); this.outgoingEventBus.dispose(); - this.listenersToRemove.forEach((element) => { - element(); - }); - this.listenersToRemove = []; - + this.listenersToRemove = dispose(this.listenersToRemove); this.listenersToDispose = dispose(this.listenersToDispose); this.keyboardHandler.dispose(); @@ -593,7 +582,7 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp return this.codeEditorHelper; } - public getCenteredRangeInViewport(): editorCommon.IEditorRange { + public getCenteredRangeInViewport(): Range { if (this._isDisposed) { throw new Error('ViewImpl.getCenteredRangeInViewport: View is disposed'); } diff --git a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts index d11d9a98327..c2d2380c6f0 100644 --- a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts +++ b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts @@ -13,6 +13,7 @@ import {ClassNames, ContentWidgetPositionPreference, IContentWidget} from 'vs/ed import {ViewPart} from 'vs/editor/browser/view/viewPart'; import {ViewContext} from 'vs/editor/common/view/viewContext'; import {IRenderingContext, IRestrictedRenderingContext} from 'vs/editor/common/view/renderingContext'; +import {Position} from 'vs/editor/common/core/position'; interface IWidgetData { allowEditorOverflow: boolean; @@ -184,7 +185,7 @@ export class ViewContentWidgets extends ViewPart { } } - private _layoutBoxInViewport(position:editorCommon.IEditorPosition, domNode:HTMLElement, ctx:IRenderingContext): IBoxLayoutResult { + private _layoutBoxInViewport(position:Position, domNode:HTMLElement, ctx:IRenderingContext): IBoxLayoutResult { let visibleRange = ctx.visibleRangeForPosition(position); @@ -228,7 +229,7 @@ export class ViewContentWidgets extends ViewPart { }; } - private _layoutBoxInPage(position: editorCommon.IEditorPosition, domNode: HTMLElement, ctx: IRenderingContext): IBoxLayoutResult { + private _layoutBoxInPage(position: Position, domNode: HTMLElement, ctx: IRenderingContext): IBoxLayoutResult { let visibleRange = ctx.visibleRangeForPosition(position); if (!visibleRange) { @@ -282,7 +283,7 @@ export class ViewContentWidgets extends ViewPart { }; } - private _prepareRenderWidgetAtExactPosition(position:editorCommon.IEditorPosition, ctx:IRenderingContext): IMyWidgetRenderData { + private _prepareRenderWidgetAtExactPosition(position:Position, ctx:IRenderingContext): IMyWidgetRenderData { let visibleRange = ctx.visibleRangeForPosition(position); if (!visibleRange) { diff --git a/src/vs/editor/browser/viewParts/lines/viewLines.ts b/src/vs/editor/browser/viewParts/lines/viewLines.ts index 67e3ae60ad6..f0f93de1240 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLines.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLines.ts @@ -436,7 +436,7 @@ export class ViewLines extends ViewLayer { } } - private _computeScrollTopToRevealRange(viewport:editorCommon.Viewport, range: editorCommon.IEditorRange, verticalType: editorCommon.VerticalRevealType): number { + private _computeScrollTopToRevealRange(viewport:editorCommon.Viewport, range: Range, verticalType: editorCommon.VerticalRevealType): number { var viewportStartY = viewport.top, viewportHeight = viewport.height, viewportEndY = viewportStartY + viewportHeight, @@ -469,7 +469,7 @@ export class ViewLines extends ViewLayer { return newScrollTop; } - private _computeScrollLeftToRevealRange(range: editorCommon.IEditorRange): { scrollLeft: number; maxHorizontalOffset: number; } { + private _computeScrollLeftToRevealRange(range: Range): { scrollLeft: number; maxHorizontalOffset: number; } { var maxHorizontalOffset = 0; diff --git a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts index 463224e6047..125f9e14295 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts @@ -6,11 +6,11 @@ import * as themes from 'vs/platform/theme/common/themes'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import {OverviewRulerZone} from 'vs/editor/browser/editorBrowser'; import {ViewPart} from 'vs/editor/browser/view/viewPart'; import {OverviewRulerImpl} from 'vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl'; import {ViewContext} from 'vs/editor/common/view/viewContext'; import {IRenderingContext, IRestrictedRenderingContext} from 'vs/editor/common/view/renderingContext'; +import {Position} from 'vs/editor/common/core/position'; export class DecorationsOverviewRuler extends ViewPart { @@ -25,10 +25,10 @@ export class DecorationsOverviewRuler extends ViewPart { private _shouldUpdateCursorPosition:boolean; private _hideCursor:boolean; - private _cursorPositions: editorCommon.IEditorPosition[]; + private _cursorPositions: Position[]; - private _zonesFromDecorations: OverviewRulerZone[]; - private _zonesFromCursors: OverviewRulerZone[]; + private _zonesFromDecorations: editorCommon.OverviewRulerZone[]; + private _zonesFromCursors: editorCommon.OverviewRulerZone[]; constructor(context:ViewContext, scrollHeight:number, getVerticalOffsetForLine:(lineNumber:number)=>number) { super(context); @@ -137,14 +137,14 @@ export class DecorationsOverviewRuler extends ViewPart { return this._overviewRuler.getDomNode(); } - private _createZonesFromDecorations(): OverviewRulerZone[] { + private _createZonesFromDecorations(): editorCommon.OverviewRulerZone[] { let decorations = this._context.model.getAllDecorations(); - let zones:OverviewRulerZone[] = []; + let zones:editorCommon.OverviewRulerZone[] = []; for (let i = 0, len = decorations.length; i < len; i++) { let dec = decorations[i]; if (dec.options.overviewRuler.color) { - zones.push(new OverviewRulerZone( + zones.push(new editorCommon.OverviewRulerZone( dec.range.startLineNumber, dec.range.endLineNumber, dec.options.overviewRuler.position, @@ -158,13 +158,13 @@ export class DecorationsOverviewRuler extends ViewPart { return zones; } - private _createZonesFromCursors(): OverviewRulerZone[] { - let zones:OverviewRulerZone[] = []; + private _createZonesFromCursors(): editorCommon.OverviewRulerZone[] { + let zones:editorCommon.OverviewRulerZone[] = []; for (let i = 0, len = this._cursorPositions.length; i < len; i++) { let cursor = this._cursorPositions[i]; - zones.push(new OverviewRulerZone( + zones.push(new editorCommon.OverviewRulerZone( cursor.lineNumber, cursor.lineNumber, editorCommon.OverviewRulerLane.Full, @@ -201,7 +201,7 @@ export class DecorationsOverviewRuler extends ViewPart { } } - var allZones:OverviewRulerZone[] = []; + var allZones:editorCommon.OverviewRulerZone[] = []; allZones = allZones.concat(this._zonesFromCursors); allZones = allZones.concat(this._zonesFromDecorations); @@ -216,11 +216,11 @@ export class DecorationsOverviewRuler extends ViewPart { ctx2.lineWidth = 1; ctx2.strokeStyle = 'rgba(197,197,197,0.8)'; ctx2.moveTo(0, 0); - ctx2.lineTo(0, this._overviewRuler.getHeight()); + ctx2.lineTo(0, this._overviewRuler.getPixelHeight()); ctx2.stroke(); ctx2.moveTo(0, 0); - ctx2.lineTo(this._overviewRuler.getWidth(), 0); + ctx2.lineTo(this._overviewRuler.getPixelWidth(), 0); ctx2.stroke(); } } diff --git a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts index a14bb490716..2e0e8fb674c 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {IConfigurationChangedEvent, OverviewRulerPosition, IScrollEvent} from 'vs/editor/common/editorCommon'; +import {IConfigurationChangedEvent, OverviewRulerPosition, OverviewRulerZone, IScrollEvent} from 'vs/editor/common/editorCommon'; import {ViewEventHandler} from 'vs/editor/common/viewModel/viewEventHandler'; -import {IOverviewRuler, OverviewRulerZone} from 'vs/editor/browser/editorBrowser'; +import {IOverviewRuler} from 'vs/editor/browser/editorBrowser'; import {OverviewRulerImpl} from 'vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl'; import {ViewContext} from 'vs/editor/common/view/viewContext'; diff --git a/src/vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl.ts b/src/vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl.ts index c0e3c8c4526..6a7ba584760 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl.ts @@ -5,269 +5,10 @@ 'use strict'; import {StyleMutator} from 'vs/base/browser/styleMutator'; -import {OverviewRulerPosition, OverviewRulerLane} from 'vs/editor/common/editorCommon'; -import {OverviewRulerZone, ColorZone} from 'vs/editor/browser/editorBrowser'; - -class ZoneManager { - - private _getVerticalOffsetForLine:(lineNumber:number)=>number; - private _zones: OverviewRulerZone[]; - private _colorZonesInvalid: boolean; - private _lineHeight: number; - private _width: number; - private _height: number; - private _outerHeight: number; - private _maximumHeight: number; - private _minimumHeight: number; - private _useDarkColor: boolean; - - private _lastAssignedId; - private _color2Id: { [color:string]: number; }; - private _id2Color: string[]; - - constructor(getVerticalOffsetForLine:(lineNumber:number)=>number) { - this._getVerticalOffsetForLine = getVerticalOffsetForLine; - this._zones = []; - this._colorZonesInvalid = false; - this._lineHeight = 0; - this._width = 0; - this._height = 0; - this._outerHeight = 0; - this._maximumHeight = 0; - this._minimumHeight = 0; - this._useDarkColor = false; - - this._lastAssignedId = 0; - this._color2Id = Object.create(null); - this._id2Color = []; - } - - public getId2Color(): string[] { - return this._id2Color; - } - - public setZones(newZones: OverviewRulerZone[]): void { - newZones.sort((a, b) => a.compareTo(b)); - - let oldZones = this._zones; - let oldIndex = 0; - let oldLength = this._zones.length; - let newIndex = 0; - let newLength = newZones.length; - - let result: OverviewRulerZone[] = []; - while (newIndex < newLength) { - let newZone = newZones[newIndex]; - - if (oldIndex >= oldLength) { - result.push(newZone); - newIndex++; - } else { - let oldZone = oldZones[oldIndex]; - let cmp = oldZone.compareTo(newZone); - if (cmp < 0) { - oldIndex++; - } else if (cmp > 0) { - result.push(newZone); - newIndex++; - } else { - // cmp === 0 - result.push(oldZone); - oldIndex++; - newIndex++; - } - } - } - - this._zones = result; - } - - public setLineHeight(lineHeight:number): boolean { - if (this._lineHeight === lineHeight) { - return false; - } - this._lineHeight = lineHeight; - this._colorZonesInvalid = true; - return true; - } - - public getWidth(): number { - return this._width; - } - - public setWidth(width:number): boolean { - if (this._width === width) { - return false; - } - this._width = width; - this._colorZonesInvalid = true; - return true; - } - - public getHeight(): number { - return this._height; - } - - public setHeight(height:number): boolean { - if (this._height === height) { - return false; - } - this._height = height; - this._colorZonesInvalid = true; - return true; - } - - public getOuterHeight(): number { - return this._outerHeight; - } - - public setOuterHeight(outerHeight:number): boolean { - if (this._outerHeight === outerHeight) { - return false; - } - this._outerHeight = outerHeight; - this._colorZonesInvalid = true; - return true; - } - - public setMaximumHeight(maximumHeight:number): boolean { - if (this._maximumHeight === maximumHeight) { - return false; - } - this._maximumHeight = maximumHeight; - this._colorZonesInvalid = true; - return true; - } - - public setMinimumHeight(minimumHeight:number): boolean { - if (this._minimumHeight === minimumHeight) { - return false; - } - this._minimumHeight = minimumHeight; - this._colorZonesInvalid = true; - return true; - } - - public setUseDarkColor(useDarkColor:boolean): boolean { - if (this._useDarkColor === useDarkColor) { - return false; - } - this._useDarkColor = useDarkColor; - this._colorZonesInvalid = true; - return true; - } - - public resolveColorZones(): ColorZone[] { - const colorZonesInvalid = this._colorZonesInvalid; - const lineHeight = Math.floor(this._lineHeight); // @perf - const totalHeight = Math.floor(this._height); // @perf - const maximumHeight = Math.floor(this._maximumHeight); // @perf - const minimumHeight = Math.floor(this._minimumHeight); // @perf - const useDarkColor = this._useDarkColor; // @perf - const outerHeight = Math.floor(this._outerHeight); // @perf - const heightRatio = totalHeight / outerHeight; - - let allColorZones: ColorZone[] = []; - for (let i = 0, len = this._zones.length; i < len; i++) { - let zone = this._zones[i]; - - if (!colorZonesInvalid) { - let colorZones = zone.getColorZones(); - if (colorZones) { - for (let j = 0, lenJ = colorZones.length; j < lenJ; j++) { - allColorZones.push(colorZones[j]); - } - continue; - } - } - - let y1 = Math.floor(this._getVerticalOffsetForLine(zone.startLineNumber)); - let y2 = Math.floor(this._getVerticalOffsetForLine(zone.endLineNumber)) + lineHeight; - - y1 = Math.floor(y1 * heightRatio); - y2 = Math.floor(y2 * heightRatio); - - let colorZones: ColorZone[] = []; - if (zone.forceHeight) { - y2 = y1 + zone.forceHeight; - colorZones.push(this.createZone(totalHeight, y1, y2, zone.forceHeight, zone.forceHeight, zone.getColor(useDarkColor), zone.position)); - } else { - // Figure out if we can render this in one continuous zone - let zoneLineNumbers = zone.endLineNumber - zone.startLineNumber + 1; - let zoneMaximumHeight = zoneLineNumbers * maximumHeight; - - if (y2 - y1 > zoneMaximumHeight) { - // We need to draw one zone per line - for (let lineNumber = zone.startLineNumber; lineNumber <= zone.endLineNumber; lineNumber++) { - y1 = Math.floor(this._getVerticalOffsetForLine(lineNumber)); - y2 = y1 + lineHeight; - - y1 = Math.floor(y1 * heightRatio); - y2 = Math.floor(y2 * heightRatio); - - colorZones.push(this.createZone(totalHeight, y1, y2, minimumHeight, maximumHeight, zone.getColor(useDarkColor), zone.position)); - } - } else { - colorZones.push(this.createZone(totalHeight, y1, y2, minimumHeight, zoneMaximumHeight, zone.getColor(useDarkColor), zone.position)); - } - } - - zone.setColorZones(colorZones); - for (let j = 0, lenJ = colorZones.length; j < lenJ; j++) { - allColorZones.push(colorZones[j]); - } - } - - this._colorZonesInvalid = false; - - let sortFunc = (a:ColorZone, b:ColorZone) => { - if (a.colorId === b.colorId) { - if (a.from === b.from) { - return a.to - b.to; - } - return a.from - b.from; - } - return a.colorId - b.colorId; - }; - - allColorZones.sort(sortFunc); - return allColorZones; - } - - public createZone(totalHeight:number, y1:number, y2:number, minimumHeight:number, maximumHeight:number, color:string, position:OverviewRulerLane): ColorZone { - totalHeight = Math.floor(totalHeight); // @perf - y1 = Math.floor(y1); // @perf - y2 = Math.floor(y2); // @perf - minimumHeight = Math.floor(minimumHeight); // @perf - maximumHeight = Math.floor(maximumHeight); // @perf - - let ycenter = Math.floor((y1 + y2) / 2); - let halfHeight = (y2 - ycenter); - - - if (halfHeight > maximumHeight / 2) { - halfHeight = maximumHeight / 2; - } - if (halfHeight < minimumHeight / 2) { - halfHeight = minimumHeight / 2; - } - - if (ycenter - halfHeight < 0) { - ycenter = halfHeight; - } - if (ycenter + halfHeight > totalHeight) { - ycenter = totalHeight - halfHeight; - } - - let colorId = this._color2Id[color]; - if (!colorId) { - colorId = (++this._lastAssignedId); - this._color2Id[color] = colorId; - this._id2Color[colorId] = color; - } - return new ColorZone(ycenter - halfHeight, ycenter + halfHeight, colorId, position); - } -} +import {OverviewRulerPosition, OverviewRulerLane, OverviewRulerZone, ColorZone} from 'vs/editor/common/editorCommon'; +import {IDisposable} from 'vs/base/common/lifecycle'; +import * as browser from 'vs/base/browser/browser'; +import {OverviewZoneManager} from 'vs/editor/common/view/overviewZoneManager'; export class OverviewRulerImpl { @@ -276,9 +17,11 @@ export class OverviewRulerImpl { private _canvasLeftOffset: number; private _domNode: HTMLCanvasElement; private _lanesCount:number; - private _zoneManager: ZoneManager; + private _zoneManager: OverviewZoneManager; private _canUseTranslate3d: boolean; + private _zoomListener: IDisposable; + constructor(canvasLeftOffset:number, cssClassName:string, scrollHeight:number, lineHeight:number, canUseTranslate3d:boolean, minimumHeight:number, maximumHeight:number, getVerticalOffsetForLine:(lineNumber:number)=>number) { this._canvasLeftOffset = canvasLeftOffset; @@ -290,17 +33,28 @@ export class OverviewRulerImpl { this._canUseTranslate3d = canUseTranslate3d; - this._zoneManager = new ZoneManager(getVerticalOffsetForLine); + this._zoneManager = new OverviewZoneManager(getVerticalOffsetForLine); this._zoneManager.setMinimumHeight(minimumHeight); this._zoneManager.setMaximumHeight(maximumHeight); this._zoneManager.setUseDarkColor(false); - this._zoneManager.setWidth(0); - this._zoneManager.setHeight(0); + this._zoneManager.setDOMWidth(0); + this._zoneManager.setDOMHeight(0); this._zoneManager.setOuterHeight(scrollHeight); this._zoneManager.setLineHeight(lineHeight); + + this._zoomListener = browser.onDidChangeZoomLevel(() => { + this._zoneManager.setPixelRatio(browser.getPixelRatio()); + this._domNode.style.width = this._zoneManager.getDOMWidth() + 'px'; + this._domNode.style.height = this._zoneManager.getDOMHeight() + 'px'; + this._domNode.width = this._zoneManager.getCanvasWidth(); + this._domNode.height = this._zoneManager.getCanvasHeight(); + this.render(true); + }); + this._zoneManager.setPixelRatio(browser.getPixelRatio()); } public dispose(): void { + this._zoomListener.dispose(); this._zoneManager = null; } @@ -309,12 +63,14 @@ export class OverviewRulerImpl { StyleMutator.setRight(this._domNode, position.right); let hasChanged = false; - hasChanged = this._zoneManager.setWidth(position.width) || hasChanged; - hasChanged = this._zoneManager.setHeight(position.height) || hasChanged; + hasChanged = this._zoneManager.setDOMWidth(position.width) || hasChanged; + hasChanged = this._zoneManager.setDOMHeight(position.height) || hasChanged; if (hasChanged) { - this._domNode.width = this._zoneManager.getWidth(); - this._domNode.height = this._zoneManager.getHeight(); + this._domNode.style.width = this._zoneManager.getDOMWidth() + 'px'; + this._domNode.style.height = this._zoneManager.getDOMHeight() + 'px'; + this._domNode.width = this._zoneManager.getCanvasWidth(); + this._domNode.height = this._zoneManager.getCanvasHeight(); if (render) { this.render(true); @@ -346,12 +102,12 @@ export class OverviewRulerImpl { return this._domNode; } - public getWidth(): number { - return this._zoneManager.getWidth(); + public getPixelWidth(): number { + return this._zoneManager.getCanvasWidth(); } - public getHeight(): number { - return this._zoneManager.getHeight(); + public getPixelHeight(): number { + return this._zoneManager.getCanvasHeight(); } public setScrollHeight(scrollHeight:number, render:boolean): void { @@ -395,8 +151,8 @@ export class OverviewRulerImpl { StyleMutator.setTransform(this._domNode, ''); } - const width = this._zoneManager.getWidth(); - const height = this._zoneManager.getHeight(); + const width = this._zoneManager.getCanvasWidth(); + const height = this._zoneManager.getCanvasHeight(); let colorZones = this._zoneManager.resolveColorZones(); let id2Color = this._zoneManager.getId2Color(); diff --git a/src/vs/editor/browser/viewParts/selections/selections.ts b/src/vs/editor/browser/viewParts/selections/selections.ts index e15c9d1851c..536d7fd09f5 100644 --- a/src/vs/editor/browser/viewParts/selections/selections.ts +++ b/src/vs/editor/browser/viewParts/selections/selections.ts @@ -11,6 +11,7 @@ import {DynamicViewOverlay} from 'vs/editor/browser/view/dynamicViewOverlay'; import {ViewContext} from 'vs/editor/common/view/viewContext'; import {HorizontalRange, LineVisibleRanges} from 'vs/editor/common/view/renderingContext'; import {IRenderingContext} from 'vs/editor/common/view/renderingContext'; +import {Range} from 'vs/editor/common/core/range'; enum CornerStyle { EXTERN, @@ -78,7 +79,7 @@ export class SelectionsOverlay extends DynamicViewOverlay { private _context:ViewContext; private _lineHeight:number; private _roundedSelection:boolean; - private _selections:editorCommon.IEditorRange[]; + private _selections:Range[]; private _renderResult:string[]; constructor(context:ViewContext) { @@ -271,7 +272,7 @@ export class SelectionsOverlay extends DynamicViewOverlay { } } - private _getVisibleRangesWithStyle(selection: editorCommon.IEditorRange, ctx: IRenderingContext, previousFrame:LineVisibleRangesWithStyle[]): LineVisibleRangesWithStyle[] { + private _getVisibleRangesWithStyle(selection: Range, ctx: IRenderingContext, previousFrame:LineVisibleRangesWithStyle[]): LineVisibleRangesWithStyle[] { let _linesVisibleRanges = ctx.linesVisibleRangesForRange(selection, true) || []; let linesVisibleRanges = _linesVisibleRanges.map(toStyled); let visibleRangesHaveGaps = this._visibleRangesHaveGaps(linesVisibleRanges); diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index 2df72cd3d74..50a87bbd73b 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -25,11 +25,40 @@ import * as editorBrowser from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {Colorizer} from 'vs/editor/browser/standalone/colorizer'; import {View} from 'vs/editor/browser/view/viewImpl'; -import {Disposable} from 'vs/base/common/lifecycle'; +import {Disposable, IDisposable} from 'vs/base/common/lifecycle'; import Event, {Emitter} from 'vs/base/common/event'; +import {IKeyboardEvent} from 'vs/base/browser/keyboardEvent'; export class CodeEditorWidget extends CommonCodeEditor implements editorBrowser.ICodeEditor { + public onMouseUp(listener: (e:editorBrowser.IEditorMouseEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.MouseUp, listener); + } + public onMouseDown(listener: (e:editorBrowser.IEditorMouseEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.MouseDown, listener); + } + public onContextMenu(listener: (e:editorBrowser.IEditorMouseEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.ContextMenu, listener); + } + public onMouseMove(listener: (e:editorBrowser.IEditorMouseEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.MouseMove, listener); + } + public onMouseLeave(listener: (e:editorBrowser.IEditorMouseEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.MouseLeave, listener); + } + public onKeyUp(listener: (e:IKeyboardEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.KeyUp, listener); + } + public onKeyDown(listener: (e:IKeyboardEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.KeyDown, listener); + } + public onDidLayoutChange(listener: (e:editorCommon.EditorLayoutInfo)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.EditorLayout, listener); + } + public onDidScrollChange(listener: (e:editorCommon.IScrollEvent)=>void): IDisposable { + return this.addListener2('scroll', listener); + } + protected domElement:HTMLElement; private _focusTracker: CodeEditorWidgetFocusTracker; @@ -121,7 +150,7 @@ export class CodeEditorWidget extends CommonCodeEditor implements editorBrowser. return this._view.domNode; } - public getCenteredRangeInViewport(): editorCommon.IEditorRange { + public getCenteredRangeInViewport(): Range { if (!this.hasView) { return null; } @@ -584,7 +613,7 @@ export enum EditCursorState { class SingleEditOperation { - range: editorCommon.IEditorRange; + range: Range; text: string; forceMoveMarkers: boolean; @@ -636,7 +665,7 @@ export class CommandRunner implements editorCommon.ICommand { } } - public computeCursorState(model: editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): editorCommon.IEditorSelection { + public computeCursorState(model: editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): Selection { var inverseEditOperations = helper.getInverseEditOperations(); var srcRange = inverseEditOperations[inverseEditOperations.length - 1].range; return Selection.createSelection( diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index da70e56125c..d26df40e110 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -8,7 +8,7 @@ import 'vs/css!./media/diffEditor'; import {IAction} from 'vs/base/common/actions'; import {RunOnceScheduler} from 'vs/base/common/async'; -import {EventEmitter, IEmitterEvent} from 'vs/base/common/eventEmitter'; +import {EventEmitter, EmitterEvent} from 'vs/base/common/eventEmitter'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import * as objects from 'vs/base/common/objects'; import * as dom from 'vs/base/browser/dom'; @@ -25,15 +25,12 @@ import * as editorBrowser from 'vs/editor/browser/editorBrowser'; import {CodeEditorWidget} from 'vs/editor/browser/widget/codeEditorWidget'; import {ViewLineToken, ViewLineTokens} from 'vs/editor/common/core/viewLineToken'; import {Configuration} from 'vs/editor/browser/config/configuration'; - -interface IEditorScrollEvent { - scrollLeft: number; - scrollTop: number; -} +import {Position} from 'vs/editor/common/core/position'; +import {Selection} from 'vs/editor/common/core/selection'; interface IEditorDiffDecorations { decorations:editorCommon.IModelDeltaDecoration[]; - overviewZones:editorBrowser.OverviewRulerZone[]; + overviewZones:editorCommon.OverviewRulerZone[]; } interface IEditorDiffDecorationsWithZones extends IEditorDiffDecorations { @@ -129,6 +126,34 @@ var DIFF_EDITOR_ID = 0; export class DiffEditorWidget extends EventEmitter implements editorBrowser.IDiffEditor { + public onDidChangeModelRawContent(listener: (e:editorCommon.IModelContentChangedEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.ModelRawContentChanged, listener); + } + public onDidChangeModelContent(listener: (e:editorCommon.IModelContentChangedEvent2)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.ModelContentChanged2, listener); + } + public onDidChangeModelMode(listener: (e:editorCommon.IModelModeChangedEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.ModelModeChanged, listener); + } + public onDidChangeModelOptions(listener: (e:editorCommon.IModelOptionsChangedEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.ModelOptionsChanged, listener); + } + public onDidChangeConfiguration(listener: (e:editorCommon.IConfigurationChangedEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.ConfigurationChanged, listener); + } + public onDidChangeCursorPosition(listener: (e:editorCommon.ICursorPositionChangedEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.CursorPositionChanged, listener); + } + public onDidChangeCursorSelection(listener: (e:editorCommon.ICursorSelectionChangedEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.CursorSelectionChanged, listener); + } + public onDidDispose(listener: ()=>void): IDisposable { + return this.addListener2(editorCommon.EventType.Disposed, listener); + } + public onDidUpdateDiff(listener: ()=>void): IDisposable { + return this.addListener2(editorCommon.EventType.DiffUpdated, listener); + } + private static ONE_OVERVIEW_WIDTH = 15; public static ENTIRE_DIFF_OVERVIEW_WIDTH = 30; private static UPDATE_DIFF_DECORATIONS_DELAY = 200; // ms @@ -327,13 +352,13 @@ export class DiffEditorWidget extends EventEmitter implements editorBrowser.IDif private _createLeftHandSideEditor(options:editorCommon.IDiffEditorOptions, instantiationService:IInstantiationService): void { this.originalEditor = instantiationService.createInstance(CodeEditorWidget, this._originalDomNode, this._adjustOptionsForLeftHandSide(options, this._originalIsEditable)); this._toDispose.push(this.originalEditor.addBulkListener2((events: any) => this._onOriginalEditorEvents(events))); - this._toDispose.push(this.addEmitter2(this.originalEditor, 'leftHandSide')); + this._toDispose.push(this.addEmitter2(this.originalEditor)); } private _createRightHandSideEditor(options:editorCommon.IDiffEditorOptions, instantiationService:IInstantiationService): void { this.modifiedEditor = instantiationService.createInstance(CodeEditorWidget, this._modifiedDomNode, this._adjustOptionsForRightHandSide(options)); this._toDispose.push(this.modifiedEditor.addBulkListener2((events: any) => this._onModifiedEditorEvents(events))); - this._toDispose.push(this.addEmitter2(this.modifiedEditor, 'rightHandSide')); + this._toDispose.push(this.addEmitter2(this.modifiedEditor)); } public destroy(): void { @@ -355,6 +380,8 @@ export class DiffEditorWidget extends EventEmitter implements editorBrowser.IDif this._strategy.dispose(); + this.emit(editorCommon.EventType.Disposed); + super.dispose(); } @@ -481,7 +508,7 @@ export class DiffEditorWidget extends EventEmitter implements editorBrowser.IDif return this.modifiedEditor.getVisibleColumnFromPosition(position); } - public getPosition(): editorCommon.IEditorPosition { + public getPosition(): Position { return this.modifiedEditor.getPosition(); } @@ -513,18 +540,18 @@ export class DiffEditorWidget extends EventEmitter implements editorBrowser.IDif this.modifiedEditor.revealPositionInCenterIfOutsideViewport(position); } - public getSelection(): editorCommon.IEditorSelection { + public getSelection(): Selection { return this.modifiedEditor.getSelection(); } - public getSelections(): editorCommon.IEditorSelection[] { + public getSelections(): Selection[] { return this.modifiedEditor.getSelections(); } public setSelection(range:editorCommon.IRange, reveal?:boolean, revealVerticalInCenter?:boolean, revealHorizontal?:boolean): void; - public setSelection(editorRange:editorCommon.IEditorRange, reveal?:boolean, revealVerticalInCenter?:boolean, revealHorizontal?:boolean): void; + public setSelection(editorRange:Range, reveal?:boolean, revealVerticalInCenter?:boolean, revealHorizontal?:boolean): void; public setSelection(selection:editorCommon.ISelection, reveal?:boolean, revealVerticalInCenter?:boolean, revealHorizontal?:boolean): void; - public setSelection(editorSelection:editorCommon.IEditorSelection, reveal?:boolean, revealVerticalInCenter?:boolean, revealHorizontal?:boolean): void; + public setSelection(editorSelection:Selection, reveal?:boolean, revealVerticalInCenter?:boolean, revealHorizontal?:boolean): void; public setSelection(something:any, reveal?:boolean, revealVerticalInCenter?:boolean, revealHorizontal?:boolean): void { this.modifiedEditor.setSelection(something, reveal, revealVerticalInCenter, revealHorizontal); } @@ -670,11 +697,11 @@ export class DiffEditorWidget extends EventEmitter implements editorBrowser.IDif //------------ end layouting methods - private _recomputeIfNecessary(events:IEmitterEvent[]): void { + private _recomputeIfNecessary(events:EmitterEvent[]): void { var changed = false; for (var i = 0; !changed && i < events.length; i++) { var type = events[i].getType(); - changed = changed || type === 'change' || type === editorCommon.EventType.ModelModeChanged; + changed = changed || type === editorCommon.EventType.ModelRawContentChanged || type === editorCommon.EventType.ModelModeChanged; } if (changed && this._isVisible) { // Clear previous timeout if necessary @@ -686,7 +713,7 @@ export class DiffEditorWidget extends EventEmitter implements editorBrowser.IDif } } - private _onOriginalEditorEvents(events:IEmitterEvent[]): void { + private _onOriginalEditorEvents(events:EmitterEvent[]): void { for (var i = 0; i < events.length; i++) { if (events[i].getType() === 'scroll') { this._onOriginalEditorScroll(events[i].getData()); @@ -698,15 +725,12 @@ export class DiffEditorWidget extends EventEmitter implements editorBrowser.IDif this._recomputeIfNecessary(events); } - private _onModifiedEditorEvents(events:IEmitterEvent[]): void { + private _onModifiedEditorEvents(events:EmitterEvent[]): void { for (var i = 0; i < events.length; i++) { if (events[i].getType() === 'scroll') { this._onModifiedEditorScroll(events[i].getData()); this._layoutOverviewViewport(); } - if (events[i].getType() === 'scrollSize') { - this._layoutOverviewViewport(); - } if (events[i].getType() === 'viewLayoutChanged') { this._layoutOverviewViewport(); } @@ -739,7 +763,7 @@ export class DiffEditorWidget extends EventEmitter implements editorBrowser.IDif var currentOriginalModel = this.originalEditor.getModel(); var currentModifiedModel = this.modifiedEditor.getModel(); - this._editorWorkerService.computeDiff(currentOriginalModel.getAssociatedResource(), currentModifiedModel.getAssociatedResource(), this._ignoreTrimWhitespace).then((result) => { + this._editorWorkerService.computeDiff(currentOriginalModel.uri, currentModifiedModel.uri, this._ignoreTrimWhitespace).then((result) => { if (currentToken === this._diffComputationToken && currentOriginalModel === this.originalEditor.getModel() && currentModifiedModel === this.modifiedEditor.getModel() @@ -747,7 +771,7 @@ export class DiffEditorWidget extends EventEmitter implements editorBrowser.IDif { this._lineChanges = result; this._updateDecorationsRunner.schedule(); - this.emit(editorCommon.EventType.DiffUpdated, { editor: this, lineChanges: result }); + this.emit(editorCommon.EventType.DiffUpdated, { }); } }, (error) => { if (currentToken === this._diffComputationToken @@ -810,7 +834,10 @@ export class DiffEditorWidget extends EventEmitter implements editorBrowser.IDif return result; } - private _onOriginalEditorScroll(e:IEditorScrollEvent): void { + private _onOriginalEditorScroll(e:editorCommon.IScrollEvent): void { + if (!e.scrollTopChanged && !e.scrollLeftChanged) { + return; + } if (this._isHandlingScrollEvent) { return; } @@ -822,7 +849,10 @@ export class DiffEditorWidget extends EventEmitter implements editorBrowser.IDif this._isHandlingScrollEvent = false; } - private _onModifiedEditorScroll(e:IEditorScrollEvent): void { + private _onModifiedEditorScroll(e:editorCommon.IScrollEvent): void { + if (!e.scrollTopChanged && !e.scrollLeftChanged) { + return; + } if(this._isHandlingScrollEvent) { return; } @@ -1329,10 +1359,10 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd this._sash.disable(); } - this._sash.on('start', () => this.onSashDragStart()); - this._sash.on('change', (e: ISashEvent) => this.onSashDrag(e)); - this._sash.on('end', () => this.onSashDragEnd()); - this._sash.on('reset', () => this.onSashReset()); + this._sash.addListener2('start', () => this.onSashDragStart()); + this._sash.addListener2('change', (e: ISashEvent) => this.onSashDrag(e)); + this._sash.addListener2('end', () => this.onSashDragEnd()); + this._sash.addListener2('reset', () => this.onSashReset()); } public dispose(): void { @@ -1449,7 +1479,7 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd result.decorations.push(createDecoration(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Number.MAX_VALUE, 'char-delete', true)); } - result.overviewZones.push(new editorBrowser.OverviewRulerZone( + result.overviewZones.push(new editorCommon.OverviewRulerZone( lineChange.originalStartLineNumber, lineChange.originalEndLineNumber, editorCommon.OverviewRulerLane.Full, @@ -1514,7 +1544,7 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd if (!isChangeOrDelete(lineChange) || !lineChange.charChanges) { result.decorations.push(createDecoration(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Number.MAX_VALUE, 'char-insert', true)); } - result.overviewZones.push(new editorBrowser.OverviewRulerZone( + result.overviewZones.push(new editorCommon.OverviewRulerZone( lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber, editorCommon.OverviewRulerLane.Full, @@ -1594,7 +1624,7 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor this.decorationsLeft = dataSource.getOriginalEditor().getLayoutInfo().decorationsLeft; this.toDispose = []; - this.toDispose.push(dataSource.getOriginalEditor().addListener2(editorCommon.EventType.EditorLayout, (layoutInfo:editorCommon.EditorLayoutInfo) => { + this.toDispose.push(dataSource.getOriginalEditor().onDidLayoutChange((layoutInfo:editorCommon.EditorLayoutInfo) => { if (this.decorationsLeft !== layoutInfo.decorationsLeft) { this.decorationsLeft = layoutInfo.decorationsLeft; dataSource.relayoutEditors(); @@ -1629,7 +1659,7 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor // Add overview zones in the overview ruler if (isChangeOrDelete(lineChange)) { - result.overviewZones.push(new editorBrowser.OverviewRulerZone( + result.overviewZones.push(new editorCommon.OverviewRulerZone( lineChange.originalStartLineNumber, lineChange.originalEndLineNumber, editorCommon.OverviewRulerLane.Full, @@ -1667,7 +1697,7 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor if (isChangeOrInsert(lineChange)) { result.decorations.push(createDecoration(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Number.MAX_VALUE, 'line-insert', true)); - result.overviewZones.push(new editorBrowser.OverviewRulerZone( + result.overviewZones.push(new editorCommon.OverviewRulerZone( lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber, editorCommon.OverviewRulerLane.Full, diff --git a/src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts b/src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts index b1fe0a1564a..324d4b6185a 100644 --- a/src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts +++ b/src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts @@ -8,7 +8,7 @@ import * as objects from 'vs/base/common/objects'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; -import {EventType, ICodeEditorWidgetCreationOptions, IConfigurationChangedEvent, IEditorOptions} from 'vs/editor/common/editorCommon'; +import {ICodeEditorWidgetCreationOptions, IConfigurationChangedEvent, IEditorOptions} from 'vs/editor/common/editorCommon'; import {ICodeEditorService} from 'vs/editor/common/services/codeEditorService'; import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; import {CodeEditorWidget} from 'vs/editor/browser/widget/codeEditorWidget'; @@ -35,7 +35,7 @@ export class EmbeddedCodeEditorWidget extends CodeEditorWidget { // Overwrite parent's options super.updateOptions(this._overwriteOptions); - this._lifetimeDispose.push(parentEditor.addListener2(EventType.ConfigurationChanged, (e:IConfigurationChangedEvent) => this._onParentConfigurationChanged(e))); + this._lifetimeDispose.push(parentEditor.onDidChangeConfiguration((e:IConfigurationChangedEvent) => this._onParentConfigurationChanged(e))); } public getParentEditor(): ICodeEditor { diff --git a/src/vs/editor/buildfile.js b/src/vs/editor/buildfile.js index c7668af3a4b..ba5cd338ddf 100644 --- a/src/vs/editor/buildfile.js +++ b/src/vs/editor/buildfile.js @@ -9,9 +9,9 @@ exports.collectModules = function() { return [{ name: 'vs/editor/common/worker/editorWorkerServer', include: [ 'vs/base/common/severity' ], - exclude: [ 'vs/base/common/worker/workerServer', 'vs/css', 'vs/nls', 'vs/text' ] + exclude: [ 'vs/base/common/worker/workerServer', 'vs/css', 'vs/nls' ] }, { name: 'vs/editor/common/services/editorSimpleWorker', - exclude: [ 'vs/base/common/worker/simpleWorker', 'vs/css', 'vs/nls', 'vs/text' ] + exclude: [ 'vs/base/common/worker/simpleWorker', 'vs/css', 'vs/nls' ] }]; }; diff --git a/src/vs/editor/common/commands/replaceCommand.ts b/src/vs/editor/common/commands/replaceCommand.ts index e0d80db818f..1d69beb6cb2 100644 --- a/src/vs/editor/common/commands/replaceCommand.ts +++ b/src/vs/editor/common/commands/replaceCommand.ts @@ -6,13 +6,14 @@ import {Selection} from 'vs/editor/common/core/selection'; import * as editorCommon from 'vs/editor/common/editorCommon'; +import {Range} from 'vs/editor/common/core/range'; export class ReplaceCommand implements editorCommon.ICommand { - private _range: editorCommon.IEditorRange; + private _range: Range; private _text: string; - constructor(range: editorCommon.IEditorRange, text: string) { + constructor(range: Range, text: string) { this._range = range; this._text = text; } @@ -21,11 +22,11 @@ export class ReplaceCommand implements editorCommon.ICommand { return this._text; } - public getRange():editorCommon.IEditorRange { + public getRange():Range { return this._range; } - public setRange(newRange:editorCommon.IEditorRange): void { + public setRange(newRange:Range): void { this._range = newRange; } @@ -33,7 +34,7 @@ export class ReplaceCommand implements editorCommon.ICommand { builder.addEditOperation(this._range, this._text); } - public computeCursorState(model: editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): editorCommon.IEditorSelection { + public computeCursorState(model: editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): Selection { var inverseEditOperations = helper.getInverseEditOperations(); var srcRange = inverseEditOperations[0].range; return new Selection( @@ -47,11 +48,11 @@ export class ReplaceCommand implements editorCommon.ICommand { export class ReplaceCommandWithoutChangingPosition extends ReplaceCommand { - constructor(range: editorCommon.IEditorRange, text: string) { + constructor(range: Range, text: string) { super(range, text); } - public computeCursorState(model: editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): editorCommon.IEditorSelection { + public computeCursorState(model: editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): Selection { var inverseEditOperations = helper.getInverseEditOperations(); var srcRange = inverseEditOperations[0].range; return new Selection( @@ -68,13 +69,13 @@ export class ReplaceCommandWithOffsetCursorState extends ReplaceCommand { private _columnDeltaOffset: number; private _lineNumberDeltaOffset: number; - constructor(range: editorCommon.IEditorRange, text: string, lineNumberDeltaOffset: number, columnDeltaOffset: number) { + constructor(range: Range, text: string, lineNumberDeltaOffset: number, columnDeltaOffset: number) { super(range, text); this._columnDeltaOffset = columnDeltaOffset; this._lineNumberDeltaOffset = lineNumberDeltaOffset; } - public computeCursorState(model: editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): editorCommon.IEditorSelection { + public computeCursorState(model: editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): Selection { var inverseEditOperations = helper.getInverseEditOperations(); var srcRange = inverseEditOperations[0].range; return new Selection( @@ -88,10 +89,10 @@ export class ReplaceCommandWithOffsetCursorState extends ReplaceCommand { export class ReplaceCommandThatPreservesSelection extends ReplaceCommand { - private _initialSelection: editorCommon.IEditorSelection; + private _initialSelection: Selection; private _selectionId: string; - constructor(editRange: editorCommon.IEditorRange, text: string, initialSelection: editorCommon.IEditorSelection) { + constructor(editRange: Range, text: string, initialSelection: Selection) { super(editRange, text); this._initialSelection = initialSelection; } @@ -102,7 +103,7 @@ export class ReplaceCommandThatPreservesSelection extends ReplaceCommand { this._selectionId = builder.trackSelection(this._initialSelection); } - public computeCursorState(model: editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): editorCommon.IEditorSelection { + public computeCursorState(model: editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): Selection { return helper.getTrackedSelection(this._selectionId); } } diff --git a/src/vs/editor/common/commands/shiftCommand.ts b/src/vs/editor/common/commands/shiftCommand.ts index 7776173f607..7d5bdbcab7a 100644 --- a/src/vs/editor/common/commands/shiftCommand.ts +++ b/src/vs/editor/common/commands/shiftCommand.ts @@ -8,7 +8,7 @@ import * as strings from 'vs/base/common/strings'; import {CursorMoveHelper} from 'vs/editor/common/controller/cursorMoveHelper'; import {Range} from 'vs/editor/common/core/range'; import {Selection} from 'vs/editor/common/core/selection'; -import {ICommand, ICursorStateComputerData, IEditOperationBuilder, IEditorSelection, ITokenizedModel} from 'vs/editor/common/editorCommon'; +import {ICommand, ICursorStateComputerData, IEditOperationBuilder, ITokenizedModel} from 'vs/editor/common/editorCommon'; import {getRawEnterActionAtPosition} from 'vs/editor/common/modes/supports/onEnter'; export interface IShiftCommandOpts { @@ -40,11 +40,11 @@ export class ShiftCommand implements ICommand { } private _opts: IShiftCommandOpts; - private _selection: IEditorSelection; + private _selection: Selection; private _selectionId: string; private _useLastEditRangeForCursorEndPosition: boolean; - constructor(range: IEditorSelection, opts:IShiftCommandOpts) { + constructor(range: Selection, opts:IShiftCommandOpts) { this._opts = opts; this._selection = range; this._useLastEditRangeForCursorEndPosition = false; @@ -152,7 +152,7 @@ export class ShiftCommand implements ICommand { this._selectionId = builder.trackSelection(this._selection); } - public computeCursorState(model: ITokenizedModel, helper: ICursorStateComputerData): IEditorSelection { + public computeCursorState(model: ITokenizedModel, helper: ICursorStateComputerData): Selection { if (this._useLastEditRangeForCursorEndPosition) { var lastOp = helper.getInverseEditOperations()[0]; return new Selection(lastOp.range.endLineNumber, lastOp.range.endColumn, lastOp.range.endLineNumber, lastOp.range.endColumn); diff --git a/src/vs/editor/common/commands/surroundSelectionCommand.ts b/src/vs/editor/common/commands/surroundSelectionCommand.ts index f42e71142a2..91a5a18a625 100644 --- a/src/vs/editor/common/commands/surroundSelectionCommand.ts +++ b/src/vs/editor/common/commands/surroundSelectionCommand.ts @@ -6,14 +6,14 @@ import {Range} from 'vs/editor/common/core/range'; import {Selection} from 'vs/editor/common/core/selection'; -import {ICommand, ICursorStateComputerData, IEditOperationBuilder, IEditorSelection, ITokenizedModel} from 'vs/editor/common/editorCommon'; +import {ICommand, ICursorStateComputerData, IEditOperationBuilder, ITokenizedModel} from 'vs/editor/common/editorCommon'; export class SurroundSelectionCommand implements ICommand { - private _range: IEditorSelection; + private _range: Selection; private _charBeforeSelection: string; private _charAfterSelection: string; - constructor(range:IEditorSelection, charBeforeSelection:string, charAfterSelection:string) { + constructor(range:Selection, charBeforeSelection:string, charAfterSelection:string) { this._range = range; this._charBeforeSelection = charBeforeSelection; this._charAfterSelection = charAfterSelection; @@ -35,7 +35,7 @@ export class SurroundSelectionCommand implements ICommand { ), this._charAfterSelection); } - public computeCursorState(model: ITokenizedModel, helper: ICursorStateComputerData): IEditorSelection { + public computeCursorState(model: ITokenizedModel, helper: ICursorStateComputerData): Selection { var inverseEditOperations = helper.getInverseEditOperations(); var firstOperationRange = inverseEditOperations[0].range; var secondOperationRange = inverseEditOperations[1].range; diff --git a/src/vs/editor/common/commands/trimTrailingWhitespaceCommand.ts b/src/vs/editor/common/commands/trimTrailingWhitespaceCommand.ts index 101ba6f1f47..c7c685c088c 100644 --- a/src/vs/editor/common/commands/trimTrailingWhitespaceCommand.ts +++ b/src/vs/editor/common/commands/trimTrailingWhitespaceCommand.ts @@ -8,13 +8,14 @@ import * as strings from 'vs/base/common/strings'; import {EditOperation} from 'vs/editor/common/core/editOperation'; import {Range} from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; +import {Selection} from 'vs/editor/common/core/selection'; export class TrimTrailingWhitespaceCommand implements editorCommon.ICommand { - private selection:editorCommon.IEditorSelection; + private selection:Selection; private selectionId:string; - constructor(selection:editorCommon.IEditorSelection) { + constructor(selection:Selection) { this.selection = selection; } @@ -29,7 +30,7 @@ export class TrimTrailingWhitespaceCommand implements editorCommon.ICommand { this.selectionId = builder.trackSelection(this.selection); } - public computeCursorState(model:editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData):editorCommon.IEditorSelection { + public computeCursorState(model:editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData):Selection { return helper.getTrackedSelection(this.selectionId); } } diff --git a/src/vs/editor/common/commonCodeEditor.ts b/src/vs/editor/common/commonCodeEditor.ts index 418d762984d..46fc9ffb398 100644 --- a/src/vs/editor/common/commonCodeEditor.ts +++ b/src/vs/editor/common/commonCodeEditor.ts @@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; import {IAction, IActionProvider, isAction} from 'vs/base/common/actions'; import {onUnexpectedError} from 'vs/base/common/errors'; -import {EventEmitter, IEventEmitter, ListenerUnbind} from 'vs/base/common/eventEmitter'; +import {EventEmitter, IEventEmitter} from 'vs/base/common/eventEmitter'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import * as objects from 'vs/base/common/objects'; import * as timer from 'vs/base/common/timer'; @@ -36,6 +36,52 @@ var EDITOR_ID = 0; export abstract class CommonCodeEditor extends EventEmitter implements IActionProvider, editorCommon.ICommonCodeEditor { + public onDidChangeModelRawContent(listener: (e:editorCommon.IModelContentChangedEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.ModelRawContentChanged, listener); + } + public onDidChangeModelContent(listener: (e:editorCommon.IModelContentChangedEvent2)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.ModelContentChanged2, listener); + } + public onDidChangeModelMode(listener: (e:editorCommon.IModelModeChangedEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.ModelModeChanged, listener); + } + public onDidChangeModelOptions(listener: (e:editorCommon.IModelOptionsChangedEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.ModelOptionsChanged, listener); + } + public onDidChangeModelModeSupport(listener: (e:editorCommon.IModeSupportChangedEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.ModelModeSupportChanged, listener); + } + public onDidChangeModelDecorations(listener: (e:editorCommon.IModelDecorationsChangedEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.ModelDecorationsChanged, listener); + } + public onDidChangeConfiguration(listener: (e:editorCommon.IConfigurationChangedEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.ConfigurationChanged, listener); + } + public onDidChangeModel(listener: (e:editorCommon.IModelChangedEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.ModelChanged, listener); + } + public onDidChangeCursorPosition(listener: (e:editorCommon.ICursorPositionChangedEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.CursorPositionChanged, listener); + } + public onDidChangeCursorSelection(listener: (e:editorCommon.ICursorSelectionChangedEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.CursorSelectionChanged, listener); + } + public onDidFocusEditorText(listener: ()=>void): IDisposable { + return this.addListener2(editorCommon.EventType.EditorTextFocus, listener); + } + public onDidBlurEditorText(listener: ()=>void): IDisposable { + return this.addListener2(editorCommon.EventType.EditorTextBlur, listener); + } + public onDidFocusEditor(listener: ()=>void): IDisposable { + return this.addListener2(editorCommon.EventType.EditorFocus, listener); + } + public onDidBlurEditor(listener: ()=>void): IDisposable { + return this.addListener2(editorCommon.EventType.EditorBlur, listener); + } + public onDidDispose(listener: ()=>void): IDisposable { + return this.addListener2(editorCommon.EventType.Disposed, listener); + } + protected domElement: IKeybindingScopeLocation; protected id:number; @@ -49,7 +95,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr // --- Members logically associated to a model protected model:editorCommon.IModel; - protected listenersToRemove:ListenerUnbind[]; + protected listenersToRemove:IDisposable[]; protected hasView: boolean; protected viewModel:ViewModel; @@ -153,7 +199,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr this._postDetachModelCleanup(this._detachModel()); this._configuration.dispose(); this._keybindingService.dispose(); - this.emit(editorCommon.EventType.Disposed, {}); + this.emit(editorCommon.EventType.Disposed); super.dispose(); } @@ -228,10 +274,10 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr var newModelUrl: string = null; if (detachedModel) { - oldModelUrl = detachedModel.getAssociatedResource().toString(); + oldModelUrl = detachedModel.uri.toString(); } if (model) { - newModelUrl = model.getAssociatedResource().toString(); + newModelUrl = model.uri.toString(); } var e: editorCommon.IModelChangedEvent = { oldModelUrl: oldModelUrl, @@ -244,7 +290,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr this._postDetachModelCleanup(detachedModel); } - public abstract getCenteredRangeInViewport(): editorCommon.IEditorRange; + public abstract getCenteredRangeInViewport(): Range; public getVisibleColumnFromPosition(rawPosition:editorCommon.IPosition): number { if (!this.model) { @@ -257,7 +303,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr return CursorMoveHelper.visibleColumnFromColumn(this.model, position.lineNumber, position.column, tabSize) + 1; } - public getPosition(): editorCommon.IEditorPosition { + public getPosition(): Position { if (!this.cursor) { return null; } @@ -363,19 +409,19 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr }, editorCommon.VerticalRevealType.CenterIfOutsideViewport, true); } - public getSelection(): editorCommon.IEditorSelection { + public getSelection(): Selection { if (!this.cursor) { return null; } return this.cursor.getSelection().clone(); } - public getSelections(): editorCommon.IEditorSelection[] { + public getSelections(): Selection[] { if (!this.cursor) { return null; } var selections = this.cursor.getSelections(); - var result:editorCommon.IEditorSelection[] = []; + var result:Selection[] = []; for (var i = 0, len = selections.length; i < len; i++) { result[i] = selections[i].clone(); } @@ -383,9 +429,9 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr } public setSelection(range:editorCommon.IRange, reveal?:boolean, revealVerticalInCenter?:boolean, revealHorizontal?:boolean): void; - public setSelection(editorRange:editorCommon.IEditorRange, reveal?:boolean, revealVerticalInCenter?:boolean, revealHorizontal?:boolean): void; + public setSelection(editorRange:Range, reveal?:boolean, revealVerticalInCenter?:boolean, revealHorizontal?:boolean): void; public setSelection(selection:editorCommon.ISelection, reveal?:boolean, revealVerticalInCenter?:boolean, revealHorizontal?:boolean): void; - public setSelection(editorSelection:editorCommon.IEditorSelection, reveal?:boolean, revealVerticalInCenter?:boolean, revealHorizontal?:boolean): void; + public setSelection(editorSelection:Selection, reveal?:boolean, revealVerticalInCenter?:boolean, revealHorizontal?:boolean): void; public setSelection(something:any, reveal:boolean = false, revealVerticalInCenter:boolean = false, revealHorizontal:boolean = false): void { var isSelection = Selection.isISelection(something); var isRange = Range.isIRange(something); @@ -642,16 +688,20 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr } } - public addTypingListener(character:string, callback: () => void): ListenerUnbind { + public addTypingListener(character:string, callback: () => void): IDisposable { if (!this.cursor) { - return () => { - // no-op + return { + dispose: () => { + // no-op + } }; } this.cursor.addTypingListener(character, callback); - return () => { - if (this.cursor) { - this.cursor.removeTypingListener(character, callback); + return { + dispose: () => { + if (this.cursor) { + this.cursor.removeTypingListener(character, callback); + } } }; } @@ -701,7 +751,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr convertModelPositionToViewPosition: (lineNumber:number, column:number) => { return this.viewModel.convertModelPositionToViewPosition(lineNumber, column); }, - convertModelRangeToViewRange: (modelRange:editorCommon.IEditorRange) => { + convertModelRangeToViewRange: (modelRange:Range) => { return this.viewModel.convertModelRangeToViewRange(modelRange); }, convertViewToModelPosition: (lineNumber:number, column:number) => { @@ -710,10 +760,10 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr convertViewSelectionToModelSelection: (viewSelection:editorCommon.ISelection) => { return this.viewModel.convertViewSelectionToModelSelection(viewSelection); }, - validateViewPosition: (viewLineNumber:number, viewColumn:number, modelPosition:editorCommon.IEditorPosition) => { + validateViewPosition: (viewLineNumber:number, viewColumn:number, modelPosition:Position) => { return this.viewModel.validateViewPosition(viewLineNumber, viewColumn, modelPosition); }, - validateViewRange: (viewStartLineNumber:number, viewStartColumn:number, viewEndLineNumber:number, viewEndColumn:number, modelRange:editorCommon.IEditorRange) => { + validateViewRange: (viewStartLineNumber:number, viewStartColumn:number, viewEndLineNumber:number, viewEndColumn:number, modelRange:Range) => { return this.viewModel.validateViewRange(viewStartLineNumber, viewStartColumn, viewEndLineNumber, viewEndColumn, modelRange); } }; @@ -730,7 +780,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr this._createView(); - this.listenersToRemove.push(this._getViewInternalEventBus().addBulkListener((events) => { + this.listenersToRemove.push(this._getViewInternalEventBus().addBulkListener2((events) => { for (var i = 0, len = events.length; i < len; i++) { var eventType = events[i].getType(); var e = events[i].getData(); @@ -746,10 +796,6 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr this.emit('scroll', e); break; - case 'scrollSize': - this.emit('scrollSize', e); - break; - case editorCommon.EventType.ViewFocusLost: this.emit(editorCommon.EventType.EditorTextBlur); break; @@ -812,10 +858,8 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr this.emit(editorCommon.EventType.ModelModeSupportChanged, e); break; - case editorCommon.EventType.ModelContentChanged: - // TODO@Alex - this.emit(editorCommon.EventType.ModelContentChanged, e); - this.emit('change', {}); + case editorCommon.EventType.ModelRawContentChanged: + this.emit(editorCommon.EventType.ModelRawContentChanged, e); break; case editorCommon.EventType.ModelOptionsChanged: @@ -838,7 +882,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr return allSelections.some(s => !s.isEmpty()); }; - this.listenersToRemove.push(this.cursor.addBulkListener((events) => { + this.listenersToRemove.push(this.cursor.addBulkListener2((events) => { var updateHasMultipleCursors = false, hasMultipleCursors = false, updateHasNonEmptySelection = false, @@ -910,10 +954,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr this.hasView = false; - this.listenersToRemove.forEach((element) => { - element(); - }); - this.listenersToRemove = []; + this.listenersToRemove = dispose(this.listenersToRemove); if (this.cursor) { this.cursor.dispose(); diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index 3022cdf5049..28bf7d6f603 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -672,10 +672,10 @@ let editorConfiguration:IConfigurationNode = { 'default': DEFAULT_TRIM_AUTO_WHITESPACE, 'description': nls.localize('trimAutoWhitespace', "Remove trailing auto inserted whitespace") }, - 'editor.dismissPeekOnEsc' : { + 'editor.stablePeek' : { 'type': 'boolean', - 'default': true, - 'description': nls.localize('dismissPeekOnEsc', "Close peek editor when pressing ESC") + 'default': false, + 'description': nls.localize('stablePeek', "Keep peek editors open even when double clicking their content or when hitting Escape.") }, 'diffEditor.renderSideBySide' : { 'type': 'boolean', diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index 6c6d1f22228..be45e38ff64 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -107,19 +107,19 @@ export class Cursor extends EventEmitter { convertModelPositionToViewPosition: (lineNumber:number, column:number) => { return new Position(lineNumber, column); }, - convertModelRangeToViewRange: (modelRange: editorCommon.IEditorRange) => { + convertModelRangeToViewRange: (modelRange: Range) => { return modelRange; }, convertViewToModelPosition: (lineNumber:number, column:number) => { return new Position(lineNumber, column); }, - convertViewSelectionToModelSelection: (viewSelection:editorCommon.IEditorSelection) => { + convertViewSelectionToModelSelection: (viewSelection:Selection) => { return viewSelection; }, - validateViewPosition: (viewLineNumber:number, viewColumn:number, modelPosition:editorCommon.IEditorPosition) => { + validateViewPosition: (viewLineNumber:number, viewColumn:number, modelPosition:Position) => { return modelPosition; }, - validateViewRange: (viewStartLineNumber:number, viewStartColumn:number, viewEndLineNumber:number, viewEndColumn:number, modelRange:editorCommon.IEditorRange) => { + validateViewRange: (viewStartLineNumber:number, viewStartColumn:number, viewEndLineNumber:number, viewEndColumn:number, modelRange:Range) => { return modelRange; } @@ -134,13 +134,13 @@ export class Cursor extends EventEmitter { this._isHandling = false; this.modelUnbinds = []; - this.modelUnbinds.push(this.model.addListener2(editorCommon.EventType.ModelContentChanged, (e:editorCommon.IModelContentChangedEvent) => { + this.modelUnbinds.push(this.model.onDidChangeRawContent((e) => { this._onModelContentChanged(e); })); - this.modelUnbinds.push(this.model.addListener2(editorCommon.EventType.ModelModeChanged, (e:editorCommon.IModelModeChangedEvent) => { + this.modelUnbinds.push(this.model.onDidChangeMode((e) => { this._onModelModeChanged(); })); - this.modelUnbinds.push(this.model.addListener2(editorCommon.EventType.ModelModeSupportChanged, (e: editorCommon.IModeSupportChangedEvent) => { + this.modelUnbinds.push(this.model.onDidChangeModeSupport((e) => { // TODO@Alex: react only if certain supports changed? this._onModelModeChanged(); })); @@ -163,7 +163,7 @@ export class Cursor extends EventEmitter { var selections = this.cursors.getSelections(), result:editorCommon.ICursorState[] = [], - selection: editorCommon.IEditorSelection; + selection: Selection; for (var i = 0; i < selections.length; i++) { selection = selections[i]; @@ -230,7 +230,7 @@ export class Cursor extends EventEmitter { this.model.setEditableRange(range); } - public getEditableRange(): editorCommon.IEditorRange { + public getEditableRange(): Range { return this.model.getEditableRange(); } @@ -259,7 +259,7 @@ export class Cursor extends EventEmitter { } private _onModelContentChanged(e:editorCommon.IModelContentChangedEvent): void { - if (e.changeType === editorCommon.EventType.ModelContentChangedFlush) { + if (e.changeType === editorCommon.EventType.ModelRawContentChangedFlush) { // a model.setValue() was called this.cursors.dispose(); @@ -281,15 +281,15 @@ export class Cursor extends EventEmitter { // ------ some getters/setters - public getSelection(): editorCommon.IEditorSelection { + public getSelection(): Selection { return this.cursors.getSelection(0); } - public getSelections(): editorCommon.IEditorSelection[] { + public getSelections(): Selection[] { return this.cursors.getSelections(); } - public getPosition(): editorCommon.IEditorPosition { + public getPosition(): Position { return this.cursors.getPosition(0); } @@ -473,7 +473,7 @@ export class Cursor extends EventEmitter { } } - private _interpretCommandResult(cursorState:editorCommon.IEditorSelection[]): boolean { + private _interpretCommandResult(cursorState:Selection[]): boolean { if (!cursorState) { return false; } @@ -488,7 +488,7 @@ export class Cursor extends EventEmitter { var operations: editorCommon.IIdentifiedSingleEditOperation[] = [], operationMinor = 0; - var addEditOperation = (selection:editorCommon.IEditorRange, text:string) => { + var addEditOperation = (selection:Range, text:string) => { if (selection.isEmpty() && text === '') { // This command wants to add a no-op => no thank you return; @@ -506,7 +506,7 @@ export class Cursor extends EventEmitter { }; var hadTrackedRange = false; - var trackSelection = (selection: editorCommon.IEditorSelection, trackPreviousOnEmpty?:boolean ) => { + var trackSelection = (selection: Selection, trackPreviousOnEmpty?:boolean ) => { var selectionMarkerStickToPreviousCharacter:boolean, positionMarkerStickToPreviousCharacter:boolean; @@ -767,7 +767,7 @@ export class Cursor extends EventEmitter { } } - var selectionsAfter = this.model.pushEditOperations(selectionsBefore, filteredOperations, (inverseEditOperations:editorCommon.IIdentifiedSingleEditOperation[]): editorCommon.IEditorSelection[] => { + var selectionsAfter = this.model.pushEditOperations(selectionsBefore, filteredOperations, (inverseEditOperations:editorCommon.IIdentifiedSingleEditOperation[]): Selection[] => { var groupedInverseEditOperations:editorCommon.IIdentifiedSingleEditOperation[][] = []; for (var i = 0; i < selectionsBefore.length; i++) { groupedInverseEditOperations[i] = []; @@ -783,7 +783,7 @@ export class Cursor extends EventEmitter { var minorBasedSorter = (a:editorCommon.IIdentifiedSingleEditOperation, b:editorCommon.IIdentifiedSingleEditOperation) => { return a.identifier.minor - b.identifier.minor; }; - var cursorSelections: editorCommon.IEditorSelection[] = []; + var cursorSelections: Selection[] = []; for (var i = 0; i < selectionsBefore.length; i++) { if (groupedInverseEditOperations[i].length > 0 || commandsData.hadTrackedRanges[i]) { groupedInverseEditOperations[i].sort(minorBasedSorter); diff --git a/src/vs/editor/common/controller/cursorCollection.ts b/src/vs/editor/common/controller/cursorCollection.ts index af87c138ebf..395273ddfcf 100644 --- a/src/vs/editor/common/controller/cursorCollection.ts +++ b/src/vs/editor/common/controller/cursorCollection.ts @@ -7,8 +7,9 @@ import {onUnexpectedError} from 'vs/base/common/errors'; import {IModeConfiguration, IOneCursorState, IViewModelHelper, OneCursor} from 'vs/editor/common/controller/oneCursor'; import {Selection} from 'vs/editor/common/core/selection'; -import {IConfiguration, IEditorPosition, IEditorSelection, IModel, ISelection} from 'vs/editor/common/editorCommon'; +import {IConfiguration, IModel, ISelection} from 'vs/editor/common/editorCommon'; import {IAutoClosingPair} from 'vs/editor/common/modes'; +import {Position} from 'vs/editor/common/core/position'; export interface ICursorCollectionState { primary: IOneCursorState; @@ -78,7 +79,7 @@ export class CursorCollection { return result; } - public getPosition(index: number): IEditorPosition { + public getPosition(index: number): Position { if (index === 0) { return this.primaryCursor.getPosition(); } else { @@ -86,7 +87,7 @@ export class CursorCollection { } } - public getViewPosition(index: number): IEditorPosition { + public getViewPosition(index: number): Position { if (index === 0) { return this.primaryCursor.getViewPosition(); } else { @@ -94,8 +95,8 @@ export class CursorCollection { } } - public getPositions(): IEditorPosition[] { - var result: IEditorPosition[] = []; + public getPositions(): Position[] { + var result: Position[] = []; result.push(this.primaryCursor.getPosition()); for (var i = 0, len = this.secondaryCursors.length; i < len; i++) { result.push(this.secondaryCursors[i].getPosition()); @@ -103,8 +104,8 @@ export class CursorCollection { return result; } - public getViewPositions(): IEditorPosition[] { - var result: IEditorPosition[] = []; + public getViewPositions(): Position[] { + var result: Position[] = []; result.push(this.primaryCursor.getViewPosition()); for (var i = 0, len = this.secondaryCursors.length; i < len; i++) { result.push(this.secondaryCursors[i].getViewPosition()); @@ -112,7 +113,7 @@ export class CursorCollection { return result; } - public getSelection(index: number): IEditorSelection { + public getSelection(index: number): Selection { if (index === 0) { return this.primaryCursor.getSelection(); } else { @@ -120,8 +121,8 @@ export class CursorCollection { } } - public getSelections(): IEditorSelection[] { - var result: IEditorSelection[] = []; + public getSelections(): Selection[] { + var result: Selection[] = []; result.push(this.primaryCursor.getSelection()); for (var i = 0, len = this.secondaryCursors.length; i < len; i++) { result.push(this.secondaryCursors[i].getSelection()); @@ -129,8 +130,8 @@ export class CursorCollection { return result; } - public getViewSelections(): IEditorSelection[] { - var result: IEditorSelection[] = []; + public getViewSelections(): Selection[] { + var result: Selection[] = []; result.push(this.primaryCursor.getViewSelection()); for (var i = 0, len = this.secondaryCursors.length; i < len; i++) { result.push(this.secondaryCursors[i].getViewSelection()); @@ -239,8 +240,8 @@ export class CursorCollection { var cursors = this.getAll(); var sortedCursors:{ index: number; - selection: IEditorSelection; - viewSelection: IEditorSelection; + selection: Selection; + viewSelection: Selection; }[] = []; for (var i = 0; i < cursors.length; i++) { sortedCursors.push({ @@ -289,7 +290,7 @@ export class CursorCollection { resultingSelectionIsLTR = winnerSelectionIsLTR; } - var resultingSelection: IEditorSelection; + var resultingSelection: Selection; if (resultingSelectionIsLTR) { resultingSelection = new Selection(resultingRange.startLineNumber, resultingRange.startColumn, resultingRange.endLineNumber, resultingRange.endColumn); } else { diff --git a/src/vs/editor/common/controller/cursorMoveHelper.ts b/src/vs/editor/common/controller/cursorMoveHelper.ts index e0b3a35ff90..cd489bc39d8 100644 --- a/src/vs/editor/common/controller/cursorMoveHelper.ts +++ b/src/vs/editor/common/controller/cursorMoveHelper.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {IPosition, IEditorSelection} from 'vs/editor/common/editorCommon'; +import {IPosition} from 'vs/editor/common/editorCommon'; import {Selection} from 'vs/editor/common/core/selection'; export interface IMoveResult { @@ -14,11 +14,11 @@ export interface IMoveResult { } export interface IViewColumnSelectResult { - viewSelections: IEditorSelection[]; + viewSelections: Selection[]; reversed: boolean; } export interface IColumnSelectResult extends IViewColumnSelectResult { - selections: IEditorSelection[]; + selections: Selection[]; toLineNumber: number; toVisualColumn: number; } @@ -152,7 +152,7 @@ export class CursorMoveHelper { let isRTL = (fromVisibleColumn > toVisibleColumn); let isLTR = (fromVisibleColumn < toVisibleColumn); - let result: IEditorSelection[] = []; + let result: Selection[] = []; // console.log(`fromVisibleColumn: ${fromVisibleColumn}, toVisibleColumn: ${toVisibleColumn}`); diff --git a/src/vs/editor/common/controller/oneCursor.ts b/src/vs/editor/common/controller/oneCursor.ts index 7751d1f5901..f46068b93e9 100644 --- a/src/vs/editor/common/controller/oneCursor.ts +++ b/src/vs/editor/common/controller/oneCursor.ts @@ -57,21 +57,21 @@ export interface IViewModelHelper { viewModel:ICursorMoveHelperModel; - convertModelPositionToViewPosition(lineNumber:number, column:number): editorCommon.IEditorPosition; - convertModelRangeToViewRange(modelRange:editorCommon.IEditorRange): editorCommon.IEditorRange; + convertModelPositionToViewPosition(lineNumber:number, column:number): Position; + convertModelRangeToViewRange(modelRange:Range): Range; - convertViewToModelPosition(lineNumber:number, column:number): editorCommon.IEditorPosition; - convertViewSelectionToModelSelection(viewSelection:editorCommon.IEditorSelection): editorCommon.IEditorSelection; + convertViewToModelPosition(lineNumber:number, column:number): Position; + convertViewSelectionToModelSelection(viewSelection:Selection): Selection; - validateViewPosition(viewLineNumber:number, viewColumn:number, modelPosition:editorCommon.IEditorPosition): editorCommon.IEditorPosition; - validateViewRange(viewStartLineNumber:number, viewStartColumn:number, viewEndLineNumber:number, viewEndColumn:number, modelRange:editorCommon.IEditorRange): editorCommon.IEditorRange; + validateViewPosition(viewLineNumber:number, viewColumn:number, modelPosition:Position): Position; + validateViewRange(viewStartLineNumber:number, viewStartColumn:number, viewEndLineNumber:number, viewEndColumn:number, modelRange:Range): Range; } export interface IOneCursorState { - selectionStart: editorCommon.IEditorRange; - viewSelectionStart: editorCommon.IEditorRange; - position: editorCommon.IEditorPosition; - viewPosition: editorCommon.IEditorPosition; + selectionStart: Range; + viewSelectionStart: Range; + position: Position; + viewPosition: Position; leftoverVisibleColumns: number; selectionStartLeftoverVisibleColumns: number; } @@ -127,21 +127,21 @@ export class OneCursor { private viewModelHelper:IViewModelHelper; // --- selection can start as a range (think double click and drag) - private selectionStart: editorCommon.IEditorRange; - private viewSelectionStart: editorCommon.IEditorRange; + private selectionStart: Range; + private viewSelectionStart: Range; private selectionStartLeftoverVisibleColumns: number; // --- position - private position: editorCommon.IEditorPosition; - private viewPosition: editorCommon.IEditorPosition; + private position: Position; + private viewPosition: Position; private leftoverVisibleColumns: number; // --- bracket match decorations private bracketDecorations: string[]; // --- computed properties - private _cachedSelection: editorCommon.IEditorSelection; - private _cachedViewSelection: editorCommon.IEditorSelection; + private _cachedSelection: Selection; + private _cachedViewSelection: Selection; private _selStartMarker: string; private _selEndMarker: string; private _selDirection: editorCommon.SelectionDirection; @@ -170,9 +170,9 @@ export class OneCursor { } private _set( - selectionStart: editorCommon.IEditorRange, selectionStartLeftoverVisibleColumns: number, - position: editorCommon.IEditorPosition, leftoverVisibleColumns:number, - viewSelectionStart: editorCommon.IEditorRange, viewPosition: editorCommon.IEditorPosition + selectionStart: Range, selectionStartLeftoverVisibleColumns: number, + position: Position, leftoverVisibleColumns:number, + viewSelectionStart: Range, viewPosition: Position ): void { this.selectionStart = selectionStart; this.selectionStartLeftoverVisibleColumns = selectionStartLeftoverVisibleColumns; @@ -214,7 +214,7 @@ export class OneCursor { public restoreState(state:IOneCursorState): void { let position = this.model.validatePosition(state.position); - let selectionStart: editorCommon.IEditorRange; + let selectionStart: Range; if (state.selectionStart) { selectionStart = this.model.validateRange(state.selectionStart); } else { @@ -222,7 +222,7 @@ export class OneCursor { } let viewPosition = this.viewModelHelper.validateViewPosition(state.viewPosition.lineNumber, state.viewPosition.column, position); - let viewSelectionStart: editorCommon.IEditorRange; + let viewSelectionStart: Range; if (state.viewSelectionStart) { viewSelectionStart = this.viewModelHelper.validateViewRange(state.viewSelectionStart.startLineNumber, state.viewSelectionStart.startColumn, state.viewSelectionStart.endLineNumber, state.viewSelectionStart.endColumn, selectionStart); } else { @@ -257,7 +257,7 @@ export class OneCursor { } public adjustBracketDecorations(): void { - let bracketMatch: [editorCommon.IEditorRange,editorCommon.IEditorRange] = null; + let bracketMatch: [Range,Range] = null; let selection = this.getSelection(); if (selection.isEmpty()) { bracketMatch = this.model.matchBracket(this.position); @@ -276,7 +276,7 @@ export class OneCursor { this.bracketDecorations = this.model.deltaDecorations(this.bracketDecorations, newDecorations, this.editorId); } - private static computeSelection(selectionStart:editorCommon.IEditorRange, position:editorCommon.IEditorPosition): Selection { + private static computeSelection(selectionStart:Range, position:Position): Selection { let startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number; if (selectionStart.isEmpty()) { startLineNumber = selectionStart.startLineNumber; @@ -338,7 +338,7 @@ export class OneCursor { // -------------------- START modifications - public setSelectionStart(rng:editorCommon.IEditorRange, viewRng:editorCommon.IEditorRange): void { + public setSelectionStart(rng:Range, viewRng:Range): void { this._set( rng, this.selectionStartLeftoverVisibleColumns, this.position, this.leftoverVisibleColumns, @@ -455,23 +455,23 @@ export class OneCursor { return Math.floor(c.layoutInfo.height / c.fontInfo.lineHeight) - 2; } - public getSelectionStart(): editorCommon.IEditorRange { + public getSelectionStart(): Range { return this.selectionStart; } - public getPosition(): editorCommon.IEditorPosition { + public getPosition(): Position { return this.position; } - public getSelection(): editorCommon.IEditorSelection { + public getSelection(): Selection { return this._cachedSelection; } - public getViewPosition(): editorCommon.IEditorPosition { + public getViewPosition(): Position { return this.viewPosition; } - public getViewSelection(): editorCommon.IEditorSelection { + public getViewSelection(): Selection { return this._cachedViewSelection; } - public getValidViewPosition(): editorCommon.IEditorPosition { + public getValidViewPosition(): Position { return this.viewModelHelper.validateViewPosition(this.viewPosition.lineNumber, this.viewPosition.column, this.position); } @@ -492,16 +492,16 @@ export class OneCursor { } // -- utils - public validatePosition(position:editorCommon.IPosition): editorCommon.IEditorPosition { + public validatePosition(position:editorCommon.IPosition): Position { return this.model.validatePosition(position); } - public validateViewPosition(viewLineNumber:number, viewColumn:number, modelPosition:editorCommon.IEditorPosition): editorCommon.IEditorPosition { + public validateViewPosition(viewLineNumber:number, viewColumn:number, modelPosition:Position): Position { return this.viewModelHelper.validateViewPosition(viewLineNumber, viewColumn, modelPosition); } public convertViewToModelPosition(lineNumber:number, column:number): editorCommon.IPosition { return this.viewModelHelper.convertViewToModelPosition(lineNumber, column); } - public convertViewSelectionToModelSelection(viewSelection:editorCommon.IEditorSelection): editorCommon.IEditorSelection { + public convertViewSelectionToModelSelection(viewSelection:Selection): Selection { return this.viewModelHelper.convertViewSelectionToModelSelection(viewSelection); } public convertModelPositionToViewPosition(lineNumber:number, column:number): editorCommon.IPosition { @@ -512,10 +512,10 @@ export class OneCursor { public getLineContent(lineNumber:number): string { return this.model.getLineContent(lineNumber); } - public findPreviousWordOnLine(position:editorCommon.IEditorPosition): IFindWordResult { + public findPreviousWordOnLine(position:Position): IFindWordResult { return this.helper.findPreviousWordOnLine(position); } - public findNextWordOnLine(position:editorCommon.IEditorPosition): IFindWordResult { + public findNextWordOnLine(position:Position): IFindWordResult { return this.helper.findNextWordOnLine(position); } public getLeftOfPosition(lineNumber:number, column:number): editorCommon.IPosition { @@ -614,15 +614,15 @@ export class OneCursorOp { public static moveTo(cursor:OneCursor, inSelectionMode: boolean, position: editorCommon.IPosition, viewPosition:editorCommon.IPosition, eventSource: string, ctx: IOneCursorOperationContext): boolean { - var validatedPosition = cursor.model.validatePosition(position); - var validatedViewPosition: editorCommon.IPosition; + let validatedPosition = cursor.model.validatePosition(position); + let validatedViewPosition: editorCommon.IPosition; if (viewPosition) { validatedViewPosition = cursor.validateViewPosition(viewPosition.lineNumber, viewPosition.column, validatedPosition); } else { validatedViewPosition = cursor.convertModelPositionToViewPosition(validatedPosition.lineNumber, validatedPosition.column); } - var reason = (eventSource === 'mouse' ? editorCommon.CursorChangeReason.Explicit : editorCommon.CursorChangeReason.NotSet); + let reason = (eventSource === 'mouse' ? editorCommon.CursorChangeReason.Explicit : editorCommon.CursorChangeReason.NotSet); if (eventSource === 'api') { ctx.shouldRevealVerticalInCenter = true; } @@ -680,7 +680,7 @@ export class OneCursorOp { } public static columnSelectUp(isPaged:boolean, cursor:OneCursor, toViewLineNumber: number, toViewVisualColumn: number): IColumnSelectResult { - var linesCount = isPaged ? cursor.getPageSize() : 1; + let linesCount = isPaged ? cursor.getPageSize() : 1; toViewLineNumber -= linesCount; if (toViewLineNumber < 1) { @@ -691,7 +691,7 @@ export class OneCursorOp { } public static columnSelectDown(isPaged:boolean, cursor:OneCursor, toViewLineNumber: number, toViewVisualColumn: number): IColumnSelectResult { - var linesCount = isPaged ? cursor.getPageSize() : 1; + let linesCount = isPaged ? cursor.getPageSize() : 1; toViewLineNumber += linesCount; if (toViewLineNumber > cursor.getViewLineCount()) { @@ -702,18 +702,18 @@ export class OneCursorOp { } public static moveLeft(cursor:OneCursor, inSelectionMode: boolean, ctx: IOneCursorOperationContext): boolean { - var viewLineNumber:number, + let viewLineNumber:number, viewColumn:number; if (cursor.hasSelection() && !inSelectionMode) { // If we are in selection mode, move left without selection cancels selection and puts cursor at the beginning of the selection - var viewSelection = cursor.getViewSelection(); - var viewSelectionStart = cursor.validateViewPosition(viewSelection.startLineNumber, viewSelection.startColumn, cursor.getSelection().getStartPosition()); + let viewSelection = cursor.getViewSelection(); + let viewSelectionStart = cursor.validateViewPosition(viewSelection.startLineNumber, viewSelection.startColumn, cursor.getSelection().getStartPosition()); viewLineNumber = viewSelectionStart.lineNumber; viewColumn = viewSelectionStart.column; } else { - var validatedViewPosition = cursor.getValidViewPosition(); - var r = cursor.getLeftOfViewPosition(validatedViewPosition.lineNumber, validatedViewPosition.column); + let validatedViewPosition = cursor.getValidViewPosition(); + let r = cursor.getLeftOfViewPosition(validatedViewPosition.lineNumber, validatedViewPosition.column); viewLineNumber = r.lineNumber; viewColumn = r.column; } @@ -760,18 +760,18 @@ export class OneCursorOp { } public static moveRight(cursor:OneCursor, inSelectionMode: boolean, ctx: IOneCursorOperationContext): boolean { - var viewLineNumber:number, + let viewLineNumber:number, viewColumn:number; if (cursor.hasSelection() && !inSelectionMode) { // If we are in selection mode, move right without selection cancels selection and puts cursor at the end of the selection - var viewSelection = cursor.getViewSelection(); - var viewSelectionEnd = cursor.validateViewPosition(viewSelection.endLineNumber, viewSelection.endColumn, cursor.getSelection().getEndPosition()); + let viewSelection = cursor.getViewSelection(); + let viewSelectionEnd = cursor.validateViewPosition(viewSelection.endLineNumber, viewSelection.endColumn, cursor.getSelection().getEndPosition()); viewLineNumber = viewSelectionEnd.lineNumber; viewColumn = viewSelectionEnd.column; } else { - var validatedViewPosition = cursor.getValidViewPosition(); - var r = cursor.getRightOfViewPosition(validatedViewPosition.lineNumber, validatedViewPosition.column); + let validatedViewPosition = cursor.getValidViewPosition(); + let r = cursor.getRightOfViewPosition(validatedViewPosition.lineNumber, validatedViewPosition.column); viewLineNumber = r.lineNumber; viewColumn = r.column; } @@ -818,24 +818,24 @@ export class OneCursorOp { } public static moveDown(cursor:OneCursor, inSelectionMode: boolean, isPaged: boolean, usePageSize: number, ctx: IOneCursorOperationContext): boolean { - var linesCount = isPaged ? (usePageSize || cursor.getPageSize()) : 1; + let linesCount = isPaged ? (usePageSize || cursor.getPageSize()) : 1; - var viewLineNumber:number, + let viewLineNumber:number, viewColumn:number; if (cursor.hasSelection() && !inSelectionMode) { // If we are in selection mode, move down acts relative to the end of selection - var viewSelection = cursor.getViewSelection(); - var viewSelectionEnd = cursor.validateViewPosition(viewSelection.endLineNumber, viewSelection.endColumn, cursor.getSelection().getEndPosition()); + let viewSelection = cursor.getViewSelection(); + let viewSelectionEnd = cursor.validateViewPosition(viewSelection.endLineNumber, viewSelection.endColumn, cursor.getSelection().getEndPosition()); viewLineNumber = viewSelectionEnd.lineNumber; viewColumn = viewSelectionEnd.column; } else { - var validatedViewPosition = cursor.getValidViewPosition(); + let validatedViewPosition = cursor.getValidViewPosition(); viewLineNumber = validatedViewPosition.lineNumber; viewColumn = validatedViewPosition.column; } - var r = cursor.getViewPositionDown(viewLineNumber, viewColumn, cursor.getLeftoverVisibleColumns(), linesCount, true); + let r = cursor.getViewPositionDown(viewLineNumber, viewColumn, cursor.getLeftoverVisibleColumns(), linesCount, true); ctx.cursorPositionChangeReason = editorCommon.CursorChangeReason.Explicit; cursor.moveViewPosition(inSelectionMode, r.lineNumber, r.column, r.leftoverVisibleColumns, true); return true; @@ -843,13 +843,13 @@ export class OneCursorOp { public static translateDown(cursor:OneCursor, ctx: IOneCursorOperationContext): boolean { - var selection = cursor.getViewSelection(); + let selection = cursor.getViewSelection(); - var selectionStart = cursor.getViewPositionDown(selection.selectionStartLineNumber, selection.selectionStartColumn, cursor.getSelectionStartLeftoverVisibleColumns(), 1, false); + let selectionStart = cursor.getViewPositionDown(selection.selectionStartLineNumber, selection.selectionStartColumn, cursor.getSelectionStartLeftoverVisibleColumns(), 1, false); ctx.cursorPositionChangeReason = editorCommon.CursorChangeReason.Explicit; cursor.moveViewPosition(false, selectionStart.lineNumber, selectionStart.column, cursor.getLeftoverVisibleColumns(), true); - var position = cursor.getViewPositionDown(selection.positionLineNumber, selection.positionColumn, cursor.getLeftoverVisibleColumns(), 1, false); + let position = cursor.getViewPositionDown(selection.positionLineNumber, selection.positionColumn, cursor.getLeftoverVisibleColumns(), 1, false); ctx.cursorPositionChangeReason = editorCommon.CursorChangeReason.Explicit; cursor.moveViewPosition(true, position.lineNumber, position.column, position.leftoverVisibleColumns, true); @@ -859,24 +859,24 @@ export class OneCursorOp { } public static moveUp(cursor:OneCursor, inSelectionMode: boolean, isPaged: boolean, usePageSize: number, ctx: IOneCursorOperationContext): boolean { - var linesCount = isPaged ? (usePageSize || cursor.getPageSize()) : 1; + let linesCount = isPaged ? (usePageSize || cursor.getPageSize()) : 1; - var viewLineNumber:number, + let viewLineNumber:number, viewColumn:number; if (cursor.hasSelection() && !inSelectionMode) { // If we are in selection mode, move up acts relative to the beginning of selection - var viewSelection = cursor.getViewSelection(); - var viewSelectionStart = cursor.validateViewPosition(viewSelection.startLineNumber, viewSelection.startColumn, cursor.getSelection().getStartPosition()); + let viewSelection = cursor.getViewSelection(); + let viewSelectionStart = cursor.validateViewPosition(viewSelection.startLineNumber, viewSelection.startColumn, cursor.getSelection().getStartPosition()); viewLineNumber = viewSelectionStart.lineNumber; viewColumn = viewSelectionStart.column; } else { - var validatedViewPosition = cursor.getValidViewPosition(); + let validatedViewPosition = cursor.getValidViewPosition(); viewLineNumber = validatedViewPosition.lineNumber; viewColumn = validatedViewPosition.column; } - var r = cursor.getViewPositionUp(viewLineNumber, viewColumn, cursor.getLeftoverVisibleColumns(), linesCount, true); + let r = cursor.getViewPositionUp(viewLineNumber, viewColumn, cursor.getLeftoverVisibleColumns(), linesCount, true); ctx.cursorPositionChangeReason = editorCommon.CursorChangeReason.Explicit; cursor.moveViewPosition(inSelectionMode, r.lineNumber, r.column, r.leftoverVisibleColumns, true); @@ -885,13 +885,13 @@ export class OneCursorOp { public static translateUp(cursor:OneCursor, ctx: IOneCursorOperationContext): boolean { - var selection = cursor.getViewSelection(); + let selection = cursor.getViewSelection(); - var selectionStart = cursor.getViewPositionUp(selection.selectionStartLineNumber, selection.selectionStartColumn, cursor.getSelectionStartLeftoverVisibleColumns(), 1, false); + let selectionStart = cursor.getViewPositionUp(selection.selectionStartLineNumber, selection.selectionStartColumn, cursor.getSelectionStartLeftoverVisibleColumns(), 1, false); ctx.cursorPositionChangeReason = editorCommon.CursorChangeReason.Explicit; cursor.moveViewPosition(false, selectionStart.lineNumber, selectionStart.column, cursor.getLeftoverVisibleColumns(), true); - var position = cursor.getViewPositionUp(selection.positionLineNumber, selection.positionColumn, cursor.getLeftoverVisibleColumns(), 1, false); + let position = cursor.getViewPositionUp(selection.positionLineNumber, selection.positionColumn, cursor.getLeftoverVisibleColumns(), 1, false); ctx.cursorPositionChangeReason = editorCommon.CursorChangeReason.Explicit; cursor.moveViewPosition(true, position.lineNumber, position.column, position.leftoverVisibleColumns, true); @@ -901,9 +901,9 @@ export class OneCursorOp { } public static moveToBeginningOfLine(cursor:OneCursor, inSelectionMode: boolean, ctx: IOneCursorOperationContext): boolean { - var validatedViewPosition = cursor.getValidViewPosition(); - var viewLineNumber = validatedViewPosition.lineNumber; - var viewColumn = validatedViewPosition.column; + let validatedViewPosition = cursor.getValidViewPosition(); + let viewLineNumber = validatedViewPosition.lineNumber; + let viewColumn = validatedViewPosition.column; viewColumn = cursor.getColumnAtBeginningOfViewLine(viewLineNumber, viewColumn); ctx.cursorPositionChangeReason = editorCommon.CursorChangeReason.Explicit; @@ -912,9 +912,9 @@ export class OneCursorOp { } public static moveToEndOfLine(cursor:OneCursor, inSelectionMode: boolean, ctx: IOneCursorOperationContext): boolean { - var validatedViewPosition = cursor.getValidViewPosition(); - var viewLineNumber = validatedViewPosition.lineNumber; - var viewColumn = validatedViewPosition.column; + let validatedViewPosition = cursor.getValidViewPosition(); + let viewLineNumber = validatedViewPosition.lineNumber; + let viewColumn = validatedViewPosition.column; viewColumn = cursor.getColumnAtEndOfViewLine(viewLineNumber, viewColumn); ctx.cursorPositionChangeReason = editorCommon.CursorChangeReason.Explicit; @@ -954,8 +954,8 @@ export class OneCursorOp { } public static moveToEndOfBuffer(cursor:OneCursor, inSelectionMode: boolean, ctx: IOneCursorOperationContext): boolean { - var lastLineNumber = cursor.model.getLineCount(); - var lastColumn = cursor.model.getLineMaxColumn(lastLineNumber); + let lastLineNumber = cursor.model.getLineCount(); + let lastColumn = cursor.model.getLineMaxColumn(lastLineNumber); ctx.cursorPositionChangeReason = editorCommon.CursorChangeReason.Explicit; cursor.moveModelPosition(inSelectionMode, lastLineNumber, lastColumn, 0, true); @@ -964,8 +964,8 @@ export class OneCursorOp { public static selectAll(cursor:OneCursor, ctx: IOneCursorOperationContext): boolean { - var selectEntireBuffer = true; - var newSelectionStartLineNumber: number, + let selectEntireBuffer = true; + let newSelectionStartLineNumber: number, newSelectionStartColumn: number, newPositionLineNumber: number, newPositionColumn: number; @@ -973,8 +973,8 @@ export class OneCursorOp { if (cursor.model.hasEditableRange()) { // Toggle between selecting editable range and selecting the entire buffer - var editableRange = cursor.model.getEditableRange(); - var selection = cursor.getSelection(); + let editableRange = cursor.model.getEditableRange(); + let selection = cursor.getSelection(); if (!selection.equalsRange(editableRange)) { // Selection is not editable range => select editable range @@ -1164,7 +1164,7 @@ export class OneCursorOp { } public static lineInsertBefore(cursor:OneCursor, ctx: IOneCursorOperationContext): boolean { - var lineNumber = cursor.getPosition().lineNumber; + let lineNumber = cursor.getPosition().lineNumber; if (lineNumber === 1) { ctx.executeCommand = new ReplaceCommandWithoutChangingPosition(new Range(1,1,1,1), '\n'); @@ -1172,14 +1172,14 @@ export class OneCursorOp { } lineNumber--; - var column = cursor.model.getLineMaxColumn(lineNumber); + let column = cursor.model.getLineMaxColumn(lineNumber); return this._enter(cursor, false, ctx, new Position(lineNumber, column), new Range(lineNumber, column, lineNumber, column)); } public static lineInsertAfter(cursor:OneCursor, ctx: IOneCursorOperationContext): boolean { let position = cursor.getPosition(); - var column = cursor.model.getLineMaxColumn(position.lineNumber); + let column = cursor.model.getLineMaxColumn(position.lineNumber); return this._enter(cursor, false, ctx, new Position(position.lineNumber, column), new Range(position.lineNumber, column, position.lineNumber, column)); } @@ -1187,7 +1187,7 @@ export class OneCursorOp { return this._enter(cursor, true, ctx); } - private static _enter(cursor:OneCursor, keepPosition: boolean, ctx: IOneCursorOperationContext, position?: editorCommon.IEditorPosition, range?: editorCommon.IEditorRange): boolean { + private static _enter(cursor:OneCursor, keepPosition: boolean, ctx: IOneCursorOperationContext, position?: Position, range?: Range): boolean { if (typeof position === 'undefined') { position = cursor.getPosition(); } @@ -1196,9 +1196,9 @@ export class OneCursorOp { } ctx.shouldPushStackElementBefore = true; - var r = getEnterActionAtPosition(cursor.model, position.lineNumber, position.column); - var enterAction = r.enterAction; - var indentation = r.indentation; + let r = getEnterActionAtPosition(cursor.model, position.lineNumber, position.column); + let enterAction = r.enterAction; + let indentation = r.indentation; ctx.isAutoWhitespaceCommand = true; if (enterAction.indentAction === IndentAction.None) { @@ -1238,7 +1238,7 @@ export class OneCursorOp { return false; } - var selection = cursor.getSelection(); + let selection = cursor.getSelection(); if (!selection.isEmpty() || !cursor.modeConfiguration.autoClosingPairsClose.hasOwnProperty(ch)) { return false; @@ -1246,14 +1246,14 @@ export class OneCursorOp { let position = cursor.getPosition(); - var lineText = cursor.model.getLineContent(position.lineNumber); - var beforeCharacter = lineText[position.column - 1]; + let lineText = cursor.model.getLineContent(position.lineNumber); + let beforeCharacter = lineText[position.column - 1]; if (beforeCharacter !== ch) { return false; } - var typeSelection = new Range(position.lineNumber, position.column, position.lineNumber, position.column + 1); + let typeSelection = new Range(position.lineNumber, position.column, position.lineNumber, position.column + 1); ctx.executeCommand = new ReplaceCommand(typeSelection, ch); return true; } @@ -1263,7 +1263,7 @@ export class OneCursorOp { return false; } - var selection = cursor.getSelection(); + let selection = cursor.getSelection(); if (!selection.isEmpty() || !cursor.modeConfiguration.autoClosingPairsOpen.hasOwnProperty(ch)) { return false; @@ -1276,13 +1276,13 @@ export class OneCursorOp { } let position = cursor.getPosition(); - var lineText = cursor.model.getLineContent(position.lineNumber); - var beforeCharacter = lineText[position.column - 1]; + let lineText = cursor.model.getLineContent(position.lineNumber); + let beforeCharacter = lineText[position.column - 1]; // Only consider auto closing the pair if a space follows or if another autoclosed pair follows if (beforeCharacter) { - var isBeforeCloseBrace = false; - for (var closeBrace in cursor.modeConfiguration.autoClosingPairsClose) { + let isBeforeCloseBrace = false; + for (let closeBrace in cursor.modeConfiguration.autoClosingPairsClose) { if (beforeCharacter === closeBrace) { isBeforeCloseBrace = true; break; @@ -1293,9 +1293,9 @@ export class OneCursorOp { } } - var lineContext = cursor.model.getLineContext(position.lineNumber); + let lineContext = cursor.model.getLineContext(position.lineNumber); - var shouldAutoClosePair = false; + let shouldAutoClosePair = false; try { shouldAutoClosePair = richEditSupport.characterPair.shouldAutoClosePair(ch, lineContext, position.column - 1); } catch(e) { @@ -1307,7 +1307,7 @@ export class OneCursorOp { } ctx.shouldPushStackElementBefore = true; - var closeCharacter = cursor.modeConfiguration.autoClosingPairsOpen[ch]; + let closeCharacter = cursor.modeConfiguration.autoClosingPairsOpen[ch]; ctx.executeCommand = new ReplaceCommandWithOffsetCursorState(selection, ch + closeCharacter, 0, -closeCharacter.length); return true; } @@ -1317,13 +1317,13 @@ export class OneCursorOp { return false; } - var selection = cursor.getSelection(); + let selection = cursor.getSelection(); if (selection.isEmpty() || !cursor.modeConfiguration.surroundingPairs.hasOwnProperty(ch)) { return false; } - var selectionContainsOnlyWhitespace = true, + let selectionContainsOnlyWhitespace = true, lineNumber:number, startIndex:number, endIndex:number, @@ -1355,7 +1355,7 @@ export class OneCursorOp { return false; } - var closeCharacter = cursor.modeConfiguration.surroundingPairs[ch]; + let closeCharacter = cursor.modeConfiguration.surroundingPairs[ch]; ctx.shouldPushStackElementBefore = true; ctx.shouldPushStackElementAfter = true; @@ -1376,10 +1376,10 @@ export class OneCursorOp { private static _typeInterceptorElectricCharRunnable(cursor:OneCursor, ctx: IOneCursorOperationContext): void { let position = cursor.getPosition(); - var lineText = cursor.model.getLineContent(position.lineNumber); - var lineContext = cursor.model.getLineContext(position.lineNumber); + let lineText = cursor.model.getLineContent(position.lineNumber); + let lineContext = cursor.model.getLineContext(position.lineNumber); - var electricAction:IElectricAction; + let electricAction:IElectricAction; let richEditSupport = cursor.model.getMode().richEditSupport; if(richEditSupport && richEditSupport.electricCharacter) { try { @@ -1391,32 +1391,32 @@ export class OneCursorOp { if (electricAction) { let matchOpenBracket = electricAction.matchOpenBracket; - var appendText = electricAction.appendText; + let appendText = electricAction.appendText; if (matchOpenBracket) { - var match = cursor.model.findMatchingBracketUp(matchOpenBracket, { + let match = cursor.model.findMatchingBracketUp(matchOpenBracket, { lineNumber: position.lineNumber, column: position.column - matchOpenBracket.length }); if (match) { - var matchLineNumber = match.startLineNumber; - var matchLine = cursor.model.getLineContent(matchLineNumber); - var matchLineIndentation = strings.getLeadingWhitespace(matchLine); - var newIndentation = cursor.model.normalizeIndentation(matchLineIndentation); + let matchLineNumber = match.startLineNumber; + let matchLine = cursor.model.getLineContent(matchLineNumber); + let matchLineIndentation = strings.getLeadingWhitespace(matchLine); + let newIndentation = cursor.model.normalizeIndentation(matchLineIndentation); - var lineFirstNonBlankColumn = cursor.model.getLineFirstNonWhitespaceColumn(position.lineNumber) || position.column; - var oldIndentation = lineText.substring(0, lineFirstNonBlankColumn - 1); + let lineFirstNonBlankColumn = cursor.model.getLineFirstNonWhitespaceColumn(position.lineNumber) || position.column; + let oldIndentation = lineText.substring(0, lineFirstNonBlankColumn - 1); if (oldIndentation !== newIndentation) { - var prefix = lineText.substring(lineFirstNonBlankColumn - 1, position.column - 1); - var typeText = newIndentation + prefix; + let prefix = lineText.substring(lineFirstNonBlankColumn - 1, position.column - 1); + let typeText = newIndentation + prefix; - var typeSelection = new Range(position.lineNumber, 1, position.lineNumber, position.column); + let typeSelection = new Range(position.lineNumber, 1, position.lineNumber, position.column); ctx.shouldPushStackElementAfter = true; ctx.executeCommand = new ReplaceCommand(typeSelection, typeText); } } } else if (appendText) { - var columnDeltaOffset = -appendText.length; + let columnDeltaOffset = -appendText.length; if (electricAction.advanceCount) { columnDeltaOffset += electricAction.advanceCount; } @@ -1426,7 +1426,7 @@ export class OneCursorOp { } } - public static actualType(cursor:OneCursor, text: string, keepPosition: boolean, ctx: IOneCursorOperationContext, range?: editorCommon.IEditorRange): boolean { + public static actualType(cursor:OneCursor, text: string, keepPosition: boolean, ctx: IOneCursorOperationContext, range?: Range): boolean { if (typeof range === 'undefined') { range = cursor.getSelection(); } @@ -1465,7 +1465,7 @@ export class OneCursorOp { public static replacePreviousChar(cursor:OneCursor, txt: string, replaceCharCnt:number, ctx: IOneCursorOperationContext): boolean { let pos = cursor.getPosition(); - let range: editorCommon.IEditorRange; + let range: Range; let startColumn = Math.max(1, pos.column - replaceCharCnt); range = new Range(pos.lineNumber, startColumn, pos.lineNumber, pos.column); ctx.executeCommand = new ReplaceCommand(range, txt); @@ -1473,11 +1473,11 @@ export class OneCursorOp { } private static _goodIndentForLine(cursor:OneCursor, lineNumber:number): string { - var lastLineNumber = lineNumber - 1; + let lastLineNumber = lineNumber - 1; for (lastLineNumber = lineNumber - 1; lastLineNumber >= 1; lastLineNumber--) { - var lineText = cursor.model.getLineContent(lastLineNumber); - var nonWhitespaceIdx = strings.lastNonWhitespaceIndex(lineText); + let lineText = cursor.model.getLineContent(lastLineNumber); + let nonWhitespaceIdx = strings.lastNonWhitespaceIndex(lineText); if (nonWhitespaceIdx >= 0) { break; } @@ -1488,9 +1488,9 @@ export class OneCursorOp { return '\t'; } - var r = getEnterActionAtPosition(cursor.model, lastLineNumber, cursor.model.getLineMaxColumn(lastLineNumber)); + let r = getEnterActionAtPosition(cursor.model, lastLineNumber, cursor.model.getLineMaxColumn(lastLineNumber)); - var indentation: string; + let indentation: string; if (r.enterAction.indentAction === IndentAction.Outdent) { let modelOpts = cursor.model.getOptions(); let desiredIndentCount = ShiftCommand.unshiftIndentCount(r.indentation, r.indentation.length, modelOpts.tabSize); @@ -1503,7 +1503,7 @@ export class OneCursorOp { indentation = r.indentation; } - var result = indentation + r.enterAction.appendText; + let result = indentation + r.enterAction.appendText; if (result.length === 0) { // good position is at column 1, but we gotta do something... return '\t'; @@ -1546,7 +1546,7 @@ export class OneCursorOp { } public static indent(cursor:OneCursor, ctx: IOneCursorOperationContext): boolean { - var selection = cursor.getSelection(); + let selection = cursor.getSelection(); ctx.shouldPushStackElementBefore = true; ctx.shouldPushStackElementAfter = true; @@ -1561,7 +1561,7 @@ export class OneCursorOp { } public static outdent(cursor:OneCursor, ctx: IOneCursorOperationContext): boolean { - var selection = cursor.getSelection(); + let selection = cursor.getSelection(); ctx.shouldPushStackElementBefore = true; ctx.shouldPushStackElementAfter = true; @@ -1583,7 +1583,7 @@ export class OneCursorOp { if (text.indexOf('\n') === text.length - 1) { // Paste entire line at the beginning of line - var typeSelection = new Range(position.lineNumber, 1, position.lineNumber, 1); + let typeSelection = new Range(position.lineNumber, 1, position.lineNumber, 1); ctx.executeCommand = new ReplaceCommand(typeSelection, text); return true; } @@ -1609,21 +1609,21 @@ export class OneCursorOp { let position = cursor.getPosition(); - var lineText = cursor.model.getLineContent(position.lineNumber); - var character = lineText[position.column - 2]; + let lineText = cursor.model.getLineContent(position.lineNumber); + let character = lineText[position.column - 2]; if (!cursor.modeConfiguration.autoClosingPairsOpen.hasOwnProperty(character)) { return false; } - var afterCharacter = lineText[position.column - 1]; - var closeCharacter = cursor.modeConfiguration.autoClosingPairsOpen[character]; + let afterCharacter = lineText[position.column - 1]; + let closeCharacter = cursor.modeConfiguration.autoClosingPairsOpen[character]; if (afterCharacter !== closeCharacter) { return false; } - var deleteSelection = new Range( + let deleteSelection = new Range( position.lineNumber, position.column - 1, position.lineNumber, @@ -1640,10 +1640,10 @@ export class OneCursorOp { return true; } - var deleteSelection: editorCommon.IEditorRange = cursor.getSelection(); + let deleteSelection: Range = cursor.getSelection(); if (deleteSelection.isEmpty()) { - var position = cursor.getPosition(); + let position = cursor.getPosition(); if (cursor.configuration.editor.useTabStops && position.column > 1) { let lineContent = cursor.getLineContent(position.lineNumber); @@ -1664,7 +1664,7 @@ export class OneCursorOp { deleteSelection = new Range(position.lineNumber, position.column - 1, position.lineNumber, position.column); } } else { - var leftOfPosition = cursor.getLeftOfPosition(position.lineNumber, position.column); + let leftOfPosition = cursor.getLeftOfPosition(position.lineNumber, position.column); deleteSelection = new Range( leftOfPosition.lineNumber, leftOfPosition.column, @@ -1754,11 +1754,11 @@ export class OneCursorOp { public static deleteRight(cursor:OneCursor, ctx: IOneCursorOperationContext): boolean { - var deleteSelection: editorCommon.IEditorRange = cursor.getSelection(); + let deleteSelection: Range = cursor.getSelection(); if (deleteSelection.isEmpty()) { let position = cursor.getPosition(); - var rightOfPosition = cursor.getRightOfPosition(position.lineNumber, position.column); + let rightOfPosition = cursor.getRightOfPosition(position.lineNumber, position.column); deleteSelection = new Range( rightOfPosition.lineNumber, rightOfPosition.column, @@ -1806,16 +1806,16 @@ export class OneCursorOp { public static deleteWordRight(cursor:OneCursor, whitespaceHeuristics:boolean, wordNavigationType:WordNavigationType, ctx: IOneCursorOperationContext): boolean { - var selection = cursor.getSelection(); + let selection = cursor.getSelection(); if (selection.isEmpty()) { let position = cursor.getPosition(); - var lineNumber = position.lineNumber; - var column = position.column; + let lineNumber = position.lineNumber; + let column = position.column; - var lineCount = cursor.model.getLineCount(); - var maxColumn = cursor.model.getLineMaxColumn(lineNumber); + let lineCount = cursor.model.getLineCount(); + let maxColumn = cursor.model.getLineMaxColumn(lineNumber); if (lineNumber === lineCount && column === maxColumn) { // Ignore deleting at end of file return true; @@ -1831,7 +1831,17 @@ export class OneCursorOp { if (nextWordOnLine) { column = nextWordOnLine.end + 1; } else { - column = maxColumn; + if (column < maxColumn || lineNumber === lineCount) { + column = maxColumn; + } else { + lineNumber++; + nextWordOnLine = cursor.findNextWordOnLine(new Position(lineNumber, 1)); + if (nextWordOnLine) { + column = nextWordOnLine.start + 1; + } else { + column = cursor.model.getLineMaxColumn(lineNumber); + } + } } } else { if (nextWordOnLine && column >= nextWordOnLine.start + 1) { @@ -1840,11 +1850,21 @@ export class OneCursorOp { if (nextWordOnLine) { column = nextWordOnLine.start + 1; } else { - column = maxColumn; + if (column < maxColumn || lineNumber === lineCount) { + column = maxColumn; + } else { + lineNumber++; + nextWordOnLine = cursor.findNextWordOnLine(new Position(lineNumber, 1)); + if (nextWordOnLine) { + column = nextWordOnLine.start + 1; + } else { + column = cursor.model.getLineMaxColumn(lineNumber); + } + } } } - var deleteSelection = new Range(lineNumber, column, lineNumber, position.column); + let deleteSelection = new Range(lineNumber, column, position.lineNumber, position.column); if (!deleteSelection.isEmpty()) { ctx.executeCommand = new ReplaceCommand(deleteSelection, ''); return true; @@ -1860,19 +1880,19 @@ export class OneCursorOp { return true; } - var selection = cursor.getSelection(); + let selection = cursor.getSelection(); if (selection.isEmpty()) { let position = cursor.getPosition(); - var lineNumber = position.lineNumber; - var column = position.column; + let lineNumber = position.lineNumber; + let column = position.column; if (column === 1) { // Ignore deleting at beginning of line return true; } - var deleteSelection = new Range(lineNumber, 1, lineNumber, column); + let deleteSelection = new Range(lineNumber, 1, lineNumber, column); if (!deleteSelection.isEmpty()) { ctx.executeCommand = new ReplaceCommand(deleteSelection, ''); return true; @@ -1883,20 +1903,20 @@ export class OneCursorOp { } public static deleteAllRight(cursor:OneCursor, ctx: IOneCursorOperationContext): boolean { - var selection = cursor.getSelection(); + let selection = cursor.getSelection(); if (selection.isEmpty()) { let position = cursor.getPosition(); - var lineNumber = position.lineNumber; - var column = position.column; - var maxColumn = cursor.model.getLineMaxColumn(lineNumber); + let lineNumber = position.lineNumber; + let column = position.column; + let maxColumn = cursor.model.getLineMaxColumn(lineNumber); if (column === maxColumn) { // Ignore deleting at end of file return true; } - var deleteSelection = new Range(lineNumber, column, lineNumber, maxColumn); + let deleteSelection = new Range(lineNumber, column, lineNumber, maxColumn); if (!deleteSelection.isEmpty()) { ctx.executeCommand = new ReplaceCommand(deleteSelection, ''); return true; @@ -1907,7 +1927,7 @@ export class OneCursorOp { } public static cut(cursor:OneCursor, enableEmptySelectionClipboard:boolean, ctx: IOneCursorOperationContext): boolean { - var selection = cursor.getSelection(); + let selection = cursor.getSelection(); if (selection.isEmpty()) { if (enableEmptySelectionClipboard) { @@ -1915,7 +1935,7 @@ export class OneCursorOp { let position = cursor.getPosition(); - var startLineNumber:number, + let startLineNumber:number, startColumn:number, endLineNumber:number, endColumn:number; @@ -1940,7 +1960,7 @@ export class OneCursorOp { endColumn = cursor.model.getLineMaxColumn(position.lineNumber); } - var deleteSelection = new Range( + let deleteSelection = new Range( startLineNumber, startColumn, endLineNumber, @@ -2020,7 +2040,7 @@ class CursorHelper { return { start: start, end: end, wordType: wordType }; } - public findPreviousWordOnLine(_position:editorCommon.IEditorPosition): IFindWordResult { + public findPreviousWordOnLine(_position:Position): IFindWordResult { let position = this.model.validatePosition(_position); let wordSeparators = getMapForWordSeparators(this.configuration.editor.wordSeparators); let lineContent = this.model.getLineContent(position.lineNumber); @@ -2072,7 +2092,7 @@ class CursorHelper { return len; } - public findNextWordOnLine(_position:editorCommon.IEditorPosition): IFindWordResult { + public findNextWordOnLine(_position:Position): IFindWordResult { let position = this.model.validatePosition(_position); let wordSeparators = getMapForWordSeparators(this.configuration.editor.wordSeparators); let lineContent = this.model.getLineContent(position.lineNumber); @@ -2137,7 +2157,7 @@ function once(keyFn:(input:T)=>string, computeFn:(input:T)=>R):(input:T)=> }; } -var getMapForWordSeparators = once( +let getMapForWordSeparators = once( (input) => input, (input) => { diff --git a/src/vs/editor/common/controller/textAreaHandler.ts b/src/vs/editor/common/controller/textAreaHandler.ts index fb4ca1d637a..385ccfc2d4c 100644 --- a/src/vs/editor/common/controller/textAreaHandler.ts +++ b/src/vs/editor/common/controller/textAreaHandler.ts @@ -11,7 +11,7 @@ import {Disposable} from 'vs/base/common/lifecycle'; import {IClipboardEvent, ICompositionEvent, IKeyboardEventWrapper, ISimpleModel, ITextAreaWrapper, ITypeData, TextAreaState, TextAreaStrategy, createTextAreaState} from 'vs/editor/common/controller/textAreaState'; import {Position} from 'vs/editor/common/core/position'; import {Range} from 'vs/editor/common/core/range'; -import {EndOfLinePreference, IEditorPosition, IEditorRange} from 'vs/editor/common/editorCommon'; +import {EndOfLinePreference} from 'vs/editor/common/editorCommon'; enum ReadFromTextArea { Type, @@ -67,14 +67,14 @@ export class TextAreaHandler extends Disposable { private model:ISimpleModel; private flushAnyAccumulatedEvents:()=>void; - private selection:IEditorRange; - private selections:IEditorRange[]; + private selection:Range; + private selections:Range[]; private hasFocus:boolean; private asyncTriggerCut: RunOnceScheduler; private lastCompositionEndTime:number; - private cursorPosition:IEditorPosition; + private cursorPosition:Position; private textAreaState:TextAreaState; private textareaIsShownAtCursor: boolean; @@ -243,13 +243,13 @@ export class TextAreaHandler extends Disposable { } } - public setCursorSelections(primary: IEditorRange, secondary: IEditorRange[]): void { + public setCursorSelections(primary: Range, secondary: Range[]): void { this.selection = primary; this.selections = [primary].concat(secondary); this._writePlaceholderAndSelectTextArea('selection changed'); } - public setCursorPosition(primary: IEditorPosition): void { + public setCursorPosition(primary: Position): void { this.cursorPosition = primary; } @@ -342,7 +342,7 @@ export class TextAreaHandler extends Disposable { let selections = this.selections; if (selections.length === 1) { - let range:IEditorRange = selections[0]; + let range:Range = selections[0]; if (range.isEmpty()) { if (this.Browser.enableEmptySelectionClipboard) { let modelLineNumber = this.model.convertViewPositionToModelPosition(range.startLineNumber, 1).lineNumber; diff --git a/src/vs/editor/common/controller/textAreaState.ts b/src/vs/editor/common/controller/textAreaState.ts index bd0aea3acbf..3361ea6f4b7 100644 --- a/src/vs/editor/common/controller/textAreaState.ts +++ b/src/vs/editor/common/controller/textAreaState.ts @@ -7,7 +7,8 @@ import Event from 'vs/base/common/event'; import {commonPrefixLength, commonSuffixLength} from 'vs/base/common/strings'; import {Range} from 'vs/editor/common/core/range'; -import {EndOfLinePreference, IEditorPosition, IEditorRange, IRange} from 'vs/editor/common/editorCommon'; +import {EndOfLinePreference, IRange} from 'vs/editor/common/editorCommon'; +import {Position} from 'vs/editor/common/core/position'; export interface IClipboardEvent { canUseTextData(): boolean; @@ -54,7 +55,7 @@ export interface ISimpleModel { getValueInRange(range:IRange, eol:EndOfLinePreference): string; getModelLineContent(lineNumber:number): string; getLineCount(): number; - convertViewPositionToModelPosition(viewLineNumber:number, viewColumn:number): IEditorPosition; + convertViewPositionToModelPosition(viewLineNumber:number, viewColumn:number): Position; } export interface ITypeData { @@ -107,7 +108,7 @@ export abstract class TextAreaState { public abstract fromTextArea(textArea:ITextAreaWrapper): TextAreaState; - public abstract fromEditorSelection(model:ISimpleModel, selection:IEditorRange); + public abstract fromEditorSelection(model:ISimpleModel, selection:Range); public abstract fromText(text:string): TextAreaState; @@ -270,7 +271,7 @@ export class IENarratorTextAreaState extends TextAreaState { return new IENarratorTextAreaState(this, textArea.getValue(), textArea.getSelectionStart(), textArea.getSelectionEnd(), textArea.isInOverwriteMode(), this.selectionToken); } - public fromEditorSelection(model:ISimpleModel, selection:IEditorRange): TextAreaState { + public fromEditorSelection(model:ISimpleModel, selection:Range): TextAreaState { let LIMIT_CHARS = 100; let PADDING_LINES_COUNT = 0; @@ -382,7 +383,7 @@ export class NVDAPagedTextAreaState extends TextAreaState { return new Range(startLineNumber, 1, endLineNumber, Number.MAX_VALUE); } - public fromEditorSelection(model:ISimpleModel, selection:IEditorRange): TextAreaState { + public fromEditorSelection(model:ISimpleModel, selection:Range): TextAreaState { let selectionStartPage = NVDAPagedTextAreaState._getPageOfLine(selection.startLineNumber); let selectionStartPageRange = NVDAPagedTextAreaState._getRangeForPage(selectionStartPage); @@ -467,7 +468,7 @@ export class NVDAFullTextAreaState extends TextAreaState { return new NVDAFullTextAreaState(this, textArea.getValue(), textArea.getSelectionStart(), textArea.getSelectionEnd(), textArea.isInOverwriteMode()); } - public fromEditorSelection(model:ISimpleModel, selection:IEditorRange): TextAreaState { + public fromEditorSelection(model:ISimpleModel, selection:Range): TextAreaState { let pretext = model.getValueInRange(new Range(1, 1, selection.startLineNumber, selection.startColumn), EndOfLinePreference.LF); let text = model.getValueInRange(selection, EndOfLinePreference.LF); let lastLine = model.getLineCount(); diff --git a/src/vs/editor/common/core/editOperation.ts b/src/vs/editor/common/core/editOperation.ts index 47222ed50e8..d04c9adf585 100644 --- a/src/vs/editor/common/core/editOperation.ts +++ b/src/vs/editor/common/core/editOperation.ts @@ -5,11 +5,12 @@ 'use strict'; import {Range} from 'vs/editor/common/core/range'; -import {IEditorPosition, IEditorRange, IIdentifiedSingleEditOperation} from 'vs/editor/common/editorCommon'; +import {IIdentifiedSingleEditOperation} from 'vs/editor/common/editorCommon'; +import {Position} from 'vs/editor/common/core/position'; export class EditOperation { - public static insert(position:IEditorPosition, text:string): IIdentifiedSingleEditOperation { + public static insert(position:Position, text:string): IIdentifiedSingleEditOperation { return { identifier: null, range: new Range(position.lineNumber, position.column, position.lineNumber, position.column), @@ -18,7 +19,7 @@ export class EditOperation { }; } - public static delete(range:IEditorRange): IIdentifiedSingleEditOperation { + public static delete(range:Range): IIdentifiedSingleEditOperation { return { identifier: null, range: range, @@ -27,7 +28,7 @@ export class EditOperation { }; } - public static replace(range:IEditorRange, text:string): IIdentifiedSingleEditOperation { + public static replace(range:Range, text:string): IIdentifiedSingleEditOperation { return { identifier: null, range: range, @@ -36,7 +37,7 @@ export class EditOperation { }; } - public static replaceMove(range:IEditorRange, text:string): IIdentifiedSingleEditOperation { + public static replaceMove(range:Range, text:string): IIdentifiedSingleEditOperation { return { identifier: null, range: range, diff --git a/src/vs/editor/common/core/editorState.ts b/src/vs/editor/common/core/editorState.ts index 05230e39cfa..69ca7a864d8 100644 --- a/src/vs/editor/common/core/editorState.ts +++ b/src/vs/editor/common/core/editorState.ts @@ -5,14 +5,16 @@ 'use strict'; import * as strings from 'vs/base/common/strings'; -import {CodeEditorStateFlag, ICodeEditorState, ICommonCodeEditor, IEditorPosition, IEditorRange} from 'vs/editor/common/editorCommon'; +import {CodeEditorStateFlag, ICodeEditorState, ICommonCodeEditor} from 'vs/editor/common/editorCommon'; +import {Position} from 'vs/editor/common/core/position'; +import {Range} from 'vs/editor/common/core/range'; export class EditorState implements ICodeEditorState { private flags:CodeEditorStateFlag[]; - private position:IEditorPosition; - private selection:IEditorRange; + private position:Position; + private selection:Range; private modelVersionId:string; private scrollLeft:number; private scrollTop:number; @@ -24,7 +26,7 @@ export class EditorState implements ICodeEditorState { switch(flag) { case CodeEditorStateFlag.Value: var model = editor.getModel(); - this.modelVersionId = model ? strings.format('{0}#{1}', model.getAssociatedResource().toString(), model.getVersionId()) : null; + this.modelVersionId = model ? strings.format('{0}#{1}', model.uri.toString(), model.getVersionId()) : null; break; case CodeEditorStateFlag.Position: this.position = editor.getPosition(); diff --git a/src/vs/editor/common/core/position.ts b/src/vs/editor/common/core/position.ts index 8094514361d..861704685f6 100644 --- a/src/vs/editor/common/core/position.ts +++ b/src/vs/editor/common/core/position.ts @@ -4,9 +4,12 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {IEditorPosition, IPosition, IRange} from 'vs/editor/common/editorCommon'; +import {IPosition, IRange} from 'vs/editor/common/editorCommon'; -export class Position implements IEditorPosition { +/** + * A position in the editor. + */ +export class Position { public lineNumber: number; public column: number; @@ -16,6 +19,9 @@ export class Position implements IEditorPosition { this.column = column; } + /** + * Test if this position equals other position + */ public equals(other:IPosition): boolean { return Position.equals(this, other); } @@ -31,6 +37,9 @@ export class Position implements IEditorPosition { ); } + /** + * Test if this position is before other position. If the two positions are equal, the result will be false. + */ public isBefore(other:IPosition): boolean { return Position.isBefore(this, other); } @@ -44,6 +53,9 @@ export class Position implements IEditorPosition { return a.column < b.column; } + /** + * Test if this position is before other position. If the two positions are equal, the result will be true. + */ public isBeforeOrEqual(other:IPosition): boolean { return Position.isBeforeOrEqual(this, other); } @@ -57,6 +69,9 @@ export class Position implements IEditorPosition { return a.column <= b.column; } + /** + * Clone this position. + */ public clone(): Position { return new Position(this.lineNumber, this.column); } @@ -67,7 +82,7 @@ export class Position implements IEditorPosition { // --- - public static lift(pos:IPosition): IEditorPosition { + public static lift(pos:IPosition): Position { return new Position(pos.lineNumber, pos.column); } diff --git a/src/vs/editor/common/core/range.ts b/src/vs/editor/common/core/range.ts index ffd19f11276..b91edb000a5 100644 --- a/src/vs/editor/common/core/range.ts +++ b/src/vs/editor/common/core/range.ts @@ -6,9 +6,12 @@ 'use strict'; import {Position} from 'vs/editor/common/core/position'; -import {IEditorPosition, IEditorRange, IPosition, IRange} from 'vs/editor/common/editorCommon'; +import {IPosition, IRange} from 'vs/editor/common/editorCommon'; -export class Range implements IEditorRange { +/** + * A range in the editor. + */ +export class Range { public startLineNumber:number; public startColumn:number; @@ -29,51 +32,87 @@ export class Range implements IEditorRange { } } + /** + * Test if this range is empty. + */ public isEmpty(): boolean { return Range.isEmpty(this); } + /** + * Test if position is in this range. If the position is at the edges, will return true. + */ public containsPosition(position:IPosition): boolean { return Range.containsPosition(this, position); } + /** + * Test if range is in this range. If the range is equal to this range, will return true. + */ public containsRange(range:IRange): boolean { return Range.containsRange(this, range); } + /** + * A reunion of the two ranges. The smallest position will be used as the start point, and the largest one as the end point. + */ public plusRange(range:IRange): Range { return Range.plusRange(this, range); } + /** + * A intersection of the two ranges. + */ public intersectRanges(range:IRange): Range { return Range.intersectRanges(this, range); } + /** + * Test if this range equals other. + */ public equalsRange(other:IRange): boolean { return Range.equalsRange(this, other); } - public getEndPosition(): IEditorPosition { + /** + * Return the end position (which will be after or equal to the start position) + */ + public getEndPosition(): Position { return new Position(this.endLineNumber, this.endColumn); } - public getStartPosition(): IEditorPosition { + /** + * Return the start position (which will be before or equal to the end position) + */ + public getStartPosition(): Position { return new Position(this.startLineNumber, this.startColumn); } + /** + * Clone this range. + */ public cloneRange(): Range { return new Range(this.startLineNumber, this.startColumn, this.endLineNumber, this.endColumn); } + /** + * Transform to a user presentable string representation. + */ public toString(): string { return '[' + this.startLineNumber + ',' + this.startColumn + ' -> ' + this.endLineNumber + ',' + this.endColumn + ']'; } - public setEndPosition(endLineNumber: number, endColumn: number): IEditorRange { + /** + * Create a new range using this range's start position, and using endLineNumber and endColumn as the end position. + */ + public setEndPosition(endLineNumber: number, endColumn: number): Range { return new Range(this.startLineNumber, this.startColumn, endLineNumber, endColumn); } - public setStartPosition(startLineNumber: number, startColumn: number): IEditorRange { + /** + * Create a new range using this range's end position, and using startLineNumber and startColumn as the start position. + */ + public setStartPosition(startLineNumber: number, startColumn: number): Range { return new Range(startLineNumber, startColumn, this.endLineNumber, this.endColumn); } @@ -83,7 +122,7 @@ export class Range implements IEditorRange { // --- - public static lift(range:IRange): IEditorRange { + public static lift(range:IRange): Range { if (!range) { return null; } diff --git a/src/vs/editor/common/core/selection.ts b/src/vs/editor/common/core/selection.ts index 4412906f08b..a08ba428689 100644 --- a/src/vs/editor/common/core/selection.ts +++ b/src/vs/editor/common/core/selection.ts @@ -5,9 +5,12 @@ 'use strict'; import {Range} from 'vs/editor/common/core/range'; -import {IEditorSelection, ISelection, SelectionDirection} from 'vs/editor/common/editorCommon'; +import {ISelection, SelectionDirection} from 'vs/editor/common/editorCommon'; -export class Selection extends Range implements IEditorSelection { +/** + * A selection in the editor. + */ +export class Selection extends Range { public selectionStartLineNumber: number; public selectionStartColumn: number; public positionLineNumber: number; @@ -21,7 +24,10 @@ export class Selection extends Range implements IEditorSelection { this.positionColumn = positionColumn; } - public clone(): IEditorSelection { + /** + * Clone this selection. + */ + public clone(): Selection { return new Selection(this.selectionStartLineNumber, this.selectionStartColumn, this.positionLineNumber, this.positionColumn); } @@ -29,12 +35,18 @@ export class Selection extends Range implements IEditorSelection { return '[' + this.selectionStartLineNumber + ',' + this.selectionStartColumn + ' -> ' + this.positionLineNumber + ',' + this.positionColumn + ']'; } + /** + * Test if equals other selection. + */ public equalsSelection(other: ISelection): boolean { return ( Selection.selectionsEqual(this, other) ); } + /** + * Get directions (LTR or RTL). + */ public getDirection(): SelectionDirection { if (this.selectionStartLineNumber === this.startLineNumber && this.selectionStartColumn === this.startColumn) { return SelectionDirection.LTR; @@ -42,14 +54,20 @@ export class Selection extends Range implements IEditorSelection { return SelectionDirection.RTL; } - public setEndPosition(endLineNumber: number, endColumn: number): IEditorSelection { + /** + * Create a new selection with a different `positionLineNumber` and `positionColumn`. + */ + public setEndPosition(endLineNumber: number, endColumn: number): Selection { if (this.getDirection() === SelectionDirection.LTR) { return new Selection(this.startLineNumber, this.startColumn, endLineNumber, endColumn); } return new Selection(endLineNumber, endColumn, this.startLineNumber, this.startColumn); } - public setStartPosition(startLineNumber: number, startColumn: number): IEditorSelection { + /** + * Create a new selection with a different `selectionStartLineNumber` and `selectionStartColumn`. + */ + public setStartPosition(startLineNumber: number, startColumn: number): Selection { if (this.getDirection() === SelectionDirection.LTR) { return new Selection(startLineNumber, startColumn, this.endLineNumber, this.endColumn); } @@ -58,11 +76,11 @@ export class Selection extends Range implements IEditorSelection { // ---- - public static createSelection(selectionStartLineNumber: number, selectionStartColumn: number, positionLineNumber: number, positionColumn: number): IEditorSelection { + public static createSelection(selectionStartLineNumber: number, selectionStartColumn: number, positionLineNumber: number, positionColumn: number): Selection { return new Selection(selectionStartLineNumber, selectionStartColumn, positionLineNumber, positionColumn); } - public static liftSelection(sel:ISelection): IEditorSelection { + public static liftSelection(sel:ISelection): Selection { return new Selection(sel.selectionStartLineNumber, sel.selectionStartColumn, sel.positionLineNumber, sel.positionColumn); } @@ -103,7 +121,7 @@ export class Selection extends Range implements IEditorSelection { ); } - public static createWithDirection(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, direction:SelectionDirection): IEditorSelection { + public static createWithDirection(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, direction:SelectionDirection): Selection { if (direction === SelectionDirection.LTR) { return new Selection(startLineNumber, startColumn, endLineNumber, endColumn); diff --git a/src/vs/editor/common/editorActionEnablement.ts b/src/vs/editor/common/editorActionEnablement.ts index 934b4214fcf..1149504194d 100644 --- a/src/vs/editor/common/editorActionEnablement.ts +++ b/src/vs/editor/common/editorActionEnablement.ts @@ -5,7 +5,7 @@ 'use strict'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; -import {EventType, ICommonCodeEditor} from 'vs/editor/common/editorCommon'; +import {ICommonCodeEditor} from 'vs/editor/common/editorCommon'; export enum Behaviour { TextFocus = 1 << 0, @@ -115,15 +115,15 @@ class InternalEnablementState extends CachingEnablementState { this._callOnDispose = []; if (this._behaviour & Behaviour.TextFocus) { - this._callOnDispose.push(this.editor.addListener2(EventType.EditorTextFocus, () => this._updateTextFocus(true))); - this._callOnDispose.push(this.editor.addListener2(EventType.EditorTextBlur, () => this._updateTextFocus(false))); + this._callOnDispose.push(this.editor.onDidFocusEditorText(() => this._updateTextFocus(true))); + this._callOnDispose.push(this.editor.onDidBlurEditorText(() => this._updateTextFocus(false))); } if (this._behaviour & Behaviour.WidgetFocus) { - this._callOnDispose.push(this.editor.addListener2(EventType.EditorFocus, () => this._updateWidgetFocus(true))); - this._callOnDispose.push(this.editor.addListener2(EventType.EditorBlur, () => this._updateWidgetFocus(false))); + this._callOnDispose.push(this.editor.onDidFocusEditor(() => this._updateWidgetFocus(true))); + this._callOnDispose.push(this.editor.onDidBlurEditor(() => this._updateWidgetFocus(false))); } if (this._behaviour & Behaviour.Writeable) { - this._callOnDispose.push(this.editor.addListener2(EventType.ConfigurationChanged, (e) => this._update())); + this._callOnDispose.push(this.editor.onDidChangeConfiguration((e) => this._update())); } } @@ -168,18 +168,18 @@ class InternalEnablementState extends CachingEnablementState { */ class DescentEnablementState extends CachingEnablementState { - private _callOnDispose:Function[] = []; + private _callOnDispose:IDisposable[] = []; constructor(behaviour:Behaviour, private editor:ICommonCodeEditor, private _action:IEditorAction) { super(); if (behaviour & Behaviour.UpdateOnModelChange) { - this._callOnDispose.push(this.editor.addListener(EventType.ModelChanged, () => this.reset())); - this._callOnDispose.push(this.editor.addListener(EventType.ModelModeChanged, () => this.reset())); - this._callOnDispose.push(this.editor.addListener(EventType.ModelModeSupportChanged, () => this.reset())); + this._callOnDispose.push(this.editor.onDidChangeModel(() => this.reset())); + this._callOnDispose.push(this.editor.onDidChangeModelMode(() => this.reset())); + this._callOnDispose.push(this.editor.onDidChangeModelModeSupport(() => this.reset())); } if (behaviour & Behaviour.UpdateOnCursorPositionChange) { - this._callOnDispose.push(this.editor.addListener(EventType.CursorPositionChanged, () => this.reset())); + this._callOnDispose.push(this.editor.onDidChangeCursorPosition(() => this.reset())); } } diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 6bbb5bbed76..509eb313582 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -5,19 +5,25 @@ 'use strict'; import {IAction} from 'vs/base/common/actions'; -import Event from 'vs/base/common/event'; -import {IEventEmitter, ListenerUnbind} from 'vs/base/common/eventEmitter'; +import {IEventEmitter, BulkListenerCallback} from 'vs/base/common/eventEmitter'; import {IHTMLContentElement} from 'vs/base/common/htmlContent'; -import {KeyCode, KeyMod} from 'vs/base/common/keyCodes'; import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import {IInstantiationService, IConstructorSignature1, IConstructorSignature2} from 'vs/platform/instantiation/common/instantiation'; import {ILineContext, IMode, IModeTransition, IToken} from 'vs/editor/common/modes'; import {ViewLineToken} from 'vs/editor/common/core/viewLineToken'; import {ScrollbarVisibility} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; +import {IDisposable} from 'vs/base/common/lifecycle'; +import {Position} from 'vs/editor/common/core/position'; +import {Range} from 'vs/editor/common/core/range'; +import {Selection} from 'vs/editor/common/core/selection'; -export type KeyCode = KeyCode; -export type KeyMod = KeyMod; +/** + * @internal + */ +export interface Event { + (listener: (e: T) => any, thisArg?: any): IDisposable; +} // --- position & range @@ -35,28 +41,6 @@ export interface IPosition { column:number; } -/** - * A position in the editor. - */ -export interface IEditorPosition extends IPosition { - /** - * Test if this position equals other position - */ - equals(other:IPosition): boolean; - /** - * Test if this position is before other position. If the two positions are equal, the result will be false. - */ - isBefore(other:IPosition): boolean; - /** - * Test if this position is before other position. If the two positions are equal, the result will be true. - */ - isBeforeOrEqual(other:IPosition): boolean; - /** - * Clone this position. - */ - clone(): IEditorPosition; -} - /** * A range in the editor. This interface is suitable for serialization. */ @@ -79,61 +63,6 @@ export interface IRange { endColumn:number; } -/** - * A range in the editor. - */ -export interface IEditorRange extends IRange { - /** - * Test if this range is empty. - */ - isEmpty(): boolean; - collapseToStart():IEditorRange; - /** - * Test if position is in this range. If the position is at the edges, will return true. - */ - containsPosition(position:IPosition): boolean; - /** - * Test if range is in this range. If the range is equal to this range, will return true. - */ - containsRange(range:IRange): boolean; - /** - * A reunion of the two ranges. The smallest position will be used as the start point, and the largest one as the end point. - */ - plusRange(range:IRange): IEditorRange; - /** - * A intersection of the two ranges. - */ - intersectRanges(range:IRange): IEditorRange; - /** - * Test if this range equals other. - */ - equalsRange(other:IRange): boolean; - /** - * Return the end position (which will be after or equal to the start position) - */ - getEndPosition(): IEditorPosition; - /** - * Create a new range using this range's start position, and using endLineNumber and endColumn as the end position. - */ - setEndPosition(endLineNumber: number, endColumn: number): IEditorRange; - /** - * Return the start position (which will be before or equal to the end position) - */ - getStartPosition(): IEditorPosition; - /** - * Create a new range using this range's end position, and using startLineNumber and startColumn as the start position. - */ - setStartPosition(startLineNumber: number, startColumn: number): IEditorRange; - /** - * Clone this range. - */ - cloneRange(): IEditorRange; - /** - * Transform to a user presentable string representation. - */ - toString(): string; -} - /** * A selection in the editor. * The selection is a range that has an orientation. @@ -171,32 +100,6 @@ export enum SelectionDirection { RTL } -/** - * A selection in the editor. - */ -export interface IEditorSelection extends ISelection, IEditorRange { - /** - * Test if equals other selection. - */ - equalsSelection(other:ISelection): boolean; - /** - * Clone this selection. - */ - clone(): IEditorSelection; - /** - * Get directions (LTR or RTL). - */ - getDirection(): SelectionDirection; - /** - * Create a new selection with a different `positionLineNumber` and `positionColumn`. - */ - setEndPosition(endLineNumber: number, endColumn: number): IEditorSelection; - /** - * Create a new selection with a different `selectionStartLineNumber` and `selectionStartColumn`. - */ - setStartPosition(startLineNumber: number, startColumn: number): IEditorSelection; -} - /** * Configuration options for editor scrollbars */ @@ -994,23 +897,6 @@ export interface IConfigurationChangedEvent { */ export interface IModeSupportChangedEvent { tokenizationSupport:boolean; - occurrencesSupport:boolean; - declarationSupport:boolean; - typeDeclarationSupport:boolean; - navigateTypesSupport:boolean; - referenceSupport:boolean; - suggestSupport:boolean; - parameterHintsSupport:boolean; - extraInfoSupport:boolean; - outlineSupport:boolean; - logicalSelectionSupport:boolean; - formattingSupport:boolean; - inplaceReplaceSupport:boolean; - emitOutputSupport:boolean; - linkSupport:boolean; - configSupport:boolean; - quickFixSupport: boolean; - codeLensSupport: boolean; richEditSupport: boolean; } @@ -1109,6 +995,7 @@ export interface IModelDeltaDecoration { /** * A tracked range in the model. + * @internal */ export interface IModelTrackedRange { /** @@ -1118,7 +1005,7 @@ export interface IModelTrackedRange { /** * Range that this tracked range covers */ - range: IEditorRange; + range: Range; } /** @@ -1136,7 +1023,7 @@ export interface IModelDecoration { /** * Range that this decoration covers. */ - range: IEditorRange; + range: Range; /** * Options associated with this decoration. */ @@ -1145,6 +1032,7 @@ export interface IModelDecoration { /** * An accessor that can add, change or remove model decorations. + * @internal */ export interface IModelDecorationsChangeAccessor { /** @@ -1203,6 +1091,7 @@ export interface IWordAtPosition { /** * Range of a word inside a model. + * @internal */ export interface IWordRange { /** @@ -1215,6 +1104,9 @@ export interface IWordRange { end:number; } +/** + * @internal + */ export interface ITokenInfo { token: IToken; lineNumber: number; @@ -1222,6 +1114,9 @@ export interface ITokenInfo { endColumn: number; } +/** + * @internal + */ export interface ITokenIterator { hasNext(): boolean; next(): ITokenInfo; @@ -1277,6 +1172,7 @@ export enum EndOfLineSequence { /** * A read-only line marker in the model. + * @internal */ export interface IReadOnlyLineMarker { id: string; @@ -1306,7 +1202,7 @@ export interface IEditOperationBuilder { * @param range The range to replace (delete). May be empty to represent a simple insert. * @param text The text to replace with. May be null to represent a simple delete. */ - addEditOperation(range:IEditorRange, text:string): void; + addEditOperation(range:Range, text:string): void; /** * Track `selection` when applying edit operations. @@ -1317,7 +1213,7 @@ export interface IEditOperationBuilder { * should clamp to the previous or the next character. * @return A unique identifer. */ - trackSelection(selection:IEditorSelection, trackPreviousOnEmpty?:boolean): string; + trackSelection(selection:Selection, trackPreviousOnEmpty?:boolean): string; } /** @@ -1333,7 +1229,7 @@ export interface ICursorStateComputerData { * @param id The unique identifier returned by `trackSelection`. * @return The selection. */ - getTrackedSelection(id:string): IEditorSelection; + getTrackedSelection(id:string): Selection; } /** @@ -1352,12 +1248,13 @@ export interface ICommand { * @param helper A helper to get inverse edit operations and to get previously tracked selections. * @return The cursor state after the command executed. */ - computeCursorState(model:ITokenizedModel, helper:ICursorStateComputerData): IEditorSelection; + computeCursorState(model:ITokenizedModel, helper:ICursorStateComputerData): Selection; } /** * A single edit operation, that acts as a simple replace. * i.e. Replace text at `range` with `text` in model. + * @internal */ export interface ISingleEditOperation { /** @@ -1386,7 +1283,7 @@ export interface IIdentifiedSingleEditOperation { /** * The range to replace. This can be empty to emulate a simple insert. */ - range: IEditorRange; + range: Range; /** * The text to replace with. This can be null to emulate a simple delete. */ @@ -1410,11 +1307,12 @@ export interface ICursorStateComputer { /** * A callback that can compute the resulting cursors state after some edit operations have been executed. */ - (inverseEditOperations:IIdentifiedSingleEditOperation[]): IEditorSelection[]; + (inverseEditOperations:IIdentifiedSingleEditOperation[]): Selection[]; } /** * A list of tokens on a line. + * @internal */ export interface ILineTokens { getTokenCount(): number; @@ -1439,8 +1337,14 @@ export interface ILineTokens { */ findIndexOfOffset(offset:number): number; + /** + * @internal + */ sliceAndInflate(startOffset:number, endOffset:number, deltaStartIndex:number): ViewLineToken[]; + /** + * @internal + */ inflate(): ViewLineToken[]; } @@ -1497,6 +1401,11 @@ export interface ITextModel { */ setValue(newValue:string): void; + /** + * Replace the entire text buffer value contained in this model. + */ + setValueFromRawText(newValue:IRawText): void; + /** * Get the text stored in this model. * @param eol The end of line character preference. Defaults to `EndOfLinePreference.TextDefined`. @@ -1531,6 +1440,7 @@ export interface ITextModel { * sit in lines with length < `LONG_LINE_BOUNDARY`. Second bucket (B) is of * characters that sit in lines with length >= `LONG_LINE_BOUNDARY`. * If count(B) > count(A) return true. Returns false otherwise. + * @internal */ isDominatedByLongLines(): boolean; @@ -1582,7 +1492,7 @@ export interface ITextModel { /** * Create a valid position, */ - validatePosition(position:IPosition): IEditorPosition; + validatePosition(position:IPosition): Position; /** * Advances the given position by the given offest (negative offsets are also accepted) @@ -1594,24 +1504,66 @@ export interface ITextModel { * If the ofsset is such that the new position would be in the middle of a multi-byte * line terminator, throws an exception. */ - modifyPosition(position: IPosition, offset: number): IEditorPosition; + modifyPosition(position: IPosition, offset: number): Position; /** * Create a valid range. */ - validateRange(range:IRange): IEditorRange; + validateRange(range:IRange): Range; /** * Get a range covering the entire model */ - getFullModelRange(): IEditorRange; + getFullModelRange(): Range; /** * Returns iff the model was disposed or not. */ isDisposed(): boolean; + + /** + * No mode supports allowed on this model because it is simply too large. + * (even tokenization would cause too much memory pressure) + * @internal + */ + isTooLargeForHavingAMode(): boolean; + + /** + * Only basic mode supports allowed on this model because it is simply too large. + * (tokenization is allowed and other basic supports) + * @internal + */ + isTooLargeForHavingARichMode(): boolean; } +export interface IReadOnlyModel extends ITextModel { + /** + * Gets the resource associated with this editor model. + */ + uri: URI; + + getModeId(): string; + + /** + * Get the word under or besides `position`. + * @param position The position to look for a word. + * @param skipSyntaxTokens Ignore syntax tokens, as identified by the mode. + * @return The word under or besides `position`. Might be null. + */ + getWordAtPosition(position:IPosition): IWordAtPosition; + + /** + * Get the word under or besides `position` trimmed to `position`.column + * @param position The position to look for a word. + * @param skipSyntaxTokens Ignore syntax tokens, as identified by the mode. + * @return The word under or besides `position`. Will never be null. + */ + getWordUntilPosition(position:IPosition): IWordAtPosition; +} + +/** + * @internal + */ export interface IRichEditBracket { modeId: string; open: string; @@ -1620,8 +1572,11 @@ export interface IRichEditBracket { reversedRegex: RegExp; } +/** + * @internal + */ export interface IFoundBracket { - range: IEditorRange; + range: Range; open: string; close: string; isOpen: boolean; @@ -1636,26 +1591,20 @@ export interface ITokenizedModel extends ITextModel { * Tokenize if necessary and get the tokens for the line `lineNumber`. * @param lineNumber The line number * @param inaccurateTokensAcceptable Are inaccurate tokens acceptable? Defaults to false + * @internal */ getLineTokens(lineNumber:number, inaccurateTokensAcceptable?:boolean): ILineTokens; /** * Tokenize if necessary and get the tokenization result for the line `lineNumber`, as returned by the language mode. + * @internal */ getLineContext(lineNumber:number): ILineContext; - /*package*/_getLineModeTransitions(lineNumber:number): IModeTransition[]; - /** - * Replace the entire text buffer value contained in this model. - * Optionally, the language mode of the model can be changed. - * This call clears all of the undo / redo stack, - * removes all decorations or tracked ranges, emits a - * ModelContentChanged(ModelContentChangedFlush) event and - * unbinds the mirror model from the previous mode to the new - * one if the mode has changed. + * @internal */ - setValue(newValue:string, newMode?:IMode): void; + _getLineModeTransitions(lineNumber:number): IModeTransition[]; /** * Get the current language mode associated with the model. @@ -1665,18 +1614,20 @@ export interface ITokenizedModel extends ITextModel { /** * Set the current language mode associated with the model. */ - setMode(newMode:IMode): void; - setMode(newModePromise:TPromise): void; + setMode(newMode:IMode|TPromise): void; + /** * A mode can be currently pending loading if a promise is used when constructing a model or calling setMode(). * * If there is no currently pending loading mode, then the result promise will complete immediately. * Otherwise, the result will complete once the currently pending loading mode is loaded. + * @internal */ whenModeIsReady(): TPromise; /** * Returns the true (inner-most) language mode at a given position. + * @internal */ getModeAtPosition(lineNumber:number, column:number): IMode; @@ -1701,6 +1652,7 @@ export interface ITokenizedModel extends ITextModel { * next and previous tokens from the provided position. * The iterator is made available through the callback * function and can't be used afterwards. + * @internal */ tokenIterator(position: IPosition, callback: (it: ITokenIterator) =>any): any; @@ -1709,8 +1661,9 @@ export interface ITokenizedModel extends ITextModel { * @param request The bracket we're searching for * @param position The position at which to start the search. * @return The range of the matching bracket, or null if the bracket match was not found. + * @internal */ - findMatchingBracketUp(bracket:string, position:IPosition): IEditorRange; + findMatchingBracketUp(bracket:string, position:IPosition): Range; // /** // * Find the first bracket in the model before `position`. @@ -1730,36 +1683,44 @@ export interface ITokenizedModel extends ITextModel { * Given a `position`, if the position is on top or near a bracket, * find the matching bracket of that bracket and return the ranges of both brackets. * @param position The position at which to look for a bracket. + * @internal */ - matchBracket(position:IPosition): [IEditorRange,IEditorRange]; - - /** - * No mode supports allowed on this model because it is simply too large. - * (even tokenization would cause too much memory pressure) - */ - isTooLargeForHavingAMode(): boolean; - - /** - * Only basic mode supports allowed on this model because it is simply too large. - * (tokenization is allowed and other basic supports) - */ - isTooLargeForHavingARichMode(): boolean; + matchBracket(position:IPosition): [Range,Range]; } /** * A model that can track markers. */ export interface ITextModelWithMarkers extends ITextModel { - /*package*/_addMarker(lineNumber:number, column:number, stickToPreviousCharacter:boolean): string; - /*package*/_changeMarker(id:string, newLineNumber:number, newColumn:number): void; - /*package*/_changeMarkerStickiness(id:string, newStickToPreviousCharacter:boolean): void; - /*package*/_getMarker(id:string): IEditorPosition; - /*package*/_removeMarker(id:string): void; - /*package*/_getLineMarkers(lineNumber: number): IReadOnlyLineMarker[]; + /** + * @internal + */ + _addMarker(lineNumber:number, column:number, stickToPreviousCharacter:boolean): string; + /** + * @internal + */ + _changeMarker(id:string, newLineNumber:number, newColumn:number): void; + /** + * @internal + */ + _changeMarkerStickiness(id:string, newStickToPreviousCharacter:boolean): void; + /** + * @internal + */ + _getMarker(id:string): Position; + /** + * @internal + */ + _removeMarker(id:string): void; + /** + * @internal + */ + _getLineMarkers(lineNumber: number): IReadOnlyLineMarker[]; } /** * A map of changed ranges used during the model internal processing + * @internal */ export interface IChangedTrackedRanges { [key:string]:IRange; @@ -1781,6 +1742,7 @@ export interface ITextModelWithTrackedRanges extends ITextModel { * @param range The range to start tracking. * @param stickiness The behaviour when typing at the edges of the range. * @return A unique identifier for the tracked range. + * @internal */ addTrackedRange(range:IRange, stickiness:TrackedRangeStickiness): string; @@ -1788,6 +1750,7 @@ export interface ITextModelWithTrackedRanges extends ITextModel { * Change the range of a tracked range. * @param id The id of the tracked range, as returned by a `addTrackedRange` call. * @param newRange The new range of the tracked range. + * @internal */ changeTrackedRange(id:string, newRange:IRange): void; @@ -1795,26 +1758,30 @@ export interface ITextModelWithTrackedRanges extends ITextModel { * Change the stickiness (behaviour when typing at the edges of the range) for a tracked range. * @param id The id of the tracked range, as returned by a `addTrackedRange` call. * @param newStickiness The new behaviour when typing at the edges of the range. + * @internal */ changeTrackedRangeStickiness(id:string, newStickiness:TrackedRangeStickiness): void; /** * Remove a tracked range. * @param id The id of the tracked range, as returned by a `addTrackedRaneg` call. + * @internal */ removeTrackedRange(id:string): void; /** * Get the range of a tracked range. * @param id The id of the tracked range, as returned by a `addTrackedRaneg` call. + * @internal */ - getTrackedRange(id:string): IEditorRange; + getTrackedRange(id:string): Range; /** * Gets all the tracked ranges for the lines between `startLineNumber` and `endLineNumber` as an array. * @param startLineNumber The start line number * @param endLineNumber The end line number * @return An array with the tracked ranges + * @internal */ getLinesTrackedRanges(startLineNumber:number, endLineNumber:number): IModelTrackedRange[]; } @@ -1829,6 +1796,7 @@ export interface ITextModelWithDecorations { * This allows for all events to be queued up until the change * is completed. Returns whatever the callback returns. * @param ownerId Identifies the editor id in which these decorations should appear. If no `ownerId` is provided, the decorations will appear in all editors that attach this model. + * @internal */ changeDecorations(callback: (changeAccessor:IModelDecorationsChangeAccessor)=>any, ownerId?:number): any; @@ -1847,6 +1815,7 @@ export interface ITextModelWithDecorations { /** * Remove all decorations that have been added with this specific ownerId. * @param ownerId The owner id to search for. + * @internal */ removeAllDecorationsWithOwnerId(ownerId:number): void; @@ -1862,7 +1831,7 @@ export interface ITextModelWithDecorations { * @param id The decoration id. * @return The decoration range or null if the decoration was not found. */ - getDecorationRange(id:string): IEditorRange; + getDecorationRange(id:string): Range; /** * Gets all the decorations for the line `lineNumber` as an array. @@ -1929,7 +1898,7 @@ export interface IEditableTextModel extends ITextModelWithMarkers { * @param cursorStateComputer A callback that can compute the resulting cursors state after the edit operations have been executed. * @return The cursor state returned by the `cursorStateComputer`. */ - pushEditOperations(beforeCursorState:IEditorSelection[], editOperations:IIdentifiedSingleEditOperation[], cursorStateComputer:ICursorStateComputer): IEditorSelection[]; + pushEditOperations(beforeCursorState:Selection[], editOperations:IIdentifiedSingleEditOperation[], cursorStateComputer:ICursorStateComputer): Selection[]; /** * Edit the model without adding the edits to the undo stack. @@ -1942,35 +1911,51 @@ export interface IEditableTextModel extends ITextModelWithMarkers { /** * Undo edit operations until the first previous stop point created by `pushStackElement`. * The inverse edit operations will be pushed on the redo stack. + * @internal */ - undo(): IEditorSelection[]; + undo(): Selection[]; /** * Redo edit operations until the next stop point created by `pushStackElement`. * The inverse edit operations will be pushed on the undo stack. + * @internal */ - redo(): IEditorSelection[]; + redo(): Selection[]; /** * Set an editable range on the model. + * @internal */ setEditableRange(range:IRange): void; /** * Check if the model has an editable range. + * @internal */ hasEditableRange(): boolean; /** * Get the editable range on the model. + * @internal */ - getEditableRange(): IEditorRange; + getEditableRange(): Range; } /** * A model. */ -export interface IModel extends IEditableTextModel, ITextModelWithMarkers, ITokenizedModel, ITextModelWithTrackedRanges, ITextModelWithDecorations, IEventEmitter, IEditorModel { +export interface IModel extends IReadOnlyModel, IEditableTextModel, ITextModelWithMarkers, ITokenizedModel, ITextModelWithTrackedRanges, ITextModelWithDecorations, IEditorModel { + + onDidChangeRawContent(listener: (e:IModelContentChangedEvent)=>void): IDisposable; + onDidChangeContent(listener: (e:IModelContentChangedEvent2)=>void): IDisposable; + onDidChangeModeSupport(listener: (e:IModeSupportChangedEvent)=>void): IDisposable; + onDidChangeDecorations(listener: (e:IModelDecorationsChangedEvent)=>void): IDisposable; + onDidChangeOptions(listener: (e:IModelOptionsChangedEvent)=>void): IDisposable; + onDidChangeMode(listener: (e:IModelModeChangedEvent)=>void): IDisposable; + onWillDispose(listener: ()=>void): IDisposable; + + addBulkListener(listener:BulkListenerCallback):IDisposable; + /** * A unique identifier associated with this model. */ @@ -1979,13 +1964,15 @@ export interface IModel extends IEditableTextModel, ITextModelWithMarkers, IToke /** * Destroy this model. This will unbind the model from the mode * and make all necessary clean-up to release this object to the GC. + * @internal */ destroy(): void; /** - * Gets the resource associated with this editor model. + * Destroy this model. This will unbind the model from the mode + * and make all necessary clean-up to release this object to the GC. */ - getAssociatedResource(): URI; + dispose(): void; /** * Search the model. @@ -1997,7 +1984,7 @@ export interface IModel extends IEditableTextModel, ITextModelWithMarkers, IToke * @param limitResultCount Limit the number of results * @return The ranges where the matches are. It is empty if not matches have been found. */ - findMatches(searchString:string, searchOnlyEditableRange:boolean, isRegex:boolean, matchCase:boolean, wholeWord:boolean, limitResultCount?:number): IEditorRange[]; + findMatches(searchString:string, searchOnlyEditableRange:boolean, isRegex:boolean, matchCase:boolean, wholeWord:boolean, limitResultCount?:number): Range[]; /** * Search the model. * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true. @@ -2008,7 +1995,7 @@ export interface IModel extends IEditableTextModel, ITextModelWithMarkers, IToke * @param limitResultCount Limit the number of results * @return The ranges where the matches are. It is empty if no matches have been found. */ - findMatches(searchString:string, searchScope:IRange, isRegex:boolean, matchCase:boolean, wholeWord:boolean, limitResultCount?:number): IEditorRange[]; + findMatches(searchString:string, searchScope:IRange, isRegex:boolean, matchCase:boolean, wholeWord:boolean, limitResultCount?:number): Range[]; /** * Search the model for the next match. Loops to the beginning of the model if needed. * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true. @@ -2018,7 +2005,7 @@ export interface IModel extends IEditableTextModel, ITextModelWithMarkers, IToke * @param wholeWord Force the matching to match entire words only. * @return The range where the next match is. It is null if no next match has been found. */ - findNextMatch(searchString:string, searchStart:IPosition, isRegex:boolean, matchCase:boolean, wholeWord:boolean): IEditorRange; + findNextMatch(searchString:string, searchStart:IPosition, isRegex:boolean, matchCase:boolean, wholeWord:boolean): Range; /** * Search the model for the previous match. Loops to the end of the model if needed. * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true. @@ -2028,45 +2015,41 @@ export interface IModel extends IEditableTextModel, ITextModelWithMarkers, IToke * @param wholeWord Force the matching to match entire words only. * @return The range where the previous match is. It is null if no previous match has been found. */ - findPreviousMatch(searchString:string, searchStart:IPosition, isRegex:boolean, matchCase:boolean, wholeWord:boolean): IEditorRange; + findPreviousMatch(searchString:string, searchStart:IPosition, isRegex:boolean, matchCase:boolean, wholeWord:boolean): Range; /** - * Replace the entire text buffer value contained in this model. - * Optionally, the language mode of the model can be changed. - * This call clears all of the undo / redo stack, - * removes all decorations or tracked ranges, emits a - * ModelContentChanged(ModelContentChangedFlush) event and - * unbinds the mirror model from the previous mode to the new - * one if the mode has changed. + * @internal */ - setValue(newValue:string, newMode?:IMode): void; - setValue(newValue:string, newModePromise:TPromise): void; - - setValueFromRawText(newValue:IRawText, newMode?:IMode): void; - setValueFromRawText(newValue:IRawText, newModePromise:TPromise): void; - onBeforeAttached(): void; + /** + * @internal + */ onBeforeDetached(): void; - getModeId(): string; - /** * Returns iff this model is attached to an editor or not. + * @internal */ isAttachedToEditor(): boolean; } +/** + * @internal + */ export interface IRangeWithText { text:string; range:IRange; } +/** + * @internal + */ export interface IMirrorModel extends IEventEmitter, ITokenizedModel { getEmbeddedAtPosition(position:IPosition): IMirrorModel; getAllEmbedded(): IMirrorModel[]; - getAssociatedResource(): URI; + uri: URI; getOffsetFromPosition(position:IPosition): number; getPositionFromOffset(offset:number): IPosition; @@ -2076,6 +2059,8 @@ export interface IMirrorModel extends IEventEmitter, ITokenizedModel { getAllWordsWithRange(): IRangeWithText[]; getAllUniqueWords(skipWordOnce?:string): string[]; + + getModeId(): string; } /** @@ -2264,19 +2249,19 @@ export interface ICursorPositionChangedEvent { /** * Primary cursor's position. */ - position:IEditorPosition; + position:Position; /** * Primary cursor's view position */ - viewPosition:IEditorPosition; + viewPosition:Position; /** * Secondary cursors' position. */ - secondaryPositions:IEditorPosition[]; + secondaryPositions:Position[]; /** * Secondary cursors' view position. */ - secondaryViewPositions:IEditorPosition[]; + secondaryViewPositions:Position[]; /** * Reason. */ @@ -2297,19 +2282,19 @@ export interface ICursorSelectionChangedEvent { /** * The primary selection. */ - selection:IEditorSelection; + selection:Selection; /** * The primary selection in view coordinates. */ - viewSelection:IEditorSelection; + viewSelection:Selection; /** * The secondary selections. */ - secondarySelections:IEditorSelection[]; + secondarySelections:Selection[]; /** * The secondary selections in view coordinates. */ - secondaryViewSelections:IEditorSelection[]; + secondaryViewSelections:Selection[]; /** * Source of the call that caused the event. */ @@ -2319,6 +2304,9 @@ export interface ICursorSelectionChangedEvent { */ reason:CursorChangeReason; } +/** + * @internal + */ export enum VerticalRevealType { Simple = 0, Center = 1, @@ -2326,16 +2314,17 @@ export enum VerticalRevealType { } /** * An event describing a request to reveal a specific range in the view of the editor. + * @internal */ export interface ICursorRevealRangeEvent { /** * Range to be reavealed. */ - range:IEditorRange; + range:Range; /** * View range to be reavealed. */ - viewRange:IEditorRange; + viewRange:Range; verticalType: VerticalRevealType; /** @@ -2345,6 +2334,9 @@ export interface ICursorRevealRangeEvent { revealHorizontal:boolean; } +/** + * @internal + */ export interface ICursorScrollRequestEvent { deltaLines: number; } @@ -2354,6 +2346,9 @@ export interface IModelChangedEvent { newModelUrl: string; } +/** + * @internal + */ export interface IEditorWhitespace { id:number; afterLineNumber:number; @@ -2737,6 +2732,7 @@ export interface ILineChange extends IChange { } /** * Information about a line in the diff editor + * @internal */ export interface IDiffLineInformation { equivalentLineNumber: number; @@ -2744,10 +2740,16 @@ export interface IDiffLineInformation { export const KEYBINDING_CONTEXT_EDITOR_TEXT_FOCUS = 'editorTextFocus'; export const KEYBINDING_CONTEXT_EDITOR_FOCUS = 'editorFocus'; +/** + * @internal + */ export const KEYBINDING_CONTEXT_EDITOR_TAB_MOVES_FOCUS = 'editorTabMovesFocus'; export const KEYBINDING_CONTEXT_EDITOR_HAS_MULTIPLE_SELECTIONS = 'editorHasMultipleSelections'; export const KEYBINDING_CONTEXT_EDITOR_HAS_NON_EMPTY_SELECTION = 'editorHasSelection'; export const KEYBINDING_CONTEXT_EDITOR_LANGUAGE_ID = 'editorLangId'; +/** + * @internal + */ export const SHOW_ACCESSIBILITY_HELP_ACTION_ID = 'editor.action.showAccessibilityHelp'; export class BareFontInfo { @@ -2813,6 +2815,9 @@ export class FontInfo extends BareFontInfo { } } +/** + * @internal + */ export interface IConfiguration { onDidChange: Event; @@ -2823,6 +2828,9 @@ export interface IConfiguration { // --- view +/** + * @internal + */ export interface IViewEventNames { ModelFlushedEvent: string; LinesDeletedEvent: string; @@ -2836,6 +2844,9 @@ export interface IViewEventNames { LineMappingChangedEvent: string; } +/** + * @internal + */ export var ViewEventNames = { ModelFlushedEvent: 'modelFlushedEvent', LinesDeletedEvent: 'linesDeletedEvent', @@ -2867,6 +2878,9 @@ export interface INewScrollPosition { scrollTop?: number; } +/** + * @internal + */ export interface IViewLinesDeletedEvent { /** * At what line the deletion began (inclusive). @@ -2878,6 +2892,9 @@ export interface IViewLinesDeletedEvent { toLineNumber: number; } +/** + * @internal + */ export interface IViewLinesInsertedEvent { /** * Before what line did the insertion begin @@ -2889,6 +2906,9 @@ export interface IViewLinesInsertedEvent { toLineNumber: number; } +/** + * @internal + */ export interface IViewLineChangedEvent { /** * The line that has changed. @@ -2896,6 +2916,9 @@ export interface IViewLineChangedEvent { lineNumber: number; } +/** + * @internal + */ export interface IViewTokensChangedEvent { /** * Start line number of range @@ -2907,6 +2930,9 @@ export interface IViewTokensChangedEvent { toLineNumber: number; } +/** + * @internal + */ export interface IViewDecorationsChangedEvent { /** * signals that at least one inline decoration has changed @@ -2914,37 +2940,46 @@ export interface IViewDecorationsChangedEvent { inlineDecorationsChanged: boolean; } +/** + * @internal + */ export interface IViewCursorPositionChangedEvent { /** * Primary cursor's position. */ - position: IEditorPosition; + position: Position; /** * Secondary cursors' position. */ - secondaryPositions: IEditorPosition[]; + secondaryPositions: Position[]; /** * Is the primary cursor in the editable range? */ isInEditableRange: boolean; } +/** + * @internal + */ export interface IViewCursorSelectionChangedEvent { /** * The primary selection. */ - selection: IEditorSelection; + selection: Selection; /** * The secondary selections. */ - secondarySelections: IEditorSelection[]; + secondarySelections: Selection[]; } +/** + * @internal + */ export interface IViewRevealRangeEvent { /** * Range to be reavealed. */ - range: IEditorRange; + range: Range; verticalType: VerticalRevealType; /** @@ -2954,10 +2989,16 @@ export interface IViewRevealRangeEvent { revealHorizontal: boolean; } +/** + * @internal + */ export interface IViewScrollRequestEvent { deltaLines: number; } +/** + * @internal + */ export interface IViewWhitespaceViewportData { id:number; afterLineNumber:number; @@ -2965,6 +3006,9 @@ export interface IViewWhitespaceViewportData { height:number; } +/** + * @internal + */ export class Viewport { _viewportBrand: void; @@ -3022,6 +3066,7 @@ export interface IActionDescriptor { /** * Data associated with an editor action contribution + * @internal */ export interface IEditorActionDescriptorData { id:string; @@ -3029,12 +3074,19 @@ export interface IEditorActionDescriptorData { alias?:string; } +/** + * @internal + */ export type IEditorActionContributionCtor = IConstructorSignature2; +/** + * @internal + */ export type ICommonEditorContributionCtor = IConstructorSignature1; /** * An editor contribution descriptor that will be used to construct editor contributions + * @internal */ export interface ICommonEditorContributionDescriptor { /** @@ -3046,7 +3098,18 @@ export interface ICommonEditorContributionDescriptor { /** * An editor. */ -export interface IEditor extends IEventEmitter { +export interface IEditor { + + onDidChangeModelRawContent(listener: (e:IModelContentChangedEvent)=>void): IDisposable; + onDidChangeModelContent(listener: (e:IModelContentChangedEvent2)=>void): IDisposable; + onDidChangeModelMode(listener: (e:IModelModeChangedEvent)=>void): IDisposable; + onDidChangeModelOptions(listener: (e:IModelOptionsChangedEvent)=>void): IDisposable; + onDidChangeConfiguration(listener: (e:IConfigurationChangedEvent)=>void): IDisposable; + onDidChangeCursorPosition(listener: (e:ICursorPositionChangedEvent)=>void): IDisposable; + onDidChangeCursorSelection(listener: (e:ICursorSelectionChangedEvent)=>void): IDisposable; + onDidDispose(listener: ()=>void): IDisposable; + + dispose(): void; getId(): string; @@ -3060,6 +3123,7 @@ export interface IEditor extends IEventEmitter { /** * Destroy the editor. + * @internal */ destroy(): void; @@ -3070,11 +3134,13 @@ export interface IEditor extends IEventEmitter { /** * Indicates that the editor becomes visible. + * @internal */ onVisible(): void; /** * Indicates that the editor becomes hidden. + * @internal */ onHide(): void; @@ -3085,7 +3151,7 @@ export interface IEditor extends IEventEmitter { layout(dimension?:IDimension): void; /** - * Brings browser focus to the editor + * Brings browser focus to the editor text */ focus(): void; @@ -3122,7 +3188,7 @@ export interface IEditor extends IEventEmitter { /** * Returns the primary position of the cursor. */ - getPosition(): IEditorPosition; + getPosition(): Position; /** * Set the primary position of the cursor. This will remove any secondary cursors. @@ -3163,21 +3229,21 @@ export interface IEditor extends IEventEmitter { /** * Returns the primary selection of the editor. */ - getSelection(): IEditorSelection; + getSelection(): Selection; /** * Returns all the selections of the editor. */ - getSelections(): IEditorSelection[]; + getSelections(): Selection[]; /** * Set the primary selection of the editor. This will remove any secondary cursors. * @param selection The new selection */ setSelection(selection:IRange): void; - setSelection(selection:IEditorRange): void; + setSelection(selection:Range): void; setSelection(selection:ISelection): void; - setSelection(selection:IEditorSelection): void; + setSelection(selection:Selection): void; /** * Set the selections for all the cursors of the editor. @@ -3244,14 +3310,21 @@ export interface IEditor extends IEventEmitter { * will get the ownerId of the editor (meaning they will not show up in other * editors). * @see IModel.changeDecorations + * @internal */ changeDecorations(callback: (changeAccessor:IModelDecorationsChangeAccessor)=>any): any; } +/** + * @internal + */ export interface ICodeEditorState { validate(editor:ICommonCodeEditor): boolean; } +/** + * @internal + */ export enum CodeEditorStateFlag { Value, Selection, @@ -3281,6 +3354,9 @@ export interface IEditorContribution { restoreViewState?(state: any): void; } +/** + * @internal + */ export interface IThemeDecorationRenderOptions { backgroundColor?: string; @@ -3304,6 +3380,9 @@ export interface IThemeDecorationRenderOptions { overviewRulerColor?: string; } +/** + * @internal + */ export interface IDecorationRenderOptions extends IThemeDecorationRenderOptions { isWholeLine?: boolean; overviewRulerLane?: OverviewRulerLane; @@ -3312,6 +3391,9 @@ export interface IDecorationRenderOptions extends IThemeDecorationRenderOptions dark?: IThemeDecorationRenderOptions; } +/** + * @internal + */ export interface IRangeWithMessage { range: IRange; hoverMessage?: IHTMLContentElement[]; @@ -3319,6 +3401,16 @@ export interface IRangeWithMessage { export interface ICommonCodeEditor extends IEditor { + onDidChangeModel(listener: (e:IModelChangedEvent)=>void): IDisposable; + onDidChangeModelModeSupport(listener: (e:IModeSupportChangedEvent)=>void): IDisposable; + onDidChangeModelDecorations(listener: (e:IModelDecorationsChangedEvent)=>void): IDisposable; + + onDidFocusEditorText(listener: ()=>void): IDisposable; + onDidBlurEditorText(listener: ()=>void): IDisposable; + + onDidFocusEditor(listener: ()=>void): IDisposable; + onDidBlurEditor(listener: ()=>void): IDisposable; + /** * Returns true if this editor or one of its widgets has keyboard focus. */ @@ -3331,6 +3423,9 @@ export interface ICommonCodeEditor extends IEditor { */ getContribution(id: string): IEditorContribution; + /** + * @internal + */ captureState(...flags:CodeEditorStateFlag[]): ICodeEditorState; /** @@ -3345,6 +3440,7 @@ export interface ICommonCodeEditor extends IEditor { /** * Returns the 'raw' editor's configuration, as it was applied over the defaults, but without any computed members. + * @internal */ getRawConfiguration(): IEditorOptions; @@ -3425,13 +3521,19 @@ export interface ICommonCodeEditor extends IEditor { getLineDecorations(lineNumber: number): IModelDecoration[]; /** - * All decorations added through this call wii get the ownerId of this editor. + * All decorations added through this call will get the ownerId of this editor. * @see IModel.deltaDecorations */ deltaDecorations(oldDecorations: string[], newDecorations: IModelDeltaDecoration[]): string[]; + /** + * @internal + */ setDecorations(decorationTypeKey: string, ranges:IRangeWithMessage[]): void; + /** + * @internal + */ removeDecorations(decorationTypeKey:string): void; /** @@ -3443,11 +3545,13 @@ export interface ICommonCodeEditor extends IEditor { * Prevent the editor from sending a widgetFocusLost event, * set it in a state where it believes that focus is in one of its widgets. * Use this method with care and always add a matching `endForcedWidgetFocus` + * @internal */ beginForcedWidgetFocus(): void; /** * End the preventing of sending a widgetFocusLost event. + * @internal */ endForcedWidgetFocus(): void; @@ -3456,12 +3560,15 @@ export interface ICommonCodeEditor extends IEditor { * The callback should not do operations on the view, as the view might not be updated to reflect previous typed characters. * @param character Character to listen to. * @param callback Function to call when `character` is typed. + * @internal */ - addTypingListener(character: string, callback: () => void): ListenerUnbind; + addTypingListener(character: string, callback: () => void): IDisposable; } export interface ICommonDiffEditor extends IEditor { + onDidUpdateDiff(listener: ()=>void): IDisposable; + /** * Type the getModel() of IEditor. */ @@ -3475,11 +3582,13 @@ export interface ICommonDiffEditor extends IEditor { /** * Get information based on computed diff about a line number from the original model. * If the diff computation is not finished or the model is missing, will return null. + * @internal */ getDiffLineInformationForOriginal(lineNumber:number): IDiffLineInformation; /** * Get information based on computed diff about a line number from the modified model. * If the diff computation is not finished or the model is missing, will return null. + * @internal */ getDiffLineInformationForModified(lineNumber:number): IDiffLineInformation; @@ -3490,10 +3599,12 @@ export interface ICommonDiffEditor extends IEditor { /** * Returns whether the diff editor is ignoring trim whitespace or not. + * @internal */ ignoreTrimWhitespace: boolean; /** * Returns whether the diff editor is rendering side by side or not. + * @internal */ renderSideBySide: boolean; } @@ -3503,6 +3614,9 @@ export var EditorType = { IDiffEditor: 'vs.editor.IDiffEditor' }; +/** + * @internal + */ export var ClassName = { EditorWarningDecoration: 'greensquiggly', EditorErrorDecoration: 'redsquiggly' @@ -3521,12 +3635,12 @@ export var EventType = { ModelModeChanged: 'modelsModeChanged', ModelModeSupportChanged: 'modelsModeSupportChanged', ModelOptionsChanged: 'modelOptionsChanged', - ModelContentChanged: 'contentChanged', + ModelRawContentChanged: 'contentChanged', ModelContentChanged2: 'contentChanged2', - ModelContentChangedFlush: 'flush', - ModelContentChangedLinesDeleted: 'linesDeleted', - ModelContentChangedLinesInserted: 'linesInserted', - ModelContentChangedLineChanged: 'lineChanged', + ModelRawContentChangedFlush: 'flush', + ModelRawContentChangedLinesDeleted: 'linesDeleted', + ModelRawContentChangedLinesInserted: 'linesInserted', + ModelRawContentChangedLineChanged: 'lineChanged', EditorTextBlur: 'blur', EditorTextFocus: 'focus', @@ -3685,6 +3799,9 @@ export enum TextEditorCursorStyle { Underline = 3 } +/** + * @internal + */ export function cursorStyleToString(cursorStyle:TextEditorCursorStyle): string { if (cursorStyle === TextEditorCursorStyle.Line) { return 'line'; @@ -3696,3 +3813,104 @@ export function cursorStyleToString(cursorStyle:TextEditorCursorStyle): string { throw new Error('cursorStyleToString: Unknown cursorStyle'); } } + +/** + * @internal + */ +export class ColorZone { + _colorZoneBrand: void; + + from: number; + to: number; + colorId: number; + position: OverviewRulerLane; + + constructor(from:number, to:number, colorId:number, position: OverviewRulerLane) { + this.from = from|0; + this.to = to|0; + this.colorId = colorId|0; + this.position = position|0; + } +} + +/** + * A zone in the overview ruler + * @internal + */ +export class OverviewRulerZone { + _overviewRulerZoneBrand: void; + + startLineNumber: number; + endLineNumber: number; + position: OverviewRulerLane; + forceHeight: number; + + private _color: string; + private _darkColor: string; + + private _colorZones: ColorZone[]; + + constructor( + startLineNumber: number, endLineNumber: number, + position: OverviewRulerLane, + forceHeight: number, + color: string, darkColor: string + ) { + this.startLineNumber = startLineNumber; + this.endLineNumber = endLineNumber; + this.position = position; + this.forceHeight = forceHeight; + this._color = color; + this._darkColor = darkColor; + this._colorZones = null; + } + + public getColor(useDarkColor:boolean): string { + if (useDarkColor) { + return this._darkColor; + } + return this._color; + } + + public equals(other:OverviewRulerZone): boolean { + return ( + this.startLineNumber === other.startLineNumber + && this.endLineNumber === other.endLineNumber + && this.position === other.position + && this.forceHeight === other.forceHeight + && this._color === other._color + && this._darkColor === other._darkColor + ); + } + + public compareTo(other:OverviewRulerZone): number { + if (this.startLineNumber === other.startLineNumber) { + if (this.endLineNumber === other.endLineNumber) { + if (this.forceHeight === other.forceHeight) { + if (this.position === other.position) { + if (this._darkColor === other._darkColor) { + if (this._color === other._color) { + return 0; + } + return this._color < other._color ? -1 : 1; + } + return this._darkColor < other._darkColor ? -1 : 1; + } + return this.position - other.position; + } + return this.forceHeight - other.forceHeight; + } + return this.endLineNumber - other.endLineNumber; + } + return this.startLineNumber - other.startLineNumber; + } + + public setColorZones(colorZones:ColorZone[]): void { + this._colorZones = colorZones; + } + + public getColorZones(): ColorZone[] { + return this._colorZones; + } +} + diff --git a/src/vs/editor/common/editorCommonExtensions.ts b/src/vs/editor/common/editorCommonExtensions.ts index f9ff6b55175..936286c53ed 100644 --- a/src/vs/editor/common/editorCommonExtensions.ts +++ b/src/vs/editor/common/editorCommonExtensions.ts @@ -102,7 +102,7 @@ export module CommonEditorRegistry { }); } - export function registerDefaultLanguageCommand(id: string, handler: (model: editorCommon.IModel, position: editorCommon.IPosition, args: { [n: string]: any }) => any) { + export function registerDefaultLanguageCommand(id: string, handler: (model: editorCommon.IModel, position: Position, args: { [n: string]: any }) => any) { registerLanguageCommand(id, function(accessor, args) { const {resource, position} = args; @@ -115,7 +115,9 @@ export module CommonEditorRegistry { throw illegalArgument(); } - return handler(model, position, args); + const editorPosition = Position.lift(position); + + return handler(model, editorPosition, args); }); } } diff --git a/src/vs/editor/common/languages.common.ts b/src/vs/editor/common/languages.common.ts index 9a688fbc112..76bf17a9d9b 100644 --- a/src/vs/editor/common/languages.common.ts +++ b/src/vs/editor/common/languages.common.ts @@ -32,11 +32,10 @@ import 'vs/editor/common/editorCommon'; import 'vs/editor/common/modes'; import 'vs/editor/common/modes/abstractMode'; import 'vs/editor/common/modes/abstractState'; -import 'vs/editor/common/modes/monarch/monarch'; +import 'vs/editor/common/modes/monarch/monarchCommon'; +import 'vs/editor/common/modes/monarch/monarchDefinition'; +import 'vs/editor/common/modes/monarch/monarchLexer'; import 'vs/editor/common/modes/monarch/monarchCompile'; -import 'vs/editor/common/modes/supports/declarationSupport'; -import 'vs/editor/common/modes/supports/parameterHintsSupport'; -import 'vs/editor/common/modes/supports/referenceSupport'; import 'vs/editor/common/modes/supports/richEditSupport'; import 'vs/editor/common/modes/supports/suggestSupport'; import 'vs/editor/common/modes/supports/tokenizationSupport'; diff --git a/src/vs/editor/common/model/editStack.ts b/src/vs/editor/common/model/editStack.ts index f0962253650..760545d9521 100644 --- a/src/vs/editor/common/model/editStack.ts +++ b/src/vs/editor/common/model/editStack.ts @@ -5,7 +5,8 @@ 'use strict'; import {onUnexpectedError} from 'vs/base/common/errors'; -import {ICursorStateComputer, IEditableTextModel, IEditorSelection, IIdentifiedSingleEditOperation} from 'vs/editor/common/editorCommon'; +import {ICursorStateComputer, IEditableTextModel, IIdentifiedSingleEditOperation} from 'vs/editor/common/editorCommon'; +import {Selection} from 'vs/editor/common/core/selection'; interface IEditOperation { operations: IIdentifiedSingleEditOperation[]; @@ -13,16 +14,16 @@ interface IEditOperation { interface IStackElement { beforeVersionId: number; - beforeCursorState: IEditorSelection[]; + beforeCursorState: Selection[]; editOperations: IEditOperation[]; - afterCursorState: IEditorSelection[]; + afterCursorState: Selection[]; afterVersionId: number; } export interface IUndoRedoResult { - selections: IEditorSelection[]; + selections: Selection[]; recordedVersionId: number; } @@ -53,7 +54,7 @@ export class EditStack { this.future = []; } - public pushEditOperation(beforeCursorState: IEditorSelection[], editOperations:IIdentifiedSingleEditOperation[], cursorStateComputer:ICursorStateComputer): IEditorSelection[] { + public pushEditOperation(beforeCursorState: Selection[], editOperations:IIdentifiedSingleEditOperation[], cursorStateComputer:ICursorStateComputer): Selection[] { // No support for parallel universes :( this.future = []; diff --git a/src/vs/editor/common/model/editableTextModel.ts b/src/vs/editor/common/model/editableTextModel.ts index cdb3f8eb128..630ccd9b553 100644 --- a/src/vs/editor/common/model/editableTextModel.ts +++ b/src/vs/editor/common/model/editableTextModel.ts @@ -12,11 +12,13 @@ import {ILineEdit, ILineMarker, ModelLine} from 'vs/editor/common/model/modelLin import {DeferredEventsBuilder, TextModelWithDecorations} from 'vs/editor/common/model/textModelWithDecorations'; import {IMode} from 'vs/editor/common/modes'; import * as strings from 'vs/base/common/strings'; +import {Selection} from 'vs/editor/common/core/selection'; +import {IDisposable} from 'vs/base/common/lifecycle'; export interface IValidatedEditOperation { sortIndex: number; identifier: editorCommon.ISingleEditOperationIdentifier; - range: editorCommon.IEditorRange; + range: Range; rangeLength: number; lines: string[]; forceMoveMarkers: boolean; @@ -29,6 +31,13 @@ interface IIdentifiedLineEdit extends ILineEdit{ export class EditableTextModel extends TextModelWithDecorations implements editorCommon.IEditableTextModel { + public onDidChangeRawContent(listener: (e:editorCommon.IModelContentChangedEvent)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.ModelRawContentChanged, listener); + } + public onDidChangeContent(listener: (e:editorCommon.IModelContentChangedEvent2)=>void): IDisposable { + return this.addListener2(editorCommon.EventType.ModelContentChanged2, listener); + } + private _commandManager:EditStack; // for extra details about change events: @@ -42,7 +51,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito private _trimAutoWhitespaceLines: number[]; constructor(allowedEventTypes:string[], rawText:editorCommon.IRawText, modeOrPromise:IMode|TPromise) { - allowedEventTypes.push(editorCommon.EventType.ModelContentChanged); + allowedEventTypes.push(editorCommon.EventType.ModelRawContentChanged); allowedEventTypes.push(editorCommon.EventType.ModelContentChanged2); super(allowedEventTypes, rawText, modeOrPromise); @@ -75,7 +84,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito this._commandManager.pushStackElement(); } - public pushEditOperations(beforeCursorState:editorCommon.IEditorSelection[], editOperations:editorCommon.IIdentifiedSingleEditOperation[], cursorStateComputer:editorCommon.ICursorStateComputer): editorCommon.IEditorSelection[] { + public pushEditOperations(beforeCursorState:Selection[], editOperations:editorCommon.IIdentifiedSingleEditOperation[], cursorStateComputer:editorCommon.ICursorStateComputer): Selection[] { return this.deferredEmit(() => { if (this._options.trimAutoWhitespace && this._trimAutoWhitespaceLines) { // Go through each saved line number and insert a trim whitespace edit @@ -336,8 +345,8 @@ export class EditableTextModel extends TextModelWithDecorations implements edito /** * Assumes `operations` are validated and sorted ascending */ - public static _getInverseEditRanges(operations:IValidatedEditOperation[]): editorCommon.IEditorRange[] { - let result:editorCommon.IEditorRange[] = []; + public static _getInverseEditRanges(operations:IValidatedEditOperation[]): Range[] { + let result:Range[] = []; let prevOpEndLineNumber: number; let prevOpEndColumn: number; @@ -361,7 +370,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito startColumn = op.range.startColumn; } - let resultRange: editorCommon.IEditorRange; + let resultRange: Range; if (op.lines && op.lines.length > 0) { // the operation inserts something @@ -593,7 +602,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito } for (let i = 0, len = contentChangedEvents.length; i < len; i++) { - this.emit(editorCommon.EventType.ModelContentChanged, contentChangedEvents[i]); + this.emit(editorCommon.EventType.ModelRawContentChanged, contentChangedEvents[i]); } for (let i = 0, len = contentChanged2Events.length; i < len; i++) { this.emit(editorCommon.EventType.ModelContentChanged2, contentChanged2Events[i]); @@ -631,7 +640,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito } } - public undo(): editorCommon.IEditorSelection[] { + public undo(): Selection[] { return this._withDeferredEvents(() => { this._isUndoing = true; let r = this._commandManager.undo(); @@ -647,7 +656,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito }); } - public redo(): editorCommon.IEditorSelection[] { + public redo(): Selection[] { return this._withDeferredEvents(() => { this._isRedoing = true; let r = this._commandManager.redo(); @@ -681,7 +690,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito return this._hasEditableRange; } - public getEditableRange(): editorCommon.IEditorRange { + public getEditableRange(): Range { if (this._hasEditableRange) { return this.getTrackedRange(this._editableRangeId); } else { @@ -691,7 +700,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito private _createLineChangedEvent(lineNumber: number): editorCommon.IModelContentChangedLineChangedEvent { return { - changeType: editorCommon.EventType.ModelContentChangedLineChanged, + changeType: editorCommon.EventType.ModelRawContentChangedLineChanged, lineNumber: lineNumber, detail: this._lines[lineNumber - 1].text, versionId: -1, @@ -702,7 +711,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito private _createLinesDeletedEvent(fromLineNumber: number, toLineNumber: number): editorCommon.IModelContentChangedLinesDeletedEvent { return { - changeType: editorCommon.EventType.ModelContentChangedLinesDeleted, + changeType: editorCommon.EventType.ModelRawContentChangedLinesDeleted, fromLineNumber: fromLineNumber, toLineNumber: toLineNumber, versionId: -1, @@ -713,7 +722,7 @@ export class EditableTextModel extends TextModelWithDecorations implements edito private _createLinesInsertedEvent(fromLineNumber: number, toLineNumber: number, newLinesContent: string): editorCommon.IModelContentChangedLinesInsertedEvent { return { - changeType: editorCommon.EventType.ModelContentChangedLinesInserted, + changeType: editorCommon.EventType.ModelRawContentChangedLinesInserted, fromLineNumber: fromLineNumber, toLineNumber: toLineNumber, detail: newLinesContent, diff --git a/src/vs/editor/common/model/mirrorModel.ts b/src/vs/editor/common/model/mirrorModel.ts index d35b5b30bab..98268958976 100644 --- a/src/vs/editor/common/model/mirrorModel.ts +++ b/src/vs/editor/common/model/mirrorModel.ts @@ -58,7 +58,7 @@ export class AbstractMirrorModel extends TextModelWithTokens implements editorCo super.dispose(); } - public getAssociatedResource(): URI { + public get uri(): URI { return this._associatedResource; } @@ -284,14 +284,12 @@ export class MirrorModel extends AbstractMirrorModel implements editorCommon.IMi public dispose(): void { super.dispose(); var embeddedModels = Object.keys(this._embeddedModels).map((modeId) => this._embeddedModels[modeId]); - embeddedModels.forEach((embeddedModel) => this._resourceService.remove(embeddedModel.getAssociatedResource())); + embeddedModels.forEach((embeddedModel) => this._resourceService.remove(embeddedModel.uri)); dispose(embeddedModels); this._embeddedModels = {}; } - public setMode(newMode:IMode): void; - public setMode(newModePromise:TPromise): void; - public setMode(newModeOrPromise:any): void { + public setMode(newModeOrPromise:IMode|TPromise): void { super.setMode(newModeOrPromise); this._updateEmbeddedModels(); } @@ -378,9 +376,9 @@ export class MirrorModel extends AbstractMirrorModel implements editorCommon.IMi this._embeddedModels[newNestedModeId].setIncludedRanges(newModesRanges[newNestedModeId].ranges); } else { // TODO@Alex: implement derived resources (embedded mirror models) better - var embeddedModelUrl = this.getAssociatedResource().withFragment(this.getAssociatedResource().fragment + 'URL_MARSHAL_REMOVE' + newNestedModeId); + var embeddedModelUrl = this.uri.withFragment(this.uri.fragment + 'URL_MARSHAL_REMOVE' + newNestedModeId); this._embeddedModels[newNestedModeId] = new MirrorModelEmbedded(this, newModesRanges[newNestedModeId].ranges, newModesRanges[newNestedModeId].mode, embeddedModelUrl); - this._resourceService.insert(this._embeddedModels[newNestedModeId].getAssociatedResource(), this._embeddedModels[newNestedModeId]); + this._resourceService.insert(this._embeddedModels[newNestedModeId].uri, this._embeddedModels[newNestedModeId]); } } @@ -397,22 +395,22 @@ export class MirrorModel extends AbstractMirrorModel implements editorCommon.IMi this._setVersionId(contentChangedEvent.versionId); switch (contentChangedEvent.changeType) { - case editorCommon.EventType.ModelContentChangedFlush: + case editorCommon.EventType.ModelRawContentChangedFlush: this._onLinesFlushed(contentChangedEvent); changed = true; break; - case editorCommon.EventType.ModelContentChangedLinesDeleted: + case editorCommon.EventType.ModelRawContentChangedLinesDeleted: this._onLinesDeleted(contentChangedEvent); changed = true; break; - case editorCommon.EventType.ModelContentChangedLinesInserted: + case editorCommon.EventType.ModelRawContentChangedLinesInserted: this._onLinesInserted(contentChangedEvent); changed = true; break; - case editorCommon.EventType.ModelContentChangedLineChanged: + case editorCommon.EventType.ModelRawContentChangedLineChanged: this._onLineChanged(contentChangedEvent); changed = true; break; diff --git a/src/vs/editor/common/model/model.ts b/src/vs/editor/common/model/model.ts index d0486d3d2b8..ca61340197a 100644 --- a/src/vs/editor/common/model/model.ts +++ b/src/vs/editor/common/model/model.ts @@ -6,10 +6,15 @@ import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; -import {EventType, IModel, ITextModelCreationOptions} from 'vs/editor/common/editorCommon'; +import { + EventType, IModel, ITextModelCreationOptions, IModeSupportChangedEvent, IModelDecorationsChangedEvent, + IModelOptionsChangedEvent, IModelModeChangedEvent +} from 'vs/editor/common/editorCommon'; import {EditableTextModel} from 'vs/editor/common/model/editableTextModel'; import {TextModel} from 'vs/editor/common/model/textModel'; import {IMode} from 'vs/editor/common/modes'; +import {IDisposable} from 'vs/base/common/lifecycle'; +import {BulkListenerCallback} from 'vs/base/common/eventEmitter'; // The hierarchy is: // Model -> EditableTextModel -> TextModelWithDecorations -> TextModelWithTrackedRanges -> TextModelWithMarkers -> TextModelWithTokens -> TextModel @@ -31,6 +36,26 @@ var aliveModels:{[modelId:string]:boolean;} = {}; export class Model extends EditableTextModel implements IModel { + public onDidChangeModeSupport(listener: (e:IModeSupportChangedEvent)=>void): IDisposable { + return this.addListener2(EventType.ModelModeSupportChanged, listener); + } + public onDidChangeDecorations(listener: (e:IModelDecorationsChangedEvent)=>void): IDisposable { + return this.addListener2(EventType.ModelDecorationsChanged, listener); + } + public onDidChangeOptions(listener: (e:IModelOptionsChangedEvent)=>void): IDisposable { + return this.addListener2(EventType.ModelOptionsChanged, listener); + } + public onWillDispose(listener: ()=>void): IDisposable { + return this.addListener2(EventType.ModelDispose, listener); + } + public onDidChangeMode(listener: (e:IModelModeChangedEvent)=>void): IDisposable { + return this.addListener2(EventType.ModelModeChanged, listener); + } + + public addBulkListener(listener:BulkListenerCallback):IDisposable { + return super.addBulkListener(listener); + } + public static DEFAULT_CREATION_OPTIONS: ITextModelCreationOptions = TextModel.DEFAULT_CREATION_OPTIONS; public id:string; @@ -111,7 +136,7 @@ export class Model extends EditableTextModel implements IModel { return this._attachedEditorCount > 0; } - public getAssociatedResource(): URI { + public get uri(): URI { return this._associatedResource; } } diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index e402fbd540c..d99dc6603b9 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -17,6 +17,8 @@ var LIMIT_FIND_COUNT = 999; export const LONG_LINE_BOUNDARY = 1000; export class TextModel extends OrderGuaranteeEventEmitter implements editorCommon.ITextModel { + private static MODEL_SYNC_LIMIT = 5 * 1024 * 1024; // 5 MB + private static MODEL_TOKENIZATION_LIMIT = 20 * 1024 * 1024; // 20 MB public static DEFAULT_CREATION_OPTIONS: editorCommon.ITextModelCreationOptions = { tabSize: DEFAULT_INDENTATION.tabSize, @@ -39,10 +41,16 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo private _alternativeVersionId: number; private _BOM:string; + private _shouldSimplifyMode: boolean; + private _shouldDenyMode: boolean; + constructor(allowedEventTypes:string[], rawText:editorCommon.IRawText) { - allowedEventTypes.push(editorCommon.EventType.ModelContentChanged, editorCommon.EventType.ModelOptionsChanged); + allowedEventTypes.push(editorCommon.EventType.ModelRawContentChanged, editorCommon.EventType.ModelOptionsChanged); super(allowedEventTypes); + this._shouldSimplifyMode = (rawText.length > TextModel.MODEL_SYNC_LIMIT); + this._shouldDenyMode = (rawText.length > TextModel.MODEL_TOKENIZATION_LIMIT); + this._options = rawText.options; this._constructLines(rawText); this._setVersionId(1); @@ -50,6 +58,14 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo this._isDisposing = false; } + public isTooLargeForHavingAMode(): boolean { + return this._shouldDenyMode; + } + + public isTooLargeForHavingARichMode(): boolean { + return this._shouldSimplifyMode; + } + public getOptions(): editorCommon.ITextModelResolvedOptions { return this._options; } @@ -187,7 +203,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo _createContentChangedFlushEvent(): editorCommon.IModelContentChangedFlushEvent { return { - changeType: editorCommon.EventType.ModelContentChangedFlush, + changeType: editorCommon.EventType.ModelRawContentChangedFlush, detail: null, // TODO@Alex -> remove these fields from here versionId: -1, @@ -249,16 +265,18 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo } public setValue(value:string): void { - let rawText: editorCommon.IRawText = null; - if (value !== null) { - rawText = TextModel.toRawText(value, { - tabSize: this._options.tabSize, - insertSpaces: this._options.insertSpaces, - trimAutoWhitespace: this._options.trimAutoWhitespace, - detectIndentation: false, - defaultEOL: this._options.defaultEOL - }); + if (value === null) { + // There's nothing to do + return; } + let rawText: editorCommon.IRawText = null; + rawText = TextModel.toRawText(value, { + tabSize: this._options.tabSize, + insertSpaces: this._options.insertSpaces, + trimAutoWhitespace: this._options.trimAutoWhitespace, + detectIndentation: false, + defaultEOL: this._options.defaultEOL + }); this.setValueFromRawText(rawText); } @@ -496,7 +514,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo return lineNumber; } - public validatePosition(position:editorCommon.IPosition): editorCommon.IEditorPosition { + public validatePosition(position:editorCommon.IPosition): Position { var lineNumber = position.lineNumber ? position.lineNumber : 1; var column = position.column ? position.column : 1; @@ -521,13 +539,13 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo return new Position(lineNumber, column); } - public validateRange(range:editorCommon.IRange): editorCommon.IEditorRange { + public validateRange(range:editorCommon.IRange): Range { var start = this.validatePosition(new Position(range.startLineNumber, range.startColumn)); var end = this.validatePosition(new Position(range.endLineNumber, range.endColumn)); return new Range(start.lineNumber, start.column, end.lineNumber, end.column); } - public modifyPosition(rawPosition: editorCommon.IPosition, offset: number) : editorCommon.IEditorPosition { + public modifyPosition(rawPosition: editorCommon.IPosition, offset: number) : Position { var position = this.validatePosition(rawPosition); // Handle positive offsets, one line at a time @@ -590,14 +608,14 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo return position; } - public getFullModelRange(): editorCommon.IEditorRange { + public getFullModelRange(): Range { var lineCount = this.getLineCount(); return new Range(1, 1, lineCount, this.getLineMaxColumn(lineCount)); } _emitModelContentChangedFlushEvent(e:editorCommon.IModelContentChangedFlushEvent): void { if (!this._isDisposing) { - this.emit(editorCommon.EventType.ModelContentChanged, e); + this.emit(editorCommon.EventType.ModelRawContentChanged, e); } } @@ -685,13 +703,13 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo throw new Error('Unknown EOL preference'); } - public findMatches(searchString:string, rawSearchScope:any, isRegex:boolean, matchCase:boolean, wholeWord:boolean, limitResultCount:number = LIMIT_FIND_COUNT): editorCommon.IEditorRange[] { + public findMatches(searchString:string, rawSearchScope:any, isRegex:boolean, matchCase:boolean, wholeWord:boolean, limitResultCount:number = LIMIT_FIND_COUNT): Range[] { var regex = strings.createSafeRegExp(searchString, isRegex, matchCase, wholeWord); if (!regex) { return []; } - var searchRange:editorCommon.IEditorRange; + var searchRange:Range; if (Range.isIRange(rawSearchScope)) { searchRange = rawSearchScope; } else { @@ -701,7 +719,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo return this._doFindMatches(searchRange, regex, limitResultCount); } - public findNextMatch(searchString:string, rawSearchStart:editorCommon.IPosition, isRegex:boolean, matchCase:boolean, wholeWord:boolean): editorCommon.IEditorRange { + public findNextMatch(searchString:string, rawSearchStart:editorCommon.IPosition, isRegex:boolean, matchCase:boolean, wholeWord:boolean): Range { var regex = strings.createSafeRegExp(searchString, isRegex, matchCase, wholeWord); if (!regex) { return null; @@ -711,7 +729,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo lineCount = this.getLineCount(), startLineNumber = searchStart.lineNumber, text: string, - r: editorCommon.IEditorRange; + r: Range; // Look in first line text = this._lines[startLineNumber - 1].text.substring(searchStart.column - 1); @@ -732,7 +750,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo return null; } - public findPreviousMatch(searchString:string, rawSearchStart:editorCommon.IPosition, isRegex:boolean, matchCase:boolean, wholeWord:boolean): editorCommon.IEditorRange { + public findPreviousMatch(searchString:string, rawSearchStart:editorCommon.IPosition, isRegex:boolean, matchCase:boolean, wholeWord:boolean): Range { var regex = strings.createSafeRegExp(searchString, isRegex, matchCase, wholeWord); if (!regex) { return null; @@ -742,7 +760,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo lineCount = this.getLineCount(), startLineNumber = searchStart.lineNumber, text: string, - r: editorCommon.IEditorRange; + r: Range; // Look in first line text = this._lines[startLineNumber - 1].text.substring(0, searchStart.column - 1); @@ -763,8 +781,8 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo return null; } - private _doFindMatches(searchRange:editorCommon.IEditorRange, searchRegex:RegExp, limitResultCount:number): editorCommon.IEditorRange[] { - var result:editorCommon.IEditorRange[] = [], + private _doFindMatches(searchRange:Range, searchRegex:RegExp, limitResultCount:number): Range[] { + var result:Range[] = [], text: string, counter = 0; @@ -793,7 +811,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo return result; } - private _findMatchInLine(searchRegex:RegExp, text:string, lineNumber:number, deltaOffset:number): editorCommon.IEditorRange { + private _findMatchInLine(searchRegex:RegExp, text:string, lineNumber:number, deltaOffset:number): Range { var m = searchRegex.exec(text); if (!m) { return null; @@ -801,8 +819,8 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo return new Range(lineNumber, m.index + 1 + deltaOffset, lineNumber, m.index + 1 + m[0].length + deltaOffset); } - private _findLastMatchInLine(searchRegex:RegExp, text:string, lineNumber:number): editorCommon.IEditorRange { - let bestResult: editorCommon.IEditorRange = null; + private _findLastMatchInLine(searchRegex:RegExp, text:string, lineNumber:number): Range { + let bestResult: Range = null; let m:RegExpExecArray; while ((m = searchRegex.exec(text))) { let result = new Range(lineNumber, m.index + 1, lineNumber, m.index + 1 + m[0].length); @@ -814,7 +832,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo return bestResult; } - private _findMatchesInLine(searchRegex:RegExp, text:string, lineNumber:number, deltaOffset:number, counter:number, result:editorCommon.IEditorRange[], limitResultCount:number): number { + private _findMatchesInLine(searchRegex:RegExp, text:string, lineNumber:number, deltaOffset:number, counter:number, result:Range[], limitResultCount:number): number { var m:RegExpExecArray; // Reset regex to search from the beginning searchRegex.lastIndex = 0; diff --git a/src/vs/editor/common/model/textModelWithDecorations.ts b/src/vs/editor/common/model/textModelWithDecorations.ts index a2839b67fd6..09463b6d9d9 100644 --- a/src/vs/editor/common/model/textModelWithDecorations.ts +++ b/src/vs/editor/common/model/textModelWithDecorations.ts @@ -8,7 +8,7 @@ import {onUnexpectedError} from 'vs/base/common/errors'; import {IHTMLContentElement, htmlContentElementArrEquals} from 'vs/base/common/htmlContent'; import * as strings from 'vs/base/common/strings'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IdGenerator} from 'vs/editor/common/core/idGenerator'; +import {IdGenerator} from 'vs/base/common/idGenerator'; import {Range} from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {TextModelWithTrackedRanges} from 'vs/editor/common/model/textModelWithTrackedRanges'; @@ -82,7 +82,7 @@ interface IRangeIdToDecorationIdMap { } interface IOldDecoration { - range: editorCommon.IEditorRange; + range: Range; options: ModelDecorationOptions; id: string; } @@ -187,7 +187,7 @@ export class TextModelWithDecorations extends TextModelWithTrackedRanges impleme return null; } - public getDecorationRange(decorationId:string): editorCommon.IEditorRange { + public getDecorationRange(decorationId:string): Range { if (this.decorations.hasOwnProperty(decorationId)) { var decoration = this.decorations[decorationId]; return this.getTrackedRange(decoration.rangeId); @@ -412,10 +412,10 @@ export class TextModelWithDecorations extends TextModelWithTrackedRanges impleme return result; } - private _addDecorationImpl(eventBuilder:DeferredEventsBuilder, ownerId:number, range:editorCommon.IEditorRange, options:ModelDecorationOptions): string { + private _addDecorationImpl(eventBuilder:DeferredEventsBuilder, ownerId:number, range:Range, options:ModelDecorationOptions): string { var rangeId = this.addTrackedRange(range, options.stickiness); - var decoration = new ModelInternalDecoration(this._decorationIdGenerator.generate(), ownerId, rangeId, options); + var decoration = new ModelInternalDecoration(this._decorationIdGenerator.nextId(), ownerId, rangeId, options); this.decorations[decoration.id] = decoration; this.rangeIdToDecorationId[rangeId] = decoration.id; @@ -432,7 +432,7 @@ export class TextModelWithDecorations extends TextModelWithTrackedRanges impleme for (let i = 0, len = newDecorations.length; i < len; i++) { let rangeId = rangeIds[i]; - var decoration = new ModelInternalDecoration(this._decorationIdGenerator.generate(), ownerId, rangeId, newDecorations[i].options); + var decoration = new ModelInternalDecoration(this._decorationIdGenerator.nextId(), ownerId, rangeId, newDecorations[i].options); this.decorations[decoration.id] = decoration; this.rangeIdToDecorationId[rangeId] = decoration.id; @@ -445,7 +445,7 @@ export class TextModelWithDecorations extends TextModelWithTrackedRanges impleme return result; } - private _changeDecorationImpl(eventBuilder:DeferredEventsBuilder, id:string, newRange:editorCommon.IEditorRange): void { + private _changeDecorationImpl(eventBuilder:DeferredEventsBuilder, id:string, newRange:Range): void { if (this.decorations.hasOwnProperty(id)) { var decoration = this.decorations[id]; var oldRange = this.getTrackedRange(decoration.rangeId); @@ -474,7 +474,7 @@ export class TextModelWithDecorations extends TextModelWithTrackedRanges impleme private _removeDecorationImpl(eventBuilder:DeferredEventsBuilder, id:string): void { if (this.decorations.hasOwnProperty(id)) { var decoration = this.decorations[id]; - var oldRange:editorCommon.IEditorRange = null; + var oldRange:Range = null; if (eventBuilder) { oldRange = this.getTrackedRange(decoration.rangeId); } @@ -694,10 +694,10 @@ class ModelDecorationOptions implements editorCommon.IModelDecorationOptions { class ModelDeltaDecoration implements editorCommon.IModelDeltaDecoration { index: number; - range: editorCommon.IEditorRange; + range: Range; options: ModelDecorationOptions; - constructor(index: number, range: editorCommon.IEditorRange, options: ModelDecorationOptions) { + constructor(index: number, range: Range, options: ModelDecorationOptions) { this.index = index; this.range = range; this.options = options; diff --git a/src/vs/editor/common/model/textModelWithMarkers.ts b/src/vs/editor/common/model/textModelWithMarkers.ts index 0e4aae8f7fb..e0986e15ddb 100644 --- a/src/vs/editor/common/model/textModelWithMarkers.ts +++ b/src/vs/editor/common/model/textModelWithMarkers.ts @@ -5,9 +5,9 @@ 'use strict'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IdGenerator} from 'vs/editor/common/core/idGenerator'; +import {IdGenerator} from 'vs/base/common/idGenerator'; import {Position} from 'vs/editor/common/core/position'; -import {IEditorPosition, IModelContentChangedFlushEvent, IRawText, IReadOnlyLineMarker, ITextModelWithMarkers} from 'vs/editor/common/editorCommon'; +import {IModelContentChangedFlushEvent, IRawText, IReadOnlyLineMarker, ITextModelWithMarkers} from 'vs/editor/common/editorCommon'; import {ILineMarker, ModelLine} from 'vs/editor/common/model/modelLine'; import {TextModelWithTokens} from 'vs/editor/common/model/textModelWithTokens'; import {IMode} from 'vs/editor/common/modes'; @@ -72,7 +72,7 @@ export class TextModelWithMarkers extends TextModelWithTokens implements ITextMo _addMarker(lineNumber:number, column:number, stickToPreviousCharacter:boolean): string { var pos = this.validatePosition(new Position(lineNumber, column)); - var marker = new LineMarker(this._markerIdGenerator.generate(), pos.column, stickToPreviousCharacter); + var marker = new LineMarker(this._markerIdGenerator.nextId(), pos.column, stickToPreviousCharacter); this._markerIdToMarker[marker.id] = marker; this._lines[pos.lineNumber - 1].addMarker(marker); @@ -89,7 +89,7 @@ export class TextModelWithMarkers extends TextModelWithTokens implements ITextMo for (let i = 0, len = newMarkers.length; i < len; i++) { let newMarker = newMarkers[i]; - let marker = new LineMarker(this._markerIdGenerator.generate(), newMarker.column, newMarker.stickToPreviousCharacter); + let marker = new LineMarker(this._markerIdGenerator.nextId(), newMarker.column, newMarker.stickToPreviousCharacter); this._markerIdToMarker[marker.id] = marker; if (!addMarkersPerLine[newMarker.lineNumber]) { @@ -135,7 +135,7 @@ export class TextModelWithMarkers extends TextModelWithTokens implements ITextMo } } - _getMarker(id:string): IEditorPosition { + _getMarker(id:string): Position { if (this._markerIdToMarker.hasOwnProperty(id)) { var marker = this._markerIdToMarker[id]; return new Position(marker.line.lineNumber, marker.column); diff --git a/src/vs/editor/common/model/textModelWithTokens.ts b/src/vs/editor/common/model/textModelWithTokens.ts index 5a94dd77610..fd8b9739a3f 100644 --- a/src/vs/editor/common/model/textModelWithTokens.ts +++ b/src/vs/editor/common/model/textModelWithTokens.ts @@ -24,6 +24,7 @@ import {BracketsUtils} from 'vs/editor/common/modes/supports/richEditBrackets'; import {ModeTransition} from 'vs/editor/common/core/modeTransition'; import {LineToken} from 'vs/editor/common/model/lineToken'; import {TokensInflatorMap} from 'vs/editor/common/model/tokensBinaryEncoding'; +import {Position} from 'vs/editor/common/core/position'; class ModeToModelBinder implements IDisposable { @@ -169,8 +170,6 @@ class LineContext implements ILineContext { export class TextModelWithTokens extends TextModel implements editorCommon.ITokenizedModel { private static MODE_TOKENIZATION_FAILED_MSG = nls.localize('mode.tokenizationSupportFailed', "The mode has failed while tokenizing the input."); - private static MODEL_SYNC_LIMIT = 5 * 1024 * 1024; // 5 MB - private static MODEL_TOKENIZATION_LIMIT = 20 * 1024 * 1024; // 20 MB private _shouldAutoTokenize:boolean; private _mode: IMode; @@ -185,9 +184,6 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke private _scheduleRetokenizeNow: RunOnceScheduler; private _retokenizers:IRetokenizeRequest[]; - private _shouldSimplifyMode: boolean; - private _shouldDenyMode: boolean; - constructor(allowedEventTypes:string[], rawText:editorCommon.IRawText, shouldAutoTokenize:boolean, modeOrPromise:IMode|TPromise) { allowedEventTypes.push(editorCommon.EventType.ModelTokensChanged); allowedEventTypes.push(editorCommon.EventType.ModelModeChanged); @@ -207,9 +203,6 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke this._scheduleRetokenizeNow = null; this._retokenizers = null; - this._shouldSimplifyMode = (rawText.length > TextModelWithTokens.MODEL_SYNC_LIMIT); - this._shouldDenyMode = (rawText.length > TextModelWithTokens.MODEL_TOKENIZATION_LIMIT); - if (!modeOrPromise) { this._mode = new NullMode(); } else if (TPromise.is(modeOrPromise)) { @@ -253,14 +246,6 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke super.dispose(); } - public isTooLargeForHavingAMode(): boolean { - return this._shouldDenyMode; - } - - public isTooLargeForHavingARichMode(): boolean { - return this._shouldSimplifyMode; - } - private _massageMode(mode: IMode): IMode { if (this.isTooLargeForHavingAMode()) { return new NullMode(); @@ -427,62 +412,32 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke return this._lines[lineNumber - 1].getTokens(); } - public setValue(value:string, newMode?:IMode): void; - public setValue(value:string, newModePromise?:TPromise): void; - public setValue(value:string, newModeOrPromise:any=null): void { - let rawText: editorCommon.IRawText = null; - if (value !== null) { - rawText = TextModel.toRawText(value, { - tabSize: this._options.tabSize, - insertSpaces: this._options.insertSpaces, - detectIndentation: false, - defaultEOL: this._options.defaultEOL, - trimAutoWhitespace: this._options.trimAutoWhitespace - }); - } - this.setValueFromRawText(rawText, newModeOrPromise); - } - - public setValueFromRawText(value:editorCommon.IRawText, newMode?:IMode): void; - public setValueFromRawText(value:editorCommon.IRawText, newModePromise?:TPromise): void; - public setValueFromRawText(value:editorCommon.IRawText, newModeOrPromise:any=null): void { - if (value !== null) { - super.setValueFromRawText(value); - } - - if (newModeOrPromise) { - if (this._modeToModelBinder) { - this._modeToModelBinder.dispose(); - this._modeToModelBinder = null; - } - if (TPromise.is(newModeOrPromise)) { - this._modeToModelBinder = new ModeToModelBinder(>newModeOrPromise, this); - } else { - var actualNewMode = this._massageMode(newModeOrPromise); - if (this._mode !== actualNewMode) { - var e2:editorCommon.IModelModeChangedEvent = { - oldMode: this._mode, - newMode: actualNewMode - }; - this._resetMode(e2, actualNewMode); - this._emitModelModeChangedEvent(e2); - } - } - } - } - public getMode(): IMode { return this._mode; } - public setMode(newMode:IMode): void; - public setMode(newModePromise:TPromise): void; - public setMode(newModeOrPromise:any): void { + public setMode(newModeOrPromise:IMode|TPromise): void { if (!newModeOrPromise) { // There's nothing to do return; } - this.setValueFromRawText(null, newModeOrPromise); + if (this._modeToModelBinder) { + this._modeToModelBinder.dispose(); + this._modeToModelBinder = null; + } + if (TPromise.is(newModeOrPromise)) { + this._modeToModelBinder = new ModeToModelBinder(>newModeOrPromise, this); + } else { + var actualNewMode = this._massageMode(newModeOrPromise); + if (this._mode !== actualNewMode) { + var e2:editorCommon.IModelModeChangedEvent = { + oldMode: this._mode, + newMode: actualNewMode + }; + this._resetMode(e2, actualNewMode); + this._emitModelModeChangedEvent(e2); + } + } } public getModeAtPosition(_lineNumber:number, _column:number): IMode { @@ -801,7 +756,7 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke return result; } - public findMatchingBracketUp(bracket:string, _position:editorCommon.IPosition): editorCommon.IEditorRange { + public findMatchingBracketUp(bracket:string, _position:editorCommon.IPosition): Range { let position = this.validatePosition(_position); let modeTransitions = this._lines[position.lineNumber - 1].getModeTransitions(this._mode); let currentModeIndex = ModeTransition.findIndexInSegmentsArray(modeTransitions, position.column - 1); @@ -821,11 +776,11 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke return this._findMatchingBracketUp(data, position); } - public matchBracket(position:editorCommon.IPosition): [editorCommon.IEditorRange,editorCommon.IEditorRange] { + public matchBracket(position:editorCommon.IPosition): [Range,Range] { return this._matchBracket(this.validatePosition(position)); } - private _matchBracket(position:editorCommon.IEditorPosition): [editorCommon.IEditorRange,editorCommon.IEditorRange] { + private _matchBracket(position:Position): [Range,Range] { let lineNumber = position.lineNumber; let lineText = this._lines[lineNumber - 1].text; @@ -913,7 +868,7 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke return null; } - private _matchFoundBracket(foundBracket:Range, data:editorCommon.IRichEditBracket, isOpen:boolean): [editorCommon.IEditorRange,editorCommon.IEditorRange] { + private _matchFoundBracket(foundBracket:Range, data:editorCommon.IRichEditBracket, isOpen:boolean): [Range,Range] { if (isOpen) { let matched = this._findMatchingBracketDown(data, foundBracket.getEndPosition()); if (matched) { @@ -929,7 +884,7 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke return null; } - private _findMatchingBracketUp(bracket:editorCommon.IRichEditBracket, position:editorCommon.IEditorPosition): Range { + private _findMatchingBracketUp(bracket:editorCommon.IRichEditBracket, position:Position): Range { // console.log('_findMatchingBracketUp: ', 'bracket: ', JSON.stringify(bracket), 'startPosition: ', String(position)); let modeId = bracket.modeId; @@ -996,7 +951,7 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke return null; } - private _findMatchingBracketDown(bracket:editorCommon.IRichEditBracket, position:editorCommon.IEditorPosition): Range { + private _findMatchingBracketDown(bracket:editorCommon.IRichEditBracket, position:Position): Range { // console.log('_findMatchingBracketDown: ', 'bracket: ', JSON.stringify(bracket), 'startPosition: ', String(position)); let modeId = bracket.modeId; diff --git a/src/vs/editor/common/model/textModelWithTrackedRanges.ts b/src/vs/editor/common/model/textModelWithTrackedRanges.ts index 06e5701cd42..d234f8e2549 100644 --- a/src/vs/editor/common/model/textModelWithTrackedRanges.ts +++ b/src/vs/editor/common/model/textModelWithTrackedRanges.ts @@ -5,13 +5,14 @@ 'use strict'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IdGenerator} from 'vs/editor/common/core/idGenerator'; +import {IdGenerator} from 'vs/base/common/idGenerator'; import {Range} from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {ILineMarker} from 'vs/editor/common/model/modelLine'; import {INewMarker, TextModelWithMarkers} from 'vs/editor/common/model/textModelWithMarkers'; import {FullModelRetokenizer, IRetokenizeRequest} from 'vs/editor/common/model/textModelWithTokens'; import {IMode} from 'vs/editor/common/modes'; +import {Position} from 'vs/editor/common/core/position'; interface ITrackedRange { id:string; @@ -140,7 +141,7 @@ export class TextModelWithTrackedRanges extends TextModelWithMarkers implements var startMarkerId = this._addMarker(textRange.startLineNumber, textRange.startColumn, startMarkerSticksToPreviousCharacter); var endMarkerId = this._addMarker(textRange.endLineNumber, textRange.endColumn, endMarkerSticksToPreviousCharacter); - var range = new TrackedRange(this._rangeIdGenerator.generate(), startMarkerId, endMarkerId); + var range = new TrackedRange(this._rangeIdGenerator.nextId(), startMarkerId, endMarkerId); this._ranges[range.id] = range; this._markerIdToRangeId[startMarkerId] = range.id; this._markerIdToRangeId[endMarkerId] = range.id; @@ -176,7 +177,7 @@ export class TextModelWithTrackedRanges extends TextModelWithMarkers implements let startMarkerId = markerIds[2 * i]; let endMarkerId = markerIds[2 * i + 1]; - let range = new TrackedRange(this._rangeIdGenerator.generate(), startMarkerId, endMarkerId); + let range = new TrackedRange(this._rangeIdGenerator.nextId(), startMarkerId, endMarkerId); this._ranges[range.id] = range; this._markerIdToRangeId[startMarkerId] = range.id; this._markerIdToRangeId[endMarkerId] = range.id; @@ -256,7 +257,7 @@ export class TextModelWithTrackedRanges extends TextModelWithMarkers implements } } - private _newEditorRange(startPosition: editorCommon.IEditorPosition, endPosition: editorCommon.IEditorPosition): editorCommon.IEditorRange { + private _newEditorRange(startPosition: Position, endPosition: Position): Range { if (endPosition.isBefore(startPosition)) { // This tracked range has turned in on itself (end marker before start marker) // This can happen in extreme editing conditions where lots of text is removed and lots is added @@ -267,7 +268,7 @@ export class TextModelWithTrackedRanges extends TextModelWithMarkers implements return new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column); } - public getTrackedRange(rangeId:string): editorCommon.IEditorRange { + public getTrackedRange(rangeId:string): Range { var range = this._ranges[rangeId]; var startMarker = this._getMarker(range.startMarkerId); var endMarker = this._getMarker(range.endMarkerId); @@ -314,8 +315,8 @@ export class TextModelWithTrackedRanges extends TextModelWithMarkers implements i: number, len: number, lineNumber: number, - startMarker: editorCommon.IEditorPosition, - endMarker: editorCommon.IEditorPosition; + startMarker: Position, + endMarker: Position; for (i = 0, len = result.length; i < len; i++) { resultMap[result[i].id] = true; diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index fe236fd01a4..5e3fd67cbb8 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -9,10 +9,12 @@ import {IDisposable} from 'vs/base/common/lifecycle'; import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import {IFilter} from 'vs/base/common/filters'; -import {IMarker} from 'vs/platform/markers/common/markers'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {ModeTransition} from 'vs/editor/common/core/modeTransition'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; +import {CancellationToken} from 'vs/base/common/cancellation'; +import {Position} from 'vs/editor/common/core/position'; +import {Range} from 'vs/editor/common/core/range'; export interface ITokenizationResult { type?:string; @@ -165,6 +167,21 @@ export interface ILineContext { findIndexOfOffset(offset:number): number; } +export enum MutableSupport { + RichEditSupport = 1, + TokenizationSupport = 2 +} +export function mutableSupportToString(registerableSupport:MutableSupport) { + if (registerableSupport === MutableSupport.RichEditSupport) { + return 'richEditSupport'; + } + if (registerableSupport === MutableSupport.TokenizationSupport) { + return 'tokenizationSupport'; + } + throw new Error('Illegal argument!'); +} + + export interface IMode { getId(): string; @@ -179,53 +196,13 @@ export interface IMode { /** * Register a support by name. Only optional. */ - registerSupport?(support:string, callback:(mode:IMode)=>T): IDisposable; + registerSupport?(support:MutableSupport, callback:(mode:IMode)=>T): IDisposable; /** * Optional adapter to support tokenization. */ tokenizationSupport?: ITokenizationSupport; - /** - * Optional adapter to support showing occurrences of words or such. - */ - occurrencesSupport?:IOccurrencesSupport; - - /** - * Optional adapter to support revealing the declaration of a symbol. - */ - declarationSupport?: IDeclarationSupport; - - /** - * Optional adapter to support finding references to a symbol. - */ - referenceSupport?:IReferenceSupport; - - /** - * Optional adapter to support intellisense. - */ - suggestSupport?:ISuggestSupport; - - /** - * Optional adapter to support intellisense. - */ - parameterHintsSupport?:IParameterHintsSupport; - - /** - * Optional adapter to support showing extra info in tokens. - */ - extraInfoSupport?:IExtraInfoSupport; - - /** - * Optional adapter to support showing an outline. - */ - outlineSupport?:IOutlineSupport; - - /** - * Optional adapter to support formatting. - */ - formattingSupport?:IFormattingSupport; - /** * Optional adapter to support inplace-replace. */ @@ -236,36 +213,11 @@ export interface IMode { */ emitOutputSupport?:IEmitOutputSupport; - /** - * Optional adapter to support detecting links. - */ - linkSupport?:ILinkSupport; - /** * Optional adapter to support configuring this mode. */ configSupport?:IConfigurationSupport; - /** - * Optional adapter to support quick fix of typing errors. - */ - quickFixSupport?:IQuickFixSupport; - - /** - * Optional adapter to show code lens - */ - codeLensSupport?:ICodeLensSupport; - - /** - * Optional adapter to support renaming - */ - renameSupport?: IRenameSupport; - - /** - * Optional adapter to support task running - */ - taskSupport?: ITaskSupport; - /** * Optional adapter to support rich editing. */ @@ -304,17 +256,44 @@ export interface ITokenizationSupport { tokenize(line:string, state:IState, offsetDelta?:number, stopAtOffset?:number):ILineTokens; } -/** - * Interface used to get extra info for a symbol - */ -export interface IComputeExtraInfoResult { - range: editorCommon.IRange; - value?: string; - htmlContent?: IHTMLContentElement[]; - className?: string; +export interface IToken2 { + startIndex: number; + scopes: string|string[]; } -export interface IExtraInfoSupport { - computeInfo(resource:URI, position:editorCommon.IPosition):TPromise; +export interface ILineTokens2 { + tokens: IToken2[]; + endState: IState2; + retokenize?: TPromise; +} +export interface IState2 { + clone():IState2; + equals(other:IState2):boolean; +} +export interface ITokenizationSupport2 { + getInitialState(): IState2; + tokenize(line:string, state:IState2): ILineTokens2; +} + +/** + * A hover represents additional information for a symbol or word. Hovers are + * rendered in a tooltip-like widget. + */ +export interface Hover { + /** + * The contents of this hover. + */ + htmlContent: IHTMLContentElement[]; + + /** + * The range to which this hover applies. When missing, the + * editor will use the range at the current position or the + * current position itself. + */ + range: editorCommon.IRange; +} + +export interface HoverProvider { + provideHover(model:editorCommon.IReadOnlyModel, position:Position, token:CancellationToken): Hover | Thenable; } export type SuggestionType = 'method' @@ -356,24 +335,15 @@ export interface ISuggestResult { incomplete?: boolean; } -/** - * Interface used to get completion suggestions at a specific location. - */ export interface ISuggestSupport { - /** - * Compute all completions for the given resource at the given position. - */ - suggest(resource: URI, position: editorCommon.IPosition, triggerCharacter?: string): TPromise; - - /** - * Compute more details for the given suggestion. - */ - getSuggestionDetails?: (resource: URI, position: editorCommon.IPosition, suggestion: ISuggestion) => TPromise; + triggerCharacters: string[]; filter?: IFilter; - getTriggerCharacters(): string[]; - shouldAutotriggerSuggest(context: ILineContext, offset: number, triggeredByCharacter: string): boolean; + + provideCompletionItems(model:editorCommon.IReadOnlyModel, position:Position, token:CancellationToken): ISuggestResult[] | Thenable; + + resolveCompletionItem?(model:editorCommon.IReadOnlyModel, position:Position, item: ISuggestion, token: CancellationToken): ISuggestion | Thenable; } /** @@ -383,109 +353,185 @@ export interface IQuickFix { command: ICommand; score: number; } - -export interface IQuickFixResult { - edits?: IResourceEdit[]; - message?: string; -} - -export interface IQuickFixSupport { - getQuickFixes(resource: URI, range: IMarker | editorCommon.IRange): TPromise; - //TODO@joh this should be removed in the furture such that we can trust the command and it's args - runQuickFixAction(resource: URI, range: editorCommon.IRange, quickFix: IQuickFix):TPromise; -} - -export interface IParameter { - label:string; - documentation?:string; - signatureLabelOffset?:number; - signatureLabelEnd?:number; -} - -export interface ISignature { - label:string; - documentation?:string; - parameters:IParameter[]; -} - -export interface IParameterHints { - currentSignature:number; - currentParameter:number; - signatures:ISignature[]; -} - -/** - * Interface used to get parameter hints. - */ -export interface IParameterHintsSupport { - getParameterHintsTriggerCharacters(): string[]; - shouldTriggerParameterHints(context: ILineContext, offset: number): boolean; - getParameterHints(resource: URI, position: editorCommon.IPosition, triggerCharacter?: string): TPromise; +export interface CodeActionProvider { + provideCodeActions(model:editorCommon.IReadOnlyModel, range:Range, token: CancellationToken): IQuickFix[] | Thenable; } -export interface IOccurence { - kind?: 'write' | 'text' | string; - range: editorCommon.IRange; -} - -/** - * Interface used to find occurrences of a symbol - */ -export interface IOccurrencesSupport { - findOccurrences(resource:URI, position:editorCommon.IPosition, strict?:boolean):TPromise; -} - - -/** - * Interface used to find declarations on a symbol - */ -export interface IReference { - resource: URI; - range: editorCommon.IRange; -} - -/** - * Interface used to find references to a symbol - */ -export interface IReferenceSupport { - - /** - * @returns true if on the given line (and its tokens) at the given - * offset reference search can be invoked. - */ - canFindReferences(context:ILineContext, offset:number):boolean; - - /** - * @returns a list of reference of the symbol at the position in the - * given resource. - */ - findReferences(resource:URI, position:editorCommon.IPosition, includeDeclaration:boolean):TPromise; -} - -/** - * Interface used to find declarations on a symbol - */ -export interface IDeclarationSupport { - canFindDeclaration(context:ILineContext, offset:number):boolean; - findDeclaration(resource:URI, position:editorCommon.IPosition):TPromise; -} - -/** - * Interface used to compute an outline - */ -export interface IOutlineEntry { +export interface ParameterInformation { label: string; - containerLabel?: string; - type: string; - icon?: string; // icon class or null to use the default images based on the type - range: editorCommon.IRange; - children?: IOutlineEntry[]; + documentation: string; +} +export interface SignatureInformation { + label: string; + documentation: string; + parameters: ParameterInformation[]; +} +export interface SignatureHelp { + signatures: SignatureInformation[]; + activeSignature: number; + activeParameter: number; +} +export interface SignatureHelpProvider { + + signatureHelpTriggerCharacters: string[]; + + provideSignatureHelp(model: editorCommon.IReadOnlyModel, position: Position, token: CancellationToken): SignatureHelp | Thenable; } -export interface IOutlineSupport { - getOutline(resource:URI):TPromise; - outlineGroupLabel?: { [name: string]: string; }; + +export enum DocumentHighlightKind { + Text, + Read, + Write +} +export interface DocumentHighlight { + range: editorCommon.IRange; + kind: DocumentHighlightKind; +} +export interface DocumentHighlightProvider { + provideDocumentHighlights(model: editorCommon.IReadOnlyModel, position: Position, token: CancellationToken): DocumentHighlight[] | Thenable; +} + + +export interface ReferenceContext { + includeDeclaration: boolean; +} +export interface ReferenceProvider { + provideReferences(model:editorCommon.IReadOnlyModel, position:Position, context: ReferenceContext, token: CancellationToken): Location[] | Thenable; +} + + +export class Location { + uri: URI; + range: editorCommon.IRange; +} +export type Definition = Location | Location[]; +export interface DefinitionProvider { + provideDefinition(model:editorCommon.IReadOnlyModel, position:Position, token:CancellationToken): Definition | Thenable; +} + +export enum SymbolKind { + File, + Module, + Namespace, + Package, + Class, + Method, + Property, + Field, + Constructor, + Enum, + Interface, + Function, + Variable, + Constant, + String, + Number, + Boolean, + Array, + Object, + Key, + Null +} +export namespace SymbolKind { + + export function from(kind: number | SymbolKind): string { + switch (kind) { + case SymbolKind.Method: + return 'method'; + case SymbolKind.Function: + return 'function'; + case SymbolKind.Constructor: + return 'constructor'; + case SymbolKind.Variable: + return 'variable'; + case SymbolKind.Class: + return 'class'; + case SymbolKind.Interface: + return 'interface'; + case SymbolKind.Namespace: + return 'namespace'; + case SymbolKind.Package: + return 'package'; + case SymbolKind.Module: + return 'module'; + case SymbolKind.Property: + return 'property'; + case SymbolKind.Enum: + return 'enum'; + case SymbolKind.String: + return 'string'; + case SymbolKind.File: + return 'file'; + case SymbolKind.Array: + return 'array'; + case SymbolKind.Number: + return 'number'; + case SymbolKind.Boolean: + return 'boolean'; + case SymbolKind.Object: + return 'object'; + case SymbolKind.Key: + return 'key'; + case SymbolKind.Null: + return 'null'; + } + return 'property'; + } + + export function to(type: string): SymbolKind { + switch (type) { + case 'method': + return SymbolKind.Method; + case 'function': + return SymbolKind.Function; + case 'constructor': + return SymbolKind.Constructor; + case 'variable': + return SymbolKind.Variable; + case 'class': + return SymbolKind.Class; + case 'interface': + return SymbolKind.Interface; + case 'namespace': + return SymbolKind.Namespace; + case 'package': + return SymbolKind.Package; + case 'module': + return SymbolKind.Module; + case 'property': + return SymbolKind.Property; + case 'enum': + return SymbolKind.Enum; + case 'string': + return SymbolKind.String; + case 'file': + return SymbolKind.File; + case 'array': + return SymbolKind.Array; + case 'number': + return SymbolKind.Number; + case 'boolean': + return SymbolKind.Boolean; + case 'object': + return SymbolKind.Object; + case 'key': + return SymbolKind.Key; + case 'null': + return SymbolKind.Null; + } + return SymbolKind.Property; + } +} +export interface SymbolInformation { + name: string; + containerName?: string; + kind: SymbolKind; + location: Location; +} +export interface DocumentSymbolProvider { + provideDocumentSymbols(model:editorCommon.IReadOnlyModel, token: CancellationToken): SymbolInformation[] | Thenable; } /** @@ -496,23 +542,18 @@ export interface IFormattingOptions { insertSpaces:boolean; } -/** - * Supports to format source code. There are three levels - * on which formatting can be offered: - * (1) format a document - * (2) format a selectin - * (3) format on keystroke - */ -export interface IFormattingSupport { - formatDocument?: (resource: URI, options: IFormattingOptions) => TPromise; - - formatRange?: (resource: URI, range: editorCommon.IRange, options: IFormattingOptions) => TPromise; - - autoFormatTriggerCharacters?: string[]; - - formatAfterKeystroke?: (resource: URI, position: editorCommon.IPosition, ch: string, options: IFormattingOptions) => TPromise; +export interface DocumentFormattingEditProvider { + provideDocumentFormattingEdits(model: editorCommon.IReadOnlyModel, options: IFormattingOptions, token: CancellationToken): editorCommon.ISingleEditOperation[] | Thenable; } +export interface DocumentRangeFormattingEditProvider { + provideDocumentRangeFormattingEdits(model: editorCommon.IReadOnlyModel, range: Range, options: IFormattingOptions, token: CancellationToken): editorCommon.ISingleEditOperation[] | Thenable; +} +export interface OnTypeFormattingEditProvider { + autoFormatTriggerCharacters: string[]; + provideOnTypeFormattingEdits(model: editorCommon.IReadOnlyModel, position: Position, ch: string, options: IFormattingOptions, token: CancellationToken): editorCommon.ISingleEditOperation[] | Thenable; +} + export interface IInplaceReplaceSupportResult { value: string; @@ -538,25 +579,15 @@ export interface IEmitOutput { content:string; } -/** - * Interface used to detect links. - */ + export interface ILink { - range: editorCommon.IRange; - - /** - * The url of the link. - * The url should be absolute and will not get any special treatment. - */ url: string; - - extraInlineClassName?: string; +} +export interface LinkProvider { + provideLinks(model: editorCommon.IReadOnlyModel, token: CancellationToken): ILink[] | Thenable; } -export interface ILinkSupport { - computeLinks(resource:URI):TPromise; -} /** * Interface used to define a configurable editor mode. @@ -565,59 +596,36 @@ export interface IConfigurationSupport { configure(options:any):TPromise; } + export interface IResourceEdit { resource: URI; - range?: editorCommon.IRange; + range: editorCommon.IRange; newText: string; } - -export interface IRenameResult { - currentName: string; +export interface WorkspaceEdit { edits: IResourceEdit[]; rejectReason?: string; } - -/** - * Interface used to support renaming of symbols - */ -export interface IRenameSupport { - - filter?: string[]; - - rename(resource: URI, position: editorCommon.IPosition, newName: string): TPromise; +export interface RenameProvider { + provideRenameEdits(model:editorCommon.IReadOnlyModel, position:Position, newName: string, token: CancellationToken): WorkspaceEdit | Thenable; } + export interface ICommand { id: string; title: string; arguments?: any[]; } - export interface ICodeLensSymbol { range: editorCommon.IRange; id?: string; command?: ICommand; } - -/** - * Interface used for the code lense support - */ -export interface ICodeLensSupport { - findCodeLensSymbols(resource: URI): TPromise; - resolveCodeLensSymbol(resource: URI, symbol: ICodeLensSymbol): TPromise; +export interface CodeLensProvider { + provideCodeLenses(model:editorCommon.IReadOnlyModel, token: CancellationToken): ICodeLensSymbol[] | Thenable; + resolveCodeLens?(model:editorCommon.IReadOnlyModel, codeLens: ICodeLensSymbol, token: CancellationToken): ICodeLensSymbol | Thenable; } -export interface ITaskSummary { -} - -/** - * Interface to support building via a langauge service - */ -export interface ITaskSupport { - build?():TPromise; - rebuild?():TPromise; - clean?():TPromise; -} export type CharacterPair = [string, string]; @@ -733,26 +741,30 @@ export interface IRichEditSupport { // --- feature registries ------ -export const ReferenceSearchRegistry = new LanguageFeatureRegistry('referenceSupport'); +export const ReferenceProviderRegistry = new LanguageFeatureRegistry(); -export const RenameRegistry = new LanguageFeatureRegistry('renameSupport'); +export const RenameProviderRegistry = new LanguageFeatureRegistry(); -export const SuggestRegistry = new LanguageFeatureRegistry('suggestSupport'); +export const SuggestRegistry = new LanguageFeatureRegistry(); -export const ParameterHintsRegistry = new LanguageFeatureRegistry('parameterHintsSupport'); +export const SignatureHelpProviderRegistry = new LanguageFeatureRegistry(); -export const ExtraInfoRegistry = new LanguageFeatureRegistry('extraInfoSupport'); +export const HoverProviderRegistry = new LanguageFeatureRegistry(); -export const OutlineRegistry = new LanguageFeatureRegistry('outlineSupport'); +export const DocumentSymbolProviderRegistry = new LanguageFeatureRegistry(); -export const OccurrencesRegistry = new LanguageFeatureRegistry('occurrencesSupport'); +export const DocumentHighlightProviderRegistry = new LanguageFeatureRegistry(); -export const DeclarationRegistry = new LanguageFeatureRegistry('declarationSupport'); +export const DefinitionProviderRegistry = new LanguageFeatureRegistry(); -export const CodeLensRegistry = new LanguageFeatureRegistry('codeLensSupport'); +export const CodeLensProviderRegistry = new LanguageFeatureRegistry(); -export const QuickFixRegistry = new LanguageFeatureRegistry('quickFixSupport'); +export const CodeActionProviderRegistry = new LanguageFeatureRegistry(); -export const FormatRegistry = new LanguageFeatureRegistry('formattingSupport'); +export const DocumentFormattingEditProviderRegistry = new LanguageFeatureRegistry(); -export const FormatOnTypeRegistry = new LanguageFeatureRegistry('formattingSupport'); +export const DocumentRangeFormattingEditProviderRegistry = new LanguageFeatureRegistry(); + +export const OnTypeFormattingEditProviderRegistry = new LanguageFeatureRegistry(); + +export const LinkProviderRegistry = new LanguageFeatureRegistry(); diff --git a/src/vs/editor/common/modes/abstractMode.ts b/src/vs/editor/common/modes/abstractMode.ts index 99c2892c2ec..9c68600bc5a 100644 --- a/src/vs/editor/common/modes/abstractMode.ts +++ b/src/vs/editor/common/modes/abstractMode.ts @@ -9,6 +9,7 @@ import {IDisposable} from 'vs/base/common/lifecycle'; import {TPromise} from 'vs/base/common/winjs.base'; import {AsyncDescriptor1, createAsyncDescriptor1} from 'vs/platform/instantiation/common/descriptors'; import {IInstantiationService, optional} from 'vs/platform/instantiation/common/instantiation'; +import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {IModeSupportChangedEvent} from 'vs/editor/common/editorCommon'; import * as modes from 'vs/editor/common/modes'; import {NullMode} from 'vs/editor/common/modes/nullMode'; @@ -101,16 +102,17 @@ export abstract class AbstractMode implements modes.IMode { return this._eventEmitter.addListener2('modeSupportChanged', callback); } - public registerSupport(support:string, callback:(mode:modes.IMode) => T) : IDisposable { + public registerSupport(supportEnum:modes.MutableSupport, callback:(mode:modes.IMode) => T) : IDisposable { + let supportStr = modes.mutableSupportToString(supportEnum); var supportImpl = callback(this); - this[support] = supportImpl; - this._eventEmitter.emit('modeSupportChanged', _createModeSupportChangedEvent(support)); + this[supportStr] = supportImpl; + this._eventEmitter.emit('modeSupportChanged', _createModeSupportChangedEvent(supportEnum)); return { dispose: () => { - if (this[support] === supportImpl) { - delete this[support]; - this._eventEmitter.emit('modeSupportChanged', _createModeSupportChangedEvent(support)); + if (this[supportStr] === supportImpl) { + delete this[supportStr]; + this._eventEmitter.emit('modeSupportChanged', _createModeSupportChangedEvent(supportEnum)); } } }; @@ -134,11 +136,8 @@ class SimplifiedMode implements modes.IMode { if (this._sourceMode.addSupportChangedListener) { this._sourceMode.addSupportChangedListener((e) => { - if (e.tokenizationSupport || e.richEditSupport) { - this._assignSupports(); - let newEvent = SimplifiedMode._createModeSupportChangedEvent(e); - this._eventEmitter.emit('modeSupportChanged', newEvent); - } + this._assignSupports(); + this._eventEmitter.emit('modeSupportChanged', e); }); } } @@ -155,31 +154,6 @@ class SimplifiedMode implements modes.IMode { this.tokenizationSupport = this._sourceMode.tokenizationSupport; this.richEditSupport = this._sourceMode.richEditSupport; } - - private static _createModeSupportChangedEvent(originalModeEvent:IModeSupportChangedEvent): IModeSupportChangedEvent { - var event:IModeSupportChangedEvent = { - codeLensSupport: false, - tokenizationSupport: originalModeEvent.tokenizationSupport, - occurrencesSupport:false, - declarationSupport:false, - typeDeclarationSupport:false, - navigateTypesSupport:false, - referenceSupport:false, - suggestSupport:false, - parameterHintsSupport:false, - extraInfoSupport:false, - outlineSupport:false, - logicalSelectionSupport:false, - formattingSupport:false, - inplaceReplaceSupport:false, - emitOutputSupport:false, - linkSupport:false, - configSupport:false, - quickFixSupport:false, - richEditSupport: originalModeEvent.richEditSupport, - }; - return event; - } } export var isDigit:(character:string, base:number)=>boolean = (function () { @@ -248,42 +222,30 @@ export var isDigit:(character:string, base:number)=>boolean = (function () { export class FrankensteinMode extends AbstractMode { - public suggestSupport:modes.ISuggestSupport; - constructor( - descriptor:modes.IModeDescriptor, + descriptor: modes.IModeDescriptor, + @IConfigurationService configurationService: IConfigurationService, @optional(IEditorWorkerService) editorWorkerService: IEditorWorkerService ) { super(descriptor.id); if (editorWorkerService) { - this.suggestSupport = new TextualSuggestSupport(this.getId(), editorWorkerService); + modes.SuggestRegistry.register(this.getId(), new TextualSuggestSupport(editorWorkerService, configurationService), true); } } } -function _createModeSupportChangedEvent(...changedSupports: string[]): IModeSupportChangedEvent { - var event:IModeSupportChangedEvent = { - codeLensSupport: false, - tokenizationSupport:false, - occurrencesSupport:false, - declarationSupport:false, - typeDeclarationSupport:false, - navigateTypesSupport:false, - referenceSupport:false, - suggestSupport:false, - parameterHintsSupport:false, - extraInfoSupport:false, - outlineSupport:false, - logicalSelectionSupport:false, - formattingSupport:false, - inplaceReplaceSupport:false, - emitOutputSupport:false, - linkSupport:false, - configSupport:false, - quickFixSupport:false, - richEditSupport: false +function _createModeSupportChangedEvent(supportEnum:modes.MutableSupport): IModeSupportChangedEvent { + let e:IModeSupportChangedEvent = { + richEditSupport: false, + tokenizationSupport: false }; - changedSupports.forEach(support => event[support] = true); - return event; -} \ No newline at end of file + if (supportEnum === modes.MutableSupport.RichEditSupport) { + e.richEditSupport = true; + return e; + } else if (supportEnum === modes.MutableSupport.TokenizationSupport) { + e.tokenizationSupport = true; + return e; + } + throw new Error('Illegal argument!'); +} diff --git a/src/vs/editor/common/modes/languageFeatureRegistry.ts b/src/vs/editor/common/modes/languageFeatureRegistry.ts index 0f07d82a13c..de8864558a6 100644 --- a/src/vs/editor/common/modes/languageFeatureRegistry.ts +++ b/src/vs/editor/common/modes/languageFeatureRegistry.ts @@ -5,15 +5,15 @@ 'use strict'; -import {binarySearch} from 'vs/base/common/arrays'; import Event, {Emitter} from 'vs/base/common/event'; import {IDisposable} from 'vs/base/common/lifecycle'; -import {IModel} from 'vs/editor/common/editorCommon'; +import {IReadOnlyModel} from 'vs/editor/common/editorCommon'; import {LanguageSelector, score} from 'vs/editor/common/modes/languageSelector'; interface Entry { selector: LanguageSelector; provider: T; + isBuiltin: boolean; _score: number; _time: number; } @@ -23,21 +23,20 @@ export default class LanguageFeatureRegistry { private _clock: number = 0; private _entries: Entry[] = []; private _onDidChange: Emitter = new Emitter(); - private _supportName: string; - constructor(supportName?: string) { - this._supportName = supportName; + constructor() { } get onDidChange(): Event { return this._onDidChange.event; } - register(selector: LanguageSelector, provider: T): IDisposable { + register(selector: LanguageSelector, provider: T, isBuiltin = false): IDisposable { let entry: Entry = { selector, provider, + isBuiltin, _score: -1, _time: this._clock++ }; @@ -61,11 +60,11 @@ export default class LanguageFeatureRegistry { }; } - has(model: IModel): boolean { + has(model: IReadOnlyModel): boolean { return this.all(model).length > 0; } - all(model: IModel): T[] { + all(model: IReadOnlyModel): T[] { if (!model || model.isTooLargeForHavingAMode()) { return []; } @@ -73,27 +72,23 @@ export default class LanguageFeatureRegistry { this._updateScores(model); const result: T[] = []; - // (1) from registry + // from registry for (let entry of this._entries) { if (entry._score > 0) { result.push(entry.provider); } } - // (2) from mode - if (model.getMode() && model.getMode()[this._supportName]) { - result.push(model.getMode()[this._supportName]); - } return result; } - ordered(model: IModel): T[] { + ordered(model: IReadOnlyModel): T[] { const result: T[] = []; this._orderedForEach(model, entry => result.push(entry.provider)); return result; } - orderedGroups(model: IModel): T[][] { + orderedGroups(model: IReadOnlyModel): T[][] { const result: T[][] = []; let lastBucket: T[]; let lastBucketScore: number; @@ -111,7 +106,7 @@ export default class LanguageFeatureRegistry { return result; } - private _orderedForEach(model: IModel, callback: (provider: Entry) => any): void { + private _orderedForEach(model: IReadOnlyModel, callback: (provider: Entry) => any): void { if (!model || model.isTooLargeForHavingAMode()) { return; @@ -119,38 +114,20 @@ export default class LanguageFeatureRegistry { this._updateScores(model); - let supportIndex: number = -1; - let supportEntry: Entry; - - if (model.getMode() && model.getMode()[this._supportName]) { - supportEntry = { - selector: undefined, - provider: model.getMode()[this._supportName], - _score: .5, - _time: -1 - }; - supportIndex = ~binarySearch(this._entries, supportEntry, LanguageFeatureRegistry._compareByScoreAndTime); - } - - const to = Math.max(supportIndex + 1, this._entries.length); - for (let from = 0; from < to; from++) { - if (from === supportIndex) { - callback(supportEntry); - } else { - let entry = this._entries[from]; - if (entry._score > 0) { - callback(entry); - } + for (let from = 0; from < this._entries.length; from++) { + let entry = this._entries[from]; + if (entry._score > 0) { + callback(entry); } } } private _lastCandidate: { uri: string; language: string; }; - private _updateScores(model: IModel): boolean { + private _updateScores(model: IReadOnlyModel): boolean { let candidate = { - uri: model.getAssociatedResource().toString(), + uri: model.uri.toString(), language: model.getModeId() }; @@ -165,7 +142,11 @@ export default class LanguageFeatureRegistry { this._lastCandidate = candidate; for (let entry of this._entries) { - entry._score = score(entry.selector, model.getAssociatedResource(), model.getModeId()); + entry._score = score(entry.selector, model.uri, model.getModeId()); + if (entry.isBuiltin && entry._score > 0) { + entry._score = .5; + entry._time = -1; + } } // needs sorting diff --git a/src/vs/editor/common/modes/linkComputer.ts b/src/vs/editor/common/modes/linkComputer.ts index c4953825da6..cea04057a49 100644 --- a/src/vs/editor/common/modes/linkComputer.ts +++ b/src/vs/editor/common/modes/linkComputer.ts @@ -13,7 +13,7 @@ export interface ILinkComputerTarget { // State machine for http:// or https:// var STATE_MAP:{[ch:string]:number}[] = [], START_STATE = 1, END_STATE = 9, ACCEPT_STATE = 10; -STATE_MAP[1] = { 'h': 2, 'H': 2 }; +STATE_MAP[1] = { 'h': 2, 'H': 2, 'f': 11, 'F': 11 }; STATE_MAP[2] = { 't': 3, 'T': 3 }; STATE_MAP[3] = { 't': 4, 'T': 4 }; STATE_MAP[4] = { 'p': 5, 'P': 5 }; @@ -21,6 +21,9 @@ STATE_MAP[5] = { 's': 6, 'S': 6, ':': 7 }; STATE_MAP[6] = { ':': 7 }; STATE_MAP[7] = { '/': 8 }; STATE_MAP[8] = { '/': 9 }; +STATE_MAP[11] = { 'i': 12, 'I': 12 }; +STATE_MAP[12] = { 'l': 13, 'L': 13 }; +STATE_MAP[13] = { 'e': 6, 'E': 6 }; enum CharacterClass { None = 0, diff --git a/src/vs/editor/common/modes/monarch/monarch.ts b/src/vs/editor/common/modes/monarch/monarch.ts deleted file mode 100644 index 87b5ee925e7..00000000000 --- a/src/vs/editor/common/modes/monarch/monarch.ts +++ /dev/null @@ -1,46 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -/** - * Create a syntax highighter with a fully declarative JSON style lexer description - * using regular expressions. - */ - -import {IRichEditSupport, ISuggestSupport, ITokenizationSupport} from 'vs/editor/common/modes'; -import {AbstractMode} from 'vs/editor/common/modes/abstractMode'; -import {ILexer} from 'vs/editor/common/modes/monarch/monarchCommon'; -import {createRichEditSupport, createSuggestSupport} from 'vs/editor/common/modes/monarch/monarchDefinition'; -import {createTokenizationSupport} from 'vs/editor/common/modes/monarch/monarchLexer'; -import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport'; -import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService'; -import {IModeService} from 'vs/editor/common/services/modeService'; -import {IModelService} from 'vs/editor/common/services/modelService'; - -/** - * The MonarchMode creates a Monaco language mode given a certain language description - */ -export abstract class MonarchMode extends AbstractMode { - - public suggestSupport:ISuggestSupport; - public tokenizationSupport: ITokenizationSupport; - public richEditSupport: IRichEditSupport; - - constructor( - modeId:string, - lexer: ILexer, - modeService: IModeService, - modelService: IModelService, - editorWorkerService: IEditorWorkerService - ) { - super(modeId); - - this.tokenizationSupport = createTokenizationSupport(modeService, this, lexer); - - this.richEditSupport = new RichEditSupport(this.getId(), null, createRichEditSupport(lexer)); - - this.suggestSupport = createSuggestSupport(modelService, editorWorkerService, this.getId(), lexer); - } -} diff --git a/src/vs/editor/common/modes/monarch/monarchCommon.ts b/src/vs/editor/common/modes/monarch/monarchCommon.ts index 8f2c3730089..d4762e29cd0 100644 --- a/src/vs/editor/common/modes/monarch/monarchCommon.ts +++ b/src/vs/editor/common/modes/monarch/monarchCommon.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {CharacterPair, IAutoClosingPairConditional, ISuggestion} from 'vs/editor/common/modes'; +import {CharacterPair, IAutoClosingPairConditional} from 'vs/editor/common/modes'; /* * This module exports common types and functionality shared between @@ -41,12 +41,6 @@ export interface ILexer extends ILexerMin { blockCommentStart: string; blockCommentEnd: string; tokenPostfix: string; - suggestSupport: { - textualCompletions: boolean; - disableAutoTrigger: boolean; - triggerCharacters: string[]; - snippets: ISuggestion[]; - }; tokenizer: IRule[][]; brackets: IBracket[]; diff --git a/src/vs/editor/common/modes/monarch/monarchCompile.ts b/src/vs/editor/common/modes/monarch/monarchCompile.ts index 01e4f0ddaa3..b363ff200ae 100644 --- a/src/vs/editor/common/modes/monarch/monarchCompile.ts +++ b/src/vs/editor/common/modes/monarch/monarchCompile.ts @@ -427,43 +427,6 @@ export function compile(json: ILanguage): monarchCommon.ILexer { } } - lexer.suggestSupport = { - textualCompletions: true, - disableAutoTrigger: false, - triggerCharacters: [], - snippets: [] - }; - if (typeof (json).suggestSupport !== 'undefined') { - var suggestSupport = (json).suggestSupport; - - if (Array.isArray(suggestSupport.snippets)) { - var _snippets: any[] = suggestSupport.snippets; - for (var i = 0, len = _snippets.length; i < len; i++) { - if (typeof _snippets[i] === 'string') { - lexer.suggestSupport.snippets.push({ - type: 'snippet', - label: _snippets[i], - codeSnippet: _snippets[i] - }); - } else { - lexer.suggestSupport.snippets.push(_snippets[i]); - } - } - } - - if (Array.isArray(suggestSupport.triggerCharacters)) { - lexer.suggestSupport.triggerCharacters = suggestSupport.triggerCharacters; - } - - if (typeof suggestSupport.textualCompletions !== 'undefined') { - lexer.suggestSupport.textualCompletions = suggestSupport.textualCompletions; - } - - if (typeof suggestSupport.disableAutoTrigger !== 'undefined') { - lexer.suggestSupport.disableAutoTrigger = suggestSupport.disableAutoTrigger; - } - } - // For calling compileAction later on var lexerMin: monarchCommon.ILexerMin = json; lexerMin.name = lexer.name; diff --git a/src/vs/editor/common/modes/monarch/monarchDefinition.ts b/src/vs/editor/common/modes/monarch/monarchDefinition.ts index 8bf3e2eb1d0..123804ca5f8 100644 --- a/src/vs/editor/common/modes/monarch/monarchDefinition.ts +++ b/src/vs/editor/common/modes/monarch/monarchDefinition.ts @@ -9,12 +9,8 @@ * using regular expressions. */ -import {ISuggestSupport} from 'vs/editor/common/modes'; import {ILexer} from 'vs/editor/common/modes/monarch/monarchCommon'; import {IRichEditConfiguration} from 'vs/editor/common/modes/supports/richEditSupport'; -import {PredefinedResultSuggestSupport, TextualAndPredefinedResultSuggestSupport} from 'vs/editor/common/modes/supports/suggestSupport'; -import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService'; -import {IModelService} from 'vs/editor/common/services/modelService'; export function createRichEditSupport(lexer: ILexer): IRichEditConfiguration { @@ -40,24 +36,3 @@ export function createRichEditSupport(lexer: ILexer): IRichEditConfiguration { } }; } - -export function createSuggestSupport(modelService: IModelService, editorWorkerService: IEditorWorkerService, modeId:string, lexer:ILexer): ISuggestSupport { - if (lexer.suggestSupport.textualCompletions) { - return new TextualAndPredefinedResultSuggestSupport( - modeId, - modelService, - editorWorkerService, - lexer.suggestSupport.snippets, - lexer.suggestSupport.triggerCharacters, - lexer.suggestSupport.disableAutoTrigger - ); - } else { - return new PredefinedResultSuggestSupport( - modeId, - modelService, - lexer.suggestSupport.snippets, - lexer.suggestSupport.triggerCharacters, - lexer.suggestSupport.disableAutoTrigger - ); - } -} diff --git a/src/vs/editor/common/modes/monarch/monarchTypes.ts b/src/vs/editor/common/modes/monarch/monarchTypes.ts index 6e65f2141b9..2e818456203 100644 --- a/src/vs/editor/common/modes/monarch/monarchTypes.ts +++ b/src/vs/editor/common/modes/monarch/monarchTypes.ts @@ -4,8 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {ISuggestion} from 'vs/editor/common/modes'; - /* * Interface types for Monarch language definitions * These descriptions are really supposed to be JSON values but if using typescript @@ -79,13 +77,6 @@ export interface ILanguage { // * Advanced auto completion, auto indenting, and bracket matching // */ // enhancedBrackets?: IRegexBracketPair[]; - - suggestSupport?: { - textualCompletions?: boolean; - disableAutoTrigger?: boolean; - triggerCharacters?: string[]; - snippets?: ISuggestion[]; - }; } /** diff --git a/src/vs/editor/common/modes/supports.ts b/src/vs/editor/common/modes/supports.ts index 73aa11209e7..ad60086e7c6 100644 --- a/src/vs/editor/common/modes/supports.ts +++ b/src/vs/editor/common/modes/supports.ts @@ -7,7 +7,7 @@ import * as strings from 'vs/base/common/strings'; import * as objects from 'vs/base/common/objects'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IModel, IPosition} from 'vs/editor/common/editorCommon'; +import {IReadOnlyModel, IPosition} from 'vs/editor/common/editorCommon'; import * as modes from 'vs/editor/common/modes'; import {ModeTransition} from 'vs/editor/common/core/modeTransition'; @@ -71,42 +71,6 @@ export function handleEvent(context:modes.ILineContext, offset:number, runner return runner(nestedMode, newCtx, offset - firstTokenCharacterOffset); } -/** - * Returns {{true}} if the line token at the specified - * offset matches one of the provided types. Matching - * happens on a substring start from the end, unless - * anywhereInToken is set to true in which case matches - * happen on a substring at any position. - */ -export function isLineToken(context:modes.ILineContext, offset:number, types:string[], anywhereInToken:boolean = false):boolean { - - if (!Array.isArray(types) || types.length === 0) { - return false; - } - - if (context.getLineContent().length <= offset) { - return false; - } - - var tokenIdx = context.findIndexOfOffset(offset); - var type = context.getTokenType(tokenIdx); - - for (var i = 0, len = types.length; i < len; i++) { - if (anywhereInToken) { - if (type.indexOf(types[i]) >= 0) { - return true; - } - } - else { - if (strings.endsWith(type, types[i])) { - return true; - } - } - } - - return false; -} - export class FilteredLineContext implements modes.ILineContext { public modeTransitions: ModeTransition[]; @@ -185,7 +149,7 @@ export class SnippetsRegistry { } // the previous - private static getNonWhitespacePrefix(model: IModel, position: IPosition) { + private static getNonWhitespacePrefix(model: IReadOnlyModel, position: IPosition) { let line = model.getLineContent(position.lineNumber); let match = line.match(/[^\s]+$/); if (match) { @@ -194,7 +158,7 @@ export class SnippetsRegistry { return ''; } - public static getSnippets(model: IModel, position: IPosition): modes.ISuggestResult { + public static getSnippets(model: IReadOnlyModel, position: IPosition): modes.ISuggestResult { let word = model.getWordAtPosition(position); let currentWord = word ? word.word.substring(0, position.column - word.startColumn).toLowerCase() : ''; let currentFullWord = SnippetsRegistry.getNonWhitespacePrefix(model, position).toLowerCase(); @@ -203,7 +167,7 @@ export class SnippetsRegistry { suggestions: [] }; - let modeId = model.getMode().getId(); + let modeId = model.getModeId(); let snippets : modes.ISuggestion[]= []; let snipppetsByMode = this._snippets[modeId]; if (snipppetsByMode) { diff --git a/src/vs/editor/common/modes/supports/declarationSupport.ts b/src/vs/editor/common/modes/supports/declarationSupport.ts deleted file mode 100644 index 276b5d495a7..00000000000 --- a/src/vs/editor/common/modes/supports/declarationSupport.ts +++ /dev/null @@ -1,47 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import URI from 'vs/base/common/uri'; -import {TPromise} from 'vs/base/common/winjs.base'; -import {IPosition} from 'vs/editor/common/editorCommon'; -import {IDeclarationSupport, ILineContext, IMode, IReference} from 'vs/editor/common/modes'; -import {handleEvent, isLineToken} from 'vs/editor/common/modes/supports'; - -export interface IDeclarationContribution { - tokens?: string[]; - findDeclaration: (resource: URI, position: IPosition) => TPromise; -} -export class DeclarationSupport implements IDeclarationSupport { - - private _modeId: string; - private contribution: IDeclarationContribution; - - /** - * Provide the token type postfixes for the tokens where a declaration can be found in the 'tokens' argument. - */ - constructor(modeId: string, contribution: IDeclarationContribution) { - this._modeId = modeId; - this.contribution = contribution; - } - - public canFindDeclaration(context: ILineContext, offset:number):boolean { - return handleEvent(context, offset, (nestedMode:IMode, context:ILineContext, offset:number) => { - if (this._modeId === nestedMode.getId()) { - return (!Array.isArray(this.contribution.tokens) || - this.contribution.tokens.length < 1 || - isLineToken(context, offset, this.contribution.tokens)); - } else if (nestedMode.declarationSupport) { - return nestedMode.declarationSupport.canFindDeclaration(context, offset); - } else { - return false; - } - }); - } - - public findDeclaration(resource: URI, position: IPosition): TPromise{ - return this.contribution.findDeclaration(resource, position); - } -} diff --git a/src/vs/editor/common/modes/supports/parameterHintsSupport.ts b/src/vs/editor/common/modes/supports/parameterHintsSupport.ts deleted file mode 100644 index a2371363fa0..00000000000 --- a/src/vs/editor/common/modes/supports/parameterHintsSupport.ts +++ /dev/null @@ -1,55 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import URI from 'vs/base/common/uri'; -import {TPromise} from 'vs/base/common/winjs.base'; -import {IPosition} from 'vs/editor/common/editorCommon'; -import {ILineContext, IMode, IParameterHints, IParameterHintsSupport} from 'vs/editor/common/modes'; -import {handleEvent, isLineToken} from 'vs/editor/common/modes/supports'; - -export interface IParameterHintsContribution { - triggerCharacters: string[]; - excludeTokens: string[]; - getParameterHints: (resource: URI, position: IPosition) => TPromise; -} - -export class ParameterHintsSupport implements IParameterHintsSupport { - - private _modeId: string; - private contribution: IParameterHintsContribution; - - constructor(modeId: string, contribution: IParameterHintsContribution) { - this._modeId = modeId; - this.contribution = contribution; - } - - public getParameterHintsTriggerCharacters(): string[] - { - return this.contribution.triggerCharacters; - } - - public shouldTriggerParameterHints(context: ILineContext, offset: number): boolean - { - return handleEvent(context, offset, (nestedMode:IMode, context:ILineContext, offset:number) => { - if (this._modeId === nestedMode.getId()) { - if (!Array.isArray(this.contribution.excludeTokens)) { - return true; - } - if (this.contribution.excludeTokens.length === 1 && this.contribution.excludeTokens[0] === '*') { - return false; - } - return !isLineToken(context, offset-1, this.contribution.excludeTokens); - } else if (nestedMode.parameterHintsSupport) { - return nestedMode.parameterHintsSupport.shouldTriggerParameterHints(context, offset); - } else { - return false; - } - }); - } - public getParameterHints(resource: URI, position: IPosition): TPromise { - return this.contribution.getParameterHints(resource, position); - } -} diff --git a/src/vs/editor/common/modes/supports/referenceSupport.ts b/src/vs/editor/common/modes/supports/referenceSupport.ts deleted file mode 100644 index a32ab235840..00000000000 --- a/src/vs/editor/common/modes/supports/referenceSupport.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import URI from 'vs/base/common/uri'; -import {TPromise} from 'vs/base/common/winjs.base'; -import {IPosition} from 'vs/editor/common/editorCommon'; -import {ILineContext, IMode, IReference, IReferenceSupport} from 'vs/editor/common/modes'; -import {handleEvent, isLineToken} from 'vs/editor/common/modes/supports'; - -export interface IReferenceContribution { - tokens: string[]; - findReferences: (resource: URI, position: IPosition, includeDeclaration: boolean) => TPromise; -} - -export class ReferenceSupport implements IReferenceSupport { - - private _modeId: string; - private contribution: IReferenceContribution; - - /** - * Provide the token type postfixes for the tokens where a reference can be found in the 'tokens' argument. - */ - constructor(modeId: string, contribution: IReferenceContribution) { - this._modeId = modeId; - this.contribution = contribution; - } - - public canFindReferences(context: ILineContext, offset:number):boolean { - return handleEvent(context, offset, (nestedMode:IMode, context:ILineContext, offset:number) => { - if (this._modeId === nestedMode.getId()) { - return (!Array.isArray(this.contribution.tokens) || - this.contribution.tokens.length < 1 || - isLineToken(context, offset, this.contribution.tokens)); - } else if (nestedMode.referenceSupport) { - return nestedMode.referenceSupport.canFindReferences(context, offset); - } else { - return false; - } - }); - } - - public findReferences(resource: URI, position: IPosition, includeDeclaration: boolean): TPromise { - return this.contribution.findReferences(resource, position, includeDeclaration); - } -} diff --git a/src/vs/editor/common/modes/supports/suggestSupport.ts b/src/vs/editor/common/modes/supports/suggestSupport.ts index d9b63f54f23..f1eadd98c95 100644 --- a/src/vs/editor/common/modes/supports/suggestSupport.ts +++ b/src/vs/editor/common/modes/supports/suggestSupport.ts @@ -4,154 +4,56 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import URI from 'vs/base/common/uri'; -import {TPromise} from 'vs/base/common/winjs.base'; -import {IModel, IPosition} from 'vs/editor/common/editorCommon'; -import {ILineContext, IMode, ISuggestResult, ISuggestSupport, ISuggestion} from 'vs/editor/common/modes'; +import {IReadOnlyModel} from 'vs/editor/common/editorCommon'; +import {ISuggestResult, ISuggestSupport} from 'vs/editor/common/modes'; import {IFilter, matchesStrictPrefix, fuzzyContiguousFilter} from 'vs/base/common/filters'; -import {handleEvent, isLineToken} from 'vs/editor/common/modes/supports'; import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService'; -import {IModelService} from 'vs/editor/common/services/modelService'; - -export interface ISuggestContribution { - triggerCharacters: string[]; - disableAutoTrigger?: boolean; - excludeTokens: string[]; - suggest: (resource: URI, position: IPosition) => TPromise; - getSuggestionDetails? : (resource:URI, position:IPosition, suggestion:ISuggestion) => TPromise; -} - -export class SuggestSupport implements ISuggestSupport { - - private _modeId: string; - private contribution: ISuggestContribution; - - public suggest : (resource:URI, position:IPosition) => TPromise; - public getSuggestionDetails : (resource:URI, position:IPosition, suggestion:ISuggestion) => TPromise; - - constructor(modeId: string, contribution : ISuggestContribution){ - this._modeId = modeId; - this.contribution = contribution; - this.suggest = (resource, position) => contribution.suggest(resource, position); - - if (typeof contribution.getSuggestionDetails === 'function') { - this.getSuggestionDetails = (resource, position, suggestion) => contribution.getSuggestionDetails(resource, position, suggestion); - } - } - - shouldAutotriggerSuggest(context: ILineContext, offset: number, triggeredByCharacter: string): boolean { - return handleEvent(context, offset, (nestedMode:IMode, context:ILineContext, offset:number) => { - if (this._modeId === nestedMode.getId()) { - if (this.contribution.disableAutoTrigger) { - return false; - } - if (!Array.isArray(this.contribution.excludeTokens)) { - return true; - } - if (this.contribution.excludeTokens.length === 1 && this.contribution.excludeTokens[0] === '*') { - return false; - } - return !isLineToken(context, offset-1, this.contribution.excludeTokens, true); - } else if (nestedMode.suggestSupport) { - return nestedMode.suggestSupport.shouldAutotriggerSuggest(context, offset, triggeredByCharacter); - } else { - return false; - } - }); - } - - public getTriggerCharacters(): string[] { - return this.contribution.triggerCharacters; - } -} +import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; +import {IConfigurationRegistry, Extensions} from 'vs/platform/configuration/common/configurationRegistry'; +import {Registry} from 'vs/platform/platform'; +import {localize} from 'vs/nls'; +import {CancellationToken} from 'vs/base/common/cancellation'; +import {wireCancellationToken} from 'vs/base/common/async'; +import {Position} from 'vs/editor/common/core/position'; export class TextualSuggestSupport implements ISuggestSupport { - private _modeId: string; - private _editorWorkerService: IEditorWorkerService; + /* tslint:disable */ + private static _c = Registry.as(Extensions.Configuration).registerConfiguration({ + type: 'object', + properties: { + 'editor.wordBasedSuggestions': { + 'type': 'boolean', + 'description': localize('editor.wordBasedSuggestions', "Enable word based suggestions."), + 'default': true + } + } + }); + /* tslint:enable */ - constructor(modeId: string, editorWorkerService: IEditorWorkerService) { - this._modeId = modeId; - this._editorWorkerService = editorWorkerService; - } - - public suggest(resource: URI, position: IPosition, triggerCharacter?: string): TPromise { - return this._editorWorkerService.textualSuggest(resource, position); + public get triggerCharacters(): string[] { + return []; } public get filter(): IFilter { return matchesStrictPrefix; } - public getTriggerCharacters(): string[] { - return []; + private _editorWorkerService: IEditorWorkerService; + private _configurationService: IConfigurationService; + + constructor(editorWorkerService: IEditorWorkerService, configurationService: IConfigurationService) { + this._editorWorkerService = editorWorkerService; + this._configurationService = configurationService; } - public shouldAutotriggerSuggest(context: ILineContext, offset: number, triggeredByCharacter: string): boolean { - return handleEvent(context, offset, (nestedMode:IMode, context:ILineContext, offset:number) => { - if (this._modeId === nestedMode.getId()) { - return true; - } else if (nestedMode.suggestSupport) { - return nestedMode.suggestSupport.shouldAutotriggerSuggest(context, offset, triggeredByCharacter); - } else { - return false; - } - }); + public provideCompletionItems(model:IReadOnlyModel, position:Position, token:CancellationToken): ISuggestResult[] | Thenable { + let config = this._configurationService.getConfiguration<{ wordBasedSuggestions: boolean }>('editor'); + if (!config || config.wordBasedSuggestions) { + return wireCancellationToken(token, this._editorWorkerService.textualSuggest(model.uri, position)); + } + return []; } - -} - -export class PredefinedResultSuggestSupport extends SuggestSupport { - - constructor(modeId:string, modelService: IModelService, predefined:ISuggestion[], triggerCharacters: string[], disableAutoTrigger?: boolean) { - super(modeId, { - triggerCharacters: triggerCharacters, - disableAutoTrigger: disableAutoTrigger, - excludeTokens: [], - suggest: (resource, position) => { - let model = modelService.getModel(resource); - let result = _addSuggestionsAtPosition(model, position, predefined, null); - return TPromise.as(result); - } - }); - } - -} - -export class TextualAndPredefinedResultSuggestSupport extends SuggestSupport { - - constructor(modeId:string, modelService: IModelService, editorWorkerService: IEditorWorkerService, predefined:ISuggestion[], triggerCharacters: string[], disableAutoTrigger?: boolean) { - super(modeId, { - triggerCharacters: triggerCharacters, - disableAutoTrigger: disableAutoTrigger, - excludeTokens: [], - suggest: (resource, position) => { - return editorWorkerService.textualSuggest(resource, position).then((textualSuggestions) => { - let model = modelService.getModel(resource); - let result = _addSuggestionsAtPosition(model, position, predefined, textualSuggestions); - return result; - }); - } - }); - } - -} - -function _addSuggestionsAtPosition(model: IModel, position:IPosition, predefined:ISuggestion[], superSuggestions:ISuggestResult[]): ISuggestResult[] { - if (!predefined || predefined.length === 0) { - return superSuggestions; - } - - if (!superSuggestions) { - superSuggestions = []; - } - - superSuggestions.push({ - currentWord: model.getWordUntilPosition(position).word, - suggestions: predefined.slice(0) - }); - - return superSuggestions; } export function filterSuggestions(value: ISuggestResult): ISuggestResult[] { diff --git a/src/vs/editor/common/modes/supports/tokenizationSupport.ts b/src/vs/editor/common/modes/supports/tokenizationSupport.ts index 126d10a9157..a4eb4543602 100644 --- a/src/vs/editor/common/modes/supports/tokenizationSupport.ts +++ b/src/vs/editor/common/modes/supports/tokenizationSupport.ts @@ -239,7 +239,7 @@ export class TokenizationSupport implements modes.ITokenizationSupport, IDisposa } if (e.tokenizationSupport) { emitting = true; - this._mode.registerSupport('tokenizationSupport', (mode) => { + this._mode.registerSupport(modes.MutableSupport.TokenizationSupport, (mode) => { return mode.tokenizationSupport; }); emitting = false; diff --git a/src/vs/editor/common/services/bulkEdit.ts b/src/vs/editor/common/services/bulkEdit.ts index aa1ab2adf47..a37c7331c51 100644 --- a/src/vs/editor/common/services/bulkEdit.ts +++ b/src/vs/editor/common/services/bulkEdit.ts @@ -15,7 +15,7 @@ import {EventType as FileEventType, FileChangesEvent, IFileChange} from 'vs/plat import {EditOperation} from 'vs/editor/common/core/editOperation'; import {Range} from 'vs/editor/common/core/range'; import {Selection} from 'vs/editor/common/core/selection'; -import {IEditorSelection, IIdentifiedSingleEditOperation, IModel, IRange, ISelection} from 'vs/editor/common/editorCommon'; +import {IIdentifiedSingleEditOperation, IModel, IRange, ISelection} from 'vs/editor/common/editorCommon'; import {ICommonCodeEditor} from 'vs/editor/common/editorCommon'; export interface IResourceEdit { @@ -42,7 +42,7 @@ class ChangeRecorder { var changes: IStringDictionary = Object.create(null); - var stop = this._eventService.addListener(FileEventType.FILE_CHANGES,(event: FileChangesEvent) => { + var stop = this._eventService.addListener2(FileEventType.FILE_CHANGES,(event: FileChangesEvent) => { event.changes.forEach(change => { var key = String(change.resource), @@ -57,7 +57,7 @@ class ChangeRecorder { }); return { - stop, + stop: () => { stop.dispose(); }, hasChanged: (resource: URI) => !!changes[resource.toString()], allChanges: () => merge(values(changes)) }; @@ -66,8 +66,8 @@ class ChangeRecorder { class EditTask { - private _initialSelections: IEditorSelection[]; - private _endCursorSelection: IEditorSelection; + private _initialSelections: Selection[]; + private _endCursorSelection: Selection; private _model: IModel; private _edits: IIdentifiedSingleEditOperation[]; @@ -97,7 +97,7 @@ class EditTask { this._model.pushEditOperations(this._initialSelections, this._edits, (edits) => this._getEndCursorSelections(edits)); } - protected _getInitialSelections(): IEditorSelection[] { + protected _getInitialSelections(): Selection[] { var firstRange = this._edits[0].range; var initialSelection = Selection.createSelection( firstRange.startLineNumber, @@ -108,7 +108,7 @@ class EditTask { return [initialSelection]; } - private _getEndCursorSelections(inverseEditOperations:IIdentifiedSingleEditOperation[]): IEditorSelection[] { + private _getEndCursorSelections(inverseEditOperations:IIdentifiedSingleEditOperation[]): Selection[] { var relevantEditIndex = 0; for (var i = 0; i < inverseEditOperations.length; i++) { var editRange = inverseEditOperations[i].range; @@ -131,7 +131,7 @@ class EditTask { return [this._endCursorSelection]; } - public getEndCursorSelection(): IEditorSelection { + public getEndCursorSelection(): Selection { return this._endCursorSelection; } @@ -142,14 +142,14 @@ class EditTask { class SourceModelEditTask extends EditTask { - private _knownInitialSelections:IEditorSelection[]; + private _knownInitialSelections:Selection[]; - constructor(model: IModel, initialSelections:IEditorSelection[]) { + constructor(model: IModel, initialSelections:Selection[]) { super(model); this._knownInitialSelections = initialSelections; } - protected _getInitialSelections(): IEditorSelection[] { + protected _getInitialSelections(): Selection[] { return this._knownInitialSelections; } } @@ -162,10 +162,10 @@ class BulkEditModel { private _edits: IStringDictionary = Object.create(null); private _tasks: EditTask[]; private _sourceModel: URI; - private _sourceSelections: IEditorSelection[]; + private _sourceSelections: Selection[]; private _sourceModelTask: SourceModelEditTask; - constructor(editorService: IEditorService, sourceModel: URI, sourceSelections: IEditorSelection[], edits: IResourceEdit[]) { + constructor(editorService: IEditorService, sourceModel: URI, sourceSelections: Selection[], edits: IResourceEdit[]) { this._editorService = editorService; this._sourceModel = sourceModel; this._sourceSelections = sourceSelections; @@ -212,7 +212,7 @@ class BulkEditModel { var textEditorModel = model.textEditorModel, task: EditTask; - if (this._sourceModel && textEditorModel.getAssociatedResource().toString() === this._sourceModel.toString()) { + if (this._sourceModel && textEditorModel.uri.toString() === this._sourceModel.toString()) { this._sourceModelTask = new SourceModelEditTask(textEditorModel, this._sourceSelections); task = this._sourceModelTask; } else { @@ -228,9 +228,9 @@ class BulkEditModel { return TPromise.join(promises).then(_ => this); } - public apply(): IEditorSelection { + public apply(): Selection { this._tasks.forEach(task => task.apply()); - var r: IEditorSelection = null; + var r: Selection = null; if (this._sourceModelTask) { r = this._sourceModelTask.getEndCursorSelection(); } @@ -285,10 +285,10 @@ export function createBulkEdit(eventService: IEventService, editorService: IEdit } let uri: URI; - let selections: IEditorSelection[]; + let selections: Selection[]; if (editor && editor.getModel()) { - uri = editor.getModel().getAssociatedResource(); + uri = editor.getModel().uri; selections = editor.getSelections(); } diff --git a/src/vs/editor/common/services/editorWorkerServiceImpl.ts b/src/vs/editor/common/services/editorWorkerServiceImpl.ts index 0a388e31880..ccaaeb52c72 100644 --- a/src/vs/editor/common/services/editorWorkerServiceImpl.ts +++ b/src/vs/editor/common/services/editorWorkerServiceImpl.ts @@ -174,13 +174,13 @@ export class EditorModelManager extends Disposable { } this._proxy.acceptNewModel({ - url: model.getAssociatedResource().toString(), + url: model.uri.toString(), value: model.toRawText(), versionId: model.getVersionId() }); let toDispose:IDisposable[] = []; - toDispose.push(model.addBulkListener2((events) => { + toDispose.push(model.addBulkListener((events) => { let changedEvents: editorCommon.IModelContentChangedEvent2[] = []; for (let i = 0, len = events.length; i < len; i++) { let e = events[i]; diff --git a/src/vs/editor/common/services/modeService.ts b/src/vs/editor/common/services/modeService.ts index 8c339de9f4e..60ef0f8b5ab 100644 --- a/src/vs/editor/common/services/modeService.ts +++ b/src/vs/editor/common/services/modeService.ts @@ -75,5 +75,6 @@ export interface IModeService { registerRichEditSupport(modeId: string, support: IRichEditConfiguration): IDisposable; registerTokenizationSupport(modeId: string, callback: (mode: modes.IMode) => modes.ITokenizationSupport): IDisposable; + registerTokenizationSupport2(modeId: string, support: modes.ITokenizationSupport2): IDisposable; registerMonarchDefinition(modelService: IModelService, editorWorkerService: IEditorWorkerService, modeId:string, language:ILanguage): IDisposable; } diff --git a/src/vs/editor/common/services/modeServiceImpl.ts b/src/vs/editor/common/services/modeServiceImpl.ts index 651e1e81acd..817a7f1cdca 100644 --- a/src/vs/editor/common/services/modeServiceImpl.ts +++ b/src/vs/editor/common/services/modeServiceImpl.ts @@ -22,16 +22,17 @@ import {FrankensteinMode} from 'vs/editor/common/modes/abstractMode'; import {ILegacyLanguageDefinition, ModesRegistry} from 'vs/editor/common/modes/modesRegistry'; import {ILexer} from 'vs/editor/common/modes/monarch/monarchCommon'; import {compile} from 'vs/editor/common/modes/monarch/monarchCompile'; -import {createRichEditSupport, createSuggestSupport} from 'vs/editor/common/modes/monarch/monarchDefinition'; +import {createRichEditSupport} from 'vs/editor/common/modes/monarch/monarchDefinition'; import {createTokenizationSupport} from 'vs/editor/common/modes/monarch/monarchLexer'; import {ILanguage} from 'vs/editor/common/modes/monarch/monarchTypes'; -import {DeclarationSupport, IDeclarationContribution} from 'vs/editor/common/modes/supports/declarationSupport'; import {IRichEditConfiguration, RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport'; import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService'; import {LanguagesRegistry} from 'vs/editor/common/services/languagesRegistry'; import {ILanguageExtensionPoint, IValidLanguageExtensionPoint, IModeLookupResult, IModeService} from 'vs/editor/common/services/modeService'; import {IModelService} from 'vs/editor/common/services/modelService'; import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; +import {AbstractState} from 'vs/editor/common/modes/abstractState'; +import {Token} from 'vs/editor/common/modes/supports'; interface IModeConfigurationMap { [modeId: string]: any; } @@ -394,16 +395,16 @@ export class ModeServiceImpl implements IModeService { }; } - private _registerModeSupport(mode:modes.IMode, support: string, callback: (mode: modes.IMode) => T): IDisposable { + private _registerModeSupport(mode:modes.IMode, support: modes.MutableSupport, callback: (mode: modes.IMode) => T): IDisposable { if (mode.registerSupport) { return mode.registerSupport(support, callback); } else { - console.warn('Cannot register support ' + support + ' on mode ' + mode.getId() + ' because it does not support it.'); + console.warn('Cannot register support ' + modes.mutableSupportToString(support) + ' on mode ' + mode.getId() + ' because it does not support it.'); return EmptyDisposable; } } - protected registerModeSupport(modeId: string, support: string, callback: (mode: modes.IMode) => T): IDisposable { + protected registerModeSupport(modeId: string, support: modes.MutableSupport, callback: (mode: modes.IMode) => T): IDisposable { if (this._instantiatedModes.hasOwnProperty(modeId)) { return this._registerModeSupport(this._instantiatedModes[modeId], support, callback); } @@ -442,18 +443,105 @@ export class ModeServiceImpl implements IModeService { return this.doRegisterMonarchDefinition(modeId, lexer); } - public registerRichEditSupport(modeId: string, support: IRichEditConfiguration): IDisposable { - return this.registerModeSupport(modeId, 'richEditSupport', (mode) => new RichEditSupport(modeId, mode.richEditSupport, support)); - } - - public registerDeclarativeDeclarationSupport(modeId: string, contribution: IDeclarationContribution): IDisposable { - return this.registerModeSupport(modeId, 'declarationSupport', (mode) => new DeclarationSupport(modeId, contribution)); + return this.registerModeSupport(modeId, modes.MutableSupport.RichEditSupport, (mode) => new RichEditSupport(modeId, mode.richEditSupport, support)); } public registerTokenizationSupport(modeId: string, callback: (mode: modes.IMode) => modes.ITokenizationSupport): IDisposable { - return this.registerModeSupport(modeId, 'tokenizationSupport', callback); + return this.registerModeSupport(modeId, modes.MutableSupport.TokenizationSupport, callback); } + + public registerTokenizationSupport2(modeId: string, support: modes.ITokenizationSupport2): IDisposable { + return this.registerModeSupport(modeId, modes.MutableSupport.TokenizationSupport, (mode) => { + return new TokenizationSupport2Adapter(mode, support); + }); + } +} + +export class TokenizationState2Adapter implements modes.IState { + + private _mode: modes.IMode; + private _actual: modes.IState2; + private _stateData: modes.IState; + + constructor(mode: modes.IMode, actual: modes.IState2, stateData: modes.IState) { + this._mode = mode; + this._actual = actual; + this._stateData = stateData; + } + + public get actual(): modes.IState2 { return this._actual; } + + public clone(): TokenizationState2Adapter { + return new TokenizationState2Adapter(this._mode, this._actual.clone(), AbstractState.safeClone(this._stateData)); + } + + public equals(other:modes.IState): boolean { + if (other instanceof TokenizationState2Adapter) { + if (!this._actual.equals(other._actual)) { + return false; + } + return AbstractState.safeEquals(this._stateData, other._stateData); + } + return false; + } + + public getMode(): modes.IMode { + return this._mode; + } + + public tokenize(stream:any): any { + throw new Error('Unexpected tokenize call!'); + } + + public getStateData(): modes.IState { + return this._stateData; + } + + public setStateData(stateData:modes.IState): void { + this._stateData = stateData; + } +} + +export class TokenizationSupport2Adapter implements modes.ITokenizationSupport { + + public shouldGenerateEmbeddedModels = false; + + private _mode: modes.IMode; + private _actual: modes.ITokenizationSupport2; + + constructor(mode: modes.IMode, actual: modes.ITokenizationSupport2) { + this._mode = mode; + this._actual = actual; + } + + public getInitialState(): modes.IState { + return new TokenizationState2Adapter(this._mode, this._actual.getInitialState(), null); + } + + public tokenize(line:string, state:modes.IState, offsetDelta: number = 0, stopAtOffset?: number): modes.ILineTokens { + if (state instanceof TokenizationState2Adapter) { + let actualResult = this._actual.tokenize(line, state.actual); + let tokens: modes.IToken[] = []; + actualResult.tokens.forEach((t) => { + if (typeof t.scopes === 'string') { + tokens.push(new Token(t.startIndex + offsetDelta, t.scopes)); + } else if (Array.isArray(t.scopes) && t.scopes.length === 1) { + tokens.push(new Token(t.startIndex + offsetDelta, t.scopes[0])); + } else { + throw new Error('Only token scopes as strings or of precisely 1 length are supported at this time!'); + } + }); + return { + tokens: tokens, + actualStopOffset: offsetDelta + line.length, + endState: new TokenizationState2Adapter(state.getMode(), actualResult.endState, state.getStateData()), + modeTransitions: [{ startIndex: offsetDelta, mode: state.getMode() }], + }; + } + throw new Error('Unexpected state to tokenize with!'); + } + } export class MainThreadModeServiceImpl extends ModeServiceImpl { @@ -564,13 +652,7 @@ export class MainThreadModeServiceImpl extends ModeServiceImpl { public registerMonarchDefinition(modelService: IModelService, editorWorkerService:IEditorWorkerService, modeId:string, language:ILanguage): IDisposable { this._getModeServiceWorkerHelper().registerMonarchDefinition(modeId, language); var lexer = compile(objects.clone(language)); - return combinedDisposable( - super.doRegisterMonarchDefinition(modeId, lexer), - - this.registerModeSupport(modeId, 'suggestSupport', (mode) => { - return createSuggestSupport(modelService, editorWorkerService, modeId, lexer); - }) - ); + return super.doRegisterMonarchDefinition(modeId, lexer); } } diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index c5f868bcb44..f98d3ca1fc8 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; import {onUnexpectedError} from 'vs/base/common/errors'; import Event, {Emitter} from 'vs/base/common/event'; -import {IEmitterEvent} from 'vs/base/common/eventEmitter'; +import {EmitterEvent} from 'vs/base/common/eventEmitter'; import {IHTMLContentElement} from 'vs/base/common/htmlContent'; import {IDisposable} from 'vs/base/common/lifecycle'; import Severity from 'vs/base/common/severity'; @@ -47,12 +47,12 @@ class ModelData implements IDisposable { private _markerDecorations: string[]; private _modelEventsListener: IDisposable; - constructor(model: editorCommon.IModel, eventsHandler: (modelData: ModelData, events: IEmitterEvent[]) => void) { + constructor(model: editorCommon.IModel, eventsHandler: (modelData: ModelData, events: EmitterEvent[]) => void) { this.model = model; this.isSyncedToWorkers = false; this._markerDecorations = []; - this._modelEventsListener = model.addBulkListener2((events) => eventsHandler(this, events)); + this._modelEventsListener = model.addBulkListener((events) => eventsHandler(this, events)); } public dispose(): void { @@ -63,7 +63,7 @@ class ModelData implements IDisposable { } public getModelId(): string { - return MODEL_ID(this.model.getAssociatedResource()); + return MODEL_ID(this.model.uri); } public acceptMarkerDecorations(newDecorations: editorCommon.IModelDeltaDecoration[]): void { @@ -90,7 +90,7 @@ class ModelMarkerHandler { private static _createDecorationRange(model: editorCommon.IModel, rawMarker: IMarker): editorCommon.IRange { let marker = model.validateRange(new Range(rawMarker.startLineNumber, rawMarker.startColumn, rawMarker.endLineNumber, rawMarker.endColumn)); - let ret: editorCommon.IEditorRange = new Range(marker.startLineNumber, marker.startColumn, marker.endLineNumber, marker.endColumn); + let ret: Range = new Range(marker.startLineNumber, marker.startColumn, marker.endLineNumber, marker.endColumn); if (ret.isEmpty()) { let word = model.getWordAtPosition(ret.getStartPosition()); if (word) { @@ -368,7 +368,7 @@ export class ModelServiceImpl implements IModelService { private _createModelData(value: string, modeOrPromise: TPromise | IMode, resource: URI): ModelData { // create & save the model let model = new Model(value, this._modelCreationOptions, modeOrPromise, resource); - let modelId = MODEL_ID(model.getAssociatedResource()); + let modelId = MODEL_ID(model.uri); if (this._models[modelId]) { // There already exists a model with this id => this is a programmer error @@ -386,7 +386,7 @@ export class ModelServiceImpl implements IModelService { // handle markers (marker service => model) if (this._markerService) { - ModelMarkerHandler.setMarkers(modelData, this._markerService.read({ resource: modelData.model.getAssociatedResource() })); + ModelMarkerHandler.setMarkers(modelData, this._markerService.read({ resource: modelData.model.uri })); } if (this._shouldSyncModelToWorkers(modelData.model)) { @@ -457,20 +457,20 @@ export class ModelServiceImpl implements IModelService { throw new Error('Model is already not being synced to workers!'); } modelData.isSyncedToWorkers = false; - this._workerHelper.$_acceptDidDisposeModel(modelData.model.getAssociatedResource()); + this._workerHelper.$_acceptDidDisposeModel(modelData.model.uri); } private _onModelDisposing(model: editorCommon.IModel): void { - let modelId = MODEL_ID(model.getAssociatedResource()); + let modelId = MODEL_ID(model.uri); let modelData = this._models[modelId]; // TODO@Joh why are we removing markers here? if (this._markerService) { - var markers = this._markerService.read({ resource: model.getAssociatedResource() }), + var markers = this._markerService.read({ resource: model.uri }), owners: { [o: string]: any } = Object.create(null); markers.forEach(marker => owners[marker.owner] = this); - Object.keys(owners).forEach(owner => this._markerService.changeOne(owner, model.getAssociatedResource(), [])); + Object.keys(owners).forEach(owner => this._markerService.changeOne(owner, model.uri, [])); } if (modelData.isSyncedToWorkers) { @@ -486,14 +486,14 @@ export class ModelServiceImpl implements IModelService { private static _getBoundModelData(model: editorCommon.IModel): IRawModelData { return { - url: model.getAssociatedResource(), + url: model.uri, versionId: model.getVersionId(), value: model.toRawText(), modeId: model.getMode().getId() }; } - private _onModelEvents(modelData: ModelData, events: IEmitterEvent[]): void { + private _onModelEvents(modelData: ModelData, events: EmitterEvent[]): void { // First look for dispose for (let i = 0, len = events.length; i < len; i++) { @@ -554,7 +554,7 @@ export class ModelServiceImpl implements IModelService { for (let i = 0, len = events.length; i < len; i++) { let e = events[i]; - if (e.getType() === editorCommon.EventType.ModelContentChanged) { + if (e.getType() === editorCommon.EventType.ModelRawContentChanged) { eventsForWorkers.contentChanged.push(e.getData()); } } @@ -583,20 +583,20 @@ export class ModelServiceWorkerHelper { public $_acceptNewModel(data: IRawModelData): TPromise { // Create & insert the mirror model eagerly in the resource service let mirrorModel = new MirrorModel(this._resourceService, data.versionId, data.value, null, data.url); - this._resourceService.insert(mirrorModel.getAssociatedResource(), mirrorModel); + this._resourceService.insert(mirrorModel.uri, mirrorModel); // Block worker execution until the mode is instantiated return this._modeService.getOrCreateMode(data.modeId).then((mode) => { // Changing mode should trigger a remove & an add, therefore: // (1) Remove from resource service - this._resourceService.remove(mirrorModel.getAssociatedResource()); + this._resourceService.remove(mirrorModel.uri); // (2) Change mode mirrorModel.setMode(mode); // (3) Insert again to resource service (it will have the new mode) - this._resourceService.insert(mirrorModel.getAssociatedResource(), mirrorModel); + this._resourceService.insert(mirrorModel.uri, mirrorModel); }); } @@ -608,13 +608,13 @@ export class ModelServiceWorkerHelper { // Changing mode should trigger a remove & an add, therefore: // (1) Remove from resource service - this._resourceService.remove(mirrorModel.getAssociatedResource()); + this._resourceService.remove(mirrorModel.uri); // (2) Change mode mirrorModel.setMode(mode); // (3) Insert again to resource service (it will have the new mode) - this._resourceService.insert(mirrorModel.getAssociatedResource(), mirrorModel); + this._resourceService.insert(mirrorModel.uri, mirrorModel); }); } diff --git a/src/vs/editor/common/services/resourceService.ts b/src/vs/editor/common/services/resourceService.ts index 932f5b7082d..9511dd6b1ec 100644 --- a/src/vs/editor/common/services/resourceService.ts +++ b/src/vs/editor/common/services/resourceService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {IEmitterEvent, ListenerCallback, ListenerUnbind} from 'vs/base/common/eventEmitter'; +import {EmitterEvent, ListenerCallback} from 'vs/base/common/eventEmitter'; import {IDisposable} from 'vs/base/common/lifecycle'; import URI from 'vs/base/common/uri'; import {ServiceIdentifier, createDecorator} from 'vs/platform/instantiation/common/instantiation'; @@ -30,7 +30,7 @@ export interface IResourceRemovedEvent { export interface IResourceChangedEvent { url: URI; - originalEvents: IEmitterEvent[]; + originalEvents: EmitterEvent[]; } export var IResourceService = createDecorator('resourceService'); @@ -42,10 +42,6 @@ export interface IResourceService { all(): IMirrorModel[]; contains(url: URI): boolean; remove(url: URI): void; - addListener_(eventType: 'resource.added', listener: (event: IResourceAddedEvent) => void): ListenerUnbind; - addListener_(eventType: 'resource.removed', listener: (event: IResourceRemovedEvent) => void): ListenerUnbind; - addListener_(eventType: 'resource.changed', listener: (event: IResourceChangedEvent) => void): ListenerUnbind; - addListener_(eventType: string, listener: ListenerCallback): ListenerUnbind; addListener2_(eventType: 'resource.added', listener: (event: IResourceAddedEvent) => void): IDisposable; addListener2_(eventType: 'resource.removed', listener: (event: IResourceRemovedEvent) => void): IDisposable; addListener2_(eventType: 'resource.changed', listener: (event: IResourceChangedEvent) => void): IDisposable; diff --git a/src/vs/editor/common/services/resourceServiceImpl.ts b/src/vs/editor/common/services/resourceServiceImpl.ts index 9b8543cc553..8cc3a8856bd 100644 --- a/src/vs/editor/common/services/resourceServiceImpl.ts +++ b/src/vs/editor/common/services/resourceServiceImpl.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {EventEmitter, IEmitterEvent, ListenerCallback, ListenerUnbind} from 'vs/base/common/eventEmitter'; -import {IDisposable} from 'vs/base/common/lifecycle'; +import {EventEmitter, EmitterEvent, ListenerCallback} from 'vs/base/common/eventEmitter'; +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import URI from 'vs/base/common/uri'; import {IMirrorModel} from 'vs/editor/common/editorCommon'; import {IResourceAddedEvent, IResourceChangedEvent, IResourceRemovedEvent, IResourceService, ResourceEvents} from 'vs/editor/common/services/resourceService'; @@ -13,7 +13,7 @@ import {IResourceAddedEvent, IResourceChangedEvent, IResourceRemovedEvent, IReso export class ResourceService extends EventEmitter implements IResourceService { public serviceId = IResourceService; private data:{[url:string]:IMirrorModel;}; - private unbinds:{[url:string]:ListenerUnbind[];}; + private unbinds:{[url:string]:IDisposable[];}; constructor() { super(); @@ -21,10 +21,6 @@ export class ResourceService extends EventEmitter implements IResourceService { this.unbinds = {}; } - public addListener_(eventType: string, listener: ListenerCallback): ListenerUnbind { - return super.addListener(eventType, listener); - } - public addListener2_(eventType: string, listener: ListenerCallback): IDisposable { return super.addListener2(eventType, listener); } @@ -61,7 +57,7 @@ export class ResourceService extends EventEmitter implements IResourceService { var key = url.toString(); this.data[key] = element; this.unbinds[key] = []; - this.unbinds[key].push(element.addBulkListener((value:IEmitterEvent[]) => { + this.unbinds[key].push(element.addBulkListener2((value:EmitterEvent[]) => { this.emit(ResourceEvents.CHANGED, { url: url, originalEvents: value }); })); @@ -96,7 +92,7 @@ export class ResourceService extends EventEmitter implements IResourceService { element = this.data[key]; // stop listen - while(this.unbinds[key].length > 0) { this.unbinds[key].pop()(); } + this.unbinds[key] = dispose(this.unbinds[key]); // removal delete this.unbinds[key]; diff --git a/src/vs/editor/common/view/overviewZoneManager.ts b/src/vs/editor/common/view/overviewZoneManager.ts new file mode 100644 index 00000000000..9c19fe5ff19 --- /dev/null +++ b/src/vs/editor/common/view/overviewZoneManager.ts @@ -0,0 +1,288 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import {OverviewRulerLane, OverviewRulerZone, ColorZone} from 'vs/editor/common/editorCommon'; + +export class OverviewZoneManager { + + private _getVerticalOffsetForLine:(lineNumber:number)=>number; + private _zones: OverviewRulerZone[]; + private _colorZonesInvalid: boolean; + private _lineHeight: number; + private _domWidth: number; + private _domHeight: number; + private _outerHeight: number; + private _maximumHeight: number; + private _minimumHeight: number; + private _useDarkColor: boolean; + private _pixelRatio: number; + + private _lastAssignedId; + private _color2Id: { [color:string]: number; }; + private _id2Color: string[]; + + constructor(getVerticalOffsetForLine:(lineNumber:number)=>number) { + this._getVerticalOffsetForLine = getVerticalOffsetForLine; + this._zones = []; + this._colorZonesInvalid = false; + this._lineHeight = 0; + this._domWidth = 0; + this._domHeight = 0; + this._outerHeight = 0; + this._maximumHeight = 0; + this._minimumHeight = 0; + this._useDarkColor = false; + this._pixelRatio = 1; + + this._lastAssignedId = 0; + this._color2Id = Object.create(null); + this._id2Color = []; + } + + public getId2Color(): string[] { + return this._id2Color; + } + + public setZones(newZones: OverviewRulerZone[]): void { + newZones.sort((a, b) => a.compareTo(b)); + + let oldZones = this._zones; + let oldIndex = 0; + let oldLength = this._zones.length; + let newIndex = 0; + let newLength = newZones.length; + + let result: OverviewRulerZone[] = []; + while (newIndex < newLength) { + let newZone = newZones[newIndex]; + + if (oldIndex >= oldLength) { + result.push(newZone); + newIndex++; + } else { + let oldZone = oldZones[oldIndex]; + let cmp = oldZone.compareTo(newZone); + if (cmp < 0) { + oldIndex++; + } else if (cmp > 0) { + result.push(newZone); + newIndex++; + } else { + // cmp === 0 + result.push(oldZone); + oldIndex++; + newIndex++; + } + } + } + + this._zones = result; + } + + public setLineHeight(lineHeight:number): boolean { + if (this._lineHeight === lineHeight) { + return false; + } + this._lineHeight = lineHeight; + this._colorZonesInvalid = true; + return true; + } + + public setPixelRatio(pixelRatio:number): void { + this._pixelRatio = pixelRatio; + this._colorZonesInvalid = true; + } + + public getDOMWidth(): number { + return this._domWidth; + } + + public getCanvasWidth(): number { + return this._domWidth * this._pixelRatio; + } + + public setDOMWidth(width:number): boolean { + if (this._domWidth === width) { + return false; + } + this._domWidth = width; + this._colorZonesInvalid = true; + return true; + } + + public getDOMHeight(): number { + return this._domHeight; + } + + public getCanvasHeight(): number { + return this._domHeight * this._pixelRatio; + } + + public setDOMHeight(height:number): boolean { + if (this._domHeight === height) { + return false; + } + this._domHeight = height; + this._colorZonesInvalid = true; + return true; + } + + public getOuterHeight(): number { + return this._outerHeight; + } + + public setOuterHeight(outerHeight:number): boolean { + if (this._outerHeight === outerHeight) { + return false; + } + this._outerHeight = outerHeight; + this._colorZonesInvalid = true; + return true; + } + + public setMaximumHeight(maximumHeight:number): boolean { + if (this._maximumHeight === maximumHeight) { + return false; + } + this._maximumHeight = maximumHeight; + this._colorZonesInvalid = true; + return true; + } + + public setMinimumHeight(minimumHeight:number): boolean { + if (this._minimumHeight === minimumHeight) { + return false; + } + this._minimumHeight = minimumHeight; + this._colorZonesInvalid = true; + return true; + } + + public setUseDarkColor(useDarkColor:boolean): boolean { + if (this._useDarkColor === useDarkColor) { + return false; + } + this._useDarkColor = useDarkColor; + this._colorZonesInvalid = true; + return true; + } + + public resolveColorZones(): ColorZone[] { + const colorZonesInvalid = this._colorZonesInvalid; + const lineHeight = Math.floor(this._lineHeight); // @perf + const totalHeight = Math.floor(this.getCanvasHeight()); // @perf + const maximumHeight = Math.floor(this._maximumHeight * this._pixelRatio); // @perf + const minimumHeight = Math.floor(this._minimumHeight * this._pixelRatio); // @perf + const useDarkColor = this._useDarkColor; // @perf + const outerHeight = Math.floor(this._outerHeight); // @perf + const heightRatio = totalHeight / outerHeight; + + let allColorZones: ColorZone[] = []; + for (let i = 0, len = this._zones.length; i < len; i++) { + let zone = this._zones[i]; + + if (!colorZonesInvalid) { + let colorZones = zone.getColorZones(); + if (colorZones) { + for (let j = 0, lenJ = colorZones.length; j < lenJ; j++) { + allColorZones.push(colorZones[j]); + } + continue; + } + } + + let colorZones: ColorZone[] = []; + if (zone.forceHeight) { + let forcedHeight = Math.floor(zone.forceHeight * this._pixelRatio); + + let y1 = Math.floor(this._getVerticalOffsetForLine(zone.startLineNumber)); + y1 = Math.floor(y1 * heightRatio); + + let y2 = y1 + forcedHeight; + colorZones.push(this.createZone(totalHeight, y1, y2, forcedHeight, forcedHeight, zone.getColor(useDarkColor), zone.position)); + } else { + let y1 = Math.floor(this._getVerticalOffsetForLine(zone.startLineNumber)); + let y2 = Math.floor(this._getVerticalOffsetForLine(zone.endLineNumber)) + lineHeight; + + y1 = Math.floor(y1 * heightRatio); + y2 = Math.floor(y2 * heightRatio); + + // Figure out if we can render this in one continuous zone + let zoneLineNumbers = zone.endLineNumber - zone.startLineNumber + 1; + let zoneMaximumHeight = zoneLineNumbers * maximumHeight; + + if (y2 - y1 > zoneMaximumHeight) { + // We need to draw one zone per line + for (let lineNumber = zone.startLineNumber; lineNumber <= zone.endLineNumber; lineNumber++) { + y1 = Math.floor(this._getVerticalOffsetForLine(lineNumber)); + y2 = y1 + lineHeight; + + y1 = Math.floor(y1 * heightRatio); + y2 = Math.floor(y2 * heightRatio); + + colorZones.push(this.createZone(totalHeight, y1, y2, minimumHeight, maximumHeight, zone.getColor(useDarkColor), zone.position)); + } + } else { + colorZones.push(this.createZone(totalHeight, y1, y2, minimumHeight, zoneMaximumHeight, zone.getColor(useDarkColor), zone.position)); + } + } + + zone.setColorZones(colorZones); + for (let j = 0, lenJ = colorZones.length; j < lenJ; j++) { + allColorZones.push(colorZones[j]); + } + } + + this._colorZonesInvalid = false; + + let sortFunc = (a:ColorZone, b:ColorZone) => { + if (a.colorId === b.colorId) { + if (a.from === b.from) { + return a.to - b.to; + } + return a.from - b.from; + } + return a.colorId - b.colorId; + }; + + allColorZones.sort(sortFunc); + return allColorZones; + } + + public createZone(totalHeight:number, y1:number, y2:number, minimumHeight:number, maximumHeight:number, color:string, position:OverviewRulerLane): ColorZone { + totalHeight = Math.floor(totalHeight); // @perf + y1 = Math.floor(y1); // @perf + y2 = Math.floor(y2); // @perf + minimumHeight = Math.floor(minimumHeight); // @perf + maximumHeight = Math.floor(maximumHeight); // @perf + + let ycenter = Math.floor((y1 + y2) / 2); + let halfHeight = (y2 - ycenter); + + + if (halfHeight > maximumHeight / 2) { + halfHeight = maximumHeight / 2; + } + if (halfHeight < minimumHeight / 2) { + halfHeight = minimumHeight / 2; + } + + if (ycenter - halfHeight < 0) { + ycenter = halfHeight; + } + if (ycenter + halfHeight > totalHeight) { + ycenter = totalHeight - halfHeight; + } + + let colorId = this._color2Id[color]; + if (!colorId) { + colorId = (++this._lastAssignedId); + this._color2Id[color] = colorId; + this._id2Color[colorId] = color; + } + return new ColorZone(ycenter - halfHeight, ycenter + halfHeight, colorId, position); + } +} diff --git a/src/vs/editor/common/view/renderingContext.ts b/src/vs/editor/common/view/renderingContext.ts index 819113afeb4..9fc441e2594 100644 --- a/src/vs/editor/common/view/renderingContext.ts +++ b/src/vs/editor/common/view/renderingContext.ts @@ -4,8 +4,9 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {IModelDecoration, IRange, IEditorRange, IPosition} from 'vs/editor/common/editorCommon'; +import {IModelDecoration, IRange, IPosition} from 'vs/editor/common/editorCommon'; import {ViewLinesViewportData} from 'vs/editor/common/viewLayout/viewLinesViewportData'; +import {Range} from 'vs/editor/common/core/range'; export interface IRestrictedRenderingContext { linesViewportData:ViewLinesViewportData; @@ -13,7 +14,7 @@ export interface IRestrictedRenderingContext { scrollWidth:number; scrollHeight:number; - visibleRange:IEditorRange; + visibleRange:Range; bigNumbersDelta:number; viewportTop:number; diff --git a/src/vs/editor/common/view/viewContext.ts b/src/vs/editor/common/view/viewContext.ts index 7eb0a32e79f..a6b322238ec 100644 --- a/src/vs/editor/common/view/viewContext.ts +++ b/src/vs/editor/common/view/viewContext.ts @@ -5,7 +5,7 @@ 'use strict'; import {IConfiguration} from 'vs/editor/common/editorCommon'; -import {IEmitterEvent} from 'vs/base/common/eventEmitter'; +import {EmitterEvent} from 'vs/base/common/eventEmitter'; import {IViewModel} from 'vs/editor/common/viewModel/viewModel'; export interface IViewEventBus { @@ -13,7 +13,7 @@ export interface IViewEventBus { } export interface IViewEventHandler { - handleEvents(events:IEmitterEvent[]): void; + handleEvents(events:EmitterEvent[]): void; } export class ViewContext { diff --git a/src/vs/editor/common/viewLayout/viewLineParts.ts b/src/vs/editor/common/viewLayout/viewLineParts.ts index 93e7a068c28..e6b94b5f80d 100644 --- a/src/vs/editor/common/viewLayout/viewLineParts.ts +++ b/src/vs/editor/common/viewLayout/viewLineParts.ts @@ -6,7 +6,6 @@ import * as strings from 'vs/base/common/strings'; import {Arrays} from 'vs/editor/common/core/arrays'; -import {IEditorRange} from 'vs/editor/common/editorCommon'; import {Range} from 'vs/editor/common/core/range'; import {ViewLineToken, ViewLineTokens} from 'vs/editor/common/core/viewLineToken'; @@ -362,7 +361,7 @@ class Stack { } export interface ILineDecoration { - range: IEditorRange; + range: Range; options: { inlineClassName?: string; }; diff --git a/src/vs/editor/common/viewLayout/viewLinesViewportData.ts b/src/vs/editor/common/viewLayout/viewLinesViewportData.ts index ae996a94f0c..42f6b5e8c1a 100644 --- a/src/vs/editor/common/viewLayout/viewLinesViewportData.ts +++ b/src/vs/editor/common/viewLayout/viewLinesViewportData.ts @@ -4,8 +4,9 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {IModelDecoration, IEditorRange} from 'vs/editor/common/editorCommon'; +import {IModelDecoration} from 'vs/editor/common/editorCommon'; import {IDecorationsViewportData} from 'vs/editor/common/viewModel/viewModel'; +import {Range} from 'vs/editor/common/core/range'; export interface IPartialViewLinesViewportData { viewportTop: number; @@ -40,12 +41,12 @@ export class ViewLinesViewportData { /** * The viewport as a range (`startLineNumber`,1) -> (`endLineNumber`,maxColumn(`endLineNumber`)). */ - visibleRange:IEditorRange; + visibleRange:Range; private _decorations: IModelDecoration[]; private _inlineDecorations: IModelDecoration[][]; - constructor(partialData:IPartialViewLinesViewportData, visibleRange:IEditorRange, decorationsData:IDecorationsViewportData) { + constructor(partialData:IPartialViewLinesViewportData, visibleRange:Range, decorationsData:IDecorationsViewportData) { this.viewportTop = partialData.viewportTop|0; this.viewportHeight = partialData.viewportHeight|0; this.bigNumbersDelta = partialData.bigNumbersDelta|0; diff --git a/src/vs/editor/common/viewModel/splitLinesCollection.ts b/src/vs/editor/common/viewModel/splitLinesCollection.ts index 6630b0c2ac3..956a86ccbab 100644 --- a/src/vs/editor/common/viewModel/splitLinesCollection.ts +++ b/src/vs/editor/common/viewModel/splitLinesCollection.ts @@ -50,7 +50,7 @@ export interface ISplitLine { getOutputLineMaxColumn(model: IModel, myLineNumber: number, outputLineIndex: number): number; getOutputLineTokens(model: IModel, myLineNumber: number, outputLineIndex: number): ViewLineTokens; getInputColumnOfOutputPosition(outputLineIndex: number, outputColumn: number): number; - getOutputPositionOfInputPosition(deltaLineNumber: number, inputColumn: number): editorCommon.IEditorPosition; + getOutputPositionOfInputPosition(deltaLineNumber: number, inputColumn: number): Position; } class IdentitySplitLine implements ISplitLine { @@ -111,7 +111,7 @@ class IdentitySplitLine implements ISplitLine { return outputColumn; } - public getOutputPositionOfInputPosition(deltaLineNumber:number, inputColumn:number): editorCommon.IEditorPosition { + public getOutputPositionOfInputPosition(deltaLineNumber:number, inputColumn:number): Position { if (!this._isVisible) { throw new Error('Not supported'); } @@ -223,7 +223,7 @@ export class SplitLine implements ISplitLine { return this.positionMapper.getInputOffsetOfOutputPosition(outputLineIndex, adjustedColumn) + 1; } - public getOutputPositionOfInputPosition(deltaLineNumber:number, inputColumn:number): editorCommon.IEditorPosition { + public getOutputPositionOfInputPosition(deltaLineNumber:number, inputColumn:number): Position { if (!this._isVisible) { throw new Error('Not supported'); } @@ -325,13 +325,13 @@ export class SplitLinesCollection implements ILinesCollection { this.prefixSumComputer = new PrefixSumComputer(values); } - private getHiddenAreas(): editorCommon.IEditorRange[] { + private getHiddenAreas(): Range[] { return this.hiddenAreasIds.map((decId) => { return this.model.getDecorationRange(decId); }).sort(Range.compareRangesUsingStarts); } - private _reduceRanges(_ranges:editorCommon.IRange[]): editorCommon.IEditorRange[] { + private _reduceRanges(_ranges:editorCommon.IRange[]): Range[] { if (_ranges.length === 0) { return []; } @@ -663,7 +663,7 @@ export class SplitLinesCollection implements ILinesCollection { return this.lines[lineIndex].getOutputLineTokens(this.model, lineIndex + 1, remainder); } - public convertOutputPositionToInputPosition(viewLineNumber: number, viewColumn: number): editorCommon.IEditorPosition { + public convertOutputPositionToInputPosition(viewLineNumber: number, viewColumn: number): Position { this._ensureValidState(); viewLineNumber = this._toValidOutputLineNumber(viewLineNumber); @@ -676,7 +676,7 @@ export class SplitLinesCollection implements ILinesCollection { return this.model.validatePosition(new Position(lineIndex+1, inputColumn)); } - public convertInputPositionToOutputPosition(_inputLineNumber: number, _inputColumn: number): editorCommon.IEditorPosition { + public convertInputPositionToOutputPosition(_inputLineNumber: number, _inputColumn: number): Position { this._ensureValidState(); let validPosition = this.model.validatePosition(new Position(_inputLineNumber, _inputColumn)); @@ -695,7 +695,7 @@ export class SplitLinesCollection implements ILinesCollection { } let deltaLineNumber = 1 + (lineIndex === 0 ? 0 : this.prefixSumComputer.getAccumulatedValue(lineIndex - 1)); - let r:editorCommon.IEditorPosition; + let r:Position; if (lineIndexChanged) { r = this.lines[lineIndex].getOutputPositionOfInputPosition(deltaLineNumber, this.model.getLineMaxColumn(lineIndex + 1)); } else { diff --git a/src/vs/editor/common/viewModel/viewEventHandler.ts b/src/vs/editor/common/viewModel/viewEventHandler.ts index c5889d87f16..06883bbca7d 100644 --- a/src/vs/editor/common/viewModel/viewEventHandler.ts +++ b/src/vs/editor/common/viewModel/viewEventHandler.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {IEmitterEvent} from 'vs/base/common/eventEmitter'; +import {EmitterEvent} from 'vs/base/common/eventEmitter'; import * as editorCommon from 'vs/editor/common/editorCommon'; export class ViewEventHandler { @@ -80,7 +80,7 @@ export class ViewEventHandler { // --- end event handlers - public handleEvents(events:IEmitterEvent[]): void { + public handleEvents(events:EmitterEvent[]): void { let shouldRender = false; diff --git a/src/vs/editor/common/viewModel/viewModel.ts b/src/vs/editor/common/viewModel/viewModel.ts index 1ce3f1b4f52..5f23de698ae 100644 --- a/src/vs/editor/common/viewModel/viewModel.ts +++ b/src/vs/editor/common/viewModel/viewModel.ts @@ -5,8 +5,11 @@ 'use strict'; import {IEventEmitter} from 'vs/base/common/eventEmitter'; -import {IModelDecoration, IRange, IEditorRange, EndOfLinePreference, IEditorSelection, IPosition, IEditorPosition} from 'vs/editor/common/editorCommon'; +import {IModelDecoration, IRange, EndOfLinePreference, IPosition} from 'vs/editor/common/editorCommon'; import {ViewLineTokens} from 'vs/editor/common/core/viewLineToken'; +import {Position} from 'vs/editor/common/core/position'; +import {Range} from 'vs/editor/common/core/range'; +import {Selection} from 'vs/editor/common/core/selection'; export interface IDecorationsViewportData { decorations: IModelDecoration[]; @@ -30,15 +33,15 @@ export interface IViewModel extends IEventEmitter { getEOL(): string; getValueInRange(range:IRange, eol:EndOfLinePreference): string; - getSelections(): IEditorSelection[]; + getSelections(): Selection[]; - convertViewPositionToModelPosition(viewLineNumber:number, viewColumn:number): IEditorPosition; - convertViewRangeToModelRange(viewRange:IRange): IEditorRange; + convertViewPositionToModelPosition(viewLineNumber:number, viewColumn:number): Position; + convertViewRangeToModelRange(viewRange:IRange): Range; getModelLineContent(lineNumber:number): string; getModelLineMaxColumn(modelLineNumber:number): number; - validateModelPosition(position:IPosition): IEditorPosition; - convertModelPositionToViewPosition(modelLineNumber:number, modelColumn:number): IEditorPosition; - convertModelSelectionToViewSelection(modelSelection:IEditorSelection): IEditorSelection; + validateModelPosition(position:IPosition): Position; + convertModelPositionToViewPosition(modelLineNumber:number, modelColumn:number): Position; + convertModelSelectionToViewSelection(modelSelection:Selection): Selection; modelPositionIsVisible(position:IPosition): boolean; } diff --git a/src/vs/editor/common/viewModel/viewModelCursors.ts b/src/vs/editor/common/viewModel/viewModelCursors.ts index c618a666827..5f59728fde7 100644 --- a/src/vs/editor/common/viewModel/viewModelCursors.ts +++ b/src/vs/editor/common/viewModel/viewModelCursors.ts @@ -7,12 +7,13 @@ import {Range} from 'vs/editor/common/core/range'; import {Selection} from 'vs/editor/common/core/selection'; import * as editorCommon from 'vs/editor/common/editorCommon'; +import {Position} from 'vs/editor/common/core/position'; export interface IConverter { - validateViewPosition(viewLineNumber:number, viewColumn:number, modelPosition:editorCommon.IEditorPosition): editorCommon.IEditorPosition; - validateViewSelection(viewSelection:editorCommon.IEditorSelection, modelSelection:editorCommon.IEditorSelection): editorCommon.IEditorSelection; - convertModelSelectionToViewSelection(modelSelection:editorCommon.IEditorSelection): editorCommon.IEditorSelection; - convertModelRangeToViewRange(modelRange:editorCommon.IRange): editorCommon.IEditorRange; + validateViewPosition(viewLineNumber:number, viewColumn:number, modelPosition:Position): Position; + validateViewSelection(viewSelection:Selection, modelSelection:Selection): Selection; + convertModelSelectionToViewSelection(modelSelection:Selection): Selection; + convertModelRangeToViewRange(modelRange:editorCommon.IRange): Range; } export class ViewModelCursors { @@ -30,9 +31,9 @@ export class ViewModelCursors { this.lastCursorSelectionChangedEvent = null; } - public getSelections(): editorCommon.IEditorSelection[] { + public getSelections(): Selection[] { if (this.lastCursorSelectionChangedEvent) { - var selections:editorCommon.IEditorSelection[] = []; + var selections:Selection[] = []; selections.push(this.converter.convertModelSelectionToViewSelection(this.lastCursorSelectionChangedEvent.selection)); for (var i = 0, len = this.lastCursorSelectionChangedEvent.secondarySelections.length; i < len; i++) { selections.push(this.converter.convertModelSelectionToViewSelection(this.lastCursorSelectionChangedEvent.secondarySelections[i])); @@ -54,7 +55,7 @@ export class ViewModelCursors { position = position.clone(); position.column = stopRenderingLineAfter; } - var secondaryPositions: editorCommon.IEditorPosition[] = []; + var secondaryPositions: Position[] = []; for (var i = 0, len = e.secondaryPositions.length; i < len; i++) { secondaryPositions[i] = this.converter.validateViewPosition(e.secondaryViewPositions[i].lineNumber, e.secondaryViewPositions[i].column, e.secondaryPositions[i]); // Limit position to be somewhere where it can actually be rendered @@ -76,7 +77,7 @@ export class ViewModelCursors { this.lastCursorSelectionChangedEvent = e; let selection = this.converter.validateViewSelection(e.viewSelection, e.selection); - let secondarySelections: editorCommon.IEditorSelection[] = []; + let secondarySelections: Selection[] = []; for (let i = 0, len = e.secondarySelections.length; i < len; i++) { secondarySelections[i] = this.converter.validateViewSelection(e.secondaryViewSelections[i], e.secondarySelections[i]); } @@ -89,7 +90,7 @@ export class ViewModelCursors { } public onCursorRevealRange(e:editorCommon.ICursorRevealRangeEvent, emit:(eventType:string, payload:any)=>void): void { - var viewRange:editorCommon.IEditorRange = null; + var viewRange:Range = null; if (e.viewRange) { var viewStartRange = this.converter.validateViewPosition(e.viewRange.startLineNumber, e.viewRange.startColumn, e.range.getStartPosition()); var viewEndRange = this.converter.validateViewPosition(e.viewRange.endLineNumber, e.viewRange.endColumn, e.range.getEndPosition()); diff --git a/src/vs/editor/common/viewModel/viewModelDecorations.ts b/src/vs/editor/common/viewModel/viewModelDecorations.ts index a8aee77ec26..ecdee3ee269 100644 --- a/src/vs/editor/common/viewModel/viewModelDecorations.ts +++ b/src/vs/editor/common/viewModel/viewModelDecorations.ts @@ -10,7 +10,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import {IDecorationsViewportData} from 'vs/editor/common/viewModel/viewModel'; export interface IModelRangeToViewRangeConverter { - convertModelRangeToViewRange(modelRange:editorCommon.IRange, isWholeLine:boolean): editorCommon.IEditorRange; + convertModelRangeToViewRange(modelRange:editorCommon.IRange, isWholeLine:boolean): Range; } interface IViewModelDecoration extends editorCommon.IModelDecoration { @@ -27,11 +27,11 @@ interface IViewModelDecorationSource { class ViewModelDecoration implements IViewModelDecoration { id: string; ownerId: number; - range: editorCommon.IEditorRange; + range: Range; options: editorCommon.IModelDecorationOptions; modelRange: editorCommon.IRange; - constructor(source:IViewModelDecorationSource, range:editorCommon.IEditorRange) { + constructor(source:IViewModelDecorationSource, range:Range) { this.id = source.id; this.options = source.options; this.ownerId = source.ownerId; @@ -187,7 +187,7 @@ export class ViewModelDecorations implements IDisposable { var decorations = this.decorations, d:IViewModelDecoration, i:number, - newRange:editorCommon.IEditorRange, + newRange:Range, somethingChanged:boolean = false, inlineDecorationsChanged = false, len:number; diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index e9bae0dc8b6..77b1de638f8 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {EmitterEvent, EventEmitter, IEmitterEvent, IEventEmitter, ListenerUnbind} from 'vs/base/common/eventEmitter'; +import {EmitterEvent, EventEmitter, IEventEmitter} from 'vs/base/common/eventEmitter'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import * as strings from 'vs/base/common/strings'; import {Position} from 'vs/editor/common/core/position'; @@ -30,8 +30,8 @@ export interface ILinesCollection { getOutputLineMinColumn(outputLineNumber:number): number; getOutputLineMaxColumn(outputLineNumber:number): number; getOutputLineTokens(outputLineNumber:number): ViewLineTokens; - convertOutputPositionToInputPosition(viewLineNumber:number, viewColumn:number): editorCommon.IEditorPosition; - convertInputPositionToOutputPosition(inputLineNumber:number, inputColumn:number): editorCommon.IEditorPosition; + convertOutputPositionToInputPosition(viewLineNumber:number, viewColumn:number): Position; + convertInputPositionToOutputPosition(inputLineNumber:number, inputColumn:number): Position; setHiddenAreas(ranges:editorCommon.IRange[], emit:(evenType:string, payload:any)=>void): void; inputPositionIsVisible(inputLineNumber:number, inputColumn:number): boolean; dispose(): void; @@ -43,15 +43,15 @@ export class ViewModel extends EventEmitter implements IViewModel { private configuration:editorCommon.IConfiguration; private model:editorCommon.IModel; - private listenersToRemove:ListenerUnbind[]; + private listenersToRemove:IDisposable[]; private _toDispose: IDisposable[]; private lines:ILinesCollection; private decorations:ViewModelDecorations; private cursors:ViewModelCursors; - private getCurrentCenteredModelRange:()=>editorCommon.IEditorRange; + private getCurrentCenteredModelRange:()=>Range; - constructor(lines:ILinesCollection, editorId:number, configuration:editorCommon.IConfiguration, model:editorCommon.IModel, getCurrentCenteredModelRange:()=>editorCommon.IEditorRange) { + constructor(lines:ILinesCollection, editorId:number, configuration:editorCommon.IConfiguration, model:editorCommon.IModel, getCurrentCenteredModelRange:()=>Range) { super(); this.lines = lines; @@ -75,7 +75,7 @@ export class ViewModel extends EventEmitter implements IViewModel { this.listenersToRemove = []; this._toDispose = []; - this.listenersToRemove.push(this.model.addBulkListener((events:IEmitterEvent[]) => this.onEvents(events))); + this.listenersToRemove.push(this.model.addBulkListener((events:EmitterEvent[]) => this.onEvents(events))); this._toDispose.push(this.configuration.onDidChange((e) => { this.onEvents([new EmitterEvent(editorCommon.EventType.ConfigurationChanged, e)]); })); @@ -93,11 +93,8 @@ export class ViewModel extends EventEmitter implements IViewModel { } public dispose(): void { - this.listenersToRemove.forEach((element) => { - element(); - }); + this.listenersToRemove = dispose(this.listenersToRemove); this._toDispose = dispose(this._toDispose); - this.listenersToRemove = []; this.decorations.dispose(); this.decorations = null; this.lines.dispose(); @@ -126,7 +123,7 @@ export class ViewModel extends EventEmitter implements IViewModel { return lineMappingChanged; } - private _restoreCenteredModelRange(range:editorCommon.IEditorRange): void { + private _restoreCenteredModelRange(range:Range): void { // modelLine -> viewLine var newCenteredViewRange = this.convertModelRangeToViewRange(range); @@ -150,14 +147,14 @@ export class ViewModel extends EventEmitter implements IViewModel { } public addEventSource(eventSource:IEventEmitter): void { - this.listenersToRemove.push(eventSource.addBulkListener((events:IEmitterEvent[]) => this.onEvents(events))); + this.listenersToRemove.push(eventSource.addBulkListener2((events:EmitterEvent[]) => this.onEvents(events))); } - private onEvents(events:IEmitterEvent[]): void { + private onEvents(events:EmitterEvent[]): void { this.deferredEmit(() => { - let hasContentChange = events.some((e) => e.getType() === editorCommon.EventType.ModelContentChanged), - previousCenteredModelRange:editorCommon.IEditorRange; + let hasContentChange = events.some((e) => e.getType() === editorCommon.EventType.ModelRawContentChanged), + previousCenteredModelRange:Range; if (!hasContentChange) { // We can only convert the current centered view range to the current centered model range if the model has no changes. previousCenteredModelRange = this.getCurrentCenteredModelRange(); @@ -165,7 +162,7 @@ export class ViewModel extends EventEmitter implements IViewModel { let i:number, len:number, - e: IEmitterEvent, + e: EmitterEvent, data:any, modelContentChangedEvent:editorCommon.IModelContentChangedEvent, hadOtherModelChange = false, @@ -178,26 +175,26 @@ export class ViewModel extends EventEmitter implements IViewModel { switch (e.getType()) { - case editorCommon.EventType.ModelContentChanged: + case editorCommon.EventType.ModelRawContentChanged: modelContentChangedEvent = data; switch (modelContentChangedEvent.changeType) { - case editorCommon.EventType.ModelContentChangedFlush: + case editorCommon.EventType.ModelRawContentChangedFlush: this.onModelFlushed(modelContentChangedEvent); hadOtherModelChange = true; break; - case editorCommon.EventType.ModelContentChangedLinesDeleted: + case editorCommon.EventType.ModelRawContentChangedLinesDeleted: this.onModelLinesDeleted(modelContentChangedEvent); hadOtherModelChange = true; break; - case editorCommon.EventType.ModelContentChangedLinesInserted: + case editorCommon.EventType.ModelRawContentChangedLinesInserted: this.onModelLinesInserted(modelContentChangedEvent); hadOtherModelChange = true; break; - case editorCommon.EventType.ModelContentChangedLineChanged: + case editorCommon.EventType.ModelRawContentChangedLineChanged: hadModelLineChangeThatChangedLineMapping = this.onModelLineChanged(modelContentChangedEvent); break; @@ -319,13 +316,13 @@ export class ViewModel extends EventEmitter implements IViewModel { this.lines.onModelLinesInserted(e.versionId, e.fromLineNumber, e.toLineNumber, e.detail.split('\n'), (eventType:string, payload:any) => this.emit(eventType, payload)); } - public validateViewRange(viewStartLineNumber:number, viewStartColumn:number, viewEndLineNumber:number, viewEndColumn:number, modelRange:editorCommon.IEditorRange): editorCommon.IEditorRange { + public validateViewRange(viewStartLineNumber:number, viewStartColumn:number, viewEndLineNumber:number, viewEndColumn:number, modelRange:Range): Range { var validViewStart = this.validateViewPosition(viewStartColumn, viewStartColumn, modelRange.getStartPosition()); var validViewEnd = this.validateViewPosition(viewEndLineNumber, viewEndColumn, modelRange.getEndPosition()); return new Range(validViewStart.lineNumber, validViewStart.column, validViewEnd.lineNumber, validViewEnd.column); } - public validateViewPosition(viewLineNumber:number, viewColumn:number, modelPosition:editorCommon.IEditorPosition): editorCommon.IEditorPosition { + public validateViewPosition(viewLineNumber:number, viewColumn:number, modelPosition:Position): Position { if (viewLineNumber < 1) { viewLineNumber = 1; } @@ -348,7 +345,7 @@ export class ViewModel extends EventEmitter implements IViewModel { return this.convertModelPositionToViewPosition(modelPosition.lineNumber, modelPosition.column); } - public validateViewSelection(viewSelection:editorCommon.IEditorSelection, modelSelection:editorCommon.IEditorSelection): editorCommon.IEditorSelection { + public validateViewSelection(viewSelection:Selection, modelSelection:Selection): Selection { let modelSelectionStart = new Position(modelSelection.selectionStartLineNumber, modelSelection.selectionStartColumn); let modelPosition = new Position(modelSelection.positionLineNumber, modelSelection.positionColumn); @@ -443,23 +440,23 @@ export class ViewModel extends EventEmitter implements IViewModel { return this.model.getValueInRange(modelRange, eol); } - public getSelections(): editorCommon.IEditorSelection[] { + public getSelections(): Selection[] { return this.cursors.getSelections(); } // View -> Model conversion and related methods - public convertViewPositionToModelPosition(viewLineNumber:number, viewColumn:number): editorCommon.IEditorPosition { + public convertViewPositionToModelPosition(viewLineNumber:number, viewColumn:number): Position { return this.lines.convertOutputPositionToInputPosition(viewLineNumber, viewColumn); } - public convertViewRangeToModelRange(viewRange:editorCommon.IRange): editorCommon.IEditorRange { + public convertViewRangeToModelRange(viewRange:editorCommon.IRange): Range { var start = this.convertViewPositionToModelPosition(viewRange.startLineNumber, viewRange.startColumn); var end = this.convertViewPositionToModelPosition(viewRange.endLineNumber, viewRange.endColumn); return new Range(start.lineNumber, start.column, end.lineNumber, end.column); } - public convertViewSelectionToModelSelection(viewSelection:editorCommon.ISelection): editorCommon.IEditorSelection { + public convertViewSelectionToModelSelection(viewSelection:editorCommon.ISelection): Selection { let selectionStart = this.convertViewPositionToModelPosition(viewSelection.selectionStartLineNumber, viewSelection.selectionStartColumn); let position = this.convertViewPositionToModelPosition(viewSelection.positionLineNumber, viewSelection.positionColumn); return new Selection(selectionStart.lineNumber, selectionStart.column, position.lineNumber, position.column); @@ -475,27 +472,27 @@ export class ViewModel extends EventEmitter implements IViewModel { return this.model.getLineMaxColumn(modelLineNumber); } - public validateModelPosition(position:editorCommon.IPosition): editorCommon.IEditorPosition { + public validateModelPosition(position:editorCommon.IPosition): Position { return this.model.validatePosition(position); } - public convertModelPositionToViewPosition(modelLineNumber:number, modelColumn:number): editorCommon.IEditorPosition { + public convertModelPositionToViewPosition(modelLineNumber:number, modelColumn:number): Position { return this.lines.convertInputPositionToOutputPosition(modelLineNumber, modelColumn); } - public convertModelRangeToViewRange(modelRange:editorCommon.IRange): editorCommon.IEditorRange { + public convertModelRangeToViewRange(modelRange:editorCommon.IRange): Range { var start = this.convertModelPositionToViewPosition(modelRange.startLineNumber, modelRange.startColumn); var end = this.convertModelPositionToViewPosition(modelRange.endLineNumber, modelRange.endColumn); return new Range(start.lineNumber, start.column, end.lineNumber, end.column); } - public convertWholeLineModelRangeToViewRange(modelRange:editorCommon.IRange): editorCommon.IEditorRange { + public convertWholeLineModelRangeToViewRange(modelRange:editorCommon.IRange): Range { var start = this.convertModelPositionToViewPosition(modelRange.startLineNumber, 1); var end = this.convertModelPositionToViewPosition(modelRange.endLineNumber, this.model.getLineMaxColumn(modelRange.endLineNumber)); return new Range(start.lineNumber, start.column, end.lineNumber, end.column); } - public convertModelSelectionToViewSelection(modelSelection:editorCommon.IEditorSelection): editorCommon.IEditorSelection { + public convertModelSelectionToViewSelection(modelSelection:Selection): Selection { var selectionStart = this.convertModelPositionToViewPosition(modelSelection.selectionStartLineNumber, modelSelection.selectionStartColumn); var position = this.convertModelPositionToViewPosition(modelSelection.positionLineNumber, modelSelection.positionColumn); return new Selection(selectionStart.lineNumber, selectionStart.column, position.lineNumber, position.column); diff --git a/src/vs/editor/common/worker/editorWorkerServer.ts b/src/vs/editor/common/worker/editorWorkerServer.ts index 34a27bd4e6d..f283ad9318a 100644 --- a/src/vs/editor/common/worker/editorWorkerServer.ts +++ b/src/vs/editor/common/worker/editorWorkerServer.ts @@ -21,8 +21,7 @@ import {SecondaryMarkerService} from 'vs/platform/markers/common/markerService'; import {IMarkerService} from 'vs/platform/markers/common/markers'; import {BaseRequestService} from 'vs/platform/request/common/baseRequestService'; import {IRequestService} from 'vs/platform/request/common/request'; -import {RemoteTelemetryService} from 'vs/platform/telemetry/common/remoteTelemetryService'; -import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; +import {NullTelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {WorkerThreadService} from 'vs/platform/thread/common/workerThreadService'; import {IThreadService} from 'vs/platform/thread/common/thread'; import {BaseWorkspaceContextService} from 'vs/platform/workspace/common/baseWorkspaceContextService'; @@ -101,11 +100,10 @@ export class EditorWorkerServer { const contextService = new BaseWorkspaceContextService(initData.contextService.workspace, initData.contextService.configuration, initData.contextService.options); this.threadService = new WorkerThreadService(mainThread.getRemoteCom()); this.threadService.setInstantiationService(new InstantiationService(new ServiceCollection([IThreadService, this.threadService]))); - const telemetryServiceInstance = new RemoteTelemetryService('workerTelemetry', this.threadService); const resourceService = new ResourceService(); const markerService = new SecondaryMarkerService(this.threadService); const modeService = new ModeServiceImpl(this.threadService, extensionService); - const requestService = new BaseRequestService(contextService, telemetryServiceInstance); + const requestService = new BaseRequestService(contextService, NullTelemetryService); services.set(IExtensionService, extensionService); services.set(IThreadService, this.threadService); @@ -114,7 +112,6 @@ export class EditorWorkerServer { services.set(IEventService, new EventService()); services.set(IResourceService, resourceService); services.set(IMarkerService, markerService); - services.set(ITelemetryService, telemetryServiceInstance); services.set(IRequestService, requestService); const instantiationService = new InstantiationService(services); diff --git a/src/vs/editor/common/worker/validationHelper.ts b/src/vs/editor/common/worker/validationHelper.ts index 0d1b2b6a276..695b6f2bbfb 100644 --- a/src/vs/editor/common/worker/validationHelper.ts +++ b/src/vs/editor/common/worker/validationHelper.ts @@ -5,7 +5,7 @@ 'use strict'; import {RunOnceScheduler} from 'vs/base/common/async'; -import {IEmitterEvent} from 'vs/base/common/eventEmitter'; +import {EmitterEvent} from 'vs/base/common/eventEmitter'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import URI from 'vs/base/common/uri'; import {IMirrorModel} from 'vs/editor/common/editorCommon'; @@ -31,9 +31,7 @@ class ValidationModel implements IDisposable { this._changeCallback = changeCallback; this._model = model; this._isDirty = false; - this._toDispose.push({ - dispose: model.addBulkListener((events) => this._onModelChanged(events)) - }); + this._toDispose.push(model.addBulkListener2((events) => this._onModelChanged(events))); } public dispose(): void { @@ -57,7 +55,7 @@ class ValidationModel implements IDisposable { return this._model; } - private _onModelChanged(events:IEmitterEvent[]): void { + private _onModelChanged(events:EmitterEvent[]): void { var containsChanged = false; for (var i = 0; !containsChanged && i < events.length; i++) { if (events[i].getType() === 'changed') { @@ -130,7 +128,7 @@ export class ValidationHelper implements IDisposable { var model = element; var validationModel = new ValidationModel(model, (model) => this._onChanged(model)); - this._models[model.getAssociatedResource().toString()] = validationModel; + this._models[model.uri.toString()] = validationModel; this._onChanged(validationModel); } @@ -170,10 +168,10 @@ export class ValidationHelper implements IDisposable { .map((modelUrl) => this._models[modelUrl]) .forEach((model) => { if (model.isDirty()) { - dirtyModels.push(model.getMirrorModel().getAssociatedResource()); + dirtyModels.push(model.getMirrorModel().uri); model.markAsClean(); } else { - cleanModels.push(model.getMirrorModel().getAssociatedResource()); + cleanModels.push(model.getMirrorModel().uri); } }); diff --git a/src/vs/editor/contrib/accessibility/browser/accessibility.ts b/src/vs/editor/contrib/accessibility/browser/accessibility.ts index fcaa87a2d09..08a5c86ba13 100644 --- a/src/vs/editor/contrib/accessibility/browser/accessibility.ts +++ b/src/vs/editor/contrib/accessibility/browser/accessibility.ts @@ -21,7 +21,7 @@ import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegi import {GlobalScreenReaderNVDA} from 'vs/editor/common/config/commonEditorConfig'; import {EditorAction} from 'vs/editor/common/editorAction'; import {Behaviour} from 'vs/editor/common/editorActionEnablement'; -import {EventType, ICommonCodeEditor, IEditorActionDescriptorData, IEditorContribution, SHOW_ACCESSIBILITY_HELP_ACTION_ID} from 'vs/editor/common/editorCommon'; +import {ICommonCodeEditor, IEditorActionDescriptorData, IEditorContribution, SHOW_ACCESSIBILITY_HELP_ACTION_ID} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; import {ICodeEditor, IOverlayWidget, IOverlayWidgetPosition} from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; @@ -91,7 +91,7 @@ class AccessibilityHelpWidget extends Widget implements IOverlayWidget { this._domNode.setAttribute('aria-hidden', 'true'); this._isVisible = false; - this._register(this._editor.addListener2(EventType.EditorLayout, () => { + this._register(this._editor.onDidLayoutChange(() => { if (this._isVisible) { this._layout(); } diff --git a/src/vs/editor/contrib/clipboard/browser/clipboard.ts b/src/vs/editor/contrib/clipboard/browser/clipboard.ts index fe2234238d0..8a1fc72c0e1 100644 --- a/src/vs/editor/contrib/clipboard/browser/clipboard.ts +++ b/src/vs/editor/contrib/clipboard/browser/clipboard.ts @@ -8,7 +8,7 @@ import 'vs/css!./clipboard'; import * as nls from 'vs/nls'; import {KeyCode, KeyMod} from 'vs/base/common/keyCodes'; -import {cAll} from 'vs/base/common/lifecycle'; +import {dispose, IDisposable} from 'vs/base/common/lifecycle'; import {TPromise} from 'vs/base/common/winjs.base'; import * as browser from 'vs/base/browser/browser'; import {ServicesAccessor} from 'vs/platform/instantiation/common/instantiation'; @@ -21,18 +21,18 @@ import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/edito class ClipboardWritingAction extends EditorAction { - private toUnhook:Function[]; + private toUnhook:IDisposable[]; constructor(descriptor:editorCommon.IEditorActionDescriptorData, editor:editorCommon.ICommonCodeEditor, condition:Behaviour) { super(descriptor, editor, condition); this.toUnhook = []; - this.toUnhook.push(this.editor.addListener(editorCommon.EventType.CursorSelectionChanged, (e:editorCommon.ICursorSelectionChangedEvent) => { + this.toUnhook.push(this.editor.onDidChangeCursorSelection((e:editorCommon.ICursorSelectionChangedEvent) => { this.resetEnablementState(); })); } public dispose(): void { - this.toUnhook = cAll(this.toUnhook); + this.toUnhook = dispose(this.toUnhook); super.dispose(); } diff --git a/src/vs/editor/contrib/codelens/browser/codelens.ts b/src/vs/editor/contrib/codelens/browser/codelens.ts index 9956057da14..efd64738c08 100644 --- a/src/vs/editor/contrib/codelens/browser/codelens.ts +++ b/src/vs/editor/contrib/codelens/browser/codelens.ts @@ -6,7 +6,7 @@ 'use strict'; import 'vs/css!./codelens'; -import {RunOnceScheduler} from 'vs/base/common/async'; +import {RunOnceScheduler, asWinJsPromise} from 'vs/base/common/async'; import {onUnexpectedError} from 'vs/base/common/errors'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import Severity from 'vs/base/common/severity'; @@ -17,7 +17,7 @@ import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingServic import {IMessageService} from 'vs/platform/message/common/message'; import {Range} from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import {CodeLensRegistry, ICodeLensSymbol, ICommand} from 'vs/editor/common/modes'; +import {CodeLensProviderRegistry, ICodeLensSymbol, ICommand} from 'vs/editor/common/modes'; import {IModelService} from 'vs/editor/common/services/modelService'; import * as editorBrowser from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; @@ -54,12 +54,12 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget { private _domNode: HTMLElement; private _subscription: IDisposable; - private _symbolRange: editorCommon.IEditorRange; + private _symbolRange: Range; private _widgetPosition: editorBrowser.IContentWidgetPosition; private _editor: editorBrowser.ICodeEditor; private _commands: { [id: string]: ICommand } = Object.create(null); - public constructor(editor: editorBrowser.ICodeEditor, symbolRange: editorCommon.IEditorRange, + public constructor(editor: editorBrowser.ICodeEditor, symbolRange: Range, keybindingService: IKeybindingService, messageService: IMessageService) { this._id = 'codeLensWidget' + (++CodeLensContentWidget.ID); @@ -132,7 +132,7 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget { return this._domNode; } - public setSymbolRange(range: editorCommon.IEditorRange): void { + public setSymbolRange(range: Range): void { this._symbolRange = range; const lineNumber = range.startLineNumber; @@ -158,7 +158,7 @@ function modelsVersionId(modelService: IModelService, modeId: string): number { .filter(model => model.getMode().getId() === modeId) .map((model) => { return { - url: model.getAssociatedResource().toString(), + url: model.uri.toString(), versionId: model.getVersionId() }; }) @@ -362,21 +362,16 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { this._currentFindCodeLensSymbolsPromise = null; this._modelChangeCounter = 0; - this._globalToDispose.push(this._editor.addListener2(editorCommon.EventType.ModelChanged, () => this.onModelChange())); - this._globalToDispose.push(this._editor.addListener2(editorCommon.EventType.ModelModeChanged, () => this.onModelChange())); - this._globalToDispose.push(this._editor.addListener2(editorCommon.EventType.ModelModeSupportChanged, (e: editorCommon.IModeSupportChangedEvent) => { - if (e.codeLensSupport) { - this.onModelChange(); - } - })); - this._globalToDispose.push(this._editor.addListener2(editorCommon.EventType.ConfigurationChanged, (e: editorCommon.IConfigurationChangedEvent) => { + this._globalToDispose.push(this._editor.onDidChangeModel(() => this.onModelChange())); + this._globalToDispose.push(this._editor.onDidChangeModelMode(() => this.onModelChange())); + this._globalToDispose.push(this._editor.onDidChangeConfiguration((e: editorCommon.IConfigurationChangedEvent) => { let prevIsEnabled = this._isEnabled; this._isEnabled = this._editor.getConfiguration().contribInfo.referenceInfos; if (prevIsEnabled !== this._isEnabled) { this.onModelChange(); } })); - this._globalToDispose.push(CodeLensRegistry.onDidChange(this.onModelChange, this)); + this._globalToDispose.push(CodeLensProviderRegistry.onDidChange(this.onModelChange, this)); this.onModelChange(); } @@ -415,7 +410,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { return; } - if (!CodeLensRegistry.has(model)) { + if (!CodeLensProviderRegistry.has(model)) { return; } @@ -441,11 +436,11 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { }, 250); this._localToDispose.push(scheduler); this._localToDispose.push(detectVisible); - this._localToDispose.push(model.addBulkListener2((events) => { + this._localToDispose.push(model.addBulkListener((events) => { let hadChange = false; for (let i = 0; i < events.length; i++) { const eventType = events[i].getType(); - if (eventType === editorCommon.EventType.ModelContentChanged) { + if (eventType === editorCommon.EventType.ModelRawContentChanged) { hadChange = true; break; } @@ -477,8 +472,10 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { scheduler.schedule(); } })); - this._localToDispose.push(this._editor.addListener2('scroll', (e) => { - detectVisible.schedule(); + this._localToDispose.push(this._editor.onDidScrollChange((e) => { + if (e.scrollTopChanged) { + detectVisible.schedule(); + } })); this._localToDispose.push({ dispose: () => { @@ -609,12 +606,13 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { return; } - const resource = model.getAssociatedResource(); const promises = toResolve.map((request, i) => { const resolvedSymbols = new Array(request.length); const promises = request.map((request, i) => { - return request.support.resolveCodeLensSymbol(resource, request.symbol).then(symbol => { + return asWinJsPromise((token) => { + return request.support.resolveCodeLens(model, request.symbol, token); + }).then(symbol => { resolvedSymbols[i] = symbol; }); }); diff --git a/src/vs/editor/contrib/codelens/common/codelens.ts b/src/vs/editor/contrib/codelens/common/codelens.ts index d164353183e..114525ed034 100644 --- a/src/vs/editor/contrib/codelens/common/codelens.ts +++ b/src/vs/editor/contrib/codelens/common/codelens.ts @@ -10,19 +10,22 @@ import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import {IModel} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; -import {CodeLensRegistry, ICodeLensSupport, ICodeLensSymbol} from 'vs/editor/common/modes'; +import {CodeLensProviderRegistry, CodeLensProvider, ICodeLensSymbol} from 'vs/editor/common/modes'; import {IModelService} from 'vs/editor/common/services/modelService'; +import {asWinJsPromise} from 'vs/base/common/async'; export interface ICodeLensData { symbol: ICodeLensSymbol; - support: ICodeLensSupport; + support: CodeLensProvider; } export function getCodeLensData(model: IModel): TPromise { const symbols: ICodeLensData[] = []; - const promises = CodeLensRegistry.all(model).map(support => { - return support.findCodeLensSymbols(model.getAssociatedResource()).then(result => { + const promises = CodeLensProviderRegistry.all(model).map(support => { + return asWinJsPromise((token) => { + return support.provideCodeLenses(model, token); + }).then(result => { if (!Array.isArray(result)) { return; } diff --git a/src/vs/editor/contrib/color/browser/color.ts b/src/vs/editor/contrib/color/browser/color.ts index 13f10e27ecd..fa00975e206 100644 --- a/src/vs/editor/contrib/color/browser/color.ts +++ b/src/vs/editor/contrib/color/browser/color.ts @@ -8,12 +8,13 @@ import 'vs/css!./color'; import {RunOnceScheduler} from 'vs/base/common/async'; import {onUnexpectedError} from 'vs/base/common/errors'; -import {IDisposable, cAll, dispose} from 'vs/base/common/lifecycle'; +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import * as strings from 'vs/base/common/strings'; import {TPromise} from 'vs/base/common/winjs.base'; import * as dom from 'vs/base/browser/dom'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; +import {Range} from 'vs/editor/common/core/range'; class ColorDecoration { public static createRenderingDecoration(range:editorCommon.IRange, inlineClassName:string): editorCommon.IModelDeltaDecoration { @@ -73,7 +74,7 @@ export class ColorContribution implements editorCommon.IEditorContribution { private _decorationsChangedScheduler:RunOnceScheduler; private _callOnDispose:IDisposable[]; - private _callOnModelChange:IFunction[]; + private _callOnModelChange:IDisposable[]; private _currentFindColorDeclarationsPromise:TPromise<{range:editorCommon.IRange; value:string; }[]>; private _currentDecorations:ColorDecoration[]; @@ -94,9 +95,9 @@ export class ColorContribution implements editorCommon.IEditorContribution { this._callOnDispose.push(this._contentChangedScheduler); this._callOnDispose.push(this._decorationsChangedScheduler); - this._callOnDispose.push(this._editor.addListener2(editorCommon.EventType.ModelChanged, () => this.onModelChange())); - this._callOnDispose.push(this._editor.addListener2(editorCommon.EventType.ModelModeChanged,() => this.onModelChange())); - this._callOnDispose.push(this._editor.addListener2(editorCommon.EventType.ModelModeSupportChanged,(e: editorCommon.IModeSupportChangedEvent) => { + this._callOnDispose.push(this._editor.onDidChangeModel(() => this.onModelChange())); + this._callOnDispose.push(this._editor.onDidChangeModelMode(() => this.onModelChange())); + this._callOnDispose.push(this._editor.onDidChangeModelModeSupport((e: editorCommon.IModeSupportChangedEvent) => { this.onModelChange(); })); @@ -126,7 +127,7 @@ export class ColorContribution implements editorCommon.IEditorContribution { } private onModelChange(): void { - cAll(this._callOnModelChange); + this._callOnModelChange = dispose(this._callOnModelChange); var model = this._editor.getModel(); if(!model) { @@ -143,7 +144,7 @@ export class ColorContribution implements editorCommon.IEditorContribution { this._currentFindColorDeclarationsPromise.cancel(); } - this._currentFindColorDeclarationsPromise = rawMode['findColorDeclarations'](model.getAssociatedResource()); + this._currentFindColorDeclarationsPromise = rawMode['findColorDeclarations'](model.uri); var myModelVersion = this._editor.getModel().getVersionId(); this._currentFindColorDeclarationsPromise.then((result) => { @@ -158,18 +159,22 @@ export class ColorContribution implements editorCommon.IEditorContribution { this._contentChangedScheduler.schedule(); - this._callOnModelChange.push(() => { - this._contentChangedScheduler.cancel(); - this._decorationsChangedScheduler.cancel(); - }); - this._callOnModelChange.push(() => { - if (this._currentFindColorDeclarationsPromise) { - this._currentFindColorDeclarationsPromise.cancel(); + this._callOnModelChange.push({ + dispose: () => { + this._contentChangedScheduler.cancel(); + this._decorationsChangedScheduler.cancel(); } - this._currentFindColorDeclarationsPromise = null; }); - this._callOnModelChange.push(this._editor.addListener(editorCommon.EventType.ModelContentChanged, (event) => this._contentChangedScheduler.schedule())); - this._callOnModelChange.push(model.addListener(editorCommon.EventType.ModelDecorationsChanged, (event) => this._decorationsChangedScheduler.schedule())); + this._callOnModelChange.push({ + dispose: () => { + if (this._currentFindColorDeclarationsPromise) { + this._currentFindColorDeclarationsPromise.cancel(); + } + this._currentFindColorDeclarationsPromise = null; + } + }); + this._callOnModelChange.push(this._editor.onDidChangeModelContent((event) => this._contentChangedScheduler.schedule())); + this._callOnModelChange.push(model.onDidChangeDecorations((event) => this._decorationsChangedScheduler.schedule())); } private renderAndTrackColors(colors:{range:editorCommon.IRange; value:string; }[]): void { @@ -206,8 +211,8 @@ export class ColorContribution implements editorCommon.IEditorContribution { var model = this._editor.getModel(), i:number, len:number, - range:editorCommon.IEditorRange, - renderingRange:editorCommon.IEditorRange, + range:Range, + renderingRange:Range, desiredRenderingRange:editorCommon.IRange, decoration: ColorDecoration, desiredColors: string[] = []; diff --git a/src/vs/editor/contrib/comment/common/blockCommentCommand.ts b/src/vs/editor/contrib/comment/common/blockCommentCommand.ts index 2e258b1c6ea..30d6bd41cfc 100644 --- a/src/vs/editor/contrib/comment/common/blockCommentCommand.ts +++ b/src/vs/editor/contrib/comment/common/blockCommentCommand.ts @@ -13,10 +13,10 @@ import {ICommentsConfiguration} from 'vs/editor/common/modes'; export class BlockCommentCommand implements editorCommon.ICommand { - private _selection: editorCommon.IEditorSelection; + private _selection: Selection; private _usedEndToken: string; - constructor(selection:editorCommon.IEditorSelection) { + constructor(selection:Selection) { this._selection = selection; this._usedEndToken = null; } @@ -136,7 +136,7 @@ export class BlockCommentCommand implements editorCommon.ICommand { }, config, model, builder); } - public computeCursorState(model:editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): editorCommon.IEditorSelection { + public computeCursorState(model:editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): Selection { var inverseEditOperations = helper.getInverseEditOperations(); if (inverseEditOperations.length === 2) { var startTokenEditOperation = inverseEditOperations[0]; diff --git a/src/vs/editor/contrib/comment/common/lineCommentCommand.ts b/src/vs/editor/contrib/comment/common/lineCommentCommand.ts index 6a473c4338d..57cb19c4942 100644 --- a/src/vs/editor/contrib/comment/common/lineCommentCommand.ts +++ b/src/vs/editor/contrib/comment/common/lineCommentCommand.ts @@ -43,14 +43,14 @@ export enum Type { export class LineCommentCommand implements editorCommon.ICommand { - private _selection: editorCommon.IEditorSelection; + private _selection: Selection; private _selectionId: string; private _deltaColumn:number; private _moveEndPositionDown: boolean; private _tabSize: number; private _type:Type; - constructor(selection:editorCommon.IEditorSelection, tabSize:number, type:Type) { + constructor(selection:Selection, tabSize:number, type:Type) { this._selection = selection; this._tabSize = tabSize; this._type = type; @@ -205,7 +205,7 @@ export class LineCommentCommand implements editorCommon.ICommand { /** * Given a successful analysis, execute either insert line comments, either remove line comments */ - private _executeLineComments(model:ISimpleModel, builder:editorCommon.IEditOperationBuilder, data:IPreflightData, s:editorCommon.IEditorSelection): void { + private _executeLineComments(model:ISimpleModel, builder:editorCommon.IEditOperationBuilder, data:IPreflightData, s:Selection): void { var ops:editorCommon.IIdentifiedSingleEditOperation[]; @@ -228,7 +228,7 @@ export class LineCommentCommand implements editorCommon.ICommand { this._selectionId = builder.trackSelection(s); } - private _attemptRemoveBlockComment(model:editorCommon.ITokenizedModel, s:editorCommon.IEditorSelection, startToken: string, endToken: string): editorCommon.IIdentifiedSingleEditOperation[] { + private _attemptRemoveBlockComment(model:editorCommon.ITokenizedModel, s:Selection, startToken: string, endToken: string): editorCommon.IIdentifiedSingleEditOperation[] { let startLineNumber = s.startLineNumber; let endLineNumber = s.endLineNumber; @@ -272,7 +272,7 @@ export class LineCommentCommand implements editorCommon.ICommand { /** * Given an unsuccessful analysis, delegate to the block comment command */ - private _executeBlockComment(model:editorCommon.ITokenizedModel, builder:editorCommon.IEditOperationBuilder, s:editorCommon.IEditorSelection): void { + private _executeBlockComment(model:editorCommon.ITokenizedModel, builder:editorCommon.IEditOperationBuilder, s:Selection): void { let richEditSupport = model.getModeAtPosition(s.startLineNumber, s.startColumn).richEditSupport; let config = richEditSupport ? richEditSupport.comments : null; if (!config || !config.blockCommentStartToken || !config.blockCommentEndToken) { @@ -335,7 +335,7 @@ export class LineCommentCommand implements editorCommon.ICommand { return this._executeBlockComment(model, builder, s); } - public computeCursorState(model:editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): editorCommon.IEditorSelection { + public computeCursorState(model:editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): Selection { var result = helper.getTrackedSelection(this._selectionId); if (this._moveEndPositionDown) { diff --git a/src/vs/editor/contrib/contextmenu/browser/contextmenu.ts b/src/vs/editor/contrib/contextmenu/browser/contextmenu.ts index 01b8bc3392e..d43874e4507 100644 --- a/src/vs/editor/contrib/contextmenu/browser/contextmenu.ts +++ b/src/vs/editor/contrib/contextmenu/browser/contextmenu.ts @@ -17,7 +17,7 @@ import {IContextMenuService, IContextViewService} from 'vs/platform/contextview/ import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; import {EditorAction} from 'vs/editor/common/editorAction'; import {Behaviour} from 'vs/editor/common/editorActionEnablement'; -import {EventType, ICommonCodeEditor, IEditorActionDescriptorData, IEditorContribution, MouseTargetType} from 'vs/editor/common/editorCommon'; +import {ICommonCodeEditor, IEditorActionDescriptorData, IEditorContribution, MouseTargetType} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; import {ICodeEditor, IEditorMouseEvent} from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; @@ -49,8 +49,8 @@ class ContextMenuController implements IEditorContribution { this._contextMenuIsBeingShownCount = 0; - this._toDispose.push(this._editor.addListener2(EventType.ContextMenu, (e:IEditorMouseEvent)=>this._onContextMenu(e))); - this._toDispose.push(this._editor.addListener2(EventType.KeyDown, (e:IKeyboardEvent)=> { + this._toDispose.push(this._editor.onContextMenu((e:IEditorMouseEvent)=>this._onContextMenu(e))); + this._toDispose.push(this._editor.onKeyDown((e:IKeyboardEvent)=> { if (e.keyCode === KeyCode.ContextMenu) { // Chrome is funny like that e.preventDefault(); diff --git a/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts b/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts index 848ad7d9660..b1b71ccafcd 100644 --- a/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts +++ b/src/vs/editor/contrib/defineKeybinding/browser/defineKeybinding.ts @@ -26,6 +26,7 @@ import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/edito import {ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, OverlayWidgetPositionPreference} from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {CodeSnippet, getSnippetController} from 'vs/editor/contrib/snippet/common/snippet'; +import {SmartSnippetInserter} from 'vs/editor/contrib/defineKeybinding/common/smartSnippetInserter'; const NLS_LAUNCH_MESSAGE = nls.localize('defineKeybinding.start', "Define Keybinding"); const NLS_DEFINE_MESSAGE = nls.localize('defineKeybinding.initial', "Press desired key combination and ENTER"); @@ -61,14 +62,14 @@ export class DefineKeybindingController implements editorCommon.IEditorContribut this._launchWidget = new DefineKeybindingLauncherWidget(this._editor, keybindingService, () => this.launch()); this._defineWidget = new DefineKeybindingWidget(this._editor, keybindingService, (keybinding) => this._onAccepted(keybinding)); - this._toDispose.push(this._editor.addListener2(editorCommon.EventType.ConfigurationChanged, (e) => { + this._toDispose.push(this._editor.onDidChangeConfiguration((e) => { if (isInterestingEditorModel(this._editor)) { this._launchWidget.show(); } else { this._launchWidget.hide(); } })); - this._toDispose.push(this._editor.addListener2(editorCommon.EventType.ModelChanged, (e) => { + this._toDispose.push(this._editor.onDidChangeModel((e) => { if (isInterestingEditorModel(this._editor)) { this._launchWidget.show(); } else { @@ -112,6 +113,10 @@ export class DefineKeybindingController implements editorCommon.IEditorContribut '}{{}}' ].join('\n'); + let smartInsertInfo = SmartSnippetInserter.insertSnippet(this._editor.getModel(), this._editor.getPosition()); + snippetText = smartInsertInfo.prepend + snippetText + smartInsertInfo.append; + this._editor.setPosition(smartInsertInfo.position); + getSnippetController(this._editor).run(new CodeSnippet(snippetText), 0, 0); } @@ -123,12 +128,12 @@ export class DefineKeybindingController implements editorCommon.IEditorContribut return; } - let url = model.getAssociatedResource().toString(); + let url = model.uri.toString(); if (!INTERESTING_FILE.test(url)) { return; } - this._modelToDispose.push(model.addListener2(editorCommon.EventType.ModelContentChanged2, (e) => this._updateDecorations.schedule())); + this._modelToDispose.push(model.onDidChangeContent((e) => this._updateDecorations.schedule())); this._modelToDispose.push({ dispose: () => { this._dec = this._editor.deltaDecorations(this._dec, []); @@ -374,7 +379,7 @@ class DefineKeybindingWidget implements IOverlayWidget { let htmlkb = this._keybindingService.getHTMLLabelFor(this._lastKeybinding); htmlkb.forEach((item) => this._outputNode.appendChild(renderHtml(item))); })); - this._toDispose.push(this._editor.addListener2(editorCommon.EventType.ConfigurationChanged, (e) => { + this._toDispose.push(this._editor.onDidChangeConfiguration((e) => { if (this._isVisible) { this._layout(); } @@ -479,7 +484,7 @@ function isInterestingEditorModel(editor:editorCommon.ICommonCodeEditor): boolea if (!model) { return false; } - let url = model.getAssociatedResource().toString(); + let url = model.uri.toString(); return INTERESTING_FILE.test(url); } diff --git a/src/vs/editor/contrib/defineKeybinding/common/smartSnippetInserter.ts b/src/vs/editor/contrib/defineKeybinding/common/smartSnippetInserter.ts new file mode 100644 index 00000000000..1716546acdb --- /dev/null +++ b/src/vs/editor/contrib/defineKeybinding/common/smartSnippetInserter.ts @@ -0,0 +1,159 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import {JSONScanner, createScanner as createJSONScanner, SyntaxKind as JSONSyntaxKind} from 'vs/base/common/json'; +import * as editorCommon from 'vs/editor/common/editorCommon'; +import {Position} from 'vs/editor/common/core/position'; +import {Range} from 'vs/editor/common/core/range'; + +export interface InsertSnippetResult { + position: Position; + prepend: string; + append: string; +} + +export class SmartSnippetInserter { + + private static hasOpenBrace(scanner:JSONScanner): boolean { + + while (scanner.scan() !== JSONSyntaxKind.EOF) { + let kind = scanner.getToken(); + + if (kind === JSONSyntaxKind.OpenBraceToken) { + return true; + } + } + + return false; + } + + private static offsetToPosition(model:editorCommon.ITextModel, offset:number): Position { + let offsetBeforeLine = 0; + let eolLength = model.getEOL().length; + let lineCount = model.getLineCount(); + for (let lineNumber = 1; lineNumber <= lineCount; lineNumber++) { + let lineTotalLength = model.getLineContent(lineNumber).length + eolLength; + let offsetAfterLine = offsetBeforeLine + lineTotalLength; + + if (offsetAfterLine > offset) { + return new Position( + lineNumber, + offset - offsetBeforeLine + 1 + ); + } + offsetBeforeLine = offsetAfterLine; + } + return new Position( + lineCount, + model.getLineMaxColumn(lineCount) + ); + } + + public static insertSnippet(model:editorCommon.ITextModel, _position:Position): InsertSnippetResult { + + let desiredPosition = model.getValueLengthInRange(new Range(1, 1, _position.lineNumber, _position.column)); + + // [ { } , { } ] + enum State { + INVALID = 0, + AFTER_OBJECT = 1, + BEFORE_OBJECT = 2, + } + let currentState = State.INVALID; + let lastValidPos = -1; + let lastValidState = State.INVALID; + + let scanner = createJSONScanner(model.getValue()); + let arrayLevel = 0; + let objLevel = 0; + + let checkRangeStatus = (pos:number, state:State) => { + if (state !== State.INVALID && arrayLevel === 1 && objLevel === 0) { + currentState = state; + lastValidPos = pos; + lastValidState = state; + } else { + if (currentState !== State.INVALID) { + currentState = State.INVALID; + lastValidPos = scanner.getTokenOffset(); + } + } + }; + + while (scanner.scan() !== JSONSyntaxKind.EOF) { + let currentPos = scanner.getPosition(); + let kind = scanner.getToken(); + + let goodKind = false; + switch (kind) { + case JSONSyntaxKind.OpenBracketToken: + goodKind = true; + arrayLevel++; + checkRangeStatus(currentPos, State.BEFORE_OBJECT); + break; + case JSONSyntaxKind.CloseBracketToken: + goodKind = true; + arrayLevel--; + checkRangeStatus(currentPos, State.INVALID); + break; + case JSONSyntaxKind.CommaToken: + goodKind = true; + checkRangeStatus(currentPos, State.BEFORE_OBJECT); + break; + case JSONSyntaxKind.OpenBraceToken: + goodKind = true; + objLevel++; + checkRangeStatus(currentPos, State.INVALID); + break; + case JSONSyntaxKind.CloseBraceToken: + goodKind = true; + objLevel--; + checkRangeStatus(currentPos, State.AFTER_OBJECT); + break; + case JSONSyntaxKind.Trivia: + case JSONSyntaxKind.LineBreakTrivia: + goodKind = true; + } + + if (currentPos >= desiredPosition && (currentState !== State.INVALID || lastValidPos !== -1)) { + let acceptPosition: number; + let acceptState: State; + + if (currentState !== State.INVALID) { + acceptPosition = (goodKind ? currentPos : scanner.getTokenOffset()); + acceptState = currentState; + } else { + acceptPosition = lastValidPos; + acceptState = lastValidState; + } + + if (acceptState === State.AFTER_OBJECT) { + return { + position: this.offsetToPosition(model, acceptPosition), + prepend: ',', + append: '' + }; + } else { + scanner.setPosition(acceptPosition); + return { + position: this.offsetToPosition(model, acceptPosition), + prepend: '', + append: this.hasOpenBrace(scanner) ? ',' : '' + }; + } + } + } + + // no valid position found! + let modelLineCount = model.getLineCount(); + return { + position: new Position(modelLineCount, model.getLineMaxColumn(modelLineCount)), + prepend: '\n[', + append: ']' + }; + } +} diff --git a/src/vs/editor/contrib/defineKeybinding/test/common/smartSnippetInserter.test.ts b/src/vs/editor/contrib/defineKeybinding/test/common/smartSnippetInserter.test.ts new file mode 100644 index 00000000000..e548bdd89f2 --- /dev/null +++ b/src/vs/editor/contrib/defineKeybinding/test/common/smartSnippetInserter.test.ts @@ -0,0 +1,164 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as assert from 'assert'; +import {SmartSnippetInserter} from 'vs/editor/contrib/defineKeybinding/common/smartSnippetInserter'; +import {TextModel} from 'vs/editor/common/model/textModel'; +import {Position} from 'vs/editor/common/core/position'; + +suite('SmartSnippetInserter', () => { + + function testSmartSnippetInserter(text:string[], runner:(assert:(desiredPos:Position, pos:Position, prepend:string, append:string)=>void)=>void): void { + let model = new TextModel([], TextModel.toRawText(text.join('\n'), TextModel.DEFAULT_CREATION_OPTIONS)); + runner((desiredPos, pos, prepend, append) => { + let actual = SmartSnippetInserter.insertSnippet(model, desiredPos); + let expected = { + position: pos, + prepend, + append + }; + assert.deepEqual(actual, expected); + }); + model.dispose(); + } + + test('empty text', () => { + testSmartSnippetInserter([ + ], (assert) => { + assert(new Position(1,1), new Position(1,1), '\n[', ']'); + }); + + testSmartSnippetInserter([ + ' ' + ], (assert) => { + assert(new Position(1,1), new Position(1,2), '\n[', ']'); + assert(new Position(1,2), new Position(1,2), '\n[', ']'); + }); + + testSmartSnippetInserter([ + '// just some text' + ], (assert) => { + assert(new Position(1,1), new Position(1,18), '\n[', ']'); + assert(new Position(1,18), new Position(1,18), '\n[', ']'); + }); + + testSmartSnippetInserter([ + '// just some text', + '' + ], (assert) => { + assert(new Position(1,1), new Position(2,1), '\n[', ']'); + assert(new Position(1,18), new Position(2,1), '\n[', ']'); + assert(new Position(2,1), new Position(2,1), '\n[', ']'); + }); + }); + + test('empty array 1', () => { + testSmartSnippetInserter([ + '// just some text', + '[]' + ], (assert) => { + assert(new Position(1,1), new Position(2,2), '', ''); + assert(new Position(2,1), new Position(2,2), '', ''); + assert(new Position(2,2), new Position(2,2), '', ''); + assert(new Position(2,3), new Position(2,2), '', ''); + }); + }); + + test('empty array 2', () => { + testSmartSnippetInserter([ + '// just some text', + '[', + ']' + ], (assert) => { + assert(new Position(1,1), new Position(2,2), '', ''); + assert(new Position(2,1), new Position(2,2), '', ''); + assert(new Position(2,2), new Position(2,2), '', ''); + assert(new Position(3,1), new Position(3,1), '', ''); + assert(new Position(3,2), new Position(3,1), '', ''); + }); + }); + + test('empty array 3', () => { + testSmartSnippetInserter([ + '// just some text', + '[', + '// just some text', + ']' + ], (assert) => { + assert(new Position(1,1), new Position(2,2), '', ''); + assert(new Position(2,1), new Position(2,2), '', ''); + assert(new Position(2,2), new Position(2,2), '', ''); + assert(new Position(3,1), new Position(3,1), '', ''); + assert(new Position(3,2), new Position(3,1), '', ''); + assert(new Position(4,1), new Position(4,1), '', ''); + assert(new Position(4,2), new Position(4,1), '', ''); + }); + }); + + test('one element array 1', () => { + testSmartSnippetInserter([ + '// just some text', + '[', + '{}', + ']' + ], (assert) => { + assert(new Position(1,1), new Position(2,2), '', ','); + assert(new Position(2,1), new Position(2,2), '', ','); + assert(new Position(2,2), new Position(2,2), '', ','); + assert(new Position(3,1), new Position(3,1), '', ','); + assert(new Position(3,2), new Position(3,1), '', ','); + assert(new Position(3,3), new Position(3,3), ',', ''); + assert(new Position(4,1), new Position(4,1), ',', ''); + assert(new Position(4,2), new Position(4,1), ',', ''); + }); + }); + + test('two elements array 1', () => { + testSmartSnippetInserter([ + '// just some text', + '[', + '{},', + '{}', + ']' + ], (assert) => { + assert(new Position(1,1), new Position(2,2), '', ','); + assert(new Position(2,1), new Position(2,2), '', ','); + assert(new Position(2,2), new Position(2,2), '', ','); + assert(new Position(3,1), new Position(3,1), '', ','); + assert(new Position(3,2), new Position(3,1), '', ','); + assert(new Position(3,3), new Position(3,3), ',', ''); + assert(new Position(3,4), new Position(3,4), '', ','); + assert(new Position(4,1), new Position(4,1), '', ','); + assert(new Position(4,2), new Position(4,1), '', ','); + assert(new Position(4,3), new Position(4,3), ',', ''); + assert(new Position(5,1), new Position(5,1), ',', ''); + assert(new Position(5,2), new Position(5,1), ',', ''); + }); + }); + + test('two elements array 2', () => { + testSmartSnippetInserter([ + '// just some text', + '[', + '{},{}', + ']' + ], (assert) => { + assert(new Position(1,1), new Position(2,2), '', ','); + assert(new Position(2,1), new Position(2,2), '', ','); + assert(new Position(2,2), new Position(2,2), '', ','); + assert(new Position(3,1), new Position(3,1), '', ','); + assert(new Position(3,2), new Position(3,1), '', ','); + assert(new Position(3,3), new Position(3,3), ',', ''); + assert(new Position(3,4), new Position(3,4), '', ','); + assert(new Position(3,5), new Position(3,4), '', ','); + assert(new Position(3,6), new Position(3,6), ',', ''); + assert(new Position(4,1), new Position(4,1), ',', ''); + assert(new Position(4,2), new Position(4,1), ',', ''); + }); + }); + +}); diff --git a/src/vs/editor/contrib/diffNavigator/common/diffNavigator.ts b/src/vs/editor/contrib/diffNavigator/common/diffNavigator.ts index 6c8731de2a7..7cd9697cc4e 100644 --- a/src/vs/editor/contrib/diffNavigator/common/diffNavigator.ts +++ b/src/vs/editor/contrib/diffNavigator/common/diffNavigator.ts @@ -5,14 +5,15 @@ 'use strict'; import * as assert from 'vs/base/common/assert'; -import {EventEmitter, ListenerUnbind} from 'vs/base/common/eventEmitter'; +import {EventEmitter} from 'vs/base/common/eventEmitter'; import * as objects from 'vs/base/common/objects'; import {Range} from 'vs/editor/common/core/range'; -import {EventType, ICommonDiffEditor, ICursorPositionChangedEvent, IEditorRange, ILineChange} from 'vs/editor/common/editorCommon'; +import {ICommonDiffEditor, ICursorPositionChangedEvent, ILineChange} from 'vs/editor/common/editorCommon'; +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; interface IDiffRange { rhs:boolean; - range:IEditorRange; + range:Range; } export interface Options { @@ -39,7 +40,7 @@ export class DiffNavigator extends EventEmitter { private editor:ICommonDiffEditor; private options:Options; private disposed:boolean; - private toUnbind:ListenerUnbind[]; + private toUnbind:IDisposable[]; private nextIdx:number; private ranges:IDiffRange[]; @@ -62,11 +63,11 @@ export class DiffNavigator extends EventEmitter { this.revealFirst = this.options.alwaysRevealFirst; // hook up to diff editor for diff, disposal, and caret move - this.toUnbind.push(this.editor.addListener(EventType.Disposed, () => this.dispose() )); - this.toUnbind.push(this.editor.addListener(EventType.DiffUpdated, () => this.onDiffUpdated() )); + this.toUnbind.push(this.editor.onDidDispose(() => this.dispose() )); + this.toUnbind.push(this.editor.onDidUpdateDiff(() => this.onDiffUpdated() )); if(this.options.followsCaret) { - this.toUnbind.push(this.editor.getModifiedEditor().addListener(EventType.CursorPositionChanged, (e:ICursorPositionChangedEvent) => { + this.toUnbind.push(this.editor.getModifiedEditor().onDidChangeCursorPosition((e:ICursorPositionChangedEvent) => { if(this.ignoreSelectionChange) { return; } @@ -74,7 +75,7 @@ export class DiffNavigator extends EventEmitter { })); } if(this.options.alwaysRevealFirst) { - this.toUnbind.push(this.editor.getModifiedEditor().addListener(EventType.ModelChanged, (e) => { + this.toUnbind.push(this.editor.getModifiedEditor().onDidChangeModel((e) => { this.revealFirst = true; })); } @@ -214,9 +215,7 @@ export class DiffNavigator extends EventEmitter { } public dispose():void { - while(this.toUnbind.length > 0) { - this.toUnbind.pop()(); - } + this.toUnbind = dispose(this.toUnbind); this.ranges = null; this.disposed = true; diff --git a/src/vs/editor/contrib/find/browser/findWidget.ts b/src/vs/editor/contrib/find/browser/findWidget.ts index fcad63a1314..0afda4ef78f 100644 --- a/src/vs/editor/contrib/find/browser/findWidget.ts +++ b/src/vs/editor/contrib/find/browser/findWidget.ts @@ -17,7 +17,7 @@ import {FindInput} from 'vs/base/browser/ui/findinput/findInput'; import {IMessage as InputBoxMessage, InputBox} from 'vs/base/browser/ui/inputbox/inputBox'; import {Widget} from 'vs/base/browser/ui/widget'; import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; -import {EventType, IConfigurationChangedEvent} from 'vs/editor/common/editorCommon'; +import {IConfigurationChangedEvent} from 'vs/editor/common/editorCommon'; import {ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, OverlayWidgetPositionPreference} from 'vs/editor/browser/editorBrowser'; import {FIND_IDS, MATCHES_LIMIT} from 'vs/editor/contrib/find/common/findModel'; import {FindReplaceState, FindReplaceStateChangedEvent} from 'vs/editor/contrib/find/common/findState'; @@ -98,7 +98,7 @@ export class FindWidget extends Widget implements IOverlayWidget { this.focusTracker = this._register(dom.trackFocus(this._findInput.inputBox.inputElement)); this.focusTracker.addFocusListener(() => this._reseedFindScope()); - this._register(this._codeEditor.addListener2(EventType.ConfigurationChanged, (e:IConfigurationChangedEvent) => { + this._register(this._codeEditor.onDidChangeConfiguration((e:IConfigurationChangedEvent) => { if (e.readOnly) { if (this._codeEditor.getConfiguration().readOnly) { // Hide replace part if editor becomes read only @@ -107,7 +107,7 @@ export class FindWidget extends Widget implements IOverlayWidget { this._updateButtons(); } })); - this._register(this._codeEditor.addListener2(EventType.CursorSelectionChanged, () => { + this._register(this._codeEditor.onDidChangeCursorSelection(() => { if (this._isVisible) { this._updateToggleSelectionFindButton(); } diff --git a/src/vs/editor/contrib/find/common/findController.ts b/src/vs/editor/contrib/find/common/findController.ts index d424ed30394..4807339c137 100644 --- a/src/vs/editor/contrib/find/common/findController.ts +++ b/src/vs/editor/contrib/find/common/findController.ts @@ -18,7 +18,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; import {FIND_IDS, FindModelBoundToEditorModel} from 'vs/editor/contrib/find/common/findModel'; import {FindReplaceState, FindReplaceStateChangedEvent, INewFindReplaceState} from 'vs/editor/contrib/find/common/findState'; -import {OccurrencesRegistry} from 'vs/editor/common/modes'; +import {DocumentHighlightProviderRegistry} from 'vs/editor/common/modes'; import {RunOnceScheduler} from 'vs/base/common/async'; export enum FindStartFocusAction { @@ -60,7 +60,7 @@ export class CommonFindController extends Disposable implements editorCommon.IEd this._model = null; - this._register(this._editor.addListener2(editorCommon.EventType.ModelChanged, () => { + this._register(this._editor.onDidChangeModel(() => { let shouldRestartFind = (this._editor.getModel() && this._state.isRevealed); this.disposeModel(); @@ -353,14 +353,14 @@ export interface IMultiCursorFindResult { matchCase:boolean; wholeWord:boolean; - nextMatch: editorCommon.IEditorSelection; + nextMatch: Selection; } function multiCursorFind(editor:editorCommon.ICommonCodeEditor, changeFindSearchString:boolean): IMultiCursorFindResult { let controller = CommonFindController.getFindController(editor); let state = controller.getState(); let searchText: string, - nextMatch: editorCommon.IEditorSelection; + nextMatch: Selection; // In any case, if the find widget was ever opened, the options are taken from it let wholeWord = state.wholeWord; @@ -411,7 +411,7 @@ export class SelectNextFindMatchAction extends EditorAction { super(descriptor, editor, Behaviour.WidgetFocus); } - protected _getNextMatch(): editorCommon.IEditorSelection { + protected _getNextMatch(): Selection { let r = multiCursorFind(this.editor, true); if (!r) { return null; @@ -514,7 +514,7 @@ export class SelectionHighlighter extends Disposable implements editorCommon.IEd private editor: editorCommon.ICommonCodeEditor; private decorations: string[]; private updateSoon: RunOnceScheduler; - private lastWordUnderCursor: editorCommon.IEditorRange; + private lastWordUnderCursor: Range; constructor(editor:editorCommon.ICommonCodeEditor) { super(); @@ -523,7 +523,7 @@ export class SelectionHighlighter extends Disposable implements editorCommon.IEd this.updateSoon = this._register(new RunOnceScheduler(() => this._update(), 300)); this.lastWordUnderCursor = null; - this._register(editor.addListener2(editorCommon.EventType.CursorSelectionChanged, (e: editorCommon.ICursorSelectionChangedEvent) => { + this._register(editor.onDidChangeCursorSelection((e: editorCommon.ICursorSelectionChangedEvent) => { if (e.selection.isEmpty()) { if (e.reason === editorCommon.CursorChangeReason.Explicit) { if (!this.lastWordUnderCursor || !this.lastWordUnderCursor.containsPosition(e.selection.getStartPosition())) { @@ -539,7 +539,7 @@ export class SelectionHighlighter extends Disposable implements editorCommon.IEd this._update(); } })); - this._register(editor.addListener2(editorCommon.EventType.ModelChanged, (e) => { + this._register(editor.onDidChangeModel((e) => { this.removeDecorations(); })); this._register(CommonFindController.getFindController(editor).getState().addChangeListener((e) => { @@ -575,7 +575,7 @@ export class SelectionHighlighter extends Disposable implements editorCommon.IEd return; } - let hasFindOccurences = OccurrencesRegistry.has(model); + let hasFindOccurences = DocumentHighlightProviderRegistry.has(model); if (r.nextMatch) { // This is an empty selection if (hasFindOccurences) { @@ -614,7 +614,7 @@ export class SelectionHighlighter extends Disposable implements editorCommon.IEd selections.sort(Range.compareRangesUsingStarts); // do not overlap with selection (issue #64 and #512) - let matches: editorCommon.IEditorRange[] = []; + let matches: Range[] = []; for (let i = 0, j = 0, len = allMatches.length, lenJ = selections.length; i < len; ) { let match = allMatches[i]; @@ -736,10 +736,10 @@ registerFindCommand(FIND_IDS.ToggleRegexCommand, x => x.toggleRegex(), { }); registerFindCommand(FIND_IDS.ReplaceOneAction, x => x.replace(), { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_1 -}); +}, CONTEXT_FIND_WIDGET_VISIBLE); registerFindCommand(FIND_IDS.ReplaceAllAction, x => x.replaceAll(), { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Enter -}); +}, CONTEXT_FIND_WIDGET_VISIBLE); registerFindCommand(FIND_IDS.SelectAllMatchesAction, x => x.selectAllMatches(), { primary: KeyMod.Alt | KeyCode.Enter -}); +}, CONTEXT_FIND_WIDGET_VISIBLE); diff --git a/src/vs/editor/contrib/find/common/findDecorations.ts b/src/vs/editor/contrib/find/common/findDecorations.ts index 9a238950833..1648cb53643 100644 --- a/src/vs/editor/contrib/find/common/findDecorations.ts +++ b/src/vs/editor/contrib/find/common/findDecorations.ts @@ -6,6 +6,8 @@ import {IDisposable} from 'vs/base/common/lifecycle'; import * as editorCommon from 'vs/editor/common/editorCommon'; +import {Position} from 'vs/editor/common/core/position'; +import {Range} from 'vs/editor/common/core/range'; export class FindDecorations implements IDisposable { @@ -13,7 +15,7 @@ export class FindDecorations implements IDisposable { private _decorations:string[]; private _findScopeDecorationId:string; private _highlightedDecorationId:string; - private _startPosition:editorCommon.IEditorPosition; + private _startPosition:Position; constructor(editor:editorCommon.ICommonCodeEditor) { this._editor = editor; @@ -43,23 +45,23 @@ export class FindDecorations implements IDisposable { return this._decorations.length; } - public getFindScope(): editorCommon.IEditorRange { + public getFindScope(): Range { if (this._findScopeDecorationId) { return this._editor.getModel().getDecorationRange(this._findScopeDecorationId); } return null; } - public getStartPosition(): editorCommon.IEditorPosition { + public getStartPosition(): Position { return this._startPosition; } - public setStartPosition(newStartPosition:editorCommon.IEditorPosition): void { + public setStartPosition(newStartPosition:Position): void { this._startPosition = newStartPosition; this.setCurrentFindMatch(null); } - public getCurrentMatchesPosition(desiredRange:editorCommon.IEditorRange): number { + public getCurrentMatchesPosition(desiredRange:Range): number { for (let i = 0, len = this._decorations.length; i < len; i++) { let range = this._editor.getModel().getDecorationRange(this._decorations[i]); if (desiredRange.equalsRange(range)) { @@ -69,7 +71,7 @@ export class FindDecorations implements IDisposable { return 1; } - public setCurrentFindMatch(nextMatch:editorCommon.IEditorRange): number { + public setCurrentFindMatch(nextMatch:Range): number { let newCurrentDecorationId: string = null; let matchPosition = 0; if (nextMatch) { @@ -99,7 +101,7 @@ export class FindDecorations implements IDisposable { return matchPosition; } - public set(matches:editorCommon.IEditorRange[], findScope:editorCommon.IEditorRange): void { + public set(matches:Range[], findScope:Range): void { let newDecorations: editorCommon.IModelDeltaDecoration[] = matches.map((match) => { return { range: match, diff --git a/src/vs/editor/contrib/find/common/findModel.ts b/src/vs/editor/contrib/find/common/findModel.ts index 520a4a2d6fa..be1f8e11b34 100644 --- a/src/vs/editor/contrib/find/common/findModel.ts +++ b/src/vs/editor/contrib/find/common/findModel.ts @@ -57,7 +57,7 @@ export class FindModelBoundToEditorModel { this._updateDecorationsScheduler = new RunOnceScheduler(() => this.research(false), 100); this._toDispose.push(this._updateDecorationsScheduler); - this._toDispose.push(this._editor.addListener2(editorCommon.EventType.CursorPositionChanged, (e:editorCommon.ICursorPositionChangedEvent) => { + this._toDispose.push(this._editor.onDidChangeCursorPosition((e:editorCommon.ICursorPositionChangedEvent) => { if ( e.reason === editorCommon.CursorChangeReason.Explicit || e.reason === editorCommon.CursorChangeReason.Undo @@ -68,11 +68,11 @@ export class FindModelBoundToEditorModel { })); this._ignoreModelContentChanged = false; - this._toDispose.push(this._editor.addListener2(editorCommon.EventType.ModelContentChanged, (e:editorCommon.IModelContentChangedEvent) => { + this._toDispose.push(this._editor.onDidChangeModelRawContent((e:editorCommon.IModelContentChangedEvent) => { if (this._ignoreModelContentChanged) { return; } - if (e.changeType === editorCommon.EventType.ModelContentChangedFlush) { + if (e.changeType === editorCommon.EventType.ModelRawContentChangedFlush) { // a model.setValue() was called this._decorations.reset(); } @@ -99,8 +99,8 @@ export class FindModelBoundToEditorModel { } } - private static _getSearchRange(model:editorCommon.IModel, searchOnlyEditableRange:boolean, findScope:editorCommon.IEditorRange): editorCommon.IEditorRange { - let searchRange:editorCommon.IEditorRange; + private static _getSearchRange(model:editorCommon.IModel, searchOnlyEditableRange:boolean, findScope:Range): Range { + let searchRange:Range; if (searchOnlyEditableRange) { searchRange = model.getEditableRange(); @@ -116,8 +116,8 @@ export class FindModelBoundToEditorModel { return searchRange; } - private research(moveCursor:boolean, newFindScope?:editorCommon.IEditorRange): void { - let findScope: editorCommon.IEditorRange = null; + private research(moveCursor:boolean, newFindScope?:Range): void { + let findScope: Range = null; if (typeof newFindScope !== 'undefined') { findScope = newFindScope; } else { @@ -153,7 +153,7 @@ export class FindModelBoundToEditorModel { return false; } - private _moveToPrevMatch(before:editorCommon.IEditorPosition, isRecursed:boolean = false): void { + private _moveToPrevMatch(before:Position, isRecursed:boolean = false): void { if (this._cannotFind()) { return; } @@ -220,7 +220,7 @@ export class FindModelBoundToEditorModel { this._moveToPrevMatch(this._editor.getSelection().getStartPosition()); } - public _moveToNextMatch(after:editorCommon.IEditorPosition, isRecursed:boolean = false): void { + public _moveToNextMatch(after:Position, isRecursed:boolean = false): void { if (this._cannotFind()) { return; } @@ -298,7 +298,7 @@ export class FindModelBoundToEditorModel { return matchedString.replace(regexp, parsedReplaceString); } - private _rangeIsMatch(range:editorCommon.IEditorRange): boolean { + private _rangeIsMatch(range:Range): boolean { let selection = this._editor.getSelection(); let selectionText = this._editor.getModel().getValueInRange(selection); let regexp = strings.createSafeRegExp(this._state.searchString, this._state.isRegex, this._state.matchCase, this._state.wholeWord); @@ -329,7 +329,7 @@ export class FindModelBoundToEditorModel { } } - private _findMatches(findScope: editorCommon.IEditorRange, limitResultCount:number): editorCommon.IEditorRange[] { + private _findMatches(findScope: Range, limitResultCount:number): Range[] { let searchRange = FindModelBoundToEditorModel._getSearchRange(this._editor.getModel(), this._state.isReplaceRevealed, findScope); return this._editor.getModel().findMatches(this._state.searchString, searchRange, this._state.isRegex, this._state.matchCase, this._state.wholeWord, limitResultCount); } @@ -350,7 +350,7 @@ export class FindModelBoundToEditorModel { replaceStrings.push(this.getReplaceString(model.getValueInRange(ranges[i]))); } - let command = new ReplaceAllCommand(ranges, replaceStrings); + let command = new ReplaceAllCommand(this._editor.getSelection(), ranges, replaceStrings); this._executeEditorCommand('replaceAll', command); this.research(false); diff --git a/src/vs/editor/contrib/find/common/findState.ts b/src/vs/editor/contrib/find/common/findState.ts index 58a851ce7c5..72a5ac4fc25 100644 --- a/src/vs/editor/contrib/find/common/findState.ts +++ b/src/vs/editor/contrib/find/common/findState.ts @@ -7,7 +7,6 @@ import {EventEmitter} from 'vs/base/common/eventEmitter'; import {IDisposable} from 'vs/base/common/lifecycle'; import {Range} from 'vs/editor/common/core/range'; -import {IEditorRange} from 'vs/editor/common/editorCommon'; export interface FindReplaceStateChangedEvent { moveCursor: boolean; @@ -32,7 +31,7 @@ export interface INewFindReplaceState { isRegex?: boolean; wholeWord?: boolean; matchCase?: boolean; - searchScope?: IEditorRange; + searchScope?: Range; // matchesPosition?: number; // matchesCount?: number; } @@ -48,7 +47,7 @@ export class FindReplaceState implements IDisposable { private _isRegex: boolean; private _wholeWord: boolean; private _matchCase: boolean; - private _searchScope: IEditorRange; + private _searchScope: Range; private _matchesPosition: number; private _matchesCount: number; private _eventEmitter: EventEmitter; @@ -60,7 +59,7 @@ export class FindReplaceState implements IDisposable { public get isRegex(): boolean { return this._isRegex; } public get wholeWord(): boolean { return this._wholeWord; } public get matchCase(): boolean { return this._matchCase; } - public get searchScope(): IEditorRange { return this._searchScope; } + public get searchScope(): Range { return this._searchScope; } public get matchesPosition(): number { return this._matchesPosition; } public get matchesCount(): number { return this._matchesCount; } diff --git a/src/vs/editor/contrib/find/common/replaceAllCommand.ts b/src/vs/editor/contrib/find/common/replaceAllCommand.ts index 873dd411e83..dce29f4074f 100644 --- a/src/vs/editor/contrib/find/common/replaceAllCommand.ts +++ b/src/vs/editor/contrib/find/common/replaceAllCommand.ts @@ -9,16 +9,19 @@ import {Selection} from 'vs/editor/common/core/selection'; import * as editorCommon from 'vs/editor/common/editorCommon'; interface IEditOperation { - range:editorCommon.IEditorRange; + range:Range; text:string; } export class ReplaceAllCommand implements editorCommon.ICommand { - private _ranges: editorCommon.IEditorRange[]; + private _editorSelection: Selection; + private _trackedEditorSelectionId: string; + private _ranges: Range[]; private _replaceStrings: string[]; - constructor(ranges: editorCommon.IEditorRange[], replaceStrings:string[]) { + constructor(editorSelection:Selection, ranges: Range[], replaceStrings:string[]) { + this._editorSelection = editorSelection; this._ranges = ranges; this._replaceStrings = replaceStrings; } @@ -58,16 +61,11 @@ export class ReplaceAllCommand implements editorCommon.ICommand { builder.addEditOperation(resultOps[i].range, resultOps[i].text); } } + + this._trackedEditorSelectionId = builder.trackSelection(this._editorSelection); } - public computeCursorState(model:editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): editorCommon.IEditorSelection { - var inverseEditOperations = helper.getInverseEditOperations(); - var srcRange = inverseEditOperations[inverseEditOperations.length - 1].range; - return Selection.createSelection( - srcRange.endLineNumber, - srcRange.endColumn, - srcRange.endLineNumber, - srcRange.endColumn - ); + public computeCursorState(model:editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): Selection { + return helper.getTrackedSelection(this._trackedEditorSelectionId); } } diff --git a/src/vs/editor/contrib/find/test/common/findModel.test.ts b/src/vs/editor/contrib/find/test/common/findModel.test.ts index 0411a09189e..0b27dc78933 100644 --- a/src/vs/editor/contrib/find/test/common/findModel.test.ts +++ b/src/vs/editor/contrib/find/test/common/findModel.test.ts @@ -1212,7 +1212,7 @@ suite('FindModel', () => { findModel.replaceAll(); assertFindState( editor, - [8, 16, 8, 16], + [6, 17, 6, 17], null, [ ] ); @@ -1248,7 +1248,7 @@ suite('FindModel', () => { findModel.replaceAll(); assertFindState( editor, - [9, 3, 9, 3], + [1, 1, 1, 1], null, [ [6, 1, 6, 3], @@ -1285,7 +1285,7 @@ suite('FindModel', () => { findModel.replaceAll(); assertFindState( editor, - [11, 16, 11, 16], + [1, 1, 1, 1], null, [] ); @@ -1314,7 +1314,7 @@ suite('FindModel', () => { findModel.replaceAll(); assertFindState( editor, - [14, 3, 14, 3], + [1, 1, 1, 1], null, [] ); @@ -1327,6 +1327,36 @@ suite('FindModel', () => { findState.dispose(); }); + findTest('issue #3516: "replace all" moves page/cursor/focus/scroll to the place of the last replacement', (editor, cursor) => { + let findState = new FindReplaceState(); + findState.change({ searchString: 'include', replaceString: 'bar' }, false); + let findModel = new FindModelBoundToEditorModel(editor, findState); + + assertFindState( + editor, + [1, 1, 1, 1], + null, + [ + [2, 2, 2, 9], + [3, 2, 3, 9] + ] + ); + + findModel.replaceAll(); + assertFindState( + editor, + [1, 1, 1, 1], + null, + [] + ); + + assert.equal(editor.getModel().getLineContent(2), '#bar "cool.h"'); + assert.equal(editor.getModel().getLineContent(3), '#bar '); + + findModel.dispose(); + findState.dispose(); + }); + findTest('finds only in editable range if replace is shown', (editor, cursor) => { editor.getModel().setEditableRange({ startLineNumber: 6, diff --git a/src/vs/editor/contrib/folding/browser/folding.ts b/src/vs/editor/contrib/folding/browser/folding.ts index 6e84142c162..8f2f19c2147 100644 --- a/src/vs/editor/contrib/folding/browser/folding.ts +++ b/src/vs/editor/contrib/folding/browser/folding.ts @@ -20,6 +20,7 @@ import {ICodeEditor, IEditorMouseEvent} from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {IFoldingRange} from 'vs/editor/contrib/folding/common/foldingRange'; import {computeRanges, limitByIndent} from 'vs/editor/contrib/folding/common/indentFoldStrategy'; +import {Selection} from 'vs/editor/common/core/selection'; class CollapsibleRegion { @@ -38,6 +39,10 @@ class CollapsibleRegion { return this._isCollapsed; } + public get isExpanded(): boolean { + return !this._isCollapsed; + } + public get indent(): number { return this._indent; } @@ -57,7 +62,7 @@ class CollapsibleRegion { } } - public getDecorationRange(model:editorCommon.IModel): editorCommon.IEditorRange { + public getDecorationRange(model:editorCommon.IModel): Range { if (this.decorationIds.length > 0) { return model.getDecorationRange(this.decorationIds[1]); } @@ -159,8 +164,8 @@ export class FoldingController implements editorCommon.IEditorContribution { this.decorations = []; this.computeToken = 0; - this.globalToDispose.push(this.editor.addListener2(editorCommon.EventType.ModelChanged, () => this.onModelChanged())); - this.globalToDispose.push(this.editor.addListener2(editorCommon.EventType.ConfigurationChanged, (e: editorCommon.IConfigurationChangedEvent) => { + this.globalToDispose.push(this.editor.onDidChangeModel(() => this.onModelChanged())); + this.globalToDispose.push(this.editor.onDidChangeConfiguration((e: editorCommon.IConfigurationChangedEvent) => { let oldIsEnabled = this._isEnabled; this._isEnabled = this.editor.getConfiguration().contribInfo.folding; if (oldIsEnabled !== this._isEnabled) { @@ -311,7 +316,7 @@ export class FoldingController implements editorCommon.IEditorContribution { this.localToDispose.push(this.contentChangedScheduler); this.localToDispose.push(this.cursorChangedScheduler); - this.localToDispose.push(this.editor.addListener2('change', () => { + this.localToDispose.push(this.editor.onDidChangeModelContent(() => { this.contentChangedScheduler.schedule(); })); this.localToDispose.push({ dispose: () => { @@ -323,9 +328,9 @@ export class FoldingController implements editorCommon.IEditorContribution { this.decorations = []; this.editor.setHiddenAreas([]); }}); - this.localToDispose.push(this.editor.addListener2(editorCommon.EventType.MouseDown, e => this.onEditorMouseDown(e))); - this.localToDispose.push(this.editor.addListener2(editorCommon.EventType.MouseUp, e => this.onEditorMouseUp(e))); - this.localToDispose.push(this.editor.addListener2(editorCommon.EventType.CursorPositionChanged, e => { + this.localToDispose.push(this.editor.onMouseDown(e => this.onEditorMouseDown(e))); + this.localToDispose.push(this.editor.onMouseUp(e => this.onEditorMouseUp(e))); + this.localToDispose.push(this.editor.onDidChangeCursorPosition(e => { this.cursorChangedScheduler.schedule(); })); @@ -444,7 +449,7 @@ export class FoldingController implements editorCommon.IEditorContribution { private updateHiddenAreas(focusLine: number): void { let model = this.editor.getModel(); - var selections : editorCommon.IEditorSelection[] = this.editor.getSelections(); + var selections : Selection[] = this.editor.getSelections(); var updateSelections = false; let hiddenAreas: editorCommon.IRange[] = []; this.decorations.filter(dec => dec.isCollapsed).forEach(dec => { @@ -486,7 +491,7 @@ export class FoldingController implements editorCommon.IEditorContribution { let selectionsHasChanged = false; selections.forEach((selection, index) => { let lineNumber = selection.startLineNumber; - let surroundingUnfolded: editorCommon.IEditorRange; + let surroundingUnfolded: Range; for (let i = 0, len = this.decorations.length; i < len; i++) { let dec = this.decorations[i]; let decRange = dec.getDecorationRange(model); @@ -564,6 +569,43 @@ export class FoldingController implements editorCommon.IEditorContribution { } } + public foldUnfoldRecursively(isFold: boolean): void { + let hasChanges = false; + let model = this.editor.getModel(); + let selections = this.editor.getSelections(); + selections.forEach(selection => { + let lineNumber = selection.startLineNumber; + let endLineNumber: number; + let decToFoldUnfold: CollapsibleRegion[] = []; + for (let i = 0, len = this.decorations.length; i < len; i++) { + let dec = this.decorations[i]; + let decRange = dec.getDecorationRange(model); + if (!decRange) { + continue; + } + if (decRange.startLineNumber >= lineNumber && (decRange.endLineNumber <= endLineNumber || typeof endLineNumber === 'undefined')) { + //Protect against cursor not being in decoration and lower decoration folding/unfolding + if (decRange.startLineNumber !== lineNumber && typeof endLineNumber === 'undefined') { + return; + } + endLineNumber = endLineNumber || decRange.endLineNumber; + decToFoldUnfold.push(dec); + } + }; + if (decToFoldUnfold.length > 0) { + decToFoldUnfold.forEach(dec => { + this.editor.changeDecorations(changeAccessor => { + dec.setCollapsed(isFold, changeAccessor); + hasChanges = true; + }); + }); + } + }); + if (hasChanges) { + this.updateHiddenAreas(selections[0].startLineNumber); + } + } + public changeAll(collapse: boolean): void { if (this.decorations.length > 0) { let hasChanges = true; @@ -583,7 +625,7 @@ export class FoldingController implements editorCommon.IEditorContribution { public foldLevel(foldLevel: number, selectedLineNumbers: number[]): void { let model = this.editor.getModel(); - let foldingRegionStack: editorCommon.IEditorRange[] = [ model.getFullModelRange() ]; // sentinel + let foldingRegionStack: Range[] = [ model.getFullModelRange() ]; // sentinel let hasChanges = false; this.editor.changeDecorations(changeAccessor => { @@ -630,6 +672,14 @@ class UnfoldAction extends FoldingAction { } } +class UnFoldRecursivelyAction extends FoldingAction { + public static ID = 'editor.unFoldRecursively'; + + invoke(foldingController: FoldingController): void { + foldingController.foldUnfoldRecursively(false); + } +} + class FoldAction extends FoldingAction { public static ID = 'editor.fold'; @@ -638,6 +688,14 @@ class FoldAction extends FoldingAction { } } +class FoldRecursivelyAction extends FoldingAction { + public static ID = 'editor.foldRecursively'; + + invoke(foldingController: FoldingController): void { + foldingController.foldUnfoldRecursively(true); + } +} + class FoldAllAction extends FoldingAction { public static ID = 'editor.foldAll'; @@ -678,18 +736,25 @@ CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(UnfoldActio context: ContextKey.EditorFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_CLOSE_SQUARE_BRACKET }, 'Unfold')); +CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(UnFoldRecursivelyAction, UnFoldRecursivelyAction.ID, nls.localize('unFoldRecursivelyAction.label', "Unfold Recursively"), { + context: ContextKey.EditorFocus, + primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.US_CLOSE_SQUARE_BRACKET) +}, 'Unfold Recursively')); CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(FoldAction, FoldAction.ID, nls.localize('foldAction.label', "Fold"), { context: ContextKey.EditorFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_OPEN_SQUARE_BRACKET }, 'Fold')); +CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(FoldRecursivelyAction, FoldRecursivelyAction.ID, nls.localize('foldRecursivelyAction.label', "Fold Recursively"), { + context: ContextKey.EditorFocus, + primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.US_OPEN_SQUARE_BRACKET) +}, 'Fold Recursively')); CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(FoldAllAction, FoldAllAction.ID, nls.localize('foldAllAction.label', "Fold All"), { context: ContextKey.EditorFocus, - primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.Shift | KeyCode.US_OPEN_SQUARE_BRACKET + primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_0) }, 'Fold All')); CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(UnfoldAllAction, UnfoldAllAction.ID, nls.localize('unfoldAllAction.label', "Unfold All"), { context: ContextKey.EditorFocus, - primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.Shift | KeyCode.US_CLOSE_SQUARE_BRACKET, - secondary: [ KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_J) ] + primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_J) }, 'Unfold All')); CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(FoldLevelAction, FoldLevelAction.ID(1), nls.localize('foldLevel1Action.label', "Fold Level 1"), { context: ContextKey.EditorFocus, diff --git a/src/vs/editor/contrib/format/common/format.ts b/src/vs/editor/contrib/format/common/format.ts index 25897c2c792..e200cc10800 100644 --- a/src/vs/editor/contrib/format/common/format.ts +++ b/src/vs/editor/contrib/format/common/format.ts @@ -9,46 +9,48 @@ import {illegalArgument} from 'vs/base/common/errors'; import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import {Range} from 'vs/editor/common/core/range'; -import {IModel, IPosition, IRange, ISingleEditOperation} from 'vs/editor/common/editorCommon'; +import {IReadOnlyModel, ISingleEditOperation} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; -import {FormatRegistry, FormatOnTypeRegistry, IFormattingOptions} from 'vs/editor/common/modes'; +import {DocumentFormattingEditProviderRegistry, DocumentRangeFormattingEditProviderRegistry, OnTypeFormattingEditProviderRegistry, IFormattingOptions} from 'vs/editor/common/modes'; import {IModelService} from 'vs/editor/common/services/modelService'; +import {asWinJsPromise} from 'vs/base/common/async'; +import {Position} from 'vs/editor/common/core/position'; -export function formatRange(model: IModel, range: IRange, options: IFormattingOptions): TPromise { - const [support] = FormatRegistry.ordered(model) - .filter(s => typeof s.formatRange === 'function'); +export function getDocumentRangeFormattingEdits(model: IReadOnlyModel, range: Range, options: IFormattingOptions): TPromise { + const [support] = DocumentRangeFormattingEditProviderRegistry.ordered(model); if (!support) { return TPromise.as(undefined); } - return support.formatRange(model.getAssociatedResource(), range, options); + + return asWinJsPromise((token) => { + return support.provideDocumentRangeFormattingEdits(model, range, options, token); + }); } -export function formatDocument(model: IModel, options: IFormattingOptions): TPromise { - const [support] = FormatRegistry.ordered(model); +export function getDocumentFormattingEdits(model: IReadOnlyModel, options: IFormattingOptions): TPromise { + const [support] = DocumentFormattingEditProviderRegistry.ordered(model); if (!support) { - return TPromise.as(undefined); - } - if (typeof support.formatDocument !== 'function') { - if (typeof support.formatRange === 'function') { - return formatRange(model, model.getFullModelRange(), options); - } else { - return TPromise.as(undefined); - } + return getDocumentRangeFormattingEdits(model, model.getFullModelRange(), options); } - return support.formatDocument(model.getAssociatedResource(), options); + return asWinJsPromise((token) => { + return support.provideDocumentFormattingEdits(model, options, token); + }); } -export function formatAfterKeystroke(model: IModel, position: IPosition, ch: string, options: IFormattingOptions): TPromise { - const [support] = FormatOnTypeRegistry.ordered(model); +export function getOnTypeFormattingEdits(model: IReadOnlyModel, position: Position, ch: string, options: IFormattingOptions): TPromise { + const [support] = OnTypeFormattingEditProviderRegistry.ordered(model); if (!support) { return TPromise.as(undefined); } if (support.autoFormatTriggerCharacters.indexOf(ch) < 0) { return TPromise.as(undefined); } - return support.formatAfterKeystroke(model.getAssociatedResource(), position, ch, options); + + return asWinJsPromise((token) => { + return support.provideOnTypeFormattingEdits(model, position, ch, options, token); + }); } CommonEditorRegistry.registerLanguageCommand('_executeFormatRangeProvider', function(accessor, args) { @@ -60,7 +62,7 @@ CommonEditorRegistry.registerLanguageCommand('_executeFormatRangeProvider', func if (!model) { throw illegalArgument('resource'); } - return formatRange(model, range, options); + return getDocumentRangeFormattingEdits(model, Range.lift(range), options); }); CommonEditorRegistry.registerLanguageCommand('_executeFormatDocumentProvider', function(accessor, args) { @@ -73,7 +75,7 @@ CommonEditorRegistry.registerLanguageCommand('_executeFormatDocumentProvider', f throw illegalArgument('resource'); } - return formatDocument(model, options); + return getDocumentFormattingEdits(model, options); }); CommonEditorRegistry.registerDefaultLanguageCommand('_executeFormatOnTypeProvider', function(model, position, args) { @@ -81,5 +83,5 @@ CommonEditorRegistry.registerDefaultLanguageCommand('_executeFormatOnTypeProvide if (typeof ch !== 'string') { throw illegalArgument('ch'); } - return formatAfterKeystroke(model, position, ch, options); + return getOnTypeFormattingEdits(model, position, ch, options); }); diff --git a/src/vs/editor/contrib/format/common/formatActions.ts b/src/vs/editor/contrib/format/common/formatActions.ts index 99b46169a76..0e1f41e84e7 100644 --- a/src/vs/editor/contrib/format/common/formatActions.ts +++ b/src/vs/editor/contrib/format/common/formatActions.ts @@ -7,21 +7,16 @@ import * as nls from 'vs/nls'; import * as arrays from 'vs/base/common/arrays'; import {KeyCode, KeyMod} from 'vs/base/common/keyCodes'; -import {IDisposable, cAll, dispose} from 'vs/base/common/lifecycle'; +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {TPromise} from 'vs/base/common/winjs.base'; import {EditorAction} from 'vs/editor/common/editorAction'; import {Behaviour} from 'vs/editor/common/editorActionEnablement'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; -import {FormatOnTypeRegistry, FormatRegistry} from 'vs/editor/common/modes'; -import {formatAfterKeystroke, formatDocument, formatRange} from '../common/format'; +import {DocumentFormattingEditProviderRegistry, DocumentRangeFormattingEditProviderRegistry, OnTypeFormattingEditProviderRegistry} from 'vs/editor/common/modes'; +import {getOnTypeFormattingEdits, getDocumentFormattingEdits, getDocumentRangeFormattingEdits} from '../common/format'; import {EditOperationsCommand} from './formatCommand'; - -interface IFormatOnTypeResult { - range: editorCommon.IEditorRange; - id: string; - lineText: string; -} +import {Selection} from 'vs/editor/common/core/selection'; class FormatOnType implements editorCommon.IEditorContribution { @@ -29,28 +24,23 @@ class FormatOnType implements editorCommon.IEditorContribution { private editor: editorCommon.ICommonCodeEditor; private callOnDispose: IDisposable[]; - private callOnModel: Function[]; + private callOnModel: IDisposable[]; constructor(editor: editorCommon.ICommonCodeEditor) { this.editor = editor; this.callOnDispose = []; this.callOnModel = []; - this.callOnDispose.push(editor.addListener2(editorCommon.EventType.ConfigurationChanged, () => this.update())); - this.callOnDispose.push(editor.addListener2(editorCommon.EventType.ModelChanged, () => this.update())); - this.callOnDispose.push(editor.addListener2(editorCommon.EventType.ModelModeChanged, () => this.update())); - this.callOnDispose.push(editor.addListener2(editorCommon.EventType.ModelModeSupportChanged,(e: editorCommon.IModeSupportChangedEvent) => { - if (e.formattingSupport) { - this.update(); - } - })); - this.callOnDispose.push(FormatOnTypeRegistry.onDidChange(this.update, this)); + this.callOnDispose.push(editor.onDidChangeConfiguration(() => this.update())); + this.callOnDispose.push(editor.onDidChangeModel(() => this.update())); + this.callOnDispose.push(editor.onDidChangeModelMode(() => this.update())); + this.callOnDispose.push(OnTypeFormattingEditProviderRegistry.onDidChange(this.update, this)); } private update(): void { // clean up - this.callOnModel = cAll(this.callOnModel); + this.callOnModel = dispose(this.callOnModel); // we are disabled if (!this.editor.getConfiguration().contribInfo.formatOnType) { @@ -65,7 +55,7 @@ class FormatOnType implements editorCommon.IEditorContribution { var model = this.editor.getModel(); // no support - var [support] = FormatOnTypeRegistry.ordered(model); + var [support] = OnTypeFormattingEditProviderRegistry.ordered(model); if (!support || !support.autoFormatTriggerCharacters) { return; } @@ -89,37 +79,37 @@ class FormatOnType implements editorCommon.IEditorContribution { // install a listener that checks if edits happens before the // position on which we format right now. Iff so, we won't // apply the format edits - var unbind = this.editor.addListener(editorCommon.EventType.ModelContentChanged,(e: editorCommon.IModelContentChangedEvent) => { - if (e.changeType === editorCommon.EventType.ModelContentChangedFlush) { + var unbind = this.editor.onDidChangeModelRawContent((e: editorCommon.IModelContentChangedEvent) => { + if (e.changeType === editorCommon.EventType.ModelRawContentChangedFlush) { // a model.setValue() was called canceled = true; - } else if (e.changeType === editorCommon.EventType.ModelContentChangedLineChanged) { + } else if (e.changeType === editorCommon.EventType.ModelRawContentChangedLineChanged) { var changedLine = (e).lineNumber; canceled = changedLine <= position.lineNumber; - } else if (e.changeType === editorCommon.EventType.ModelContentChangedLinesInserted) { + } else if (e.changeType === editorCommon.EventType.ModelRawContentChangedLinesInserted) { var insertLine = (e).fromLineNumber; canceled = insertLine <= position.lineNumber; - } else if (e.changeType === editorCommon.EventType.ModelContentChangedLinesDeleted) { + } else if (e.changeType === editorCommon.EventType.ModelRawContentChangedLinesDeleted) { var deleteLine2 = (e).toLineNumber; canceled = deleteLine2 <= position.lineNumber; } if (canceled) { // cancel only once - unbind(); + unbind.dispose(); } }); let modelOpts = model.getOptions(); - formatAfterKeystroke(model, position, ch, { + getOnTypeFormattingEdits(model, position, ch, { tabSize: modelOpts.tabSize, insertSpaces: modelOpts.insertSpaces }).then(edits => { - unbind(); + unbind.dispose(); if (canceled || arrays.isFalsyOrEmpty(edits)) { return; @@ -128,7 +118,7 @@ class FormatOnType implements editorCommon.IEditorContribution { this.editor.executeCommand(this.getId(), new EditOperationsCommand(edits, this.editor.getSelection())); },(err) => { - unbind(); + unbind.dispose(); throw err; }); } @@ -139,9 +129,7 @@ class FormatOnType implements editorCommon.IEditorContribution { public dispose(): void { this.callOnDispose = dispose(this.callOnDispose); - while (this.callOnModel.length > 0) { - this.callOnModel.pop()(); - } + this.callOnModel = dispose(this.callOnModel); } } @@ -149,16 +137,19 @@ export class FormatAction extends EditorAction { public static ID = 'editor.action.format'; - private _disposable: IDisposable; + private _disposables: IDisposable[]; constructor(descriptor:editorCommon.IEditorActionDescriptorData, editor:editorCommon.ICommonCodeEditor) { super(descriptor, editor, Behaviour.WidgetFocus | Behaviour.Writeable | Behaviour.UpdateOnModelChange | Behaviour.ShowInContextMenu); - this._disposable = FormatRegistry.onDidChange(() => this.resetEnablementState()); + this._disposables = [ + DocumentFormattingEditProviderRegistry.onDidChange(() => this.resetEnablementState()), + DocumentRangeFormattingEditProviderRegistry.onDidChange(() => this.resetEnablementState()) + ]; } public dispose() { super.dispose(); - this._disposable.dispose(); + this._disposables = dispose(this._disposables); } public getGroupId(): string { @@ -166,7 +157,13 @@ export class FormatAction extends EditorAction { } public isSupported(): boolean { - return FormatRegistry.has(this.editor.getModel()) && super.isSupported(); + return ( + ( + DocumentFormattingEditProviderRegistry.has(this.editor.getModel()) + || DocumentRangeFormattingEditProviderRegistry.has(this.editor.getModel()) + ) + && super.isSupported() + ); } public run(): TPromise { @@ -182,9 +179,9 @@ export class FormatAction extends EditorAction { let formattingPromise: TPromise; if (editorSelection.isEmpty()) { - formattingPromise = formatDocument(model, options); + formattingPromise = getDocumentFormattingEdits(model, options); } else { - formattingPromise = formatRange(model, editorSelection, options); + formattingPromise = getDocumentRangeFormattingEdits(model, editorSelection, options); } if (!formattingPromise) { @@ -211,7 +208,7 @@ export class FormatAction extends EditorAction { }); } - public apply(editor: editorCommon.ICommonCodeEditor, editorSelection: editorCommon.IEditorSelection, value: editorCommon.ISingleEditOperation[]): void { + public apply(editor: editorCommon.ICommonCodeEditor, editorSelection: Selection, value: editorCommon.ISingleEditOperation[]): void { var state: editorCommon.IEditorViewState = null; if (editorSelection.isEmpty()) { diff --git a/src/vs/editor/contrib/format/common/formatCommand.ts b/src/vs/editor/contrib/format/common/formatCommand.ts index 458916cdac5..e6c0545cede 100644 --- a/src/vs/editor/contrib/format/common/formatCommand.ts +++ b/src/vs/editor/contrib/format/common/formatCommand.ts @@ -7,14 +7,15 @@ import * as strings from 'vs/base/common/strings'; import {Range} from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; +import {Selection} from 'vs/editor/common/core/selection'; export class EditOperationsCommand implements editorCommon.ICommand { private _edits:editorCommon.ISingleEditOperation[]; - private _initialSelection: editorCommon.IEditorSelection; + private _initialSelection: Selection; private _selectionId: string; - constructor(edits:editorCommon.ISingleEditOperation[], initialSelection: editorCommon.IEditorSelection) { + constructor(edits:editorCommon.ISingleEditOperation[], initialSelection: Selection) { this._edits = edits; this._initialSelection = initialSelection; } @@ -44,7 +45,7 @@ export class EditOperationsCommand implements editorCommon.ICommand { } } - public computeCursorState(model: editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): editorCommon.IEditorSelection { + public computeCursorState(model: editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData): Selection { return helper.getTrackedSelection(this._selectionId); } diff --git a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts index 1b2094af88e..0d89d9dd284 100644 --- a/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/browser/goToDeclaration.ts @@ -9,7 +9,6 @@ import 'vs/css!./goToDeclaration'; import * as nls from 'vs/nls'; import {Throttler} from 'vs/base/common/async'; import {onUnexpectedError} from 'vs/base/common/errors'; -import {ListenerUnbind} from 'vs/base/common/eventEmitter'; import {IHTMLContentElement} from 'vs/base/common/htmlContent'; import {KeyCode, KeyMod} from 'vs/base/common/keyCodes'; import * as platform from 'vs/base/common/platform'; @@ -25,13 +24,17 @@ import {EditorAction} from 'vs/editor/common/editorAction'; import {Behaviour} from 'vs/editor/common/editorActionEnablement'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; -import {IReference, DeclarationRegistry} from 'vs/editor/common/modes'; +import {Location, DefinitionProviderRegistry} from 'vs/editor/common/modes'; import {tokenizeToHtmlContent} from 'vs/editor/common/modes/textToHtmlTokenizer'; import {ICodeEditor, IEditorMouseEvent, IMouseTarget} from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {getDeclarationsAtPosition} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; import {ReferencesController} from 'vs/editor/contrib/referenceSearch/browser/referencesController'; import {ReferencesModel} from 'vs/editor/contrib/referenceSearch/browser/referencesModel'; +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; +import {IPeekViewService} from 'vs/editor/contrib/zoneWidget/browser/peekViewWidget'; +import {optional} from 'vs/platform/instantiation/common/instantiation'; + export class DefinitionActionConfig { @@ -62,7 +65,7 @@ export class DefinitionAction extends EditorAction { } public isSupported(): boolean { - return DeclarationRegistry.has(this.editor.getModel()) && super.isSupported(); + return DefinitionProviderRegistry.has(this.editor.getModel()) && super.isSupported(); } public getEnablementState(): boolean { @@ -70,13 +73,7 @@ export class DefinitionAction extends EditorAction { return false; } - const model = this.editor.getModel(); - const position = this.editor.getSelection().getStartPosition(); - return DeclarationRegistry.all(model).some(provider => { - return provider.canFindDeclaration( - model.getLineContext(position.lineNumber), - position.column - 1); - }); + return DefinitionProviderRegistry.has(this.editor.getModel()); } public run(): TPromise { @@ -93,19 +90,19 @@ export class DefinitionAction extends EditorAction { // * remove falsy references // * remove reference at the current pos // * collapse ranges to start pos - let result: IReference[] = []; + let result: Location[] = []; for (let i = 0; i < references.length; i++) { let reference = references[i]; if (!reference) { continue; } - let {resource, range} = reference; + let {uri, range} = reference; if (!this._configuration.filterCurrent - || resource.toString() !== model.getAssociatedResource().toString() + || uri.toString() !== model.uri.toString() || !Range.containsPosition(range, pos)) { result.push({ - resource, + uri, range: Range.collapseToStart(range) }); } @@ -124,7 +121,7 @@ export class DefinitionAction extends EditorAction { }); } - private _onResult(references: IReference[]) { + private _onResult(references: Location[]) { if (this._configuration.openInPeek) { this._openInPeek(this.editor, references); } else { @@ -137,14 +134,14 @@ export class DefinitionAction extends EditorAction { } } - private _openReference(reference: IReference, sideBySide: boolean): TPromise{ - let {resource, range} = reference; - return this._editorService.openEditor({ resource, options: { selection: range } }, sideBySide).then(editor => { + private _openReference(reference: Location, sideBySide: boolean): TPromise{ + let {uri, range} = reference; + return this._editorService.openEditor({ resource:uri, options: { selection: range } }, sideBySide).then(editor => { return editor.getControl(); }); } - private _openInPeek(target: editorCommon.ICommonCodeEditor, references: IReference[]) { + private _openInPeek(target: editorCommon.ICommonCodeEditor, references: Location[]) { let controller = ReferencesController.getController(target); controller.toggleWidget(target.getSelection(), TPromise.as(new ReferencesModel(references)), { getMetaTitle: (model) => { @@ -195,10 +192,16 @@ export class PeekDefinitionAction extends DefinitionAction { descriptor: editorCommon.IEditorActionDescriptorData, editor: editorCommon.ICommonCodeEditor, @IMessageService messageService: IMessageService, - @IEditorService editorService: IEditorService + @IEditorService editorService: IEditorService, + @optional(IPeekViewService) private _peekViewService: IPeekViewService ) { super(descriptor, editor, messageService, editorService, new DefinitionActionConfig(void 0, void 0, true, false)); } + + getEnablementState(): boolean { + return (!this._peekViewService || !this._peekViewService.isActive) + && super.getEnablementState(); + } } // --- Editor Contribution to goto definition using the mouse and a modifier key @@ -212,7 +215,7 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC static MAX_SOURCE_PREVIEW_LINES = 7; private editor: ICodeEditor; - private toUnhook: ListenerUnbind[]; + private toUnhook: IDisposable[]; private decorations: string[]; private currentWordUnderMouse: editorCommon.IWordAtPosition; private throttler: Throttler; @@ -228,15 +231,19 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC this.editor = editor; this.throttler = new Throttler(); - this.toUnhook.push(this.editor.addListener(editorCommon.EventType.MouseDown, (e: IEditorMouseEvent) => this.onEditorMouseDown(e))); - this.toUnhook.push(this.editor.addListener(editorCommon.EventType.MouseUp, (e: IEditorMouseEvent) => this.onEditorMouseUp(e))); - this.toUnhook.push(this.editor.addListener(editorCommon.EventType.MouseMove, (e: IEditorMouseEvent) => this.onEditorMouseMove(e))); - this.toUnhook.push(this.editor.addListener(editorCommon.EventType.KeyDown, (e: IKeyboardEvent) => this.onEditorKeyDown(e))); - this.toUnhook.push(this.editor.addListener(editorCommon.EventType.KeyUp, (e: IKeyboardEvent) => this.onEditorKeyUp(e))); + this.toUnhook.push(this.editor.onMouseDown((e: IEditorMouseEvent) => this.onEditorMouseDown(e))); + this.toUnhook.push(this.editor.onMouseUp((e: IEditorMouseEvent) => this.onEditorMouseUp(e))); + this.toUnhook.push(this.editor.onMouseMove((e: IEditorMouseEvent) => this.onEditorMouseMove(e))); + this.toUnhook.push(this.editor.onKeyDown((e: IKeyboardEvent) => this.onEditorKeyDown(e))); + this.toUnhook.push(this.editor.onKeyUp((e: IKeyboardEvent) => this.onEditorKeyUp(e))); - this.toUnhook.push(this.editor.addListener(editorCommon.EventType.ModelChanged, (e: editorCommon.IModelContentChangedEvent) => this.resetHandler())); - this.toUnhook.push(this.editor.addListener('change', (e: editorCommon.IModelContentChangedEvent) => this.resetHandler())); - this.toUnhook.push(this.editor.addListener('scroll', () => this.resetHandler())); + this.toUnhook.push(this.editor.onDidChangeModel((e) => this.resetHandler())); + this.toUnhook.push(this.editor.onDidChangeModelContent(() => this.resetHandler())); + this.toUnhook.push(this.editor.onDidScrollChange((e) => { + if (e.scrollTopChanged || e.scrollLeftChanged) { + this.resetHandler(); + } + })); } private onEditorMouseMove(mouseEvent: IEditorMouseEvent, withKey?: IKeyboardEvent): void { @@ -294,7 +301,7 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC // Single result else { let result = results[0]; - this.editorService.resolveEditorModel({ resource: result.resource }).then(model => { + this.editorService.resolveEditorModel({ resource: result.uri }).then(model => { let source: string; if (model && model.textEditorModel) { @@ -435,10 +442,10 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC (browser.isIE11orEarlier || mouseEvent.event.detail <= 1) && // IE does not support event.detail properly mouseEvent.target.type === editorCommon.MouseTargetType.CONTENT_TEXT && (mouseEvent.event[GotoDefinitionWithMouseEditorContribution.TRIGGER_MODIFIER] || (withKey && withKey.keyCode === GotoDefinitionWithMouseEditorContribution.TRIGGER_KEY_VALUE)) && - DeclarationRegistry.has(this.editor.getModel()); + DefinitionProviderRegistry.has(this.editor.getModel()); } - private findDefinition(target: IMouseTarget): TPromise { + private findDefinition(target: IMouseTarget): TPromise { let model = this.editor.getModel(); if (!model) { return TPromise.as(null); @@ -463,9 +470,7 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC } public dispose(): void { - while (this.toUnhook.length > 0) { - this.toUnhook.pop()(); - } + this.toUnhook = dispose(this.toUnhook); } } diff --git a/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts index e6fa774c9e6..a4643576f5e 100644 --- a/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts @@ -7,19 +7,22 @@ import {onUnexpectedError} from 'vs/base/common/errors'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IModel, IPosition} from 'vs/editor/common/editorCommon'; +import {IReadOnlyModel} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; -import {DeclarationRegistry} from 'vs/editor/common/modes'; -import {IReference} from 'vs/editor/common/modes'; +import {DefinitionProviderRegistry} from 'vs/editor/common/modes'; +import {Location} from 'vs/editor/common/modes'; +import {asWinJsPromise} from 'vs/base/common/async'; +import {Position} from 'vs/editor/common/core/position'; -export function getDeclarationsAtPosition(model: IModel, position: IPosition): TPromise { +export function getDeclarationsAtPosition(model: IReadOnlyModel, position: Position): TPromise { - const resource = model.getAssociatedResource(); - const provider = DeclarationRegistry.ordered(model); + const provider = DefinitionProviderRegistry.ordered(model); // get results const promises = provider.map((provider, idx) => { - return provider.findDeclaration(resource, position).then(result => { + return asWinJsPromise((token) => { + return provider.provideDefinition(model, position, token); + }).then(result => { return result; }, err => { onUnexpectedError(err); @@ -27,7 +30,7 @@ export function getDeclarationsAtPosition(model: IModel, position: IPosition): T }); return TPromise.join(promises).then(allReferences => { - let result: IReference[] = []; + let result: Location[] = []; for (let references of allReferences) { if (Array.isArray(references)) { result.push(...references); diff --git a/src/vs/editor/contrib/gotoError/browser/gotoError.ts b/src/vs/editor/contrib/gotoError/browser/gotoError.ts index fc4dd5a2a4c..5241af30ebc 100644 --- a/src/vs/editor/contrib/gotoError/browser/gotoError.ts +++ b/src/vs/editor/contrib/gotoError/browser/gotoError.ts @@ -10,35 +10,33 @@ import * as nls from 'vs/nls'; import {onUnexpectedError} from 'vs/base/common/errors'; import {Emitter} from 'vs/base/common/event'; import {CommonKeybindings, KeyCode, KeyMod} from 'vs/base/common/keyCodes'; -import {IDisposable, cAll, dispose} from 'vs/base/common/lifecycle'; -import severity from 'vs/base/common/severity'; +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; +import Severity from 'vs/base/common/severity'; import * as strings from 'vs/base/common/strings'; import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import * as dom from 'vs/base/browser/dom'; import {renderHtml} from 'vs/base/browser/htmlContentRenderer'; -import {IEditorService} from 'vs/platform/editor/common/editor'; -import {IEventService} from 'vs/platform/event/common/event'; import {IKeybindingContextKey, IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; import {IMarker, IMarkerService} from 'vs/platform/markers/common/markers'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {Position} from 'vs/editor/common/core/position'; +import {Range} from 'vs/editor/common/core/range'; import {EditorAction} from 'vs/editor/common/editorAction'; import {Behaviour} from 'vs/editor/common/editorActionEnablement'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; -import {IQuickFix} from 'vs/editor/common/modes'; -import {bulkEdit} from 'vs/editor/common/services/bulkEdit'; import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {IOptions, ZoneWidget} from 'vs/editor/contrib/zoneWidget/browser/zoneWidget'; +import {getCodeActions} from 'vs/editor/contrib/quickFix/common/quickFix'; class MarkerModel { private _editor: ICodeEditor; private _markers: IMarker[]; private _nextIdx: number; - private _toUnbind: Function[]; + private _toUnbind: IDisposable[]; private _ignoreSelectionChange: boolean; private _onCurrentMarkerChanged: Emitter; private _onMarkerSetChanged: Emitter; @@ -54,8 +52,8 @@ class MarkerModel { this.setMarkers(markers); // listen on editor - this._toUnbind.push(this._editor.addListener(editorCommon.EventType.Disposed, () => this.dispose())); - this._toUnbind.push(this._editor.addListener(editorCommon.EventType.CursorPositionChanged, () => { + this._toUnbind.push(this._editor.onDidDispose(() => this.dispose())); + this._toUnbind.push(this._editor.onDidChangeCursorPosition(() => { if (!this._ignoreSelectionChange) { this._nextIdx = -1; } @@ -75,13 +73,7 @@ class MarkerModel { this._markers = markers || []; // sort markers - this._markers.sort((left, right) => { - if (left.startLineNumber === right.startLineNumber) { - return left.startColumn - right.startColumn; - } else { - return left.startLineNumber - right.startLineNumber; - } - }); + this._markers.sort((left, right) => Severity.compare(left.severity, right.severity) || Range.compareRangesUsingStarts(left, right)); this._nextIdx = -1; this._onMarkerSetChanged.fire(this); @@ -155,7 +147,7 @@ class MarkerModel { for (var i = 0; i < this._markers.length; i++) { var marker = this._markers[i]; if (marker.startLineNumber <= pos.lineNumber && marker.endLineNumber >= pos.lineNumber - && marker.startColumn <= pos.column && marker.endColumn >= pos.column) { + && marker.startColumn <= pos.column && marker.endColumn >= pos.column) { this._onCurrentMarkerChanged.fire(marker); return; } @@ -185,7 +177,7 @@ class MarkerModel { } public dispose(): void { - this._toUnbind = cAll(this._toUnbind); + this._toUnbind = dispose(this._toUnbind); } } @@ -197,8 +189,6 @@ var zoneOptions: IOptions = { class MarkerNavigationWidget extends ZoneWidget { - private _eventService: IEventService; - private _editorService: IEditorService; private _container: HTMLElement; private _element: HTMLElement; private _quickFixSection: HTMLElement; @@ -206,10 +196,8 @@ class MarkerNavigationWidget extends ZoneWidget { private _localCleanup: IDisposable[] = []; private _quickFixEntries: HTMLElement[]; - constructor(eventService:IEventService, editorService:IEditorService, editor: ICodeEditor, private _model: MarkerModel) { + constructor(editor: ICodeEditor, private _model: MarkerModel, private _keybindingService: IKeybindingService) { super(editor, zoneOptions); - this._eventService = eventService; - this._editorService = editorService; this.create(); this._wireModelAndView(); } @@ -231,7 +219,7 @@ class MarkerNavigationWidget extends ZoneWidget { this._container.appendChild(this._quickFixSection); this._callOnDispose.push(dom.addStandardDisposableListener(this._container, 'keydown', (e) => { - switch(e.asKeybinding()) { + switch (e.asKeybinding()) { case CommonKeybindings.LEFT_ARROW: this._goLeft(); e.preventDefault(); @@ -268,9 +256,7 @@ class MarkerNavigationWidget extends ZoneWidget { this._quickFixEntries[idx].focus(); } - public show(where:editorCommon.IRange, heightInLines:number):void; - public show(where:editorCommon.IPosition, heightInLines:number):void; - public show(where:any, heightInLines:number):void { + public show(where: editorCommon.IPosition, heightInLines: number): void { super.show(where, heightInLines); this._container.focus(); } @@ -287,11 +273,11 @@ class MarkerNavigationWidget extends ZoneWidget { // set color switch (marker.severity) { - case severity.Error: + case Severity.Error: this.options.frameColor = '#ff5a5a'; break; - case severity.Warning: - case severity.Info: + case Severity.Warning: + case Severity.Info: this.options.frameColor = '#5aac5a'; break; } @@ -306,76 +292,64 @@ class MarkerNavigationWidget extends ZoneWidget { dom.clearNode(this._element); this._element.appendChild(document.createTextNode(text)); this._element.appendChild(renderHtml(marker.message)); - - var mode = this.editor.getModel().getMode(); this._quickFixSection.style.display = 'none'; - if (mode.quickFixSupport) { - var promise = mode.quickFixSupport.getQuickFixes(this.editor.getModel().getAssociatedResource(), marker); - promise.then((result: IQuickFix[]) => { - dom.clearNode(this._quickFixSection); - if (result.length > 0) { + getCodeActions(this.editor.getModel(), Range.lift(marker)).then(result => { + dom.clearNode(this._quickFixSection); - this._localCleanup.push({ - dispose:() => { - this._quickFixEntries = []; + if (result.length > 0) { + + this._localCleanup.push({ + dispose: () => { + this._quickFixEntries = []; + } + }); + + let quickfixhead = document.createElement('span'); + quickfixhead.className = 'quickfixhead'; + quickfixhead.appendChild(document.createTextNode(result.length > 1 ? nls.localize('quickfix.multiple.label', 'Suggested fixes: ') : nls.localize('quickfix.single.label', 'Suggested fix: '))); + this._quickFixSection.appendChild(quickfixhead); + + this._quickFixEntries = []; + let quickfixcontainer = document.createElement('span'); + quickfixcontainer.className = 'quickfixcontainer'; + result.forEach((fix, idx, arr) => { + var container = quickfixcontainer; + if (idx > 0) { + let separator = document.createElement('span'); + separator.appendChild(document.createTextNode(', ')); + container.appendChild(separator); + } + + let entry = document.createElement('a'); + entry.tabIndex = 0; + entry.className = 'quickfixentry'; + entry.appendChild(document.createTextNode(fix.command.title)); + this._localCleanup.push(dom.addDisposableListener(entry, dom.EventType.CLICK, () => { + this._keybindingService.executeCommand(fix.command.id, ...fix.command.arguments); + return true; + })); + this._localCleanup.push(dom.addStandardDisposableListener(entry, 'keydown', (e) => { + switch (e.asKeybinding()) { + case CommonKeybindings.ENTER: + case CommonKeybindings.SPACE: + this._keybindingService.executeCommand(fix.command.id, ...fix.command.arguments); + e.preventDefault(); + e.stopPropagation(); } - }); + })); + container.appendChild(entry); - let quickfixhead = document.createElement('span'); - quickfixhead.className = 'quickfixhead'; - quickfixhead.appendChild(document.createTextNode(result.length > 1 ? nls.localize('quickfix.multiple.label', 'Suggested fixes: ') : nls.localize('quickfix.single.label', 'Suggested fix: '))); - this._quickFixSection.appendChild(quickfixhead); + this._quickFixEntries.push(entry); + }); + this._quickFixSection.appendChild(quickfixcontainer); - this._quickFixEntries = []; - let quickfixcontainer = document.createElement('span'); - quickfixcontainer.className = 'quickfixcontainer'; - result.forEach((fix, idx, arr) => { - var container = quickfixcontainer; - if (idx > 0) { - let separator = document.createElement('span'); - separator.appendChild(document.createTextNode(', ')); - container.appendChild(separator); - } + this._quickFixSection.style.display = ''; + this.show(new Position(marker.startLineNumber, marker.startColumn), 4); + } + }, onUnexpectedError); - let entry = document.createElement('a'); - entry.tabIndex = 0; - entry.className = 'quickfixentry'; - entry.appendChild(document.createTextNode(fix.command.title)); - this._localCleanup.push(dom.addDisposableListener(entry, dom.EventType.CLICK, () => { - mode.quickFixSupport.runQuickFixAction(this.editor.getModel().getAssociatedResource(), marker, fix).then(result => { - return bulkEdit(this._eventService, this._editorService, this.editor, result.edits); - }); - return true; - })); - this._localCleanup.push(dom.addStandardDisposableListener(entry, 'keydown', (e) => { - switch (e.asKeybinding()) { - case CommonKeybindings.ENTER: - case CommonKeybindings.SPACE: - mode.quickFixSupport.runQuickFixAction(this.editor.getModel().getAssociatedResource(), marker, fix).then(result => { - return bulkEdit(this._eventService, this._editorService, this.editor, result.edits); - }); - e.preventDefault(); - e.stopPropagation(); - } - })); - container.appendChild(entry); - - this._quickFixEntries.push(entry); - }); - this._quickFixSection.appendChild(quickfixcontainer); - - this._quickFixSection.style.display = ''; - this.show(new Position(marker.startLineNumber, marker.startColumn), 4); - } - },(error) => { - onUnexpectedError(error); - }); - } - - this._model.withoutWatchingEditorPosition(() => { - this.show(new Position(marker.startLineNumber, marker.startColumn), 3); - }); + this._model.withoutWatchingEditorPosition(() => this.show(new Position(marker.startLineNumber, marker.startColumn), 3)); } public dispose(): void { @@ -388,9 +362,9 @@ class MarkerNavigationAction extends EditorAction { private _isNext: boolean; - private telemetryService:ITelemetryService; + private telemetryService: ITelemetryService; - constructor(descriptor:editorCommon.IEditorActionDescriptorData, editor:editorCommon.ICommonCodeEditor, next: boolean, @ITelemetryService telemetryService: ITelemetryService) { + constructor(descriptor: editorCommon.IEditorActionDescriptorData, editor: editorCommon.ICommonCodeEditor, next: boolean, @ITelemetryService telemetryService: ITelemetryService) { super(descriptor, editor, Behaviour.WidgetFocus | Behaviour.Writeable | Behaviour.UpdateOnModelChange); this.telemetryService = telemetryService; this._isNext = next; @@ -415,27 +389,23 @@ class MarkerController implements editorCommon.IEditorContribution { static ID = 'editor.contrib.markerController'; - static getMarkerController(editor:editorCommon.ICommonCodeEditor): MarkerController { + static getMarkerController(editor: editorCommon.ICommonCodeEditor): MarkerController { return editor.getContribution(MarkerController.ID); } - private eventService:IEventService; - private editorService:IEditorService; - private markerService: IMarkerService; - private editor:ICodeEditor; + private _editor: ICodeEditor; private _model: MarkerModel; private _zone: MarkerNavigationWidget; private _callOnClose: IDisposable[] = []; private _markersNavigationVisible: IKeybindingContextKey; constructor( - editor: ICodeEditor, @IMarkerService markerService: IMarkerService, @IKeybindingService keybindingService: IKeybindingService, - @IEventService eventService: IEventService, @IEditorService editorService: IEditorService) { - this.markerService = markerService; - this.eventService = eventService; - this.editorService = editorService; - this.editor = editor; - this._markersNavigationVisible = keybindingService.createKey(CONTEXT_MARKERS_NAVIGATION_VISIBLE, false); + editor: ICodeEditor, + @IMarkerService private _markerService: IMarkerService, + @IKeybindingService private _keybindingService: IKeybindingService + ) { + this._editor = editor; + this._markersNavigationVisible = this._keybindingService.createKey(CONTEXT_MARKERS_NAVIGATION_VISIBLE, false); } public getId(): string { @@ -460,36 +430,37 @@ class MarkerController implements editorCommon.IEditorContribution { } var markers = this._getMarkers(); - this._model = new MarkerModel(this.editor, markers); - this._zone = new MarkerNavigationWidget(this.eventService, this.editorService, this.editor, this._model); + this._model = new MarkerModel(this._editor, markers); + this._zone = new MarkerNavigationWidget(this._editor, this._model, this._keybindingService); this._markersNavigationVisible.set(true); this._callOnClose.push(this._model); this._callOnClose.push(this._zone); - this._callOnClose.push(this.editor.addListener2(editorCommon.EventType.ModelChanged, () => { + this._callOnClose.push(this._editor.onDidChangeModel(() => { this._cleanUp(); })); this._model.onCurrentMarkerChanged(marker => !marker && this._cleanUp(), undefined, this._callOnClose); - this.markerService.onMarkerChanged(this._onMarkerChanged, this, this._callOnClose); - return this._model; } + this._markerService.onMarkerChanged(this._onMarkerChanged, this, this._callOnClose); + return this._model; + } public closeMarkersNavigation(): void { this._cleanUp(); - this.editor.focus(); + this._editor.focus(); } private _onMarkerChanged(changedResources: URI[]): void { - if(!changedResources.some(r => this.editor.getModel().getAssociatedResource().toString() === r.toString())) { + if (!changedResources.some(r => this._editor.getModel().uri.toString() === r.toString())) { return; } this._model.setMarkers(this._getMarkers()); } private _getMarkers(): IMarker[] { - var resource = this.editor.getModel().getAssociatedResource(), - markers = this.markerService.read({ resource: resource }); + var resource = this._editor.getModel().uri, + markers = this._markerService.read({ resource: resource }); return markers; } @@ -498,7 +469,7 @@ class MarkerController implements editorCommon.IEditorContribution { class NextMarkerAction extends MarkerNavigationAction { public static ID = 'editor.action.marker.next'; - constructor(descriptor:editorCommon.IEditorActionDescriptorData, editor:editorCommon.ICommonCodeEditor, @ITelemetryService telemetryService: ITelemetryService) { + constructor(descriptor: editorCommon.IEditorActionDescriptorData, editor: editorCommon.ICommonCodeEditor, @ITelemetryService telemetryService: ITelemetryService) { super(descriptor, editor, true, telemetryService); } } @@ -506,7 +477,7 @@ class NextMarkerAction extends MarkerNavigationAction { class PrevMarkerAction extends MarkerNavigationAction { public static ID = 'editor.action.marker.prev'; - constructor(descriptor:editorCommon.IEditorActionDescriptorData, editor:editorCommon.ICommonCodeEditor, @ITelemetryService telemetryService: ITelemetryService) { + constructor(descriptor: editorCommon.IEditorActionDescriptorData, editor: editorCommon.ICommonCodeEditor, @ITelemetryService telemetryService: ITelemetryService) { super(descriptor, editor, false, telemetryService); } } diff --git a/src/vs/editor/contrib/hover/browser/hover.ts b/src/vs/editor/contrib/hover/browser/hover.ts index bb55f292fab..e1f4231f749 100644 --- a/src/vs/editor/contrib/hover/browser/hover.ts +++ b/src/vs/editor/contrib/hover/browser/hover.ts @@ -7,7 +7,6 @@ import 'vs/css!./hover'; import * as nls from 'vs/nls'; -import {ListenerUnbind} from 'vs/base/common/eventEmitter'; import {KeyCode, KeyMod} from 'vs/base/common/keyCodes'; import * as platform from 'vs/base/common/platform'; import {TPromise} from 'vs/base/common/winjs.base'; @@ -23,13 +22,14 @@ import {ICodeEditor, IEditorMouseEvent} from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {ModesContentHoverWidget} from './modesContentHover'; import {ModesGlyphHoverWidget} from './modesGlyphHover'; +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; class ModesHoverController implements editorCommon.IEditorContribution { static ID = 'editor.contrib.hover'; private _editor: ICodeEditor; - private _toUnhook:ListenerUnbind[]; + private _toUnhook:IDisposable[]; private _contentWidget: ModesContentHoverWidget; private _glyphWidget: ModesGlyphHoverWidget; @@ -46,13 +46,17 @@ class ModesHoverController implements editorCommon.IEditorContribution { this._toUnhook = []; if (editor.getConfiguration().contribInfo.hover) { - this._toUnhook.push(this._editor.addListener(editorCommon.EventType.MouseDown, (e: IEditorMouseEvent) => this._onEditorMouseDown(e))); - this._toUnhook.push(this._editor.addListener(editorCommon.EventType.MouseMove, (e: IEditorMouseEvent) => this._onEditorMouseMove(e))); - this._toUnhook.push(this._editor.addListener(editorCommon.EventType.MouseLeave, (e: IEditorMouseEvent) => this._hideWidgets())); - this._toUnhook.push(this._editor.addListener(editorCommon.EventType.KeyDown, (e:IKeyboardEvent) => this._onKeyDown(e))); - this._toUnhook.push(this._editor.addListener(editorCommon.EventType.ModelChanged, () => this._hideWidgets())); - this._toUnhook.push(this._editor.addListener(editorCommon.EventType.ModelDecorationsChanged, () => this._onModelDecorationsChanged())); - this._toUnhook.push(this._editor.addListener('scroll', () => this._hideWidgets())); + this._toUnhook.push(this._editor.onMouseDown((e: IEditorMouseEvent) => this._onEditorMouseDown(e))); + this._toUnhook.push(this._editor.onMouseMove((e: IEditorMouseEvent) => this._onEditorMouseMove(e))); + this._toUnhook.push(this._editor.onMouseLeave((e: IEditorMouseEvent) => this._hideWidgets())); + this._toUnhook.push(this._editor.onKeyDown((e:IKeyboardEvent) => this._onKeyDown(e))); + this._toUnhook.push(this._editor.onDidChangeModel(() => this._hideWidgets())); + this._toUnhook.push(this._editor.onDidChangeModelDecorations(() => this._onModelDecorationsChanged())); + this._toUnhook.push(this._editor.onDidScrollChange((e) => { + if (e.scrollTopChanged || e.scrollLeftChanged) { + this._hideWidgets(); + } + })); this._contentWidget = new ModesContentHoverWidget(editor, openerService); this._glyphWidget = new ModesGlyphHoverWidget(editor); @@ -118,7 +122,7 @@ class ModesHoverController implements editorCommon.IEditorContribution { this._contentWidget.hide(); } - public showContentHover(range: editorCommon.IEditorRange, focus: boolean): void { + public showContentHover(range: Range, focus: boolean): void { this._contentWidget.startShowingAt(range, focus); } @@ -127,9 +131,7 @@ class ModesHoverController implements editorCommon.IEditorContribution { } public dispose(): void { - while(this._toUnhook.length > 0) { - this._toUnhook.pop()(); - } + this._toUnhook = dispose(this._toUnhook); if (this._glyphWidget) { this._glyphWidget.dispose(); this._glyphWidget = null; diff --git a/src/vs/editor/contrib/hover/browser/hoverOperation.ts b/src/vs/editor/contrib/hover/browser/hoverOperation.ts index 7e8051647f9..47455bae5ae 100644 --- a/src/vs/editor/contrib/hover/browser/hoverOperation.ts +++ b/src/vs/editor/contrib/hover/browser/hoverOperation.ts @@ -56,7 +56,7 @@ export class HoverOperation { private _firstWaitScheduler: RunOnceScheduler; private _secondWaitScheduler: RunOnceScheduler; private _loadingMessageScheduler: RunOnceScheduler; - private _asyncComputationPromise:TPromise; + private _asyncComputationPromise: TPromise; private _asyncComputationPromiseDone:boolean; private _completeCallback:(r:Result)=>void; @@ -96,12 +96,10 @@ export class HoverOperation { if (this._computer.computeAsync) { this._asyncComputationPromiseDone = false; - this._asyncComputationPromise = this._computer.computeAsync(); - - this._asyncComputationPromise.then((asyncResult: Result) => { + this._asyncComputationPromise = this._computer.computeAsync().then((asyncResult: Result) => { this._asyncComputationPromiseDone = true; this._withAsyncResult(asyncResult); - }).done(null, () => this._onError); + }, () => this._onError); } else { this._asyncComputationPromiseDone = true; } @@ -175,11 +173,13 @@ export class HoverOperation { this._secondWaitScheduler.cancel(); if (this._asyncComputationPromise) { this._asyncComputationPromise.cancel(); + this._asyncComputationPromise = null; } } if (this._state === ComputeHoverOperationState.WAITING_FOR_ASYNC_COMPUTATION) { if (this._asyncComputationPromise) { this._asyncComputationPromise.cancel(); + this._asyncComputationPromise = null; } } this._state = ComputeHoverOperationState.IDLE; diff --git a/src/vs/editor/contrib/hover/browser/hoverWidgets.ts b/src/vs/editor/contrib/hover/browser/hoverWidgets.ts index c225b831314..579a41d4290 100644 --- a/src/vs/editor/contrib/hover/browser/hoverWidgets.ts +++ b/src/vs/editor/contrib/hover/browser/hoverWidgets.ts @@ -8,7 +8,7 @@ import {CommonKeybindings} from 'vs/base/common/keyCodes'; import {IKeyboardEvent} from 'vs/base/browser/keyboardEvent'; import {StyleMutator} from 'vs/base/browser/styleMutator'; import {Position} from 'vs/editor/common/core/position'; -import {IEditorPosition, IPosition, EventType, IConfigurationChangedEvent} from 'vs/editor/common/editorCommon'; +import {IPosition, IConfigurationChangedEvent} from 'vs/editor/common/editorCommon'; import * as editorBrowser from 'vs/editor/browser/editorBrowser'; import {Widget} from 'vs/base/browser/ui/widget'; @@ -19,7 +19,7 @@ export class ContentHoverWidget extends Widget implements editorBrowser.IContent protected _isVisible: boolean; private _containerDomNode: HTMLElement; protected _domNode: HTMLElement; - protected _showAtPosition: IEditorPosition; + protected _showAtPosition: Position; private _stoleFocus: boolean; // Editor.IContentWidget.allowEditorOverflow @@ -45,7 +45,7 @@ export class ContentHoverWidget extends Widget implements editorBrowser.IContent }); this._editor.applyFontInfo(this._domNode); - this._register(this._editor.addListener2(EventType.ConfigurationChanged, (e:IConfigurationChangedEvent) => { + this._register(this._editor.onDidChangeConfiguration((e:IConfigurationChangedEvent) => { if (e.fontInfo) { this._editor.applyFontInfo(this._domNode); } @@ -144,7 +144,7 @@ export class GlyphHoverWidget extends Widget implements editorBrowser.IOverlayWi this._showAtLineNumber = -1; this._editor.applyFontInfo(this._domNode); - this._register(this._editor.addListener2(EventType.ConfigurationChanged, (e:IConfigurationChangedEvent) => { + this._register(this._editor.onDidChangeConfiguration((e:IConfigurationChangedEvent) => { if (e.fontInfo) { this._editor.applyFontInfo(this._domNode); } diff --git a/src/vs/editor/contrib/hover/browser/modesContentHover.ts b/src/vs/editor/contrib/hover/browser/modesContentHover.ts index 9203fc05854..baff31c615d 100644 --- a/src/vs/editor/contrib/hover/browser/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/browser/modesContentHover.ts @@ -11,26 +11,27 @@ import {TPromise} from 'vs/base/common/winjs.base'; import {renderHtml} from 'vs/base/browser/htmlContentRenderer'; import {IOpenerService, NullOpenerService} from 'vs/platform/opener/common/opener'; import {Range} from 'vs/editor/common/core/range'; -import {IEditorRange, IRange} from 'vs/editor/common/editorCommon'; -import {ExtraInfoRegistry, IComputeExtraInfoResult, IMode} from 'vs/editor/common/modes'; +import {Position} from 'vs/editor/common/core/position'; +import {IRange} from 'vs/editor/common/editorCommon'; +import {HoverProviderRegistry, Hover, IMode} from 'vs/editor/common/modes'; import {tokenizeToString} from 'vs/editor/common/modes/textToHtmlTokenizer'; import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; -import {getExtraInfoAtPosition} from '../common/hover'; +import {getHover} from '../common/hover'; import {HoverOperation, IHoverComputer} from './hoverOperation'; import {ContentHoverWidget} from './hoverWidgets'; -class ModesContentComputer implements IHoverComputer { +class ModesContentComputer implements IHoverComputer { private _editor: ICodeEditor; - private _result: IComputeExtraInfoResult[]; - private _range: IEditorRange; + private _result: Hover[]; + private _range: Range; constructor(editor: ICodeEditor) { this._editor = editor; this._range = null; } - public setRange(range: IEditorRange): void { + public setRange(range: Range): void { this._range = range; this._result = []; } @@ -39,21 +40,21 @@ class ModesContentComputer implements IHoverComputer this._result = []; } - public computeAsync(): TPromise { + public computeAsync(): TPromise { let model = this._editor.getModel(); - if (!ExtraInfoRegistry.has(model)) { + if (!HoverProviderRegistry.has(model)) { return TPromise.as(null); } - return getExtraInfoAtPosition(model, { - lineNumber: this._range.startLineNumber, - column: this._range.startColumn - }); + return getHover(model, new Position( + this._range.startLineNumber, + this._range.startColumn + )); } - public computeSync(): IComputeExtraInfoResult[] { - var result:IComputeExtraInfoResult[] = []; + public computeSync(): Hover[] { + var result:Hover[] = []; var lineNumber = this._range.startLineNumber; if (lineNumber > this._editor.getModel().getLineCount()) { @@ -68,12 +69,15 @@ class ModesContentComputer implements IHoverComputer var endColumn = (d.range.endLineNumber === lineNumber) ? d.range.endColumn : maxColumn; if (startColumn <= this._range.startColumn && this._range.endColumn <= endColumn && (d.options.hoverMessage || (d.options.htmlMessage && d.options.htmlMessage.length > 0))) { - var obj:IComputeExtraInfoResult = { - value: d.options.hoverMessage, + var obj:Hover = { + htmlContent: [], range: new Range(this._range.startLineNumber, startColumn, this._range.startLineNumber, endColumn) }; - if(d.options.htmlMessage) { - obj.htmlContent = d.options.htmlMessage; + if (d.options.hoverMessage) { + obj.htmlContent.push({ text: d.options.hoverMessage }); + } + if (d.options.htmlMessage) { + obj.htmlContent = obj.htmlContent.concat(d.options.htmlMessage); } result.push(obj); } @@ -81,7 +85,7 @@ class ModesContentComputer implements IHoverComputer return result; } - public onResult(result: IComputeExtraInfoResult[], isFromSynchronousComputation: boolean): void { + public onResult(result: Hover[], isFromSynchronousComputation: boolean): void { // Always put synchronous messages before asynchronous ones if (isFromSynchronousComputation) { this._result = result.concat(this._result); @@ -90,15 +94,15 @@ class ModesContentComputer implements IHoverComputer } } - public getResult(): IComputeExtraInfoResult[] { + public getResult(): Hover[] { return this._result.slice(0); } - public getResultWithLoadingMessage(): IComputeExtraInfoResult[] { + public getResultWithLoadingMessage(): Hover[] { return this._result.slice(0).concat([this._getLoadingMessage()]); } - private _getLoadingMessage(): IComputeExtraInfoResult { + private _getLoadingMessage(): Hover { return { range: this._range, htmlContent: [{ @@ -115,10 +119,10 @@ class ModesContentComputer implements IHoverComputer export class ModesContentHoverWidget extends ContentHoverWidget { static ID = 'editor.contrib.modesContentHoverWidget'; - private _messages: IComputeExtraInfoResult[]; - private _lastRange: IEditorRange; + private _messages: Hover[]; + private _lastRange: Range; private _computer: ModesContentComputer; - private _hoverOperation: HoverOperation; + private _hoverOperation: HoverOperation; private _highlightDecorations:string[]; private _isChangingDecorations: boolean; private _openerService: IOpenerService; @@ -134,7 +138,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget { this._hoverOperation = new HoverOperation( this._computer, - (result:IComputeExtraInfoResult[]) => this._withResult(result, true), + (result:Hover[]) => this._withResult(result, true), null, (result:any) => this._withResult(result, false) ); @@ -153,7 +157,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget { } } - public startShowingAt(range: IEditorRange, focus: boolean): void { + public startShowingAt(range: Range, focus: boolean): void { if (this._lastRange) { if (this._lastRange.equalsRange(range)) { // We have to show the widget at the exact same range as before, so no work is needed @@ -170,7 +174,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget { if (this._showAtPosition.lineNumber !== range.startLineNumber) { this.hide(); } else { - var filteredMessages: IComputeExtraInfoResult[] = []; + var filteredMessages: Hover[] = []; for (var i = 0, len = this._messages.length; i < len; i++) { var msg = this._messages[i]; var rng = msg.range; @@ -201,7 +205,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget { this._isChangingDecorations = false; } - public _withResult(result: IComputeExtraInfoResult[], complete:boolean): void { + public _withResult(result: Hover[], complete:boolean): void { this._messages = result; if (this._lastRange && this._messages.length > 0) { @@ -211,8 +215,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget { } } - // TODO@Alex: pull this out into a common utility class - private _renderMessages(renderRange: IRange, messages: IComputeExtraInfoResult[]): void { + private _renderMessages(renderRange: IRange, messages: Hover[]): void { // update column from which to show var renderColumn = Number.MAX_VALUE, @@ -228,17 +231,9 @@ export class ModesContentHoverWidget extends ContentHoverWidget { highlightRange = Range.plusRange(highlightRange, msg.range); var row:HTMLElement = document.createElement('div'); - var span:HTMLElement = null; var container = row; - if (msg.className) { - span = document.createElement('span'); - span.className = msg.className; - container = span; - row.appendChild(span); - } - - if(msg.htmlContent && msg.htmlContent.length > 0) { + if (msg.htmlContent && msg.htmlContent.length > 0) { msg.htmlContent.forEach((content) => { container.appendChild(renderHtml(content, { actionCallback: (content) => { @@ -254,8 +249,6 @@ export class ModesContentHoverWidget extends ContentHoverWidget { } })); }); - } else { - container.textContent = msg.value; } fragment.appendChild(row); diff --git a/src/vs/editor/contrib/hover/common/hover.ts b/src/vs/editor/contrib/hover/common/hover.ts index a6c4f2fa6a4..33b2b77395f 100644 --- a/src/vs/editor/contrib/hover/common/hover.ts +++ b/src/vs/editor/contrib/hover/common/hover.ts @@ -8,23 +8,25 @@ import {coalesce} from 'vs/base/common/arrays'; import {onUnexpectedError} from 'vs/base/common/errors'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IModel, IPosition} from 'vs/editor/common/editorCommon'; +import {IReadOnlyModel} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; -import {IComputeExtraInfoResult, ExtraInfoRegistry} from 'vs/editor/common/modes'; +import {Hover, HoverProviderRegistry} from 'vs/editor/common/modes'; +import {asWinJsPromise} from 'vs/base/common/async'; +import {Position} from 'vs/editor/common/core/position'; -export function getExtraInfoAtPosition(model: IModel, position: IPosition): TPromise { +export function getHover(model: IReadOnlyModel, position: Position): TPromise { - const resource = model.getAssociatedResource(); - const supports = ExtraInfoRegistry.ordered(model); - const values: IComputeExtraInfoResult[] = []; + const supports = HoverProviderRegistry.ordered(model); + const values: Hover[] = []; const promises = supports.map((support, idx) => { - return support.computeInfo(resource, position).then(result => { + return asWinJsPromise((token) => { + return support.provideHover(model, position, token); + }).then((result) => { if (result) { let hasRange = (typeof result.range !== 'undefined'); - let hasValue = (typeof result.value !== 'undefined'); let hasHtmlContent = (typeof result.htmlContent !== 'undefined' && result.htmlContent && result.htmlContent.length > 0); - if (hasRange && (hasValue || hasHtmlContent)) { + if (hasRange && hasHtmlContent) { values[idx] = result; } } @@ -36,4 +38,4 @@ export function getExtraInfoAtPosition(model: IModel, position: IPosition): TPro return TPromise.join(promises).then(() => coalesce(values)); } -CommonEditorRegistry.registerDefaultLanguageCommand('_executeHoverProvider', getExtraInfoAtPosition); \ No newline at end of file +CommonEditorRegistry.registerDefaultLanguageCommand('_executeHoverProvider', getHover); \ No newline at end of file diff --git a/src/vs/editor/contrib/iPadShowKeyboard/browser/iPadShowKeyboard.ts b/src/vs/editor/contrib/iPadShowKeyboard/browser/iPadShowKeyboard.ts index ab7c931c9a3..0961ff85fb3 100644 --- a/src/vs/editor/contrib/iPadShowKeyboard/browser/iPadShowKeyboard.ts +++ b/src/vs/editor/contrib/iPadShowKeyboard/browser/iPadShowKeyboard.ts @@ -9,7 +9,7 @@ import 'vs/css!./iPadShowKeyboard'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import * as browser from 'vs/base/browser/browser'; import * as dom from 'vs/base/browser/dom'; -import {EventType, IEditorContribution} from 'vs/editor/common/editorCommon'; +import {IEditorContribution} from 'vs/editor/common/editorCommon'; import {ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, OverlayWidgetPositionPreference} from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; @@ -25,7 +25,7 @@ export class IPadShowKeyboard implements IEditorContribution { this.editor = editor; this.toDispose = []; if (browser.isIPad) { - this.toDispose.push(editor.addListener2(EventType.ConfigurationChanged, () => this.update())); + this.toDispose.push(editor.onDidChangeConfiguration(() => this.update())); this.update(); } } diff --git a/src/vs/editor/contrib/inPlaceReplace/common/inPlaceReplace.ts b/src/vs/editor/contrib/inPlaceReplace/common/inPlaceReplace.ts index 9950a902c90..458d60f4e77 100644 --- a/src/vs/editor/contrib/inPlaceReplace/common/inPlaceReplace.ts +++ b/src/vs/editor/contrib/inPlaceReplace/common/inPlaceReplace.ts @@ -51,7 +51,7 @@ class InPlaceReplace extends EditorAction { var selection = this.editor.getSelection(), model = this.editor.getModel(), support = model.getMode().inplaceReplaceSupport, - modelURI = model.getAssociatedResource(); + modelURI = model.uri; if(selection.startLineNumber !== selection.endLineNumber) { // Can't accept multiline selection diff --git a/src/vs/editor/contrib/inPlaceReplace/common/inPlaceReplaceCommand.ts b/src/vs/editor/contrib/inPlaceReplace/common/inPlaceReplaceCommand.ts index 5916b79525a..f40e6b77269 100644 --- a/src/vs/editor/contrib/inPlaceReplace/common/inPlaceReplaceCommand.ts +++ b/src/vs/editor/contrib/inPlaceReplace/common/inPlaceReplaceCommand.ts @@ -6,14 +6,15 @@ import {Selection} from 'vs/editor/common/core/selection'; import * as editorCommon from 'vs/editor/common/editorCommon'; +import {Range} from 'vs/editor/common/core/range'; export class InPlaceReplaceCommand implements editorCommon.ICommand { - private _editRange: editorCommon.IEditorRange; - private _originalSelection: editorCommon.IEditorSelection; + private _editRange: Range; + private _originalSelection: Selection; private _text:string; - constructor(editRange: editorCommon.IEditorRange, originalSelection: editorCommon.IEditorSelection, text:string) { + constructor(editRange: Range, originalSelection: Selection, text:string) { this._editRange = editRange; this._originalSelection = originalSelection; this._text = text; @@ -23,7 +24,7 @@ export class InPlaceReplaceCommand implements editorCommon.ICommand { builder.addEditOperation(this._editRange, this._text); } - public computeCursorState(model:editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData):editorCommon.IEditorSelection { + public computeCursorState(model:editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData):Selection { var inverseEditOperations = helper.getInverseEditOperations(); var srcRange = inverseEditOperations[0].range; diff --git a/src/vs/editor/contrib/indentation/common/indentationCommands.ts b/src/vs/editor/contrib/indentation/common/indentationCommands.ts index 1f7ea212286..e52b3e170b7 100644 --- a/src/vs/editor/contrib/indentation/common/indentationCommands.ts +++ b/src/vs/editor/contrib/indentation/common/indentationCommands.ts @@ -4,7 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import {Range} from 'vs/editor/common/core/range'; -import {ICommand, ICursorStateComputerData, IEditOperationBuilder, IEditorSelection, ITokenizedModel} from 'vs/editor/common/editorCommon'; +import {ICommand, ICursorStateComputerData, IEditOperationBuilder, ITokenizedModel} from 'vs/editor/common/editorCommon'; +import {Selection} from 'vs/editor/common/core/selection'; function getIndentationEditOperations(model: ITokenizedModel, builder: IEditOperationBuilder, tabSize: number, tabsToSpaces: boolean): void { if (model.getLineCount() === 1 && model.getLineMaxColumn(1) === 1) { @@ -36,14 +37,14 @@ export class IndentationToSpacesCommand implements ICommand { private selectionId: string; - constructor(private selection: IEditorSelection, private tabSize: number) { } + constructor(private selection: Selection, private tabSize: number) { } public getEditOperations(model: ITokenizedModel, builder: IEditOperationBuilder): void { this.selectionId = builder.trackSelection(this.selection); getIndentationEditOperations(model, builder, this.tabSize, true); } - public computeCursorState(model: ITokenizedModel, helper: ICursorStateComputerData): IEditorSelection { + public computeCursorState(model: ITokenizedModel, helper: ICursorStateComputerData): Selection { return helper.getTrackedSelection(this.selectionId); } } @@ -52,14 +53,14 @@ export class IndentationToTabsCommand implements ICommand { private selectionId: string; - constructor(private selection: IEditorSelection, private tabSize: number) { } + constructor(private selection: Selection, private tabSize: number) { } public getEditOperations(model: ITokenizedModel, builder: IEditOperationBuilder): void { this.selectionId = builder.trackSelection(this.selection); getIndentationEditOperations(model, builder, this.tabSize, false); } - public computeCursorState(model: ITokenizedModel, helper: ICursorStateComputerData): IEditorSelection { + public computeCursorState(model: ITokenizedModel, helper: ICursorStateComputerData): Selection { return helper.getTrackedSelection(this.selectionId); } } diff --git a/src/vs/editor/contrib/linesOperations/common/copyLinesCommand.ts b/src/vs/editor/contrib/linesOperations/common/copyLinesCommand.ts index 569048032db..34b710e693b 100644 --- a/src/vs/editor/contrib/linesOperations/common/copyLinesCommand.ts +++ b/src/vs/editor/contrib/linesOperations/common/copyLinesCommand.ts @@ -10,7 +10,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; export class CopyLinesCommand implements editorCommon.ICommand { - private _selection: editorCommon.IEditorSelection; + private _selection: Selection; private _isCopyingDown: boolean; private _selectionDirection:editorCommon.SelectionDirection; @@ -18,7 +18,7 @@ export class CopyLinesCommand implements editorCommon.ICommand { private _startLineNumberDelta: number; private _endLineNumberDelta: number; - constructor(selection: editorCommon.IEditorSelection, isCopyingDown: boolean) { + constructor(selection: Selection, isCopyingDown: boolean) { this._selection = selection; this._isCopyingDown = isCopyingDown; } @@ -57,7 +57,7 @@ export class CopyLinesCommand implements editorCommon.ICommand { this._selectionDirection = this._selection.getDirection(); } - public computeCursorState(model:editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData):editorCommon.IEditorSelection { + public computeCursorState(model:editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData):Selection { var result = helper.getTrackedSelection(this._selectionId); if (this._startLineNumberDelta !== 0 || this._endLineNumberDelta !== 0) { diff --git a/src/vs/editor/contrib/linesOperations/common/deleteLinesCommand.ts b/src/vs/editor/contrib/linesOperations/common/deleteLinesCommand.ts index c268b80ec75..bcca93db4f2 100644 --- a/src/vs/editor/contrib/linesOperations/common/deleteLinesCommand.ts +++ b/src/vs/editor/contrib/linesOperations/common/deleteLinesCommand.ts @@ -6,12 +6,12 @@ import {Range} from 'vs/editor/common/core/range'; import {Selection} from 'vs/editor/common/core/selection'; -import {ICommand, ICursorStateComputerData, IEditOperationBuilder, IEditorSelection, ITokenizedModel} from 'vs/editor/common/editorCommon'; +import {ICommand, ICursorStateComputerData, IEditOperationBuilder, ITokenizedModel} from 'vs/editor/common/editorCommon'; export class DeleteLinesCommand implements ICommand { - public static createFromSelection(selection:IEditorSelection): DeleteLinesCommand { + public static createFromSelection(selection:Selection): DeleteLinesCommand { var endLineNumber = selection.endLineNumber; if (selection.startLineNumber < selection.endLineNumber && selection.endColumn === 1) { endLineNumber -= 1; @@ -51,7 +51,7 @@ export class DeleteLinesCommand implements ICommand { builder.addEditOperation(new Range(startLineNumber, startColumn, endLineNumber, endColumn), null); } - public computeCursorState(model:ITokenizedModel, helper: ICursorStateComputerData):IEditorSelection { + public computeCursorState(model:ITokenizedModel, helper: ICursorStateComputerData):Selection { var inverseEditOperations = helper.getInverseEditOperations(); var srcRange = inverseEditOperations[0].range; return Selection.createSelection( diff --git a/src/vs/editor/contrib/linesOperations/common/moveLinesCommand.ts b/src/vs/editor/contrib/linesOperations/common/moveLinesCommand.ts index eba420f1cd2..e6d88a2f154 100644 --- a/src/vs/editor/contrib/linesOperations/common/moveLinesCommand.ts +++ b/src/vs/editor/contrib/linesOperations/common/moveLinesCommand.ts @@ -6,17 +6,17 @@ import {Range} from 'vs/editor/common/core/range'; import {Selection} from 'vs/editor/common/core/selection'; -import {ICommand, ICursorStateComputerData, IEditOperationBuilder, IEditorSelection, ITokenizedModel} from 'vs/editor/common/editorCommon'; +import {ICommand, ICursorStateComputerData, IEditOperationBuilder, ITokenizedModel} from 'vs/editor/common/editorCommon'; export class MoveLinesCommand implements ICommand { - private _selection: IEditorSelection; + private _selection: Selection; private _isMovingDown: boolean; private _selectionId: string; private _moveEndPositionDown: boolean; - constructor(selection: IEditorSelection, isMovingDown: boolean) { + constructor(selection: Selection, isMovingDown: boolean) { this._selection = selection; this._isMovingDown = isMovingDown; } @@ -88,7 +88,7 @@ export class MoveLinesCommand implements ICommand { this._selectionId = builder.trackSelection(s); } - public computeCursorState(model:ITokenizedModel, helper: ICursorStateComputerData):IEditorSelection { + public computeCursorState(model:ITokenizedModel, helper: ICursorStateComputerData):Selection { var result = helper.getTrackedSelection(this._selectionId); if (this._moveEndPositionDown) { diff --git a/src/vs/editor/contrib/linesOperations/common/sortLinesCommand.ts b/src/vs/editor/contrib/linesOperations/common/sortLinesCommand.ts index 0d0f5156f69..3036688b561 100644 --- a/src/vs/editor/contrib/linesOperations/common/sortLinesCommand.ts +++ b/src/vs/editor/contrib/linesOperations/common/sortLinesCommand.ts @@ -7,14 +7,15 @@ import {EditOperation} from 'vs/editor/common/core/editOperation'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {Range} from 'vs/editor/common/core/range'; +import {Selection} from 'vs/editor/common/core/selection'; export class SortLinesCommand implements editorCommon.ICommand { - private selection:editorCommon.IEditorSelection; + private selection:Selection; private selectionId:string; private descending:boolean; - constructor(selection:editorCommon.IEditorSelection, descending:boolean) { + constructor(selection:Selection, descending:boolean) { this.selection = selection; this.descending = descending; } @@ -28,7 +29,7 @@ export class SortLinesCommand implements editorCommon.ICommand { this.selectionId = builder.trackSelection(this.selection); } - public computeCursorState(model:editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData):editorCommon.IEditorSelection { + public computeCursorState(model:editorCommon.ITokenizedModel, helper: editorCommon.ICursorStateComputerData):Selection { return helper.getTrackedSelection(this.selectionId); } } @@ -36,7 +37,7 @@ export class SortLinesCommand implements editorCommon.ICommand { /** * Generate commands for sorting lines on a model. */ -export function sortLines(model:editorCommon.ITextModel, selection:editorCommon.IEditorSelection, descending:boolean): editorCommon.IIdentifiedSingleEditOperation { +export function sortLines(model:editorCommon.ITextModel, selection:Selection, descending:boolean): editorCommon.IIdentifiedSingleEditOperation { let startLineNumber = selection.startLineNumber; let endLineNumber = selection.endLineNumber; diff --git a/src/vs/editor/contrib/links/browser/links.ts b/src/vs/editor/contrib/links/browser/links.ts index 78f9112efca..d9387382213 100644 --- a/src/vs/editor/contrib/links/browser/links.ts +++ b/src/vs/editor/contrib/links/browser/links.ts @@ -8,7 +8,6 @@ import 'vs/css!./links'; import * as nls from 'vs/nls'; import {onUnexpectedError} from 'vs/base/common/errors'; -import {ListenerUnbind} from 'vs/base/common/eventEmitter'; import {KeyCode} from 'vs/base/common/keyCodes'; import * as platform from 'vs/base/common/platform'; import Severity from 'vs/base/common/severity'; @@ -22,9 +21,12 @@ import {EditorAction} from 'vs/editor/common/editorAction'; import {Behaviour} from 'vs/editor/common/editorActionEnablement'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; -import {ILink} from 'vs/editor/common/modes'; +import {ILink, LinkProviderRegistry} from 'vs/editor/common/modes'; import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService'; -import {IEditorMouseEvent} from 'vs/editor/browser/editorBrowser'; +import {IEditorMouseEvent, ICodeEditor} from 'vs/editor/browser/editorBrowser'; +import {getLinks} from 'vs/editor/contrib/links/common/links'; +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; +import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; class LinkOccurence { @@ -42,9 +44,6 @@ class LinkOccurence { private static _getOptions(link:ILink, isActive:boolean):editorCommon.IModelDecorationOptions { var result = ''; - if (link.extraInlineClassName) { - result = link.extraInlineClassName + ' '; - } if (isActive) { result += LinkDetector.CLASS_NAME_ACTIVE; @@ -77,18 +76,22 @@ class LinkOccurence { } class Link { - range: editorCommon.IEditorRange; + range: Range; url: string; - extraInlineClassName: string; constructor(source:ILink) { this.range = new Range(source.range.startLineNumber, source.range.startColumn, source.range.endLineNumber, source.range.endColumn); this.url = source.url; - this.extraInlineClassName = source.extraInlineClassName || null; } } -class LinkDetector { +class LinkDetector implements editorCommon.IEditorContribution { + + public static ID: string = 'editor.linkDetector'; + public static get(editor:editorCommon.ICommonCodeEditor): LinkDetector { + return editor.getContribution(LinkDetector.ID); + } + static RECOMPUTE_TIME = 1000; // ms static TRIGGER_KEY_VALUE = platform.isMacintosh ? KeyCode.Meta : KeyCode.Ctrl; static TRIGGER_MODIFIER = platform.isMacintosh ? 'metaKey' : 'ctrlKey'; @@ -96,8 +99,8 @@ class LinkDetector { static CLASS_NAME = 'detected-link'; static CLASS_NAME_ACTIVE = 'detected-link-active'; - private editor:editorCommon.ICommonCodeEditor; - private listenersToRemove:ListenerUnbind[]; + private editor:ICodeEditor; + private listenersToRemove:IDisposable[]; private timeoutPromise:TPromise; private computePromise:TPromise; private activeLinkDecorationId:string; @@ -108,28 +111,23 @@ class LinkDetector { private currentOccurences:{ [decorationId:string]:LinkOccurence; }; constructor( - editor:editorCommon.ICommonCodeEditor, - editorService:IEditorService, - messageService:IMessageService, - editorWorkerService: IEditorWorkerService + editor:ICodeEditor, + @IEditorService editorService:IEditorService, + @IMessageService messageService:IMessageService, + @IEditorWorkerService editorWorkerService: IEditorWorkerService ) { this.editor = editor; this.editorService = editorService; this.messageService = messageService; this.editorWorkerService = editorWorkerService; this.listenersToRemove = []; - this.listenersToRemove.push(editor.addListener('change', (e:editorCommon.IModelContentChangedEvent) => this.onChange())); - this.listenersToRemove.push(editor.addListener(editorCommon.EventType.ModelChanged, (e:editorCommon.IModelContentChangedEvent) => this.onModelChanged())); - this.listenersToRemove.push(editor.addListener(editorCommon.EventType.ModelModeChanged, (e:editorCommon.IModelModeChangedEvent) => this.onModelModeChanged())); - this.listenersToRemove.push(editor.addListener(editorCommon.EventType.ModelModeSupportChanged, (e: editorCommon.IModeSupportChangedEvent) => { - if (e.linkSupport) { - this.onModelModeChanged(); - } - })); - this.listenersToRemove.push(this.editor.addListener(editorCommon.EventType.MouseUp, (e:IEditorMouseEvent) => this.onEditorMouseUp(e))); - this.listenersToRemove.push(this.editor.addListener(editorCommon.EventType.MouseMove, (e:IEditorMouseEvent) => this.onEditorMouseMove(e))); - this.listenersToRemove.push(this.editor.addListener(editorCommon.EventType.KeyDown, (e:IKeyboardEvent) => this.onEditorKeyDown(e))); - this.listenersToRemove.push(this.editor.addListener(editorCommon.EventType.KeyUp, (e:IKeyboardEvent) => this.onEditorKeyUp(e))); + this.listenersToRemove.push(editor.onDidChangeModelContent((e) => this.onChange())); + this.listenersToRemove.push(editor.onDidChangeModel((e) => this.onModelChanged())); + this.listenersToRemove.push(editor.onDidChangeModelMode((e) => this.onModelModeChanged())); + this.listenersToRemove.push(this.editor.onMouseUp((e:IEditorMouseEvent) => this.onEditorMouseUp(e))); + this.listenersToRemove.push(this.editor.onMouseMove((e:IEditorMouseEvent) => this.onEditorMouseMove(e))); + this.listenersToRemove.push(this.editor.onKeyDown((e:IKeyboardEvent) => this.onEditorKeyDown(e))); + this.listenersToRemove.push(this.editor.onKeyUp((e:IKeyboardEvent) => this.onEditorKeyUp(e))); this.timeoutPromise = null; this.computePromise = null; this.currentOccurences = {}; @@ -137,6 +135,10 @@ class LinkDetector { this.beginCompute(); } + public getId(): string { + return LinkDetector.ID; + } + public isComputing(): boolean { return TPromise.is(this.computePromise); } @@ -170,12 +172,11 @@ class LinkDetector { } let modePromise:TPromise = TPromise.as(null); - let mode = this.editor.getModel().getMode(); - if (mode.linkSupport) { - modePromise = mode.linkSupport.computeLinks(this.editor.getModel().getAssociatedResource()); + if (LinkProviderRegistry.has(this.editor.getModel())) { + modePromise = getLinks(this.editor.getModel()); } - let standardPromise:TPromise = this.editorWorkerService.computeLinks(this.editor.getModel().getAssociatedResource()); + let standardPromise:TPromise = this.editorWorkerService.computeLinks(this.editor.getModel().uri); this.computePromise = TPromise.join([modePromise, standardPromise]).then((r) => { let a = r[0]; @@ -407,10 +408,7 @@ class LinkDetector { } public dispose():void { - this.listenersToRemove.forEach((element) => { - element(); - }); - this.listenersToRemove = []; + this.listenersToRemove = dispose(this.listenersToRemove); this.stop(); } } @@ -419,40 +417,33 @@ class OpenLinkAction extends EditorAction { static ID = 'editor.action.openLink'; - private _linkDetector: LinkDetector; - constructor( descriptor:editorCommon.IEditorActionDescriptorData, - editor:editorCommon.ICommonCodeEditor, - @IEditorService editorService:IEditorService, - @IMessageService messageService:IMessageService, - @IEditorWorkerService editorWorkerService: IEditorWorkerService + editor:editorCommon.ICommonCodeEditor ) { super(descriptor, editor, Behaviour.WidgetFocus | Behaviour.UpdateOnCursorPositionChange); - - this._linkDetector = new LinkDetector(editor, editorService, messageService, editorWorkerService); } public dispose(): void { - this._linkDetector.dispose(); super.dispose(); } public getEnablementState(): boolean { - if(this._linkDetector.isComputing()) { + if (LinkDetector.get(this.editor).isComputing()) { // optimistic enablement while state is being computed return true; } - return !!this._linkDetector.getLinkOccurence(this.editor.getPosition()); + return !!LinkDetector.get(this.editor).getLinkOccurence(this.editor.getPosition()); } public run():TPromise { - var link = this._linkDetector.getLinkOccurence(this.editor.getPosition()); + var link = LinkDetector.get(this.editor).getLinkOccurence(this.editor.getPosition()); if(link) { - this._linkDetector.openLinkOccurence(link, false); + LinkDetector.get(this.editor).openLinkOccurence(link, false); } return TPromise.as(null); } } CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(OpenLinkAction, OpenLinkAction.ID, nls.localize('label', "Open Link"), void 0, 'Open Link')); +EditorBrowserRegistry.registerEditorContribution(LinkDetector); diff --git a/src/vs/editor/contrib/links/common/links.ts b/src/vs/editor/contrib/links/common/links.ts new file mode 100644 index 00000000000..cedde11015f --- /dev/null +++ b/src/vs/editor/contrib/links/common/links.ts @@ -0,0 +1,37 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import {onUnexpectedError} from 'vs/base/common/errors'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {IReadOnlyModel} from 'vs/editor/common/editorCommon'; +import {ILink, LinkProviderRegistry} from 'vs/editor/common/modes'; +import {asWinJsPromise} from 'vs/base/common/async'; + +export function getLinks(model: IReadOnlyModel): TPromise { + + const promises = LinkProviderRegistry.ordered(model).map((support) => { + return asWinJsPromise((token) => { + return support.provideLinks(model, token); + }).then((result) => { + if (Array.isArray(result)) { + return result; + } + }, err => { + onUnexpectedError(err); + }); + }); + + return TPromise.join(promises).then(manyLinks => { + let result: ILink[] = []; + for (let links of manyLinks) { + if (links) { + result = result.concat(links); + } + } + return result; + }); +} diff --git a/src/vs/editor/contrib/outlineMarker/browser/outlineMarker.ts b/src/vs/editor/contrib/outlineMarker/browser/outlineMarker.ts index d7c1c926633..2360502202b 100644 --- a/src/vs/editor/contrib/outlineMarker/browser/outlineMarker.ts +++ b/src/vs/editor/contrib/outlineMarker/browser/outlineMarker.ts @@ -12,9 +12,10 @@ import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {TPromise} from 'vs/base/common/winjs.base'; import {Range} from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import {IOutlineEntry} from 'vs/editor/common/modes'; +import {SymbolInformation, SymbolKind, DocumentSymbolProviderRegistry} from 'vs/editor/common/modes'; import {ICodeEditor, IViewZone, IViewZoneChangeAccessor} from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; +import {getDocumentSymbols, IOutline} from 'vs/editor/contrib/quickOpen/common/quickOpen'; class OutlineViewZone implements IViewZone { @@ -24,15 +25,14 @@ class OutlineViewZone implements IViewZone { public domNode:HTMLElement; - constructor(range:editorCommon.IRange, outlineType:string) - { + constructor(range:editorCommon.IRange, outlineType:SymbolKind) { this.afterLineNumber = range.startLineNumber-1; this.heightInPx = 4; this.suppressMouseDown = true; this.domNode = document.createElement('div'); var hr = document.createElement('hr'); - hr.className = 'outlineRule ' + outlineType; + hr.className = 'outlineRule ' + SymbolKind.from(outlineType); this.domNode.appendChild(hr); } } @@ -77,8 +77,7 @@ class OutlineMarker { private _editor:ICodeEditor; - public constructor(range:editorCommon.IRange, outlineType:string, _editor:ICodeEditor, helper:OutlineMarkerHelper, viewZoneChangeAccessor:IViewZoneChangeAccessor) - { + public constructor(range:editorCommon.IRange, outlineType:SymbolKind, _editor:ICodeEditor, helper:OutlineMarkerHelper, viewZoneChangeAccessor:IViewZoneChangeAccessor) { this._editor = _editor; this._viewZone = new OutlineViewZone(range, outlineType); this._viewZoneId = viewZoneChangeAccessor.addZone(this._viewZone); @@ -117,7 +116,7 @@ export class OutlineMarkerContribution implements editorCommon.IEditorContributi private _globalToDispose:IDisposable[]; private _localToDispose:IDisposable[]; - private _currentOutlinePromise:TPromise; + private _currentOutlinePromise:TPromise; private _markers:OutlineMarker[]; @@ -130,14 +129,9 @@ export class OutlineMarkerContribution implements editorCommon.IEditorContributi this._markers = []; this._currentOutlinePromise = null; - this._globalToDispose.push(this._editor.addListener2(editorCommon.EventType.ModelChanged, () => this.onChange(true))); - this._globalToDispose.push(this._editor.addListener2(editorCommon.EventType.ModelModeChanged, () => this.onChange(false))); - this._globalToDispose.push(this._editor.addListener2(editorCommon.EventType.ModelModeSupportChanged, (e: editorCommon.IModeSupportChangedEvent) => { - if (e.outlineSupport) { - this.onChange(false); - } - })); - this._globalToDispose.push(this._editor.addListener2(editorCommon.EventType.ConfigurationChanged,(e: editorCommon.IConfigurationChangedEvent) => { + this._globalToDispose.push(this._editor.onDidChangeModel(() => this.onChange(true))); + this._globalToDispose.push(this._editor.onDidChangeModelMode(() => this.onChange(false))); + this._globalToDispose.push(this._editor.onDidChangeConfiguration((e: editorCommon.IConfigurationChangedEvent) => { let oldIsEnabled = this._isEnabled; this._isEnabled = this._editor.getConfiguration().contribInfo.outlineMarkers; if (oldIsEnabled !== this._isEnabled) { @@ -181,8 +175,7 @@ export class OutlineMarkerContribution implements editorCommon.IEditorContributi return; } - var mode = model.getMode(); - if (!mode.outlineSupport) { + if (!DocumentSymbolProviderRegistry.has(model)) { return; } @@ -191,16 +184,16 @@ export class OutlineMarkerContribution implements editorCommon.IEditorContributi this._currentOutlinePromise.cancel(); } - this._currentOutlinePromise = mode.outlineSupport.getOutline(model.getAssociatedResource()); + this._currentOutlinePromise = getDocumentSymbols(model); this._currentOutlinePromise.then((result) => { - this.renderOutlines(result); + this.renderOutlines(result.entries); }, (error) => { onUnexpectedError(error); }); }, 250); this._localToDispose.push(scheduler); - this._localToDispose.push(this._editor.addListener2('change',() => { + this._localToDispose.push(this._editor.onDidChangeModelContent(() => { // Synchronously move markers this._editor.changeViewZones((viewAccessor) => { @@ -229,7 +222,7 @@ export class OutlineMarkerContribution implements editorCommon.IEditorContributi scheduler.schedule(); } - private renderOutlines(entries: IOutlineEntry[]): void { + private renderOutlines(entries: SymbolInformation[]): void { var centeredRange = this._editor.getCenteredRangeInViewport(); var oldMarkersCount = this._markers.length; this._editor.changeDecorations((decorationsAccessor) => { @@ -249,18 +242,16 @@ export class OutlineMarkerContribution implements editorCommon.IEditorContributi } } - private renderOutlinesRecursive(entries: IOutlineEntry[], helper:OutlineMarkerHelper, viewZoneChangeAccessor:IViewZoneChangeAccessor): void { + private renderOutlinesRecursive(entries: SymbolInformation[], helper:OutlineMarkerHelper, viewZoneChangeAccessor:IViewZoneChangeAccessor): void { if (entries) { entries.forEach((outline) => { - if (outline.type === 'class' || outline.type === 'method' || outline.type === 'function') { - var range = Range.lift(outline.range); + if (outline.kind === SymbolKind.Class || outline.kind === SymbolKind.Method || outline.kind === SymbolKind.Function) { + var range = Range.lift(outline.location.range); if (!this.alreadyHasMarkerAtRange(range)) { - var marker = new OutlineMarker(range, outline.type, this._editor, helper, viewZoneChangeAccessor); + var marker = new OutlineMarker(range, outline.kind, this._editor, helper, viewZoneChangeAccessor); this._markers.push(marker); } } - - this.renderOutlinesRecursive(outline.children, helper, viewZoneChangeAccessor); }); } } diff --git a/src/vs/editor/contrib/parameterHints/browser/parameterHints.ts b/src/vs/editor/contrib/parameterHints/browser/parameterHints.ts index bbf4ea5f39e..c7c81071136 100644 --- a/src/vs/editor/contrib/parameterHints/browser/parameterHints.ts +++ b/src/vs/editor/contrib/parameterHints/browser/parameterHints.ts @@ -13,7 +13,7 @@ import {ICommonCodeEditor, IEditorActionDescriptorData, IEditorContribution} fro import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; -import {ParameterHintsRegistry} from 'vs/editor/common/modes'; +import {SignatureHelpProviderRegistry} from 'vs/editor/common/modes'; import {ParameterHintsModel} from './parameterHintsModel'; import {ParameterHintsWidget} from './parameterHintsWidget'; @@ -65,7 +65,7 @@ class ParameterHintsController implements IEditorContribution { } public trigger(): void { - this.model.trigger(undefined, 0); + this.model.trigger(0); } } @@ -78,7 +78,7 @@ export class TriggerParameterHintsAction extends EditorAction { } public isSupported(): boolean { - return ParameterHintsRegistry.has(this.editor.getModel()) && super.isSupported(); + return SignatureHelpProviderRegistry.has(this.editor.getModel()) && super.isSupported(); } public run():TPromise { diff --git a/src/vs/editor/contrib/parameterHints/browser/parameterHintsModel.ts b/src/vs/editor/contrib/parameterHints/browser/parameterHintsModel.ts index 9913c7b29d4..a0281c79dcb 100644 --- a/src/vs/editor/contrib/parameterHints/browser/parameterHintsModel.ts +++ b/src/vs/editor/contrib/parameterHints/browser/parameterHintsModel.ts @@ -4,17 +4,16 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {ThrottledDelayer} from 'vs/base/common/async'; +import {RunOnceScheduler} from 'vs/base/common/async'; import {onUnexpectedError} from 'vs/base/common/errors'; import Event, {Emitter} from 'vs/base/common/event'; import {IDisposable, dispose, Disposable} from 'vs/base/common/lifecycle'; -import {TPromise} from 'vs/base/common/winjs.base'; -import {EventType, ICommonCodeEditor, ICursorSelectionChangedEvent, IModeSupportChangedEvent} from 'vs/editor/common/editorCommon'; -import {ParameterHintsRegistry, IParameterHints} from 'vs/editor/common/modes'; -import {getParameterHints} from '../common/parameterHints'; +import {ICommonCodeEditor, ICursorSelectionChangedEvent} from 'vs/editor/common/editorCommon'; +import {SignatureHelpProviderRegistry, SignatureHelp} from 'vs/editor/common/modes'; +import {provideSignatureHelp} from '../common/parameterHints'; export interface IHintEvent { - hints: IParameterHints; + hints: SignatureHelp; } export class ParameterHintsModel extends Disposable { @@ -31,7 +30,7 @@ export class ParameterHintsModel extends Disposable { private triggerCharactersListeners: IDisposable[]; private active: boolean; - private throttledDelayer: ThrottledDelayer; + private throttledDelayer: RunOnceScheduler; constructor(editor:ICommonCodeEditor) { super(); @@ -39,15 +38,14 @@ export class ParameterHintsModel extends Disposable { this.editor = editor; this.triggerCharactersListeners = []; - this.throttledDelayer = new ThrottledDelayer(ParameterHintsModel.DELAY); + this.throttledDelayer = new RunOnceScheduler(() => this.doTrigger(), ParameterHintsModel.DELAY); this.active = false; - this._register(this.editor.addListener2(EventType.ModelChanged, e => this.onModelChanged())); - this._register(this.editor.addListener2(EventType.ModelModeChanged, _ => this.onModelChanged())); - this._register(this.editor.addListener2(EventType.ModelModeSupportChanged, e => this.onModeChanged(e))); - this._register(this.editor.addListener2(EventType.CursorSelectionChanged, e => this.onCursorChange(e))); - this._register(ParameterHintsRegistry.onDidChange(this.onModelChanged, this)); + this._register(this.editor.onDidChangeModel(e => this.onModelChanged())); + this._register(this.editor.onDidChangeModelMode(_ => this.onModelChanged())); + this._register(this.editor.onDidChangeCursorSelection(e => this.onCursorChange(e))); + this._register(SignatureHelpProviderRegistry.onDidChange(this.onModelChanged, this)); this.onModelChanged(); } @@ -61,18 +59,18 @@ export class ParameterHintsModel extends Disposable { } } - public trigger(triggerCharacter?: string, delay: number = ParameterHintsModel.DELAY): TPromise { - if (!ParameterHintsRegistry.has(this.editor.getModel())) { + public trigger(delay = ParameterHintsModel.DELAY): void { + if (!SignatureHelpProviderRegistry.has(this.editor.getModel())) { return; } this.cancel(true); - return this.throttledDelayer.trigger(() => this.doTrigger(triggerCharacter), delay); + return this.throttledDelayer.schedule(delay); } - private doTrigger(triggerCharacter: string): TPromise { - return getParameterHints(this.editor.getModel(), this.editor.getPosition(), triggerCharacter) - .then(null, onUnexpectedError) + private doTrigger(): void { + provideSignatureHelp(this.editor.getModel(), this.editor.getPosition()) + .then(null, onUnexpectedError) .then(result => { if (!result || result.signatures.length === 0) { this.cancel(); @@ -89,7 +87,7 @@ export class ParameterHintsModel extends Disposable { } public isTriggered():boolean { - return this.active || this.throttledDelayer.isTriggered(); + return this.active || this.throttledDelayer.isScheduled(); } private onModelChanged(): void { @@ -103,33 +101,18 @@ export class ParameterHintsModel extends Disposable { return; } - let support = ParameterHintsRegistry.ordered(model)[0]; + let support = SignatureHelpProviderRegistry.ordered(model)[0]; if (!support) { return; } - this.triggerCharactersListeners = support.getParameterHintsTriggerCharacters().map((ch) => { - let listener = this.editor.addTypingListener(ch, () => { - let position = this.editor.getPosition(); - let lineContext = model.getLineContext(position.lineNumber); - - if (!support.shouldTriggerParameterHints(lineContext, position.column - 1)) { - return; - } - - this.trigger(ch); + this.triggerCharactersListeners = support.signatureHelpTriggerCharacters.map((ch) => { + return this.editor.addTypingListener(ch, () => { + this.trigger(); }); - - return { dispose: listener }; }); } - private onModeChanged(e: IModeSupportChangedEvent): void { - if (e.parameterHintsSupport) { - this.onModelChanged(); - } - } - private onCursorChange(e: ICursorSelectionChangedEvent): void { if (e.source === 'mouse') { this.cancel(); diff --git a/src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts b/src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts index b91335599c1..28e4e7d96c0 100644 --- a/src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts +++ b/src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts @@ -11,8 +11,8 @@ import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {TPromise} from 'vs/base/common/winjs.base'; import {Builder, $} from 'vs/base/browser/builder'; import aria = require('vs/base/browser/ui/aria/aria'); -import {EventType, ICursorSelectionChangedEvent, IConfigurationChangedEvent} from 'vs/editor/common/editorCommon'; -import {IParameterHints, ISignature} from 'vs/editor/common/modes'; +import {ICursorSelectionChangedEvent, IConfigurationChangedEvent} from 'vs/editor/common/editorCommon'; +import {SignatureHelp, SignatureInformation} from 'vs/editor/common/modes'; import {ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition} from 'vs/editor/browser/editorBrowser'; import {IHintEvent, ParameterHintsModel} from './parameterHintsModel'; @@ -35,7 +35,7 @@ export class ParameterHintsWidget implements IContentWidget { private currentSignature: number; private isDisposed: boolean; private isVisible: boolean; - private parameterHints: IParameterHints; + private parameterHints: SignatureHelp; private announcedLabel: string; private toDispose: IDisposable[]; @@ -61,7 +61,7 @@ export class ParameterHintsWidget implements IContentWidget { this.show(); this.parameterHints = e.hints; this.render(e.hints); - this.currentSignature = e.hints.currentSignature; + this.currentSignature = e.hints.activeSignature; this.select(this.currentSignature); })); @@ -100,14 +100,14 @@ export class ParameterHintsWidget implements IContentWidget { this.editor.addContentWidget(this); this.hide(); - this.toDispose.push(this.editor.addListener2(EventType.CursorSelectionChanged,(e: ICursorSelectionChangedEvent) => { + this.toDispose.push(this.editor.onDidChangeCursorSelection((e: ICursorSelectionChangedEvent) => { if (this.isVisible) { this.editor.layoutContentWidget(this); } })); this.editor.applyFontInfo(this.getDomNode()); - this.toDispose.push(this.editor.addListener2(EventType.ConfigurationChanged,(e: IConfigurationChangedEvent) => { + this.toDispose.push(this.editor.onDidChangeConfiguration((e: IConfigurationChangedEvent) => { if (e.fontInfo) { this.editor.applyFontInfo(this.getDomNode()); } @@ -156,7 +156,7 @@ export class ParameterHintsWidget implements IContentWidget { return null; } - private render(hints:IParameterHints): void { + private render(hints:SignatureHelp): void { if (hints.signatures.length > 1) { this.$el.addClass('multiple'); } else { @@ -169,9 +169,9 @@ export class ParameterHintsWidget implements IContentWidget { for (var i = 0, len = hints.signatures.length; i < len; i++) { var signature = hints.signatures[i]; - var $signature = this.renderSignature(this.$signatures, signature, hints.currentParameter); + var $signature = this.renderSignature(this.$signatures, signature, hints.activeParameter); - this.renderDocumentation($signature, signature, hints.currentParameter); + this.renderDocumentation($signature, signature, hints.activeParameter); var signatureHeight = $signature.getClientArea().height; @@ -184,7 +184,7 @@ export class ParameterHintsWidget implements IContentWidget { } } - private renderSignature($el:Builder, signature:ISignature, currentParameter:number):Builder { + private renderSignature($el:Builder, signature:SignatureInformation, currentParameter:number):Builder { var $signature = $('.signature').appendTo($el), hasParameters = signature.parameters.length > 0; @@ -197,11 +197,22 @@ export class ParameterHintsWidget implements IContentWidget { var $parameters = $('span.parameters'), offset = 0; + let idx = 0; for (var i = 0, len = signature.parameters.length; i < len; i++) { var parameter = signature.parameters[i]; - (i === 0 ? $signature : $parameters).append($('span').text(signature.label.substring(offset, parameter.signatureLabelOffset))); - $parameters.append($('span.parameter').addClass(i === currentParameter ? 'active' : '').text(signature.label.substring(parameter.signatureLabelOffset, parameter.signatureLabelEnd))); - offset = parameter.signatureLabelEnd; + idx = signature.label.indexOf(parameter.label, idx); + + let signatureLabelOffset = 0; + let signatureLabelEnd = 0; + if (idx >= 0) { + signatureLabelOffset = idx; + idx += parameter.label.length; + signatureLabelEnd = idx; + } + + (i === 0 ? $signature : $parameters).append($('span').text(signature.label.substring(offset, signatureLabelOffset))); + $parameters.append($('span.parameter').addClass(i === currentParameter ? 'active' : '').text(signature.label.substring(signatureLabelOffset, signatureLabelEnd))); + offset = signatureLabelEnd; } $signature.append($parameters); @@ -211,7 +222,7 @@ export class ParameterHintsWidget implements IContentWidget { return $signature; } - private renderDocumentation($el:Builder, signature:ISignature, activeParameterIdx:number): void { + private renderDocumentation($el:Builder, signature:SignatureInformation, activeParameterIdx:number): void { if(signature.documentation) { $el.append($('.documentation').text(signature.documentation)); @@ -243,8 +254,8 @@ export class ParameterHintsWidget implements IContentWidget { } this.$overloads.text(overloads); - if (this.parameterHints && this.parameterHints.signatures[position].parameters[this.parameterHints.currentParameter]) { - const labelToAnnounce = this.parameterHints.signatures[position].parameters[this.parameterHints.currentParameter].label; + if (this.parameterHints && this.parameterHints.signatures[position].parameters[this.parameterHints.activeParameter]) { + const labelToAnnounce = this.parameterHints.signatures[position].parameters[this.parameterHints.activeParameter].label; // Select method gets called on every user type while parameter hints are visible. // We do not want to spam the user with same announcements, so we only announce if the current parameter changed. if (this.announcedLabel !== labelToAnnounce) { diff --git a/src/vs/editor/contrib/parameterHints/common/parameterHints.ts b/src/vs/editor/contrib/parameterHints/common/parameterHints.ts index 167eca90413..911e86d6b48 100644 --- a/src/vs/editor/contrib/parameterHints/common/parameterHints.ts +++ b/src/vs/editor/contrib/parameterHints/common/parameterHints.ts @@ -5,26 +5,21 @@ 'use strict'; -import {illegalArgument} from 'vs/base/common/errors'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IModel, IPosition} from 'vs/editor/common/editorCommon'; +import {IReadOnlyModel} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; -import {IParameterHints, ParameterHintsRegistry} from 'vs/editor/common/modes'; +import {SignatureHelp, SignatureHelpProviderRegistry} from 'vs/editor/common/modes'; +import {asWinJsPromise} from 'vs/base/common/async'; +import {Position} from 'vs/editor/common/core/position'; -export function getParameterHints(model:IModel, position:IPosition, triggerCharacter: string): TPromise { +export function provideSignatureHelp(model:IReadOnlyModel, position:Position): TPromise { - let support = ParameterHintsRegistry.ordered(model)[0]; + let support = SignatureHelpProviderRegistry.ordered(model)[0]; if (!support) { return TPromise.as(undefined); } - return support.getParameterHints(model.getAssociatedResource(), position, triggerCharacter); + return asWinJsPromise((token) => support.provideSignatureHelp(model, position, token)); } -CommonEditorRegistry.registerDefaultLanguageCommand('_executeSignatureHelpProvider', function(model, position, args) { - let {triggerCharacter} = args; - if (triggerCharacter && typeof triggerCharacter !== 'string') { - throw illegalArgument('triggerCharacter'); - } - return getParameterHints(model, position, triggerCharacter); -}); \ No newline at end of file +CommonEditorRegistry.registerDefaultLanguageCommand('_executeSignatureHelpProvider', provideSignatureHelp); \ No newline at end of file diff --git a/src/vs/editor/contrib/quickFix/browser/quickFix.ts b/src/vs/editor/contrib/quickFix/browser/quickFix.ts index e73efc6bbe6..dee047d3166 100644 --- a/src/vs/editor/contrib/quickFix/browser/quickFix.ts +++ b/src/vs/editor/contrib/quickFix/browser/quickFix.ts @@ -7,7 +7,6 @@ import * as nls from 'vs/nls'; import {onUnexpectedError} from 'vs/base/common/errors'; import {KeyCode, KeyMod} from 'vs/base/common/keyCodes'; -import Severity from 'vs/base/common/severity'; import {TPromise} from 'vs/base/common/winjs.base'; import {IEditorService} from 'vs/platform/editor/common/editor'; import {IEventService} from 'vs/platform/event/common/event'; @@ -18,9 +17,8 @@ import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {EditorAction} from 'vs/editor/common/editorAction'; import {ICommonCodeEditor, IEditorActionDescriptorData, IEditorContribution, IRange} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; -import {bulkEdit} from 'vs/editor/common/services/bulkEdit'; import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; -import {QuickFixRegistry} from 'vs/editor/common/modes'; +import {CodeActionProviderRegistry} from 'vs/editor/common/modes'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {IQuickFix2} from '../common/quickFix'; import {QuickFixModel} from './quickFixModel'; @@ -34,30 +32,23 @@ export class QuickFixController implements IEditorContribution { return editor.getContribution(QuickFixController.ID); } - private eventService: IEventService; - private editorService: IEditorService; - private messageService: IMessageService; - private editor:ICodeEditor; private model:QuickFixModel; private suggestWidget: QuickFixSelectionWidget; private quickFixWidgetVisible: IKeybindingContextKey; constructor(editor: ICodeEditor, - @IMarkerService markerService: IMarkerService, - @IKeybindingService keybindingService: IKeybindingService, + @IMarkerService private _markerService: IMarkerService, + @IKeybindingService private _keybindingService: IKeybindingService, @ITelemetryService telemetryService: ITelemetryService, - @IEventService eventService: IEventService, + @IEventService private _eventService: IEventService, @IEditorService editorService: IEditorService, @IMessageService messageService: IMessageService ) { this.editor = editor; - this.model = new QuickFixModel(this.editor, markerService, this.onAccept.bind(this)); - this.eventService = eventService; - this.editorService = editorService; - this.messageService = messageService; + this.model = new QuickFixModel(this.editor, this._markerService, this.onAccept.bind(this)); - this.quickFixWidgetVisible = keybindingService.createKey(CONTEXT_QUICK_FIX_WIDGET_VISIBLE, false); + this.quickFixWidgetVisible = this._keybindingService.createKey(CONTEXT_QUICK_FIX_WIDGET_VISIBLE, false); this.suggestWidget = new QuickFixSelectionWidget(this.editor, telemetryService,() => { this.quickFixWidgetVisible.set(true); },() => { @@ -72,29 +63,15 @@ export class QuickFixController implements IEditorContribution { private onAccept(fix: IQuickFix2, range: IRange): void { var model = this.editor.getModel(); - if (!model) { - return; + if (model) { + let {command} = fix; + return this._keybindingService.executeCommand(command.id, ...command.arguments).done(void 0, onUnexpectedError); } - - fix.support.runQuickFixAction(this.editor.getModel().getAssociatedResource(), range, { command: fix.command, score: fix.score }).then(result => { - if (result) { - if (result.message) { - this.messageService.show(Severity.Info, result.message); - } - if (result.edits) { - return bulkEdit(this.eventService, this.editorService, this.editor, result.edits); - } - } - return TPromise.as(0); - }).done(undefined, err => { - onUnexpectedError(err); - }); } public run():TPromise { this.model.triggerDialog(false, this.editor.getPosition()); this.editor.focus(); - return TPromise.as(false); } @@ -151,7 +128,7 @@ export class QuickFixAction extends EditorAction { public isSupported(): boolean { var model = this.editor.getModel(); - return QuickFixRegistry.has(model) && !this.editor.getConfiguration().readOnly; + return CodeActionProviderRegistry.has(model) && !this.editor.getConfiguration().readOnly; } public run():TPromise { diff --git a/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts b/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts index 23edf07444b..9d24ee30e99 100644 --- a/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts +++ b/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts @@ -14,10 +14,10 @@ import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import {IMarker, IMarkerService} from 'vs/platform/markers/common/markers'; import {Range} from 'vs/editor/common/core/range'; -import {EventType, ICursorPositionChangedEvent, IModeSupportChangedEvent, IPosition, IRange} from 'vs/editor/common/editorCommon'; +import {ICursorPositionChangedEvent, IPosition, IRange} from 'vs/editor/common/editorCommon'; import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; -import {QuickFixRegistry} from 'vs/editor/common/modes'; -import {IQuickFix2, getQuickFixes} from '../common/quickFix'; +import {CodeActionProviderRegistry} from 'vs/editor/common/modes'; +import {IQuickFix2, getCodeActions} from '../common/quickFix'; import {LightBulpWidget} from './lightBulpWidget'; enum QuickFixSuggestState { @@ -78,14 +78,9 @@ export class QuickFixModel extends EventEmitter { this.autoSuggestDelay = 300; } - this.toDispose.push(this.editor.addListener2(EventType.ModelChanged, () => this.onModelChanged())); - this.toDispose.push(this.editor.addListener2(EventType.ModelModeChanged, () => this.onModelChanged())); - this.toDispose.push(this.editor.addListener2(EventType.ModelModeSupportChanged, (e: IModeSupportChangedEvent) => { - if (e.quickFixSupport) { - this.onModelChanged(); - } - })); - this.toDispose.push(QuickFixRegistry.onDidChange(this.onModelChanged, this)); + this.toDispose.push(this.editor.onDidChangeModel(() => this.onModelChanged())); + this.toDispose.push(this.editor.onDidChangeModelMode(() => this.onModelChanged())); + this.toDispose.push(CodeActionProviderRegistry.onDidChange(this.onModelChanged, this)); } private onModelChanged(): void { @@ -96,14 +91,14 @@ export class QuickFixModel extends EventEmitter { this.markers = null; this.updateScheduler = null; - if (!QuickFixRegistry.has(this.editor.getModel()) || this.editor.getConfiguration().readOnly) { + if (!CodeActionProviderRegistry.has(this.editor.getModel()) || this.editor.getConfiguration().readOnly) { this.setDecoration(null); return; } this.markerService.onMarkerChanged(this.onMarkerChanged, this, this.toLocalDispose); - this.toLocalDispose.push(this.editor.addListener2(EventType.CursorPositionChanged, (e: ICursorPositionChangedEvent) => { + this.toLocalDispose.push(this.editor.onDidChangeCursorPosition((e: ICursorPositionChangedEvent) => { this.onCursorPositionChanged(); })); } @@ -124,7 +119,7 @@ export class QuickFixModel extends EventEmitter { if (!model) { return; } - var associatedResource = model.getAssociatedResource(); + var associatedResource = model.uri; if (!changedResources.some(r => associatedResource.toString() === r.toString())) { return; } @@ -199,7 +194,7 @@ export class QuickFixModel extends EventEmitter { private computeFixes(range: IMarker | IRange): TPromise { let model = this.editor.getModel(); - if (!QuickFixRegistry.has(model)) { + if (!CodeActionProviderRegistry.has(model)) { return TPromise.as(null); } @@ -213,7 +208,7 @@ export class QuickFixModel extends EventEmitter { } this.quickFixRequestPromiseRange = range; - this.quickFixRequestPromise = getQuickFixes(model, range); + this.quickFixRequestPromise = getCodeActions(model, Range.lift(range)); return this.quickFixRequestPromise; } @@ -228,7 +223,7 @@ export class QuickFixModel extends EventEmitter { if (!model) { return; } - this.markers = this.markerService.read({ resource: model.getAssociatedResource() }) + this.markers = this.markerService.read({ resource: model.uri }) .sort((e1, e2) => { return e1.startLineNumber - e2.startLineNumber; }); return this.markers; diff --git a/src/vs/editor/contrib/quickFix/browser/quickFixSelectionWidget.ts b/src/vs/editor/contrib/quickFix/browser/quickFixSelectionWidget.ts index 1b09c084ae4..03b02bd9643 100644 --- a/src/vs/editor/contrib/quickFix/browser/quickFixSelectionWidget.ts +++ b/src/vs/editor/contrib/quickFix/browser/quickFixSelectionWidget.ts @@ -8,7 +8,6 @@ import 'vs/css!./quickFix'; import * as nls from 'vs/nls'; import {illegalArgument, onUnexpectedError} from 'vs/base/common/errors'; -import {ListenerUnbind} from 'vs/base/common/eventEmitter'; import * as timer from 'vs/base/common/timer'; import {TPromise} from 'vs/base/common/winjs.base'; import * as dom from 'vs/base/browser/dom'; @@ -17,12 +16,13 @@ import {IDataSource, IFocusEvent, IRenderer, ISelectionEvent, ITree, IAccessibil import {DefaultController} from 'vs/base/parts/tree/browser/treeDefaults'; import {Tree} from 'vs/base/parts/tree/browser/treeImpl'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; -import {EventType, ICursorSelectionChangedEvent, IRange} from 'vs/editor/common/editorCommon'; +import {ICursorSelectionChangedEvent, IRange} from 'vs/editor/common/editorCommon'; import {ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition} from 'vs/editor/browser/editorBrowser'; import {IQuickFix2} from '../common/quickFix'; import {QuickFixModel} from './quickFixModel'; import {alert} from 'vs/base/browser/ui/aria/aria'; import {ScrollbarVisibility} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; var $ = dom.emmet; @@ -207,8 +207,8 @@ export class QuickFixSelectionWidget implements IContentWidget { private isActive: boolean; private isLoading: boolean; private isAuto: boolean; - private listenersToRemove: ListenerUnbind[]; - private modelListenersToRemove: ListenerUnbind[]; + private listenersToRemove: IDisposable[]; + private modelListenersToRemove: IDisposable[]; private model: QuickFixModel; private telemetryData: ITelemetryData; @@ -259,7 +259,7 @@ export class QuickFixSelectionWidget implements IContentWidget { ariaLabel: nls.localize('treeAriaLabel', "Quick Fix") }); - this.listenersToRemove.push(this.tree.addListener('selection', (e:ISelectionEvent) => { + this.listenersToRemove.push(this.tree.addListener2('selection', (e:ISelectionEvent) => { if (e.selection && e.selection.length > 0) { var element = e.selection[0]; if (isQuickFix(element) && !(element instanceof MessageRoot) && !(element instanceof Message)) { @@ -278,7 +278,7 @@ export class QuickFixSelectionWidget implements IContentWidget { var oldFocus: any = null; - this.listenersToRemove.push(this.tree.addListener('focus', (e:IFocusEvent) => { + this.listenersToRemove.push(this.tree.addListener2('focus', (e:IFocusEvent) => { var focus = e.focus; var payload = e.payload; @@ -313,7 +313,7 @@ export class QuickFixSelectionWidget implements IContentWidget { this.editor.addContentWidget(this); - this.listenersToRemove.push(this.editor.addListener(EventType.CursorSelectionChanged, (e: ICursorSelectionChangedEvent) => { + this.listenersToRemove.push(this.editor.onDidChangeCursorSelection((e: ICursorSelectionChangedEvent) => { if (this.isActive) { this.editor.layoutContentWidget(this); } @@ -340,7 +340,7 @@ export class QuickFixSelectionWidget implements IContentWidget { var timer : timer.ITimerEvent = null, loadingHandle:number; - this.modelListenersToRemove.push(this.model.addListener('loading', (e: any) => { + this.modelListenersToRemove.push(this.model.addListener2('loading', (e: any) => { if (!this.isActive) { timer = this.telemetryService.timedPublicLog('QuickFixSelectionWidgetLoadingTime'); this.isLoading = true; @@ -363,7 +363,7 @@ export class QuickFixSelectionWidget implements IContentWidget { } })); - this.modelListenersToRemove.push(this.model.addListener('suggest',(e: { fixes: IQuickFix2[]; range: IRange; auto:boolean; }) => { + this.modelListenersToRemove.push(this.model.addListener2('suggest',(e: { fixes: IQuickFix2[]; range: IRange; auto:boolean; }) => { this.isLoading = false; if(typeof loadingHandle !== 'undefined') { @@ -405,7 +405,7 @@ export class QuickFixSelectionWidget implements IContentWidget { } })); - this.modelListenersToRemove.push(this.model.addListener('empty', (e: { auto:boolean; }) => { + this.modelListenersToRemove.push(this.model.addListener2('empty', (e: { auto:boolean; }) => { var wasLoading = this.isLoading; this.isLoading = false; @@ -436,7 +436,7 @@ export class QuickFixSelectionWidget implements IContentWidget { } })); - this.modelListenersToRemove.push(this.model.addListener('cancel', (e:any) => { + this.modelListenersToRemove.push(this.model.addListener2('cancel', (e:any) => { this.isLoading = false; if(typeof loadingHandle !== 'undefined') { @@ -532,10 +532,7 @@ export class QuickFixSelectionWidget implements IContentWidget { } private releaseModel() : void { - var listener:()=>void; - while (listener = this.modelListenersToRemove.pop()) { - listener(); - } + this.modelListenersToRemove = dispose(this.modelListenersToRemove); this.model = null; } @@ -603,9 +600,6 @@ export class QuickFixSelectionWidget implements IContentWidget { this.tree.dispose(); this.tree = null; - this.listenersToRemove.forEach((element) => { - element(); - }); - this.listenersToRemove = null; + this.listenersToRemove = dispose(this.listenersToRemove); } } \ No newline at end of file diff --git a/src/vs/editor/contrib/quickFix/common/quickFix.ts b/src/vs/editor/contrib/quickFix/common/quickFix.ts index ed25fd20b55..fe4f81446b6 100644 --- a/src/vs/editor/contrib/quickFix/common/quickFix.ts +++ b/src/vs/editor/contrib/quickFix/common/quickFix.ts @@ -8,23 +8,27 @@ import {illegalArgument, onUnexpectedError} from 'vs/base/common/errors'; import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; +import {IdGenerator} from 'vs/base/common/idGenerator'; import {Range} from 'vs/editor/common/core/range'; -import {IModel, IRange} from 'vs/editor/common/editorCommon'; +import {IReadOnlyModel} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; -import {QuickFixRegistry, IQuickFix, IQuickFixSupport} from 'vs/editor/common/modes'; +import {CodeActionProviderRegistry, IQuickFix, CodeActionProvider} from 'vs/editor/common/modes'; import {IModelService} from 'vs/editor/common/services/modelService'; +import {asWinJsPromise} from 'vs/base/common/async'; export interface IQuickFix2 extends IQuickFix { - support: IQuickFixSupport; + support: CodeActionProvider; id: string; } -export function getQuickFixes(model: IModel, range: IRange): TPromise { +export function getCodeActions(model: IReadOnlyModel, range: Range): TPromise { const quickFixes: IQuickFix2[] = []; - let idPool = 0; - const promises = QuickFixRegistry.all(model).map(support => { - return support.getQuickFixes(model.getAssociatedResource(), range).then(result => { + let ids = new IdGenerator('quickfix'); + const promises = CodeActionProviderRegistry.all(model).map(support => { + return asWinJsPromise((token) => { + return support.provideCodeActions(model, range, token); + }).then(result => { if (!Array.isArray(result)) { return; } @@ -32,7 +36,7 @@ export function getQuickFixes(model: IModel, range: IRange): TPromise { let model = this.editor.getModel(); - let mode = model.getMode(); - let outlineSupport = mode.outlineSupport; - // Only works for models with outline support - if (!outlineSupport) { + if (!DocumentSymbolProviderRegistry.has(model)) { return null; } // Resolve outline - let promise = outlineSupport.getOutline(model.getAssociatedResource()); - return promise.then((result: IOutlineEntry[]) => { - if (Array.isArray(result) && result.length > 0) { + let promise = getDocumentSymbols(model); + return promise.then((result: IOutline) => { + if (result.entries.length > 0) { // Cache result - this.cachedResult = result; + this.cachedResult = result.entries; return super.run(); } @@ -184,15 +171,9 @@ export class QuickOutlineAction extends BaseEditorQuickOpenAction { return nls.localize('quickOutlineActionInput', "Type the name of an identifier you wish to navigate to"); } - private toQuickOpenEntries(outline: OutlineNode[], searchValue: string): SymbolEntry[] { + private toQuickOpenEntries(flattened: SymbolInformation[], searchValue: string): SymbolEntry[] { let results: SymbolEntry[] = []; - // Flatten - let flattened: OutlineNode[] = []; - if (outline) { - this.flatten(outline, flattened); - } - // Convert to Entries let normalizedSearchValue = searchValue; if (searchValue.indexOf(SCOPE_PREFIX) === 0) { @@ -201,7 +182,7 @@ export class QuickOutlineAction extends BaseEditorQuickOpenAction { for (let i = 0; i < flattened.length; i++) { let element = flattened[i]; - let label = strings.trim(element.label); + let label = strings.trim(element.name); // Check for meatch let highlights = matchesFuzzy(normalizedSearchValue, label); @@ -209,12 +190,12 @@ export class QuickOutlineAction extends BaseEditorQuickOpenAction { // Show parent scope as description let description: string = null; - if (element.parentScope) { - description = arrays.tail(element.parentScope); + if (element.containerName) { + description = element.containerName; } // Add - results.push(new SymbolEntry(label, element.type, description, element.range, highlights, this.editor, this)); + results.push(new SymbolEntry(label, SymbolKind.from(element.kind), description, element.location.range, highlights, this.editor, this)); } } @@ -288,27 +269,6 @@ export class QuickOutlineAction extends BaseEditorQuickOpenAction { return type; } - private flatten(outline: OutlineNode[], flattened: OutlineNode[], parentScope?: string[]): void { - for (let i = 0; i < outline.length; i++) { - let element = outline[i]; - flattened.push(element); - - if (parentScope) { - element.parentScope = parentScope; - } - - if (element.children) { - let elementScope: string[] = []; - if (parentScope) { - elementScope = parentScope.slice(0); - } - elementScope.push(element.label); - - this.flatten(element.children, flattened, elementScope); - } - } - } - private sortNormal(searchValue: string, elementA: SymbolEntry, elementB: SymbolEntry): number { let elementAName = elementA.getLabel().toLowerCase(); let elementBName = elementB.getLabel().toLowerCase(); diff --git a/src/vs/editor/contrib/quickOpen/common/quickOpen.ts b/src/vs/editor/contrib/quickOpen/common/quickOpen.ts index 4fe14698ab5..f44b0ff6669 100644 --- a/src/vs/editor/contrib/quickOpen/common/quickOpen.ts +++ b/src/vs/editor/contrib/quickOpen/common/quickOpen.ts @@ -11,30 +11,23 @@ import {TPromise} from 'vs/base/common/winjs.base'; import {Range} from 'vs/editor/common/core/range'; import {IModel} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; -import {IOutlineEntry, OutlineRegistry} from 'vs/editor/common/modes'; +import {SymbolInformation, DocumentSymbolProviderRegistry} from 'vs/editor/common/modes'; import {IModelService} from 'vs/editor/common/services/modelService'; +import {asWinJsPromise} from 'vs/base/common/async'; export interface IOutline { - entries: IOutlineEntry[]; - outlineGroupLabel: { [n: string]: string; }; + entries: SymbolInformation[]; } -export function getOutlineEntries(model: IModel): TPromise { +export function getDocumentSymbols(model: IModel): TPromise { - let groupLabels: { [n: string]: string } = Object.create(null); - let entries: IOutlineEntry[] = []; + let entries: SymbolInformation[] = []; - let promises = OutlineRegistry.all(model).map(support => { + let promises = DocumentSymbolProviderRegistry.all(model).map(support => { - if (support.outlineGroupLabel) { - let keys = Object.keys(support.outlineGroupLabel); - for (let i = 0, len = keys.length; i < len; i++) { - let key = keys[i]; - groupLabels[key] = support.outlineGroupLabel[key]; - } - } - - return support.getOutline(model.getAssociatedResource()).then(result => { + return asWinJsPromise((token) => { + return support.provideDocumentSymbols(model, token); + }).then(result => { if (Array.isArray(result)) { entries.push(...result); } @@ -44,33 +37,28 @@ export function getOutlineEntries(model: IModel): TPromise { }); return TPromise.join(promises).then(() => { - let flatEntries: IOutlineEntry[] = []; + let flatEntries: SymbolInformation[] = []; flatten(flatEntries, entries, ''); flatEntries.sort(compareEntriesUsingStart); return { entries: flatEntries, - outlineGroupLabel: groupLabels }; }); } -function compareEntriesUsingStart(a: IOutlineEntry, b: IOutlineEntry): number{ - return Range.compareRangesUsingStarts(Range.lift(a.range), Range.lift(b.range)); +function compareEntriesUsingStart(a: SymbolInformation, b: SymbolInformation): number{ + return Range.compareRangesUsingStarts(Range.lift(a.location.range), Range.lift(b.location.range)); } -function flatten(bucket: IOutlineEntry[], entries: IOutlineEntry[], overrideContainerLabel: string): void { +function flatten(bucket: SymbolInformation[], entries: SymbolInformation[], overrideContainerLabel: string): void { for (let entry of entries) { bucket.push({ - type: entry.type, - range: entry.range, - label: entry.label, - icon: entry.icon, - containerLabel: entry.containerLabel || overrideContainerLabel + kind: entry.kind, + location: entry.location, + name: entry.name, + containerName: entry.containerName || overrideContainerLabel }); - if (entry.children) { - flatten(bucket, entry.children, entry.label); - } } } @@ -84,5 +72,5 @@ CommonEditorRegistry.registerLanguageCommand('_executeDocumentSymbolProvider', f if (!model) { throw illegalArgument('resource'); } - return getOutlineEntries(model); + return getDocumentSymbols(model); }); \ No newline at end of file diff --git a/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts b/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts index cf5d4c201f7..74c483a01ce 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referenceSearch.ts @@ -18,9 +18,9 @@ import {EditorAction} from 'vs/editor/common/editorAction'; import {Behaviour} from 'vs/editor/common/editorActionEnablement'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; -import {IReference, ReferenceSearchRegistry} from 'vs/editor/common/modes'; +import {Location, ReferenceProviderRegistry} from 'vs/editor/common/modes'; import {IPeekViewService, getOuterEditor} from 'vs/editor/contrib/zoneWidget/browser/peekViewWidget'; -import {findReferences} from '../common/referenceSearch'; +import {provideReferences} from '../common/referenceSearch'; import {ReferenceWidget} from './referencesWidget'; import {ReferencesController, RequestOptions, ctxReferenceSearchVisible} from './referencesController'; import {ReferencesModel} from './referencesModel'; @@ -61,7 +61,7 @@ export class ReferenceAction extends EditorAction { } public isSupported():boolean { - return ReferenceSearchRegistry.has(this.editor.getModel()) && super.isSupported(); + return ReferenceProviderRegistry.has(this.editor.getModel()) && super.isSupported(); } public getEnablementState():boolean { @@ -69,20 +69,13 @@ export class ReferenceAction extends EditorAction { return false; } - let model = this.editor.getModel(); - let position = this.editor.getSelection().getStartPosition(); - let context = model.getLineContext(position.lineNumber); - let offset = position.column - 1; - - return ReferenceSearchRegistry.all(model).some(support => { - return support.canFindReferences(context, offset); - }); + return ReferenceProviderRegistry.has(this.editor.getModel()); } public run():TPromise { let range = this.editor.getSelection(); let model = this.editor.getModel(); - let references = findReferences(model, range.getStartPosition()).then(references => new ReferencesModel(references)); + let references = provideReferences(model, range.getStartPosition()).then(references => new ReferencesModel(references)); let controller = ReferencesController.getController(this.editor); return TPromise.as(controller.toggleWidget(range, references, defaultReferenceSearchOptions)).then(() => true); } @@ -104,14 +97,14 @@ let findReferencesCommand: ICommandHandler = (accessor:ServicesAccessor, resourc return; } - let references = findReferences(control.getModel(), position).then(references => new ReferencesModel(references)); + let references = provideReferences(control.getModel(), Position.lift(position)).then(references => new ReferencesModel(references)); let controller = ReferencesController.getController(control); let range = new Range(position.lineNumber, position.column, position.lineNumber, position.column); return TPromise.as(controller.toggleWidget(range, references, defaultReferenceSearchOptions)); }); }; -let showReferencesCommand: ICommandHandler = (accessor:ServicesAccessor, resource:URI, position:editorCommon.IPosition, references:IReference[]) => { +let showReferencesCommand: ICommandHandler = (accessor:ServicesAccessor, resource:URI, position:editorCommon.IPosition, references:Location[]) => { if (!(resource instanceof URI)) { throw new Error('illegal argument, uri expected'); } @@ -176,7 +169,7 @@ KeybindingsRegistry.registerCommandDesc({ weight: CommonEditorRegistry.commandWeight(50), primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape], - when: KbExpr.and(KbExpr.has(ctxReferenceSearchVisible), KbExpr.has('config.editor.dismissPeekOnEsc')), + when: KbExpr.and(KbExpr.has(ctxReferenceSearchVisible), KbExpr.not('config.editor.stablePeek')), handler: closeActiveReferenceSearch }); @@ -185,6 +178,6 @@ KeybindingsRegistry.registerCommandDesc({ weight: CommonEditorRegistry.commandWeight(-101), primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape], - when: KbExpr.and(KbExpr.has(ReferenceWidget.INNER_EDITOR_CONTEXT_KEY), KbExpr.has('config.editor.dismissPeekOnEsc')), + when: KbExpr.and(KbExpr.has(ReferenceWidget.INNER_EDITOR_CONTEXT_KEY), KbExpr.not('config.editor.stablePeek')), handler: closeActiveReferenceSearch }); diff --git a/src/vs/editor/contrib/referenceSearch/browser/referencesController.ts b/src/vs/editor/contrib/referenceSearch/browser/referencesController.ts index 764080e8d02..590462d715e 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referencesController.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referencesController.ts @@ -14,6 +14,7 @@ import {IInstantiationService, optional} from 'vs/platform/instantiation/common/ import {IKeybindingContextKey, IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; import {IMessageService} from 'vs/platform/message/common/message'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; +import {IConfigurationService, getConfigurationValue} from 'vs/platform/configuration/common/configuration'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {IStorageService} from 'vs/platform/storage/common/storage'; import * as editorCommon from 'vs/editor/common/editorCommon'; @@ -22,6 +23,7 @@ import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {IPeekViewService} from 'vs/editor/contrib/zoneWidget/browser/peekViewWidget'; import {ReferencesModel, OneReference} from './referencesModel'; import {ReferenceWidget, LayoutData} from './referencesWidget'; +import {Range} from 'vs/editor/common/core/range'; export const ctxReferenceSearchVisible = 'referenceSearchVisible'; @@ -56,6 +58,7 @@ export class ReferencesController implements editorCommon.IEditorContribution { @IInstantiationService private _instantiationService: IInstantiationService, @IWorkspaceContextService private _contextService: IWorkspaceContextService, @IStorageService private _storageService: IStorageService, + @IConfigurationService private _configurationService: IConfigurationService, @optional(IPeekViewService) private _peekViewService: IPeekViewService ) { this._editor = editor; @@ -74,7 +77,7 @@ export class ReferencesController implements editorCommon.IEditorContribution { this._editor = null; } - public toggleWidget(range: editorCommon.IEditorRange, modelPromise: TPromise, options: RequestOptions) : void { + public toggleWidget(range: Range, modelPromise: TPromise, options: RequestOptions) : void { // close current widget and return early is position didn't change let widgetPosition: editorCommon.IPosition; @@ -89,8 +92,8 @@ export class ReferencesController implements editorCommon.IEditorContribution { this._referenceSearchVisible.set(true); // close the widget on model/mode changes - this._disposables.push(this._editor.addListener2(editorCommon.EventType.ModelModeChanged, () => { this.closeWidget(); })); - this._disposables.push(this._editor.addListener2(editorCommon.EventType.ModelChanged, () => { + this._disposables.push(this._editor.onDidChangeModelMode(() => { this.closeWidget(); })); + this._disposables.push(this._editor.onDidChangeModel(() => { if(!this._ignoreModelChangeEvent) { this.closeWidget(); } @@ -111,8 +114,15 @@ export class ReferencesController implements editorCommon.IEditorContribution { this._disposables.push(this._widget.onDidSelectReference(event => { let {element, kind} = event; switch (kind) { - case 'side': case 'open': + if (event.source === 'editor' + && getConfigurationValue(this._configurationService.getConfiguration(), 'editor.stablePeek', false)) { + + // when stable peek is configured we don't close + // the peek window on selecting the editor + break; + } + case 'side': this._openReference(element, kind === 'side'); break; case 'goto': @@ -153,13 +163,15 @@ export class ReferencesController implements editorCommon.IEditorContribution { return this._widget.setModel(this._model).then(() => { // set title - this._widget.setMetaTitle(options.getMetaTitle(model)); + this._widget.setMetaTitle(options.getMetaTitle(this._model)); // set 'best' selection - let uri = this._editor.getModel().getAssociatedResource(); + let uri = this._editor.getModel().uri; let pos = { lineNumber: range.startLineNumber, column: range.startColumn }; let selection = this._model.nearestReference(uri, pos); - return this._widget.setSelection(selection); + if (selection) { + return this._widget.setSelection(selection); + } }); }, error => { @@ -184,10 +196,10 @@ export class ReferencesController implements editorCommon.IEditorContribution { private _gotoReference(ref: OneReference): void { this._ignoreModelChangeEvent = true; - const {resource, range} = ref; + const {uri, range} = ref; this._editorService.openEditor({ - resource, + resource: uri, options: { selection: range } }).done(openedEditor => { this._ignoreModelChangeEvent = false; @@ -214,9 +226,9 @@ export class ReferencesController implements editorCommon.IEditorContribution { } private _openReference(ref: OneReference, sideBySide: boolean): void { - const {resource, range} = ref; + const {uri, range} = ref; this._editorService.openEditor({ - resource, + resource: uri, options: { selection: range } }, sideBySide); diff --git a/src/vs/editor/contrib/referenceSearch/browser/referencesModel.ts b/src/vs/editor/contrib/referenceSearch/browser/referencesModel.ts index e281f462bd5..9a433da183f 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referencesModel.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referencesModel.ts @@ -9,12 +9,12 @@ import Event, {fromEventEmitter} from 'vs/base/common/event'; import {basename, dirname} from 'vs/base/common/paths'; import * as strings from 'vs/base/common/strings'; import URI from 'vs/base/common/uri'; -import {generateUuid} from 'vs/base/common/uuid'; +import {defaultGenerator} from 'vs/base/common/idGenerator'; import {TPromise} from 'vs/base/common/winjs.base'; import {IEditorService} from 'vs/platform/editor/common/editor'; import {Range} from 'vs/editor/common/core/range'; import {IModel, IPosition, IRange} from 'vs/editor/common/editorCommon'; -import {IReference} from 'vs/editor/common/modes'; +import {Location} from 'vs/editor/common/modes'; export class OneReference { @@ -25,7 +25,7 @@ export class OneReference { private _range: IRange, private _eventBus: EventEmitter ) { - this._id = generateUuid(); + this._id = defaultGenerator.nextId(); } public get id(): string { @@ -40,8 +40,8 @@ export class OneReference { return this._parent; } - public get resource(): URI { - return this._parent.resource; + public get uri(): URI { + return this._parent.uri; } public get name(): string { @@ -96,12 +96,12 @@ export class FileReferences { private _preview: FilePreview; private _resolved: boolean; - constructor(private _parent: ReferencesModel, private _resource: URI) { + constructor(private _parent: ReferencesModel, private _uri: URI) { this._children = []; } public get id(): string { - return this._resource.toString(); + return this._uri.toString(); } public get parent(): ReferencesModel { @@ -112,16 +112,16 @@ export class FileReferences { return this._children; } - public get resource(): URI { - return this._resource; + public get uri(): URI { + return this._uri; } public get name(): string { - return basename(this.resource.fsPath); + return basename(this.uri.fsPath); } public get directory(): string { - return dirname(this.resource.fsPath); + return dirname(this.uri.fsPath); } public get preview(): FilePreview { @@ -134,7 +134,7 @@ export class FileReferences { return TPromise.as(this); } - return editorService.resolveEditorModel({ resource: this._resource }).then(model => { + return editorService.resolveEditorModel({ resource: this._uri }).then(model => { this._preview = new FilePreview((model.textEditorModel).getValue()); this._resolved = true; return this; @@ -150,16 +150,16 @@ export class ReferencesModel { onDidChangeReferenceRange: Event = fromEventEmitter(this._eventBus, 'ref/changed'); - constructor(references: IReference[]) { + constructor(references: Location[]) { // grouping and sorting references.sort(ReferencesModel._compareReferences); let current: FileReferences; for (let ref of references) { - if (!current || current.resource.toString() !== ref.resource.toString()) { + if (!current || current.uri.toString() !== ref.uri.toString()) { // new group - current = new FileReferences(this, ref.resource); + current = new FileReferences(this, ref.uri); this.groups.push(current); } @@ -206,7 +206,7 @@ export class ReferencesModel { let candidate: OneReference; let candiateDist: number; for (let ref of this._references) { - if (ref.resource.toString() !== resource.toString()) { + if (ref.uri.toString() !== resource.toString()) { continue; } @@ -227,10 +227,10 @@ export class ReferencesModel { return candidate || this._references[0]; } - private static _compareReferences(a: IReference, b: IReference): number { - if (a.resource.toString() < b.resource.toString()) { + private static _compareReferences(a: Location, b: Location): number { + if (a.uri.toString() < b.uri.toString()) { return -1; - } else if (a.resource.toString() > b.resource.toString()) { + } else if (a.uri.toString() > b.uri.toString()) { return 1; } else { return Range.compareRangesUsingStarts(a.range, b.range); diff --git a/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts b/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts index d184968b0c6..1229d40e540 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/referencesWidget.ts @@ -10,7 +10,7 @@ import * as collections from 'vs/base/common/collections'; import {onUnexpectedError} from 'vs/base/common/errors'; import {getPathLabel} from 'vs/base/common/labels'; import Event, {Emitter} from 'vs/base/common/event'; -import {IDisposable, cAll, dispose, Disposables} from 'vs/base/common/lifecycle'; +import {IDisposable, dispose, Disposables} from 'vs/base/common/lifecycle'; import {Schemas} from 'vs/base/common/network'; import * as strings from 'vs/base/common/strings'; import {TPromise} from 'vs/base/common/winjs.base'; @@ -19,6 +19,7 @@ import * as dom from 'vs/base/browser/dom'; import {Sash, ISashEvent, IVerticalSashLayoutProvider} from 'vs/base/browser/ui/sash/sash'; import {IKeyboardEvent} from 'vs/base/browser/keyboardEvent'; import {IMouseEvent} from 'vs/base/browser/mouseEvent'; +import {GestureEvent} from 'vs/base/browser/touch'; import {CountBadge} from 'vs/base/browser/ui/countBadge/countBadge'; import {FileLabel} from 'vs/base/browser/ui/filelabel/fileLabel'; import {LeftRightWidget} from 'vs/base/browser/ui/leftRightWidget/leftRightWidget'; @@ -33,7 +34,7 @@ import {DefaultConfig} from 'vs/editor/common/config/defaultConfig'; import {Range} from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {Model} from 'vs/editor/common/model/model'; -import {ICodeEditor, IMouseTarget} from 'vs/editor/browser/editorBrowser'; +import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; import {EmbeddedCodeEditorWidget} from 'vs/editor/browser/widget/embeddedCodeEditorWidget'; import {PeekViewWidget, IPeekViewService} from 'vs/editor/contrib/zoneWidget/browser/peekViewWidget'; import {FileReferences, OneReference, ReferencesModel} from './referencesModel'; @@ -47,24 +48,24 @@ class DecorationsManager implements IDisposable { private _decorationSet = collections.createStringDictionary(); private _decorationIgnoreSet = collections.createStringDictionary(); - private _callOnDispose:Function[] = []; - private _callOnModelChange:Function[] = []; + private _callOnDispose:IDisposable[] = []; + private _callOnModelChange:IDisposable[] = []; constructor(private editor:ICodeEditor, private model:ReferencesModel) { - this._callOnDispose.push(this.editor.addListener(editorCommon.EventType.ModelChanged, () => this._onModelChanged())); + this._callOnDispose.push(this.editor.onDidChangeModel(() => this._onModelChanged())); this._onModelChanged(); } public dispose(): void { - this._callOnModelChange = cAll(this._callOnModelChange); - this._callOnDispose = cAll(this._callOnDispose); + this._callOnModelChange = dispose(this._callOnModelChange); + this._callOnDispose = dispose(this._callOnDispose); this.removeDecorations(); } private _onModelChanged():void { this.removeDecorations(); - this._callOnModelChange = cAll(this._callOnModelChange); + this._callOnModelChange = dispose(this._callOnModelChange); var model = this.editor.getModel(); if(!model) { @@ -72,7 +73,7 @@ class DecorationsManager implements IDisposable { } for(var i = 0, len = this.model.groups.length; i < len; i++) { - if(this.model.groups[i].resource.toString() === model.getAssociatedResource().toString()) { + if(this.model.groups[i].uri.toString() === model.uri.toString()) { this._addDecorations(this.model.groups[i]); return; } @@ -80,7 +81,7 @@ class DecorationsManager implements IDisposable { } private _addDecorations(reference:FileReferences):void { - this._callOnModelChange.push(this.editor.getModel().addListener(editorCommon.EventType.ModelDecorationsChanged, (event) => this._onDecorationChanged(event))); + this._callOnModelChange.push(this.editor.getModel().onDidChangeDecorations((event) => this._onDecorationChanged(event))); this.editor.getModel().changeDecorations((accessor) => { var newDecorations: editorCommon.IModelDeltaDecoration[] = []; @@ -106,17 +107,17 @@ class DecorationsManager implements IDisposable { }); } - private _onDecorationChanged(event:any):void { - var addedOrChangedDecorations = event.addedOrChangedDecorations, + private _onDecorationChanged(event:editorCommon.IModelDecorationsChangedEvent):void { + var addedOrChangedDecorations = event.addedOrChangedDecorations, toRemove:string[] = []; for(var i = 0, len = addedOrChangedDecorations.length; i < len; i++) { - var reference = collections.lookup(this._decorationSet, addedOrChangedDecorations[i].id); + var reference = collections.lookup(this._decorationSet, addedOrChangedDecorations[i].id); if(!reference) { continue; } - var newRange = addedOrChangedDecorations[i].range, + var newRange = addedOrChangedDecorations[i].range, ignore = false; if(Range.equalsRange(newRange, reference.range)) { @@ -212,6 +213,18 @@ class Controller extends DefaultController { OPEN_TO_SIDE: 'events/custom/opentoside' }; + public onTap(tree: tree.ITree, element: any, event: GestureEvent):boolean { + if (element instanceof FileReferences) { + event.preventDefault(); + event.stopPropagation(); + return this._expandCollapse(tree, element); + } + + var result = super.onTap(tree, element, event); + tree.emit(Controller.Events.FOCUSED, element); + return result; + } + public onMouseDown(tree:tree.ITree, element:any, event:IMouseEvent):boolean { if (event.leftButton) { if (element instanceof FileReferences) { @@ -319,13 +332,13 @@ class Controller extends DefaultController { class Renderer extends LegacyRenderer { private _contextService:IWorkspaceContextService; - constructor(private editor: ICodeEditor, @IWorkspaceContextService contextService:IWorkspaceContextService) { + constructor( @IWorkspaceContextService contextService: IWorkspaceContextService) { super(); this._contextService = contextService; } - public getHeight(tree:tree.ITree, element:any):number { - return 1.2 * this.editor.getConfiguration().lineHeight; + public getHeight(tree: tree.ITree, element: any): number { + return 22; } protected render(tree:tree.ITree, element:any, container:HTMLElement):tree.IElementCallback { @@ -338,7 +351,7 @@ class Renderer extends LegacyRenderer { /* tslint:disable:no-unused-expression */ new LeftRightWidget(fileReferencesContainer, (left: HTMLElement) => { - var resource = fileReferences.resource; + var resource = fileReferences.uri; new FileLabel(left, resource, this._contextService); return null; @@ -386,16 +399,19 @@ class VSash { getVerticalSashHeight: () => this._height }); - let data: { startX: number, startRatio: number }; + // compute the current widget clientX postion since + // the sash works with clientX when dragging + let clientX: number; this._disposables.add(this._sash.addListener2('start', (e: ISashEvent) => { - data = { startX: e.startX, startRatio: this._ratio }; + clientX = e.startX - (this._width * this.ratio); })); this._disposables.add(this._sash.addListener2('change', (e: ISashEvent) => { - let {currentX} = e; - let newRatio = data.startRatio * (currentX / data.startX); - if (newRatio > .05 && newRatio < .95) { - this._ratio = newRatio; + // compute the new position of the sash and from that + // compute the new ratio that we are using + let newLeft = e.currentX - clientX; + if (newLeft > 20 && newLeft + 20 < this._width) { + this._ratio = newLeft / this._width; this._sash.layout(); this._onDidChangePercentages.fire(this); } @@ -440,6 +456,7 @@ export interface LayoutData { export interface SelectionEvent { kind: 'goto' | 'show' | 'side' | 'open'; + source: 'editor' | 'tree' | 'title'; element: OneReference; } @@ -500,7 +517,8 @@ export class ReferenceWidget extends PeekViewWidget { if (this._preview && this._preview.getModel()) { this._onDidSelectReference.fire({ element: this._getFocusedReference(), - kind: e.ctrlKey || e.metaKey ? 'side' : 'open' + kind: e.ctrlKey || e.metaKey ? 'side' : 'open', + source: 'title' }); } } @@ -544,7 +562,7 @@ export class ReferenceWidget extends PeekViewWidget { container.div({ 'class': 'ref-tree inline' }, (div: Builder) => { var config = { dataSource: this._instantiationService.createInstance(DataSource), - renderer: this._instantiationService.createInstance(Renderer, this.editor), + renderer: this._instantiationService.createInstance(Renderer), //sorter: new Sorter(), controller: new Controller() }; @@ -606,7 +624,7 @@ export class ReferenceWidget extends PeekViewWidget { if (this._model.empty) { this.setTitle(''); this._messageContainer.innerHtml(nls.localize('noResults', "No results")).show(); - return; + return TPromise.as(void 0); } this._messageContainer.hide(); @@ -620,27 +638,28 @@ export class ReferenceWidget extends PeekViewWidget { this._disposeOnNewModel.push(this._tree.addListener2(Controller.Events.FOCUSED, (element) => { if (element instanceof OneReference) { this._revealReference(element); - this._onDidSelectReference.fire({ element, kind: 'show' }); + this._onDidSelectReference.fire({ element, kind: 'show', source: 'tree' }); } })); this._disposeOnNewModel.push(this._tree.addListener2(Controller.Events.SELECTED, (element: any) => { if (element instanceof OneReference) { this._revealReference(element); - this._onDidSelectReference.fire({ element, kind: 'goto' }); + this._onDidSelectReference.fire({ element, kind: 'goto', source: 'tree' }); } })); this._disposeOnNewModel.push(this._tree.addListener2(Controller.Events.OPEN_TO_SIDE, (element: any) => { if (element instanceof OneReference) { - this._onDidSelectReference.fire({ element, kind: 'side' }); + this._onDidSelectReference.fire({ element, kind: 'side', source: 'tree' }); } })); // listen on editor - this._disposeOnNewModel.push(this._preview.addListener2(editorCommon.EventType.MouseDown, (e: { event: MouseEvent; target: IMouseTarget; }) => { + this._disposeOnNewModel.push(this._preview.onMouseDown((e) => { if (e.event.detail === 2) { this._onDidSelectReference.fire({ element: this._getFocusedReference(), - kind: (e.event.ctrlKey || e.event.metaKey) ? 'side' : 'open' + kind: (e.event.ctrlKey || e.event.metaKey) ? 'side' : 'open', + source: 'editor' }); } })); @@ -672,14 +691,14 @@ export class ReferenceWidget extends PeekViewWidget { private _revealReference(reference: OneReference) { // Update widget header - if (reference.resource.scheme !== Schemas.inMemory) { + if (reference.uri.scheme !== Schemas.inMemory) { this.setTitle(reference.name, getPathLabel(reference.directory, this._contextService)); } else { this.setTitle(nls.localize('peekView.alternateTitle', "References")); } return TPromise.join([ - this._editorService.resolveEditorModel({ resource: reference.resource }), + this._editorService.resolveEditorModel({ resource: reference.uri }), this._tree.reveal(reference) ]).then(values => { if (!this._model) { diff --git a/src/vs/editor/contrib/referenceSearch/common/referenceSearch.ts b/src/vs/editor/contrib/referenceSearch/common/referenceSearch.ts index c43b7f9117a..9847a825266 100644 --- a/src/vs/editor/contrib/referenceSearch/common/referenceSearch.ts +++ b/src/vs/editor/contrib/referenceSearch/common/referenceSearch.ts @@ -7,17 +7,21 @@ import {onUnexpectedError} from 'vs/base/common/errors'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IModel, IPosition} from 'vs/editor/common/editorCommon'; +import {IReadOnlyModel} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; -import {IReference, ReferenceSearchRegistry} from 'vs/editor/common/modes'; +import {Location, ReferenceProviderRegistry} from 'vs/editor/common/modes'; +import {asWinJsPromise} from 'vs/base/common/async'; +import {Position} from 'vs/editor/common/core/position'; -export function findReferences(model: IModel, position: IPosition): TPromise { +export function provideReferences(model: IReadOnlyModel, position: Position): TPromise { // collect references from all providers - const promises = ReferenceSearchRegistry.ordered(model).map(provider => { - return provider.findReferences(model.getAssociatedResource(), position, true).then(result => { + const promises = ReferenceProviderRegistry.ordered(model).map(provider => { + return asWinJsPromise((token) => { + return provider.provideReferences(model, position, { includeDeclaration: true }, token); + }).then(result => { if (Array.isArray(result)) { - return result; + return result; } }, err => { onUnexpectedError(err); @@ -25,7 +29,7 @@ export function findReferences(model: IModel, position: IPosition): TPromise { - let result: IReference[] = []; + let result: Location[] = []; for (let ref of references) { if (ref) { result.push(...ref); @@ -35,4 +39,4 @@ export function findReferences(model: IModel, position: IPosition): TPromise { - if (!support.filter) { - return true; - } - if (isLineToken(lineContext, position.column - 1, support.filter)) { - return true; - } - - if (position.column > 1 && isLineToken(lineContext, position.column - 2, support.filter)) { - // in case we are in between two tokens - return true; - } - }); + return RenameProviderRegistry.has(this.editor.getModel()); } public run(event?: any): TPromise { diff --git a/src/vs/editor/contrib/rename/browser/renameInputField.ts b/src/vs/editor/contrib/rename/browser/renameInputField.ts index 79dbc76b870..61bd78d4f87 100644 --- a/src/vs/editor/contrib/rename/browser/renameInputField.ts +++ b/src/vs/editor/contrib/rename/browser/renameInputField.ts @@ -11,7 +11,7 @@ import {canceled} from 'vs/base/common/errors'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {TPromise} from 'vs/base/common/winjs.base'; import {Range} from 'vs/editor/common/core/range'; -import {EventType, IPosition, IRange} from 'vs/editor/common/editorCommon'; +import {IPosition, IRange} from 'vs/editor/common/editorCommon'; import {ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition} from 'vs/editor/browser/editorBrowser'; export default class RenameInputField implements IContentWidget, IDisposable { @@ -116,8 +116,8 @@ export default class RenameInputField implements IContentWidget, IDisposable { } }; - disposeOnDone.push(this._editor.addListener2(EventType.CursorSelectionChanged, onCursorChanged)); - disposeOnDone.push(this._editor.addListener2(EventType.EditorBlur, this._currentCancelInput)); + disposeOnDone.push(this._editor.onDidChangeCursorSelection(onCursorChanged)); + disposeOnDone.push(this._editor.onDidBlurEditor(this._currentCancelInput)); this._show(); diff --git a/src/vs/editor/contrib/rename/browser/renameModel.ts b/src/vs/editor/contrib/rename/browser/renameModel.ts index 3bef19ac3a3..de40f72705d 100644 --- a/src/vs/editor/contrib/rename/browser/renameModel.ts +++ b/src/vs/editor/contrib/rename/browser/renameModel.ts @@ -13,12 +13,12 @@ import {IEditorService} from 'vs/platform/editor/common/editor'; import {EditOperation} from 'vs/editor/common/core/editOperation'; import {Range} from 'vs/editor/common/core/range'; import {Selection} from 'vs/editor/common/core/selection'; -import {IEditorSelection, IIdentifiedSingleEditOperation, IModel, IRange} from 'vs/editor/common/editorCommon'; +import {IIdentifiedSingleEditOperation, IModel, IRange} from 'vs/editor/common/editorCommon'; import {IResourceEdit} from 'vs/editor/common/modes'; class EditTask { - private _initialSelections: IEditorSelection[]; - private _endCursorSelection: IEditorSelection; + private _initialSelections: Selection[]; + private _endCursorSelection: Selection; private _model: IModel; private _edits: IIdentifiedSingleEditOperation[]; @@ -48,7 +48,7 @@ class EditTask { this._model.pushEditOperations(this._initialSelections, this._edits, (edits) => this._getEndCursorSelections(edits)); } - protected _getInitialSelections(): IEditorSelection[] { + protected _getInitialSelections(): Selection[] { var firstRange = this._edits[0].range; var initialSelection = Selection.createSelection( firstRange.startLineNumber, @@ -59,7 +59,7 @@ class EditTask { return [initialSelection]; } - private _getEndCursorSelections(inverseEditOperations:IIdentifiedSingleEditOperation[]): IEditorSelection[] { + private _getEndCursorSelections(inverseEditOperations:IIdentifiedSingleEditOperation[]): Selection[] { var relevantEditIndex = 0; for (var i = 0; i < inverseEditOperations.length; i++) { var editRange = inverseEditOperations[i].range; @@ -82,7 +82,7 @@ class EditTask { return [this._endCursorSelection]; } - public getEndCursorSelection(): IEditorSelection { + public getEndCursorSelection(): Selection { return this._endCursorSelection; } @@ -93,14 +93,14 @@ class EditTask { class SourceModelEditTask extends EditTask { - private _knownInitialSelections:IEditorSelection[]; + private _knownInitialSelections:Selection[]; - constructor(model: IModel, initialSelections:IEditorSelection[]) { + constructor(model: IModel, initialSelections:Selection[]) { super(model); this._knownInitialSelections = initialSelections; } - protected _getInitialSelections(): IEditorSelection[] { + protected _getInitialSelections(): Selection[] { return this._knownInitialSelections; } } @@ -114,10 +114,10 @@ export default class RenameModel { private _rejectReasons: string[]; private _tasks: EditTask[]; private _sourceModel: URI; - private _sourceSelections: IEditorSelection[]; + private _sourceSelections: Selection[]; private _sourceModelTask: SourceModelEditTask; - constructor(editorService: IEditorService, sourceModel: URI, sourceSelections: IEditorSelection[], editsOrReject: string|IResourceEdit[]) { + constructor(editorService: IEditorService, sourceModel: URI, sourceSelections: Selection[], editsOrReject: string|IResourceEdit[]) { this._editorService = editorService; this._sourceModel = sourceModel; this._sourceSelections = sourceSelections; @@ -180,7 +180,7 @@ export default class RenameModel { var textEditorModel = model.textEditorModel, task: EditTask; - if (textEditorModel.getAssociatedResource().toString() === this._sourceModel.toString()) { + if (textEditorModel.uri.toString() === this._sourceModel.toString()) { this._sourceModelTask = new SourceModelEditTask(textEditorModel, this._sourceSelections); task = this._sourceModelTask; } else { @@ -197,9 +197,9 @@ export default class RenameModel { return TPromise.join(promises).then(_ => this); } - public apply(): IEditorSelection { + public apply(): Selection { this._tasks.forEach(task => task.apply()); - var r: IEditorSelection = null; + var r: Selection = null; if (this._sourceModelTask) { r = this._sourceModelTask.getEndCursorSelection(); } diff --git a/src/vs/editor/contrib/rename/common/rename.ts b/src/vs/editor/contrib/rename/common/rename.ts index eb767c314d3..deedc8f6317 100644 --- a/src/vs/editor/contrib/rename/common/rename.ts +++ b/src/vs/editor/contrib/rename/common/rename.ts @@ -6,24 +6,26 @@ 'use strict'; import {localize} from 'vs/nls'; -import {sequence} from 'vs/base/common/async'; +import {sequence, asWinJsPromise} from 'vs/base/common/async'; import {illegalArgument} from 'vs/base/common/errors'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IModel, IPosition} from 'vs/editor/common/editorCommon'; +import {IReadOnlyModel} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; -import {IRenameResult, RenameRegistry} from 'vs/editor/common/modes'; +import {WorkspaceEdit, RenameProviderRegistry} from 'vs/editor/common/modes'; +import {Position} from 'vs/editor/common/core/position'; -export function rename(model: IModel, position: IPosition, newName: string): TPromise { +export function rename(model: IReadOnlyModel, position: Position, newName: string): TPromise { - const supports = RenameRegistry.ordered(model); - const resource = model.getAssociatedResource(); + const supports = RenameProviderRegistry.ordered(model); const rejects: string[] = []; let hasResult = false; const factory = supports.map(support => { return () => { if (!hasResult) { - return support.rename(resource, position, newName).then(result => { + return asWinJsPromise((token) => { + return support.provideRenameEdits(model, position, newName, token); + }).then(result => { if (!result) { // ignore } else if (!result.rejectReason) { @@ -37,17 +39,15 @@ export function rename(model: IModel, position: IPosition, newName: string): TPr }; }); - return sequence(factory).then(values => { + return sequence(factory).then((values): WorkspaceEdit => { let result = values[0]; if (rejects.length > 0) { - return { - currentName: undefined, + return { edits: undefined, rejectReason: rejects.join('\n') }; } else if (!result) { - return { - currentName: undefined, + return { edits: undefined, rejectReason: localize('no result', "No result.") }; diff --git a/src/vs/editor/contrib/selectionClipboard/electron-browser/selectionClipboard.ts b/src/vs/editor/contrib/selectionClipboard/electron-browser/selectionClipboard.ts index 72fe4eaa3e9..9d1664fff9e 100644 --- a/src/vs/editor/contrib/selectionClipboard/electron-browser/selectionClipboard.ts +++ b/src/vs/editor/contrib/selectionClipboard/electron-browser/selectionClipboard.ts @@ -9,7 +9,7 @@ import {clipboard} from 'electron'; import * as platform from 'vs/base/common/platform'; import {ICodeEditor, IEditorMouseEvent} from 'vs/editor/browser/editorBrowser'; import {Disposable} from 'vs/base/common/lifecycle'; -import {EndOfLinePreference, EventType, IEditorContribution, ICursorSelectionChangedEvent, IConfigurationChangedEvent} from 'vs/editor/common/editorCommon'; +import {EndOfLinePreference, IEditorContribution, ICursorSelectionChangedEvent, IConfigurationChangedEvent} from 'vs/editor/common/editorCommon'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; import {RunOnceScheduler} from 'vs/base/common/async'; @@ -25,13 +25,13 @@ class SelectionClipboard extends Disposable implements IEditorContribution { if (platform.isLinux) { var isEnabled = editor.getConfiguration().contribInfo.selectionClipboard; - this._register(editor.addListener2(EventType.ConfigurationChanged, (e:IConfigurationChangedEvent) => { + this._register(editor.onDidChangeConfiguration((e:IConfigurationChangedEvent) => { if (e.contribInfo) { isEnabled = editor.getConfiguration().contribInfo.selectionClipboard; } })); - this._register(editor.addListener2(EventType.MouseDown, (e:IEditorMouseEvent) => { + this._register(editor.onMouseDown((e:IEditorMouseEvent) => { if (!isEnabled) { return; } @@ -81,7 +81,7 @@ class SelectionClipboard extends Disposable implements IEditorContribution { clipboard.writeText(textToCopy, 'selection'); }, 100)); - this._register(editor.addListener2(EventType.CursorSelectionChanged, (e:ICursorSelectionChangedEvent) => { + this._register(editor.onDidChangeCursorSelection((e:ICursorSelectionChangedEvent) => { if (!isEnabled) { return; } diff --git a/src/vs/editor/contrib/smartSelect/common/smartSelect.ts b/src/vs/editor/contrib/smartSelect/common/smartSelect.ts index 17013fdad00..c822f7bc024 100644 --- a/src/vs/editor/contrib/smartSelect/common/smartSelect.ts +++ b/src/vs/editor/contrib/smartSelect/common/smartSelect.ts @@ -12,7 +12,7 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat import {Range} from 'vs/editor/common/core/range'; import {EditorAction} from 'vs/editor/common/editorAction'; import {Behaviour} from 'vs/editor/common/editorActionEnablement'; -import {EventType, ICommonCodeEditor, ICursorPositionChangedEvent, IEditorActionDescriptorData, IEditorRange} from 'vs/editor/common/editorCommon'; +import {ICommonCodeEditor, ICursorPositionChangedEvent, IEditorActionDescriptorData} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; import {TokenSelectionSupport, ILogicalSelectionEntry} from './tokenSelectionSupport'; @@ -23,7 +23,7 @@ class State { public editor:ICommonCodeEditor; public next:State; public previous:State; - public selection:IEditorRange; + public selection:Range; constructor(editor:ICommonCodeEditor) { this.editor = editor; @@ -64,7 +64,7 @@ class SmartSelect extends EditorAction { var promise:TPromise = TPromise.as(null); if (!state) { - promise = this._tokenSelectionSupport.getRangesToPosition(model.getAssociatedResource(), selection.getStartPosition()).then((elements: ILogicalSelectionEntry[]) => { + promise = this._tokenSelectionSupport.getRangesToPosition(model.uri, selection.getStartPosition()).then((elements: ILogicalSelectionEntry[]) => { if (arrays.isFalsyOrEmpty(elements)) { return; @@ -98,12 +98,12 @@ class SmartSelect extends EditorAction { state = editorState; // listen to caret move and forget about state - var unhook: () => void = this.editor.addListener(EventType.CursorPositionChanged,(e: ICursorPositionChangedEvent) => { + var unhook = this.editor.onDidChangeCursorPosition((e: ICursorPositionChangedEvent) => { if (ignoreSelection) { return; } state = null; - unhook(); + unhook.dispose(); }); }); } diff --git a/src/vs/editor/contrib/snippet/common/snippet.ts b/src/vs/editor/contrib/snippet/common/snippet.ts index 1471788d328..7e36db5156d 100644 --- a/src/vs/editor/contrib/snippet/common/snippet.ts +++ b/src/vs/editor/contrib/snippet/common/snippet.ts @@ -6,7 +6,6 @@ 'use strict'; import * as collections from 'vs/base/common/collections'; -import {ListenerUnbind} from 'vs/base/common/eventEmitter'; import {KeyCode, KeyMod} from 'vs/base/common/keyCodes'; import * as strings from 'vs/base/common/strings'; import {IKeybindingContextKey, IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; @@ -15,6 +14,7 @@ import {Range} from 'vs/editor/common/core/range'; import {Selection} from 'vs/editor/common/core/selection'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; interface IParsedLinePlaceHolderInfo { id: string; @@ -384,7 +384,7 @@ class InsertSnippetController { private model: editorCommon.IModel; private finishPlaceHolderIndex:number; - private listenersToRemove:ListenerUnbind[]; + private listenersToRemove:IDisposable[]; private trackedPlaceHolders:ITrackedPlaceHolder[]; private placeHolderDecorations: string[]; private currentPlaceHolderIndex:number; @@ -460,29 +460,29 @@ class InsertSnippetController { }); this.listenersToRemove = []; - this.listenersToRemove.push(this.editor.addListener(editorCommon.EventType.ModelContentChanged, (e:editorCommon.IModelContentChangedEvent) => { + this.listenersToRemove.push(this.editor.onDidChangeModelRawContent((e:editorCommon.IModelContentChangedEvent) => { if (this.isFinished) { return; } - if (e.changeType === editorCommon.EventType.ModelContentChangedFlush) { + if (e.changeType === editorCommon.EventType.ModelRawContentChangedFlush) { // a model.setValue() was called this.stopAll(); - } else if (e.changeType === editorCommon.EventType.ModelContentChangedLineChanged) { + } else if (e.changeType === editorCommon.EventType.ModelRawContentChangedLineChanged) { var changedLine = (e).lineNumber; var highlightRange = this.model.getDecorationRange(this.highlightDecorationId); if (changedLine < highlightRange.startLineNumber || changedLine > highlightRange.endLineNumber) { this.stopAll(); } - } else if (e.changeType === editorCommon.EventType.ModelContentChangedLinesInserted) { + } else if (e.changeType === editorCommon.EventType.ModelRawContentChangedLinesInserted) { var insertLine = (e).fromLineNumber; var highlightRange = this.model.getDecorationRange(this.highlightDecorationId); if (insertLine < highlightRange.startLineNumber || insertLine > highlightRange.endLineNumber) { this.stopAll(); } - } else if (e.changeType === editorCommon.EventType.ModelContentChangedLinesDeleted) { + } else if (e.changeType === editorCommon.EventType.ModelRawContentChangedLinesDeleted) { var deleteLine1 = (e).fromLineNumber; var deleteLine2 = (e).toLineNumber; var highlightRange = this.model.getDecorationRange(this.highlightDecorationId); @@ -502,7 +502,7 @@ class InsertSnippetController { } })); - this.listenersToRemove.push(this.editor.addListener(editorCommon.EventType.CursorPositionChanged, (e:editorCommon.ICursorPositionChangedEvent) => { + this.listenersToRemove.push(this.editor.onDidChangeCursorPosition((e:editorCommon.ICursorPositionChangedEvent) => { if (this.isFinished) { return; } @@ -513,19 +513,19 @@ class InsertSnippetController { } })); - this.listenersToRemove.push(this.editor.addListener(editorCommon.EventType.ModelChanged, () => { + this.listenersToRemove.push(this.editor.onDidChangeModel(() => { this.stopAll(); })); var blurTimeout = -1; - this.listenersToRemove.push(this.editor.addListener(editorCommon.EventType.EditorBlur, () => { + this.listenersToRemove.push(this.editor.onDidBlurEditor(() => { // Blur if within 100ms we do not focus back blurTimeout = setTimeout(() => { this.stopAll(); }, 100); })); - this.listenersToRemove.push(this.editor.addListener(editorCommon.EventType.EditorFocus, () => { + this.listenersToRemove.push(this.editor.onDidFocusEditor(() => { // Cancel the blur timeout (if any) if (blurTimeout !== -1) { clearTimeout(blurTimeout); @@ -533,13 +533,13 @@ class InsertSnippetController { } })); - this.listenersToRemove.push(this.model.addListener(editorCommon.EventType.ModelDecorationsChanged, (e: editorCommon.IModelDecorationsChangedEvent) => { + this.listenersToRemove.push(this.model.onDidChangeDecorations((e) => { if (this.isFinished) { return; } var modelEditableRange = this.model.getEditableRange(), - previousRange: editorCommon.IEditorRange = null, + previousRange: Range = null, allCollapsed = true, allEqualToEditableRange = true; @@ -676,10 +676,7 @@ class InsertSnippetController { this.isFinished = true; - this.listenersToRemove.forEach((element) => { - element(); - }); - this.listenersToRemove = []; + this.listenersToRemove = dispose(this.listenersToRemove); for (var i = 0; i < this.trackedPlaceHolders.length; i++) { var ranges = this.trackedPlaceHolders[i].ranges; @@ -761,8 +758,8 @@ class SnippetController implements ISnippetController { } } - private static _getTypeRangeForSelection(model:editorCommon.IModel, selection:editorCommon.IEditorSelection, overwriteBefore:number, overwriteAfter:number): editorCommon.IEditorRange { - var typeRange:editorCommon.IEditorRange; + private static _getTypeRangeForSelection(model:editorCommon.IModel, selection:Selection, overwriteBefore:number, overwriteAfter:number): Range { + var typeRange:Range; if (overwriteBefore || overwriteAfter) { typeRange = model.validateRange(Range.plusRange(selection, { startLineNumber: selection.positionLineNumber, @@ -776,11 +773,11 @@ class SnippetController implements ISnippetController { return typeRange; } - private static _getAdaptedSnippet(model:editorCommon.IModel, snippet:CodeSnippet, typeRange:editorCommon.IEditorRange): ICodeSnippet { + private static _getAdaptedSnippet(model:editorCommon.IModel, snippet:CodeSnippet, typeRange:Range): ICodeSnippet { return snippet.bind(model.getLineContent(typeRange.startLineNumber), typeRange.startLineNumber - 1, typeRange.startColumn - 1, model); } - private static _addCommandForSnippet(model:editorCommon.ITextModel, adaptedSnippet:ICodeSnippet, typeRange:editorCommon.IEditorRange, out:editorCommon.IIdentifiedSingleEditOperation[]): void { + private static _addCommandForSnippet(model:editorCommon.ITextModel, adaptedSnippet:ICodeSnippet, typeRange:Range, out:editorCommon.IIdentifiedSingleEditOperation[]): void { let insertText = adaptedSnippet.lines.join('\n'); let currentText = model.getValueInRange(typeRange, editorCommon.EndOfLinePreference.LF); if (insertText !== currentText) { @@ -829,7 +826,7 @@ class SnippetController implements ISnippetController { } } - private static _prepareSnippet(editor:editorCommon.ICommonCodeEditor, selection:editorCommon.IEditorSelection, snippet:CodeSnippet, overwriteBefore:number, overwriteAfter:number): { typeRange: editorCommon.IEditorRange; adaptedSnippet: ICodeSnippet; } { + private static _prepareSnippet(editor:editorCommon.ICommonCodeEditor, selection:Selection, snippet:CodeSnippet, overwriteBefore:number, overwriteAfter:number): { typeRange: Range; adaptedSnippet: ICodeSnippet; } { var model = editor.getModel(); var typeRange = SnippetController._getTypeRangeForSelection(model, selection, overwriteBefore, overwriteAfter); diff --git a/src/vs/editor/contrib/suggest/browser/completionModel.ts b/src/vs/editor/contrib/suggest/browser/completionModel.ts index 2c6f270571f..9382d9256a6 100644 --- a/src/vs/editor/contrib/suggest/browser/completionModel.ts +++ b/src/vs/editor/contrib/suggest/browser/completionModel.ts @@ -7,12 +7,13 @@ import {isFalsyOrEmpty} from 'vs/base/common/arrays'; import {assign} from 'vs/base/common/objects'; -import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IPosition} from 'vs/editor/common/editorCommon'; +import {IReadOnlyModel} from 'vs/editor/common/editorCommon'; import {IFilter, IMatch, fuzzyContiguousFilter} from 'vs/base/common/filters'; import {ISuggestResult, ISuggestSupport, ISuggestion} from 'vs/editor/common/modes'; import {ISuggestResult2} from '../common/suggest'; +import {asWinJsPromise} from 'vs/base/common/async'; +import {Position} from 'vs/editor/common/core/position'; export class CompletionItem { @@ -30,12 +31,14 @@ export class CompletionItem { this.filter = container.support && container.support.filter || fuzzyContiguousFilter; } - resolveDetails(resource: URI, position: IPosition): TPromise { - if (!this._support || typeof this._support.getSuggestionDetails !== 'function') { + resolveDetails(model:IReadOnlyModel, position:Position): TPromise { + if (!this._support || typeof this._support.resolveCompletionItem !== 'function') { return TPromise.as(this.suggestion); } - return this._support.getSuggestionDetails(resource, position, this.suggestion); + return asWinJsPromise((token) => { + return this._support.resolveCompletionItem(model, position, this.suggestion, token); + }); } updateDetails(value: ISuggestion): void { diff --git a/src/vs/editor/contrib/suggest/browser/suggest.ts b/src/vs/editor/contrib/suggest/browser/suggest.ts index d97e30dd0eb..d54ac1d59ac 100644 --- a/src/vs/editor/contrib/suggest/browser/suggest.ts +++ b/src/vs/editor/contrib/suggest/browser/suggest.ts @@ -7,12 +7,12 @@ import * as nls from 'vs/nls'; import {onUnexpectedError} from 'vs/base/common/errors'; import {KeyCode, KeyMod} from 'vs/base/common/keyCodes'; -import {IDisposable, cAll, dispose} from 'vs/base/common/lifecycle'; +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {TPromise} from 'vs/base/common/winjs.base'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IKeybindingContextKey, IKeybindingService, KbExpr} from 'vs/platform/keybinding/common/keybindingService'; import {EditorAction} from 'vs/editor/common/editorAction'; -import {EventType, ICommonCodeEditor, IEditorActionDescriptorData, IEditorContribution, IModeSupportChangedEvent} from 'vs/editor/common/editorCommon'; +import {ICommonCodeEditor, IEditorActionDescriptorData, IEditorContribution} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; import {ISuggestSupport, SuggestRegistry} from 'vs/editor/common/modes'; import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; @@ -33,7 +33,7 @@ export class SuggestController implements IEditorContribution { private model: SuggestModel; private widget: SuggestWidget; - private triggerCharacterListeners: Function[]; + private triggerCharacterListeners: IDisposable[]; private suggestWidgetVisible: IKeybindingContextKey; private toDispose: IDisposable[]; @@ -50,14 +50,9 @@ export class SuggestController implements IEditorContribution { this.toDispose = []; this.toDispose.push(this.widget.onDidVisibilityChange(visible => visible ? this.suggestWidgetVisible.set(true) : this.suggestWidgetVisible.reset())); - this.toDispose.push(editor.addListener2(EventType.ConfigurationChanged, () => this.update())); - this.toDispose.push(editor.addListener2(EventType.ModelChanged, () => this.update())); - this.toDispose.push(editor.addListener2(EventType.ModelModeChanged, () => this.update())); - this.toDispose.push(editor.addListener2(EventType.ModelModeSupportChanged, (e: IModeSupportChangedEvent) => { - if (e.suggestSupport) { - this.update(); - } - })); + this.toDispose.push(editor.onDidChangeConfiguration(() => this.update())); + this.toDispose.push(editor.onDidChangeModel(() => this.update())); + this.toDispose.push(editor.onDidChangeModelMode(() => this.update())); this.toDispose.push(SuggestRegistry.onDidChange(this.update, this)); this.toDispose.push(this.model.onDidAccept(e => getSnippetController(this.editor).run(e.snippet, e.overwriteBefore, e.overwriteAfter))); @@ -71,7 +66,7 @@ export class SuggestController implements IEditorContribution { public dispose(): void { this.toDispose = dispose(this.toDispose); - this.triggerCharacterListeners = cAll(this.triggerCharacterListeners); + this.triggerCharacterListeners = dispose(this.triggerCharacterListeners); if (this.widget) { this.widget.dispose(); @@ -85,7 +80,7 @@ export class SuggestController implements IEditorContribution { private update(): void { - this.triggerCharacterListeners = cAll(this.triggerCharacterListeners); + this.triggerCharacterListeners = dispose(this.triggerCharacterListeners); if (this.editor.getConfiguration().readOnly || !this.editor.getModel() @@ -106,7 +101,7 @@ export class SuggestController implements IEditorContribution { let groupTriggerCharacters: { [ch: string]: ISuggestSupport[] } = Object.create(null); group.forEach(support => { - let localTriggerCharacters = support.getTriggerCharacters(); + let localTriggerCharacters = support.triggerCharacters; if (localTriggerCharacters) { for (let ch of localTriggerCharacters) { let array = groupTriggerCharacters[ch]; @@ -134,13 +129,6 @@ export class SuggestController implements IEditorContribution { } private triggerCharacterHandler(character: string, groups: ISuggestSupport[][]): void { - const position = this.editor.getPosition(); - const lineContext = this.editor.getModel().getLineContext(position.lineNumber); - - groups = groups.map(supports => { - return supports.filter(support => support.shouldAutotriggerSuggest(lineContext, position.column - 1, character)); - }); - if (groups.length > 0) { this.triggerSuggest(character, groups).done(null, onUnexpectedError); } diff --git a/src/vs/editor/contrib/suggest/browser/suggestModel.ts b/src/vs/editor/contrib/suggest/browser/suggestModel.ts index c99c810fa4c..91395042691 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestModel.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestModel.ts @@ -9,11 +9,12 @@ import Event, { Emitter } from 'vs/base/common/event'; import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {startsWith} from 'vs/base/common/strings'; import {TPromise} from 'vs/base/common/winjs.base'; -import {EventType, ICommonCodeEditor, ICursorSelectionChangedEvent, IPosition, CursorChangeReason} from 'vs/editor/common/editorCommon'; +import {ICommonCodeEditor, ICursorSelectionChangedEvent, CursorChangeReason} from 'vs/editor/common/editorCommon'; import {ISuggestSupport, ISuggestion, SuggestRegistry} from 'vs/editor/common/modes'; import {CodeSnippet} from 'vs/editor/contrib/snippet/common/snippet'; -import {ISuggestResult2, suggest} from '../common/suggest'; +import {ISuggestResult2, provideCompletionItems} from '../common/suggest'; import {CompletionModel} from './completionModel'; +import {Position} from 'vs/editor/common/core/position'; export interface ICancelEvent { retrigger: boolean; @@ -80,10 +81,8 @@ class Context { } } - const lineContext = model.getLineContext(position.lineNumber); - const character = model.getLineContent(position.lineNumber).charAt(position.column - 1); const supports = SuggestRegistry.all(model); - this.isAutoTriggerEnabled = supports.some(s => s.shouldAutotriggerSuggest(lineContext, position.column - 1, character)); + this.isAutoTriggerEnabled = (supports.length > 0); } public shouldAutoTrigger(): boolean { @@ -197,9 +196,9 @@ export class SuggestModel implements IDisposable { this.context = null; this.toDispose = []; - this.toDispose.push(this.editor.addListener2(EventType.ConfigurationChanged, () => this.onEditorConfigurationChange())); - this.toDispose.push(this.editor.addListener2(EventType.CursorSelectionChanged, e => this.onCursorChange(e))); - this.toDispose.push(this.editor.addListener2(EventType.ModelChanged, () => this.cancel())); + this.toDispose.push(this.editor.onDidChangeConfiguration(() => this.onEditorConfigurationChange())); + this.toDispose.push(this.editor.onDidChangeCursorSelection(e => this.onCursorChange(e))); + this.toDispose.push(this.editor.onDidChangeModel(() => this.cancel())); this.toDispose.push(SuggestRegistry.onDidChange(this.onSuggestRegistryChange, this)); this.onEditorConfigurationChange(); } @@ -230,15 +229,12 @@ export class SuggestModel implements IDisposable { return actuallyCanceled; } - public getRequestPosition(): IPosition { + public getRequestPosition(): Position { if (!this.context) { return null; } - return { - lineNumber: this.context.lineNumber, - column: this.context.column - }; + return new Position(this.context.lineNumber, this.context.column); } private isAutoSuggest(): boolean { @@ -325,7 +321,7 @@ export class SuggestModel implements IDisposable { const position = this.editor.getPosition(); - this.requestPromise = suggest(model, position, triggerCharacter, groups).then(all => { + this.requestPromise = provideCompletionItems(model, position, groups).then(all => { this.requestPromise = null; if (this.state === State.Idle) { diff --git a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts index 31cc70d09e5..9038c93c016 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts @@ -21,7 +21,7 @@ import {DomScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableEleme import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IKeybindingContextKey, IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; -import {EventType, IConfigurationChangedEvent} from 'vs/editor/common/editorCommon'; +import {IConfigurationChangedEvent} from 'vs/editor/common/editorCommon'; import {ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition} from 'vs/editor/browser/editorBrowser'; import {CONTEXT_SUGGESTION_SUPPORTS_ACCEPT_ON_KEY} from '../common/suggest'; import {CompletionItem, CompletionModel} from './completionModel'; @@ -81,7 +81,7 @@ class Renderer implements IRenderer { configureFont(); - data.disposables.push(this.editor.addListener2(EventType.ConfigurationChanged, (e: IConfigurationChangedEvent) => { + data.disposables.push(this.editor.onDidChangeConfiguration((e: IConfigurationChangedEvent) => { if (e.fontInfo) { configureFont(); } @@ -231,7 +231,7 @@ class SuggestionDetails { this.configureFont(); - this.disposables.push(this.editor.addListener2(EventType.ConfigurationChanged, (e: IConfigurationChangedEvent) => { + this.disposables.push(this.editor.onDidChangeConfiguration((e: IConfigurationChangedEvent) => { if (e.fontInfo) { this.configureFont(); } @@ -369,10 +369,10 @@ export class SuggestWidget implements IContentWidget, IDisposable { this.list = new List(this.listElement, this.delegate, [renderer]); this.toDispose = [ - editor.addListener2(EventType.EditorTextBlur, () => this.onEditorBlur()), + editor.onDidBlurEditorText(() => this.onEditorBlur()), this.list.onSelectionChange(e => this.onListSelection(e)), this.list.onFocusChange(e => this.onListFocus(e)), - this.editor.addListener2(EventType.CursorSelectionChanged, () => this.onCursorSelectionChanged()), + this.editor.onDidChangeCursorSelection(() => this.onCursorSelectionChanged()), this.model.onDidTrigger(e => this.onDidTrigger(e)), this.model.onDidSuggest(e => this.onDidSuggest(e)), this.model.onDidCancel(e => this.onDidCancel(e)) @@ -484,14 +484,12 @@ export class SuggestWidget implements IContentWidget, IDisposable { this.suggestionSupportsAutoAccept.set(!item.suggestion.noAutoAccept); this.focusedItem = item; - this.list.setFocus(index); this.updateWidgetHeight(); this.list.reveal(index); - const resource = this.editor.getModel().getAssociatedResource(); const position = this.model.getRequestPosition() || this.editor.getPosition(); - this.currentSuggestionDetails = item.resolveDetails(resource, position) + this.currentSuggestionDetails = item.resolveDetails(this.editor.getModel(), position) .then(details => { item.updateDetails(details); this.list.setFocus(index); diff --git a/src/vs/editor/contrib/suggest/common/suggest.ts b/src/vs/editor/contrib/suggest/common/suggest.ts index 40fe2967317..c82e42fa920 100644 --- a/src/vs/editor/contrib/suggest/common/suggest.ts +++ b/src/vs/editor/contrib/suggest/common/suggest.ts @@ -4,14 +4,15 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {sequence} from 'vs/base/common/async'; +import {sequence, asWinJsPromise} from 'vs/base/common/async'; import {isFalsyOrEmpty} from 'vs/base/common/arrays'; -import {illegalArgument, onUnexpectedError} from 'vs/base/common/errors'; +import {onUnexpectedError} from 'vs/base/common/errors'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IModel, IPosition} from 'vs/editor/common/editorCommon'; +import {IReadOnlyModel} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; import {ISuggestResult, ISuggestSupport, SuggestRegistry} from 'vs/editor/common/modes'; import {SnippetsRegistry} from 'vs/editor/common/modes/supports'; +import {Position} from 'vs/editor/common/core/position'; export var CONTEXT_SUGGEST_WIDGET_VISIBLE = 'suggestWidgetVisible'; export var CONTEXT_SUGGESTION_SUPPORTS_ACCEPT_ON_KEY = 'suggestionSupportsAcceptOnKey'; @@ -21,13 +22,12 @@ export interface ISuggestResult2 extends ISuggestResult { support?: ISuggestSupport; } -export function suggest(model: IModel, position: IPosition, triggerCharacter: string, groups?: ISuggestSupport[][]): TPromise { +export function provideCompletionItems(model: IReadOnlyModel, position: Position, groups?: ISuggestSupport[][]): TPromise { if (!groups) { groups = SuggestRegistry.orderedGroups(model); } - const resource = model.getAssociatedResource(); const result: ISuggestResult2[] = []; const factory = groups.map((supports, index) => { @@ -40,7 +40,9 @@ export function suggest(model: IModel, position: IPosition, triggerCharacter: st // for each support in the group ask for suggestions return TPromise.join(supports.map(support => { - return support.suggest(resource, position, triggerCharacter).then(values => { + return asWinJsPromise((token) => { + return support.provideCompletionItems(model, position, token); + }).then(values => { if (!values) { return; @@ -74,11 +76,5 @@ export function suggest(model: IModel, position: IPosition, triggerCharacter: st } CommonEditorRegistry.registerDefaultLanguageCommand('_executeCompletionItemProvider', (model, position, args) => { - - let triggerCharacter = args['triggerCharacter']; - if (typeof triggerCharacter !== 'undefined' && typeof triggerCharacter !== 'string') { - throw illegalArgument('triggerCharacter'); - } - - return suggest(model, position, triggerCharacter); + return provideCompletionItems(model, position); }); diff --git a/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts b/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts index 2144841e904..6112b03274b 100644 --- a/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts +++ b/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts @@ -4,18 +4,19 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {sequence} from 'vs/base/common/async'; +import {sequence, asWinJsPromise} from 'vs/base/common/async'; import {onUnexpectedError} from 'vs/base/common/errors'; import {TPromise} from 'vs/base/common/winjs.base'; import {Range} from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; -import {IOccurence, OccurrencesRegistry} from 'vs/editor/common/modes'; +import {DocumentHighlight, DocumentHighlightKind, DocumentHighlightProviderRegistry} from 'vs/editor/common/modes'; +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; +import {Position} from 'vs/editor/common/core/position'; -export function getOccurrencesAtPosition(model: editorCommon.IModel, position: editorCommon.IPosition):TPromise { +export function getOccurrencesAtPosition(model: editorCommon.IReadOnlyModel, position: Position):TPromise { - const resource = model.getAssociatedResource(); - const orderedByScore = OccurrencesRegistry.ordered(model); + const orderedByScore = DocumentHighlightProviderRegistry.ordered(model); let foundResult = false; // in order of score ask the occurrences provider @@ -24,7 +25,9 @@ export function getOccurrencesAtPosition(model: editorCommon.IModel, position: e return sequence(orderedByScore.map(provider => { return () => { if (!foundResult) { - return provider.findOccurrences(resource, position).then(data => { + return asWinJsPromise((token) => { + return provider.provideDocumentHighlights(model, position, token); + }).then(data => { if (Array.isArray(data) && data.length > 0) { foundResult = true; return data; @@ -45,14 +48,14 @@ class WordHighlighter { private editor: editorCommon.ICommonCodeEditor; private model: editorCommon.IModel; - private _lastWordRange: editorCommon.IEditorRange; + private _lastWordRange: Range; private _decorationIds: string[]; - private toUnhook: Function[]; + private toUnhook: IDisposable[]; private workerRequestTokenId:number = 0; - private workerRequest:TPromise = null; + private workerRequest:TPromise = null; private workerRequestCompleted:boolean = false; - private workerRequestValue:IOccurence[] = []; + private workerRequestValue:DocumentHighlight[] = []; private lastCursorPositionChangeTime:number = 0; private renderDecorationsTimer:number = -1; @@ -61,14 +64,14 @@ class WordHighlighter { this.editor = editor; this.model = this.editor.getModel(); this.toUnhook = []; - this.toUnhook.push(editor.addListener(editorCommon.EventType.CursorPositionChanged, (e:editorCommon.ICursorPositionChangedEvent) => { + this.toUnhook.push(editor.onDidChangeCursorPosition((e:editorCommon.ICursorPositionChangedEvent) => { this._onPositionChanged(e); })); - this.toUnhook.push(editor.addListener(editorCommon.EventType.ModelChanged, (e) => { + this.toUnhook.push(editor.onDidChangeModel((e) => { this._stopAll(); this.model = this.editor.getModel(); })); - this.toUnhook.push(editor.addListener('change', (e) => { + this.toUnhook.push(editor.onDidChangeModelContent((e) => { this._stopAll(); })); @@ -123,7 +126,7 @@ class WordHighlighter { } // no providers for this model - if(!OccurrencesRegistry.has(this.model)) { + if(!DocumentHighlightProviderRegistry.has(this.model)) { this._stopAll(); return; } @@ -234,16 +237,17 @@ class WordHighlighter { var decorations:editorCommon.IModelDeltaDecoration[] = []; for(var i = 0, len = this.workerRequestValue.length; i < len; i++) { var info = this.workerRequestValue[i]; - var className = 'wordHighlight'; var color = '#A0A0A0'; - if (info.kind === 'write') { + let className:string; + if (info.kind === DocumentHighlightKind.Write) { className = 'wordHighlightStrong'; - } else if (info.kind === 'text') { + } else if (info.kind === DocumentHighlightKind.Text) { className = 'selectionHighlight'; - // Keep the same color for now - //color = 'rgba(249, 206, 130, 0.7)'; + } else { + className = 'wordHighlight'; } + decorations.push({ range: info.range, options: { @@ -263,9 +267,7 @@ class WordHighlighter { public destroy(): void { this._stopAll(); - while(this.toUnhook.length > 0) { - this.toUnhook.pop()(); - } + this.toUnhook = dispose(this.toUnhook); } } diff --git a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts index 458016f2417..6e0d87a59a4 100644 --- a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts +++ b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts @@ -10,7 +10,7 @@ import {Disposables} from 'vs/base/common/lifecycle'; import * as objects from 'vs/base/common/objects'; import * as dom from 'vs/base/browser/dom'; import {Sash, Orientation, IHorizontalSashLayoutProvider, ISashEvent} from 'vs/base/browser/ui/sash/sash'; -import {EventType, EditorLayoutInfo, IPosition, IRange} from 'vs/editor/common/editorCommon'; +import {EditorLayoutInfo, IPosition, IRange} from 'vs/editor/common/editorCommon'; import {Range} from 'vs/editor/common/core/range'; import {Position} from 'vs/editor/common/core/position'; import {ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, IViewZone, IViewZoneChangeAccessor} from 'vs/editor/browser/editorBrowser'; @@ -111,7 +111,7 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { this.domNode.setAttribute('role', 'presentation'); } - this._disposables.add(this.editor.addListener2(EventType.EditorLayout, (info: EditorLayoutInfo) => { + this._disposables.add(this.editor.onDidLayoutChange((info: EditorLayoutInfo) => { var width = this._getWidth(info); this.domNode.style.width = width + 'px'; this._onWidth(width); diff --git a/src/vs/editor/node/textMate/TMSnippets.ts b/src/vs/editor/node/textMate/TMSnippets.ts index d7ddd45d9d9..bef5e357c19 100644 --- a/src/vs/editor/node/textMate/TMSnippets.ts +++ b/src/vs/editor/node/textMate/TMSnippets.ts @@ -5,7 +5,7 @@ 'use strict'; import * as nls from 'vs/nls'; -import {parse} from 'vs/base/common/json'; +import {parse, ParseError} from 'vs/base/common/json'; import * as paths from 'vs/base/common/paths'; import {TPromise} from 'vs/base/common/winjs.base'; import {readFile} from 'vs/base/node/pfs'; @@ -23,7 +23,7 @@ export interface ITMSnippetsExtensionPoint { export function snippetUpdated(modeId: string, filePath: string): TPromise { return readFile(filePath).then((fileContents) => { - var errors: string[] = []; + var errors: ParseError[] = []; var snippetsObj = parse(fileContents.toString(), errors); var adaptedSnippets = TMSnippetsAdaptor.adapt(snippetsObj); SnippetsRegistry.registerSnippets(modeId, filePath, adaptedSnippets); @@ -98,7 +98,7 @@ export class MainProcessTextMateSnippet { public registerDefinition(modeId: string, filePath: string): void { readFile(filePath).then((fileContents) => { - var errors: string[] = []; + var errors: ParseError[] = []; var snippetsObj = parse(fileContents.toString(), errors); var adaptedSnippets = TMSnippetsAdaptor.adapt(snippetsObj); SnippetsRegistry.registerDefaultSnippets(modeId, adaptedSnippets); diff --git a/src/vs/editor/node/textMate/TMSyntax.ts b/src/vs/editor/node/textMate/TMSyntax.ts index 388f1ffb289..605aa2c7c6a 100644 --- a/src/vs/editor/node/textMate/TMSyntax.ts +++ b/src/vs/editor/node/textMate/TMSyntax.ts @@ -19,12 +19,13 @@ export interface ITMSyntaxExtensionPoint { language: string; scopeName: string; path: string; + injectTo: string[]; } let grammarsExtPoint = ExtensionsRegistry.registerExtensionPoint('grammars', { description: nls.localize('vscode.extension.contributes.grammars', 'Contributes textmate tokenizers.'), type: 'array', - defaultSnippets: [ { body: [{ id: '', extensions: [] }] }], + defaultSnippets: [ { body: [{ language: '{{id}}', scopeName: 'source.{{id}}', path: './syntaxes/{{id}}.tmLanguage.'}] }], items: { type: 'object', defaultSnippets: [ { body: { language: '{{id}}', scopeName: 'source.{{id}}', path: './syntaxes/{{id}}.tmLanguage.'} }], @@ -40,8 +41,16 @@ let grammarsExtPoint = ExtensionsRegistry.registerExtensionPoint { return this._scopeNameToFilePath[scopeName]; + }, + getInjections: (scopeName:string) => { + return this._injections[scopeName]; } }); this._scopeNameToFilePath = {}; + this._injections = {}; grammarsExtPoint.setHandler((extensions) => { for (let i = 0; i < extensions.length; i++) { @@ -84,6 +98,10 @@ export class MainProcessTextMateSyntax { collector.error(nls.localize('invalid.path.0', "Expected string in `contributes.{0}.path`. Provided value: {1}", grammarsExtPoint.name, String(syntax.path))); return; } + if (syntax.injectTo && (!Array.isArray(syntax.injectTo) || syntax.injectTo.some(scope => typeof scope !== 'string'))) { + collector.error(nls.localize('invalid.injectTo', "Invalid value in `contributes.{0}.injectTo`. Must be an array of language scope names. Provided value: {1}", grammarsExtPoint.name, JSON.stringify(syntax.injectTo))); + return; + } let normalizedAbsolutePath = paths.normalize(paths.join(extensionFolderPath, syntax.path)); if (normalizedAbsolutePath.indexOf(extensionFolderPath) !== 0) { diff --git a/src/vs/editor/node/textMate/vscode-textmate.d.ts b/src/vs/editor/node/textMate/vscode-textmate.d.ts index 7fa8bf6e728..9a61ada1bdd 100644 --- a/src/vs/editor/node/textMate/vscode-textmate.d.ts +++ b/src/vs/editor/node/textMate/vscode-textmate.d.ts @@ -10,6 +10,7 @@ declare module "vscode-textmate" { */ export interface IGrammarLocator { getFilePath(scopeName:string): string; + getInjections(scopeName:string): string[]; } /** diff --git a/src/vs/editor/test/common/commands/commandTestUtils.ts b/src/vs/editor/test/common/commands/commandTestUtils.ts index 5ec20a94846..eb165e5fe69 100644 --- a/src/vs/editor/test/common/commands/commandTestUtils.ts +++ b/src/vs/editor/test/common/commands/commandTestUtils.ts @@ -47,7 +47,7 @@ export function testCommand( export function getEditOperation(model: editorCommon.IModel, command: editorCommon.ICommand): editorCommon.IIdentifiedSingleEditOperation[] { var operations: editorCommon.IIdentifiedSingleEditOperation[] = []; var editOperationBuilder: editorCommon.IEditOperationBuilder = { - addEditOperation: (range: editorCommon.IEditorRange, text: string) => { + addEditOperation: (range: Range, text: string) => { operations.push({ identifier: null, range: range, @@ -56,7 +56,7 @@ export function getEditOperation(model: editorCommon.IModel, command: editorComm }); }, - trackSelection: (selection: editorCommon.IEditorSelection) => { + trackSelection: (selection: Selection) => { return null; } }; diff --git a/src/vs/editor/test/common/controller/cursor.test.ts b/src/vs/editor/test/common/controller/cursor.test.ts index 0221c68b9ea..619e7354fe6 100644 --- a/src/vs/editor/test/common/controller/cursor.test.ts +++ b/src/vs/editor/test/common/controller/cursor.test.ts @@ -722,10 +722,10 @@ suite('Editor Controller - Cursor', () => { // --------- eventing test('no move doesn\'t trigger event', () => { - thisCursor.addListener(EventType.CursorPositionChanged, (e) => { + thisCursor.addListener2(EventType.CursorPositionChanged, (e) => { assert.ok(false, 'was not expecting event'); }); - thisCursor.addListener(EventType.CursorSelectionChanged, (e) => { + thisCursor.addListener2(EventType.CursorSelectionChanged, (e) => { assert.ok(false, 'was not expecting event'); }); moveTo(thisCursor, 1, 1); @@ -733,11 +733,11 @@ suite('Editor Controller - Cursor', () => { test('move eventing', () => { let events = 0; - thisCursor.addListener(EventType.CursorPositionChanged, (e) => { + thisCursor.addListener2(EventType.CursorPositionChanged, (e) => { events++; positionEqual(e.position, 1, 2); }); - thisCursor.addListener(EventType.CursorSelectionChanged, (e) => { + thisCursor.addListener2(EventType.CursorSelectionChanged, (e) => { events++; selectionEqual(e.selection, 1, 2, 1, 2); }); @@ -747,11 +747,11 @@ suite('Editor Controller - Cursor', () => { test('move in selection mode eventing', () => { let events = 0; - thisCursor.addListener(EventType.CursorPositionChanged, (e) => { + thisCursor.addListener2(EventType.CursorPositionChanged, (e) => { events++; positionEqual(e.position, 1, 2); }); - thisCursor.addListener(EventType.CursorSelectionChanged, (e) => { + thisCursor.addListener2(EventType.CursorSelectionChanged, (e) => { events++; selectionEqual(e.selection, 1, 2, 1, 1); }); @@ -1420,7 +1420,7 @@ suite('Editor Controller - Regression tests', () => { moveTo(cursor, 3, 4, true); let isFirst = true; - model.addListener2(EventType.ModelContentChanged, (e) => { + model.onDidChangeContent(() => { if (isFirst) { isFirst = false; cursorCommand(cursor, H.Type, { text: '\t' }, 'keyboard'); @@ -1553,6 +1553,42 @@ suite('Editor Controller - Regression tests', () => { }); }); + test('issue #3882: deleteWordRight', () => { + usingCursor({ + text: [ + 'public void Add( int x,', + ' int y )' + ], + }, (model, cursor) => { + moveTo(cursor, 1, 24, false); + deleteWordRight(cursor); assert.equal(model.getLineContent(1), 'public void Add( int x,int y )', '001'); + }); + }); + + test('issue #3882: deleteWordStartRight', () => { + usingCursor({ + text: [ + 'public void Add( int x,', + ' int y )' + ], + }, (model, cursor) => { + moveTo(cursor, 1, 24, false); + deleteWordStartRight(cursor); assert.equal(model.getLineContent(1), 'public void Add( int x,int y )', '001'); + }); + }); + + test('issue #3882: deleteWordEndRight', () => { + usingCursor({ + text: [ + 'public void Add( int x,', + ' int y )' + ], + }, (model, cursor) => { + moveTo(cursor, 1, 24, false); + deleteWordEndRight(cursor); assert.equal(model.getLineContent(1), 'public void Add( int x,int y )', '001'); + }); + }); + test('deleteWordStartRight', () => { usingCursor({ text: [ @@ -1844,7 +1880,7 @@ suite('Editor Controller - Regression tests', () => { ], }, (model, cursor) => { moveTo(cursor, 1, 18, false); - deleteWordRight(cursor); assert.equal(model.getLineContent(1), 'A line with text. And another one', '001'); + deleteWordRight(cursor); assert.equal(model.getLineContent(1), 'A line with text.And another one', '001'); }); }); diff --git a/src/vs/editor/test/common/controller/textAreaState.test.ts b/src/vs/editor/test/common/controller/textAreaState.test.ts index 1afd11ba2a5..e196f14088d 100644 --- a/src/vs/editor/test/common/controller/textAreaState.test.ts +++ b/src/vs/editor/test/common/controller/textAreaState.test.ts @@ -8,7 +8,7 @@ import * as assert from 'assert'; import {IENarratorTextAreaState, ISimpleModel, TextAreaState} from 'vs/editor/common/controller/textAreaState'; import {Position} from 'vs/editor/common/core/position'; import {Range} from 'vs/editor/common/core/range'; -import {EndOfLinePreference, IEditorPosition, IRange} from 'vs/editor/common/editorCommon'; +import {EndOfLinePreference, IRange} from 'vs/editor/common/editorCommon'; import {MockTextAreaWrapper} from 'vs/editor/test/common/mocks/mockTextAreaWrapper'; suite('TextAreaState', () => { @@ -467,7 +467,7 @@ class SimpleModel implements ISimpleModel { return this._lines.length; } - public convertViewPositionToModelPosition(viewLineNumber:number, viewColumn:number): IEditorPosition { + public convertViewPositionToModelPosition(viewLineNumber:number, viewColumn:number): Position { return new Position(viewLineNumber, viewColumn); } } diff --git a/src/vs/editor/test/common/mocks/mockCodeEditor.ts b/src/vs/editor/test/common/mocks/mockCodeEditor.ts index 72d0f1c92cb..01b0fc06b5d 100644 --- a/src/vs/editor/test/common/mocks/mockCodeEditor.ts +++ b/src/vs/editor/test/common/mocks/mockCodeEditor.ts @@ -18,12 +18,13 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import {Model} from 'vs/editor/common/model/model'; import {MockCodeEditorService} from 'vs/editor/test/common/mocks/mockCodeEditorService'; import {MockConfiguration} from 'vs/editor/test/common/mocks/mockConfiguration'; +import {Range} from 'vs/editor/common/core/range'; export class MockCodeEditor extends CommonCodeEditor { protected _createConfiguration(options:editorCommon.ICodeEditorWidgetCreationOptions): CommonEditorConfiguration { return new MockConfiguration(options); } - public getCenteredRangeInViewport(): editorCommon.IEditorRange { return null; } + public getCenteredRangeInViewport(): Range { return null; } public getScrollWidth(): number { return 0; } public getScrollLeft(): number { return 0; } diff --git a/src/vs/editor/test/common/mocks/mockModeService.ts b/src/vs/editor/test/common/mocks/mockModeService.ts index d7b7308fdd8..ff7ccf881d8 100644 --- a/src/vs/editor/test/common/mocks/mockModeService.ts +++ b/src/vs/editor/test/common/mocks/mockModeService.ts @@ -89,6 +89,9 @@ export class MockModeService implements IModeService { registerTokenizationSupport(modeId: string, callback: (mode: modes.IMode) => modes.ITokenizationSupport): IDisposable { throw new Error('Not implemented'); } + registerTokenizationSupport2(modeId: string, support: modes.ITokenizationSupport2): IDisposable { + throw new Error('Not implemented'); + } registerMonarchDefinition(modelService: IModelService, editorWorkerService: IEditorWorkerService, modeId:string, language:ILanguage): IDisposable { throw new Error('Not implemented'); } diff --git a/src/vs/editor/test/common/model/editableTextModel.test.ts b/src/vs/editor/test/common/model/editableTextModel.test.ts index 6cbdafa02b7..a40af4dd82f 100644 --- a/src/vs/editor/test/common/model/editableTextModel.test.ts +++ b/src/vs/editor/test/common/model/editableTextModel.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import {Range} from 'vs/editor/common/core/range'; -import {EndOfLinePreference, EndOfLineSequence, EventType, IIdentifiedSingleEditOperation, IModelContentChangedEvent2} from 'vs/editor/common/editorCommon'; +import {EndOfLinePreference, EndOfLineSequence, IIdentifiedSingleEditOperation, IModelContentChangedEvent2} from 'vs/editor/common/editorCommon'; import {EditableTextModel, IValidatedEditOperation} from 'vs/editor/common/model/editableTextModel'; import {MirrorModel2} from 'vs/editor/common/model/mirrorModel2'; import {TextModel} from 'vs/editor/common/model/textModel'; @@ -1340,7 +1340,7 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { }, (model) => { var isFirstTime = true; - model.addBulkListener((events) => { + model.addBulkListener2((events) => { if (!isFirstTime) { return; } @@ -1370,7 +1370,7 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { }, (model) => { var isFirstTime = true; - model.addListener(EventType.ModelContentChanged2, (e:IModelContentChangedEvent2) => { + model.onDidChangeContent((e:IModelContentChangedEvent2) => { if (!isFirstTime) { return; } @@ -1393,7 +1393,7 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { let mirrorModel2 = new MirrorModel2(null, model.toRawText().lines, model.toRawText().EOL, model.getVersionId()); let mirrorModel2PrevVersionId = model.getVersionId(); - model.addListener(EventType.ModelContentChanged2, (e:IModelContentChangedEvent2) => { + model.onDidChangeContent((e:IModelContentChangedEvent2) => { let versionId = e.versionId; if (versionId < mirrorModel2PrevVersionId) { console.warn('Model version id did not advance between edits (2)'); diff --git a/src/vs/editor/test/common/model/editableTextModelTestUtils.ts b/src/vs/editor/test/common/model/editableTextModelTestUtils.ts index 90c86bab9ce..1e5da89796f 100644 --- a/src/vs/editor/test/common/model/editableTextModelTestUtils.ts +++ b/src/vs/editor/test/common/model/editableTextModelTestUtils.ts @@ -37,7 +37,7 @@ export function testApplyEditsWithSyncedModels(original:string[], edits:editorCo }); } -export function assertSyncedModels(text:string, callback:(model:EditableTextModel, assertMirrorModels:()=>void)=>void, setup:(model:EditableTextModel)=>void = null): void { +export function assertSyncedModels(text:string, callback:(model:EditableTextModel, assertMirrorModels:()=>void)=>void, setup:(model:EditableTextModel)=>void = null): void { var model = new EditableTextModel([], TextModel.toRawText(text, TextModel.DEFAULT_CREATION_OPTIONS), null); model.setEOL(editorCommon.EndOfLineSequence.LF); @@ -51,7 +51,7 @@ export function assertSyncedModels(text:string, callback:(model:EditableTextMod var mirrorModel2 = new MirrorModel2(null, model.toRawText().lines, model.toRawText().EOL, model.getVersionId()); var mirrorModel2PrevVersionId = model.getVersionId(); - model.addListener(editorCommon.EventType.ModelContentChanged, (e:editorCommon.IModelContentChangedEvent) => { + model.onDidChangeRawContent((e:editorCommon.IModelContentChangedEvent) => { let versionId = e.versionId; if (versionId < mirrorModel1PrevVersionId) { console.warn('Model version id did not advance between edits (1)'); @@ -63,7 +63,7 @@ export function assertSyncedModels(text:string, callback:(model:EditableTextMod mirrorModel1.onEvents(mirrorModelEvents); }); - model.addListener(editorCommon.EventType.ModelContentChanged2, (e:editorCommon.IModelContentChangedEvent2) => { + model.onDidChangeContent((e:editorCommon.IModelContentChangedEvent2) => { let versionId = e.versionId; if (versionId < mirrorModel2PrevVersionId) { console.warn('Model version id did not advance between edits (2)'); diff --git a/src/vs/editor/test/common/model/mirrorModel.test.ts b/src/vs/editor/test/common/model/mirrorModel.test.ts index ce0c0ff243b..5aae573a892 100644 --- a/src/vs/editor/test/common/model/mirrorModel.test.ts +++ b/src/vs/editor/test/common/model/mirrorModel.test.ts @@ -22,7 +22,7 @@ function equalRange(left, right) { function contentChangedFlushEvent(detail: editorCommon.IRawText): editorCommon.IModelContentChangedFlushEvent { return { - changeType: editorCommon.EventType.ModelContentChangedFlush, + changeType: editorCommon.EventType.ModelRawContentChangedFlush, isRedoing: false, isUndoing: false, versionId: 0, @@ -32,7 +32,7 @@ function contentChangedFlushEvent(detail: editorCommon.IRawText): editorCommon.I function contentChangedLinesDeletedEvent(fromLineNumber: number, toLineNumber: number): editorCommon.IModelContentChangedLinesDeletedEvent { return { - changeType: editorCommon.EventType.ModelContentChangedLinesDeleted, + changeType: editorCommon.EventType.ModelRawContentChangedLinesDeleted, isRedoing: false, isUndoing: false, versionId: 0, @@ -43,7 +43,7 @@ function contentChangedLinesDeletedEvent(fromLineNumber: number, toLineNumber: n function contentChangedLinesInsertedEvent(fromLineNumber: number, toLineNumber: number, detail: string): editorCommon.IModelContentChangedLinesInsertedEvent { return { - changeType: editorCommon.EventType.ModelContentChangedLinesInserted, + changeType: editorCommon.EventType.ModelRawContentChangedLinesInserted, isRedoing: false, isUndoing: false, versionId: 0, @@ -55,7 +55,7 @@ function contentChangedLinesInsertedEvent(fromLineNumber: number, toLineNumber: function contentChangedLineChanged(lineNumber: number, detail: string): editorCommon.IModelContentChangedLineChangedEvent { return { - changeType: editorCommon.EventType.ModelContentChangedLineChanged, + changeType: editorCommon.EventType.ModelRawContentChangedLineChanged, isRedoing: false, isUndoing: false, versionId: 0, diff --git a/src/vs/editor/test/common/model/model.test.ts b/src/vs/editor/test/common/model/model.test.ts index 501b4d97e69..4f515d29835 100644 --- a/src/vs/editor/test/common/model/model.test.ts +++ b/src/vs/editor/test/common/model/model.test.ts @@ -8,7 +8,10 @@ import * as assert from 'assert'; import {EditOperation} from 'vs/editor/common/core/editOperation'; import {Position} from 'vs/editor/common/core/position'; import {Range} from 'vs/editor/common/core/range'; -import {EventType, IModelContentChangedEvent, IModelContentChangedFlushEvent} from 'vs/editor/common/editorCommon'; +import { + EventType, IModelContentChangedEvent, IModelContentChangedFlushEvent, IModelContentChangedLineChangedEvent, + IModelContentChangedLinesDeletedEvent, IModelContentChangedLinesInsertedEvent +} from 'vs/editor/common/editorCommon'; import {Model} from 'vs/editor/common/model/model'; import {BracketMode} from 'vs/editor/test/common/testModes'; @@ -109,7 +112,7 @@ suite('Editor Model - Model', () => { // --------- insert text eventing test('model insert empty text does not trigger eventing', () => { - thisModel.addListener(EventType.ModelContentChanged, (e) => { + thisModel.onDidChangeRawContent((e) => { assert.ok(false, 'was not expecting event'); }); thisModel.applyEdits([EditOperation.insert(new Position(1, 1), '')]); @@ -117,10 +120,10 @@ suite('Editor Model - Model', () => { test('model insert text without newline eventing', () => { var listenerCalls = 0; - thisModel.addListener(EventType.ModelContentChanged, (e) => { + thisModel.onDidChangeRawContent((e) => { listenerCalls++; - assert.equal(e.changeType, EventType.ModelContentChangedLineChanged); - assert.equal(e.lineNumber, 1); + assert.equal(e.changeType, EventType.ModelRawContentChangedLineChanged); + assert.equal((e).lineNumber, 1); }); thisModel.applyEdits([EditOperation.insert(new Position(1, 1), 'foo ')]); assert.equal(listenerCalls, 1, 'listener calls'); @@ -130,21 +133,21 @@ suite('Editor Model - Model', () => { var listenerCalls = 0; var order = 0; - thisModel.addListener(EventType.ModelContentChanged, (e) => { + thisModel.onDidChangeRawContent((e) => { listenerCalls++; - if (e.changeType === EventType.ModelContentChangedLineChanged) { + if (e.changeType === EventType.ModelRawContentChangedLineChanged) { if (order === 0) { assert.equal(++order, 1, 'ModelContentChangedLineChanged first'); - assert.equal(e.lineNumber, 1, 'ModelContentChangedLineChanged line number 1'); + assert.equal((e).lineNumber, 1, 'ModelContentChangedLineChanged line number 1'); } else { assert.equal(++order, 2, 'ModelContentChangedLineChanged first'); - assert.equal(e.lineNumber, 1, 'ModelContentChangedLineChanged line number 1'); + assert.equal((e).lineNumber, 1, 'ModelContentChangedLineChanged line number 1'); } - } else if (e.changeType === EventType.ModelContentChangedLinesInserted) { + } else if (e.changeType === EventType.ModelRawContentChangedLinesInserted) { assert.equal(++order, 3, 'ModelContentChangedLinesInserted second'); - assert.equal(e.fromLineNumber, 2, 'ModelContentChangedLinesInserted fromLineNumber'); - assert.equal(e.toLineNumber, 2, 'ModelContentChangedLinesInserted toLineNumber'); + assert.equal((e).fromLineNumber, 2, 'ModelContentChangedLinesInserted fromLineNumber'); + assert.equal((e).toLineNumber, 2, 'ModelContentChangedLinesInserted toLineNumber'); } else { assert.ok (false); } @@ -206,7 +209,7 @@ suite('Editor Model - Model', () => { // --------- delete text eventing test('model delete empty text does not trigger eventing', () => { - thisModel.addListener(EventType.ModelContentChanged, (e) => { + thisModel.onDidChangeRawContent((e) => { assert.ok(false, 'was not expecting event'); }); thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 1, 1))]); @@ -214,10 +217,10 @@ suite('Editor Model - Model', () => { test('model delete text from one line eventing', () => { var listenerCalls = 0; - thisModel.addListener(EventType.ModelContentChanged, (e) => { + thisModel.onDidChangeRawContent((e) => { listenerCalls++; - assert.equal(e.changeType, EventType.ModelContentChangedLineChanged); - assert.equal(e.lineNumber, 1); + assert.equal(e.changeType, EventType.ModelRawContentChangedLineChanged); + assert.equal((e).lineNumber, 1); }); thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 1, 2))]); assert.equal(listenerCalls, 1, 'listener calls'); @@ -225,10 +228,10 @@ suite('Editor Model - Model', () => { test('model delete all text from a line eventing', () => { var listenerCalls = 0; - thisModel.addListener(EventType.ModelContentChanged, (e) => { + thisModel.onDidChangeRawContent((e) => { listenerCalls++; - assert.equal(e.changeType, EventType.ModelContentChangedLineChanged); - assert.equal(e.lineNumber, 1); + assert.equal(e.changeType, EventType.ModelRawContentChangedLineChanged); + assert.equal((e).lineNumber, 1); }); thisModel.applyEdits([EditOperation.delete(new Range(1, 1, 1, 14))]); assert.equal(listenerCalls, 1, 'listener calls'); @@ -237,21 +240,21 @@ suite('Editor Model - Model', () => { test('model delete text from two lines eventing', () => { var listenerCalls = 0; var order = 0; - thisModel.addListener(EventType.ModelContentChanged, (e) => { + thisModel.onDidChangeRawContent((e) => { listenerCalls++; - if (e.changeType === EventType.ModelContentChangedLineChanged) { + if (e.changeType === EventType.ModelRawContentChangedLineChanged) { if (order === 0) { assert.equal(++order, 1); - assert.equal(e.lineNumber, 1); + assert.equal((e).lineNumber, 1); } else { assert.equal(++order, 2); - assert.equal(e.lineNumber, 1); + assert.equal((e).lineNumber, 1); } - } else if (e.changeType === EventType.ModelContentChangedLinesDeleted) { + } else if (e.changeType === EventType.ModelRawContentChangedLinesDeleted) { assert.equal(++order, 3); - assert.equal(e.fromLineNumber, 2); - assert.equal(e.toLineNumber, 2); + assert.equal((e).fromLineNumber, 2); + assert.equal((e).toLineNumber, 2); } else { assert.ok (false); } @@ -265,21 +268,21 @@ suite('Editor Model - Model', () => { var listenerCalls = 0; var order = 0; - thisModel.addListener(EventType.ModelContentChanged, (e) => { + thisModel.onDidChangeRawContent((e) => { listenerCalls++; - if (e.changeType === EventType.ModelContentChangedLineChanged) { + if (e.changeType === EventType.ModelRawContentChangedLineChanged) { if (order === 0) { assert.equal(++order, 1); - assert.equal(e.lineNumber, 1); + assert.equal((e).lineNumber, 1); } else { assert.equal(++order, 2); - assert.equal(e.lineNumber, 1); + assert.equal((e).lineNumber, 1); } - } else if (e.changeType === EventType.ModelContentChangedLinesDeleted) { + } else if (e.changeType === EventType.ModelRawContentChangedLinesDeleted) { assert.equal(++order, 3); - assert.equal(e.fromLineNumber, 2); - assert.equal(e.toLineNumber, 3); + assert.equal((e).fromLineNumber, 2); + assert.equal((e).toLineNumber, 3); } else { assert.ok (false); } @@ -324,10 +327,10 @@ suite('Editor Model - Model', () => { // --------- setValue test('setValue eventing', () => { var listenerCalls = 0; - thisModel.addOneTimeListener(EventType.ModelContentChanged, (e:IModelContentChangedEvent) => { + thisModel.onDidChangeRawContent((e:IModelContentChangedEvent) => { listenerCalls++; - assert.equal(e.changeType, EventType.ModelContentChangedFlush); + assert.equal(e.changeType, EventType.ModelRawContentChangedFlush); assert.deepEqual((e).detail.lines, [ 'new value' ]); }); diff --git a/src/vs/editor/test/common/model/modelDecorations.test.ts b/src/vs/editor/test/common/model/modelDecorations.test.ts index f3a96344a13..752246a0a22 100644 --- a/src/vs/editor/test/common/model/modelDecorations.test.ts +++ b/src/vs/editor/test/common/model/modelDecorations.test.ts @@ -8,7 +8,7 @@ import * as assert from 'assert'; import {EditOperation} from 'vs/editor/common/core/editOperation'; import {Position} from 'vs/editor/common/core/position'; import {Range} from 'vs/editor/common/core/range'; -import {EventType, IModelDeltaDecoration, IRange, TrackedRangeStickiness} from 'vs/editor/common/editorCommon'; +import {IModelDeltaDecoration, IRange, TrackedRangeStickiness} from 'vs/editor/common/editorCommon'; import {Model} from 'vs/editor/common/model/model'; // --------- utils @@ -200,7 +200,7 @@ suite('Editor Model - Model Decorations', () => { test('decorations emit event on add', () => { var listenerCalled = 0; - thisModel.addListener(EventType.ModelDecorationsChanged, (e) => { + thisModel.onDidChangeDecorations((e) => { listenerCalled++; assert.equal(e.ids.length, 1); assert.equal(e.addedOrChangedDecorations.length, 1); @@ -219,7 +219,7 @@ suite('Editor Model - Model Decorations', () => { test('decorations emit event on change', () => { var listenerCalled = 0; var decId = addDecoration(thisModel, 1, 2, 3, 2, 'myType'); - thisModel.addListener(EventType.ModelDecorationsChanged, (e) => { + thisModel.onDidChangeDecorations((e) => { listenerCalled++; assert.equal(e.ids.length, 1); assert.equal(e.addedOrChangedDecorations.length, 1); @@ -246,7 +246,7 @@ suite('Editor Model - Model Decorations', () => { test('decorations emit event on remove', () => { var listenerCalled = 0; var decId = addDecoration(thisModel, 1, 2, 3, 2, 'myType'); - thisModel.addListener(EventType.ModelDecorationsChanged, (e) => { + thisModel.onDidChangeDecorations((e) => { listenerCalled++; assert.equal(e.ids.length, 1); assert.equal(e.addedOrChangedDecorations.length, 0); @@ -269,7 +269,7 @@ suite('Editor Model - Model Decorations', () => { var listenerCalled = 0; var decId = addDecoration(thisModel, 1, 2, 3, 2, 'myType'); - thisModel.addListener(EventType.ModelDecorationsChanged, (e) => { + thisModel.onDidChangeDecorations((e) => { listenerCalled++; assert.equal(e.ids.length, 1); assert.equal(e.addedOrChangedDecorations.length, 1); diff --git a/src/vs/editor/test/common/modes/linkComputer.test.ts b/src/vs/editor/test/common/modes/linkComputer.test.ts index df1acbbe61b..853cef3df96 100644 --- a/src/vs/editor/test/common/modes/linkComputer.test.ts +++ b/src/vs/editor/test/common/modes/linkComputer.test.ts @@ -163,6 +163,25 @@ suite('Editor Modes - Link Computer', () => { ' http://go.microsoft.com/fwlink/?LinkId=761051 ' ); + assertLink( + 'x = "file:///foo.bar";', + ' file:///foo.bar ' + ); + assertLink( + 'x = "file://c:/foo.bar";', + ' file://c:/foo.bar ' + ); + + assertLink( + 'x = "file://shares/foo.bar";', + ' file://shares/foo.bar ' + ); + + assertLink( + 'x = "file://shäres/foo.bar";', + ' file://shäres/foo.bar ' + ); + // foo bar (see http://www.w3schools.com/tags/att_iframe_sandbox.asp) }); }); diff --git a/src/vs/editor/test/common/modes/supports/richEditBrackets.test.ts b/src/vs/editor/test/common/modes/supports/richEditBrackets.test.ts index 2c7a5696357..5dd6c26122f 100644 --- a/src/vs/editor/test/common/modes/supports/richEditBrackets.test.ts +++ b/src/vs/editor/test/common/modes/supports/richEditBrackets.test.ts @@ -6,15 +6,15 @@ import * as assert from 'assert'; import {BracketsUtils} from 'vs/editor/common/modes/supports/richEditBrackets'; -import {IEditorRange} from 'vs/editor/common/editorCommon'; +import {Range} from 'vs/editor/common/core/range'; suite('richEditBrackets', () => { - function findPrevBracketInToken(reversedBracketRegex:RegExp, lineText:string, currentTokenStart:number, currentTokenEnd:number): IEditorRange { + function findPrevBracketInToken(reversedBracketRegex:RegExp, lineText:string, currentTokenStart:number, currentTokenEnd:number): Range { return BracketsUtils.findPrevBracketInToken(reversedBracketRegex, 1, lineText, currentTokenStart, currentTokenEnd); } - function findNextBracketInToken(forwardBracketRegex:RegExp, lineText:string, currentTokenStart:number, currentTokenEnd:number): IEditorRange { + function findNextBracketInToken(forwardBracketRegex:RegExp, lineText:string, currentTokenStart:number, currentTokenEnd:number): Range { return BracketsUtils.findNextBracketInToken(forwardBracketRegex, 1, lineText, currentTokenStart, currentTokenEnd); } diff --git a/src/vs/editor/test/common/modes/tokenization.test.ts b/src/vs/editor/test/common/modes/tokenization.test.ts index 137e7d3823e..dbe1b45918c 100644 --- a/src/vs/editor/test/common/modes/tokenization.test.ts +++ b/src/vs/editor/test/common/modes/tokenization.test.ts @@ -104,14 +104,11 @@ export class SwitchingMode extends MockMode { this.tokenizationSupport = new TokenizationSupport(this, this, true, false); } - public addSupportChangedListener(callback: (e: IModeSupportChangedEvent) => void): IDisposable { + registerSupport(support:modes.MutableSupport, callback:(mode:modes.IMode)=>T): IDisposable { return EmptyDisposable; } - /** - * Register a support by name. Only optional. - */ - public registerSupport(support:string, callback:(mode:modes.IMode)=>T): IDisposable { + public addSupportChangedListener(callback: (e: IModeSupportChangedEvent) => void): IDisposable { return EmptyDisposable; } diff --git a/src/vs/editor/test/common/modesUtil.ts b/src/vs/editor/test/common/modesUtil.ts index 6af217cb1ac..b7b91229bf7 100644 --- a/src/vs/editor/test/common/modesUtil.ts +++ b/src/vs/editor/test/common/modesUtil.ts @@ -13,14 +13,14 @@ import {ILanguage} from 'vs/editor/common/modes/monarch/monarchTypes'; import {createMockModeService} from 'vs/editor/test/common/servicesTestUtils'; import {MockMode} from 'vs/editor/test/common/mocks/mockMode'; -export interface IRelaxedToken { - startIndex:number; - type:string; -} - export interface ITestItem { line: string; - tokens: IRelaxedToken[]; + tokens: modes.IToken[]; +} + +export interface ITestItem2 { + line: string; + tokens: modes.IToken2[]; } export function assertWords(actual:string[], expected:string[], message?:string): void { @@ -33,7 +33,7 @@ export function assertTokenization(tokenizationSupport: modes.ITokenizationSuppo assert.ok(true, tests[i].line); var result = tokenizationSupport.tokenize(tests[i].line, state); if (tests[i].tokens) { - assert.deepEqual(toRelaxedTokens(result.tokens), toRelaxedTokens(tests[i].tokens), JSON.stringify(result.tokens, null, '\t')); + assert.deepEqual(result.tokens, tests[i].tokens, JSON.stringify(result.tokens, null, '\t')); } state = result.endState; @@ -85,6 +85,13 @@ export function executeTests(tokenizationSupport: modes.ITokenizationSupport, te } } +export function executeTests2(tokenizationSupport: modes.ITokenizationSupport2, tests:ITestItem2[][]): void { + for (var i = 0, len = tests.length; i < len; i++) { + assert.ok(true, 'TEST #' + i); + executeTest2(tokenizationSupport, tests[i]); + } +} + export function executeMonarchTokenizationTests(name:string, language:ILanguage, tests:ITestItem[][]): void { var lexer = compile(language); @@ -96,15 +103,6 @@ export function executeMonarchTokenizationTests(name:string, language:ILanguage, executeTests(tokenizationSupport, tests); } -function toRelaxedTokens(tokens: modes.IToken[]): IRelaxedToken[] { - return tokens.map((t) => { - return { - startIndex: t.startIndex, - type: t.type - }; - }); -} - function executeTest(tokenizationSupport: modes.ITokenizationSupport, tests:ITestItem[]): void { var state = tokenizationSupport.getInitialState(); for (var i = 0, len = tests.length; i < len; i++) { @@ -120,6 +118,25 @@ function executeTest(tokenizationSupport: modes.ITokenizationSupport, tests:ITes } } -function assertTokens(actual:modes.IToken[], expected:IRelaxedToken[], message?:string): void { - assert.deepEqual(toRelaxedTokens(actual), toRelaxedTokens(expected), message + ': ' + JSON.stringify(actual, null, '\t')); +function executeTest2(tokenizationSupport: modes.ITokenizationSupport2, tests:ITestItem2[]): void { + var state = tokenizationSupport.getInitialState(); + for (var i = 0, len = tests.length; i < len; i++) { + assert.ok(true, tests[i].line); + + var result = tokenizationSupport.tokenize(tests[i].line, state); + + if (tests[i].tokens) { + assertTokens2(result.tokens, tests[i].tokens, 'Tokenizing line ' + tests[i].line); + } + + state = result.endState; + } +} + +function assertTokens(actual:modes.IToken[], expected:modes.IToken[], message?:string): void { + assert.deepEqual(actual, expected, message + ': ' + JSON.stringify(actual, null, '\t')); +} + +function assertTokens2(actual:modes.IToken2[], expected:modes.IToken2[], message?:string): void { + assert.deepEqual(actual, expected, message + ': ' + JSON.stringify(actual, null, '\t')); } \ No newline at end of file diff --git a/src/vs/editor/test/common/services/resourceService.test.ts b/src/vs/editor/test/common/services/resourceService.test.ts index ea053ffa0a4..6a8ed426609 100644 --- a/src/vs/editor/test/common/services/resourceService.test.ts +++ b/src/vs/editor/test/common/services/resourceService.test.ts @@ -39,11 +39,11 @@ suite('Editor Services - ResourceService', () => { var url = URI.parse('far'); var element = createTestMirrorModelFromString('hi'); var service = new ResourceService(); - service.addListener(ResourceEvents.ADDED, () => { + service.addListener2(ResourceEvents.ADDED, () => { eventCnt++; assert.ok(true); }); - service.addListener(ResourceEvents.REMOVED, () => { + service.addListener2(ResourceEvents.REMOVED, () => { eventCnt++; assert.ok(true); }); @@ -64,7 +64,7 @@ suite('Editor Services - ResourceService', () => { var service = new ResourceService(); service.insert(url, element); - service.addBulkListener((events) => { + service.addBulkListener2((events) => { eventCnt++; assert.equal(events.length, 1); assert.equal(events[0].getData().originalEvents.length, 1); diff --git a/src/vs/editor/test/common/servicesTestUtils.ts b/src/vs/editor/test/common/servicesTestUtils.ts index 039d7f6aaaf..e4df66e6299 100644 --- a/src/vs/editor/test/common/servicesTestUtils.ts +++ b/src/vs/editor/test/common/servicesTestUtils.ts @@ -168,4 +168,8 @@ export class MockConfigurationService extends ConfigurationService { }); } + setUserConfiguration(key: any, value: any) : Thenable { + return TPromise.as(null); + } + } diff --git a/src/vs/editor/test/common/view/overviewZoneManager.test.ts b/src/vs/editor/test/common/view/overviewZoneManager.test.ts new file mode 100644 index 00000000000..522b3241e47 --- /dev/null +++ b/src/vs/editor/test/common/view/overviewZoneManager.test.ts @@ -0,0 +1,100 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as assert from 'assert'; +import {OverviewRulerLane, OverviewRulerZone, ColorZone} from 'vs/editor/common/editorCommon'; +import {OverviewZoneManager} from 'vs/editor/common/view/overviewZoneManager'; + +suite('Editor View - OverviewZoneManager', () => { + + test('pixel ratio 1, dom height 600', () => { + const LINE_COUNT = 50; + const LINE_HEIGHT = 20; + let manager = new OverviewZoneManager((lineNumber) => LINE_HEIGHT * lineNumber); + manager.setMinimumHeight(6); + manager.setMaximumHeight(6); + manager.setUseDarkColor(false); + manager.setDOMWidth(30); + manager.setDOMHeight(600); + manager.setOuterHeight(LINE_COUNT * LINE_HEIGHT); + manager.setLineHeight(LINE_HEIGHT); + manager.setPixelRatio(1); + + manager.setZones([ + new OverviewRulerZone(1, 1, OverviewRulerLane.Full, 10, '1', '1'), + new OverviewRulerZone(10, 10, OverviewRulerLane.Full, 0, '2', '2'), + new OverviewRulerZone(30, 31, OverviewRulerLane.Full, 0, '3', '3'), + new OverviewRulerZone(50, 50, OverviewRulerLane.Full, 0, '4', '4'), + ]); + + // one line = 12, but cap is at 6 + assert.deepEqual(manager.resolveColorZones(), [ + new ColorZone(12, 22, 1, OverviewRulerLane.Full), // forced height of 10 + new ColorZone(123, 129, 2, OverviewRulerLane.Full), // 120 -> 132 + new ColorZone(363, 369, 3, OverviewRulerLane.Full), // 360 -> 372 [360 -> 384] + new ColorZone(375, 381, 3, OverviewRulerLane.Full), // 372 -> 384 [360 -> 384] + new ColorZone(594, 600, 4, OverviewRulerLane.Full), // 588 -> 600 + ]); + }); + + test('pixel ratio 1, dom height 300', () => { + const LINE_COUNT = 50; + const LINE_HEIGHT = 20; + let manager = new OverviewZoneManager((lineNumber) => LINE_HEIGHT * lineNumber); + manager.setMinimumHeight(6); + manager.setMaximumHeight(6); + manager.setUseDarkColor(false); + manager.setDOMWidth(30); + manager.setDOMHeight(300); + manager.setOuterHeight(LINE_COUNT * LINE_HEIGHT); + manager.setLineHeight(LINE_HEIGHT); + manager.setPixelRatio(1); + + manager.setZones([ + new OverviewRulerZone(1, 1, OverviewRulerLane.Full, 10, '1', '1'), + new OverviewRulerZone(10, 10, OverviewRulerLane.Full, 0, '2', '2'), + new OverviewRulerZone(30, 31, OverviewRulerLane.Full, 0, '3', '3'), + new OverviewRulerZone(50, 50, OverviewRulerLane.Full, 0, '4', '4'), + ]); + + // one line = 6, cap is at 6 + assert.deepEqual(manager.resolveColorZones(), [ + new ColorZone(6, 16, 1, OverviewRulerLane.Full), // forced height of 10 + new ColorZone(60, 66, 2, OverviewRulerLane.Full), // 60 -> 66 + new ColorZone(180, 192, 3, OverviewRulerLane.Full), // 180 -> 192 + new ColorZone(294, 300, 4, OverviewRulerLane.Full), // 294 -> 300 + ]); + }); + + test('pixel ratio 2, dom height 300', () => { + const LINE_COUNT = 50; + const LINE_HEIGHT = 20; + let manager = new OverviewZoneManager((lineNumber) => LINE_HEIGHT * lineNumber); + manager.setMinimumHeight(6); + manager.setMaximumHeight(6); + manager.setUseDarkColor(false); + manager.setDOMWidth(30); + manager.setDOMHeight(300); + manager.setOuterHeight(LINE_COUNT * LINE_HEIGHT); + manager.setLineHeight(LINE_HEIGHT); + manager.setPixelRatio(2); + + manager.setZones([ + new OverviewRulerZone(1, 1, OverviewRulerLane.Full, 10, '1', '1'), + new OverviewRulerZone(10, 10, OverviewRulerLane.Full, 0, '2', '2'), + new OverviewRulerZone(30, 31, OverviewRulerLane.Full, 0, '3', '3'), + new OverviewRulerZone(50, 50, OverviewRulerLane.Full, 0, '4', '4'), + ]); + + // one line = 6, cap is at 12 + assert.deepEqual(manager.resolveColorZones(), [ + new ColorZone(12, 32, 1, OverviewRulerLane.Full), // forced height of 10 => forced height of 20 + new ColorZone(120, 132, 2, OverviewRulerLane.Full), // 120 -> 132 + new ColorZone(360, 384, 3, OverviewRulerLane.Full), // 360 -> 384 + new ColorZone(588, 600, 4, OverviewRulerLane.Full), // 588 -> 600 + ]); + }); +}); diff --git a/src/vs/languages/buildfile-editor-languages.js b/src/vs/languages/buildfile-editor-languages.js index 1d21b527b69..cc0920cadd3 100644 --- a/src/vs/languages/buildfile-editor-languages.js +++ b/src/vs/languages/buildfile-editor-languages.js @@ -23,7 +23,7 @@ var EntryPoint = (function() { excludes = toArray(excludes); this.result.push({ name: moduleId, - exclude: ['vs/css', 'vs/nls', 'vs/text'].concat(this.modules).concat(excludes) + exclude: ['vs/css', 'vs/nls'].concat(this.modules).concat(excludes) }); return new EntryPoint(this.result, this.modules.concat([moduleId].concat(excludes))); }; @@ -48,17 +48,17 @@ exports.collectModules = function(args) { result.push({ name: 'vs/languages/typescript/common/lib/typescriptServices', - exclude: ['vs/css', 'vs/nls', 'vs/text'] + exclude: ['vs/css', 'vs/nls'] }); result.push({ name: 'vs/languages/typescript/common/worker', - exclude: ['vs/base/common/worker/simpleWorker', 'vs/languages/typescript/common/lib/typescriptServices', 'vs/css', 'vs/nls', 'vs/text'] + exclude: ['vs/base/common/worker/simpleWorker', 'vs/languages/typescript/common/lib/typescriptServices', 'vs/css', 'vs/nls'] }); result.push({ name: 'vs/languages/typescript/common/mode', - exclude: ['vs/editor/editor.main', 'vs/languages/typescript/common/lib/typescriptServices', 'vs/css', 'vs/nls', 'vs/text'] + exclude: ['vs/editor/editor.main', 'vs/languages/typescript/common/lib/typescriptServices', 'vs/css', 'vs/nls'] }); return result; diff --git a/src/vs/languages/buildfile.js b/src/vs/languages/buildfile.js index d5e627f4fc4..50d3a57ac48 100644 --- a/src/vs/languages/buildfile.js +++ b/src/vs/languages/buildfile.js @@ -23,7 +23,7 @@ var EntryPoint = (function() { excludes = toArray(excludes); this.result.push({ name: moduleId, - exclude: ['vs/css', 'vs/nls', 'vs/text'].concat(this.modules).concat(excludes) + exclude: ['vs/css', 'vs/nls'].concat(this.modules).concat(excludes) }); return new EntryPoint(this.result, this.modules.concat([moduleId].concat(excludes))); }; diff --git a/src/vs/languages/css/common/buildscripts/css-schema.xml b/src/vs/languages/css/common/buildscripts/css-schema.xml index 6867241c32f..1c063c3b63c 100644 --- a/src/vs/languages/css/common/buildscripts/css-schema.xml +++ b/src/vs/languages/css/common/buildscripts/css-schema.xml @@ -505,7 +505,7 @@ - + diff --git a/src/vs/languages/css/common/css.contribution.ts b/src/vs/languages/css/common/css.contribution.ts index 9f3f26da3fa..d138a6b210a 100644 --- a/src/vs/languages/css/common/css.contribution.ts +++ b/src/vs/languages/css/common/css.contribution.ts @@ -10,6 +10,10 @@ import Platform = require('vs/platform/platform'); import {ModesRegistry} from 'vs/editor/common/modes/modesRegistry'; import ConfigurationRegistry = require('vs/platform/configuration/common/configurationRegistry'); import lintRules = require('vs/languages/css/common/services/lintRules'); +import {IRange} from 'vs/editor/common/editorCommon'; +import {Range} from 'vs/editor/common/core/range'; +import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; +import {ReplaceCommandWithoutChangingPosition} from 'vs/editor/common/commands/replaceCommand'; ModesRegistry.registerCompatMode({ id: 'css', @@ -29,4 +33,9 @@ configurationRegistry.registerConfiguration({ 'title': nls.localize('lint', "Controls CSS validation and problem severities."), 'properties': lintRules.getConfigurationProperties('css') }] +}); + +CommonEditorRegistry.registerEditorCommand('_css.replaceText', -1, { primary: undefined }, true, void 0, (accessor, editor, args: { range: IRange; newText: string;}) => { + let {range, newText} = args; + editor.executeCommand('_css.replaceText', new ReplaceCommandWithoutChangingPosition(Range.lift(range), newText)); }); \ No newline at end of file diff --git a/src/vs/languages/css/common/css.ts b/src/vs/languages/css/common/css.ts index 3cdfeeaaccc..a52b08584e9 100644 --- a/src/vs/languages/css/common/css.ts +++ b/src/vs/languages/css/common/css.ts @@ -7,8 +7,8 @@ import WinJS = require('vs/base/common/winjs.base'); import objects = require('vs/base/common/objects'); import URI from 'vs/base/common/uri'; -import EditorCommon = require('vs/editor/common/editorCommon'); -import Modes = require('vs/editor/common/modes'); +import editorCommon = require('vs/editor/common/editorCommon'); +import modes = require('vs/editor/common/modes'); import {OneWorkerAttr, AllWorkersAttr} from 'vs/platform/thread/common/threadService'; import cssWorker = require('vs/languages/css/common/cssWorker'); import cssTokenTypes = require('vs/languages/css/common/cssTokenTypes'); @@ -19,7 +19,7 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat import {IThreadService, ThreadAffinity} from 'vs/platform/thread/common/thread'; import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport'; import {TokenizationSupport} from 'vs/editor/common/modes/supports/tokenizationSupport'; -import {SuggestSupport} from 'vs/editor/common/modes/supports/suggestSupport'; +import {wireCancellationToken} from 'vs/base/common/async'; export enum States { Selector, @@ -45,7 +45,7 @@ export class State extends AbstractState { public inMeta:boolean; public metaBraceCount: number; - constructor(mode:Modes.IMode, kind:States, inComment:boolean, quote:string, inMeta:boolean, metaBraceCount: number) { + constructor(mode:modes.IMode, kind:States, inComment:boolean, quote:string, inMeta:boolean, metaBraceCount: number) { super(mode); this.kind = kind; this.inComment = inComment; @@ -54,7 +54,7 @@ export class State extends AbstractState { this.metaBraceCount = metaBraceCount; } - private nextState(next:States, token:Modes.ITokenizationResult):Modes.ITokenizationResult { + private nextState(next:States, token:modes.ITokenizationResult):modes.ITokenizationResult { this.kind = next; return token; } @@ -63,18 +63,18 @@ export class State extends AbstractState { return new State(this.getMode(), this.kind, this.inComment, this.quote, this.inMeta, this.metaBraceCount); } - public equals(other:Modes.IState):boolean { + public equals(other:modes.IState):boolean { return super.equals(other) && objects.equals(this, other); } - private tokenizeInComment(stream:Modes.IStream):Modes.ITokenizationResult { + private tokenizeInComment(stream:modes.IStream):modes.ITokenizationResult { if (/\*\/$/.test(stream.advanceUntilString('*/', true))) { this.inComment = false; } return { type:'comment.css' }; } - private tokenizeInString(stream:Modes.IStream):Modes.ITokenizationResult { + private tokenizeInString(stream:modes.IStream):modes.ITokenizationResult { var ch:string, afterBackslash = false, quote = this.quote; while (!stream.eos()) { @@ -96,7 +96,7 @@ export class State extends AbstractState { return { type:'string.css' }; } - private consumeIdent(stream:Modes.IStream) { + private consumeIdent(stream:modes.IStream) { stream.goBack(1); if (stream.advanceIfRegExp2(identRegEx)) { return true; @@ -105,7 +105,7 @@ export class State extends AbstractState { return false; } - public tokenize(stream:Modes.IStream):Modes.ITokenizationResult { + public tokenize(stream:modes.IStream):modes.ITokenizationResult { if (this.inComment) { return this.tokenizeInComment(stream); } @@ -278,23 +278,16 @@ export class State extends AbstractState { export class CSSMode extends AbstractMode { - public tokenizationSupport: Modes.ITokenizationSupport; - public richEditSupport: Modes.IRichEditSupport; - public inplaceReplaceSupport:Modes.IInplaceReplaceSupport; - public configSupport:Modes.IConfigurationSupport; - public referenceSupport: Modes.IReferenceSupport; - public extraInfoSupport:Modes.IExtraInfoSupport; - public occurrencesSupport:Modes.IOccurrencesSupport; - public outlineSupport: Modes.IOutlineSupport; - public declarationSupport: Modes.IDeclarationSupport; - public suggestSupport: Modes.ISuggestSupport; - public quickFixSupport: Modes.IQuickFixSupport; + public tokenizationSupport: modes.ITokenizationSupport; + public richEditSupport: modes.IRichEditSupport; + public inplaceReplaceSupport:modes.IInplaceReplaceSupport; + public configSupport:modes.IConfigurationSupport; private _modeWorkerManager: ModeWorkerManager; private _threadService:IThreadService; constructor( - descriptor:Modes.IModeDescriptor, + descriptor:modes.IModeDescriptor, @IInstantiationService instantiationService: IInstantiationService, @IThreadService threadService: IThreadService ) { @@ -333,23 +326,49 @@ export class CSSMode extends AbstractMode { this.inplaceReplaceSupport = this; this.configSupport = this; - //this.occurrencesSupport = this; - this.extraInfoSupport = this; - // this.referenceSupport = new ReferenceSupport(this.getId(), { - // tokens: [cssTokenTypes.TOKEN_PROPERTY + '.css', cssTokenTypes.TOKEN_VALUE + '.css', cssTokenTypes.TOKEN_SELECTOR_TAG + '.css'], - // findReferences: (resource, position, /*unused*/includeDeclaration) => this.findReferences(resource, position)}); - this.outlineSupport = this; - // this.declarationSupport = new DeclarationSupport(this.getId(), { - // tokens: [cssTokenTypes.TOKEN_VALUE + '.css'], - // findDeclaration: (resource, position) => this.findDeclaration(resource, position)}); - this.suggestSupport = new SuggestSupport(this.getId(), { + modes.DocumentHighlightProviderRegistry.register(this.getId(), { + provideDocumentHighlights: (model, position, token): Thenable => { + return wireCancellationToken(token, this._provideDocumentHighlights(model.uri, position)); + } + }, true); + + modes.HoverProviderRegistry.register(this.getId(), { + provideHover: (model, position, token): Thenable => { + return wireCancellationToken(token, this._provideHover(model.uri, position)); + } + }, true); + + modes.ReferenceProviderRegistry.register(this.getId(), { + provideReferences: (model, position, context, token): Thenable => { + return wireCancellationToken(token, this._provideReferences(model.uri, position)); + } + }, true); + + modes.DocumentSymbolProviderRegistry.register(this.getId(), { + provideDocumentSymbols: (model, token): Thenable => { + return wireCancellationToken(token, this._provideDocumentSymbols(model.uri)); + } + }, true); + + modes.DefinitionProviderRegistry.register(this.getId(), { + provideDefinition: (model, position, token): Thenable => { + return wireCancellationToken(token, this._provideDefinition(model.uri, position)); + } + }, true); + + modes.SuggestRegistry.register(this.getId(), { triggerCharacters: [' ', ':'], - excludeTokens: ['comment.css', 'string.css'], - suggest: (resource, position) => this.suggest(resource, position)}); + provideCompletionItems: (model, position, token): Thenable => { + return wireCancellationToken(token, this._provideCompletionItems(model.uri, position)); + } + }, true); - - this.quickFixSupport = this; + modes.CodeActionProviderRegistry.register(this.getId(), { + provideCodeActions: (model, range, token): Thenable => { + return wireCancellationToken(token, this._provideCodeActions(model.uri, range)); + } + }, true); } public creationDone(): void { @@ -377,7 +396,7 @@ export class CSSMode extends AbstractMode { } static $navigateValueSet = OneWorkerAttr(CSSMode, CSSMode.prototype.navigateValueSet); - public navigateValueSet(resource:URI, position:EditorCommon.IRange, up:boolean):WinJS.TPromise { + public navigateValueSet(resource:URI, position:editorCommon.IRange, up:boolean):WinJS.TPromise { return this._worker((w) => w.navigateValueSet(resource, position, up)); } @@ -386,48 +405,43 @@ export class CSSMode extends AbstractMode { return this._worker((w) => w.enableValidator()); } - static $findOccurrences = OneWorkerAttr(CSSMode, CSSMode.prototype.findOccurrences); - public findOccurrences(resource:URI, position:EditorCommon.IPosition, strict:boolean = false): WinJS.TPromise { - return this._worker((w) => w.findOccurrences(resource, position, strict)); + static $_provideDocumentHighlights = OneWorkerAttr(CSSMode, CSSMode.prototype._provideDocumentHighlights); + private _provideDocumentHighlights(resource:URI, position:editorCommon.IPosition): WinJS.TPromise { + return this._worker((w) => w.provideDocumentHighlights(resource, position)); } - static $suggest = OneWorkerAttr(CSSMode, CSSMode.prototype.suggest); - public suggest(resource:URI, position:EditorCommon.IPosition):WinJS.TPromise { - return this._worker((w) => w.suggest(resource, position)); + static $_provideCompletionItems = OneWorkerAttr(CSSMode, CSSMode.prototype._provideCompletionItems); + private _provideCompletionItems(resource:URI, position:editorCommon.IPosition):WinJS.TPromise { + return this._worker((w) => w.provideCompletionItems(resource, position)); } - static $findDeclaration = OneWorkerAttr(CSSMode, CSSMode.prototype.findDeclaration); - public findDeclaration(resource:URI, position:EditorCommon.IPosition):WinJS.TPromise { - return this._worker((w) => w.findDeclaration(resource, position)); + static $_provideDefinition = OneWorkerAttr(CSSMode, CSSMode.prototype._provideDefinition); + private _provideDefinition(resource:URI, position:editorCommon.IPosition):WinJS.TPromise { + return this._worker((w) => w.provideDefinition(resource, position)); } - static $computeInfo = OneWorkerAttr(CSSMode, CSSMode.prototype.computeInfo); - public computeInfo(resource:URI, position:EditorCommon.IPosition): WinJS.TPromise { - return this._worker((w) => w.computeInfo(resource, position)); + static $_provideHover = OneWorkerAttr(CSSMode, CSSMode.prototype._provideHover); + private _provideHover(resource:URI, position:editorCommon.IPosition): WinJS.TPromise { + return this._worker((w) => w.provideHover(resource, position)); } - static $findReferences = OneWorkerAttr(CSSMode, CSSMode.prototype.findReferences); - public findReferences(resource:URI, position:EditorCommon.IPosition):WinJS.TPromise { - return this._worker((w) => w.findReferences(resource, position)); + static $_provideReferences = OneWorkerAttr(CSSMode, CSSMode.prototype._provideReferences); + private _provideReferences(resource:URI, position:editorCommon.IPosition):WinJS.TPromise { + return this._worker((w) => w.provideReferences(resource, position)); } - static $getOutline = OneWorkerAttr(CSSMode, CSSMode.prototype.getOutline); - public getOutline(resource:URI):WinJS.TPromise { - return this._worker((w) => w.getOutline(resource)); + static $_provideDocumentSymbols = OneWorkerAttr(CSSMode, CSSMode.prototype._provideDocumentSymbols); + private _provideDocumentSymbols(resource:URI):WinJS.TPromise { + return this._worker((w) => w.provideDocumentSymbols(resource)); } static $findColorDeclarations = OneWorkerAttr(CSSMode, CSSMode.prototype.findColorDeclarations); - public findColorDeclarations(resource:URI):WinJS.TPromise<{range:EditorCommon.IRange; value:string; }[]> { + public findColorDeclarations(resource:URI):WinJS.TPromise<{range:editorCommon.IRange; value:string; }[]> { return this._worker((w) => w.findColorDeclarations(resource)); } - static getQuickFixes = OneWorkerAttr(CSSMode, CSSMode.prototype.getQuickFixes); - public getQuickFixes(resource: URI, marker: IMarker | EditorCommon.IRange): WinJS.TPromise{ - return this._worker((w) => w.getQuickFixes(resource, marker)); + static _provideCodeActions = OneWorkerAttr(CSSMode, CSSMode.prototype._provideCodeActions); + private _provideCodeActions(resource: URI, marker: IMarker | editorCommon.IRange): WinJS.TPromise{ + return this._worker((w) => w.provideCodeActions(resource, marker)); } - - static runQuickFixAction = OneWorkerAttr(CSSMode, CSSMode.prototype.runQuickFixAction); - public runQuickFixAction(resource:URI, range:EditorCommon.IRange, id: any):WinJS.TPromise{ - return this._worker((w) => w.runQuickFixAction(resource, range, id)); - } -} +} \ No newline at end of file diff --git a/src/vs/languages/css/common/cssWorker.ts b/src/vs/languages/css/common/cssWorker.ts index dae04dd0b34..b73217d53f7 100644 --- a/src/vs/languages/css/common/cssWorker.ts +++ b/src/vs/languages/css/common/cssWorker.ts @@ -13,8 +13,8 @@ import languageService = require('vs/languages/css/common/services/cssLanguageSe import languageFacts = require('vs/languages/css/common/services/languageFacts'); import occurrences = require('./services/occurrences'); import cssIntellisense = require('vs/languages/css/common/services/intelliSense'); -import EditorCommon = require('vs/editor/common/editorCommon'); -import Modes = require('vs/editor/common/modes'); +import editorCommon = require('vs/editor/common/editorCommon'); +import modes = require('vs/editor/common/modes'); import nodes = require('vs/languages/css/common/parser/cssNodes'); import _level = require('vs/languages/css/common/level'); import parser = require('vs/languages/css/common/parser/cssParser'); @@ -23,6 +23,7 @@ import lint = require('vs/languages/css/common/services/lint'); import lintRules = require('vs/languages/css/common/services/lintRules'); import {IMarker, IMarkerData} from 'vs/platform/markers/common/markers'; import {IMarkerService} from 'vs/platform/markers/common/markers'; +import {Range} from 'vs/editor/common/core/range'; import {IResourceService} from 'vs/editor/common/services/resourceService'; import {filterSuggestions} from 'vs/editor/common/modes/supports/suggestSupport'; import {ValidationHelper} from 'vs/editor/common/worker/validationHelper'; @@ -58,7 +59,7 @@ export class CSSWorker { this.validationEnabled = true; } - public navigateValueSet(resource:URI, range:EditorCommon.IRange, up:boolean):winjs.TPromise { + public navigateValueSet(resource:URI, range:editorCommon.IRange, up:boolean):winjs.TPromise { return this.languageService.join().then(() => { let model = this.resourceService.get(resource); @@ -98,7 +99,7 @@ export class CSSWorker { nextIdx = len - 1; } } - let result:Modes.IInplaceReplaceSupportResult = { + let result:modes.IInplaceReplaceSupportResult = { value: values[nextIdx], range: this._range(node, model) }; @@ -107,7 +108,7 @@ export class CSSWorker { } // if none matches, take the first one if (values.length > 0) { - let result:Modes.IInplaceReplaceSupportResult = { + let result:modes.IInplaceReplaceSupportResult = { value: values[0], range: this._range(node, model) }; @@ -174,7 +175,7 @@ export class CSSWorker { }); } - private _createMarkerData(model: EditorCommon.IMirrorModel, marker: nodes.IMarker): IMarkerData { + private _createMarkerData(model: editorCommon.IMirrorModel, marker: nodes.IMarker): IMarkerData { let range = model.getRangeFromOffsetAndLength(marker.getOffset(), marker.getLength()); return { code: marker.getRule().id, @@ -195,11 +196,11 @@ export class CSSWorker { return new cssIntellisense.CSSIntellisense(); } - public suggest(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { + public provideCompletionItems(resource:URI, position:editorCommon.IPosition):winjs.TPromise { return this.doSuggest(resource, position).then(value => filterSuggestions(value)); } - private doSuggest(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { + private doSuggest(resource:URI, position:editorCommon.IPosition):winjs.TPromise { return this.languageService.join().then(() => { @@ -210,42 +211,44 @@ export class CSSWorker { } - public getOutline(resource:URI):winjs.TPromise { + public provideDocumentSymbols(resource:URI):winjs.TPromise { return this.languageService.join().then(() => { let model = this.resourceService.get(resource), stylesheet = this.languageService.getStylesheet(resource), - result:Modes.IOutlineEntry[] = []; + result:modes.SymbolInformation[] = []; stylesheet.accept((node) => { - let entry:Modes.IOutlineEntry = { - label: null, - type: 'rule', - range: null, - children: [] + let entry:modes.SymbolInformation = { + name: null, + kind: modes.SymbolKind.Class, // TODO@Martin: find a good SymbolKind + location: null }; if(node instanceof nodes.Selector) { - entry.label = node.getText(); + entry.name = node.getText(); } else if(node instanceof nodes.VariableDeclaration) { - entry.label = ( node).getName(); - entry.type = 'letiable'; + entry.name = ( node).getName(); + entry.kind = modes.SymbolKind.Variable; } else if(node instanceof nodes.MixinDeclaration) { - entry.label = ( node).getName(); - entry.type = 'method'; + entry.name = ( node).getName(); + entry.kind = modes.SymbolKind.Method; } else if(node instanceof nodes.FunctionDeclaration) { - entry.label = ( node).getName(); - entry.type = 'function'; + entry.name = ( node).getName(); + entry.kind = modes.SymbolKind.Function; } else if(node instanceof nodes.Keyframe) { - entry.label = nls.localize('literal.keyframes', "@keyframes {0}", ( node).getName()); + entry.name = nls.localize('literal.keyframes', "@keyframes {0}", ( node).getName()); } else if(node instanceof nodes.FontFace) { - entry.label = nls.localize('literal.fontface', "@font-face"); + entry.name = nls.localize('literal.fontface', "@font-face"); } - if(entry.label) { - entry.range = this._range(node, model, true); + if(entry.name) { + entry.location = { + uri: resource, + range: this._range(node, model, true) + }; result.push(entry); } @@ -256,7 +259,7 @@ export class CSSWorker { }); } - public computeInfo(resource:URI, position:EditorCommon.IPosition): winjs.TPromise { + public provideHover(resource:URI, position:editorCommon.IPosition): winjs.TPromise { return this.languageService.join().then(() => { @@ -295,7 +298,7 @@ export class CSSWorker { }); } - public findDeclaration(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { + public provideDefinition(resource:URI, position:editorCommon.IPosition):winjs.TPromise { return this.languageService.join().then(() => { @@ -307,14 +310,14 @@ export class CSSWorker { return null; } - return { - resource: resource, + return { + uri: resource, range: this._range(node, model, true) }; }); } - public findOccurrences(resource:URI, position:EditorCommon.IPosition, strict?:boolean):winjs.TPromise { + public provideDocumentHighlights(resource:URI, position:editorCommon.IPosition):winjs.TPromise { return this.languageService.join().then(() => { @@ -331,7 +334,7 @@ export class CSSWorker { }); } - public findReferences(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { + public provideReferences(resource:URI, position:editorCommon.IPosition):winjs.TPromise { return this.languageService.join().then(() => { let model = this.resourceService.get(resource), @@ -339,8 +342,8 @@ export class CSSWorker { nodes = occurrences.findOccurrences(this.languageService.getStylesheet(resource), offset); return nodes.map((occurrence) => { - return { - resource: model.getAssociatedResource(), + return { + uri: model.uri, range: this._range(occurrence.node, model) }; }); @@ -353,7 +356,7 @@ export class CSSWorker { let model = this.resourceService.get(resource), styleSheet = this.languageService.getStylesheet(resource), - result:{range:EditorCommon.IRange; value:string; }[] = []; + result:{range:editorCommon.IRange; value:string; }[] = []; styleSheet.accept((node) => { if (languageFacts.isColorValue(node)) { @@ -369,7 +372,7 @@ export class CSSWorker { }); } - _range(node:{offset:number; length:number;}, model:EditorCommon.IMirrorModel, empty:boolean = false):EditorCommon.IRange { + _range(node:{offset:number; length:number;}, model:editorCommon.IMirrorModel, empty:boolean = false):editorCommon.IRange { if (empty) { let position = model.getPositionFromOffset(node.offset); return { @@ -383,18 +386,18 @@ export class CSSWorker { } } - private getFixesForUnknownProperty(property: nodes.Property) : Modes.IQuickFix[] { + private getFixesForUnknownProperty(property: nodes.Property, marker: IMarker) : modes.IQuickFix[] { let propertyName = property.getName(); - let result: Modes.IQuickFix[] = []; + let result: modes.IQuickFix[] = []; for (let p in languageFacts.getProperties()) { let score = strings.difference(propertyName, p); if (score >= propertyName.length / 2 /*score_lim*/) { result.push({ command: { - id: 'css.renameProptery', + id: '_css.replaceText', title: nls.localize('css.quickfix.rename', "Rename to '{0}'", p), - arguments: [{ type: 'rename', name: p }] + arguments: [{ range: Range.lift(marker), newText: p }] }, score }); @@ -409,40 +412,39 @@ export class CSSWorker { return result.slice(0, 3 /*max_result*/); } - public getQuickFixes(resource: URI, marker: IMarker | EditorCommon.IRange): winjs.TPromise { - if (( marker).code !== lintRules.Rules.UnknownProperty.id) { - return winjs.TPromise.as([]); + private appendFixesForMarker(bucket: modes.IQuickFix[], marker: IMarker): void { + + if ((marker).code !== lintRules.Rules.UnknownProperty.id) { + return; } + let model = this.resourceService.get(marker.resource), + offset = model.getOffsetFromPosition({ column: marker.startColumn, lineNumber: marker.startLineNumber }), + stylesheet = this.languageService.getStylesheet(marker.resource), + nodepath = nodes.getNodePath(stylesheet, offset); - return this.languageService.join().then(() => { - - let model = this.resourceService.get(resource), - offset = model.getOffsetFromPosition({ column: marker.startColumn, lineNumber: marker.startLineNumber }), - stylesheet = this.languageService.getStylesheet(resource), - nodepath = nodes.getNodePath(stylesheet, offset); - - for (let i = nodepath.length - 1; i >= 0; i--) { - let node = nodepath[i]; - if (node instanceof nodes.Declaration) { - let property = ( node).getProperty(); - if (property && property.offset === offset && property.length === marker.endColumn - marker.startColumn) { - return this.getFixesForUnknownProperty(property); - } + for (let i = nodepath.length - 1; i >= 0; i--) { + let node = nodepath[i]; + if (node instanceof nodes.Declaration) { + let property = ( node).getProperty(); + if (property && property.offset === offset && property.length === marker.endColumn - marker.startColumn) { + bucket.push(...this.getFixesForUnknownProperty(property, marker)); + return; } } - return []; + } + } + + public provideCodeActions(resource: URI, range: editorCommon.IRange): winjs.TPromise { + + return this.languageService.join().then(() => { + const result: modes.IQuickFix[] = []; + + this.markerService.read({ resource }) + .filter(marker => Range.containsRange(range, marker)) + .forEach(marker => this.appendFixesForMarker(result, marker)); + + return result; }); } - public runQuickFixAction(resource: URI, range: EditorCommon.IRange, quickFix: Modes.IQuickFix): winjs.TPromise{ - let [{type, name}] = quickFix.command.arguments; - switch (type) { - case 'rename': { - return winjs.TPromise.as({ - edits: [{ resource, range, newText: name }] - }); - } - } - return null; - } } diff --git a/src/vs/languages/css/common/parser/cssNodes.ts b/src/vs/languages/css/common/parser/cssNodes.ts index f3be1859b6e..647cf4a3269 100644 --- a/src/vs/languages/css/common/parser/cssNodes.ts +++ b/src/vs/languages/css/common/parser/cssNodes.ts @@ -492,11 +492,7 @@ export class SimpleSelector extends Node { } } -export class Declaration extends Node { - - private property:Property; - private value:Expression; - private nestedProprties:NestedProperties; +export abstract class AbstractDeclaration extends Node { // positions for code assist public colonPosition:number; @@ -505,6 +501,17 @@ export class Declaration extends Node { constructor(offset:number, length:number) { super(offset, length); } +} + +export class Declaration extends AbstractDeclaration { + + private property:Property; + private value:Expression; + private nestedProprties:NestedProperties; + + constructor(offset:number, length:number) { + super(offset, length); + } public get type():NodeType { return NodeType.Declaration; @@ -1117,13 +1124,11 @@ export class NumericValue extends Node { } } -export class VariableDeclaration extends Node { +export class VariableDeclaration extends AbstractDeclaration { private variable:Variable; private value:Node; - public colonPosition: number; - constructor(offset:number, length:number) { super(offset, length); } @@ -1141,6 +1146,10 @@ export class VariableDeclaration extends Node { return false; } + public getVariable():Variable { + return this.variable; + } + public getName():string { return this.variable ? this.variable.getName() : ''; } diff --git a/src/vs/languages/css/common/parser/cssParser.ts b/src/vs/languages/css/common/parser/cssParser.ts index d1828c242d3..8dff2096b75 100644 --- a/src/vs/languages/css/common/parser/cssParser.ts +++ b/src/vs/languages/css/common/parser/cssParser.ts @@ -49,7 +49,7 @@ export class Parser { return true; } - public peekRegEx(type:scanner.TokenType, regEx: RegExp): boolean { + public peekRegExp(type:scanner.TokenType, regEx: RegExp): boolean { if (type !== this.token.type) { return false; } @@ -89,7 +89,6 @@ export class Parser { return false; } - public accept(type: scanner.TokenType, text?: string, ignoreCase:boolean=true): boolean { if(this.peek(type, text, ignoreCase)) { this.consumeToken(); @@ -955,7 +954,6 @@ export class Parser { return null; } - public _parseFunction(): nodes.Function { var pos = this.mark(); @@ -964,16 +962,16 @@ export class Parser { if (!node.setIdentifier(this._parseFunctionIdentifier())) { return null; } + if (this.hasWhitespace() || !this.accept(scanner.TokenType.ParenthesisL)) { this.restoreAtMark(pos); return null; } - // arguments if (node.getArguments().addChild(this._parseFunctionArgument())) { while (this.accept(scanner.TokenType.Comma)) { if (!node.getArguments().addChild(this._parseFunctionArgument())) { - return this.finish(node, errors.ParseError.ExpressionExpected); + this.markError(node, errors.ParseError.ExpressionExpected); } } } @@ -987,6 +985,7 @@ export class Parser { public _parseFunctionIdentifier(): nodes.Identifier { var node = this.create(nodes.Identifier); node.referenceTypes = [ nodes.ReferenceType.Function ]; + if (this.accept(scanner.TokenType.Ident, 'progid')) { // support for IE7 specific filters: 'progid:DXImageTransform.Microsoft.MotionBlur(strength=13, direction=310)' if (this.accept(scanner.TokenType.Colon)) { @@ -1010,8 +1009,8 @@ export class Parser { } public _parseHexColor(): nodes.Node { - var node = this.create(nodes.HexColorValue); - if (this.peekRegEx(scanner.TokenType.Hash, /^#[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$/g)) { + if (this.peekRegExp(scanner.TokenType.Hash, /^#[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$/g)) { + var node = this.create(nodes.HexColorValue); this.consumeToken(); return this.finish(node); } else { diff --git a/src/vs/languages/css/common/parser/cssScanner.ts b/src/vs/languages/css/common/parser/cssScanner.ts index 461ad682dc6..d259b327052 100644 --- a/src/vs/languages/css/common/parser/cssScanner.ts +++ b/src/vs/languages/css/common/parser/cssScanner.ts @@ -43,7 +43,6 @@ export enum TokenType { Resolution, Comma, Charset, - EscapedJavaScript, BadEscapedJavaScript, Comment, @@ -288,6 +287,7 @@ export class Scanner { if (tokenType !== null) { return this.finishToken(offset, tokenType); } + let content: string[] = []; if (this.ident(content)) { return this.finishToken(offset, TokenType.Ident, content.join('')); diff --git a/src/vs/languages/css/common/parser/cssSymbols.ts b/src/vs/languages/css/common/parser/cssSymbols.ts index 19ef312278e..5598ba1ca93 100644 --- a/src/vs/languages/css/common/parser/cssSymbols.ts +++ b/src/vs/languages/css/common/parser/cssSymbols.ts @@ -139,9 +139,10 @@ export class ScopeBuilder implements nodes.IVisitor { case nodes.NodeType.Keyframe: this.addSymbol(node, ( node).getName(), nodes.ReferenceType.Keyframe); return true; + case nodes.NodeType.Declaration: + return this.visitDeclarationNode(node); case nodes.NodeType.VariableDeclaration: - this.addSymbol(node, ( node).getName(), nodes.ReferenceType.Variable); - return true; + return this.visitVariableDeclarationNode(node); case nodes.NodeType.Ruleset: return this.visitRuleSet( node); case nodes.NodeType.MixinDeclaration: @@ -176,17 +177,44 @@ export class ScopeBuilder implements nodes.IVisitor { public visitRuleSet(node:nodes.RuleSet):boolean { var current = this.scope.findScope(node.offset, node.length); - node.getSelectors().getChildren().forEach((node) => { - if (node instanceof nodes.Selector) { - if (node.getChildren().length === 1) { // only selectors with a single element can be extended - current.addSymbol(new Symbol(node.getChild(0).getText(), node, nodes.ReferenceType.Rule)); + node.getSelectors().getChildren().forEach((child) => { + if (child instanceof nodes.Selector) { + if (child.getChildren().length === 1) { // only selectors with a single element can be extended + current.addSymbol(new Symbol(child.getChild(0).getText(), child, nodes.ReferenceType.Rule)); } } }); + return true; } -} + public visitVariableDeclarationNode(node:nodes.VariableDeclaration):boolean { + this.addSymbol(node, ( node).getName(), nodes.ReferenceType.Variable); + return true; + } + + public visitDeclarationNode(node:nodes.Declaration):boolean { + if (Symbols.isCssVariable(node.getProperty().getIdentifier())) { + this.addCSSVariable(node.getProperty(), node.getProperty().getName(), nodes.ReferenceType.Variable); + } + return true; + } + + private addCSSVariable(node:nodes.Node, name:string, type: nodes.ReferenceType) : void { + if (node.offset !== -1) { + var globalScope = this.getGlobalScope(node, name, type); + globalScope.addSymbol(new Symbol(name, node, type)); + } + } + + private getGlobalScope(node:nodes.Node, name:string, type: nodes.ReferenceType): Scope { + let current = this.scope.findScope(node.offset, node.length); + while (current.parent !== null) { + current= current.parent; + } + return current; + } +} export class Symbols { @@ -253,6 +281,9 @@ export class Symbols { if (referenceTypes) { return referenceTypes; } else { + if (Symbols.isCssVariable(node)) { + return [ nodes.ReferenceType.Variable ]; + } // are a reference to a keyframe? var decl = nodes.getParentDeclaration(node); if (decl) { @@ -324,4 +355,8 @@ export class Symbols { } return null; } -} + + public static isCssVariable(identifier: nodes.Identifier):boolean { + return /^--/.test(identifier.getText()); + } +} \ No newline at end of file diff --git a/src/vs/languages/css/common/services/browsers.js b/src/vs/languages/css/common/services/browsers.js index ab1e928aac4..227bb6f2319 100644 --- a/src/vs/languages/css/common/services/browsers.js +++ b/src/vs/languages/css/common/services/browsers.js @@ -671,7 +671,7 @@ exports.data ={ "browsers": "E13,C,O15,S6" }, { - "name": "::-webkit-ouer-spin-button", + "name": "::-webkit-outer-spin-button", "browsers": "C,O,S6" }, { @@ -3978,7 +3978,7 @@ exports.data ={ }, { "name": "margin", - "desc": "Shorthand property to set values the thickness of the margin area. If left is omitted, it is the same as right. If bottom is omitted it is the same as top, if right is omitted it is the same as top. The value may not be negative.", + "desc": "Shorthand property to set values the thickness of the margin area. If left is omitted, it is the same as right. If bottom is omitted it is the same as top, if right is omitted it is the same as top.", "restriction": "length, percentage", "values": [ { @@ -4010,7 +4010,7 @@ exports.data ={ }, { "name": "margin-bottom", - "desc": "Shorthand property to set values the thickness of the margin area. If left is omitted, it is the same as right. If bottom is omitted it is the same as top, if right is omitted it is the same as top. The value may not be negative.", + "desc": "Shorthand property to set values the thickness of the margin area. If left is omitted, it is the same as right. If bottom is omitted it is the same as top, if right is omitted it is the same as top.", "restriction": "length, percentage", "values": [ { @@ -4042,7 +4042,7 @@ exports.data ={ }, { "name": "margin-left", - "desc": "Shorthand property to set values the thickness of the margin area. If left is omitted, it is the same as right. If bottom is omitted it is the same as top, if right is omitted it is the same as top. The value may not be negative.", + "desc": "Shorthand property to set values the thickness of the margin area. If left is omitted, it is the same as right. If bottom is omitted it is the same as top, if right is omitted it is the same as top.", "restriction": "length, percentage", "values": [ { @@ -4052,7 +4052,7 @@ exports.data ={ }, { "name": "margin-right", - "desc": "Shorthand property to set values the thickness of the margin area. If left is omitted, it is the same as right. If bottom is omitted it is the same as top, if right is omitted it is the same as top. The value may not be negative.", + "desc": "Shorthand property to set values the thickness of the margin area. If left is omitted, it is the same as right. If bottom is omitted it is the same as top, if right is omitted it is the same as top.", "restriction": "length, percentage", "values": [ { @@ -4062,7 +4062,7 @@ exports.data ={ }, { "name": "margin-top", - "desc": "Shorthand property to set values the thickness of the margin area. If left is omitted, it is the same as right. If bottom is omitted it is the same as top, if right is omitted it is the same as top. The value may not be negative.", + "desc": "Shorthand property to set values the thickness of the margin area. If left is omitted, it is the same as right. If bottom is omitted it is the same as top, if right is omitted it is the same as top.", "restriction": "length, percentage", "values": [ { diff --git a/src/vs/languages/css/common/services/cssLanguageService.ts b/src/vs/languages/css/common/services/cssLanguageService.ts index fec9131b99e..99669545561 100644 --- a/src/vs/languages/css/common/services/cssLanguageService.ts +++ b/src/vs/languages/css/common/services/cssLanguageService.ts @@ -10,6 +10,7 @@ import nodes = require('vs/languages/css/common/parser/cssNodes'); import parser = require('vs/languages/css/common/parser/cssParser'); import EditorCommon = require('vs/editor/common/editorCommon'); import resourceService = require('vs/editor/common/services/resourceService'); +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; interface Entry { node:nodes.Stylesheet; @@ -50,7 +51,7 @@ export class CSSLanguageService implements ILanguageService { private entries:{[url:string]:Entry;}; private activeDelay:PromiseWithTrigger; private onChangeHandle:number; - private callOnDispose:Function[]; + private callOnDispose:IDisposable[]; private createParser: () => parser.Parser; constructor(service:resourceService.IResourceService, createParser: () => parser.Parser, private _cssModeId:string) { @@ -60,15 +61,13 @@ export class CSSLanguageService implements ILanguageService { this.createParser = createParser; this.updateResources(); - this.callOnDispose.push(this.resourceService.addListener_(resourceService.ResourceEvents.ADDED, (e: resourceService.IResourceAddedEvent) => this.onResourceAdded(e))); - this.callOnDispose.push(this.resourceService.addListener_(resourceService.ResourceEvents.REMOVED, (e: resourceService.IResourceRemovedEvent) => this.onResourceRemoved(e))); - this.callOnDispose.push(this.resourceService.addListener_(resourceService.ResourceEvents.CHANGED, (e: resourceService.IResourceChangedEvent) => this.onResourceChange(e))); + this.callOnDispose.push(this.resourceService.addListener2_(resourceService.ResourceEvents.ADDED, (e: resourceService.IResourceAddedEvent) => this.onResourceAdded(e))); + this.callOnDispose.push(this.resourceService.addListener2_(resourceService.ResourceEvents.REMOVED, (e: resourceService.IResourceRemovedEvent) => this.onResourceRemoved(e))); + this.callOnDispose.push(this.resourceService.addListener2_(resourceService.ResourceEvents.CHANGED, (e: resourceService.IResourceChangedEvent) => this.onResourceChange(e))); } public dispose():void { - while(this.callOnDispose.length > 0) { - this.callOnDispose.pop()(); - } + this.callOnDispose = dispose(this.callOnDispose); clearTimeout(this.onChangeHandle); this.onChangeHandle = null; this.entries = null; @@ -126,7 +125,7 @@ export class CSSLanguageService implements ILanguageService { this.resourceService.all().filter((element) => this._isMyMirrorModel(element)).forEach((model:EditorCommon.IMirrorModel) => { // Reparse changes or new models - var url = model.getAssociatedResource().toString(), + var url = model.uri.toString(), entry = this.entries[url], hasEntry = typeof entry !== 'undefined'; diff --git a/src/vs/languages/css/common/services/intelliSense.ts b/src/vs/languages/css/common/services/intelliSense.ts index 7a98a76c519..bf75d9ac9f5 100644 --- a/src/vs/languages/css/common/services/intelliSense.ts +++ b/src/vs/languages/css/common/services/intelliSense.ts @@ -11,6 +11,7 @@ import service = require('vs/languages/css/common/services/cssLanguageService'); import URI from 'vs/base/common/uri'; import EditorCommon = require('vs/editor/common/editorCommon'); import Modes = require('vs/editor/common/modes'); +import strings = require('vs/base/common/strings'); import nls = require('vs/nls'); export class CSSIntellisense { @@ -73,9 +74,11 @@ export class CSSIntellisense { } else if (node instanceof nodes.Interpolation) { this.getCompletionsForInterpolation( node, result); } else if (node instanceof nodes.FunctionArgument) { - this.getCompletionsForFunctionArguments( node, result); + this.getCompletionsForFunctionArgument( node, node.getParent(), result); } else if (node instanceof nodes.FunctionDeclaration) { this.getCompletionsForFunctionDeclaration( node, result); + } else if (node instanceof nodes.Function) { + this.getCompletionsForFunctionArgument(null, node, result); } if (result.length > 0) { return { currentWord: this.currentWord, suggestions: result, incomplete: this.isIncomplete }; @@ -195,6 +198,21 @@ export class CSSIntellisense { public getVariableProposals(result:Modes.ISuggestion[]):Modes.ISuggestion[]{ var symbols = this.getSymbolContext().findSymbolsAtOffset(this.offset, nodes.ReferenceType.Variable); + symbols.forEach((symbol) => { + result.push({ + label: symbol.name, + codeSnippet: strings.startsWith(symbol.name, '--') ? `var(${symbol.name})` : symbol.name, + type: 'variable' + }); + }); + return result; + } + + public getVariableProposalsForCSSVarFunction(result:Modes.ISuggestion[]):Modes.ISuggestion[]{ + var symbols = this.getSymbolContext().findSymbolsAtOffset(this.offset, nodes.ReferenceType.Variable); + symbols= symbols.filter((symbol):boolean => { + return strings.startsWith(symbol.name, '--'); + }); symbols.forEach((symbol) => { result.push({ label: symbol.name, @@ -497,12 +515,14 @@ export class CSSIntellisense { if (!declarations) { // incomplete nodes return result; } + var node = declarations.findFirstChildBeforeOffset(this.offset); if (!node) { return this.getCompletionsForDeclarationProperty(result); } - if (node instanceof nodes.Declaration) { - var declaration = node; + + if (node instanceof nodes.AbstractDeclaration) { + var declaration = node; if ((!isDefined(declaration.colonPosition) || this.offset <= declaration.colonPosition) || (isDefined(declaration.semicolonPosition) && declaration.semicolonPosition < this.offset)) { if (this.offset === declaration.semicolonPosition + 1) { return result; // don't show new properties right after semicolon (see Bug 15421:[intellisense] [css] Be less aggressive when manually typing CSS) @@ -511,13 +531,15 @@ export class CSSIntellisense { // complete property return this.getCompletionsForDeclarationProperty(result); } - // complete value - return this.getCompletionsForDeclarationValue(declaration, result); + + if (declaration instanceof nodes.Declaration) { + // complete value + return this.getCompletionsForDeclarationValue(declaration, result); + } } return result; } - public getCompletionsForVariableDeclaration(declaration: nodes.VariableDeclaration, result:Modes.ISuggestion[]):Modes.ISuggestion[] { if (this.offset > declaration.colonPosition) { this.getVariableProposals(result); @@ -526,6 +548,11 @@ export class CSSIntellisense { } public getCompletionsForExpression(expression: nodes.Expression, result:Modes.ISuggestion[]):Modes.ISuggestion[]{ + if (expression.getParent() instanceof nodes.FunctionArgument) { + this.getCompletionsForFunctionArgument(expression.getParent(), expression.getParent().getParent(), result); + return result; + } + var declaration = expression.findParent(nodes.NodeType.Declaration); if (!declaration) { this.getTermProposals(result); @@ -542,7 +569,12 @@ export class CSSIntellisense { return result; } - public getCompletionsForFunctionArguments(arg: nodes.FunctionArgument, result: Modes.ISuggestion[]): Modes.ISuggestion[] { + public getCompletionsForFunctionArgument(arg: nodes.FunctionArgument, func: nodes.Function, result: Modes.ISuggestion[]): Modes.ISuggestion[] { + if (func.getIdentifier().getText() === 'var') { + if (!func.getArguments().hasChildren() || func.getArguments().getChild(0) === arg) { + this.getVariableProposalsForCSSVarFunction(result); + } + } return result; } diff --git a/src/vs/languages/css/common/services/occurrences.ts b/src/vs/languages/css/common/services/occurrences.ts index be2716f2156..eac2dd732c6 100644 --- a/src/vs/languages/css/common/services/occurrences.ts +++ b/src/vs/languages/css/common/services/occurrences.ts @@ -6,6 +6,7 @@ import nodes = require('vs/languages/css/common/parser/cssNodes'); import _symbols = require('vs/languages/css/common/parser/cssSymbols'); +import {DocumentHighlightKind} from 'vs/editor/common/modes'; export function findDeclaration(stylesheet:nodes.Node, offset:number):nodes.Node { @@ -25,7 +26,7 @@ export function findDeclaration(stylesheet:nodes.Node, offset:number):nodes.Node } export interface IOccurrence { - kind:string; + kind:DocumentHighlightKind; type:nodes.ReferenceType; node:nodes.Node; } @@ -66,10 +67,18 @@ export function findOccurrences(stylesheet:nodes.Node, offset:number):IOccurrenc return result; } -function getKind(node:nodes.Node):string { +function getKind(node:nodes.Node):DocumentHighlightKind { if (node.type === nodes.NodeType.Selector) { - return 'write'; + return DocumentHighlightKind.Write; + } + + if (node instanceof nodes.Identifier) { + if (node.parent && node.parent instanceof nodes.Property) { + if (_symbols.Symbols.isCssVariable(node)) { + return DocumentHighlightKind.Write; + } + } } if (node.parent) { @@ -79,8 +88,9 @@ function getKind(node:nodes.Node):string { case nodes.NodeType.Keyframe: case nodes.NodeType.VariableDeclaration: case nodes.NodeType.FunctionParameter: - return 'write'; + return DocumentHighlightKind.Write; } } - return null; + + return DocumentHighlightKind.Read; } \ No newline at end of file diff --git a/src/vs/languages/css/test/common/css-worker.test.ts b/src/vs/languages/css/test/common/css-worker.test.ts index ee0d236575b..43ec70606e6 100644 --- a/src/vs/languages/css/test/common/css-worker.test.ts +++ b/src/vs/languages/css/test/common/css-worker.test.ts @@ -74,7 +74,7 @@ suite('Validation - CSS', () => { var idx = stringBefore ? value.indexOf(stringBefore) + stringBefore.length : 0; var position = env.model.getPositionFromOffset(idx); - return env.worker.suggest(url, position).then(result => result[0]); + return env.worker.provideCompletionItems(url, position).then(result => result[0]); }; var testValueSetFor = function(value:string, selection:string, selectionLength: number, up: boolean):WinJS.TPromise { @@ -87,13 +87,13 @@ suite('Validation - CSS', () => { return env.worker.navigateValueSet(url, range, up); }; - var testOccurrences = function (value: string, tokenBefore: string): WinJS.TPromise<{ occurrences: Modes.IOccurence[]; model: mm.MirrorModel; }> { + var testOccurrences = function (value: string, tokenBefore: string): WinJS.TPromise<{ occurrences: Modes.DocumentHighlight[]; model: mm.MirrorModel; }> { var url = URI.parse('test://1'); var env = mockCSSWorkerEnv(url, value); var pos = env.model.getPositionFromOffset(value.indexOf(tokenBefore) + tokenBefore.length); - return env.worker.findOccurrences(url, pos).then((occurrences) => { return { occurrences: occurrences, model: env.model}; }); + return env.worker.provideDocumentHighlights(url, pos).then((occurrences) => { return { occurrences: occurrences, model: env.model}; }); }; var testQuickFixes = function (value: string, tokenBefore: string): WinJS.TPromise<{ fixes: Modes.IQuickFix[]; model: mm.MirrorModel; }> { @@ -105,7 +105,7 @@ suite('Validation - CSS', () => { var markers = env.markers.filter((m) => m.startColumn === pos.column && m.startLineNumber === pos.lineNumber); assert.equal(1, markers.length, 'No marker at pos: ' + JSON.stringify({ pos: pos, markers: env.markers })); - return env.worker.getQuickFixes(url, markers[0]).then((fixes) => { return { fixes: fixes, model: env.model}; }); + return env.worker.provideCodeActions(url, markers[0]).then((fixes) => { return { fixes: fixes, model: env.model}; }); }; var assertSuggestion= function(completion:Modes.ISuggestResult, label:string, type?:string) { @@ -121,7 +121,7 @@ suite('Validation - CSS', () => { assert.equal(result.value, expected); }; - var assertOccurrences= function(occurrences: Modes.IOccurence[], model: mm.MirrorModel , expectedNumber:number, expectedContent:string) { + var assertOccurrences= function(occurrences: Modes.DocumentHighlight[], model: mm.MirrorModel , expectedNumber:number, expectedContent:string) { assert.equal(occurrences.length, expectedNumber); occurrences.forEach((occurrence) => { assert.equal(model.getValueInRange(occurrence.range), expectedContent); diff --git a/src/vs/languages/css/test/common/parser.test.ts b/src/vs/languages/css/test/common/parser.test.ts index 56f7e8c7f2b..60c29e77ffb 100644 --- a/src/vs/languages/css/test/common/parser.test.ts +++ b/src/vs/languages/css/test/common/parser.test.ts @@ -10,7 +10,8 @@ import _parser = require('vs/languages/css/common/parser/cssParser'); import scanner = require('vs/languages/css/common/parser/cssScanner'); import nodes = require ('vs/languages/css/common/parser/cssNodes'); import errors = require('vs/languages/css/common/parser/cssErrors'); -export function assertNode(text: string, parser: _parser.Parser, f: ()=>nodes.Node):void { + +export function assertNode(text: string, parser: _parser.Parser, f: ()=>nodes.Node):nodes.Node { var node = parser.internalParse(text, f); assert.ok(node !== null, 'no node returned'); var markers = nodes.ParseErrorCollector.entries(node); @@ -18,6 +19,11 @@ export function assertNode(text: string, parser: _parser.Parser, f: ()=>nodes.No assert.ok(false, 'node has errors: ' + markers[0].getMessage() + ', offset: ' + markers[0].getNode().offset); } assert.ok(parser.accept(scanner.TokenType.EOF), 'Expect scanner at EOF'); + return node; +} + +export function assertFunction(text: string, parser: _parser.Parser, f: ()=>nodes.Node):void { + assertNode(text, parser, f); } export function assertNoNode(text: string, parser: _parser.Parser, f: ()=>nodes.Node):void { @@ -207,6 +213,13 @@ suite('CSS - Parser', () => { var parser = new _parser.Parser(); assertNode('asdsa', parser, parser._parseProperty.bind(parser)); assertNode('asdsa334', parser, parser._parseProperty.bind(parser)); + + assertNode('--color', parser, parser._parseProperty.bind(parser)); + assertNode('--primary-font', parser, parser._parseProperty.bind(parser)); + assertNode('-color', parser, parser._parseProperty.bind(parser)); + assertNode('somevar', parser, parser._parseProperty.bind(parser)); + assertNode('some--var', parser, parser._parseProperty.bind(parser)); + assertNode('somevar--', parser, parser._parseProperty.bind(parser)); }); test('Parser - Ruleset', function() { @@ -297,6 +310,16 @@ suite('CSS - Parser', () => { assertNode('*background: #f00 /* IE 7 and below */', parser, parser._parseDeclaration.bind(parser)); assertNode('_background: #f60 /* IE 6 and below */', parser, parser._parseDeclaration.bind(parser)); assertNode('background-image: linear-gradient(to right, silver, white 50px, white calc(100% - 50px), silver)', parser, parser._parseDeclaration.bind(parser)); + + assertNode('--color: #F5F5F5', parser, parser._parseDeclaration.bind(parser)); + assertNode('--color: 0', parser, parser._parseDeclaration.bind(parser)); + assertNode('--color: 255', parser, parser._parseDeclaration.bind(parser)); + assertNode('--color: 25.5', parser, parser._parseDeclaration.bind(parser)); + assertNode('--color: 25px', parser, parser._parseDeclaration.bind(parser)); + assertNode('--color: 25.5px', parser, parser._parseDeclaration.bind(parser)); + assertNode('--primary-font: "wf_SegoeUI","Segoe UI","Segoe","Segoe WP"', parser, parser._parseDeclaration.bind(parser)); + assertError('--color : ', parser, parser._parseDeclaration.bind(parser), errors.ParseError.PropertyValueExpected); + assertError('--color value', parser, parser._parseDeclaration.bind(parser), errors.ParseError.ColonExpected); }); @@ -335,6 +358,11 @@ suite('CSS - Parser', () => { assertNoNode('%()', parser, parser._parseFunction.bind(parser)); assertNoNode('% ()', parser, parser._parseFunction.bind(parser)); + assertFunction('var(--color)', parser, parser._parseFunction.bind(parser)); + assertFunction('var(--color, somevalue)', parser, parser._parseFunction.bind(parser)); + assertFunction('var(--variable1, --variable2)', parser, parser._parseFunction.bind(parser)); + assertFunction('var(--variable1, var(--variable2))', parser, parser._parseFunction.bind(parser)); + assertFunction('fun(value1, value2)', parser, parser._parseFunction.bind(parser)); }); test('Test Token prio', function() { @@ -372,5 +400,6 @@ suite('CSS - Parser', () => { assertNode('5/6', parser, parser._parseExpr.bind(parser)); assertNode('36mm, -webkit-calc(100%-10px)', parser, parser._parseExpr.bind(parser)); }); + }); diff --git a/src/vs/languages/css/test/common/scanner.test.ts b/src/vs/languages/css/test/common/scanner.test.ts index 56058e969b8..4652f9de7c2 100644 --- a/src/vs/languages/css/test/common/scanner.test.ts +++ b/src/vs/languages/css/test/common/scanner.test.ts @@ -280,4 +280,5 @@ suite('CSS - Token Sequences', () => { // assert.equal(tokCount, input.length); // assert.ok(d < 500, 'scanner fast? took ms' + d + ', token count ' + tokCount + ', input length: ' + inputText.length); // }); + }); diff --git a/src/vs/languages/css/test/common/symbols.test.ts b/src/vs/languages/css/test/common/symbols.test.ts index f056f8d40a4..d1a18a868fb 100644 --- a/src/vs/languages/css/test/common/symbols.test.ts +++ b/src/vs/languages/css/test/common/symbols.test.ts @@ -10,6 +10,7 @@ import nodes = require('vs/languages/css/common/parser/cssNodes'); import parser = require('vs/languages/css/common/parser/cssParser'); import occurrences = require('vs/languages/css/common/services/occurrences'); import workerTests = require('./css-worker.test'); +import * as modes from 'vs/editor/common/modes'; export function assertScopesAndSymbols(p: parser.Parser, input:string, expected:string):void { var global = createScope(p, input); @@ -29,7 +30,7 @@ export function assertOccurrences(p: parser.Parser, input:string, marker:string, var nWrites = 0; for (var index = 0; index < os.length; index++) { - if (os[index].kind === 'write') { + if (os[index].kind === modes.DocumentHighlightKind.Write) { nWrites++; } } @@ -51,7 +52,7 @@ export function assertSymbolsInScope(p: parser.Parser, input:string, offset:numb for (var i = 0; i < selections.length; i++) { var selection = selections[i]; - var sym = scope.getSymbol(selection.name, selection.type); + var sym = scope.getSymbol(selection.name, selection.type) || global.getSymbol(selection.name, selection.type); assert.ok(!!sym, getErrorMessage(selection.name)); } } @@ -167,4 +168,34 @@ suite('CSS - symbols', () => { assertOccurrences(p, '@keyframes id {}; #main { animation: /**/id 4s linear 0s infinite alternate; }', '/**/', 2, 1, nodes.ReferenceType.Keyframe); assertOccurrences(p, '@keyframes id {}; #main { animation-name: /**/id; foo: id;}', '/**/', 2, 1, nodes.ReferenceType.Keyframe); }); + + test('test variables in root scope', function() { + var p = new parser.Parser(); + assertSymbolsInScope(p, ':root{ --var1: abc; --var2: def; }', 0, {name:'--var1', type:nodes.ReferenceType.Variable}, {name:'--var2', type:nodes.ReferenceType.Variable}); + }); + + test('test variables in local scope', function() { + var p = new parser.Parser(); + assertSymbolsInScope(p, '.a{ --var1: abc; --var2: def; }', 2, {name:'--var1', type:nodes.ReferenceType.Variable}, {name:'--var2', type:nodes.ReferenceType.Variable}); + }); + + test('test variables in local scope get root variables too', function() { + var p = new parser.Parser(); + assertSymbolsInScope(p, '.a{ --var1: abc; } :root{ --var2: abc;}', 2, {name:'--var1', type:nodes.ReferenceType.Variable}, {name:'--var2', type:nodes.ReferenceType.Variable}); + }); + + test('test variables in local scope get root variables and other local variables too', function() { + var p = new parser.Parser(); + assertSymbolsInScope(p, '.a{ --var1: abc; } .b{ --var2: abc; } :root{ --var3: abc;}', 2, {name:'--var1', type:nodes.ReferenceType.Variable}, {name:'--var2', type:nodes.ReferenceType.Variable}, {name:'--var3', type:nodes.ReferenceType.Variable}); + }); + + test('mark occurrences for variable defined in root and used in a rule', function() { + var p = new parser.Parser(); + assertOccurrences(p, '.a{ background: var(--var1); } :root{ --var1: abc;}', '--var1', 2, 1, nodes.ReferenceType.Variable); + }); + + test('mark occurrences for variable defined in a rule and used in a different rule', function() { + var p = new parser.Parser(); + assertOccurrences(p, '.a{ background: var(--var1); } :b{ --var1: abc;}', '--var1', 2, 1, nodes.ReferenceType.Variable); + }); }); \ No newline at end of file diff --git a/src/vs/languages/handlebars/common/handlebars.ts b/src/vs/languages/handlebars/common/handlebars.ts index cbab656ff93..300ce3544ea 100644 --- a/src/vs/languages/handlebars/common/handlebars.ts +++ b/src/vs/languages/handlebars/common/handlebars.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import Modes = require('vs/editor/common/modes'); +import modes = require('vs/editor/common/modes'); import htmlMode = require('vs/languages/html/common/html'); import handlebarsTokenTypes = require('vs/languages/handlebars/common/handlebarsTokenTypes'); import htmlWorker = require('vs/languages/html/common/htmlWorker'); @@ -14,6 +14,7 @@ import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport'; import {createWordRegExp} from 'vs/editor/common/modes/abstractMode'; import {ILeavingNestedModeData} from 'vs/editor/common/modes/supports/tokenizationSupport'; import {IThreadService} from 'vs/platform/thread/common/thread'; +import {wireCancellationToken} from 'vs/base/common/async'; export enum States { HTML, @@ -23,7 +24,7 @@ export enum States { export class HandlebarsState extends htmlMode.State { - constructor(mode:Modes.IMode, + constructor(mode:modes.IMode, public kind:htmlMode.States, public handlebarsKind:States, public lastTagName:string, @@ -39,7 +40,7 @@ export class HandlebarsState extends htmlMode.State { return new HandlebarsState(this.getMode(), this.kind, this.handlebarsKind, this.lastTagName, this.lastAttributeName, this.embeddedContentType, this.attributeValueQuote, this.attributeValue); } - public equals(other:Modes.IState):boolean { + public equals(other:modes.IState):boolean { if (other instanceof HandlebarsState) { return ( super.equals(other) @@ -48,7 +49,7 @@ export class HandlebarsState extends htmlMode.State { return false; } - public tokenize(stream:Modes.IStream) : Modes.ITokenizationResult { + public tokenize(stream:modes.IStream) : modes.ITokenizationResult { switch(this.handlebarsKind) { case States.HTML: if (stream.advanceIfString('{{{').length > 0) { @@ -107,17 +108,48 @@ export class HandlebarsState extends htmlMode.State { export class HandlebarsMode extends htmlMode.HTMLMode { constructor( - descriptor:Modes.IModeDescriptor, + descriptor:modes.IModeDescriptor, @IInstantiationService instantiationService: IInstantiationService, @IModeService modeService: IModeService, @IThreadService threadService: IThreadService ) { super(descriptor, instantiationService, modeService, threadService); - - this.formattingSupport = null; } - protected _createRichEditSupport(): Modes.IRichEditSupport { + protected _registerSupports(): void { + modes.HoverProviderRegistry.register(this.getId(), { + provideHover: (model, position, token): Thenable => { + return wireCancellationToken(token, this._provideHover(model.uri, position)); + } + }, true); + + modes.ReferenceProviderRegistry.register(this.getId(), { + provideReferences: (model, position, context, token): Thenable => { + return wireCancellationToken(token, this._provideReferences(model.uri, position, context)); + } + }, true); + + modes.SuggestRegistry.register(this.getId(), { + triggerCharacters: ['.', ':', '<', '"', '=', '/'], + provideCompletionItems: (model, position, token): Thenable => { + return wireCancellationToken(token, this._provideCompletionItems(model.uri, position)); + } + }, true); + + modes.DocumentHighlightProviderRegistry.register(this.getId(), { + provideDocumentHighlights: (model, position, token): Thenable => { + return wireCancellationToken(token, this._provideDocumentHighlights(model.uri, position)); + } + }, true); + + modes.LinkProviderRegistry.register(this.getId(), { + provideLinks: (model, token): Thenable => { + return wireCancellationToken(token, this._provideLinks(model.uri)); + } + }, true); + } + + protected _createRichEditSupport(): modes.IRichEditSupport { return new RichEditSupport(this.getId(), null, { wordPattern: createWordRegExp('#-?%'), @@ -155,21 +187,21 @@ export class HandlebarsMode extends htmlMode.HTMLMode { { beforeText: new RegExp(`<(?!(?:${htmlMode.EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'), afterText: /^<\/(\w[\w\d]*)\s*>$/i, - action: { indentAction: Modes.IndentAction.IndentOutdent } + action: { indentAction: modes.IndentAction.IndentOutdent } }, { beforeText: new RegExp(`<(?!(?:${htmlMode.EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'), - action: { indentAction: Modes.IndentAction.Indent } + action: { indentAction: modes.IndentAction.Indent } } ], }); } - public getInitialState() : Modes.IState { + public getInitialState() : modes.IState { return new HandlebarsState(this, htmlMode.States.Content, States.HTML, '', '', '', '', ''); } - public getLeavingNestedModeData(line:string, state:Modes.IState):ILeavingNestedModeData { + public getLeavingNestedModeData(line:string, state:modes.IState):ILeavingNestedModeData { var leavingNestedModeData = super.getLeavingNestedModeData(line, state); if (leavingNestedModeData) { leavingNestedModeData.stateAfterNestedMode = new HandlebarsState(this, htmlMode.States.Content, States.HTML, '', '', '', '', ''); diff --git a/src/vs/languages/html/common/html.contribution.ts b/src/vs/languages/html/common/html.contribution.ts index 83652a91437..ebe40d140d6 100644 --- a/src/vs/languages/html/common/html.contribution.ts +++ b/src/vs/languages/html/common/html.contribution.ts @@ -11,7 +11,7 @@ import ConfigurationRegistry = require('vs/platform/configuration/common/configu ModesRegistry.registerCompatMode({ id: 'html', - extensions: ['.html', '.htm', '.shtml', '.mdoc', '.jsp', '.asp', '.aspx', '.jshtm'], + extensions: ['.html', '.htm', '.shtml', '.xhtml', '.mdoc', '.jsp', '.asp', '.aspx', '.jshtm'], aliases: ['HTML', 'htm', 'html', 'xhtml'], mimetypes: ['text/html', 'text/x-jshtm', 'text/template', 'text/ng-template'], moduleId: 'vs/languages/html/common/html', @@ -33,8 +33,8 @@ configurationRegistry.registerConfiguration({ }, 'html.format.unformatted': { 'type': ['string', 'null'], - 'default': null, - 'description': nls.localize('format.unformatted', "List of tags, comma separated, that shouldn't be reformatted. 'null' defaults to all inline tags."), + 'default': 'a, abbr, acronym, b, bdo, big, br, button, cite, code, dfn, em, i, img, input, kbd, label, map, object, q, samp, script, select, small, span, strong, sub, sup, textarea, tt, var', + 'description': nls.localize('format.unformatted', "List of tags, comma separated, that shouldn't be reformatted. 'null' defaults to all tags listed at https://www.w3.org/TR/html5/dom.html#phrasing-content."), }, 'html.format.indentInnerHtml': { 'type': 'boolean', @@ -63,7 +63,7 @@ configurationRegistry.registerConfiguration({ }, 'html.format.extraLiners': { 'type': ['string', 'null'], - 'default': null, + 'default': 'head, body, /html', 'description': nls.localize('format.extraLiners', "List of tags, comma separated, that should have an extra newline before them. 'null' defaults to \"head, body, /html\"."), }, } diff --git a/src/vs/languages/html/common/html.ts b/src/vs/languages/html/common/html.ts index adbc95bf164..29da5657d31 100644 --- a/src/vs/languages/html/common/html.ts +++ b/src/vs/languages/html/common/html.ts @@ -6,8 +6,8 @@ import URI from 'vs/base/common/uri'; import winjs = require('vs/base/common/winjs.base'); -import EditorCommon = require('vs/editor/common/editorCommon'); -import Modes = require('vs/editor/common/modes'); +import editorCommon = require('vs/editor/common/editorCommon'); +import modes = require('vs/editor/common/modes'); import htmlWorker = require('vs/languages/html/common/htmlWorker'); import { AbstractMode, createWordRegExp, ModeWorkerManager } from 'vs/editor/common/modes/abstractMode'; import { AbstractState } from 'vs/editor/common/modes/abstractState'; @@ -18,14 +18,11 @@ import * as htmlTokenTypes from 'vs/languages/html/common/htmlTokenTypes'; import {EMPTY_ELEMENTS} from 'vs/languages/html/common/htmlEmptyTagsShared'; import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport'; import {TokenizationSupport, IEnteringNestedModeData, ILeavingNestedModeData, ITokenizationCustomization} from 'vs/editor/common/modes/supports/tokenizationSupport'; -// import {DeclarationSupport} from 'vs/editor/common/modes/supports/declarationSupport'; -import {ReferenceSupport} from 'vs/editor/common/modes/supports/referenceSupport'; -import {ParameterHintsSupport} from 'vs/editor/common/modes/supports/parameterHintsSupport'; -import {SuggestSupport} from 'vs/editor/common/modes/supports/suggestSupport'; import {IThreadService} from 'vs/platform/thread/common/thread'; +import {wireCancellationToken} from 'vs/base/common/async'; -export { htmlTokenTypes }; // export to be used by Razor. We are the main module, so Razor should get ot from use. -export { EMPTY_ELEMENTS }; // export to be used by Razor. We are the main module, so Razor should get ot from use. +export { htmlTokenTypes }; // export to be used by Razor. We are the main module, so Razor should get it from us. +export { EMPTY_ELEMENTS }; // export to be used by Razor. We are the main module, so Razor should get it from us. export enum States { Content, @@ -52,7 +49,7 @@ export class State extends AbstractState { public attributeValueQuote:string; public attributeValue:string; - constructor(mode:Modes.IMode, kind:States, lastTagName:string, lastAttributeName:string, embeddedContentType:string, attributeValueQuote:string, attributeValue:string) { + constructor(mode:modes.IMode, kind:States, lastTagName:string, lastAttributeName:string, embeddedContentType:string, attributeValueQuote:string, attributeValue:string) { super(mode); this.kind = kind; this.lastTagName = lastTagName; @@ -70,7 +67,7 @@ export class State extends AbstractState { return new State(this.getMode(), this.kind, this.lastTagName, this.lastAttributeName, this.embeddedContentType, this.attributeValueQuote, this.attributeValue); } - public equals(other:Modes.IState):boolean { + public equals(other:modes.IState):boolean { if (other instanceof State) { return ( super.equals(other) && @@ -85,15 +82,15 @@ export class State extends AbstractState { return false; } - private nextElementName(stream:Modes.IStream):string { + private nextElementName(stream:modes.IStream):string { return stream.advanceIfRegExp(/^[_:\w][_:\w-.\d]*/).toLowerCase(); } - private nextAttributeName(stream:Modes.IStream):string { + private nextAttributeName(stream:modes.IStream):string { return stream.advanceIfRegExp(/^[^\s"'>/=\x00-\x0F\x7F\x80-\x9F]*/).toLowerCase(); } - public tokenize(stream:Modes.IStream) : Modes.ITokenizationResult { + public tokenize(stream:modes.IStream) : modes.ITokenizationResult { switch(this.kind){ case States.WithinComment: @@ -288,23 +285,16 @@ export class State extends AbstractState { export class HTMLMode extends AbstractMode implements ITokenizationCustomization { - public tokenizationSupport: Modes.ITokenizationSupport; - public richEditSupport: Modes.IRichEditSupport; - public linkSupport:Modes.ILinkSupport; - public extraInfoSupport:Modes.IExtraInfoSupport; - public occurrencesSupport:Modes.IOccurrencesSupport; - public referenceSupport: Modes.IReferenceSupport; - public formattingSupport: Modes.IFormattingSupport; - public parameterHintsSupport: Modes.IParameterHintsSupport; - public suggestSupport: Modes.ISuggestSupport; - public configSupport: Modes.IConfigurationSupport; + public tokenizationSupport: modes.ITokenizationSupport; + public richEditSupport: modes.IRichEditSupport; + public configSupport: modes.IConfigurationSupport; private modeService:IModeService; private threadService:IThreadService; private _modeWorkerManager: ModeWorkerManager; constructor( - descriptor:Modes.IModeDescriptor, + descriptor:modes.IModeDescriptor, @IInstantiationService instantiationService: IInstantiationService, @IModeService modeService: IModeService, @IThreadService threadService: IThreadService @@ -316,30 +306,11 @@ export class HTMLMode extends AbstractMode impl this.threadService = threadService; this.tokenizationSupport = new TokenizationSupport(this, this, true, true); - this.linkSupport = this; this.configSupport = this; - this.formattingSupport = this; - this.extraInfoSupport = this; - this.occurrencesSupport = this; - this.referenceSupport = new ReferenceSupport(this.getId(), { - tokens: ['invalid'], - findReferences: (resource, position, includeDeclaration) => this.findReferences(resource, position, includeDeclaration)}); - - this.parameterHintsSupport = new ParameterHintsSupport(this.getId(), { - triggerCharacters: ['(', ','], - excludeTokens: ['*'], - getParameterHints: (resource, position) => this.getParameterHints(resource, position)}); - // TODO@Alex TODO@Joh: there is something off about declaration support of embedded JS in HTML - // this.declarationSupport = new DeclarationSupport(this, { - // tokens: ['invalid'], - // findDeclaration: (resource, position) => this.findDeclaration(resource, position)}); - - this.suggestSupport = new SuggestSupport(this.getId(), { - triggerCharacters: ['.', ':', '<', '"', '=', '/'], - excludeTokens: ['comment'], - suggest: (resource, position) => this.suggest(resource, position)}); this.richEditSupport = this._createRichEditSupport(); + + this._registerSupports(); } public asyncCtor(): winjs.Promise { @@ -349,7 +320,50 @@ export class HTMLMode extends AbstractMode impl ]); } - protected _createModeWorkerManager(descriptor:Modes.IModeDescriptor, instantiationService: IInstantiationService): ModeWorkerManager { + protected _registerSupports(): void { + if (this.getId() !== 'html') { + throw new Error('This method must be overwritten!'); + } + + modes.HoverProviderRegistry.register(this.getId(), { + provideHover: (model, position, token): Thenable => { + return wireCancellationToken(token, this._provideHover(model.uri, position)); + } + }, true); + + modes.ReferenceProviderRegistry.register(this.getId(), { + provideReferences: (model, position, context, token): Thenable => { + return wireCancellationToken(token, this._provideReferences(model.uri, position, context)); + } + }, true); + + modes.SuggestRegistry.register(this.getId(), { + triggerCharacters: ['.', ':', '<', '"', '=', '/'], + provideCompletionItems: (model, position, token): Thenable => { + return wireCancellationToken(token, this._provideCompletionItems(model.uri, position)); + } + }, true); + + modes.DocumentHighlightProviderRegistry.register(this.getId(), { + provideDocumentHighlights: (model, position, token): Thenable => { + return wireCancellationToken(token, this._provideDocumentHighlights(model.uri, position)); + } + }, true); + + modes.DocumentRangeFormattingEditProviderRegistry.register(this.getId(), { + provideDocumentRangeFormattingEdits: (model, range, options, token): Thenable => { + return wireCancellationToken(token, this._provideDocumentRangeFormattingEdits(model.uri, range, options)); + } + }, true); + + modes.LinkProviderRegistry.register(this.getId(), { + provideLinks: (model, token): Thenable => { + return wireCancellationToken(token, this._provideLinks(model.uri)); + } + }, true); + } + + protected _createModeWorkerManager(descriptor:modes.IModeDescriptor, instantiationService: IInstantiationService): ModeWorkerManager { return new ModeWorkerManager(descriptor, 'vs/languages/html/common/htmlWorker', 'HTMLWorker', null, instantiationService); } @@ -357,7 +371,7 @@ export class HTMLMode extends AbstractMode impl return this._modeWorkerManager.worker(runner); } - protected _createRichEditSupport(): Modes.IRichEditSupport { + protected _createRichEditSupport(): modes.IRichEditSupport { return new RichEditSupport(this.getId(), null, { wordPattern: createWordRegExp('#-?%'), @@ -392,13 +406,13 @@ export class HTMLMode extends AbstractMode impl onEnterRules: [ { - beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'), - afterText: /^<\/(\w[\w\d]*)\s*>$/i, - action: { indentAction: Modes.IndentAction.IndentOutdent } + beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'), + afterText: /^<\/([_:\w][_:\w-.\d]*)\s*>$/i, + action: { indentAction: modes.IndentAction.IndentOutdent } }, { beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'), - action: { indentAction: Modes.IndentAction.Indent } + action: { indentAction: modes.IndentAction.Indent } } ], }); @@ -406,16 +420,16 @@ export class HTMLMode extends AbstractMode impl // TokenizationSupport - public getInitialState():Modes.IState { + public getInitialState():modes.IState { return new State(this, States.Content, '', '', '', '', ''); } - public enterNestedMode(state:Modes.IState):boolean { + public enterNestedMode(state:modes.IState):boolean { return state instanceof State && (state).kind === States.WithinEmbeddedContent; } - public getNestedMode(state:Modes.IState): IEnteringNestedModeData { - var result:Modes.IMode = null; + public getNestedMode(state:modes.IState): IEnteringNestedModeData { + var result:modes.IMode = null; var htmlState:State = state; var missingModePromise: winjs.Promise = null; @@ -446,7 +460,7 @@ export class HTMLMode extends AbstractMode impl }; } - public getLeavingNestedModeData(line:string, state:Modes.IState):ILeavingNestedModeData { + public getLeavingNestedModeData(line:string, state:modes.IState):ILeavingNestedModeData { var tagName = (state).lastTagName; var regexp = new RegExp('<\\/' + tagName + '\\s*>', 'i'); var match:any = regexp.exec(line); @@ -473,48 +487,38 @@ export class HTMLMode extends AbstractMode impl return this._worker((w) => w._doConfigure(options)); } - static $computeLinks = OneWorkerAttr(HTMLMode, HTMLMode.prototype.computeLinks); - public computeLinks(resource:URI):winjs.TPromise { - return this._worker((w) => w.computeLinks(resource)); + static $_provideLinks = OneWorkerAttr(HTMLMode, HTMLMode.prototype._provideLinks); + protected _provideLinks(resource:URI):winjs.TPromise { + return this._worker((w) => w.provideLinks(resource)); } - static $formatRange = OneWorkerAttr(HTMLMode, HTMLMode.prototype.formatRange); - public formatRange(resource:URI, range:EditorCommon.IRange, options:Modes.IFormattingOptions):winjs.TPromise { - return this._worker((w) => w.format(resource, range, options)); + static $_provideDocumentRangeFormattingEdits = OneWorkerAttr(HTMLMode, HTMLMode.prototype._provideDocumentRangeFormattingEdits); + private _provideDocumentRangeFormattingEdits(resource:URI, range:editorCommon.IRange, options:modes.IFormattingOptions):winjs.TPromise { + return this._worker((w) => w.provideDocumentRangeFormattingEdits(resource, range, options)); } - static $computeInfo = OneWorkerAttr(HTMLMode, HTMLMode.prototype.computeInfo); - public computeInfo(resource:URI, position:EditorCommon.IPosition): winjs.TPromise { - return this._worker((w) => w.computeInfo(resource, position)); + static $_provideHover = OneWorkerAttr(HTMLMode, HTMLMode.prototype._provideHover); + protected _provideHover(resource:URI, position:editorCommon.IPosition): winjs.TPromise { + return this._worker((w) => w.provideHover(resource, position)); } - static $findReferences = OneWorkerAttr(HTMLMode, HTMLMode.prototype.findReferences); - public findReferences(resource:URI, position:EditorCommon.IPosition, includeDeclaration:boolean): winjs.TPromise { - return this._worker((w) => w.findReferences(resource, position, includeDeclaration)); + static $_provideReferences = OneWorkerAttr(HTMLMode, HTMLMode.prototype._provideReferences); + protected _provideReferences(resource:URI, position:editorCommon.IPosition, context: modes.ReferenceContext): winjs.TPromise { + return this._worker((w) => w.provideReferences(resource, position)); } - static $findDeclaration = OneWorkerAttr(HTMLMode, HTMLMode.prototype.findDeclaration); - public findDeclaration(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { - return this._worker((w) => w.findDeclaration(resource, position)); + static $_provideDocumentHighlights = OneWorkerAttr(HTMLMode, HTMLMode.prototype._provideDocumentHighlights); + protected _provideDocumentHighlights(resource:URI, position:editorCommon.IPosition, strict:boolean = false): winjs.TPromise { + return this._worker((w) => w.provideDocumentHighlights(resource, position, strict)); } - static $findOccurrences = OneWorkerAttr(HTMLMode, HTMLMode.prototype.findOccurrences); - public findOccurrences(resource:URI, position:EditorCommon.IPosition, strict:boolean = false): winjs.TPromise { - return this._worker((w) => w.findOccurrences(resource, position, strict)); - } - - static $suggest = OneWorkerAttr(HTMLMode, HTMLMode.prototype.suggest); - public suggest(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { - return this._worker((w) => w.suggest(resource, position)); + static $_provideCompletionItems = OneWorkerAttr(HTMLMode, HTMLMode.prototype._provideCompletionItems); + protected _provideCompletionItems(resource:URI, position:editorCommon.IPosition):winjs.TPromise { + return this._worker((w) => w.provideCompletionItems(resource, position)); } static $findColorDeclarations = OneWorkerAttr(HTMLMode, HTMLMode.prototype.findColorDeclarations); - public findColorDeclarations(resource:URI):winjs.TPromise<{range:EditorCommon.IRange; value:string; }[]> { + public findColorDeclarations(resource:URI):winjs.TPromise<{range:editorCommon.IRange; value:string; }[]> { return this._worker((w) => w.findColorDeclarations(resource)); } - - static $getParameterHints = OneWorkerAttr(HTMLMode, HTMLMode.prototype.getParameterHints); - public getParameterHints(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { - return this._worker((w) => w.getParameterHints(resource, position)); - } } diff --git a/src/vs/languages/html/common/htmlWorker.ts b/src/vs/languages/html/common/htmlWorker.ts index 2685061bc75..c82441f4cb0 100644 --- a/src/vs/languages/html/common/htmlWorker.ts +++ b/src/vs/languages/html/common/htmlWorker.ts @@ -9,8 +9,8 @@ import winjs = require('vs/base/common/winjs.base'); import beautifyHTML = require('vs/languages/lib/common/beautify-html'); import htmlTags = require('vs/languages/html/common/htmlTags'); import network = require('vs/base/common/network'); -import EditorCommon = require('vs/editor/common/editorCommon'); -import Modes = require('vs/editor/common/modes'); +import editorCommon = require('vs/editor/common/editorCommon'); +import modes = require('vs/editor/common/modes'); import strings = require('vs/base/common/strings'); import {Position} from 'vs/editor/common/core/position'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; @@ -21,6 +21,9 @@ import {isTag, DELIM_END, DELIM_START, DELIM_ASSIGN, ATTRIB_NAME, ATTRIB_VALUE} import {isEmptyElement} from 'vs/languages/html/common/htmlEmptyTagsShared'; import {filterSuggestions} from 'vs/editor/common/modes/supports/suggestSupport'; import paths = require('vs/base/common/paths'); +import {getHover} from 'vs/editor/contrib/hover/common/hover'; +import {provideReferences} from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; +import {provideCompletionItems} from 'vs/editor/contrib/suggest/common/suggest'; enum LinkDetectionState { LOOKING_FOR_HREF_OR_SRC = 1, @@ -28,7 +31,7 @@ enum LinkDetectionState { } interface IColorRange { - range:EditorCommon.IRange; + range:editorCommon.IRange; value:string; } @@ -64,17 +67,11 @@ export class HTMLWorker { providers.push(htmlTags.getIonicTagProvider()); } - public format(resource: URI, range: EditorCommon.IRange, options: Modes.IFormattingOptions): winjs.TPromise { - return this._delegateToModeAtPosition(resource, Position.startPosition(range), (isEmbeddedMode, model) => { - if (isEmbeddedMode && model.getMode().formattingSupport) { - return model.getMode().formattingSupport.formatRange(model.getAssociatedResource(), range, options); - } - - return this.formatHTML(resource, range, options); - }); + public provideDocumentRangeFormattingEdits(resource: URI, range: editorCommon.IRange, options: modes.IFormattingOptions): winjs.TPromise { + return this.formatHTML(resource, range, options); } - private formatHTML(resource: URI, range: EditorCommon.IRange, options: Modes.IFormattingOptions): winjs.TPromise { + private formatHTML(resource: URI, range: editorCommon.IRange, options: modes.IFormattingOptions): winjs.TPromise { let model = this.resourceService.get(resource); let value = range ? model.getValueInRange(range) : model.getValue(); @@ -111,8 +108,11 @@ export class HTMLWorker { private getTagsFormatOption(key: string, dflt: string[]): string[] { let list = this.getFormatOption(key, null); - if (list) { - return list.split(',').map(t => t.trim().toLowerCase()); + if (typeof list === 'string') { + if (list.length > 0) { + return list.split(',').map(t => t.trim().toLowerCase()); + } + return []; } return dflt; } @@ -122,7 +122,7 @@ export class HTMLWorker { return winjs.TPromise.as(null); } - _delegateToModeAtPosition(resource:URI, position:EditorCommon.IPosition, callback:(isEmbeddedMode:boolean, model:EditorCommon.IMirrorModel) => T): T { + _delegateToModeAtPosition(resource:URI, position:editorCommon.IPosition, callback:(isEmbeddedMode:boolean, model:editorCommon.IMirrorModel) => T): T { let model = this.resourceService.get(resource); if (!model) { @@ -140,7 +140,7 @@ export class HTMLWorker { return callback(modeAtPosition.getId() !== this._modeId, modelAtPosition); } - _delegateToAllModes(resource:URI, callback:(models:EditorCommon.IMirrorModel[]) => T): T { + _delegateToAllModes(resource:URI, callback:(models:editorCommon.IMirrorModel[]) => T): T { let model = this.resourceService.get(resource); if (!model) { @@ -150,37 +150,31 @@ export class HTMLWorker { return callback(model.getAllEmbedded()); } - public computeInfo(resource:URI, position:EditorCommon.IPosition): winjs.TPromise { + public provideHover(resource:URI, position:editorCommon.IPosition): winjs.TPromise { return this._delegateToModeAtPosition(resource, position, (isEmbeddedMode, model) => { - if (isEmbeddedMode && model.getMode().extraInfoSupport) { - return model.getMode().extraInfoSupport.computeInfo(model.getAssociatedResource(), position); + if (isEmbeddedMode) { + return getHover(model, Position.lift(position)).then((r) => { + return (r.length > 0 ? r[0] : null); + }); } }); } - public findReferences(resource:URI, position:EditorCommon.IPosition, includeDeclaration:boolean): winjs.TPromise { + public provideReferences(resource:URI, position:editorCommon.IPosition): winjs.TPromise { return this._delegateToModeAtPosition(resource, position, (isEmbeddedMode, model) => { - if (isEmbeddedMode && model.getMode().referenceSupport) { - return model.getMode().referenceSupport.findReferences(model.getAssociatedResource(), position, includeDeclaration); + if (isEmbeddedMode) { + return provideReferences(model, Position.lift(position)); } }); } - public findDeclaration(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { - return this._delegateToModeAtPosition(resource, position, (isEmbeddedMode, model) => { - if (isEmbeddedMode && model.getMode().declarationSupport) { - return model.getMode().declarationSupport.findDeclaration(model.getAssociatedResource(), position); - } - }); - } - - public findColorDeclarations(resource:URI):winjs.TPromise<{range:EditorCommon.IRange; value:string; }[]> { + public findColorDeclarations(resource:URI):winjs.TPromise<{range:editorCommon.IRange; value:string; }[]> { return this._delegateToAllModes(resource, (models) => { let allPromises: winjs.TPromise[] = []; allPromises = models .filter((model) => (typeof model.getMode()['findColorDeclarations'] === 'function')) - .map((model) => model.getMode()['findColorDeclarations'](model.getAssociatedResource())); + .map((model) => model.getMode()['findColorDeclarations'](model.uri)); return winjs.TPromise.join(allPromises).then((results:IColorRange[][]) => { let result:IColorRange[] = []; @@ -192,14 +186,6 @@ export class HTMLWorker { }); } - public getParameterHints(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { - return this._delegateToModeAtPosition(resource, position, (isEmbeddedMode, model) => { - if (isEmbeddedMode && model.getMode().parameterHintsSupport) { - return model.getMode().parameterHintsSupport.getParameterHints(model.getAssociatedResource(), position); - } - }); - } - private findMatchingOpenTag(scanner: IHTMLScanner) : string { let closedTags : { [name:string]: number } = {}; let tagClosed = false; @@ -223,7 +209,7 @@ export class HTMLWorker { return null; } - private collectTagSuggestions(scanner: IHTMLScanner, position: EditorCommon.IPosition, suggestions: Modes.ISuggestResult): void { + private collectTagSuggestions(scanner: IHTMLScanner, position: editorCommon.IPosition, suggestions: modes.ISuggestResult): void { let model = scanner.getModel(); let currentLine = model.getLineContent(position.lineNumber); let contentAfter = currentLine.substr(position.column - 1); @@ -233,7 +219,7 @@ export class HTMLWorker { let endPosition = scanner.getTokenPosition(); let matchingTag = this.findMatchingOpenTag(scanner); if (matchingTag) { - let suggestion : Modes.ISuggestion = { + let suggestion : modes.ISuggestion = { label: '/' + matchingTag, codeSnippet: '/' + matchingTag + closeTag, overwriteBefore: overwriteBefore, @@ -290,11 +276,11 @@ export class HTMLWorker { } - private collectContentSuggestions(suggestions: Modes.ISuggestResult): void { + private collectContentSuggestions(suggestions: modes.ISuggestResult): void { // disable the simple snippets in favor of the emmet templates } - private collectAttributeSuggestions(scanner: IHTMLScanner, suggestions: Modes.ISuggestResult): void { + private collectAttributeSuggestions(scanner: IHTMLScanner, suggestions: modes.ISuggestResult): void { let parentTag: string = null; do { if (isTag(scanner.getTokenType())) { @@ -321,7 +307,7 @@ export class HTMLWorker { }); } - private collectAttributeValueSuggestions(scanner: IHTMLScanner, suggestions: Modes.ISuggestResult): void { + private collectAttributeValueSuggestions(scanner: IHTMLScanner, suggestions: modes.ISuggestResult): void { let needsQuotes = scanner.getTokenType() === DELIM_ASSIGN; let attribute: string = null; @@ -353,26 +339,26 @@ export class HTMLWorker { }); } - public suggest(resource:URI, position:EditorCommon.IPosition, triggerCharacter?:string):winjs.TPromise { + public provideCompletionItems(resource:URI, position:editorCommon.IPosition):winjs.TPromise { return this._delegateToModeAtPosition(resource, position, (isEmbeddedMode, model) => { - if (isEmbeddedMode && model.getMode().suggestSupport) { - return model.getMode().suggestSupport.suggest(model.getAssociatedResource(), position, triggerCharacter); + if (isEmbeddedMode) { + return provideCompletionItems(model, Position.lift(position)); } return this.suggestHTML(resource, position); }); } - private suggestHTML(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { + private suggestHTML(resource:URI, position:editorCommon.IPosition):winjs.TPromise { return this.doSuggest(resource, position).then(value => filterSuggestions(value)); } - private doSuggest(resource: URI, position: EditorCommon.IPosition): winjs.TPromise { + private doSuggest(resource: URI, position: editorCommon.IPosition): winjs.TPromise { let model = this.resourceService.get(resource), currentWord = model.getWordUntilPosition(position).word; - let suggestions: Modes.ISuggestResult = { + let suggestions: modes.ISuggestResult = { currentWord: currentWord, suggestions: [], }; @@ -434,7 +420,7 @@ export class HTMLWorker { return winjs.TPromise.as(suggestions); } - private findMatchingBracket(tagname: string, scanner: IHTMLScanner) : EditorCommon.IRange { + private findMatchingBracket(tagname: string, scanner: IHTMLScanner) : editorCommon.IRange { if (isEmptyElement(tagname)) { return null; } @@ -490,34 +476,25 @@ export class HTMLWorker { } - public findOccurrences(resource:URI, position:EditorCommon.IPosition, strict:boolean = false): winjs.TPromise { - return this._delegateToModeAtPosition(resource, position, (isEmbeddedMode, model) => { - if (isEmbeddedMode && model.getMode().occurrencesSupport) { - return model.getMode().occurrencesSupport.findOccurrences(model.getAssociatedResource(), position, strict); - } - - return this.findOccurrencesHTML(resource, position, strict); - }); - } - - public findOccurrencesHTML(resource:URI, position:EditorCommon.IPosition, strict?:boolean):winjs.TPromise { - + public provideDocumentHighlights(resource:URI, position:editorCommon.IPosition, strict:boolean = false): winjs.TPromise { let model = this.resourceService.get(resource), wordAtPosition = model.getWordAtPosition(position), currentWord = (wordAtPosition ? wordAtPosition.word : ''), - result:Modes.IOccurence[] = []; + result:modes.DocumentHighlight[] = []; let scanner = getScanner(model, position); if (isTag(scanner.getTokenType())) { let tagname = scanner.getTokenContent(); result.push({ - range: scanner.getTokenRange() + range: scanner.getTokenRange(), + kind: modes.DocumentHighlightKind.Read }); let range = this.findMatchingBracket(tagname, scanner); if (range) { result.push({ - range: range + range: range, + kind: modes.DocumentHighlightKind.Read }); } } else { @@ -527,7 +504,8 @@ export class HTMLWorker { for(let i = 0; i < upperBound; i++) { if(words[i].text === currentWord) { result.push({ - range: words[i].range + range: words[i].range, + kind: modes.DocumentHighlightKind.Read }); } } @@ -587,7 +565,7 @@ export class HTMLWorker { return potentialResult; } - private createLink(modelAbsoluteUrl: URI, rootAbsoluteUrl: URI, tokenContent: string, lineNumber: number, startColumn: number, endColumn: number): Modes.ILink { + private createLink(modelAbsoluteUrl: URI, rootAbsoluteUrl: URI, tokenContent: string, lineNumber: number, startColumn: number, endColumn: number): modes.ILink { let workspaceUrl = HTMLWorker._getWorkspaceUrl(modelAbsoluteUrl, rootAbsoluteUrl, tokenContent); if (!workspaceUrl) { return null; @@ -605,21 +583,21 @@ export class HTMLWorker { }; } - private _computeHTMLLinks(model: EditorCommon.IMirrorModel): Modes.ILink[] { + private _computeHTMLLinks(model: editorCommon.IMirrorModel): modes.ILink[] { let lineCount = model.getLineCount(), - newLinks: Modes.ILink[] = [], + newLinks: modes.ILink[] = [], state: LinkDetectionState = LinkDetectionState.LOOKING_FOR_HREF_OR_SRC, - modelAbsoluteUrl = model.getAssociatedResource(), + modelAbsoluteUrl = model.uri, lineNumber: number, lineContent: string, lineContentLength: number, - tokens: EditorCommon.ILineTokens, + tokens: editorCommon.ILineTokens, tokenType: string, tokensLength: number, i: number, nextTokenEndIndex: number, tokenContent: string, - link: Modes.ILink; + link: modes.ILink; let rootAbsoluteUrl: URI = null; let workspace = this._contextService.getWorkspace(); @@ -684,7 +662,7 @@ export class HTMLWorker { return newLinks; } - public computeLinks(resource: URI): winjs.TPromise { + public provideLinks(resource: URI): winjs.TPromise { let model = this.resourceService.get(resource); return winjs.TPromise.as(this._computeHTMLLinks(model)); } diff --git a/src/vs/languages/html/test/common/html-worker.test.ts b/src/vs/languages/html/test/common/html-worker.test.ts index 2c232f560c8..242b757fd00 100644 --- a/src/vs/languages/html/test/common/html-worker.test.ts +++ b/src/vs/languages/html/test/common/html-worker.test.ts @@ -71,7 +71,7 @@ suite('HTML - worker', () => { var env = mockHtmlWorkerEnv(url, content); var position = env.model.getPositionFromOffset(idx); - return env.worker.suggest(url, position).then(result => result[0]); + return env.worker.provideCompletionItems(url, position).then(result => result[0]); }; var assertSuggestion = function(completion: Modes.ISuggestResult, label: string, type?: string, codeSnippet?: string) { diff --git a/src/vs/languages/html/test/common/html.test.ts b/src/vs/languages/html/test/common/html.test.ts index 815d37c56d2..45c56182f8f 100644 --- a/src/vs/languages/html/test/common/html.test.ts +++ b/src/vs/languages/html/test/common/html.test.ts @@ -749,7 +749,7 @@ suite('Colorizing - HTML', () => { test('matchBracket', () => { - function toString(brackets:[EditorCommon.IEditorRange, EditorCommon.IEditorRange]): [string,string] { + function toString(brackets:[Range, Range]): [string,string] { if (!brackets) { return null; } @@ -757,7 +757,7 @@ suite('Colorizing - HTML', () => { return [brackets[0].toString(), brackets[1].toString()]; } - function assertBracket(lines:string[], lineNumber:number, column:number, expected:[EditorCommon.IEditorRange, EditorCommon.IEditorRange]): void { + function assertBracket(lines:string[], lineNumber:number, column:number, expected:[Range, Range]): void { let model = new TextModelWithTokens([], TextModel.toRawText(lines.join('\n'), TextModel.DEFAULT_CREATION_OPTIONS), false, _mode); // force tokenization model.getLineContext(model.getLineCount()); diff --git a/src/vs/languages/json/common/features/jsonFormatter.ts b/src/vs/languages/json/common/features/jsonFormatter.ts deleted file mode 100644 index 22afdd07983..00000000000 --- a/src/vs/languages/json/common/features/jsonFormatter.ts +++ /dev/null @@ -1,147 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import strings = require('vs/base/common/strings'); -import Json = require('vs/base/common/json'); -import EditorCommon = require('vs/editor/common/editorCommon'); -import Modes = require('vs/editor/common/modes'); - -export function format(model: EditorCommon.IMirrorModel, range: EditorCommon.IRange, options: Modes.IFormattingOptions): EditorCommon.ISingleEditOperation[] { - var initialIndentLevel: number; - var value: string; - var rangeOffset: number; - if (range) { - range = { startLineNumber: range.startLineNumber, startColumn: 1, endLineNumber: range.endLineNumber, endColumn: model.getLineMaxColumn(range.endLineNumber) }; // extend to full range - initialIndentLevel = computeIndentLevel(model.getLineContent(range.startLineNumber), options); - value = model.getValueInRange(range); - rangeOffset = model.getOffsetFromPosition({ lineNumber: range.startLineNumber, column: range.startColumn }); - } else { - range = model.getFullModelRange(); - initialIndentLevel = 0; - value = model.getValue(); - rangeOffset = 0; - } - - var lineBreak = false; - var indentLevel = 0; - var indentValue: string; - if (options.insertSpaces) { - indentValue = strings.repeat(' ', options.tabSize); - } else { - indentValue = '\t'; - } - - var scanner = Json.createScanner(value, false); - - function newLineAndIndent(): string { - return model.getEOL() + strings.repeat(indentValue, initialIndentLevel + indentLevel); - } - function scanNext(): Json.SyntaxKind { - var token = scanner.scan(); - lineBreak = false; - while (token === Json.SyntaxKind.Trivia || token === Json.SyntaxKind.LineBreakTrivia) { - lineBreak = lineBreak || (token === Json.SyntaxKind.LineBreakTrivia); - token = scanner.scan(); - } - return token; - } - var editOperations: EditorCommon.ISingleEditOperation[] = []; - function addEdit(text: string, range: EditorCommon.IRange) { - if (model.getValueInRange(range) !== text) { - editOperations.push({ range: range, text: text }); - } - } - - var firstToken = scanNext(); - if (firstToken !== Json.SyntaxKind.EOF) { - var firstTokenStart = model.getPositionFromOffset(scanner.getTokenOffset() + rangeOffset); - var initialIndent = strings.repeat(indentValue, initialIndentLevel); - addEdit(initialIndent, { startLineNumber: range.startLineNumber, startColumn: range.startColumn, endLineNumber: firstTokenStart.lineNumber, endColumn: firstTokenStart.column }); - } - - while (firstToken !== Json.SyntaxKind.EOF) { - var firstTokenEnd = model.getPositionFromOffset(scanner.getTokenOffset() + scanner.getTokenLength() + rangeOffset); - var secondToken = scanNext(); - - let replaceContent = ''; - while (!lineBreak && (secondToken === Json.SyntaxKind.LineCommentTrivia || secondToken === Json.SyntaxKind.BlockCommentTrivia)) { - // comments on the same line: keep them on the same line, but ignore them otherwise - var commentTokenStart = model.getPositionFromOffset(scanner.getTokenOffset() + rangeOffset); - addEdit(' ', { startLineNumber: firstTokenEnd.lineNumber, startColumn: firstTokenEnd.column, endLineNumber: commentTokenStart.lineNumber, endColumn: commentTokenStart.column }); - firstTokenEnd = model.getPositionFromOffset(scanner.getTokenOffset() + scanner.getTokenLength() + rangeOffset); - replaceContent = secondToken === Json.SyntaxKind.LineCommentTrivia ? newLineAndIndent() : ''; - secondToken = scanNext(); - } - if (secondToken === Json.SyntaxKind.CloseBraceToken) { - if (firstToken !== Json.SyntaxKind.OpenBraceToken) { - indentLevel--; - replaceContent = newLineAndIndent(); - } - } else if (secondToken === Json.SyntaxKind.CloseBracketToken) { - if (firstToken !== Json.SyntaxKind.OpenBracketToken) { - indentLevel--; - replaceContent = newLineAndIndent(); - } - } else { - switch (firstToken) { - case Json.SyntaxKind.OpenBracketToken: - case Json.SyntaxKind.OpenBraceToken: - indentLevel++; - replaceContent = newLineAndIndent(); - break; - case Json.SyntaxKind.CommaToken: - case Json.SyntaxKind.LineCommentTrivia: - replaceContent = newLineAndIndent(); - break; - case Json.SyntaxKind.BlockCommentTrivia: - if (lineBreak) { - replaceContent = newLineAndIndent(); - } else { - // symbol following comment on the same line: keep on same line, separate with ' ' - replaceContent = ' '; - } - break; - case Json.SyntaxKind.ColonToken: - replaceContent = ' '; - break; - case Json.SyntaxKind.NullKeyword: - case Json.SyntaxKind.TrueKeyword: - case Json.SyntaxKind.FalseKeyword: - case Json.SyntaxKind.NumericLiteral: - if (secondToken === Json.SyntaxKind.NullKeyword || secondToken === Json.SyntaxKind.FalseKeyword || secondToken === Json.SyntaxKind.NumericLiteral) { - replaceContent = ' '; - } - break; - } - if (lineBreak && (secondToken === Json.SyntaxKind.LineCommentTrivia || secondToken === Json.SyntaxKind.BlockCommentTrivia)) { - replaceContent = newLineAndIndent(); - } - - } - var secondTokenStart = model.getPositionFromOffset(scanner.getTokenOffset() + rangeOffset); - addEdit(replaceContent, { startLineNumber: firstTokenEnd.lineNumber, startColumn: firstTokenEnd.column, endLineNumber: secondTokenStart.lineNumber, endColumn: secondTokenStart.column }); - firstToken = secondToken; - } - return editOperations; -} - -function computeIndentLevel(line: string, options: Modes.IFormattingOptions): number { - var i = 0; - var nChars = 0; - var tabSize = options.tabSize || 4; - while (i < line.length) { - var ch = line.charAt(i); - if (ch === ' ') { - nChars++; - } else if (ch === '\t') { - nChars += tabSize; - } else { - break; - } - i++; - } - return Math.floor(nChars / tabSize); -} \ No newline at end of file diff --git a/src/vs/languages/json/common/json.ts b/src/vs/languages/json/common/json.ts index 95fb6f4e32f..e250f0ca23d 100644 --- a/src/vs/languages/json/common/json.ts +++ b/src/vs/languages/json/common/json.ts @@ -4,12 +4,11 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import EditorCommon = require('vs/editor/common/editorCommon'); -import Modes = require('vs/editor/common/modes'); +import editorCommon = require('vs/editor/common/editorCommon'); +import modes = require('vs/editor/common/modes'); import URI from 'vs/base/common/uri'; import WinJS = require('vs/base/common/winjs.base'); import Platform = require('vs/platform/platform'); -import nls = require('vs/nls'); import jsonWorker = require('vs/languages/json/common/jsonWorker'); import tokenization = require('vs/languages/json/common/features/tokenization'); import {AbstractMode, createWordRegExp, ModeWorkerManager} from 'vs/editor/common/modes/abstractMode'; @@ -18,26 +17,20 @@ import {IThreadService, ThreadAffinity} from 'vs/platform/thread/common/thread'; import {IJSONContributionRegistry, Extensions, ISchemaContributions} from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport'; -import {SuggestSupport} from 'vs/editor/common/modes/supports/suggestSupport'; +import {wireCancellationToken} from 'vs/base/common/async'; -export class JSONMode extends AbstractMode implements Modes.IExtraInfoSupport, Modes.IOutlineSupport { +export class JSONMode extends AbstractMode { - public tokenizationSupport: Modes.ITokenizationSupport; - public richEditSupport: Modes.IRichEditSupport; - public configSupport:Modes.IConfigurationSupport; - public inplaceReplaceSupport:Modes.IInplaceReplaceSupport; - public extraInfoSupport: Modes.IExtraInfoSupport; - public outlineSupport: Modes.IOutlineSupport; - public formattingSupport: Modes.IFormattingSupport; - public suggestSupport: Modes.ISuggestSupport; - - public outlineGroupLabel : { [name: string]: string; }; + public tokenizationSupport: modes.ITokenizationSupport; + public richEditSupport: modes.IRichEditSupport; + public configSupport:modes.IConfigurationSupport; + public inplaceReplaceSupport:modes.IInplaceReplaceSupport; private _modeWorkerManager: ModeWorkerManager; private _threadService:IThreadService; constructor( - descriptor:Modes.IModeDescriptor, + descriptor:modes.IModeDescriptor, @IInstantiationService instantiationService: IInstantiationService, @IThreadService threadService: IThreadService ) { @@ -70,26 +63,41 @@ export class JSONMode extends AbstractMode implements Modes.IExtraInfoSupport, M } }); - this.extraInfoSupport = this; + modes.HoverProviderRegistry.register(this.getId(), { + provideHover: (model, position, token): Thenable => { + return wireCancellationToken(token, this._provideHover(model.uri, position)); + } + }, true); + this.inplaceReplaceSupport = this; + this.configSupport = this; // Initialize Outline support - this.outlineSupport = this; - this.outlineGroupLabel = Object.create(null); - this.outlineGroupLabel['object'] = nls.localize('object', "objects"); - this.outlineGroupLabel['array'] = nls.localize('array', "arrays"); - this.outlineGroupLabel['string'] = nls.localize('string', "strings"); - this.outlineGroupLabel['number'] = nls.localize('number', "numbers"); - this.outlineGroupLabel['boolean'] = nls.localize('boolean', "booleans"); - this.outlineGroupLabel['null'] = nls.localize('undefined', "undefined"); + modes.DocumentSymbolProviderRegistry.register(this.getId(), { + provideDocumentSymbols: (model, token): Thenable => { + return wireCancellationToken(token, this._provideDocumentSymbols(model.uri)); + } + }, true); - this.formattingSupport = this; + modes.DocumentFormattingEditProviderRegistry.register(this.getId(), { + provideDocumentFormattingEdits: (model, options, token): Thenable => { + return wireCancellationToken(token, this._provideDocumentFormattingEdits(model.uri, options)); + } + }, true); - this.suggestSupport = new SuggestSupport(this.getId(), { + modes.DocumentRangeFormattingEditProviderRegistry.register(this.getId(), { + provideDocumentRangeFormattingEdits: (model, range, options, token): Thenable => { + return wireCancellationToken(token, this._provideDocumentRangeFormattingEdits(model.uri, range, options)); + } + }, true); + + modes.SuggestRegistry.register(this.getId(), { triggerCharacters: [], - excludeTokens: ['comment.line.json', 'comment.block.json'], - suggest: (resource, position) => this.suggest(resource, position)}); + provideCompletionItems: (model, position, token): Thenable => { + return wireCancellationToken(token, this._provideCompletionItems(model.uri, position)); + } + }, true); } public creationDone(): void { @@ -139,32 +147,32 @@ export class JSONMode extends AbstractMode implements Modes.IExtraInfoSupport, M } static $navigateValueSet = OneWorkerAttr(JSONMode, JSONMode.prototype.navigateValueSet); - public navigateValueSet(resource:URI, position:EditorCommon.IRange, up:boolean):WinJS.TPromise { + public navigateValueSet(resource:URI, position:editorCommon.IRange, up:boolean):WinJS.TPromise { return this._worker((w) => w.navigateValueSet(resource, position, up)); } - static $suggest = OneWorkerAttr(JSONMode, JSONMode.prototype.suggest); - public suggest(resource:URI, position:EditorCommon.IPosition):WinJS.TPromise { - return this._worker((w) => w.suggest(resource, position)); + static $_provideCompletionItems = OneWorkerAttr(JSONMode, JSONMode.prototype._provideCompletionItems); + private _provideCompletionItems(resource:URI, position:editorCommon.IPosition):WinJS.TPromise { + return this._worker((w) => w.provideCompletionItems(resource, position)); } - static $computeInfo = OneWorkerAttr(JSONMode, JSONMode.prototype.computeInfo); - public computeInfo(resource:URI, position:EditorCommon.IPosition): WinJS.TPromise { - return this._worker((w) => w.computeInfo(resource, position)); + static $_provideHover = OneWorkerAttr(JSONMode, JSONMode.prototype._provideHover); + private _provideHover(resource:URI, position:editorCommon.IPosition): WinJS.TPromise { + return this._worker((w) => w.provideHover(resource, position)); } - static $getOutline = OneWorkerAttr(JSONMode, JSONMode.prototype.getOutline); - public getOutline(resource:URI):WinJS.TPromise { - return this._worker((w) => w.getOutline(resource)); + static $_provideDocumentSymbols = OneWorkerAttr(JSONMode, JSONMode.prototype._provideDocumentSymbols); + private _provideDocumentSymbols(resource:URI):WinJS.TPromise { + return this._worker((w) => w.provideDocumentSymbols(resource)); } - static $formatDocument = OneWorkerAttr(JSONMode, JSONMode.prototype.formatDocument); - public formatDocument(resource:URI, options:Modes.IFormattingOptions):WinJS.TPromise { + static $_provideDocumentFormattingEdits = OneWorkerAttr(JSONMode, JSONMode.prototype._provideDocumentFormattingEdits); + public _provideDocumentFormattingEdits(resource:URI, options:modes.IFormattingOptions):WinJS.TPromise { return this._worker((w) => w.format(resource, null, options)); } - static $formatRange = OneWorkerAttr(JSONMode, JSONMode.prototype.formatRange); - public formatRange(resource:URI, range:EditorCommon.IRange, options:Modes.IFormattingOptions):WinJS.TPromise { + static $_provideDocumentRangeFormattingEdits = OneWorkerAttr(JSONMode, JSONMode.prototype._provideDocumentRangeFormattingEdits); + public _provideDocumentRangeFormattingEdits(resource:URI, range:editorCommon.IRange, options:modes.IFormattingOptions):WinJS.TPromise { return this._worker((w) => w.format(resource, range, options)); } } \ No newline at end of file diff --git a/src/vs/languages/json/common/jsonSchemaService.ts b/src/vs/languages/json/common/jsonSchemaService.ts index e63e19bd27c..4ea938fc81f 100644 --- a/src/vs/languages/json/common/jsonSchemaService.ts +++ b/src/vs/languages/json/common/jsonSchemaService.ts @@ -19,7 +19,7 @@ import {IResourceService, ResourceEvents, IResourceChangedEvent} from 'vs/editor import {IRequestService} from 'vs/platform/request/common/request'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {ISchemaContributions} from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; -import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; +import {IDisposable, dispose} from 'vs/base/common/lifecycle'; export interface IJSONSchemaService { @@ -214,20 +214,17 @@ export class JSONSchemaService implements IJSONSchemaService { private requestService: IRequestService; private contextService : IWorkspaceContextService; - private callOnDispose:Function[]; - private telemetryService: ITelemetryService; + private callOnDispose:IDisposable[]; constructor(@IRequestService requestService: IRequestService, - @ITelemetryService telemetryService?: ITelemetryService, @IWorkspaceContextService contextService?: IWorkspaceContextService, @IResourceService resourceService?: IResourceService) { this.requestService = requestService; this.contextService = contextService; - this.telemetryService = telemetryService; this.callOnDispose = []; if (resourceService) { - this.callOnDispose.push(resourceService.addListener_(ResourceEvents.CHANGED, (e: IResourceChangedEvent) => this.onResourceChange(e))); + this.callOnDispose.push(resourceService.addListener2_(ResourceEvents.CHANGED, (e: IResourceChangedEvent) => this.onResourceChange(e))); } this.contributionSchemas = {}; @@ -238,9 +235,7 @@ export class JSONSchemaService implements IJSONSchemaService { } public dispose(): void { - while(this.callOnDispose.length > 0) { - this.callOnDispose.pop()(); - } + this.callOnDispose = dispose(this.callOnDispose); } private onResourceChange(e: IResourceChangedEvent): void { @@ -327,12 +322,6 @@ export class JSONSchemaService implements IJSONSchemaService { } public loadSchema(url:string) : WinJS.TPromise { - if (this.telemetryService && Strings.startsWith(url, 'https://schema.management.azure.com')) { - this.telemetryService.publicLog('json.schema', { - schemaURL: url - }); - } - return this.requestService.makeRequest({ url: url }).then( request => { var content = request.responseText; @@ -342,9 +331,9 @@ export class JSONSchemaService implements IJSONSchemaService { } var schemaContent: IJSONSchema = {}; - var jsonErrors = []; - schemaContent = Json.parse(content, errors); - var errors = jsonErrors.length ? [ nls.localize('json.schema.invalidFormat', 'Unable to parse content from \'{0}\': {1}.', toDisplayString(url), jsonErrors[0])] : []; + var jsonErrors: Json.ParseError[] = []; + schemaContent = Json.parse(content, jsonErrors); + var errors = jsonErrors.length ? [ nls.localize('json.schema.invalidFormat', 'Unable to parse content from \'{0}\': {1}.', toDisplayString(url), Json.getParseErrorMessage(jsonErrors[0].error))] : []; return new UnresolvedSchema(schemaContent, errors); }, (error : http.IXHRResponse) => { diff --git a/src/vs/languages/json/common/jsonWorker.ts b/src/vs/languages/json/common/jsonWorker.ts index 9e6bf88f97c..48c39dc7468 100644 --- a/src/vs/languages/json/common/jsonWorker.ts +++ b/src/vs/languages/json/common/jsonWorker.ts @@ -10,7 +10,7 @@ import EditorCommon = require('vs/editor/common/editorCommon'); import Modes = require('vs/editor/common/modes'); import HtmlContent = require('vs/base/common/htmlContent'); import Parser = require('./parser/jsonParser'); -import JSONFormatter = require('vs/languages/json/common/features/jsonFormatter'); +import JSONFormatter = require('vs/base/common/jsonFormatter'); import SchemaService = require('./jsonSchemaService'); import JSONSchema = require('vs/base/common/jsonSchema'); import JSONIntellisense = require('./jsonIntellisense'); @@ -68,7 +68,7 @@ export interface IJSONWorkerContribution { collectDefaultSuggestions(resource: URI, result: ISuggestionsCollector): WinJS.Promise; } -export class JSONWorker implements Modes.IExtraInfoSupport { +export class JSONWorker { private schemaService: SchemaService.IJSONSchemaService; private requestService: IRequestService; @@ -265,7 +265,7 @@ export class JSONWorker implements Modes.IExtraInfoSupport { } - public suggest(resource:URI, position:EditorCommon.IPosition):WinJS.TPromise { + public provideCompletionItems(resource:URI, position:EditorCommon.IPosition):WinJS.TPromise { return this.doSuggest(resource, position).then(value => filterSuggestions(value)); } @@ -275,7 +275,7 @@ export class JSONWorker implements Modes.IExtraInfoSupport { return this.jsonIntellisense.doSuggest(resource, modelMirror, position); } - public computeInfo(resource:URI, position:EditorCommon.IPosition): WinJS.TPromise { + public provideHover(resource:URI, position:EditorCommon.IPosition): WinJS.TPromise { var modelMirror = this.resourceService.get(resource); @@ -333,11 +333,10 @@ export class JSONWorker implements Modes.IExtraInfoSupport { }); } - private createInfoResult(htmlContent : HtmlContent.IHTMLContentElement[], node: Parser.ASTNode, modelMirror: EditorCommon.IMirrorModel) : Modes.IComputeExtraInfoResult { + private createInfoResult(htmlContent : HtmlContent.IHTMLContentElement[], node: Parser.ASTNode, modelMirror: EditorCommon.IMirrorModel) : Modes.Hover { var range = modelMirror.getRangeFromOffsetAndLength(node.start, node.end - node.start); - var result:Modes.IComputeExtraInfoResult = { - value: '', + var result:Modes.Hover = { htmlContent: htmlContent, range: range }; @@ -345,7 +344,7 @@ export class JSONWorker implements Modes.IExtraInfoSupport { } - public getOutline(resource:URI):WinJS.TPromise { + public provideDocumentSymbols(resource:URI):WinJS.TPromise { var modelMirror = this.resourceService.get(resource); var parser = new Parser.JSONParser(); @@ -359,13 +358,20 @@ export class JSONWorker implements Modes.IExtraInfoSupport { var resourceString = resource.toString(); if ((resourceString === 'vscode://defaultsettings/keybindings.json') || Strings.endsWith(resourceString.toLowerCase(), '/user/keybindings.json')) { if (root.type === 'array') { - var result : Modes.IOutlineEntry[] = []; + var result : Modes.SymbolInformation[] = []; ( root).items.forEach((item) => { if (item.type === 'object') { var property = ( item).getFirstProperty('key'); if (property && property.value) { var range = modelMirror.getRangeFromOffsetAndLength(item.start, item.end - item.start); - result.push({ label: property.value.getValue(), icon: 'function', type: 'string', range: range, children: []}); + result.push({ + name: property.value.getValue(), + kind: Modes.SymbolKind.String, + location: { + uri: resource, + range: range + } + }); } } }); @@ -373,10 +379,10 @@ export class JSONWorker implements Modes.IExtraInfoSupport { } } - function collectOutlineEntries(result: Modes.IOutlineEntry[], node: Parser.ASTNode): Modes.IOutlineEntry[] { + function collectOutlineEntries(result: Modes.SymbolInformation[], node: Parser.ASTNode, containerName: string): Modes.SymbolInformation[] { if (node.type === 'array') { (node).items.forEach((node:Parser.ASTNode) => { - collectOutlineEntries(result, node); + collectOutlineEntries(result, node, containerName); }); } else if (node.type === 'object') { var objectNode = node; @@ -385,20 +391,48 @@ export class JSONWorker implements Modes.IExtraInfoSupport { var range = modelMirror.getRangeFromOffsetAndLength(property.start, property.end - property.start); var valueNode = property.value; if (valueNode) { - var children = collectOutlineEntries([], valueNode); - var icon = valueNode.type === 'object' ? 'module' : valueNode.type; - result.push({ label: property.key.getValue(), icon: icon, type: valueNode.type, range: range, children: children}); + let childContainerName = containerName ? containerName + '.' + property.key.name : property.key.name; + result.push({ + name: property.key.getValue(), + kind: getSymbolKind(valueNode.type), + location: { + uri: resource, + range: range, + }, + containerName: containerName + }); + collectOutlineEntries(result, valueNode, childContainerName); } }); } return result; } - var result = collectOutlineEntries([], root); + var result = collectOutlineEntries([], root, void 0); return WinJS.TPromise.as(result); } public format(resource: URI, range: EditorCommon.IRange, options: Modes.IFormattingOptions): WinJS.TPromise { - var model = this.resourceService.get(resource); - return WinJS.TPromise.as(JSONFormatter.format(model, range, options)); + let model = this.resourceService.get(resource); + let formatRange = range ? model.getOffsetAndLengthFromRange(range) : void 0; + let edits = JSONFormatter.format(model.getValue(), formatRange, { insertSpaces: options.insertSpaces, tabSize: options.tabSize, eol: model.getEOL() }); + let operations = edits.map(e => ({ range: model.getRangeFromOffsetAndLength(e.offset, e.length), text: e.content })); + return WinJS.TPromise.as(operations); + } +} + +function getSymbolKind(nodeType: string): Modes.SymbolKind { + switch (nodeType) { + case 'object': + return Modes.SymbolKind.Module; + case 'string': + return Modes.SymbolKind.String; + case 'number': + return Modes.SymbolKind.Number; + case 'array': + return Modes.SymbolKind.Array; + case 'boolean': + return Modes.SymbolKind.Boolean; + default: // 'null' + return Modes.SymbolKind.Variable; } } diff --git a/src/vs/languages/json/common/parser/jsonParser.ts b/src/vs/languages/json/common/parser/jsonParser.ts index df73072da3b..36f7ebce115 100644 --- a/src/vs/languages/json/common/parser/jsonParser.ts +++ b/src/vs/languages/json/common/parser/jsonParser.ts @@ -898,7 +898,7 @@ export class JSONParser { if (_scanner.getToken() === Json.SyntaxKind.Unknown) { // give a more helpful error message var value = _scanner.getTokenValue(); - if (value.length > 0 && (value.charAt(0) === '\'' || Json.isLetter(value.charAt(0).charCodeAt(0)))) { + if (value.match(/^['\w]/)) { _error(nls.localize('DoubleQuotesExpected', 'Property keys must be doublequoted')); } } diff --git a/src/vs/languages/json/test/common/jsonworker.test.ts b/src/vs/languages/json/test/common/jsonworker.test.ts index 66d05cc17ab..f653d370633 100644 --- a/src/vs/languages/json/test/common/jsonworker.test.ts +++ b/src/vs/languages/json/test/common/jsonworker.test.ts @@ -18,18 +18,24 @@ import EditorCommon = require('vs/editor/common/editorCommon'); import Modes = require('vs/editor/common/modes'); import WinJS = require('vs/base/common/winjs.base'); +interface RelaxedSymbolInformation { + name: string; + containerName?: string; + kind: Modes.SymbolKind; +} suite('JSON - Worker', () => { - var assertOutline:any = function(actual: Modes.IOutlineEntry[], expected: any[], message: string) { - assert.equal(actual.length, expected.length, message); - for (var i = 0; i < expected.length; i++) { - assert.equal(actual[i].label, expected[i].label, message); - assert.equal(actual[i].type, expected[i].type, message); - var childrenExpected = expected[i].children || []; - var childrenActual = actual[i].children || []; - assertOutline(childrenExpected, childrenActual, message); - } + function toRelaxedSymbolInformation(a: RelaxedSymbolInformation): RelaxedSymbolInformation { + return { + name: a.name, + containerName: a.containerName, + kind: a.kind + }; + } + + var assertOutline = function(actual: Modes.SymbolInformation[], expected: RelaxedSymbolInformation[], message?: string) { + assert.deepEqual(actual.map(toRelaxedSymbolInformation), expected.map(toRelaxedSymbolInformation), message); }; function mockWorkerEnv(url: URI, content: string): { worker: jsonworker.JSONWorker; model: EditorCommon.IMirrorModel; } { @@ -59,14 +65,14 @@ suite('JSON - Worker', () => { var idx = stringAfter ? value.indexOf(stringAfter) : 0; var position = env.model.getPositionFromOffset(idx); - return env.worker.suggest(url, position).then(result => result[0]); + return env.worker.provideCompletionItems(url, position).then(result => result[0]); }; - function testComputeInfo(content:string, schema:jsonSchema.IJSONSchema, position:EditorCommon.IPosition):WinJS.TPromise { + function testComputeInfo(content:string, schema:jsonSchema.IJSONSchema, position:EditorCommon.IPosition):WinJS.TPromise { var url = URI.parse('test://test.json'); var env = mockWorkerEnv(url, content); prepareSchemaServer(schema, env.worker); - return env.worker.computeInfo(url, position); + return env.worker.provideHover(url, position); } var testValueSetFor = function(value:string, schema:jsonSchema.IJSONSchema, selection:string, selectionLength: number, up: boolean):WinJS.TPromise { @@ -80,10 +86,10 @@ suite('JSON - Worker', () => { return env.worker.navigateValueSet(url, range, up); }; - function getOutline(content: string):WinJS.TPromise { + function getOutline(content: string):WinJS.TPromise { var url = URI.parse('test'); var workerEnv = mockWorkerEnv(url, content); - return workerEnv.worker.getOutline(url); + return workerEnv.worker.provideDocumentSymbols(url); }; var assertSuggestion= function(completion:Modes.ISuggestResult, label:string, documentationLabel?: string) { @@ -96,13 +102,13 @@ suite('JSON - Worker', () => { test('JSON outline - base types', function(testDone) { var content= '{ "key1": 1, "key2": "foo", "key3" : true }'; - var expected= [ - { label: 'key1', type: 'number'}, - { label: 'key2', type: 'string'}, - { label: 'key3', type: 'boolean'}, + var expected = [ + { name: 'key1', kind: Modes.SymbolKind.Number}, + { name: 'key2', kind: Modes.SymbolKind.String}, + { name: 'key3', kind: Modes.SymbolKind.Boolean}, ]; - getOutline(content).then((entries: Modes.IOutlineEntry[]) => { + getOutline(content).then((entries: Modes.SymbolInformation[]) => { assertOutline(entries, expected); }).done(() => testDone(), (error) => { testDone(error); @@ -113,12 +119,14 @@ suite('JSON - Worker', () => { var content= '{ "key1": 1, "key2": [ 1, 2, 3 ], "key3" : [ { "k1": 1 }, {"k2": 2 } ] }'; var expected= [ - { label: 'key1', type: 'number'}, - { label: 'key2', type: 'array'}, - { label: 'key3', type: 'array', children : [ { label: 'k1', type: 'number'}, { label: 'k2', type: 'number'} ]}, + { name: 'key1', kind: Modes.SymbolKind.Number}, + { name: 'key2', kind: Modes.SymbolKind.Array}, + { name: 'key3', kind: Modes.SymbolKind.Array}, + { name: 'k1', kind: Modes.SymbolKind.Number, containerName: 'key3'}, + { name: 'k2', kind: Modes.SymbolKind.Number, containerName: 'key3'}, ]; - getOutline(content).then((entries: Modes.IOutlineEntry[]) => { + getOutline(content).then((entries: Modes.SymbolInformation[]) => { assertOutline(entries, expected); }).done(() => testDone(), (error) => { testDone(error); @@ -129,11 +137,13 @@ suite('JSON - Worker', () => { var content= '{ "key1": { "key2": true }, "key3" : { "k1": { } }'; var expected= [ - { label: 'key1', type: 'object', children : [ { label: 'key2', type: 'boolean'} ] }, - { label: 'key3', type: 'object', children : [ { label: 'k1', type: 'object'} ] } + { name: 'key1', kind: Modes.SymbolKind.Module}, + { name: 'key2', kind: Modes.SymbolKind.Boolean, containerName: 'key1' }, + { name: 'key3', kind: Modes.SymbolKind.Module}, + { name: 'k1', kind: Modes.SymbolKind.Module, containerName: 'key3'} ]; - getOutline(content).then((entries: Modes.IOutlineEntry[]) => { + getOutline(content).then((entries: Modes.SymbolInformation[]) => { assertOutline(entries, expected); }).done(() => testDone(), (error) => { testDone(error); @@ -144,10 +154,12 @@ suite('JSON - Worker', () => { var content= '{ "key1": { "key2": true, "key3":, "key4": false } }'; var expected= [ - { label: 'key1', type: 'object', children : [ { label: 'key2', type: 'boolean'}, { label: 'key4', type: 'boolean'} ] }, + { name: 'key1', kind: Modes.SymbolKind.Module }, + { name: 'key2', kind: Modes.SymbolKind.Boolean, containerName: 'key1'}, + { name: 'key4', kind: Modes.SymbolKind.Boolean, containerName: 'key1'}, ]; - getOutline(content).then((entries: Modes.IOutlineEntry[]) => { + getOutline(content).then((entries: Modes.SymbolInformation[]) => { assertOutline(entries, expected); }).done(() => testDone(), (error) => { testDone(error); diff --git a/src/vs/languages/less/common/less.ts b/src/vs/languages/less/common/less.ts index 3888b763c89..ac077ada0a5 100644 --- a/src/vs/languages/less/common/less.ts +++ b/src/vs/languages/less/common/less.ts @@ -6,23 +6,23 @@ import winjs = require('vs/base/common/winjs.base'); import URI from 'vs/base/common/uri'; -import EditorCommon = require('vs/editor/common/editorCommon'); -import Modes = require('vs/editor/common/modes'); -import Monarch = require('vs/editor/common/modes/monarch/monarch'); +import editorCommon = require('vs/editor/common/editorCommon'); +import modes = require('vs/editor/common/modes'); import Types = require('vs/editor/common/modes/monarch/monarchTypes'); import Compile = require('vs/editor/common/modes/monarch/monarchCompile'); import lessWorker = require('vs/languages/less/common/lessWorker'); import * as lessTokenTypes from 'vs/languages/less/common/lessTokenTypes'; -import {ModeWorkerManager} from 'vs/editor/common/modes/abstractMode'; +import {ModeWorkerManager, AbstractMode} from 'vs/editor/common/modes/abstractMode'; import {OneWorkerAttr, AllWorkersAttr} from 'vs/platform/thread/common/threadService'; import {IModeService} from 'vs/editor/common/services/modeService'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IThreadService, ThreadAffinity} from 'vs/platform/thread/common/thread'; import {IModelService} from 'vs/editor/common/services/modelService'; -import {DeclarationSupport} from 'vs/editor/common/modes/supports/declarationSupport'; -import {ReferenceSupport} from 'vs/editor/common/modes/supports/referenceSupport'; -import {SuggestSupport} from 'vs/editor/common/modes/supports/suggestSupport'; import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService'; +import {wireCancellationToken} from 'vs/base/common/async'; +import {createRichEditSupport} from 'vs/editor/common/modes/monarch/monarchDefinition'; +import {createTokenizationSupport} from 'vs/editor/common/modes/monarch/monarchLexer'; +import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport'; export var language: Types.ILanguage = { displayName: 'LESS', @@ -176,49 +176,71 @@ export var language: Types.ILanguage = { } }; -export class LESSMode extends Monarch.MonarchMode implements Modes.IExtraInfoSupport, Modes.IOutlineSupport { +export class LESSMode extends AbstractMode { - public inplaceReplaceSupport:Modes.IInplaceReplaceSupport; - public configSupport:Modes.IConfigurationSupport; - public referenceSupport: Modes.IReferenceSupport; - public extraInfoSupport: Modes.IExtraInfoSupport; - public declarationSupport: Modes.IDeclarationSupport; - public outlineSupport: Modes.IOutlineSupport; - public suggestSupport: Modes.ISuggestSupport; + public inplaceReplaceSupport:modes.IInplaceReplaceSupport; + public configSupport:modes.IConfigurationSupport; + public tokenizationSupport: modes.ITokenizationSupport; + public richEditSupport: modes.IRichEditSupport; private modeService: IModeService; private _modeWorkerManager: ModeWorkerManager; private _threadService:IThreadService; constructor( - descriptor:Modes.IModeDescriptor, + descriptor:modes.IModeDescriptor, @IInstantiationService instantiationService: IInstantiationService, @IThreadService threadService: IThreadService, @IModeService modeService: IModeService, @IModelService modelService: IModelService, @IEditorWorkerService editorWorkerService: IEditorWorkerService ) { - super(descriptor.id, Compile.compile(language), modeService, modelService, editorWorkerService); + super(descriptor.id); + let lexer = Compile.compile(language); + this._modeWorkerManager = new ModeWorkerManager(descriptor, 'vs/languages/less/common/lessWorker', 'LessWorker', 'vs/languages/css/common/cssWorker', instantiationService); this._threadService = threadService; this.modeService = modeService; - this.extraInfoSupport = this; - this.inplaceReplaceSupport = this; - this.configSupport = this; - this.referenceSupport = new ReferenceSupport(this.getId(), { - tokens: [lessTokenTypes.TOKEN_PROPERTY + '.less', lessTokenTypes.TOKEN_VALUE + '.less', 'variable.less', lessTokenTypes.TOKEN_SELECTOR + '.class.less', lessTokenTypes.TOKEN_SELECTOR + '.id.less', 'selector.less'], - findReferences: (resource, position, /*unused*/includeDeclaration) => this.findReferences(resource, position)}); - this.declarationSupport = new DeclarationSupport(this.getId(), { - tokens: ['variable.less', lessTokenTypes.TOKEN_SELECTOR + '.class.less', lessTokenTypes.TOKEN_SELECTOR + '.id.less', 'selector.less'], - findDeclaration: (resource, position) => this.findDeclaration(resource, position)}); - this.outlineSupport = this; + modes.HoverProviderRegistry.register(this.getId(), { + provideHover: (model, position, token): Thenable => { + return wireCancellationToken(token, this._provideHover(model.uri, position)); + } + }, true); - this.suggestSupport = new SuggestSupport(this.getId(), { + this.inplaceReplaceSupport = this; + + this.configSupport = this; + + modes.ReferenceProviderRegistry.register(this.getId(), { + provideReferences: (model, position, context, token): Thenable => { + return wireCancellationToken(token, this._provideReferences(model.uri, position)); + } + }, true); + + modes.DefinitionProviderRegistry.register(this.getId(), { + provideDefinition: (model, position, token): Thenable => { + return wireCancellationToken(token, this._provideDefinition(model.uri, position)); + } + }, true); + + modes.DocumentSymbolProviderRegistry.register(this.getId(), { + provideDocumentSymbols: (model, token): Thenable => { + return wireCancellationToken(token, this._provideDocumentSymbols(model.uri)); + } + }, true); + + modes.SuggestRegistry.register(this.getId(), { triggerCharacters: [], - excludeTokens: ['comment.less', 'string.less'], - suggest: (resource, position) => this.suggest(resource, position)}); + provideCompletionItems: (model, position, token): Thenable => { + return wireCancellationToken(token, this._provideCompletionItems(model.uri, position)); + } + }, true); + + this.tokenizationSupport = createTokenizationSupport(modeService, this, lexer); + + this.richEditSupport = new RichEditSupport(this.getId(), null, createRichEditSupport(lexer)); } public creationDone(): void { @@ -246,7 +268,7 @@ export class LESSMode extends Monarch.MonarchMode implements Modes.IExtraInfoSup } static $navigateValueSet = OneWorkerAttr(LESSMode, LESSMode.prototype.navigateValueSet); - public navigateValueSet(resource:URI, position:EditorCommon.IRange, up:boolean):winjs.TPromise { + public navigateValueSet(resource:URI, position:editorCommon.IRange, up:boolean):winjs.TPromise { return this._worker((w) => w.navigateValueSet(resource, position, up)); } @@ -255,33 +277,33 @@ export class LESSMode extends Monarch.MonarchMode implements Modes.IExtraInfoSup return this._worker((w) => w.enableValidator()); } - static $findReferences = OneWorkerAttr(LESSMode, LESSMode.prototype.findReferences); - public findReferences(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { - return this._worker((w) => w.findReferences(resource, position)); + static $_provideReferences = OneWorkerAttr(LESSMode, LESSMode.prototype._provideReferences); + private _provideReferences(resource:URI, position:editorCommon.IPosition):winjs.TPromise { + return this._worker((w) => w.provideReferences(resource, position)); } - static $suggest = OneWorkerAttr(LESSMode, LESSMode.prototype.suggest); - public suggest(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { - return this._worker((w) => w.suggest(resource, position)); + static $_provideCompletionItems = OneWorkerAttr(LESSMode, LESSMode.prototype._provideCompletionItems); + private _provideCompletionItems(resource:URI, position:editorCommon.IPosition):winjs.TPromise { + return this._worker((w) => w.provideCompletionItems(resource, position)); } - static $computeInfo = OneWorkerAttr(LESSMode, LESSMode.prototype.computeInfo); - public computeInfo(resource:URI, position:EditorCommon.IPosition): winjs.TPromise { - return this._worker((w) => w.computeInfo(resource, position)); + static $_provideHover = OneWorkerAttr(LESSMode, LESSMode.prototype._provideHover); + private _provideHover(resource:URI, position:editorCommon.IPosition): winjs.TPromise { + return this._worker((w) => w.provideHover(resource, position)); } - static $getOutline = OneWorkerAttr(LESSMode, LESSMode.prototype.getOutline); - public getOutline(resource:URI):winjs.TPromise { - return this._worker((w) => w.getOutline(resource)); + static $_provideDocumentSymbols = OneWorkerAttr(LESSMode, LESSMode.prototype._provideDocumentSymbols); + private _provideDocumentSymbols(resource:URI):winjs.TPromise { + return this._worker((w) => w.provideDocumentSymbols(resource)); } - static $findDeclaration = OneWorkerAttr(LESSMode, LESSMode.prototype.findDeclaration); - public findDeclaration(resource:URI, position:EditorCommon.IPosition):winjs.TPromise { - return this._worker((w) => w.findDeclaration(resource, position)); + static $_provideDefinition = OneWorkerAttr(LESSMode, LESSMode.prototype._provideDefinition); + private _provideDefinition(resource:URI, position:editorCommon.IPosition):winjs.TPromise { + return this._worker((w) => w.provideDefinition(resource, position)); } static $findColorDeclarations = OneWorkerAttr(LESSMode, LESSMode.prototype.findColorDeclarations); - public findColorDeclarations(resource:URI):winjs.TPromise<{range:EditorCommon.IRange; value:string; }[]> { + public findColorDeclarations(resource:URI):winjs.TPromise<{range:editorCommon.IRange; value:string; }[]> { return this._worker((w) => w.findColorDeclarations(resource)); } } diff --git a/src/vs/languages/less/common/parser/lessParser.ts b/src/vs/languages/less/common/parser/lessParser.ts index 457d23aeb9d..d78853e123b 100644 --- a/src/vs/languages/less/common/parser/lessParser.ts +++ b/src/vs/languages/less/common/parser/lessParser.ts @@ -77,6 +77,11 @@ export class LessParser extends cssParser.Parser { this.restoreAtMark(mark); return null; // at keyword, but no ':', not a variable declaration but some at keyword } + + if (this.peek(scanner.TokenType.SemiColon)) { + node.semicolonPosition = this.token.offset; // not part of the declaration, but useful information for code assist + } + return this.finish(node); } @@ -158,7 +163,7 @@ export class LessParser extends cssParser.Parser { || this._tryParseRuleset(true) // nested ruleset || this._parseMixinReference() // less mixin reference || this._parseExtend() // less extend declaration - || this._parseDeclaration(); // try declaration as the last option + || super._parseRuleSetDeclaration(); // try css ruleset declaration as the last option } public _parseSimpleSelectorBody(): nodes.Node { diff --git a/src/vs/languages/less/test/common/intellisense.test.ts b/src/vs/languages/less/test/common/intellisense.test.ts index e3d6bacf7fd..4ed16b2ebb1 100644 --- a/src/vs/languages/less/test/common/intellisense.test.ts +++ b/src/vs/languages/less/test/common/intellisense.test.ts @@ -40,7 +40,7 @@ suite('LESS - Intellisense', () => { lineNumber: 1 }; } - return worker.suggest(url, position).then(result => result[0]); + return worker.provideCompletionItems(url, position).then(result => result[0]); }; var assertSuggestion= function(completion:Modes.ISuggestResult, label:string) { diff --git a/src/vs/languages/less/test/common/parser.test.ts b/src/vs/languages/less/test/common/parser.test.ts index 0a75954bbf3..269b50b7325 100644 --- a/src/vs/languages/less/test/common/parser.test.ts +++ b/src/vs/languages/less/test/common/parser.test.ts @@ -5,6 +5,7 @@ 'use strict'; +import assert = require('assert'); import _parser = require('vs/languages/less/common/parser/lessParser'); import nodes = require ('vs/languages/css/common/parser/cssNodes'); import errors = require ('vs/languages/css/common/parser/cssErrors'); @@ -12,8 +13,8 @@ import errors = require ('vs/languages/css/common/parser/cssErrors'); import cssParserTests = require ('vs/languages/css/test/common/parser.test'); -function assertNode(text: string, parser: _parser.LessParser, f: ()=>nodes.Node):void { - cssParserTests.assertNode(text, parser, f); +function assertNode(text: string, parser: _parser.LessParser, f: ()=>nodes.Node):nodes.Node { + return cssParserTests.assertNode(text, parser, f); } function assertNoNode(text: string, parser: _parser.LessParser, f: ()=>nodes.Node):void { diff --git a/src/vs/languages/markdown/common/markdown.ts b/src/vs/languages/markdown/common/markdown.ts index fde44fa9d14..f7a99c41b26 100644 --- a/src/vs/languages/markdown/common/markdown.ts +++ b/src/vs/languages/markdown/common/markdown.ts @@ -5,7 +5,6 @@ 'use strict'; import WinJS = require('vs/base/common/winjs.base'); -import Monarch = require('vs/editor/common/modes/monarch/monarch'); import URI from 'vs/base/common/uri'; import Types = require('vs/editor/common/modes/monarch/monarchTypes'); import Compile = require('vs/editor/common/modes/monarch/monarchCompile'); @@ -17,10 +16,13 @@ import markdownTokenTypes = require('vs/languages/markdown/common/markdownTokenT import {IModeService} from 'vs/editor/common/services/modeService'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IThreadService} from 'vs/platform/thread/common/thread'; -import {IModelService} from 'vs/editor/common/services/modelService'; -import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; +import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService'; -import {ModeWorkerManager} from 'vs/editor/common/modes/abstractMode'; +import {AbstractMode, ModeWorkerManager} from 'vs/editor/common/modes/abstractMode'; +import {createRichEditSupport} from 'vs/editor/common/modes/monarch/monarchDefinition'; +import {createTokenizationSupport} from 'vs/editor/common/modes/monarch/monarchLexer'; +import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport'; +import {TextualSuggestSupport} from 'vs/editor/common/modes/supports/suggestSupport'; export const language = { @@ -28,10 +30,6 @@ export const language = name: 'md', defaultToken: '', - suggestSupport: { - disableAutoTrigger: true, - }, - autoClosingPairs: [], blockCommentStart: '