From 02d96247484ac6c5a04e8541cb5bebe3e27e3ab1 Mon Sep 17 00:00:00 2001 From: Abhijeet Jha Date: Fri, 28 Aug 2026 22:03:53 +0530 Subject: [PATCH] SourceFileManager::PropagateOutOfDateStatus: report malformed XAML against the offending file Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../BuildTasks/CompileXamlInternal.cs | 16 +++++++++++++--- .../Xaml/XamlCompiler/XamlNodeStreamReader.cs | 17 +++++++++++++++++ .../BuildTasks/SourceFileManager.cs | 5 +++-- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/XamlCompiler/BuildTasks/CompileXamlInternal.cs b/src/XamlCompiler/BuildTasks/CompileXamlInternal.cs index 3fbb0fc931..259c471156 100644 --- a/src/XamlCompiler/BuildTasks/CompileXamlInternal.cs +++ b/src/XamlCompiler/BuildTasks/CompileXamlInternal.cs @@ -3087,9 +3087,19 @@ internal void LogError_XamlInternalError(Exception e, string file) internal void LogUnhandledException(string subcategory, ErrorCode code, Exception e, string file) { - XamlException xamlException = e as XamlException; - int line = xamlException != null ? xamlException.LineNumber : 0; - int column = xamlException != null ? xamlException.LinePosition : 0; + int line = 0; + int column = 0; + if (e is XamlException xamlException) + { + line = xamlException.LineNumber; + column = xamlException.LinePosition; + } + else if (e is XmlException xmlException) + { + // XmlException does not derive from XamlException, so extract its position separately. + line = xmlException.LineNumber; + column = xmlException.LinePosition; + } string message = e.Message; LogError(subcategory, code, null, file, line, column, 0, 0, message); diff --git a/src/XamlCompiler/BuildTasks/Microsoft/Xaml/XamlCompiler/XamlNodeStreamReader.cs b/src/XamlCompiler/BuildTasks/Microsoft/Xaml/XamlCompiler/XamlNodeStreamReader.cs index a2cb562153..9d0b607508 100644 --- a/src/XamlCompiler/BuildTasks/Microsoft/Xaml/XamlCompiler/XamlNodeStreamReader.cs +++ b/src/XamlCompiler/BuildTasks/Microsoft/Xaml/XamlCompiler/XamlNodeStreamReader.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. See LICENSE in the project root for license information. +using System; using System.IO; using System.Xaml; using System.Xml; @@ -9,6 +10,22 @@ namespace Microsoft.UI.Xaml.Markup.Compiler.Utilities { class XamlNodeStreamHelper { + // Speculative x:Class read. Malformed markup is reported by the authoritative parse in + // CompileXamlInternal.LoadXamlDom, which names the offending file, so it must not fail here first. + public static bool TryReadXClassFromXamlFileStream(TextReader fileStream, XamlSchemaContext schemaContext, out string className) + { + try + { + className = ReadXClassFromXamlFileStream(fileStream, schemaContext); + return true; + } + catch (Exception e) when (e is XmlException || e is XamlException) + { + className = null; + return false; + } + } + public static string ReadXClassFromXamlFileStream(TextReader fileStream, XamlSchemaContext schemaContext) { string className = null; diff --git a/src/XamlCompiler/BuildTasks/SourceFileManager.cs b/src/XamlCompiler/BuildTasks/SourceFileManager.cs index 7e7d554846..2c65260340 100644 --- a/src/XamlCompiler/BuildTasks/SourceFileManager.cs +++ b/src/XamlCompiler/BuildTasks/SourceFileManager.cs @@ -125,12 +125,13 @@ public void PropagateOutOfDateStatus(DirectUI.DirectUISchemaContext context) // look to see if a new class was specified; if so, we guessed wrong before, undo that. // Note that both the old and new classes are out of date. string newClassFullName = null; + bool readClassName; using (var fileReader = TaskFileService.GetFileContents(tif.SourceXamlFullPath)) { - newClassFullName = XamlNodeStreamHelper.ReadXClassFromXamlFileStream(fileReader, context); + readClassName = XamlNodeStreamHelper.TryReadXClassFromXamlFileStream(fileReader, context, out newClassFullName); } - if (newClassFullName != tif.ClassFullName) + if (readClassName && newClassFullName != tif.ClassFullName) { UnregisterClassOfTaskItem(tif); tif.ClassFullName = newClassFullName;