@@ -36,7 +36,7 @@ namespace ts {
3636 }
3737
3838 safeFileList = < Path > "" ;
39- postInstallActions : ( ( map : ( t : string [ ] ) => string [ ] ) => void ) [ ] = [ ] ;
39+ postInstallActions : ( ( map : ( t : string [ ] ) => string [ ] ) => void ) [ ] = [ ] ;
4040
4141 runPostInstallActions ( map : ( t : string [ ] ) => string [ ] ) {
4242 for ( const f of this . postInstallActions ) {
@@ -281,7 +281,7 @@ namespace ts {
281281 private timeoutCallbacks = new Callbacks ( ) ;
282282 private immediateCallbacks = new Callbacks ( ) ;
283283
284- readonly watchedDirectories = createMap < { cb : DirectoryWatcherCallback , recursive : boolean } [ ] > ( ) ;
284+ readonly watchedDirectories = createMap < { cb : DirectoryWatcherCallback , recursive : boolean } [ ] > ( ) ;
285285 readonly watchedFiles = createMap < FileWatcherCallback [ ] > ( ) ;
286286
287287 private filesOrFolders : FileOrFolder [ ] ;
@@ -2011,7 +2011,7 @@ namespace ts {
20112011
20122012 checkNumberOfProjects ( projectService , { configuredProjects : 1 } ) ;
20132013 const p = projectService . configuredProjects [ 0 ] ;
2014- checkProjectActualFiles ( p , [ file1 . path ] ) ;
2014+ checkProjectActualFiles ( p , [ file1 . path ] ) ;
20152015
20162016 assert ( host . fileExists ( combinePaths ( installer . cachePath , "tsd.json" ) ) ) ;
20172017
@@ -2021,10 +2021,10 @@ namespace ts {
20212021 return [ "jquery/jquery.d.ts" ] ;
20222022 } ) ;
20232023 checkNumberOfProjects ( projectService , { configuredProjects : 1 } ) ;
2024- checkProjectActualFiles ( p , [ file1 . path , jquery . path ] ) ;
2024+ checkProjectActualFiles ( p , [ file1 . path , jquery . path ] ) ;
20252025 } ) ;
20262026
2027- it ( "inferred project (tsd installed)" , ( ) => {
2027+ it ( "inferred project (tsd installed)" , ( ) => {
20282028 const file1 = {
20292029 path : "/a/b/app.js" ,
20302030 content : ""
@@ -2051,7 +2051,7 @@ namespace ts {
20512051
20522052 checkNumberOfProjects ( projectService , { inferredProjects : 1 } ) ;
20532053 const p = projectService . inferredProjects [ 0 ] ;
2054- checkProjectActualFiles ( p , [ file1 . path ] ) ;
2054+ checkProjectActualFiles ( p , [ file1 . path ] ) ;
20552055
20562056 assert ( host . fileExists ( combinePaths ( installer . cachePath , "tsd.json" ) ) ) ;
20572057
@@ -2061,10 +2061,10 @@ namespace ts {
20612061 return [ "jquery/jquery.d.ts" ] ;
20622062 } ) ;
20632063 checkNumberOfProjects ( projectService , { inferredProjects : 1 } ) ;
2064- checkProjectActualFiles ( p , [ file1 . path , jquery . path ] ) ;
2064+ checkProjectActualFiles ( p , [ file1 . path , jquery . path ] ) ;
20652065 } ) ;
20662066
2067- it ( "external project - no typing options, no .d.ts/js files" , ( ) => {
2067+ it ( "external project - no typing options, no .d.ts/js files" , ( ) => {
20682068 const file1 = {
20692069 path : "/a/b/app.ts" ,
20702070 content : ""
@@ -2091,7 +2091,7 @@ namespace ts {
20912091 projectService . checkNumberOfProjects ( { externalProjects : 1 } ) ;
20922092 } ) ;
20932093
2094- it ( "external project - no autoDiscovery in typing options, no .d.ts/js files" , ( ) => {
2094+ it ( "external project - no autoDiscovery in typing options, no .d.ts/js files" , ( ) => {
20952095 const file1 = {
20962096 path : "/a/b/app.ts" ,
20972097 content : ""
@@ -2119,7 +2119,7 @@ namespace ts {
21192119 projectService . checkNumberOfProjects ( { externalProjects : 1 } ) ;
21202120 } ) ;
21212121
2122- it ( "external project - autoDiscovery = true, no .d.ts/js files" , ( ) => {
2122+ it ( "external project - autoDiscovery = true, no .d.ts/js files" , ( ) => {
21232123 const file1 = {
21242124 path : "/a/b/app.ts" ,
21252125 content : ""
@@ -2156,4 +2156,209 @@ namespace ts {
21562156 assert . isTrue ( runTsdIsCalled , "expected 'runTsdIsCalled' to be true" ) ;
21572157 } ) ;
21582158 } ) ;
2159+
2160+ describe ( "Project errors" , ( ) => {
2161+ function checkProjectErrors ( projectFiles : server . ProjectFilesWithTSDiagnostics , expectedErrors : string [ ] ) {
2162+ assert . isTrue ( projectFiles !== undefined , "missing project files" ) ;
2163+ const errors = projectFiles . projectErrors ;
2164+ assert . equal ( errors ? errors . length : 0 , expectedErrors . length , `expected ${ expectedErrors . length } error in the list` ) ;
2165+ if ( expectedErrors . length ) {
2166+ for ( let i = 0 ; i < errors . length ; i ++ ) {
2167+ const actualMessage = flattenDiagnosticMessageText ( errors [ i ] . messageText , "\n" ) ;
2168+ const expectedMessage = expectedErrors [ i ] ;
2169+ assert . equal ( actualMessage , expectedMessage , "error message does not match" ) ;
2170+ }
2171+ }
2172+ }
2173+
2174+ it ( "external project - diagnostics for missing files" , ( ) => {
2175+ const file1 = {
2176+ path : "/a/b/app.ts" ,
2177+ content : ""
2178+ } ;
2179+ const file2 = {
2180+ path : "/a/b/lib.ts" ,
2181+ content : ""
2182+ } ;
2183+ // only file1 exists - expect error
2184+ const host = createServerHost ( [ file1 ] ) ;
2185+ const projectService = createProjectService ( host ) ;
2186+ const projectFileName = "/a/b/test.csproj" ;
2187+
2188+ {
2189+ projectService . openExternalProject ( {
2190+ projectFileName,
2191+ options : { } ,
2192+ rootFiles : toExternalFiles ( [ file1 . path , file2 . path ] )
2193+ } ) ;
2194+
2195+ projectService . checkNumberOfProjects ( { externalProjects : 1 } ) ;
2196+ const knownProjects = projectService . synchronizeProjectList ( [ ] ) ;
2197+ checkProjectErrors ( knownProjects [ 0 ] , [ "File '/a/b/lib.ts' not found." ] ) ;
2198+ }
2199+ // only file2 exists - expect error
2200+ host . reloadFS ( [ file2 ] ) ;
2201+ {
2202+ projectService . openExternalProject ( {
2203+ projectFileName,
2204+ options : { } ,
2205+ rootFiles : toExternalFiles ( [ file1 . path , file2 . path ] )
2206+ } ) ;
2207+ projectService . checkNumberOfProjects ( { externalProjects : 1 } ) ;
2208+ const knownProjects = projectService . synchronizeProjectList ( [ ] ) ;
2209+ checkProjectErrors ( knownProjects [ 0 ] , [ "File '/a/b/app.ts' not found." ] ) ;
2210+ }
2211+
2212+ // both files exist - expect no errors
2213+ host . reloadFS ( [ file1 , file2 ] ) ;
2214+ {
2215+ projectService . openExternalProject ( {
2216+ projectFileName,
2217+ options : { } ,
2218+ rootFiles : toExternalFiles ( [ file1 . path , file2 . path ] )
2219+ } ) ;
2220+
2221+ projectService . checkNumberOfProjects ( { externalProjects : 1 } ) ;
2222+ const knownProjects = projectService . synchronizeProjectList ( [ ] ) ;
2223+ checkProjectErrors ( knownProjects [ 0 ] , [ ] ) ;
2224+ }
2225+ } ) ;
2226+
2227+ it ( "configured projects - diagnostics for missing files" , ( ) => {
2228+ const file1 = {
2229+ path : "/a/b/app.ts" ,
2230+ content : ""
2231+ } ;
2232+ const file2 = {
2233+ path : "/a/b/lib.ts" ,
2234+ content : ""
2235+ } ;
2236+ const config = {
2237+ path : "/a/b/tsconfig.json" ,
2238+ content : JSON . stringify ( { files : [ file1 , file2 ] . map ( f => getBaseFileName ( f . path ) ) } )
2239+ } ;
2240+ const host = createServerHost ( [ file1 , config ] ) ;
2241+ const projectService = createProjectService ( host ) ;
2242+
2243+ projectService . openClientFile ( file1 . path ) ;
2244+ projectService . checkNumberOfProjects ( { configuredProjects : 1 } ) ;
2245+ checkProjectErrors ( projectService . synchronizeProjectList ( [ ] ) [ 0 ] , [ "File '/a/b/lib.ts' not found." ] ) ;
2246+
2247+ host . reloadFS ( [ file1 , file2 , config ] ) ;
2248+
2249+ projectService . openClientFile ( file1 . path ) ;
2250+ projectService . checkNumberOfProjects ( { configuredProjects : 1 } ) ;
2251+ checkProjectErrors ( projectService . synchronizeProjectList ( [ ] ) [ 0 ] , [ ] ) ;
2252+ } ) ;
2253+
2254+ it ( "configured projects - diagnostics for corrupted config 1" , ( ) => {
2255+ const file1 = {
2256+ path : "/a/b/app.ts" ,
2257+ content : ""
2258+ } ;
2259+ const file2 = {
2260+ path : "/a/b/lib.ts" ,
2261+ content : ""
2262+ } ;
2263+ const correctConfig = {
2264+ path : "/a/b/tsconfig.json" ,
2265+ content : JSON . stringify ( { files : [ file1 , file2 ] . map ( f => getBaseFileName ( f . path ) ) } )
2266+ } ;
2267+ const corruptedConfig = {
2268+ path : correctConfig . path ,
2269+ content : correctConfig . content . substr ( 1 )
2270+ } ;
2271+ const host = createServerHost ( [ file1 , file2 , corruptedConfig ] ) ;
2272+ const projectService = createProjectService ( host ) ;
2273+
2274+ projectService . openClientFile ( file1 . path ) ;
2275+ {
2276+ projectService . checkNumberOfProjects ( { inferredProjects : 1 , configuredProjects : 1 } ) ;
2277+ const configuredProject = forEach ( projectService . synchronizeProjectList ( [ ] ) , f => f . info . projectName === corruptedConfig . path && f ) ;
2278+ assert . isTrue ( configuredProject !== undefined , "should find configured project" ) ;
2279+ checkProjectErrors ( configuredProject , [ `Failed to parse file \'/a/b/tsconfig.json\': Unexpected token : in JSON at position 7.` ] ) ;
2280+ }
2281+ // fix config and trigger watcher
2282+ host . reloadFS ( [ file1 , file2 , correctConfig ] ) ;
2283+ host . triggerFileWatcherCallback ( correctConfig . path , /*false*/ ) ;
2284+ {
2285+ projectService . checkNumberOfProjects ( { configuredProjects : 1 } ) ;
2286+ const configuredProject = forEach ( projectService . synchronizeProjectList ( [ ] ) , f => f . info . projectName === corruptedConfig . path && f ) ;
2287+ assert . isTrue ( configuredProject !== undefined , "should find configured project" ) ;
2288+ checkProjectErrors ( configuredProject , [ ] ) ;
2289+ }
2290+ } ) ;
2291+
2292+ it ( "configured projects - diagnostics for corrupted config 2" , ( ) => {
2293+ const file1 = {
2294+ path : "/a/b/app.ts" ,
2295+ content : ""
2296+ } ;
2297+ const file2 = {
2298+ path : "/a/b/lib.ts" ,
2299+ content : ""
2300+ } ;
2301+ const correctConfig = {
2302+ path : "/a/b/tsconfig.json" ,
2303+ content : JSON . stringify ( { files : [ file1 , file2 ] . map ( f => getBaseFileName ( f . path ) ) } )
2304+ } ;
2305+ const corruptedConfig = {
2306+ path : correctConfig . path ,
2307+ content : correctConfig . content . substr ( 1 )
2308+ } ;
2309+ const host = createServerHost ( [ file1 , file2 , correctConfig ] ) ;
2310+ const projectService = createProjectService ( host ) ;
2311+
2312+ projectService . openClientFile ( file1 . path ) ;
2313+ {
2314+ projectService . checkNumberOfProjects ( { configuredProjects : 1 } ) ;
2315+ const configuredProject = forEach ( projectService . synchronizeProjectList ( [ ] ) , f => f . info . projectName === corruptedConfig . path && f ) ;
2316+ assert . isTrue ( configuredProject !== undefined , "should find configured project" ) ;
2317+ checkProjectErrors ( configuredProject , [ ] ) ;
2318+ }
2319+ // fix config and trigger watcher
2320+ host . reloadFS ( [ file1 , file2 , corruptedConfig ] ) ;
2321+ host . triggerFileWatcherCallback ( corruptedConfig . path , /*false*/ ) ;
2322+ {
2323+ projectService . checkNumberOfProjects ( { inferredProjects : 1 , configuredProjects : 1 } ) ;
2324+ const configuredProject = forEach ( projectService . synchronizeProjectList ( [ ] ) , f => f . info . projectName === corruptedConfig . path && f ) ;
2325+ assert . isTrue ( configuredProject !== undefined , "should find configured project" ) ;
2326+ checkProjectErrors ( configuredProject , [ `Failed to parse file \'/a/b/tsconfig.json\': Unexpected token : in JSON at position 7.` ] ) ;
2327+ }
2328+ } ) ;
2329+ } ) ;
2330+
2331+ describe ( "Proper errors" , ( ) => {
2332+ it ( "document is not contained in project" , ( ) => {
2333+ const file1 = {
2334+ path : "/a/b/app.ts" ,
2335+ content : ""
2336+ } ;
2337+ const corruptedConfig = {
2338+ path : "/a/b/tsconfig.json" ,
2339+ content : "{"
2340+ } ;
2341+ const host = createServerHost ( [ file1 , corruptedConfig ] ) ;
2342+ const projectService = createProjectService ( host ) ;
2343+
2344+ projectService . openClientFile ( file1 . path ) ;
2345+ projectService . checkNumberOfProjects ( { inferredProjects : 1 , configuredProjects : 1 } ) ;
2346+
2347+ const project = projectService . findProject ( corruptedConfig . path ) ;
2348+ let expectedMessage : string ;
2349+ try {
2350+ server . Errors . ThrowProjectDoesNotContainDocument ( file1 . path , project ) ;
2351+ assert ( false , "should not get there" ) ;
2352+ }
2353+ catch ( e ) {
2354+ expectedMessage = ( < Error > e ) . message ;
2355+ }
2356+ try {
2357+ project . getScriptInfo ( file1 . path ) ;
2358+ }
2359+ catch ( e ) {
2360+ assert . equal ( ( < Error > e ) . message , expectedMessage , "Unexpected error" ) ;
2361+ }
2362+ } ) ;
2363+ } ) ;
21592364}
0 commit comments