@@ -217,9 +217,9 @@ namespace ts.projectSystem {
217
217
constructor ( ) {
218
218
super ( host ) ;
219
219
}
220
- enqueueInstallTypingsRequest ( project : server . Project , typingOptions : TypingOptions ) {
220
+ enqueueInstallTypingsRequest ( project : server . Project , typingOptions : TypingOptions , unresolvedImports : server . SortedReadonlyArray < string > ) {
221
221
enqueueIsCalled = true ;
222
- super . enqueueInstallTypingsRequest ( project , typingOptions ) ;
222
+ super . enqueueInstallTypingsRequest ( project , typingOptions , unresolvedImports ) ;
223
223
}
224
224
executeRequest ( requestKind : TI . RequestKind , _requestId : number , _args : string [ ] , _cwd : string , cb : TI . RequestCompletedAction ) : void {
225
225
const installedTypings = [ "@types/jquery" ] ;
@@ -319,9 +319,9 @@ namespace ts.projectSystem {
319
319
constructor ( ) {
320
320
super ( host ) ;
321
321
}
322
- enqueueInstallTypingsRequest ( project : server . Project , typingOptions : TypingOptions ) {
322
+ enqueueInstallTypingsRequest ( project : server . Project , typingOptions : TypingOptions , unresolvedImports : server . SortedReadonlyArray < string > ) {
323
323
enqueueIsCalled = true ;
324
- super . enqueueInstallTypingsRequest ( project , typingOptions ) ;
324
+ super . enqueueInstallTypingsRequest ( project , typingOptions , unresolvedImports ) ;
325
325
}
326
326
executeRequest ( requestKind : TI . RequestKind , _requestId : number , _args : string [ ] , _cwd : string , cb : TI . RequestCompletedAction ) : void {
327
327
const installedTypings : string [ ] = [ ] ;
@@ -724,7 +724,7 @@ namespace ts.projectSystem {
724
724
it ( "Malformed package.json should be watched" , ( ) => {
725
725
const f = {
726
726
path : "/a/b/app.js" ,
727
- content : "var x = require('commander') "
727
+ content : "var x = 1 "
728
728
} ;
729
729
const brokenPackageJson = {
730
730
path : "/a/b/package.json" ,
@@ -763,6 +763,133 @@ namespace ts.projectSystem {
763
763
service . checkNumberOfProjects ( { inferredProjects : 1 } ) ;
764
764
checkProjectActualFiles ( service . inferredProjects [ 0 ] , [ f . path , commander . path ] ) ;
765
765
} ) ;
766
+
767
+ it ( "should install typings for unresolved imports" , ( ) => {
768
+ const file = {
769
+ path : "/a/b/app.js" ,
770
+ content : `
771
+ import * as fs from "fs";
772
+ import * as commander from "commander";`
773
+ } ;
774
+ const cachePath = "/a/cache" ;
775
+ const node = {
776
+ path : cachePath + "/node_modules/@types/node/index.d.ts" ,
777
+ content : "export let x: number"
778
+ } ;
779
+ const commander = {
780
+ path : cachePath + "/node_modules/@types/commander/index.d.ts" ,
781
+ content : "export let y: string"
782
+ } ;
783
+ const host = createServerHost ( [ file ] ) ;
784
+ const installer = new ( class extends Installer {
785
+ constructor ( ) {
786
+ super ( host , { globalTypingsCacheLocation : cachePath } ) ;
787
+ }
788
+ executeRequest ( requestKind : TI . RequestKind , _requestId : number , _args : string [ ] , _cwd : string , cb : server . typingsInstaller . RequestCompletedAction ) {
789
+ const installedTypings = [ "@types/node" , "@types/commander" ] ;
790
+ const typingFiles = [ node , commander ] ;
791
+ executeCommand ( this , host , installedTypings , typingFiles , requestKind , cb ) ;
792
+ }
793
+ } ) ( ) ;
794
+ const service = createProjectService ( host , { typingsInstaller : installer } ) ;
795
+ service . openClientFile ( file . path ) ;
796
+
797
+ service . checkNumberOfProjects ( { inferredProjects : 1 } ) ;
798
+ checkProjectActualFiles ( service . inferredProjects [ 0 ] , [ file . path ] ) ;
799
+
800
+ installer . installAll ( [ TI . NpmViewRequest , TI . NpmViewRequest ] , [ TI . NpmInstallRequest ] ) ;
801
+
802
+ assert . isTrue ( host . fileExists ( node . path ) , "typings for 'node' should be created" ) ;
803
+ assert . isTrue ( host . fileExists ( commander . path ) , "typings for 'commander' should be created" ) ;
804
+
805
+ checkProjectActualFiles ( service . inferredProjects [ 0 ] , [ file . path , node . path , commander . path ] ) ;
806
+ } ) ;
807
+
808
+ it ( "should pick typing names from non-relative unresolved imports" , ( ) => {
809
+ const f1 = {
810
+ path : "/a/b/app.js" ,
811
+ content : `
812
+ import * as a from "foo/a/a";
813
+ import * as b from "foo/a/b";
814
+ import * as c from "foo/a/c";
815
+ import * as d from "@bar/router/";
816
+ import * as e from "@bar/common/shared";
817
+ import * as e from "@bar/common/apps";
818
+ import * as f from "./lib"
819
+ `
820
+ } ;
821
+
822
+ const host = createServerHost ( [ f1 ] ) ;
823
+ const installer = new ( class extends Installer {
824
+ constructor ( ) {
825
+ super ( host , { globalTypingsCacheLocation : "/tmp" } ) ;
826
+ }
827
+ executeRequest ( requestKind : TI . RequestKind , _requestId : number , args : string [ ] , _cwd : string , cb : server . typingsInstaller . RequestCompletedAction ) {
828
+ if ( requestKind === TI . NpmViewRequest ) {
829
+ // args should have only non-scoped packages - scoped packages are not yet supported
830
+ assert . deepEqual ( args , [ "foo" ] ) ;
831
+ }
832
+ executeCommand ( this , host , [ "foo" ] , [ ] , requestKind , cb ) ;
833
+ }
834
+ } ) ( ) ;
835
+ const projectService = createProjectService ( host , { typingsInstaller : installer } ) ;
836
+ projectService . openClientFile ( f1 . path ) ;
837
+ projectService . checkNumberOfProjects ( { inferredProjects : 1 } ) ;
838
+
839
+ const proj = projectService . inferredProjects [ 0 ] ;
840
+ proj . updateGraph ( ) ;
841
+
842
+ assert . deepEqual (
843
+ proj . getCachedUnresolvedImportsPerFile_TestOnly ( ) . get ( < Path > f1 . path ) ,
844
+ [ "foo" , "foo" , "foo" , "@bar/router" , "@bar/common" , "@bar/common" ]
845
+ ) ;
846
+
847
+ installer . installAll ( [ TI . NpmViewRequest ] , [ TI . NpmInstallRequest ] ) ;
848
+ } ) ;
849
+
850
+ it ( "cached unresolved typings are not recomputed if program structure did not change" , ( ) => {
851
+ const host = createServerHost ( [ ] ) ;
852
+ const session = createSession ( host ) ;
853
+ const f = {
854
+ path : "/a/app.js" ,
855
+ content : `
856
+ import * as fs from "fs";
857
+ import * as cmd from "commander
858
+ `
859
+ } ;
860
+ session . executeCommand ( < server . protocol . OpenRequest > {
861
+ seq : 1 ,
862
+ type : "request" ,
863
+ command : "open" ,
864
+ arguments : {
865
+ file : f . path ,
866
+ fileContent : f . content
867
+ }
868
+ } ) ;
869
+ const projectService = session . getProjectService ( ) ;
870
+ checkNumberOfProjects ( projectService , { inferredProjects : 1 } ) ;
871
+ const proj = projectService . inferredProjects [ 0 ] ;
872
+ const version1 = proj . getCachedUnresolvedImportsPerFile_TestOnly ( ) . getVersion ( ) ;
873
+
874
+ // make a change that should not affect the structure of the program
875
+ session . executeCommand ( < server . protocol . ChangeRequest > {
876
+ seq : 2 ,
877
+ type : "request" ,
878
+ command : "change" ,
879
+ arguments : {
880
+ file : f . path ,
881
+ insertString : "\nlet x = 1;" ,
882
+ line : 2 ,
883
+ offset : 0 ,
884
+ endLine : 2 ,
885
+ endOffset : 0
886
+ }
887
+ } ) ;
888
+ host . checkTimeoutQueueLength ( 1 ) ;
889
+ host . runQueuedTimeoutCallbacks ( ) ;
890
+ const version2 = proj . getCachedUnresolvedImportsPerFile_TestOnly ( ) . getVersion ( ) ;
891
+ assert . equal ( version1 , version2 , "set of unresolved imports should not change" ) ;
892
+ } ) ;
766
893
} ) ;
767
894
768
895
describe ( "Validate package name:" , ( ) => {
@@ -820,4 +947,35 @@ namespace ts.projectSystem {
820
947
assert . isTrue ( messages . indexOf ( "Package name '; say ‘Hello from TypeScript!’ #' contains non URI safe characters" ) > 0 , "should find package with invalid name" ) ;
821
948
} ) ;
822
949
} ) ;
950
+
951
+ describe ( "discover typings" , ( ) => {
952
+ it ( "should return node for core modules" , ( ) => {
953
+ const f = {
954
+ path : "/a/b/app.js" ,
955
+ content : ""
956
+ } ;
957
+ const host = createServerHost ( [ f ] ) ;
958
+ const cache = createMap < string > ( ) ;
959
+ for ( const name of JsTyping . nodeCoreModuleList ) {
960
+ const result = JsTyping . discoverTypings ( host , [ f . path ] , getDirectoryPath ( < Path > f . path ) , /*safeListPath*/ undefined , cache , { enableAutoDiscovery : true } , [ name , "somename" ] ) ;
961
+ assert . deepEqual ( result . newTypingNames . sort ( ) , [ "node" , "somename" ] ) ;
962
+ }
963
+ } ) ;
964
+
965
+ it ( "should use cached locaitons" , ( ) => {
966
+ const f = {
967
+ path : "/a/b/app.js" ,
968
+ content : ""
969
+ } ;
970
+ const node = {
971
+ path : "/a/b/node.d.ts" ,
972
+ content : ""
973
+ } ;
974
+ const host = createServerHost ( [ f , node ] ) ;
975
+ const cache = createMap < string > ( { "node" : node . path } ) ;
976
+ const result = JsTyping . discoverTypings ( host , [ f . path ] , getDirectoryPath ( < Path > f . path ) , /*safeListPath*/ undefined , cache , { enableAutoDiscovery : true } , [ "fs" , "bar" ] ) ;
977
+ assert . deepEqual ( result . cachedTypingPaths , [ node . path ] ) ;
978
+ assert . deepEqual ( result . newTypingNames , [ "bar" ] ) ;
979
+ } ) ;
980
+ } ) ;
823
981
}
0 commit comments