diff --git a/src/Uno.CodeGen.Tests.ExternalClasses/ConcreteExternalGenericClass.cs b/src/Uno.CodeGen.Tests.ExternalClasses/ConcreteExternalGenericClass.cs new file mode 100644 index 0000000..2c9cd1e --- /dev/null +++ b/src/Uno.CodeGen.Tests.ExternalClasses/ConcreteExternalGenericClass.cs @@ -0,0 +1,25 @@ +// ****************************************************************** +// Copyright � 2015-2018 nventive inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ****************************************************************** +namespace Uno.CodeGen.Tests.ExternalClasses +{ + [GeneratedImmutable] + public abstract partial class ConcreteExternalGenericClass + { + [EqualityHash] + public TId Id { get; } + } +} diff --git a/src/Uno.CodeGen.Tests.ExternalClasses/SubNamespace/ConcreteExternalClass.cs b/src/Uno.CodeGen.Tests.ExternalClasses/SubNamespace/ConcreteExternalClass.cs new file mode 100644 index 0000000..8328f34 --- /dev/null +++ b/src/Uno.CodeGen.Tests.ExternalClasses/SubNamespace/ConcreteExternalClass.cs @@ -0,0 +1,25 @@ +// ****************************************************************** +// Copyright � 2015-2018 nventive inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ****************************************************************** +namespace Uno.CodeGen.Tests.ExternalClasses.SubNamespace +{ + [GeneratedImmutable] + public partial class ConcreteExternalClass + { + [EqualityHash] + public string Id { get; } + } +} diff --git a/src/Uno.CodeGen.Tests.ExternalClasses/SubNamespace/ConcreteExternalGenericClass.cs b/src/Uno.CodeGen.Tests.ExternalClasses/SubNamespace/ConcreteExternalGenericClass.cs new file mode 100644 index 0000000..af48c65 --- /dev/null +++ b/src/Uno.CodeGen.Tests.ExternalClasses/SubNamespace/ConcreteExternalGenericClass.cs @@ -0,0 +1,25 @@ +// ****************************************************************** +// Copyright � 2015-2018 nventive inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ****************************************************************** +namespace Uno.CodeGen.Tests.ExternalClasses.SubNamespace +{ + [GeneratedImmutable] + public abstract partial class ConcreteExternalGenericClass + { + [EqualityHash] + public TId Id { get; } + } +} diff --git a/src/Uno.CodeGen/Helpers/NamedTypeSymbolExtensions.cs b/src/Uno.CodeGen/Helpers/NamedTypeSymbolExtensions.cs index ca862ce..9b93115 100644 --- a/src/Uno.CodeGen/Helpers/NamedTypeSymbolExtensions.cs +++ b/src/Uno.CodeGen/Helpers/NamedTypeSymbolExtensions.cs @@ -31,9 +31,13 @@ namespace Uno.Helpers var substitutions = typeToUseForSubstitutions.GetSubstitutionTypes(); var symbolName = typeSymbol.Name; + + // Generate a filename suffix from the namespace to prevent filename clashing when processing classes with the same name. + var filenameSuffix = $"{typeSymbol.GetNamespaceHash():X}"; + if (typeSymbol.TypeArguments.Length == 0) // not a generic type { - return new SymbolNames(typeSymbol, symbolName, "", symbolName, symbolName, symbolName, symbolName, ""); + return new SymbolNames(typeSymbol, symbolName, "", symbolName, symbolName, symbolName, $"{symbolName}_{filenameSuffix}", ""); } var argumentNames = typeSymbol.GetTypeArgumentNames(substitutions); @@ -49,7 +53,7 @@ namespace Uno.Helpers var symbolNameDefinition = $"{symbolName}<{string.Join(",", typeSymbol.TypeArguments.Select(ta => ""))}>"; // symbolNameWithGenerics: MyType_T1_T2 - var symbolFilename = $"{symbolName}_{string.Join("_", argumentNames)}"; + var symbolFilename = $"{symbolName}_{string.Join("_", argumentNames)}_{filenameSuffix}"; var genericConstraints = " " + string.Join(" ", typeSymbol .TypeArguments @@ -98,6 +102,19 @@ namespace Uno.Helpers return result; } + + public static int GetNamespaceHash(this INamedTypeSymbol typeSymbol) + { + var hashCode = 0; + INamespaceSymbol namespaceSymbol = typeSymbol.ContainingNamespace; + while (!namespaceSymbol?.IsGlobalNamespace ?? false) + { + hashCode ^= namespaceSymbol.Name.GetStableHashCode(); + namespaceSymbol = namespaceSymbol.ContainingNamespace; + } + + return hashCode; + } } public class SymbolNames diff --git a/src/Uno.CodeGen/Helpers/StringExtensions.cs b/src/Uno.CodeGen/Helpers/StringExtensions.cs new file mode 100644 index 0000000..c169fa3 --- /dev/null +++ b/src/Uno.CodeGen/Helpers/StringExtensions.cs @@ -0,0 +1,51 @@ +// ****************************************************************** +// Copyright � 2015-2018 nventive inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ****************************************************************** +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using Microsoft.CodeAnalysis; + +namespace Uno.Helpers +{ + public static class StringExtensions + { + public static int GetStableHashCode(this string str) + { + // A fully managed version of the 64bit GetHashCode() that does not use any randomization and will always return + // the same value for equal strings. + // https://stackoverflow.com/questions/36845430/persistent-hashcode-for-strings + unchecked + { + int hash1 = 5381; + int hash2 = hash1; + + for (int i = 0; i < str.Length && str[i] != '\0'; i += 2) + { + hash1 = ((hash1 << 5) + hash1) ^ str[i]; + if (i == str.Length - 1 || str[i + 1] == '\0') + break; + hash2 = ((hash2 << 5) + hash2) ^ str[i + 1]; + } + + return hash1 + (hash2 * 1566083941); + } + } + } +}