@@ -353,6 +353,10 @@ namespace ts.server {
353353 * Open files: with value being project root path, and key being Path of the file that is open
354354 */
355355 readonly openFiles = createMap < NormalizedPath > ( ) ;
356+ /**
357+ * Map of open files that are opened without complete path but have projectRoot as current directory
358+ */
359+ private readonly openFilesWithNonRootedDiskPath = createMap < ScriptInfo > ( ) ;
356360
357361 private compilerOptionsForInferredProjects : CompilerOptions ;
358362 private compilerOptionsForInferredProjectsPerProjectRoot = createMap < CompilerOptions > ( ) ;
@@ -930,12 +934,16 @@ namespace ts.server {
930934 // Closing file should trigger re-reading the file content from disk. This is
931935 // because the user may chose to discard the buffer content before saving
932936 // to the disk, and the server's version of the file can be out of sync.
933- info . close ( ) ;
937+ const fileExists = this . host . fileExists ( info . fileName ) ;
938+ info . close ( fileExists ) ;
934939 this . stopWatchingConfigFilesForClosedScriptInfo ( info ) ;
935940
936941 this . openFiles . delete ( info . path ) ;
942+ const canonicalFileName = this . toCanonicalFileName ( info . fileName ) ;
943+ if ( this . openFilesWithNonRootedDiskPath . get ( canonicalFileName ) === info ) {
944+ this . openFilesWithNonRootedDiskPath . delete ( canonicalFileName ) ;
945+ }
937946
938- const fileExists = this . host . fileExists ( info . fileName ) ;
939947
940948 // collect all projects that should be removed
941949 let projectsToRemove : Project [ ] ;
@@ -1535,7 +1543,7 @@ namespace ts.server {
15351543 else {
15361544 const scriptKind = propertyReader . getScriptKind ( f , this . hostConfiguration . extraFileExtensions ) ;
15371545 const hasMixedContent = propertyReader . hasMixedContent ( f , this . hostConfiguration . extraFileExtensions ) ;
1538- scriptInfo = this . getOrCreateScriptInfoNotOpenedByClientForNormalizedPath ( normalizedPath , scriptKind , hasMixedContent , project . directoryStructureHost ) ;
1546+ scriptInfo = this . getOrCreateScriptInfoNotOpenedByClientForNormalizedPath ( normalizedPath , project . currentDirectory , scriptKind , hasMixedContent , project . directoryStructureHost ) ;
15391547 path = scriptInfo . path ;
15401548 // If this script info is not already a root add it
15411549 if ( ! project . isRoot ( scriptInfo ) ) {
@@ -1689,9 +1697,9 @@ namespace ts.server {
16891697 }
16901698
16911699 /*@internal */
1692- getOrCreateScriptInfoNotOpenedByClient ( uncheckedFileName : string , hostToQueryFileExistsOn : DirectoryStructureHost ) {
1700+ getOrCreateScriptInfoNotOpenedByClient ( uncheckedFileName : string , currentDirectory : string , hostToQueryFileExistsOn : DirectoryStructureHost ) {
16931701 return this . getOrCreateScriptInfoNotOpenedByClientForNormalizedPath (
1694- toNormalizedPath ( uncheckedFileName ) , /*scriptKind*/ undefined ,
1702+ toNormalizedPath ( uncheckedFileName ) , currentDirectory , /*scriptKind*/ undefined ,
16951703 /*hasMixedContent*/ undefined , hostToQueryFileExistsOn
16961704 ) ;
16971705 }
@@ -1722,20 +1730,26 @@ namespace ts.server {
17221730 }
17231731
17241732 /*@internal */
1725- getOrCreateScriptInfoNotOpenedByClientForNormalizedPath ( fileName : NormalizedPath , scriptKind ? : ScriptKind , hasMixedContent ? : boolean , hostToQueryFileExistsOn ? : DirectoryStructureHost ) {
1726- return this . getOrCreateScriptInfoForNormalizedPath ( fileName , /*openedByClient*/ false , /*fileContent*/ undefined , scriptKind , hasMixedContent , hostToQueryFileExistsOn ) ;
1733+ getOrCreateScriptInfoNotOpenedByClientForNormalizedPath ( fileName : NormalizedPath , currentDirectory : string , scriptKind : ScriptKind | undefined , hasMixedContent : boolean | undefined , hostToQueryFileExistsOn : DirectoryStructureHost | undefined ) {
1734+ return this . getOrCreateScriptInfoWorker ( fileName , currentDirectory , /*openedByClient*/ false , /*fileContent*/ undefined , scriptKind , hasMixedContent , hostToQueryFileExistsOn ) ;
17271735 }
17281736
17291737 /*@internal */
1730- getOrCreateScriptInfoOpenedByClientForNormalizedPath ( fileName : NormalizedPath , fileContent ? : string , scriptKind ? : ScriptKind , hasMixedContent ? : boolean , hostToQueryFileExistsOn ?: DirectoryStructureHost ) {
1731- return this . getOrCreateScriptInfoForNormalizedPath ( fileName , /*openedByClient*/ true , fileContent , scriptKind , hasMixedContent , hostToQueryFileExistsOn ) ;
1738+ getOrCreateScriptInfoOpenedByClientForNormalizedPath ( fileName : NormalizedPath , currentDirectory : string , fileContent : string | undefined , scriptKind : ScriptKind | undefined , hasMixedContent : boolean | undefined ) {
1739+ return this . getOrCreateScriptInfoWorker ( fileName , currentDirectory , /*openedByClient*/ true , fileContent , scriptKind , hasMixedContent ) ;
17321740 }
17331741
17341742 getOrCreateScriptInfoForNormalizedPath ( fileName : NormalizedPath , openedByClient : boolean , fileContent ?: string , scriptKind ?: ScriptKind , hasMixedContent ?: boolean , hostToQueryFileExistsOn ?: DirectoryStructureHost ) {
1743+ return this . getOrCreateScriptInfoWorker ( fileName , this . currentDirectory , openedByClient , fileContent , scriptKind , hasMixedContent , hostToQueryFileExistsOn ) ;
1744+ }
1745+
1746+ private getOrCreateScriptInfoWorker ( fileName : NormalizedPath , currentDirectory : string , openedByClient : boolean , fileContent ?: string , scriptKind ?: ScriptKind , hasMixedContent ?: boolean , hostToQueryFileExistsOn ?: DirectoryStructureHost ) {
17351747 Debug . assert ( fileContent === undefined || openedByClient , "ScriptInfo needs to be opened by client to be able to set its user defined content" ) ;
1736- const path = normalizedPathToPath ( fileName , this . currentDirectory , this . toCanonicalFileName ) ;
1748+ const path = normalizedPathToPath ( fileName , currentDirectory , this . toCanonicalFileName ) ;
17371749 let info = this . getScriptInfoForPath ( path ) ;
17381750 if ( ! info ) {
1751+ Debug . assert ( isRootedDiskPath ( fileName ) || openedByClient , "Script info with relative file name can only be open script info" ) ;
1752+ 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" ) ;
17391753 const isDynamic = isDynamicFileName ( fileName ) ;
17401754 // If the file is not opened by client and the file doesnot exist on the disk, return
17411755 if ( ! openedByClient && ! isDynamic && ! ( hostToQueryFileExistsOn || this . host ) . fileExists ( fileName ) ) {
@@ -1746,6 +1760,10 @@ namespace ts.server {
17461760 if ( ! openedByClient ) {
17471761 this . watchClosedScriptInfo ( info ) ;
17481762 }
1763+ else if ( ! isRootedDiskPath ( fileName ) && currentDirectory !== this . currentDirectory ) {
1764+ // File that is opened by user but isn't rooted disk path
1765+ this . openFilesWithNonRootedDiskPath . set ( this . toCanonicalFileName ( fileName ) , info ) ;
1766+ }
17491767 }
17501768 if ( openedByClient && ! info . isScriptOpen ( ) ) {
17511769 // Opening closed script info
@@ -1762,8 +1780,12 @@ namespace ts.server {
17621780 return info ;
17631781 }
17641782
1783+ /**
1784+ * 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
1785+ */
17651786 getScriptInfoForNormalizedPath ( fileName : NormalizedPath ) {
1766- return this . getScriptInfoForPath ( normalizedPathToPath ( fileName , this . currentDirectory , this . toCanonicalFileName ) ) ;
1787+ return ! isRootedDiskPath ( fileName ) && this . openFilesWithNonRootedDiskPath . get ( this . toCanonicalFileName ( fileName ) ) ||
1788+ this . getScriptInfoForPath ( normalizedPathToPath ( fileName , this . currentDirectory , this . toCanonicalFileName ) ) ;
17671789 }
17681790
17691791 getScriptInfoForPath ( fileName : Path ) {
@@ -1948,7 +1970,7 @@ namespace ts.server {
19481970 let sendConfigFileDiagEvent = false ;
19491971 let configFileErrors : ReadonlyArray < Diagnostic > ;
19501972
1951- const info = this . getOrCreateScriptInfoOpenedByClientForNormalizedPath ( fileName , fileContent , scriptKind , hasMixedContent ) ;
1973+ const info = this . getOrCreateScriptInfoOpenedByClientForNormalizedPath ( fileName , projectRootPath ? this . getNormalizedAbsolutePath ( projectRootPath ) : this . currentDirectory , fileContent , scriptKind , hasMixedContent ) ;
19521974 let project : ConfiguredProject | ExternalProject = this . findContainingExternalProject ( fileName ) ;
19531975 if ( ! project ) {
19541976 configFileName = this . getConfigFileNameForFile ( info , projectRootPath ) ;
0 commit comments