1- /// <reference path="..\harness.ts" />
1+ /// <reference path="..\harness.ts" />
22/// <reference path="../../server/typingsInstaller/typingsInstaller.ts" />
33
44namespace ts . projectSystem {
@@ -136,6 +136,19 @@ namespace ts.projectSystem {
136136 return map ( fileNames , toExternalFile ) ;
137137 }
138138
139+ export class TestServerEventManager {
140+ private events : server . ProjectServiceEvent [ ] = [ ] ;
141+
142+ handler : server . ProjectServiceEventHandler = ( event : server . ProjectServiceEvent ) => {
143+ this . events . push ( event ) ;
144+ }
145+
146+ checkEventCountOfType ( eventType : "context" | "configFileDiag" , expectedCount : number ) {
147+ const eventsOfType = filter ( this . events , e => e . eventName === eventType ) ;
148+ assert . equal ( eventsOfType . length , expectedCount , `The actual event counts of type ${ eventType } is ${ eventsOfType . length } , while expected ${ expectedCount } ` ) ;
149+ }
150+ }
151+
139152 export interface TestServerHostCreationParameters {
140153 useCaseSensitiveFileNames ?: boolean ;
141154 executingFilePath ?: string ;
@@ -159,11 +172,11 @@ namespace ts.projectSystem {
159172 return host ;
160173 }
161174
162- export function createSession ( host : server . ServerHost , typingsInstaller ?: server . ITypingsInstaller ) {
175+ export function createSession ( host : server . ServerHost , typingsInstaller ?: server . ITypingsInstaller , projectServiceEventHandler ?: server . ProjectServiceEventHandler ) {
163176 if ( typingsInstaller === undefined ) {
164177 typingsInstaller = new TestTypingsInstaller ( "/a/data/" , /*throttleLimit*/ 5 , host ) ;
165178 }
166- return new server . Session ( host , nullCancellationToken , /*useSingleInferredProject*/ false , typingsInstaller , Utils . byteLength , process . hrtime , nullLogger , /*canUseEvents*/ false ) ;
179+ return new server . Session ( host , nullCancellationToken , /*useSingleInferredProject*/ false , typingsInstaller , Utils . byteLength , process . hrtime , nullLogger , /*canUseEvents*/ projectServiceEventHandler !== undefined , projectServiceEventHandler ) ;
167180 }
168181
169182 export interface CreateProjectServiceParameters {
@@ -2084,7 +2097,7 @@ namespace ts.projectSystem {
20842097 const projectFileName = "externalProject" ;
20852098 const host = createServerHost ( [ f ] ) ;
20862099 const projectService = createProjectService ( host ) ;
2087- // create a project
2100+ // create a project
20882101 projectService . openExternalProject ( { projectFileName, rootFiles : [ toExternalFile ( f . path ) ] , options : { } } ) ;
20892102 projectService . checkNumberOfProjects ( { externalProjects : 1 } ) ;
20902103
@@ -2121,4 +2134,179 @@ namespace ts.projectSystem {
21212134 projectService . inferredProjects [ 0 ] . getLanguageService ( ) . getProgram ( ) ;
21222135 } ) ;
21232136 } ) ;
2137+
2138+ describe ( "rename a module file and rename back" , ( ) => {
2139+ it ( "should restore the states for inferred projects" , ( ) => {
2140+ const moduleFile = {
2141+ path : "/a/b/moduleFile.ts" ,
2142+ content : "export function bar() { };"
2143+ } ;
2144+ const file1 = {
2145+ path : "/a/b/file1.ts" ,
2146+ content : "import * as T from './moduleFile'; T.bar();"
2147+ } ;
2148+ const host = createServerHost ( [ moduleFile , file1 ] ) ;
2149+ const session = createSession ( host ) ;
2150+
2151+ openFilesForSession ( [ file1 ] , session ) ;
2152+ const getErrRequest = makeSessionRequest < server . protocol . SemanticDiagnosticsSyncRequestArgs > (
2153+ server . CommandNames . SemanticDiagnosticsSync ,
2154+ { file : file1 . path }
2155+ ) ;
2156+ let diags = < server . protocol . Diagnostic [ ] > session . executeCommand ( getErrRequest ) . response ;
2157+ assert . equal ( diags . length , 0 ) ;
2158+
2159+ const moduleFileOldPath = moduleFile . path ;
2160+ const moduleFileNewPath = "/a/b/moduleFile1.ts" ;
2161+ moduleFile . path = moduleFileNewPath ;
2162+ host . reloadFS ( [ moduleFile , file1 ] ) ;
2163+ host . triggerFileWatcherCallback ( moduleFileOldPath ) ;
2164+ host . triggerDirectoryWatcherCallback ( "/a/b" , moduleFile . path ) ;
2165+ host . runQueuedTimeoutCallbacks ( ) ;
2166+ diags = < server . protocol . Diagnostic [ ] > session . executeCommand ( getErrRequest ) . response ;
2167+ assert . equal ( diags . length , 1 ) ;
2168+
2169+ moduleFile . path = moduleFileOldPath ;
2170+ host . reloadFS ( [ moduleFile , file1 ] ) ;
2171+ host . triggerFileWatcherCallback ( moduleFileNewPath ) ;
2172+ host . triggerDirectoryWatcherCallback ( "/a/b" , moduleFile . path ) ;
2173+ host . runQueuedTimeoutCallbacks ( ) ;
2174+
2175+ // Make a change to trigger the program rebuild
2176+ const changeRequest = makeSessionRequest < server . protocol . ChangeRequestArgs > (
2177+ server . CommandNames . Change ,
2178+ { file : file1 . path , line : 1 , offset : 44 , endLine : 1 , endOffset : 44 , insertString : "\n" }
2179+ ) ;
2180+ session . executeCommand ( changeRequest ) ;
2181+ host . runQueuedTimeoutCallbacks ( ) ;
2182+
2183+ diags = < server . protocol . Diagnostic [ ] > session . executeCommand ( getErrRequest ) . response ;
2184+ assert . equal ( diags . length , 0 ) ;
2185+ } ) ;
2186+
2187+ it ( "should restore the states for configured projects" , ( ) => {
2188+ const moduleFile = {
2189+ path : "/a/b/moduleFile.ts" ,
2190+ content : "export function bar() { };"
2191+ } ;
2192+ const file1 = {
2193+ path : "/a/b/file1.ts" ,
2194+ content : "import * as T from './moduleFile'; T.bar();"
2195+ } ;
2196+ const configFile = {
2197+ path : "/a/b/tsconfig.json" ,
2198+ content : `{}`
2199+ } ;
2200+ const host = createServerHost ( [ moduleFile , file1 , configFile ] ) ;
2201+ const session = createSession ( host ) ;
2202+
2203+ openFilesForSession ( [ file1 ] , session ) ;
2204+ const getErrRequest = makeSessionRequest < server . protocol . SemanticDiagnosticsSyncRequestArgs > (
2205+ server . CommandNames . SemanticDiagnosticsSync ,
2206+ { file : file1 . path }
2207+ ) ;
2208+ let diags = < server . protocol . Diagnostic [ ] > session . executeCommand ( getErrRequest ) . response ;
2209+ assert . equal ( diags . length , 0 ) ;
2210+
2211+ const moduleFileOldPath = moduleFile . path ;
2212+ const moduleFileNewPath = "/a/b/moduleFile1.ts" ;
2213+ moduleFile . path = moduleFileNewPath ;
2214+ host . reloadFS ( [ moduleFile , file1 , configFile ] ) ;
2215+ host . triggerFileWatcherCallback ( moduleFileOldPath ) ;
2216+ host . triggerDirectoryWatcherCallback ( "/a/b" , moduleFile . path ) ;
2217+ host . runQueuedTimeoutCallbacks ( ) ;
2218+ diags = < server . protocol . Diagnostic [ ] > session . executeCommand ( getErrRequest ) . response ;
2219+ assert . equal ( diags . length , 1 ) ;
2220+
2221+ moduleFile . path = moduleFileOldPath ;
2222+ host . reloadFS ( [ moduleFile , file1 , configFile ] ) ;
2223+ host . triggerFileWatcherCallback ( moduleFileNewPath ) ;
2224+ host . triggerDirectoryWatcherCallback ( "/a/b" , moduleFile . path ) ;
2225+ host . runQueuedTimeoutCallbacks ( ) ;
2226+ diags = < server . protocol . Diagnostic [ ] > session . executeCommand ( getErrRequest ) . response ;
2227+ assert . equal ( diags . length , 0 ) ;
2228+ } ) ;
2229+
2230+ } ) ;
2231+
2232+ describe ( "add the missing module file for inferred project" , ( ) => {
2233+ it ( "should remove the `module not found` error" , ( ) => {
2234+ const moduleFile = {
2235+ path : "/a/b/moduleFile.ts" ,
2236+ content : "export function bar() { };"
2237+ } ;
2238+ const file1 = {
2239+ path : "/a/b/file1.ts" ,
2240+ content : "import * as T from './moduleFile'; T.bar();"
2241+ } ;
2242+ const host = createServerHost ( [ file1 ] ) ;
2243+ const session = createSession ( host ) ;
2244+ openFilesForSession ( [ file1 ] , session ) ;
2245+ const getErrRequest = makeSessionRequest < server . protocol . SemanticDiagnosticsSyncRequestArgs > (
2246+ server . CommandNames . SemanticDiagnosticsSync ,
2247+ { file : file1 . path }
2248+ ) ;
2249+ let diags = < server . protocol . Diagnostic [ ] > session . executeCommand ( getErrRequest ) . response ;
2250+ assert . equal ( diags . length , 1 ) ;
2251+
2252+ host . reloadFS ( [ file1 , moduleFile ] ) ;
2253+ host . triggerDirectoryWatcherCallback ( getDirectoryPath ( file1 . path ) , moduleFile . path ) ;
2254+ host . runQueuedTimeoutCallbacks ( ) ;
2255+
2256+ // Make a change to trigger the program rebuild
2257+ const changeRequest = makeSessionRequest < server . protocol . ChangeRequestArgs > (
2258+ server . CommandNames . Change ,
2259+ { file : file1 . path , line : 1 , offset : 44 , endLine : 1 , endOffset : 44 , insertString : "\n" }
2260+ ) ;
2261+ session . executeCommand ( changeRequest ) ;
2262+
2263+ // Recheck
2264+ diags = < server . protocol . Diagnostic [ ] > session . executeCommand ( getErrRequest ) . response ;
2265+ assert . equal ( diags . length , 0 ) ;
2266+ } ) ;
2267+ } ) ;
2268+
2269+ describe ( "Configure file diagnostics events" , ( ) => {
2270+
2271+ it ( "are generated when the config file has errors" , ( ) => {
2272+ const serverEventManager = new TestServerEventManager ( ) ;
2273+ const file = {
2274+ path : "/a/b/app.ts" ,
2275+ content : "let x = 10"
2276+ } ;
2277+ const configFile = {
2278+ path : "/a/b/tsconfig.json" ,
2279+ content : `{
2280+ "compilerOptions": {
2281+ "foo": "bar",
2282+ "allowJS": true
2283+ }
2284+ }`
2285+ } ;
2286+
2287+ const host = createServerHost ( [ file , configFile ] ) ;
2288+ const session = createSession ( host , /*typingsInstaller*/ undefined , serverEventManager . handler ) ;
2289+ openFilesForSession ( [ file ] , session ) ;
2290+ serverEventManager . checkEventCountOfType ( "configFileDiag" , 1 ) ;
2291+ } ) ;
2292+
2293+ it ( "are generated when the config file doesn't have errors" , ( ) => {
2294+ const serverEventManager = new TestServerEventManager ( ) ;
2295+ const file = {
2296+ path : "/a/b/app.ts" ,
2297+ content : "let x = 10"
2298+ } ;
2299+ const configFile = {
2300+ path : "/a/b/tsconfig.json" ,
2301+ content : `{
2302+ "compilerOptions": {}
2303+ }`
2304+ } ;
2305+
2306+ const host = createServerHost ( [ file , configFile ] ) ;
2307+ const session = createSession ( host , /*typingsInstaller*/ undefined , serverEventManager . handler ) ;
2308+ openFilesForSession ( [ file ] , session ) ;
2309+ serverEventManager . checkEventCountOfType ( "configFileDiag" , 1 ) ;
2310+ } ) ;
2311+ } ) ;
21242312}
0 commit comments