Skip to content

Commit

Permalink
Merge pull request #4406 from unoplatform/dev/djo/resourcedictionary-fix
Browse files Browse the repository at this point in the history
fix(resourcedictionary): Fix Source path not registered correctly
  • Loading branch information
mergify[bot] committed Nov 6, 2020
2 parents d57b9ad + d94812c commit a9091f9
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@

<CompilerVisibleItemMetadata Include="AdditionalFiles" MetadataName="SourceItemGroup" />
<CompilerVisibleItemMetadata Include="AdditionalFiles" MetadataName="Link" />
<CompilerVisibleItemMetadata Include="AdditionalFiles" MetadataName="FullPath" />
</ItemGroup>

</When>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ internal partial class XamlCodeGeneration
private readonly string _configuration;
private readonly bool _isDebug;
private readonly string _projectDirectory;
private readonly string _projectFullPath;
private readonly bool _outputSourceComments = true;
private readonly RoslynMetadataHelper _metadataHelper;

Expand Down Expand Up @@ -76,23 +77,8 @@ internal partial class XamlCodeGeneration
"Generic.Native.xaml",
};

#if NETSTANDARD
private const string WinUIThemeResourcePathSuffix = "themeresources.xaml";
private const string WinUICompactPathSuffix = "DensityStyles/Compact.xaml";
#else
private const string WinUIThemeResourcePathSuffix = "/themeresources.xaml";
private const string WinUICompactPathSuffix = "/DensityStyles/Compact.xaml";
#endif

/// <summary>
/// ResourceDictionaries that aren't counted as default system resources (eg WinUI Fluent resources)
/// </summary>
private static readonly string[] _nonSystemResources = new[]
{
WinUIThemeResourcePathSuffix,
WinUICompactPathSuffix,
"DensityStyles/CompactDatePickerTimePickerFlyout.xaml",
};
private static string WinUICompactPathSuffix = Path.Combine("DensityStyles", "Compact.xaml");

#pragma warning disable 649 // Unused member
private readonly bool _forceGeneration;
Expand Down Expand Up @@ -125,7 +111,8 @@ public XamlCodeGeneration(GeneratorExecutionContext context)

_isDebug = string.Equals(_configuration, "Debug", StringComparison.OrdinalIgnoreCase);

_projectDirectory = Path.GetDirectoryName(context.GetMSBuildPropertyValue("MSBuildProjectFullPath"));
_projectFullPath = context.GetMSBuildPropertyValue("MSBuildProjectFullPath");
_projectDirectory = Path.GetDirectoryName(_projectFullPath);

var xamlItems = context.GetMSBuildItems("Page")
.Concat(context.GetMSBuildItems("ApplicationDefinition"));
Expand Down Expand Up @@ -199,23 +186,38 @@ public XamlCodeGeneration(GeneratorExecutionContext context)
/// </summary>
private string GetSourceLink(MSBuildItem projectItemInstance)
{
var value = projectItemInstance.GetMetadataValue("Link");
var link = projectItemInstance.GetMetadataValue("Link");
var definingProjectFullPath = projectItemInstance.GetMetadataValue("DefiningProjectFullPath");
var fullPath = projectItemInstance.GetMetadataValue("FullPath");

#if NETSTANDARD
// Both Uno.SourceGeneration uses relative pathrs and Roslyn Generators provide
// full paths. Dependents need specific portions so adjust the paths here for now.

if (value.IsNullOrEmpty())
// Reproduce the logic from https://github.com/dotnet/msbuild/blob/e70a3159d64f9ed6ec3b60253ef863fa883a99b1/src/Tasks/AssignLinkMetadata.cs
if (link.IsNullOrEmpty())
{
return Path.IsPathRooted(projectItemInstance.Identity)
? projectItemInstance.Identity.TrimStart(_projectDirectory).TrimStart(Path.DirectorySeparatorChar)
: projectItemInstance.Identity;
if (definingProjectFullPath.IsNullOrEmpty())
{
// Both Uno.SourceGeneration uses relative paths and Roslyn Generators provide
// full paths. Dependents need specific portions so adjust the paths here for now.
// For the case of Roslyn generators, DefiningProjectFullPath is not populated on purpose
// so that we can adjust paths properly.
if (link.IsNullOrEmpty())
{
return Path.IsPathRooted(projectItemInstance.Identity)
? projectItemInstance.Identity.TrimStart(_projectDirectory).TrimStart(Path.DirectorySeparatorChar)
: projectItemInstance.Identity;
}
}
else
{
var definingProjectDirectory = Path.GetDirectoryName(definingProjectFullPath) + Path.DirectorySeparatorChar;

if (fullPath.StartsWith(definingProjectDirectory, StringComparison.OrdinalIgnoreCase))
{
link = fullPath.Substring(definingProjectDirectory.Length);
}
}
}

return value;
#else
return value.IsNullOrEmpty() ? projectItemInstance.Identity : value;
#endif
return link;
}

public KeyValuePair<string, string>[] Generate()
Expand Down Expand Up @@ -564,7 +566,7 @@ private string GenerateGlobalResources(IEnumerable<XamlFileDefinition> files, Xa
if (IsUnoAssembly && _xamlSourceFiles.Any())
{
// Build master dictionary
foreach (var dictProperty in map.GetAllDictionaryProperties(_baseResourceDependencies, _nonSystemResources))
foreach (var dictProperty in map.GetAllDictionaryProperties(_baseResourceDependencies))
{
writer.AppendLineInvariant("MasterDictionary.MergedDictionaries.Add({0});", dictProperty);
}
Expand All @@ -578,7 +580,7 @@ private string GenerateGlobalResources(IEnumerable<XamlFileDefinition> files, Xa
using (writer.BlockInvariant("if(!_stylesRegistered)"))
{
writer.AppendLineInvariant("_stylesRegistered = true;");
foreach (var file in files.Where(f => IsIncludedResource(f, map)).Select(f => f.UniqueID).Distinct())
foreach (var file in files.Select(f => f.UniqueID).Distinct())
{
writer.AppendLineInvariant("RegisterDefaultStyles_{0}();", file);
}
Expand All @@ -598,17 +600,25 @@ private string GenerateGlobalResources(IEnumerable<XamlFileDefinition> files, Xa
foreach (var file in files.Where(IsResourceDictionary))
{
var url = "{0}/{1}".InvariantCultureFormat(_metadataHelper.AssemblyName, map.GetSourceLink(file));
RegisterForFile(file, url);
RegisterForXamlFile(file, url);
}
}
else if (files.Any()) // The NETSTD reference assembly contains no Xaml files
else if (files.Any() && IsUnoFluentAssembly)
{
// For Uno assembly, we expose WinUI resources using same uri as on Windows
RegisterForFile(files.FirstOrDefault(f => map.GetSourceLink(f).EndsWith(WinUIThemeResourcePathSuffix)), XamlFilePathHelper.WinUIThemeResourceURL);
RegisterForFile(files.FirstOrDefault(f => map.GetSourceLink(f).EndsWith(WinUICompactPathSuffix)), XamlFilePathHelper.WinUICompactURL);
RegisterForFile(WinUIThemeResourcePathSuffix, XamlFilePathHelper.WinUIThemeResourceURL);
RegisterForFile(WinUICompactPathSuffix, XamlFilePathHelper.WinUICompactURL);
}

void RegisterForFile(string baseFilePath, string url)
{
var file = files.FirstOrDefault(f =>
f.FilePath.Substring(_projectDirectory.Length+1).Equals(baseFilePath, StringComparison.OrdinalIgnoreCase));

RegisterForXamlFile(file, url);
}

void RegisterForFile(XamlFileDefinition file, string url)
void RegisterForXamlFile(XamlFileDefinition file, string url)
{
if (file != null)
{
Expand Down Expand Up @@ -668,11 +678,5 @@ void RegisterForFile(XamlFileDefinition file, string url)
}

private bool IsResourceDictionary(XamlFileDefinition fileDefinition) => fileDefinition.Objects.FirstOrDefault()?.Type.Name == "ResourceDictionary";

/// <summary>
/// Should this Xaml be included when defining default styles? Outside of Uno this is always true. In Uno, this excludes WinUI Fluent resources (which consumer code accesses via XamlControlsResources)
/// </summary>
private bool IsIncludedResource(XamlFileDefinition xamlFileDefinition, XamlGlobalStaticResourcesMap map) => !IsUnoAssembly
|| _nonSystemResources.None(s => map.GetSourceLink(xamlFileDefinition).EndsWith(s));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ internal void Add(string staticResourceKey, string ns, ResourcePrecedence preced
/// <param name="initialFiles">File names of the ResourceDictionaries whose properties should be returned first.</param>
/// <param name="ignoredFiles">Files which shouldn't be included in the default system resources</param>
/// <remarks>This is used when building Uno.UI itself to create a master dictionary of system resources.</remarks>
internal IEnumerable<string> GetAllDictionaryProperties(string[] initialFiles, string[] ignoredFiles)
internal IEnumerable<string> GetAllDictionaryProperties(string[] initialFiles)
{
var initialProperties = initialFiles.Select(f =>
_rdMap.First(kvp =>
Expand All @@ -50,7 +50,6 @@ internal IEnumerable<string> GetAllDictionaryProperties(string[] initialFiles, s
return initialProperties.Concat(
_rdMap.Except(initialProperties)
)
.Where(kvp => ignoredFiles.None(ignoredFile => kvp.Key.EndsWith(ignoredFile)))
.Select(kvp => ConvertIdToResourceDictionaryProperty(kvp.Value.UniqueID));
}

Expand Down

0 comments on commit a9091f9

Please sign in to comment.