1
0
Эх сурвалжийг харах

Fixes microsoft/monaco-editor#1999: Use parent stack to keep track of the current parent and previous parents for any particular key or value part

Pankaj Khandelwal 4 жил өмнө
parent
commit
77add4162b
1 өөрчлөгдсөн 80 нэмэгдсэн , 19 устгасан
  1. 80 19
      src/tokenization.ts

+ 80 - 19
src/tokenization.ts

@@ -10,7 +10,7 @@ export function createTokenizationSupport(
 	supportComments: boolean
 ): languages.TokensProvider {
 	return {
-		getInitialState: () => new JSONState(null, null),
+		getInitialState: () => new JSONState(null, null, false, []),
 		tokenize: (line, state, offsetDelta?, stopAtOffset?) =>
 			tokenize(
 				supportComments,
@@ -34,18 +34,60 @@ export const TOKEN_PROPERTY_NAME = 'string.key.json';
 export const TOKEN_COMMENT_BLOCK = 'comment.block.json';
 export const TOKEN_COMMENT_LINE = 'comment.line.json';
 
+enum JSONParent {
+	Object = 0,
+	Array = 1
+}
+
 class JSONState implements languages.IState {
 	private _state: languages.IState;
 
 	public scanError: json.ScanError;
-
-	constructor(state: languages.IState, scanError: json.ScanError) {
+	public lastWasColon: boolean;
+	public parents: JSONParent[];
+
+	constructor(
+		state: languages.IState,
+		scanError: json.ScanError,
+		lastWasColon: boolean,
+		parents: JSONParent[]
+	) {
 		this._state = state;
 		this.scanError = scanError;
+		this.lastWasColon = lastWasColon;
+		this.parents = parents;
+	}
+
+	private static areArraysEqual(first: JSONParent[], second: JSONParent[]) {
+		if (first === second) {
+			return true;
+		}
+
+		if (first == null || second === null) {
+			return false;
+		}
+
+		if (first.length !== second.length) {
+			return false;
+		}
+
+		let index = -1;
+		while (++index < first.length) {
+			if (first[index] !== second[index]) {
+				return false;
+			}
+		}
+
+		return true;
 	}
 
 	public clone(): JSONState {
-		return new JSONState(this._state, this.scanError);
+		return new JSONState(
+			this._state,
+			this.scanError,
+			this.lastWasColon,
+			this.parents
+		);
 	}
 
 	public equals(other: languages.IState): boolean {
@@ -55,7 +97,11 @@ class JSONState implements languages.IState {
 		if (!other || !(other instanceof JSONState)) {
 			return false;
 		}
-		return this.scanError === (<JSONState>other).scanError;
+		return (
+			this.scanError === (<JSONState>other).scanError &&
+			this.lastWasColon === (<JSONState>other).lastWasColon &&
+			JSONState.areArraysEqual(this.parents, (<JSONState>other).parents)
+		);
 	}
 
 	public getStateData(): languages.IState {
@@ -89,7 +135,9 @@ function tokenize(
 			break;
 	}
 
-	const scanner = json.createScanner(line);
+	let scanner = json.createScanner(line),
+		lastWasColon = state.lastWasColon,
+		parents = Array.from(state.parents);
 
 	const ret: languages.ILineTokens = {
 		tokens: <languages.IToken[]>[],
@@ -123,46 +171,54 @@ function tokenize(
 		// brackets and type
 		switch (kind) {
 			case json.SyntaxKind.OpenBraceToken:
+				parents.push(JSONParent.Object);
 				type = TOKEN_DELIM_OBJECT;
+				lastWasColon = false;
 				break;
 			case json.SyntaxKind.CloseBraceToken:
+				parents.pop();
 				type = TOKEN_DELIM_OBJECT;
+				lastWasColon = false;
 				break;
 			case json.SyntaxKind.OpenBracketToken:
+				parents.push(JSONParent.Array);
 				type = TOKEN_DELIM_ARRAY;
+				lastWasColon = false;
 				break;
 			case json.SyntaxKind.CloseBracketToken:
+				parents.pop();
 				type = TOKEN_DELIM_ARRAY;
+				lastWasColon = false;
 				break;
 			case json.SyntaxKind.ColonToken:
-				for (let i = ret.tokens.length - 1; i >= 0; i--) {
-					const token = ret.tokens[i];
-					if (token.scopes === '' || token.scopes === TOKEN_COMMENT_BLOCK) {
-						continue;
-					}
-					if (token.scopes === TOKEN_VALUE_STRING) {
-						// !change previous token to property name!
-						token.scopes = TOKEN_PROPERTY_NAME;
-					}
-					break;
-				}
 				type = TOKEN_DELIM_COLON;
+				lastWasColon = true;
 				break;
 			case json.SyntaxKind.CommaToken:
 				type = TOKEN_DELIM_COMMA;
+				lastWasColon = false;
 				break;
 			case json.SyntaxKind.TrueKeyword:
 			case json.SyntaxKind.FalseKeyword:
 				type = TOKEN_VALUE_BOOLEAN;
+				lastWasColon = false;
 				break;
 			case json.SyntaxKind.NullKeyword:
 				type = TOKEN_VALUE_NULL;
+				lastWasColon = false;
 				break;
 			case json.SyntaxKind.StringLiteral:
-				type = TOKEN_VALUE_STRING;
+				let currentParent = parents.length
+					? parents[parents.length - 1]
+					: JSONParent.Object;
+				let inArray = currentParent === JSONParent.Array;
+				type =
+					lastWasColon || inArray ? TOKEN_VALUE_STRING : TOKEN_PROPERTY_NAME;
+				lastWasColon = false;
 				break;
 			case json.SyntaxKind.NumericLiteral:
 				type = TOKEN_VALUE_NUMBER;
+				lastWasColon = false;
 				break;
 		}
 
@@ -178,7 +234,12 @@ function tokenize(
 			}
 		}
 
-		ret.endState = new JSONState(state.getStateData(), scanner.getTokenError());
+		ret.endState = new JSONState(
+			state.getStateData(),
+			scanner.getTokenError(),
+			lastWasColon,
+			parents
+		);
 		ret.tokens.push({
 			startIndex: offset,
 			scopes: type