@@ -880,6 +880,131 @@ namespace ts.projectSystem {
880
880
assert . isFalse ( host . fileExists ( `${ tscWatch . projectRoot } /test/file2.d.ts` ) ) ;
881
881
}
882
882
} ) ;
883
+
884
+ describe ( "compile on save in global files" , ( ) => {
885
+ describe ( "when program contains module" , ( ) => {
886
+ it ( "when d.ts emit is enabled" , ( ) => {
887
+ verifyGlobalSave ( /*declaration*/ true , /*hasModule*/ true ) ;
888
+ } ) ;
889
+ it ( "when d.ts emit is not enabled" , ( ) => {
890
+ verifyGlobalSave ( /*declaration*/ false , /*hasModule*/ true ) ;
891
+ } ) ;
892
+ } ) ;
893
+ describe ( "when program doesnt have module" , ( ) => {
894
+ it ( "when d.ts emit is enabled" , ( ) => {
895
+ verifyGlobalSave ( /*declaration*/ true , /*hasModule*/ false ) ;
896
+ } ) ;
897
+ it ( "when d.ts emit is not enabled" , ( ) => {
898
+ verifyGlobalSave ( /*declaration*/ false , /*hasModule*/ false ) ;
899
+ } ) ;
900
+ } ) ;
901
+ function verifyGlobalSave ( declaration : boolean , hasModule : boolean ) {
902
+ const config : File = {
903
+ path : `${ tscWatch . projectRoot } /tsconfig.json` ,
904
+ content : JSON . stringify ( {
905
+ compileOnSave : true ,
906
+ compilerOptions : {
907
+ declaration,
908
+ module : hasModule ? undefined : "none"
909
+ } ,
910
+ } )
911
+ } ;
912
+ const file1 : File = {
913
+ path : `${ tscWatch . projectRoot } /file1.ts` ,
914
+ content : `const x = 1;
915
+ function foo() {
916
+ return "hello";
917
+ }`
918
+ } ;
919
+ const file2 : File = {
920
+ path : `${ tscWatch . projectRoot } /file2.ts` ,
921
+ content : `const y = 2;
922
+ function bar() {
923
+ return "world";
924
+ }`
925
+ } ;
926
+ const file3 : File = {
927
+ path : `${ tscWatch . projectRoot } /file3.ts` ,
928
+ content : "const xy = 3;"
929
+ } ;
930
+ const module : File = {
931
+ path : `${ tscWatch . projectRoot } /module.ts` ,
932
+ content : "export const xyz = 4;"
933
+ } ;
934
+ const files = [ file1 , file2 , file3 , ...( hasModule ? [ module ] : emptyArray ) ] ;
935
+ const host = createServerHost ( [ ...files , config , libFile ] ) ;
936
+ const session = createSession ( host ) ;
937
+ openFilesForSession ( [ file1 , file2 ] , session ) ;
938
+
939
+ const affectedFileResponse = session . executeCommandSeq < protocol . CompileOnSaveAffectedFileListRequest > ( {
940
+ command : protocol . CommandTypes . CompileOnSaveAffectedFileList ,
941
+ arguments : { file : file1 . path }
942
+ } ) . response as protocol . CompileOnSaveAffectedFileListSingleProject [ ] ;
943
+ assert . deepEqual ( affectedFileResponse , [
944
+ { fileNames : files . map ( f => f . path ) , projectFileName : config . path , projectUsesOutFile : false }
945
+ ] ) ;
946
+ verifyFileSave ( file1 ) ;
947
+ verifyFileSave ( file2 ) ;
948
+ verifyFileSave ( file3 ) ;
949
+ if ( hasModule ) {
950
+ verifyFileSave ( module ) ;
951
+ }
952
+
953
+ // Change file1 get affected file list
954
+ verifyLocalEdit ( file1 , "hello" , "world" ) ;
955
+
956
+ // Change file2 get affected file list = will return only file2 if --declaration otherwise all files
957
+ verifyLocalEdit ( file2 , "world" , "hello" , /*returnsAllFilesAsAffected*/ ! declaration ) ;
958
+
959
+ function verifyFileSave ( file : File ) {
960
+ const response = session . executeCommandSeq < protocol . CompileOnSaveEmitFileRequest > ( {
961
+ command : protocol . CommandTypes . CompileOnSaveEmitFile ,
962
+ arguments : { file : file . path }
963
+ } ) . response ;
964
+ assert . isTrue ( response ) ;
965
+ assert . strictEqual (
966
+ host . readFile ( changeExtension ( file . path , ".js" ) ) ,
967
+ file === module ?
968
+ `"use strict";\nexports.__esModule = true;\nexports.xyz = void 0;\nexports.xyz = 4;\n` :
969
+ `${ file . content . replace ( "const" , "var" ) } \n`
970
+ ) ;
971
+ if ( declaration ) {
972
+ assert . strictEqual (
973
+ host . readFile ( changeExtension ( file . path , ".d.ts" ) ) ,
974
+ ( file . content . substr ( 0 , file . content . indexOf ( " {" ) === - 1 ? file . content . length : file . content . indexOf ( " {" ) )
975
+ . replace ( "const " , "declare const " )
976
+ . replace ( "function " , "declare function " )
977
+ . replace ( ")" , "): string;" ) ) + "\n"
978
+ ) ;
979
+ }
980
+ }
981
+
982
+ function verifyLocalEdit ( file : File , oldText : string , newText : string , returnsAllFilesAsAffected ?: boolean ) {
983
+ // Change file1 get affected file list
984
+ session . executeCommandSeq < protocol . UpdateOpenRequest > ( {
985
+ command : protocol . CommandTypes . UpdateOpen ,
986
+ arguments : {
987
+ changedFiles : [ {
988
+ fileName : file . path ,
989
+ textChanges : [ {
990
+ newText,
991
+ ...protocolTextSpanFromSubstring ( file . content , oldText )
992
+ } ]
993
+ } ]
994
+ }
995
+ } ) ;
996
+ const affectedFileResponse = session . executeCommandSeq < protocol . CompileOnSaveAffectedFileListRequest > ( {
997
+ command : protocol . CommandTypes . CompileOnSaveAffectedFileList ,
998
+ arguments : { file : file . path }
999
+ } ) . response as protocol . CompileOnSaveAffectedFileListSingleProject [ ] ;
1000
+ assert . deepEqual ( affectedFileResponse , [
1001
+ { fileNames : [ file . path , ...( returnsAllFilesAsAffected ? files . filter ( f => f !== file ) . map ( f => f . path ) : emptyArray ) ] , projectFileName : config . path , projectUsesOutFile : false }
1002
+ ] ) ;
1003
+ file . content = file . content . replace ( oldText , newText ) ;
1004
+ verifyFileSave ( file ) ;
1005
+ }
1006
+ }
1007
+ } ) ;
883
1008
} ) ;
884
1009
885
1010
describe ( "unittests:: tsserver:: compileOnSave:: CompileOnSaveAffectedFileListRequest with and without projectFileName in request" , ( ) => {
0 commit comments