Skip to content

Commit 7971774

Browse files
committed
add onLineBreak visit function
1 parent 77ae9d4 commit 7971774

File tree

5 files changed

+177
-67
lines changed

5 files changed

+177
-67
lines changed

README.md

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ export interface JSONScanner {
6868
* The length of the last read token.
6969
*/
7070
getTokenLength(): number;
71+
/**
72+
* The zero-based start line number of the last read token.
73+
*/
74+
getTokenLine(): number;
75+
/**
76+
* The zero-based character (start column) of the last read token.
77+
*/
78+
getTokenCharacter(): number;
7179
/**
7280
* An error code of the last scan.
7381
*/
@@ -93,42 +101,42 @@ export declare function parse(text: string, errors?: {error: ParseErrorCode;}[],
93101
export declare function visit(text: string, visitor: JSONVisitor, options?: ParseOptions): any;
94102

95103
export interface JSONVisitor {
96-
/**
97-
* Invoked when an open brace is encountered and an object is started. The offset and length represent the location of the open brace.
98-
*/
99-
onObjectBegin?: (offset: number, length: number) => void;
100-
/**
101-
* Invoked when a property is encountered. The offset and length represent the location of the property name.
102-
*/
103-
onObjectProperty?: (property: string, offset: number, length: number) => void;
104-
/**
105-
* Invoked when a closing brace is encountered and an object is completed. The offset and length represent the location of the closing brace.
106-
*/
107-
onObjectEnd?: (offset: number, length: number) => void;
108-
/**
109-
* Invoked when an open bracket is encountered. The offset and length represent the location of the open bracket.
110-
*/
111-
onArrayBegin?: (offset: number, length: number) => void;
112-
/**
113-
* Invoked when a closing bracket is encountered. The offset and length represent the location of the closing bracket.
114-
*/
115-
onArrayEnd?: (offset: number, length: number) => void;
116-
/**
117-
* Invoked when a literal value is encountered. The offset and length represent the location of the literal value.
118-
*/
119-
onLiteralValue?: (value: any, offset: number, length: number) => void;
120-
/**
121-
* Invoked when a comma or colon separator is encountered. The offset and length represent the location of the separator.
122-
*/
123-
onSeparator?: (charcter: string, offset: number, length: number) => void;
104+
/**
105+
* Invoked when an open brace is encountered and an object is started. The offset and length represent the location of the open brace.
106+
*/
107+
onObjectBegin?: (offset: number, length: number, startLine: number, startCharacter: number) => void;
108+
/**
109+
* Invoked when a property is encountered. The offset and length represent the location of the property name.
110+
*/
111+
onObjectProperty?: (property: string, offset: number, length: number, startLine: number, startCharacter: number) => void;
112+
/**
113+
* Invoked when a closing brace is encountered and an object is completed. The offset and length represent the location of the closing brace.
114+
*/
115+
onObjectEnd?: (offset: number, length: number, startLine: number, startCharacter: number) => void;
116+
/**
117+
* Invoked when an open bracket is encountered. The offset and length represent the location of the open bracket.
118+
*/
119+
onArrayBegin?: (offset: number, length: number, startLine: number, startCharacter: number) => void;
120+
/**
121+
* Invoked when a closing bracket is encountered. The offset and length represent the location of the closing bracket.
122+
*/
123+
onArrayEnd?: (offset: number, length: number, startLine: number, startCharacter: number) => void;
124+
/**
125+
* Invoked when a literal value is encountered. The offset and length represent the location of the literal value.
126+
*/
127+
onLiteralValue?: (value: any, offset: number, length: number, startLine: number, startCharacter: number) => void;
128+
/**
129+
* Invoked when a comma or colon separator is encountered. The offset and length represent the location of the separator.
130+
*/
131+
onSeparator?: (character: string, offset: number, length: number, startLine: number, startCharacter: number) => void;
124132
/**
125133
* When comments are allowed, invoked when a line or block comment is encountered. The offset and length represent the location of the comment.
126134
*/
127-
onComment?: (offset: number, length: number) => void;
128-
/**
129-
* Invoked on an error.
130-
*/
131-
onError?: (error: ParseErrorCode, offset: number, length: number) => void;
135+
onComment?: (offset: number, length: number, startLine: number, startCharacter: number) => void;
136+
/**
137+
* Invoked on an error.
138+
*/
139+
onError?: (error: ParseErrorCode, offset: number, length: number, startLine: number, startCharacter: number) => void;
132140
}
133141

134142
/**
@@ -298,4 +306,4 @@ License
298306

299307
(MIT License)
300308

301-
Copyright 2018, Microsoft
309+
Copyright 2018, Microsoft

src/impl/parser.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,17 @@
66

77
import { createScanner } from './scanner';
88
import {
9-
ScanError, SyntaxKind, Node, NodeType, Edit, JSONPath, FormattingOptions,
10-
ModificationOptions, ParseError, ParseErrorCode, Location, Segment, ParseOptions, JSONVisitor
9+
JSONPath,
10+
JSONVisitor,
11+
Location,
12+
Node,
13+
NodeType,
14+
ParseError,
15+
ParseErrorCode,
16+
ParseOptions,
17+
ScanError,
18+
Segment,
19+
SyntaxKind
1120
} from '../main';
1221

1322
namespace ParseOptions {
@@ -376,11 +385,11 @@ export function visit(text: string, visitor: JSONVisitor, options: ParseOptions
376385

377386
let _scanner = createScanner(text, false);
378387

379-
function toNoArgVisit(visitFunction?: (offset: number, length: number) => void): () => void {
380-
return visitFunction ? () => visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength()) : () => true;
388+
function toNoArgVisit(visitFunction?: (offset: number, length: number, startLine: number, startCharacter: number) => void): () => void {
389+
return visitFunction ? () => visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenLine(), _scanner.getTokenCharacter()) : () => true;
381390
}
382-
function toOneArgVisit<T>(visitFunction?: (arg: T, offset: number, length: number) => void): (arg: T) => void {
383-
return visitFunction ? (arg: T) => visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength()) : () => true;
391+
function toOneArgVisit<T>(visitFunction?: (arg: T, offset: number, length: number, startLine: number, startCharacter: number) => void): (arg: T) => void {
392+
return visitFunction ? (arg: T) => visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenLine(), _scanner.getTokenCharacter()) : () => true;
384393
}
385394

386395
let onObjectBegin = toNoArgVisit(visitor.onObjectBegin),
@@ -650,4 +659,4 @@ function getLiteralNodeType(value: any): NodeType {
650659
case 'string': return 'string';
651660
default: return 'null';
652661
}
653-
}
662+
}

src/impl/scanner.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON
1717
value: string = '',
1818
tokenOffset = 0,
1919
token: SyntaxKind = SyntaxKind.Unknown,
20+
lineNumber = 0,
21+
tokenLineNumber = 0,
22+
lineEndOffset = 0,
23+
prevLineEndOffset = 0,
2024
scanError: ScanError = ScanError.None;
2125

2226
function scanHexDigits(count: number, exact?: boolean): number {
@@ -179,6 +183,8 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON
179183
scanError = ScanError.None;
180184

181185
tokenOffset = pos;
186+
tokenLineNumber = lineNumber;
187+
prevLineEndOffset = lineEndOffset;
182188

183189
if (pos >= len) {
184190
// at the end
@@ -206,6 +212,8 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON
206212
pos++;
207213
value += '\n';
208214
}
215+
lineNumber++;
216+
lineEndOffset = pos;
209217
return token = SyntaxKind.LineBreakTrivia;
210218
}
211219

@@ -268,7 +276,17 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON
268276
commentClosed = true;
269277
break;
270278
}
279+
271280
pos++;
281+
282+
if (isLineBreak(ch)) {
283+
if (ch === CharacterCodes.carriageReturn && text.charCodeAt(pos) === CharacterCodes.lineFeed) {
284+
pos++;
285+
}
286+
287+
lineNumber++;
288+
lineEndOffset = pos;
289+
}
272290
}
273291

274292
if (!commentClosed) {
@@ -365,7 +383,9 @@ export function createScanner(text: string, ignoreTrivia: boolean = false): JSON
365383
getTokenValue: () => value,
366384
getTokenOffset: () => tokenOffset,
367385
getTokenLength: () => pos - tokenOffset,
368-
getTokenError: () => scanError
386+
getTokenLine: () => tokenLineNumber,
387+
getTokenCharacter: () => tokenOffset - prevLineEndOffset,
388+
getTokenError: () => scanError,
369389
};
370390
}
371391

src/main.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ export interface JSONScanner {
7777
* The length of the last read token.
7878
*/
7979
getTokenLength(): number;
80+
/**
81+
* The zero-based start line number of the last read token.
82+
*/
83+
getTokenLine(): number;
84+
/**
85+
* The zero-based character (start column) of the last read token.
86+
*/
87+
getTokenCharacter(): number;
8088
/**
8189
* An error code of the last scan.
8290
*/
@@ -225,47 +233,47 @@ export interface JSONVisitor {
225233
/**
226234
* Invoked when an open brace is encountered and an object is started. The offset and length represent the location of the open brace.
227235
*/
228-
onObjectBegin?: (offset: number, length: number) => void;
236+
onObjectBegin?: (offset: number, length: number, startLine: number, startCharacter: number) => void;
229237

230238
/**
231239
* Invoked when a property is encountered. The offset and length represent the location of the property name.
232240
*/
233-
onObjectProperty?: (property: string, offset: number, length: number) => void;
241+
onObjectProperty?: (property: string, offset: number, length: number, startLine: number, startCharacter: number) => void;
234242

235243
/**
236244
* Invoked when a closing brace is encountered and an object is completed. The offset and length represent the location of the closing brace.
237245
*/
238-
onObjectEnd?: (offset: number, length: number) => void;
246+
onObjectEnd?: (offset: number, length: number, startLine: number, startCharacter: number) => void;
239247

240248
/**
241249
* Invoked when an open bracket is encountered. The offset and length represent the location of the open bracket.
242250
*/
243-
onArrayBegin?: (offset: number, length: number) => void;
251+
onArrayBegin?: (offset: number, length: number, startLine: number, startCharacter: number) => void;
244252

245253
/**
246254
* Invoked when a closing bracket is encountered. The offset and length represent the location of the closing bracket.
247255
*/
248-
onArrayEnd?: (offset: number, length: number) => void;
256+
onArrayEnd?: (offset: number, length: number, startLine: number, startCharacter: number) => void;
249257

250258
/**
251259
* Invoked when a literal value is encountered. The offset and length represent the location of the literal value.
252260
*/
253-
onLiteralValue?: (value: any, offset: number, length: number) => void;
261+
onLiteralValue?: (value: any, offset: number, length: number, startLine: number, startCharacter: number) => void;
254262

255263
/**
256264
* Invoked when a comma or colon separator is encountered. The offset and length represent the location of the separator.
257265
*/
258-
onSeparator?: (character: string, offset: number, length: number) => void;
266+
onSeparator?: (character: string, offset: number, length: number, startLine: number, startCharacter: number) => void;
259267

260268
/**
261269
* When comments are allowed, invoked when a line or block comment is encountered. The offset and length represent the location of the comment.
262270
*/
263-
onComment?: (offset: number, length: number) => void;
271+
onComment?: (offset: number, length: number, startLine: number, startCharacter: number) => void;
264272

265273
/**
266274
* Invoked on an error.
267275
*/
268-
onError?: (error: ParseErrorCode, offset: number, length: number) => void;
276+
onError?: (error: ParseErrorCode, offset: number, length: number, startLine: number, startCharacter: number) => void;
269277
}
270278

271279
/**

0 commit comments

Comments
 (0)