@@ -831,5 +831,158 @@ module m3 { }\
831831 const index = source . indexOf ( "enum " ) + "enum " . length ;
832832 insertCode ( source , index , "Fo" ) ;
833833 } ) ;
834+
835+ describe ( "comment directives" , ( ) => {
836+ const tsIgnoreComment = "// @ts-ignore" ;
837+ const textWithIgnoreComment = `const x = 10;
838+ function foo() {
839+ // @ts-ignore
840+ let y: string = x;
841+ return y;
842+ }
843+ function bar() {
844+ // @ts-ignore
845+ let z : string = x;
846+ return z;
847+ }
848+ function bar3() {
849+ // @ts-ignore
850+ let z : string = x;
851+ return z;
852+ }
853+ foo();
854+ bar();
855+ bar3();` ;
856+ verifyScenario ( "when deleting ts-ignore comment" , verifyDelete ) ;
857+ verifyScenario ( "when inserting ts-ignore comment" , verifyInsert ) ;
858+ verifyScenario ( "when changing ts-ignore comment to blah" , verifyChangeToBlah ) ;
859+ verifyScenario ( "when changing blah comment to ts-ignore" , verifyChangeBackToDirective ) ;
860+ verifyScenario ( "when deleting blah comment" , verifyDeletingBlah ) ;
861+ verifyScenario ( "when changing text that adds another comment" , verifyChangeDirectiveType ) ;
862+ verifyScenario ( "when changing text that keeps the comment but adds more nodes" , verifyReuseChange ) ;
863+
864+ function verifyCommentDirectives ( oldText : IScriptSnapshot , newTextAndChange : { text : IScriptSnapshot ; textChangeRange : TextChangeRange ; } ) {
865+ const { incrementalNewTree, newTree } = compareTrees ( oldText , newTextAndChange . text , newTextAndChange . textChangeRange , - 1 ) ;
866+ assert . deepEqual ( incrementalNewTree . commentDirectives , newTree . commentDirectives ) ;
867+ }
868+
869+ function verifyScenario ( scenario : string , verifyChange : ( atIndex : number , singleIgnore ?: true ) => void ) {
870+ it ( `${ scenario } - 0` , ( ) => {
871+ verifyChange ( 0 ) ;
872+ } ) ;
873+ it ( `${ scenario } - 1` , ( ) => {
874+ verifyChange ( 1 ) ;
875+ } ) ;
876+ it ( `${ scenario } - 2` , ( ) => {
877+ verifyChange ( 2 ) ;
878+ } ) ;
879+ it ( `${ scenario } - with single ts-ignore` , ( ) => {
880+ verifyChange ( 0 , /*singleIgnore*/ true ) ;
881+ } ) ;
882+ }
883+
884+ function getIndexOfTsIgnoreComment ( atIndex : number ) {
885+ let index : number ;
886+ for ( let i = 0 ; i <= atIndex ; i ++ ) {
887+ index = textWithIgnoreComment . indexOf ( tsIgnoreComment ) ;
888+ }
889+ return index ! ;
890+ }
891+
892+ function textWithIgnoreCommentFrom ( text : string , singleIgnore : true | undefined ) {
893+ if ( ! singleIgnore ) return text ;
894+ const splits = text . split ( tsIgnoreComment ) ;
895+ if ( splits . length > 2 ) {
896+ const tail = splits [ splits . length - 2 ] + splits [ splits . length - 1 ] ;
897+ splits . length = splits . length - 2 ;
898+ return splits . join ( tsIgnoreComment ) + tail ;
899+ }
900+ else {
901+ return splits . join ( tsIgnoreComment ) ;
902+ }
903+ }
904+
905+ function verifyDelete ( atIndex : number , singleIgnore ?: true ) {
906+ const index = getIndexOfTsIgnoreComment ( atIndex ) ;
907+ const oldText = ScriptSnapshot . fromString ( textWithIgnoreCommentFrom ( textWithIgnoreComment , singleIgnore ) ) ;
908+ const newTextAndChange = withDelete ( oldText , index , tsIgnoreComment . length ) ;
909+ verifyCommentDirectives ( oldText , newTextAndChange ) ;
910+ }
911+
912+ function verifyInsert ( atIndex : number , singleIgnore ?: true ) {
913+ const index = getIndexOfTsIgnoreComment ( atIndex ) ;
914+ const source = textWithIgnoreCommentFrom ( textWithIgnoreComment . slice ( 0 , index ) + textWithIgnoreComment . slice ( index + tsIgnoreComment . length ) , singleIgnore ) ;
915+ const oldText = ScriptSnapshot . fromString ( source ) ;
916+ const newTextAndChange = withInsert ( oldText , index , tsIgnoreComment ) ;
917+ verifyCommentDirectives ( oldText , newTextAndChange ) ;
918+ }
919+
920+ function verifyChangeToBlah ( atIndex : number , singleIgnore ?: true ) {
921+ const index = getIndexOfTsIgnoreComment ( atIndex ) + "// " . length ;
922+ const oldText = ScriptSnapshot . fromString ( textWithIgnoreCommentFrom ( textWithIgnoreComment , singleIgnore ) ) ;
923+ const newTextAndChange = withChange ( oldText , index , 1 , "blah " ) ;
924+ verifyCommentDirectives ( oldText , newTextAndChange ) ;
925+ }
926+
927+ function verifyChangeBackToDirective ( atIndex : number , singleIgnore ?: true ) {
928+ const index = getIndexOfTsIgnoreComment ( atIndex ) + "// " . length ;
929+ const source = textWithIgnoreCommentFrom ( textWithIgnoreComment . slice ( 0 , index ) + "blah " + textWithIgnoreComment . slice ( index + 1 ) , singleIgnore ) ;
930+ const oldText = ScriptSnapshot . fromString ( source ) ;
931+ const newTextAndChange = withChange ( oldText , index , "blah " . length , "@" ) ;
932+ verifyCommentDirectives ( oldText , newTextAndChange ) ;
933+ }
934+
935+ function verifyDeletingBlah ( atIndex : number , singleIgnore ?: true ) {
936+ const tsIgnoreIndex = getIndexOfTsIgnoreComment ( atIndex ) ;
937+ const index = tsIgnoreIndex + "// " . length ;
938+ const source = textWithIgnoreCommentFrom ( textWithIgnoreComment . slice ( 0 , index ) + "blah " + textWithIgnoreComment . slice ( index + 1 ) , singleIgnore ) ;
939+ const oldText = ScriptSnapshot . fromString ( source ) ;
940+ const newTextAndChange = withDelete ( oldText , tsIgnoreIndex , tsIgnoreComment . length + "blah" . length ) ;
941+ verifyCommentDirectives ( oldText , newTextAndChange ) ;
942+ }
943+
944+ function verifyChangeDirectiveType ( atIndex : number , singleIgnore ?: true ) {
945+ const index = getIndexOfTsIgnoreComment ( atIndex ) + "// @ts-" . length ;
946+ const oldText = ScriptSnapshot . fromString ( textWithIgnoreCommentFrom ( textWithIgnoreComment , singleIgnore ) ) ;
947+ const newTextAndChange = withChange ( oldText , index , "ignore" . length , "expect-error" ) ;
948+ verifyCommentDirectives ( oldText , newTextAndChange ) ;
949+ }
950+
951+ function verifyReuseChange ( atIndex : number , singleIgnore ?: true ) {
952+ const source = `const x = 10;
953+ function foo1() {
954+ const x1 = 10;
955+ // @ts-ignore
956+ let y0: string = x;
957+ let y1: string = x;
958+ return y1;
959+ }
960+ function foo2() {
961+ const x2 = 10;
962+ // @ts-ignore
963+ let y0: string = x;
964+ let y2: string = x;
965+ return y2;
966+ }
967+ function foo3() {
968+ const x3 = 10;
969+ // @ts-ignore
970+ let y0: string = x;
971+ let y3: string = x;
972+ return y3;
973+ }
974+ foo1();
975+ foo2();
976+ foo3();` ;
977+ const oldText = ScriptSnapshot . fromString ( textWithIgnoreCommentFrom ( source , singleIgnore ) ) ;
978+ const start = source . indexOf ( `const x${ atIndex + 1 } ` ) ;
979+ const letStr = `let y${ atIndex + 1 } : string = x;` ;
980+ const end = source . indexOf ( letStr ) + letStr . length ;
981+ const oldSubStr = source . slice ( start , end ) ;
982+ const newText = oldSubStr . replace ( letStr , `let yn : string = x;` ) ;
983+ const newTextAndChange = withChange ( oldText , start , end - start , newText ) ;
984+ verifyCommentDirectives ( oldText , newTextAndChange ) ;
985+ }
986+ } ) ;
834987 } ) ;
835988}
0 commit comments