@@ -8,27 +8,29 @@ import {
88 EnumMemberNode ,
99 EnumSpreadMemberNode ,
1010 EnumStatementNode ,
11+ Expression ,
1112 getNamespaceFullName ,
1213 getSourceLocation ,
1314 IdentifierNode ,
1415 InterfaceStatementNode ,
1516 IntersectionExpressionNode ,
16- listServices ,
1717 MemberExpressionNode ,
1818 ModelExpressionNode ,
1919 ModelPropertyNode ,
2020 ModelSpreadPropertyNode ,
2121 ModelStatementNode ,
2222 Namespace ,
2323 navigateProgram ,
24- NoTarget ,
2524 NumericLiteralNode ,
2625 OperationSignatureDeclarationNode ,
2726 OperationSignatureReferenceNode ,
2827 OperationStatementNode ,
2928 Program ,
3029 ScalarStatementNode ,
3130 StringLiteralNode ,
31+ StringTemplateExpressionNode ,
32+ StringTemplateHeadNode ,
33+ StringTemplateSpanNode ,
3234 SyntaxKind ,
3335 TemplateArgumentNode ,
3436 TemplateParameterDeclarationNode ,
@@ -43,7 +45,6 @@ import { ApiViewDiagnostic, ApiViewDiagnosticLevel } from "./diagnostic.js";
4345import { ApiViewNavigation } from "./navigation.js" ;
4446import { generateId , NamespaceModel } from "./namespace-model.js" ;
4547import { LIB_VERSION } from "./version.js" ;
46- import { reportDiagnostic } from "./lib.js" ;
4748
4849const WHITESPACE = " " ;
4950
@@ -383,6 +384,7 @@ export class ApiView {
383384 this . namespaceStack . push ( obj . id . sv ) ;
384385 this . keyword ( "alias" , false , true ) ;
385386 this . typeDeclaration ( obj . id . sv , this . namespaceStack . value ( ) , true ) ;
387+ this . tokenizeTemplateParameters ( obj . templateParameters ) ;
386388 this . punctuation ( "=" , true , true ) ;
387389 this . tokenize ( obj . value ) ;
388390 this . namespaceStack . pop ( ) ;
@@ -633,10 +635,83 @@ export class ApiView {
633635 this . tokenize ( obj . argument ) ;
634636 }
635637 break ;
638+ case SyntaxKind . StringTemplateExpression :
639+ obj = node as StringTemplateExpressionNode ;
640+ const stringValue = this . buildTemplateString ( obj ) ;
641+ const multiLine = stringValue . includes ( "\n" ) ;
642+ // single line case
643+ if ( ! multiLine ) {
644+ this . stringLiteral ( stringValue ) ;
645+ break ;
646+ }
647+ // otherwise multiline case
648+ const lines = stringValue . split ( "\n" ) ;
649+ this . punctuation ( `"""` ) ;
650+ this . newline ( ) ;
651+ this . indent ( ) ;
652+ for ( const line of lines ) {
653+ this . literal ( line ) ;
654+ this . newline ( ) ;
655+ }
656+ this . deindent ( ) ;
657+ this . punctuation ( `"""` ) ;
658+ break ;
659+ case SyntaxKind . StringTemplateSpan :
660+ obj = node as StringTemplateSpanNode ;
661+ this . punctuation ( "${" , false , false ) ;
662+ this . tokenize ( obj . expression ) ;
663+ this . punctuation ( "}" , false , false ) ;
664+ this . tokenize ( obj . literal ) ;
665+ break ;
666+ case SyntaxKind . StringTemplateHead :
667+ case SyntaxKind . StringTemplateMiddle :
668+ case SyntaxKind . StringTemplateTail :
669+ obj = node as StringTemplateHeadNode ;
670+ this . literal ( obj . value ) ;
671+ break ;
672+ default :
673+ // All Projection* cases should fail here...
674+ throw new Error ( `Case "${ SyntaxKind [ node . kind ] . toString ( ) } " not implemented` ) ;
675+ }
676+ }
677+
678+ private buildExpressionString ( node : Expression ) {
679+ switch ( node . kind ) {
680+ case SyntaxKind . StringLiteral :
681+ return `"${ ( node as StringLiteralNode ) . value } "` ;
682+ case SyntaxKind . NumericLiteral :
683+ return ( node as NumericLiteralNode ) . value . toString ( ) ;
684+ case SyntaxKind . BooleanLiteral :
685+ return ( node as BooleanLiteralNode ) . value . toString ( ) ;
686+ case SyntaxKind . StringTemplateExpression :
687+ return this . buildTemplateString ( node as StringTemplateExpressionNode ) ;
688+ case SyntaxKind . VoidKeyword :
689+ return "void" ;
690+ case SyntaxKind . NeverKeyword :
691+ return "never" ;
692+ case SyntaxKind . TypeReference :
693+ const obj = node as TypeReferenceNode ;
694+ switch ( obj . target . kind ) {
695+ case SyntaxKind . Identifier :
696+ return ( obj . target as IdentifierNode ) . sv ;
697+ case SyntaxKind . MemberExpression :
698+ return this . getFullyQualifiedIdentifier ( obj . target as MemberExpressionNode ) ;
699+ }
700+ break ;
636701 default :
637- // All Projection* cases should fall in here...
638- throw new Error ( `Case "${ node . kind . toString ( ) } " not implemented` ) ;
702+ throw new Error ( `Unsupported expression kind: ${ SyntaxKind [ node . kind ] } ` ) ;
703+ //unsupported ArrayExpressionNode | MemberExpressionNode | ModelExpressionNode | TupleExpressionNode | UnionExpressionNode | IntersectionExpressionNode | TypeReferenceNode | ValueOfExpressionNode | AnyKeywordNode;
704+ }
705+ }
706+
707+ /** Constructs a single string with template markers. */
708+ private buildTemplateString ( node : StringTemplateExpressionNode ) : string {
709+ let result = node . head . value ;
710+ for ( const span of node . spans ) {
711+ result += "${" + this . buildExpressionString ( span . expression ) + "}" ;
712+ result += span . literal . value ;
639713 }
714+ return result ;
640715 }
641716
642717 private tokenizeModelStatement ( node : ModelStatementNode ) {
@@ -891,6 +966,7 @@ export class ApiView {
891966 }
892967 for ( const node of model . aliases . values ( ) ) {
893968 this . tokenize ( node ) ;
969+ this . punctuation ( ";" ) ;
894970 this . blankLines ( 1 ) ;
895971 }
896972 this . endGroup ( ) ;
0 commit comments