Skip to content
This repository has been archived by the owner on Nov 5, 2021. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Use parent stack to keep track of the current parent and previous parents for any particular key or value part
  • Loading branch information
pankajk07 committed Sep 19, 2020
1 parent b41e49f commit 17bf74d
Showing 1 changed file with 80 additions and 19 deletions.
99 changes: 80 additions & 19 deletions src/tokenization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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[]>[],
Expand Down Expand Up @@ -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;
}

Expand All @@ -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
Expand Down

0 comments on commit 17bf74d

Please sign in to comment.