@@ -339,6 +339,22 @@ namespace ts.textChanges {
339
339
this . insertText ( sourceFile , token . getStart ( sourceFile ) , text ) ;
340
340
}
341
341
342
+ public insertJsdocCommentBefore ( sourceFile : SourceFile , fn : FunctionDeclaration | FunctionExpression , tag : JSDocTag ) : void {
343
+ const existingJsdoc = fn . jsDoc && firstOrUndefined ( fn . jsDoc ) ;
344
+ if ( existingJsdoc ) {
345
+ // `/** foo */` --> `/**\n * @constructor\n * foo */`
346
+ const jsdocStart = existingJsdoc . getStart ( sourceFile ) ;
347
+ const indent = getIndent ( sourceFile , jsdocStart ) ;
348
+ const indentAsterisk = `${ this . newLineCharacter } ${ indent } *` ;
349
+ this . insertNodeAt ( sourceFile , jsdocStart + "/**" . length , tag , { prefix : `${ indentAsterisk } ` , suffix : indentAsterisk } ) ;
350
+ }
351
+ else {
352
+ const fnStart = fn . getStart ( sourceFile ) ;
353
+ const indent = getIndent ( sourceFile , fnStart ) ;
354
+ this . insertNodeAt ( sourceFile , fnStart , tag , { prefix : "/** " , suffix : ` */${ this . newLineCharacter } ${ indent } ` } ) ;
355
+ }
356
+ }
357
+
342
358
public replaceRangeWithText ( sourceFile : SourceFile , range : TextRange , text : string ) {
343
359
this . changes . push ( { kind : ChangeKind . Text , sourceFile, range, text } ) ;
344
360
}
@@ -720,6 +736,11 @@ namespace ts.textChanges {
720
736
}
721
737
}
722
738
739
+ function getIndent ( sourceFile : SourceFile , position : number ) : string {
740
+ const lineStart = getStartPositionOfLine ( getLineAndCharacterOfPosition ( sourceFile , position ) . line , sourceFile ) ;
741
+ return sourceFile . text . slice ( lineStart , position ) ;
742
+ }
743
+
723
744
// find first non-whitespace position in the leading trivia of the node
724
745
function startPositionToDeleteNodeInList ( sourceFile : SourceFile , node : Node ) : number {
725
746
return skipTrivia ( sourceFile . text , getAdjustedStartPosition ( sourceFile , node , { } , Position . FullStart ) , /*stopAfterLineBreak*/ false , /*stopAtComments*/ true ) ;
@@ -788,21 +809,35 @@ namespace ts.textChanges {
788
809
}
789
810
790
811
/** Note: this may mutate `nodeIn`. */
791
- function getFormattedTextOfNode ( nodeIn : Node , sourceFile : SourceFile , pos : number , { indentation, prefix, delta } : InsertNodeOptions , newLineCharacter : string , formatContext : formatting . FormatContext , validate : ValidateNonFormattedText | undefined ) : string {
792
- const { node, text } = getNonformattedText ( nodeIn , sourceFile , newLineCharacter ) ;
793
- if ( validate ) validate ( node , text ) ;
794
- const { options : formatOptions } = formatContext ;
795
- const initialIndentation =
796
- indentation !== undefined
797
- ? indentation
798
- : formatting . SmartIndenter . getIndentation ( pos , sourceFile , formatOptions , prefix === newLineCharacter || getLineStartPositionForPosition ( pos , sourceFile ) === pos ) ;
799
- if ( delta === undefined ) {
800
- delta = formatting . SmartIndenter . shouldIndentChildNode ( formatContext . options , nodeIn ) ? ( formatOptions . indentSize || 0 ) : 0 ;
812
+ export function getFormattedTextOfNode ( nodeIn : Node , sourceFile : SourceFile , pos : number , { indentation, prefix, delta } : InsertNodeOptions , newLineCharacter : string , formatContext : formatting . FormatContext , validate : ValidateNonFormattedText | undefined ) : string {
813
+ // Emitter doesn't handle JSDoc, so generate that here.
814
+ if ( isJSDocTag ( nodeIn ) ) {
815
+ switch ( nodeIn . kind ) {
816
+ case SyntaxKind . JSDocClassTag :
817
+ return "@class" ;
818
+ case SyntaxKind . JSDocThisTag :
819
+ const { typeExpression } = nodeIn as JSDocThisTag ;
820
+ return typeExpression ? `@this {${ getNonformattedText ( typeExpression . type , sourceFile , newLineCharacter ) . text } }` : "@this" ;
821
+ default :
822
+ return Debug . fail ( ) ; // TODO (if this is needed)
823
+ }
801
824
}
825
+ else {
826
+ const { node, text } = getNonformattedText ( nodeIn , sourceFile , newLineCharacter ) ;
827
+ if ( validate ) validate ( node , text ) ;
828
+ const { options : formatOptions } = formatContext ;
829
+ const initialIndentation =
830
+ indentation !== undefined
831
+ ? indentation
832
+ : formatting . SmartIndenter . getIndentation ( pos , sourceFile , formatOptions , prefix === newLineCharacter || getLineStartPositionForPosition ( pos , sourceFile ) === pos ) ;
833
+ if ( delta === undefined ) {
834
+ delta = formatting . SmartIndenter . shouldIndentChildNode ( formatContext . options , nodeIn ) ? ( formatOptions . indentSize || 0 ) : 0 ;
835
+ }
802
836
803
- const file : SourceFileLike = { text, getLineAndCharacterOfPosition ( pos ) { return getLineAndCharacterOfPosition ( this , pos ) ; } } ;
804
- const changes = formatting . formatNodeGivenIndentation ( node , file , sourceFile . languageVariant , initialIndentation , delta , formatContext ) ;
805
- return applyChanges ( text , changes ) ;
837
+ const file : SourceFileLike = { text, getLineAndCharacterOfPosition ( pos ) { return getLineAndCharacterOfPosition ( this , pos ) ; } } ;
838
+ const changes = formatting . formatNodeGivenIndentation ( node , file , sourceFile . languageVariant , initialIndentation , delta , formatContext ) ;
839
+ return applyChanges ( text , changes ) ;
840
+ }
806
841
}
807
842
808
843
/** Note: output node may be mutated input node. */
@@ -1103,15 +1138,23 @@ namespace ts.textChanges {
1103
1138
deleteImportBinding ( changes , sourceFile , node as NamespaceImport ) ;
1104
1139
break ;
1105
1140
1141
+ case SyntaxKind . SemicolonToken :
1142
+ deleteNode ( changes , sourceFile , node , { useNonAdjustedEndPosition : true } ) ;
1143
+ break ;
1144
+
1145
+ case SyntaxKind . FunctionKeyword :
1146
+ deleteNode ( changes , sourceFile , node , { useNonAdjustedStartPosition : true } ) ;
1147
+ break ;
1148
+
1106
1149
default :
1107
1150
if ( isImportClause ( node . parent ) && node . parent . name === node ) {
1108
1151
deleteDefaultImport ( changes , sourceFile , node . parent ) ;
1109
1152
}
1110
- else if ( isCallLikeExpression ( node . parent ) ) {
1153
+ else if ( isCallExpression ( node . parent ) && contains ( node . parent . arguments , node ) ) {
1111
1154
deleteNodeInList ( changes , deletedNodesInLists , sourceFile , node ) ;
1112
1155
}
1113
1156
else {
1114
- deleteNode ( changes , sourceFile , node , node . kind === SyntaxKind . SemicolonToken ? { useNonAdjustedEndPosition : true } : undefined ) ;
1157
+ deleteNode ( changes , sourceFile , node ) ;
1115
1158
}
1116
1159
}
1117
1160
}
0 commit comments