@@ -1105,6 +1105,7 @@ def __init__(self, postprocessor_factory: Callable[[], Postprocessor]) -> None:
11051105
11061106 self .postprocessor_factory = postprocessor_factory
11071107 self ._parsed : Dict [FileId , Tuple [Page , FileId , List [Diagnostic ]]] = {}
1108+ self ._orphan_diagnostics : Dict [FileId , List [Diagnostic ]] = {}
11081109 self .__cached = PostprocessorResult ({}, {}, {}, TargetDatabase ())
11091110 self .__changed_pages : Set [FileId ] = set ()
11101111
@@ -1137,6 +1138,13 @@ def start(
11371138 Postprocessor , PostprocessorResult
11381139 ] = util .WorkerLauncher ("postprocessor" , start )
11391140
1141+ def set_orphan_diagnostics (self , key : FileId , value : List [Diagnostic ]) -> None :
1142+ """Some diagnostics can't be associated with a parsed Page because of underlying
1143+ problems like invalid YAML syntax. These are orphan diagnostics, and we need
1144+ to track them too."""
1145+ with self ._lock :
1146+ self ._orphan_diagnostics [key ] = value
1147+
11401148 def __setitem__ (
11411149 self , key : FileId , value : Tuple [Page , FileId , List [Diagnostic ]]
11421150 ) -> None :
@@ -1164,7 +1172,15 @@ def __contains__(self, key: FileId) -> bool:
11641172
11651173 def __delitem__ (self , key : FileId ) -> None :
11661174 with self ._lock :
1167- del self ._parsed [key ]
1175+ try :
1176+ del self ._parsed [key ]
1177+ except KeyError :
1178+ pass
1179+
1180+ try :
1181+ del self ._orphan_diagnostics [key ]
1182+ except KeyError :
1183+ pass
11681184
11691185 def merge_diagnostics (
11701186 self , * others : Dict [FileId , List [Diagnostic ]]
@@ -1174,6 +1190,12 @@ def merge_diagnostics(
11741190 v [1 ]: list (v [2 ]) for v in self ._parsed .values ()
11751191 }
11761192
1193+ for key , diagnostics in self ._orphan_diagnostics .items ():
1194+ if key in result :
1195+ result [key ].extend (diagnostics )
1196+ else :
1197+ result [key ] = list (diagnostics )
1198+
11771199 all_keys : Set [FileId ] = set ()
11781200 for other in others :
11791201 all_keys .update (other .keys ())
@@ -1501,11 +1523,13 @@ def build(
15011523 for prefix , giza_category in self .yaml_mapping .items ():
15021524 logger .debug ("Parsing %s YAML" , prefix )
15031525 for path in categorized [prefix ]:
1504- steps , text , diagnostics = giza_category .parse (path )
1505- all_yaml_diagnostics [path ] = diagnostics
1506- giza_category .add (path , text , steps )
1526+ artifacts , text , diagnostics = giza_category .parse (path )
1527+ if diagnostics :
1528+ all_yaml_diagnostics [path ] = diagnostics
1529+ giza_category .add (path , text , artifacts )
15071530
15081531 # Now that all of our YAML files are loaded, generate a page for each one
1532+ seen_paths : Set [Path ] = set ()
15091533 for prefix , giza_category in self .yaml_mapping .items ():
15101534 logger .debug ("Processing %s YAML: %d nodes" , prefix , len (giza_category ))
15111535 for file_id , giza_node in giza_category .reify_all_files (
@@ -1531,10 +1555,19 @@ def create_page(filename: str) -> Tuple[Page, EmbeddedRstParser]:
15311555 for page in giza_category .to_pages (
15321556 giza_node .path , create_page , giza_node .data
15331557 ):
1558+ seen_paths .add (page .source_path )
15341559 self ._page_updated (
15351560 page , all_yaml_diagnostics .get (page .source_path , [])
15361561 )
15371562
1563+ # Handle parsing and unmarshaling errors that lead to diagnostics not associated with
1564+ # any page.
1565+ for key in all_yaml_diagnostics :
1566+ if key not in seen_paths :
1567+ self .pages .set_orphan_diagnostics (
1568+ self .config .get_fileid (key ), all_yaml_diagnostics [key ]
1569+ )
1570+
15381571 if postprocess :
15391572 postprocessor_result = self .postprocess ()
15401573
0 commit comments