11import * as path from "path" ;
22import fs from "fs" ;
33import * as utils from "./utils" ;
4- import { pathToFileURL } from "url" ;
54import readline from "readline" ;
65import { performance } from "perf_hooks" ;
76import * as p from "vscode-languageserver-protocol" ;
@@ -14,7 +13,8 @@ import { fileCodeActions } from "./codeActions";
1413import { projectsFiles } from "./projectFiles" ;
1514import { getRewatchBscArgs , RewatchCompilerArgs } from "./bsc-args/rewatch" ;
1615import { BsbCompilerArgs , getBsbBscArgs } from "./bsc-args/bsb" ;
17- import { workspaceFolders } from "./server" ;
16+ import { getCurrentCompilerDiagnosticsForFile } from "./server" ;
17+ import { NormalizedPath } from "./utils" ;
1818
1919export function debug ( ) {
2020 return (
@@ -32,8 +32,8 @@ export type IncrementallyCompiledFileInfo = {
3232 file : {
3333 /** File type. */
3434 extension : ".res" | ".resi" ;
35- /** Path to the source file. */
36- sourceFilePath : string ;
35+ /** Path to the source file (normalized) . */
36+ sourceFilePath : NormalizedPath ;
3737 /** Name of the source file. */
3838 sourceFileName : string ;
3939 /** Module name of the source file. */
@@ -69,29 +69,29 @@ export type IncrementallyCompiledFileInfo = {
6969 killCompilationListeners : Array < ( ) => void > ;
7070 /** Project specific information. */
7171 project : {
72- /** The root path of the project. */
73- rootPath : string ;
72+ /** The root path of the project (normalized to match projectsFiles keys) . */
73+ rootPath : NormalizedPath ;
7474 /** The root path of the workspace (if a monorepo) */
75- workspaceRootPath : string ;
75+ workspaceRootPath : NormalizedPath ;
7676 /** Computed location of bsc. */
77- bscBinaryLocation : string ;
77+ bscBinaryLocation : NormalizedPath ;
7878 /** The arguments needed for bsc, derived from the project configuration/build.ninja. */
7979 callArgs : Promise < Array < string > | null > ;
8080 /** The location of the incremental folder for this project. */
81- incrementalFolderPath : string ;
81+ incrementalFolderPath : NormalizedPath ;
8282 } ;
8383 /** Any code actions for this incremental file. */
8484 codeActions : Array < fileCodeActions > ;
8585} ;
8686
8787const incrementallyCompiledFileInfo : Map <
88- string ,
88+ NormalizedPath ,
8989 IncrementallyCompiledFileInfo
9090> = new Map ( ) ;
9191const hasReportedFeatureFailedError : Set < string > = new Set ( ) ;
92- const originalTypeFileToFilePath : Map < string , string > = new Map ( ) ;
92+ const originalTypeFileToFilePath : Map < string , NormalizedPath > = new Map ( ) ;
9393
94- export function incrementalCompilationFileChanged ( changedPath : string ) {
94+ export function incrementalCompilationFileChanged ( changedPath : NormalizedPath ) {
9595 const filePath = originalTypeFileToFilePath . get ( changedPath ) ;
9696 if ( filePath != null ) {
9797 const entry = incrementallyCompiledFileInfo . get ( filePath ) ;
@@ -116,7 +116,7 @@ export function incrementalCompilationFileChanged(changedPath: string) {
116116}
117117
118118export function removeIncrementalFileFolder (
119- projectRootPath : string ,
119+ projectRootPath : NormalizedPath ,
120120 onAfterRemove ?: ( ) => void ,
121121) {
122122 fs . rm (
@@ -128,7 +128,7 @@ export function removeIncrementalFileFolder(
128128 ) ;
129129}
130130
131- export function recreateIncrementalFileFolder ( projectRootPath : string ) {
131+ export function recreateIncrementalFileFolder ( projectRootPath : NormalizedPath ) {
132132 if ( debug ( ) ) {
133133 console . log ( "Recreating incremental file folder" ) ;
134134 }
@@ -142,8 +142,8 @@ export function recreateIncrementalFileFolder(projectRootPath: string) {
142142}
143143
144144export function cleanUpIncrementalFiles (
145- filePath : string ,
146- projectRootPath : string ,
145+ filePath : NormalizedPath ,
146+ projectRootPath : NormalizedPath ,
147147) {
148148 const ext = filePath . endsWith ( ".resi" ) ? ".resi" : ".res" ;
149149 const namespace = utils . getNamespaceNameFromConfigFile ( projectRootPath ) ;
@@ -242,7 +242,7 @@ function removeAnsiCodes(s: string): string {
242242 return s . replace ( ansiEscape , "" ) ;
243243}
244244function triggerIncrementalCompilationOfFile (
245- filePath : string ,
245+ filePath : NormalizedPath ,
246246 fileContent : string ,
247247 send : send ,
248248 onCompilationFinished ?: ( ) => void ,
@@ -256,25 +256,31 @@ function triggerIncrementalCompilationOfFile(
256256 console . log ( "Did not find project root path for " + filePath ) ;
257257 return ;
258258 }
259- const project = projectsFiles . get ( projectRootPath ) ;
259+ // projectRootPath is already normalized (NormalizedPath) from findProjectRootOfFile
260+ // Use getProjectFile to verify the project exists
261+ const project = utils . getProjectFile ( projectRootPath ) ;
260262 if ( project == null ) {
261263 if ( debug ( ) ) console . log ( "Did not find open project for " + filePath ) ;
262264 return ;
263265 }
266+ // projectRootPath is already the correct normalized key format
267+ const actualProjectRootPath = projectRootPath ;
264268
265269 // computeWorkspaceRootPathFromLockfile returns null if lockfile found (local package) or if no parent found
266- const computedWorkspaceRoot =
267- utils . computeWorkspaceRootPathFromLockfile ( projectRootPath ) ;
270+ const computedWorkspaceRoot = utils . computeWorkspaceRootPathFromLockfile (
271+ actualProjectRootPath ,
272+ ) ;
268273 // If null, it means either a lockfile was found (local package) or no parent project root exists
269- // In both cases, we default to projectRootPath
270- const workspaceRootPath = computedWorkspaceRoot ?? projectRootPath ;
274+ // In both cases, we default to actualProjectRootPath
275+ const workspaceRootPath : NormalizedPath =
276+ computedWorkspaceRoot ?? actualProjectRootPath ;
271277
272278 // Determine if lockfile was found for debug logging
273- // If computedWorkspaceRoot is null and projectRootPath is not null, check if parent exists
279+ // If computedWorkspaceRoot is null and actualProjectRootPath is not null, check if parent exists
274280 const foundRewatchLockfileInProjectRoot =
275281 computedWorkspaceRoot == null &&
276- projectRootPath != null &&
277- utils . findProjectRootOfFile ( projectRootPath , true ) != null ;
282+ actualProjectRootPath != null &&
283+ utils . findProjectRootOfFile ( actualProjectRootPath , true ) != null ;
278284
279285 if ( foundRewatchLockfileInProjectRoot && debug ( ) ) {
280286 console . log (
@@ -299,15 +305,15 @@ function triggerIncrementalCompilationOfFile(
299305 ? `${ moduleName } -${ project . namespaceName } `
300306 : moduleName ;
301307
302- const incrementalFolderPath = path . join (
303- projectRootPath ,
308+ const incrementalFolderPath : NormalizedPath = path . join (
309+ actualProjectRootPath ,
304310 INCREMENTAL_FILE_FOLDER_LOCATION ,
305- ) ;
311+ ) as NormalizedPath ;
306312
307313 let originalTypeFileLocation = path . resolve (
308- projectRootPath ,
314+ actualProjectRootPath ,
309315 c . compilerDirPartialPath ,
310- path . relative ( projectRootPath , filePath ) ,
316+ path . relative ( actualProjectRootPath , filePath ) ,
311317 ) ;
312318
313319 const parsed = path . parse ( originalTypeFileLocation ) ;
@@ -326,8 +332,8 @@ function triggerIncrementalCompilationOfFile(
326332 incrementalFilePath : path . join ( incrementalFolderPath , moduleName + ext ) ,
327333 } ,
328334 project : {
329- workspaceRootPath : workspaceRootPath ?? projectRootPath ,
330- rootPath : projectRootPath ,
335+ workspaceRootPath,
336+ rootPath : actualProjectRootPath ,
331337 callArgs : Promise . resolve ( [ ] ) ,
332338 bscBinaryLocation,
333339 incrementalFolderPath,
@@ -373,7 +379,10 @@ function triggerIncrementalCompilationOfFile(
373379 } ;
374380 }
375381}
376- function verifyTriggerToken ( filePath : string , triggerToken : number ) : boolean {
382+ function verifyTriggerToken (
383+ filePath : NormalizedPath ,
384+ triggerToken : number ,
385+ ) : boolean {
377386 return (
378387 incrementallyCompiledFileInfo . get ( filePath ) ?. compilation ?. triggerToken ===
379388 triggerToken
@@ -578,7 +587,8 @@ async function compileContents(
578587 const change = Object . values ( ca . codeAction . edit . changes ) [ 0 ] ;
579588
580589 ca . codeAction . edit . changes = {
581- [ pathToFileURL ( entry . file . sourceFilePath ) . toString ( ) ] : change ,
590+ [ utils . pathToURI ( entry . file . sourceFilePath ) as utils . FileURI ] :
591+ change ,
582592 } ;
583593 }
584594 } ) ;
@@ -645,11 +655,34 @@ async function compileContents(
645655 }
646656 }
647657
658+ const fileUri = utils . pathToURI (
659+ entry . file . sourceFilePath ,
660+ ) as utils . FileURI ;
661+
662+ // Update filesWithDiagnostics to track this file
663+ // entry.project.rootPath is guaranteed to match a key in projectsFiles
664+ // (see triggerIncrementalCompilationOfFile where the entry is created)
665+ const projectFile = projectsFiles . get ( entry . project . rootPath ) ;
666+
667+ if ( projectFile != null ) {
668+ // Get compiler diagnostics from main build (if any)
669+ const compilerDiagnosticsForFile =
670+ getCurrentCompilerDiagnosticsForFile ( fileUri ) ;
671+ const allDiagnostics = [ ...res , ...compilerDiagnosticsForFile ] ;
672+
673+ if ( allDiagnostics . length > 0 ) {
674+ projectFile . filesWithDiagnostics . add ( fileUri as utils . FileURI ) ;
675+ } else {
676+ // Only remove if there are no diagnostics at all
677+ projectFile . filesWithDiagnostics . delete ( fileUri as utils . FileURI ) ;
678+ }
679+ }
680+
648681 const notification : p . NotificationMessage = {
649682 jsonrpc : c . jsonrpcVersion ,
650683 method : "textDocument/publishDiagnostics" ,
651684 params : {
652- uri : pathToFileURL ( entry . file . sourceFilePath ) ,
685+ uri : fileUri ,
653686 diagnostics : res ,
654687 } ,
655688 } ;
@@ -667,7 +700,7 @@ async function compileContents(
667700}
668701
669702export function handleUpdateOpenedFile (
670- filePath : string ,
703+ filePath : utils . NormalizedPath ,
671704 fileContent : string ,
672705 send : send ,
673706 onCompilationFinished ?: ( ) => void ,
@@ -683,7 +716,7 @@ export function handleUpdateOpenedFile(
683716 ) ;
684717}
685718
686- export function handleClosedFile ( filePath : string ) {
719+ export function handleClosedFile ( filePath : NormalizedPath ) {
687720 if ( debug ( ) ) {
688721 console . log ( "Closed: " + filePath ) ;
689722 }
@@ -695,7 +728,7 @@ export function handleClosedFile(filePath: string) {
695728}
696729
697730export function getCodeActionsFromIncrementalCompilation (
698- filePath : string ,
731+ filePath : NormalizedPath ,
699732) : Array < fileCodeActions > | null {
700733 const entry = incrementallyCompiledFileInfo . get ( filePath ) ;
701734 if ( entry != null ) {
0 commit comments