@@ -355,6 +355,10 @@ namespace ts.server {
355355 * Open files: with value being project root path, and key being Path of the file that is open
356356 */
357357 readonly openFiles = createMap < NormalizedPath > ( ) ;
358+ /**
359+ * Map of open files that are opened without complete path but have projectRoot as current directory
360+ */
361+ private readonly openFilesWithNonRootedDiskPath = createMap < ScriptInfo > ( ) ;
358362
359363 private compilerOptionsForInferredProjects : CompilerOptions ;
360364 private compilerOptionsForInferredProjectsPerProjectRoot = createMap < CompilerOptions > ( ) ;
@@ -932,12 +936,16 @@ namespace ts.server {
932936 // Closing file should trigger re-reading the file content from disk. This is
933937 // because the user may chose to discard the buffer content before saving
934938 // to the disk, and the server's version of the file can be out of sync.
935- info . close ( ) ;
939+ const fileExists = this . host . fileExists ( info . fileName ) ;
940+ info . close ( fileExists ) ;
936941 this . stopWatchingConfigFilesForClosedScriptInfo ( info ) ;
937942
938943 this . openFiles . delete ( info . path ) ;
944+ const canonicalFileName = this . toCanonicalFileName ( info . fileName ) ;
945+ if ( this . openFilesWithNonRootedDiskPath . get ( canonicalFileName ) === info ) {
946+ this . openFilesWithNonRootedDiskPath . delete ( canonicalFileName ) ;
947+ }
939948
940- const fileExists = this . host . fileExists ( info . fileName ) ;
941949
942950 // collect all projects that should be removed
943951 let projectsToRemove : Project [ ] ;
@@ -1537,7 +1545,7 @@ namespace ts.server {
15371545 else {
15381546 const scriptKind = propertyReader . getScriptKind ( f , this . hostConfiguration . extraFileExtensions ) ;
15391547 const hasMixedContent = propertyReader . hasMixedContent ( f , this . hostConfiguration . extraFileExtensions ) ;
1540- scriptInfo = this . getOrCreateScriptInfoNotOpenedByClientForNormalizedPath ( normalizedPath , scriptKind , hasMixedContent , project . directoryStructureHost ) ;
1548+ scriptInfo = this . getOrCreateScriptInfoNotOpenedByClientForNormalizedPath ( normalizedPath , project . currentDirectory , scriptKind , hasMixedContent , project . directoryStructureHost ) ;
15411549 path = scriptInfo . path ;
15421550 // If this script info is not already a root add it
15431551 if ( ! project . isRoot ( scriptInfo ) ) {
@@ -1691,9 +1699,9 @@ namespace ts.server {
16911699 }
16921700
16931701 /*@internal */
1694- getOrCreateScriptInfoNotOpenedByClient ( uncheckedFileName : string , hostToQueryFileExistsOn : DirectoryStructureHost ) {
1702+ getOrCreateScriptInfoNotOpenedByClient ( uncheckedFileName : string , currentDirectory : string , hostToQueryFileExistsOn : DirectoryStructureHost ) {
16951703 return this . getOrCreateScriptInfoNotOpenedByClientForNormalizedPath (
1696- toNormalizedPath ( uncheckedFileName ) , /*scriptKind*/ undefined ,
1704+ toNormalizedPath ( uncheckedFileName ) , currentDirectory , /*scriptKind*/ undefined ,
16971705 /*hasMixedContent*/ undefined , hostToQueryFileExistsOn
16981706 ) ;
16991707 }
@@ -1724,20 +1732,26 @@ namespace ts.server {
17241732 }
17251733
17261734 /*@internal */
1727- getOrCreateScriptInfoNotOpenedByClientForNormalizedPath ( fileName : NormalizedPath , scriptKind ? : ScriptKind , hasMixedContent ? : boolean , hostToQueryFileExistsOn ? : DirectoryStructureHost ) {
1728- return this . getOrCreateScriptInfoForNormalizedPath ( fileName , /*openedByClient*/ false , /*fileContent*/ undefined , scriptKind , hasMixedContent , hostToQueryFileExistsOn ) ;
1735+ getOrCreateScriptInfoNotOpenedByClientForNormalizedPath ( fileName : NormalizedPath , currentDirectory : string , scriptKind : ScriptKind | undefined , hasMixedContent : boolean | undefined , hostToQueryFileExistsOn : DirectoryStructureHost | undefined ) {
1736+ return this . getOrCreateScriptInfoWorker ( fileName , currentDirectory , /*openedByClient*/ false , /*fileContent*/ undefined , scriptKind , hasMixedContent , hostToQueryFileExistsOn ) ;
17291737 }
17301738
17311739 /*@internal */
1732- getOrCreateScriptInfoOpenedByClientForNormalizedPath ( fileName : NormalizedPath , fileContent ? : string , scriptKind ? : ScriptKind , hasMixedContent ? : boolean , hostToQueryFileExistsOn ?: DirectoryStructureHost ) {
1733- return this . getOrCreateScriptInfoForNormalizedPath ( fileName , /*openedByClient*/ true , fileContent , scriptKind , hasMixedContent , hostToQueryFileExistsOn ) ;
1740+ getOrCreateScriptInfoOpenedByClientForNormalizedPath ( fileName : NormalizedPath , currentDirectory : string , fileContent : string | undefined , scriptKind : ScriptKind | undefined , hasMixedContent : boolean | undefined ) {
1741+ return this . getOrCreateScriptInfoWorker ( fileName , currentDirectory , /*openedByClient*/ true , fileContent , scriptKind , hasMixedContent ) ;
17341742 }
17351743
17361744 getOrCreateScriptInfoForNormalizedPath ( fileName : NormalizedPath , openedByClient : boolean , fileContent ?: string , scriptKind ?: ScriptKind , hasMixedContent ?: boolean , hostToQueryFileExistsOn ?: DirectoryStructureHost ) {
1745+ return this . getOrCreateScriptInfoWorker ( fileName , this . currentDirectory , openedByClient , fileContent , scriptKind , hasMixedContent , hostToQueryFileExistsOn ) ;
1746+ }
1747+
1748+ private getOrCreateScriptInfoWorker ( fileName : NormalizedPath , currentDirectory : string , openedByClient : boolean , fileContent ?: string , scriptKind ?: ScriptKind , hasMixedContent ?: boolean , hostToQueryFileExistsOn ?: DirectoryStructureHost ) {
17371749 Debug . assert ( fileContent === undefined || openedByClient , "ScriptInfo needs to be opened by client to be able to set its user defined content" ) ;
1738- const path = normalizedPathToPath ( fileName , this . currentDirectory , this . toCanonicalFileName ) ;
1750+ const path = normalizedPathToPath ( fileName , currentDirectory , this . toCanonicalFileName ) ;
17391751 let info = this . getScriptInfoForPath ( path ) ;
17401752 if ( ! info ) {
1753+ Debug . assert ( isRootedDiskPath ( fileName ) || openedByClient , "Script info with relative file name can only be open script info" ) ;
1754+ Debug . assert ( ! isRootedDiskPath ( fileName ) || this . currentDirectory === currentDirectory || ! this . openFilesWithNonRootedDiskPath . has ( this . toCanonicalFileName ( fileName ) ) , "Open script files with non rooted disk path opened with current directory context cannot have same canonical names" ) ;
17411755 const isDynamic = isDynamicFileName ( fileName ) ;
17421756 // If the file is not opened by client and the file doesnot exist on the disk, return
17431757 if ( ! openedByClient && ! isDynamic && ! ( hostToQueryFileExistsOn || this . host ) . fileExists ( fileName ) ) {
@@ -1748,6 +1762,10 @@ namespace ts.server {
17481762 if ( ! openedByClient ) {
17491763 this . watchClosedScriptInfo ( info ) ;
17501764 }
1765+ else if ( ! isRootedDiskPath ( fileName ) && currentDirectory !== this . currentDirectory ) {
1766+ // File that is opened by user but isn't rooted disk path
1767+ this . openFilesWithNonRootedDiskPath . set ( this . toCanonicalFileName ( fileName ) , info ) ;
1768+ }
17511769 }
17521770 if ( openedByClient && ! info . isScriptOpen ( ) ) {
17531771 // Opening closed script info
@@ -1764,8 +1782,12 @@ namespace ts.server {
17641782 return info ;
17651783 }
17661784
1785+ /**
1786+ * This gets the script info for the normalized path. If the path is not rooted disk path then the open script info with project root context is preferred
1787+ */
17671788 getScriptInfoForNormalizedPath ( fileName : NormalizedPath ) {
1768- return this . getScriptInfoForPath ( normalizedPathToPath ( fileName , this . currentDirectory , this . toCanonicalFileName ) ) ;
1789+ return ! isRootedDiskPath ( fileName ) && this . openFilesWithNonRootedDiskPath . get ( this . toCanonicalFileName ( fileName ) ) ||
1790+ this . getScriptInfoForPath ( normalizedPathToPath ( fileName , this . currentDirectory , this . toCanonicalFileName ) ) ;
17691791 }
17701792
17711793 getScriptInfoForPath ( fileName : Path ) {
@@ -1950,7 +1972,7 @@ namespace ts.server {
19501972 let sendConfigFileDiagEvent = false ;
19511973 let configFileErrors : ReadonlyArray < Diagnostic > ;
19521974
1953- const info = this . getOrCreateScriptInfoOpenedByClientForNormalizedPath ( fileName , fileContent , scriptKind , hasMixedContent ) ;
1975+ const info = this . getOrCreateScriptInfoOpenedByClientForNormalizedPath ( fileName , projectRootPath ? this . getNormalizedAbsolutePath ( projectRootPath ) : this . currentDirectory , fileContent , scriptKind , hasMixedContent ) ;
19541976 let project : ConfiguredProject | ExternalProject = this . findContainingExternalProject ( fileName ) ;
19551977 if ( ! project ) {
19561978 configFileName = this . getConfigFileNameForFile ( info , projectRootPath ) ;
0 commit comments