/*--------------------------------------------------------------------------------------------- * 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 Modes = require('vs/editor/common/modes'); import {Arrays} from 'vs/editor/common/core/arrays'; export class Token implements Modes.IToken { public startIndex:number; public type:string; constructor(startIndex:number, type:string) { this.startIndex = startIndex; this.type = type; } public toString(): string { return '(' + this.startIndex + ', ' + this.type + ')'; } } export function handleEvent(context:Modes.ILineContext, offset:number, runner:(mode:Modes.IMode, newContext:Modes.ILineContext, offset:number)=>T):T { var modeTransitions = context.modeTransitions; if (modeTransitions.length === 1) { return runner(modeTransitions[0].mode, context, offset); } var modeIndex = Arrays.findIndexInSegmentsArray(modeTransitions, offset); var nestedMode = modeTransitions[modeIndex].mode; var modeStartIndex = modeTransitions[modeIndex].startIndex; var firstTokenInModeIndex = context.findIndexOfOffset(modeStartIndex); var nextCharacterAfterModeIndex = -1; var nextTokenAfterMode = -1; if (modeIndex + 1 < modeTransitions.length) { nextTokenAfterMode = context.findIndexOfOffset(modeTransitions[modeIndex + 1].startIndex); nextCharacterAfterModeIndex = context.getTokenStartIndex(nextTokenAfterMode); } else { nextTokenAfterMode = context.getTokenCount(); nextCharacterAfterModeIndex = context.getLineContent().length; } var firstTokenCharacterOffset = context.getTokenStartIndex(firstTokenInModeIndex); var newCtx = new FilteredLineContext(context, nestedMode, firstTokenInModeIndex, nextTokenAfterMode, firstTokenCharacterOffset, nextCharacterAfterModeIndex); 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: Modes.IModeTransition[]; private _actual:Modes.ILineContext; private _firstTokenInModeIndex:number; private _nextTokenAfterMode:number; private _firstTokenCharacterOffset:number; private _nextCharacterAfterModeIndex:number; constructor(actual:Modes.ILineContext, mode:Modes.IMode, firstTokenInModeIndex:number, nextTokenAfterMode:number, firstTokenCharacterOffset:number, nextCharacterAfterModeIndex:number) { this.modeTransitions = [{ startIndex: 0, mode: mode }]; this._actual = actual; this._firstTokenInModeIndex = firstTokenInModeIndex; this._nextTokenAfterMode = nextTokenAfterMode; this._firstTokenCharacterOffset = firstTokenCharacterOffset; this._nextCharacterAfterModeIndex = nextCharacterAfterModeIndex; } public getLineContent(): string { var actualLineContent = this._actual.getLineContent(); return actualLineContent.substring(this._firstTokenCharacterOffset, this._nextCharacterAfterModeIndex); } public getTokenCount(): number { return this._nextTokenAfterMode - this._firstTokenInModeIndex; } public findIndexOfOffset(offset:number): number { return this._actual.findIndexOfOffset(offset + this._firstTokenCharacterOffset) - this._firstTokenInModeIndex; } public getTokenStartIndex(tokenIndex:number): number { return this._actual.getTokenStartIndex(tokenIndex + this._firstTokenInModeIndex) - this._firstTokenCharacterOffset; } public getTokenEndIndex(tokenIndex:number): number { return this._actual.getTokenEndIndex(tokenIndex + this._firstTokenInModeIndex) - this._firstTokenCharacterOffset; } public getTokenType(tokenIndex:number): string { return this._actual.getTokenType(tokenIndex + this._firstTokenInModeIndex); } public getTokenText(tokenIndex:number): string { return this._actual.getTokenText(tokenIndex + this._firstTokenInModeIndex); } } export function ignoreBracketsInToken(tokenType:string): boolean { return /\b(comment|string|regex)\b/.test(tokenType); }