1
1
// Copyright © 2023, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
2
2
// SPDX-License-Identifier: Apache-2.0
3
3
import { Lexer , Token as RealToken } from "../Lexer" ;
4
- import type { FoldingBlock } from "../LexerEx" ;
4
+ import { type FoldingBlock , LexerEx } from "../LexerEx" ;
5
5
import type { Model } from "../Model" ;
6
6
import type { SyntaxProvider } from "../SyntaxProvider" ;
7
+ import { isSamePosition } from "../utils" ;
7
8
8
9
interface FakeToken extends Omit < RealToken , "type" > {
9
10
type : "raw-data" ;
@@ -33,6 +34,11 @@ export type SASAST = Program | Region | Statement | Token;
33
34
export const isComment = ( token : Token ) =>
34
35
token . type === "comment" || token . type === "macro-comment" ;
35
36
37
+ const isAtBlockEnd = ( block : FoldingBlock | undefined , token : Token ) =>
38
+ block &&
39
+ block . endLine === token . end . line &&
40
+ block . endCol === token . end . column ;
41
+
36
42
const removePrevStatement = ( parent : Program | Region ) => {
37
43
if ( parent . children . length <= 1 ) {
38
44
return ;
@@ -167,6 +173,58 @@ const preserveProcs = (
167
173
return current ;
168
174
} ;
169
175
176
+ const preserveCustomRegion = (
177
+ current : number ,
178
+ statement : Statement ,
179
+ model : Model ,
180
+ syntaxProvider : SyntaxProvider ,
181
+ ) => {
182
+ const token = statement . children [ statement . children . length - 1 ] ;
183
+ if ( current === - 1 ) {
184
+ if ( isComment ( token ) && / \* \s * r e g i o n \s + f o r m a t - i g n o r e \b / . test ( token . text ) ) {
185
+ const block = syntaxProvider . getFoldingBlock (
186
+ token . start . line ,
187
+ token . start . column ,
188
+ true ,
189
+ false ,
190
+ true ,
191
+ ) ;
192
+ if (
193
+ block &&
194
+ block . type === LexerEx . SEC_TYPE . CUSTOM &&
195
+ block . startLine === token . start . line &&
196
+ block . startCol === token . start . column
197
+ ) {
198
+ current = 0 ;
199
+ const start = token . start ;
200
+ const end = { line : block . endLine , column : block . endCol } ;
201
+ statement . children . pop ( ) ;
202
+ statement . children . push ( {
203
+ type : "raw-data" ,
204
+ text : model . getText ( { start, end } ) ,
205
+ start,
206
+ end,
207
+ } ) ;
208
+ }
209
+ }
210
+ } else if ( current === 0 ) {
211
+ statement . children . pop ( ) ;
212
+ if (
213
+ statement &&
214
+ statement . children . length > 0 &&
215
+ isSamePosition (
216
+ token . end ,
217
+ statement . children [ statement . children . length - 1 ] . end ,
218
+ )
219
+ ) {
220
+ current = 1 ;
221
+ }
222
+ } else if ( current === 1 ) {
223
+ return - 1 ;
224
+ }
225
+ return current ;
226
+ } ;
227
+
170
228
const preserveQuoting = (
171
229
current : number ,
172
230
statement : Statement ,
@@ -222,11 +280,13 @@ export const getParser =
222
280
let prevStatement : Statement | undefined = undefined ;
223
281
let quoting = - 1 ;
224
282
let preserveProc = - 1 ;
283
+ let preserveCustom = - 1 ;
225
284
226
285
for ( let i = 0 ; i < tokens . length ; i ++ ) {
227
286
const node = tokens [ i ] ;
228
287
let parent = parents . length ? parents [ parents . length - 1 ] : root ;
229
288
289
+ //#region --- Preserve Python/Lua
230
290
if ( region && region . block ) {
231
291
preserveProc = preserveProcs ( preserveProc , region , node , model ) ;
232
292
if ( preserveProc === 0 && i === tokens . length - 1 ) {
@@ -245,8 +305,9 @@ export const getParser =
245
305
if ( node . type === "embedded-code" ) {
246
306
continue ;
247
307
}
308
+ //#endregion ---
248
309
249
- // --- Check for block start: DATA, PROC, %MACRO ---
310
+ //#region --- Check for block start: DATA, PROC, %MACRO
250
311
if ( node . type === "sec-keyword" || node . type === "macro-sec-keyword" ) {
251
312
const block = syntaxProvider . getFoldingBlock (
252
313
node . start . line ,
@@ -276,9 +337,9 @@ export const getParser =
276
337
}
277
338
}
278
339
}
279
- // --- ---
340
+ //#endregion ---
280
341
281
- // --- Check for statement start ---
342
+ //#region --- Check for statement start
282
343
if ( ! currentStatement ) {
283
344
currentStatement = {
284
345
type : "statement" ,
@@ -301,16 +362,30 @@ export const getParser =
301
362
parent . children . push ( currentStatement ) ;
302
363
}
303
364
}
304
- // --- ---
365
+ //#endregion ---
305
366
306
367
currentStatement . children . push ( node ) ;
307
368
369
+ preserveCustom = preserveCustomRegion (
370
+ preserveCustom ,
371
+ currentStatement ,
372
+ model ,
373
+ syntaxProvider ,
374
+ ) ;
375
+ if ( preserveCustom >= 0 ) {
376
+ if ( preserveCustom === 1 ) {
377
+ prevStatement = currentStatement ;
378
+ currentStatement = undefined ;
379
+ }
380
+ continue ;
381
+ }
382
+
308
383
quoting = preserveQuoting ( quoting , currentStatement , model ) ;
309
384
if ( quoting >= 0 ) {
310
385
continue ;
311
386
}
312
387
313
- // --- Check for statement end ---
388
+ //#region --- Check for statement end
314
389
if ( node . type === "sep" && node . text === ";" ) {
315
390
if (
316
391
currentStatement . children [ 0 ] . type === "cards-data" &&
@@ -353,12 +428,7 @@ export const getParser =
353
428
// put `end` out of region children to outdent
354
429
parent . children . push ( region . children . pop ( ) ! ) ;
355
430
region = parents . pop ( ) ;
356
- } else if (
357
- region &&
358
- region . block &&
359
- region . block . endLine === node . end . line &&
360
- region . block . endCol === node . end . column
361
- ) {
431
+ } else if ( region && isAtBlockEnd ( region . block , node ) ) {
362
432
// block end
363
433
if ( / ^ ( r u n | q u i t | % m e n d ) \b / i. test ( currentStatement . children [ 0 ] . text ) ) {
364
434
// put `run` out of section children to outdent
@@ -389,12 +459,7 @@ export const getParser =
389
459
// standalone comment, treat as a whole statement
390
460
prevStatement = currentStatement ;
391
461
currentStatement = undefined ;
392
- if (
393
- region &&
394
- region . block &&
395
- region . block . endLine === node . end . line &&
396
- region . block . endCol === node . end . column
397
- ) {
462
+ if ( isAtBlockEnd ( region ?. block , node ) ) {
398
463
region = parents . pop ( ) ;
399
464
}
400
465
} else if (
@@ -411,7 +476,7 @@ export const getParser =
411
476
prevStatement = currentStatement ;
412
477
currentStatement = undefined ;
413
478
}
414
- // --- ---
479
+ //#endregion ---
415
480
}
416
481
417
482
return root ;
0 commit comments