1+ // Adapted from @prettier /plugin-yuku to use SWC Next:
2+ // https://github.com/prettier/prettier/tree/main/packages/plugin-yuku
3+
14import * as prettierEstreePlugin from 'prettier/plugins/estree' ;
25import type { Parser , ParserOptions , Plugin } from 'prettier' ;
36import {
7+ CommentMode ,
8+ Lang ,
9+ SourceType ,
410 langFromPath ,
5- parse as parseWithYuku ,
11+ parseSync as parseWithSwcNext ,
612 type Comment ,
713 type Diagnostic ,
8- type ParseOptions ,
914 type ParseResult ,
10- type SourceLang ,
11- type SourceType ,
12- } from 'yuku-parser' ;
15+ } from '@swc-next/parser' ;
1316
14- const AST_FORMAT = 'estree-yuku ' ;
17+ const AST_FORMAT = 'estree-swc-next ' ;
1518const JS_TS_FILE_REGEXP = / \. (?: j s | m j s | c j s | j s x | t s | m t s | c t s | t s x ) $ / i;
1619const JSX_REGEXP = / ^ [ ^ " ' ` ] * < \/ | ^ [ ^ / ] { 2 } .* \/ > / m;
17- const SOURCE_TYPE_COMBINATIONS : SourceType [ ] = [ 'module' , 'commonjs' ] ;
20+ const SOURCE_TYPE_COMBINATIONS : SourceType [ ] = [
21+ SourceType . Module ,
22+ SourceType . CommonJs ,
23+ ] ;
1824
1925type Range = [ start : number , end : number ] ;
2026
@@ -158,7 +164,7 @@ const isAstNode = (value: unknown): value is AstNode =>
158164
159165const asAstNode = ( value : unknown ) : AstNode => {
160166 if ( ! isAstNode ( value ) ) {
161- throw new TypeError ( 'Expected a Yuku AST node.' ) ;
167+ throw new TypeError ( 'Expected a SWC Next AST node.' ) ;
162168 }
163169 return value ;
164170} ;
@@ -220,7 +226,7 @@ const stripComments = (
220226 const chunks : string [ ] = [ ] ;
221227 let cursor = 0 ;
222228
223- // Yuku returns comments in source order, so mask each range while copying the source only once.
229+ // SWC Next returns comments in source order, so mask each range while copying the source only once.
224230 for ( const comment of comments ) {
225231 const start = locStart ( comment ) ;
226232 const end = locEnd ( comment ) ;
@@ -356,7 +362,7 @@ const postprocess = (
356362 ast : AstNode ,
357363 comments : PrettierComment [ ] ,
358364 text : string ,
359- astType : 'yuku- js' | 'yuku -ts' ,
365+ astType : 'swc-next- js' | 'swc-next -ts' ,
360366) : AstNode => {
361367 mergeNestedJsdocComments ( comments ) ;
362368
@@ -384,7 +390,7 @@ const postprocess = (
384390 const expression = asAstNode ( node . expression ) ;
385391 const start = locStart ( node ) ;
386392
387- // Yuku comments are in source order, so these end offsets are sorted.
393+ // SWC Next comments are in source order, so these end offsets are sorted.
388394 typeCastCommentEnds ??= comments
389395 . filter ( isTypeCastComment )
390396 . map ( ( comment ) => locEnd ( comment ) ) ;
@@ -415,7 +421,7 @@ const postprocess = (
415421 }
416422
417423 case 'TemplateElement' : {
418- if ( astType === 'yuku -ts' ) {
424+ if ( astType === 'swc-next -ts' ) {
419425 const start = locStart ( node ) + 1 ;
420426 const end = locEnd ( node ) - ( node . tail ? 1 : 2 ) ;
421427 node . range = [ start , end ] ;
@@ -482,11 +488,13 @@ const createParseError = (error: Diagnostic, text: string): SyntaxError => {
482488 ) ;
483489} ;
484490
485- const parseWithOptions = ( text : string , options : ParseOptions ) : ParseResult => {
486- const result = parseWithYuku ( text , {
491+ const parseWithOptions = (
492+ text : string ,
493+ options : { sourceType : SourceType ; lang : Lang } ,
494+ ) : ParseResult => {
495+ const result = parseWithSwcNext ( text , {
487496 preserveParens : true ,
488- semanticErrors : false ,
489- attachComments : false ,
497+ comments : CommentMode . Flat ,
490498 ...options ,
491499 } ) ;
492500
@@ -499,28 +507,27 @@ const parseWithOptions = (text: string, options: ParseOptions): ParseResult => {
499507
500508const getSourceType = ( filepath : string ) : SourceType | undefined => {
501509 if ( / \. (?: m j s | m t s ) $ / i. test ( filepath ) ) {
502- return 'module' ;
510+ return SourceType . Module ;
503511 }
504512
505513 if ( / \. (?: c j s | c t s ) $ / i. test ( filepath ) ) {
506- return 'commonjs' ;
514+ return SourceType . CommonJs ;
507515 }
508516
509517 return undefined ;
510518} ;
511519
512- const getLanguageCombinations = (
513- text : string ,
514- filepath : string ,
515- ) : SourceLang [ ] => {
520+ const getLanguageCombinations = ( text : string , filepath : string ) : Lang [ ] => {
516521 const normalizedPath = filepath . toLowerCase ( ) ;
517522
518523 if ( JS_TS_FILE_REGEXP . test ( normalizedPath ) ) {
519524 return [ langFromPath ( normalizedPath ) ] ;
520525 }
521526
522527 // Embedded code from Vue or Svelte keeps the host file path, so detect JSX from its content.
523- return JSX_REGEXP . test ( text ) ? [ 'tsx' , 'ts' , 'dts' ] : [ 'ts' , 'tsx' , 'dts' ] ;
528+ return JSX_REGEXP . test ( text )
529+ ? [ Lang . Tsx , Lang . Ts , Lang . Dts ]
530+ : [ Lang . Ts , Lang . Tsx , Lang . Dts ] ;
524531} ;
525532
526533const tryCombinations = ( combinations : ( ( ) => ParseResult ) [ ] ) : ParseResult => {
@@ -542,7 +549,7 @@ const tryCombinations = (combinations: (() => ParseResult)[]): ParseResult => {
542549 throw firstError ;
543550 }
544551
545- throw new Error ( 'No Yuku parser combinations were provided.' ) ;
552+ throw new Error ( 'No SWC Next parser combinations were provided.' ) ;
546553} ;
547554
548555const parseJavaScript = (
@@ -554,11 +561,16 @@ const parseJavaScript = (
554561 sourceType ? [ sourceType ] : SOURCE_TYPE_COMBINATIONS
555562 ) . map (
556563 ( candidate ) => ( ) =>
557- parseWithOptions ( text , { sourceType : candidate , lang : 'jsx' } ) ,
564+ parseWithOptions ( text , { sourceType : candidate , lang : Lang . Jsx } ) ,
558565 ) ;
559- const { program , comments } = tryCombinations ( combinations ) ;
566+ const result = tryCombinations ( combinations ) ;
560567
561- return postprocess ( program as unknown as AstNode , comments , text , 'yuku-js' ) ;
568+ return postprocess (
569+ asAstNode ( result . program ) ,
570+ result . comments ,
571+ text ,
572+ 'swc-next-js' ,
573+ ) ;
562574} ;
563575
564576const parseTypeScript = (
@@ -574,9 +586,14 @@ const parseTypeScript = (
574586 ( lang ) => ( ) => parseWithOptions ( text , { sourceType : candidate , lang } ) ,
575587 ) ,
576588 ) ;
577- const { program , comments } = tryCombinations ( combinations ) ;
589+ const result = tryCombinations ( combinations ) ;
578590
579- return postprocess ( program as unknown as AstNode , comments , text , 'yuku-ts' ) ;
591+ return postprocess (
592+ asAstNode ( result . program ) ,
593+ result . comments ,
594+ text ,
595+ 'swc-next-ts' ,
596+ ) ;
580597} ;
581598
582599const createParser = (
@@ -611,23 +628,23 @@ const parseBabel = (text: string, options: ParserOptions<AstNode>): AstNode => {
611628 } ;
612629} ;
613630
614- const yukuParser = createParser ( parseJavaScript ) ;
615- const yukuBabelParser = createParser ( parseBabel ) ;
616- const yukuTypeScriptParser = createParser ( parseTypeScript ) ;
631+ const swcNextParser = createParser ( parseJavaScript ) ;
632+ const swcNextBabelParser = createParser ( parseBabel ) ;
633+ const swcNextTypeScriptParser = createParser ( parseTypeScript ) ;
617634
618- const yukuPlugin : Plugin = {
635+ const swcNextPlugin : Plugin = {
619636 options : estreePlugin . options ,
620637 parsers : {
621638 // Prettier resolves parsers from the last plugin that provides the name.
622639 // Project plugins are loaded after this one, so parser wrappers take priority.
623- babel : yukuBabelParser ,
624- typescript : yukuTypeScriptParser ,
625- yuku : yukuParser ,
626- 'yuku- ts' : yukuTypeScriptParser ,
640+ babel : swcNextBabelParser ,
641+ typescript : swcNextTypeScriptParser ,
642+ 'swc-next' : swcNextParser ,
643+ 'swc-next- ts' : swcNextTypeScriptParser ,
627644 } ,
628645 printers : {
629646 [ AST_FORMAT ] : estreePrinter ,
630647 } ,
631648} ;
632649
633- export { yukuPlugin } ;
650+ export { swcNextPlugin } ;
0 commit comments