@@ -297,10 +297,23 @@ private static void updateModel(C4DocumentModel model, CompletableFuture<ViewSet
297297 private PublishDiagnosticsParams calcDiagnosticsForFile (File file , String content ) {
298298
299299 String filePath = file .getAbsolutePath ();
300-
300+ String currentDirectory = file .getParent ();
301+
302+ // Find workspace.dsl early — needed for combined cache key
303+ File worksapceFile = findWorksapce (currentDirectory , "workspace.dsl" );
304+ boolean isWorkspace = worksapceFile .getAbsolutePath ().equals (file .getAbsolutePath ());
305+
301306 // Check content hash — if file unchanged, return cached diagnostics without re-parsing.
307+ // For fragment files, combine hash with workspace.dsl content to detect changes in either file.
302308 logger .info ("Check content changes for {}" , filePath );
303- int newHash = content .hashCode ();
309+ int fileHash = content .hashCode ();
310+ int newHash = fileHash ;
311+ if (!isWorkspace && worksapceFile .exists ()) {
312+ String wsContent = fileContent .get (worksapceFile );
313+ if (wsContent != null ) {
314+ newHash = 31 * newHash + wsContent .hashCode ();
315+ }
316+ }
304317 Integer oldHash = contentHashes .get (filePath );
305318 if (oldHash != null && oldHash .equals (newHash )) {
306319 PublishDiagnosticsParams cached = cachedDiagnostics .get (filePath );
@@ -310,8 +323,6 @@ private PublishDiagnosticsParams calcDiagnosticsForFile(File file, String conten
310323 }
311324 }
312325 logger .info ("Content changed, parsing for {}" , filePath );
313-
314- String currentDirectory = file .getParent ();
315326 CompletableFuture <ViewSet > layouts = null ;
316327
317328 fileContent .put (file , content );
@@ -344,9 +355,6 @@ private PublishDiagnosticsParams calcDiagnosticsForFile(File file, String conten
344355 StructurizrDslParser parser = new StructurizrDslParser ();
345356 List <Diagnostic > errors = new ArrayList <>();
346357
347- File worksapceFile = findWorksapce (currentDirectory , "workspace.dsl" );
348- boolean isWorkspace = worksapceFile .getAbsolutePath ().equals (file .getAbsolutePath ());
349-
350358 if (isWorkspace ) {
351359 C4DocumentModel model = createModel (file , content );
352360 try {
@@ -364,9 +372,6 @@ private PublishDiagnosticsParams calcDiagnosticsForFile(File file, String conten
364372 if (errors .isEmpty ()) {
365373 updateModel (model , layouts );
366374 }
367- } else {
368- errors .clear ();
369- model .setValid (true );
370375 }
371376 }
372377 // Parsing complete — commit content hash and
@@ -384,7 +389,11 @@ private PublishDiagnosticsParams calcDiagnosticsForFile(File file, String conten
384389 parser .parse (content , file );
385390 } catch (StructurizrDslParserException e ) {
386391 logger .info ("Got structurizr exception {}" , e .getMessage ());
387- if (worksapceFile .exists ()) {
392+ if (parser .getWorkspace () != null || !worksapceFile .exists ()) {
393+ // File has workspace {} (real error) or no workspace.dsl to fall back to
394+ errors .add (createError (e ));
395+ } else {
396+ // File is a fragment (no workspace created) — try parsing via workspace.dsl
388397 logger .info ("try to parse workspace {}" , worksapceFile .getAbsolutePath ());
389398 String content0 = fileContent .get (worksapceFile );
390399 if (content0 == null ) {
@@ -397,6 +406,7 @@ private PublishDiagnosticsParams calcDiagnosticsForFile(File file, String conten
397406 if (content0 != null ) {
398407 model = createModel (worksapceFile , content0 );
399408 createModel (file , content );
409+ parser = new StructurizrDslParser ();
400410 try {
401411 model .clear ();
402412 parser .parse (content0 , worksapceFile );
@@ -412,21 +422,19 @@ private PublishDiagnosticsParams calcDiagnosticsForFile(File file, String conten
412422 if (errors .isEmpty ()) {
413423 updateModel (model , layouts );
414424 }
415- } else {
416- errors .clear ();
417- model .setValid (true );
418425 }
419426 }
420- // Parsing workspace.dsl (fallback) complete — commit and move models
427+ // Parsing workspace.dsl (fallback) complete — commit and move models.
428+ // Cache with combined hash (fragment + workspace) so changes in either file invalidate it
421429 PublishDiagnosticsParams result0 = new PublishDiagnosticsParams (worksapceFile .toURI ().toString (), errors );
422- contentHashes .put (filePath , newHash );
430+ int combinedHash = 31 * fileHash + content0 .hashCode ();
431+ contentHashes .put (filePath , combinedHash );
423432 cachedDiagnostics .put (filePath , result0 );
424433 commitPendingModels ();
425434 return result0 ;
435+ } else {
436+ errors .add (createError (e ));
426437 }
427- } else {
428- logger .info ("ParserException {}" , e .getMessage ());
429- errors .add (createError (e ));
430438 }
431439 } catch (Exception e ) {
432440 logger .error ("calcDiagnostics {}" , e .getMessage ());
@@ -437,9 +445,6 @@ private PublishDiagnosticsParams calcDiagnosticsForFile(File file, String conten
437445 if (errors .isEmpty ()) {
438446 updateModel (model , layouts );
439447 }
440- } else {
441- errors .clear ();
442- model .setValid (true );
443448 }
444449 }
445450 // Parsing regular .dsl file complete — commit and move models
0 commit comments