Merge pull request #54 from nventive/dev/cdb/immutable/treat-as-immutable

[KnownAsImmutable] -> [TreatAsImmutable]
This commit is contained in:
Carl de Billy 2018-07-25 09:53:42 -04:00 коммит произвёл GitHub
Родитель e8fe6665d8 3d1bf01177
Коммит 99bb659ce9
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 26 добавлений и 21 удалений

Просмотреть файл

@ -367,11 +367,11 @@ public class MyImmutable
I'm getting this error:
``` csharp
#error: 'ImmutableGenerator: Property MyClass.SomeField type ExternalClass.SuperClass is not immutable. It cannot be used in an immutable entity.'
#error: 'ImmutableGenerator: Property MyClass.SomeField (BaseClass) is not immutable. It cannot be used in an immutable entity.'
```
To fix this, put this attribute on your assembly:
``` csharp
[assembly: Uno.KnownAsImmutable(typeof(ExternalClass.SuperClass))]
[assembly: Uno.TreatAsImmutable(typeof(BaseClass))]
```

Просмотреть файл

@ -14,22 +14,23 @@
// limitations under the License.
//
// ******************************************************************
using System;
using System.Net.Mail;
using Uno;
[assembly: KnownAsImmutable(typeof(SmtpException))]
[assembly: TreatAsImmutable(typeof(DivideByZeroException))]
namespace Uno.CodeGen.Tests
{
partial class Given_ImmutableEntity
{
internal static readonly MyImmutableWithExternalKnownAsImmutable KnownAsImmutable =
MyImmutableWithExternalKnownAsImmutable.Default;
internal static readonly MyImmutableWithExternalTreatAsImmutable TreatAsImmutable =
MyImmutableWithExternalTreatAsImmutable.Default;
}
[GeneratedImmutable]
internal partial class MyImmutableWithExternalKnownAsImmutable
internal partial class MyImmutableWithExternalTreatAsImmutable
{
private SmtpException Exception { get; }
private DivideByZeroException Exception { get; }
}
}

Просмотреть файл

@ -47,7 +47,7 @@ namespace Uno
private INamedTypeSymbol _immutableBuilderAttributeSymbol;
private INamedTypeSymbol _immutableAttributeCopyIgnoreAttributeSymbol;
private INamedTypeSymbol _immutableGenerationOptionsAttributeSymbol;
private INamedTypeSymbol _immutableKnownAsImmutableAttributeSymbol;
private INamedTypeSymbol _immutableTreatAsImmutableAttributeSymbol;
private (bool generateOptionCode, bool treatArrayAsImmutable, bool generateEqualityByDefault, bool generateJsonNet) _generationOptions;
private bool _generateOptionCode = true;
@ -67,7 +67,7 @@ namespace Uno
_immutableBuilderAttributeSymbol = context.Compilation.GetTypeByMetadataName("Uno.ImmutableBuilderAttribute");
_immutableAttributeCopyIgnoreAttributeSymbol = context.Compilation.GetTypeByMetadataName("Uno.ImmutableAttributeCopyIgnoreAttribute");
_immutableGenerationOptionsAttributeSymbol = context.Compilation.GetTypeByMetadataName("Uno.ImmutableGenerationOptionsAttribute");
_immutableKnownAsImmutableAttributeSymbol = context.Compilation.GetTypeByMetadataName("Uno.KnownAsImmutableAttribute");
_immutableTreatAsImmutableAttributeSymbol = context.Compilation.GetTypeByMetadataName("Uno.TreatAsImmutableAttribute");
var generationData = EnumerateImmutableGeneratedEntities()
.OrderBy(x => x.symbol.Name)
@ -80,7 +80,7 @@ namespace Uno
return; // nothing to do
}
_knownAsImmutableTypes = EnumerateKnownAsImmutables();
_knownAsImmutableTypes = EnumerateTreatAsImmutables();
_copyIgnoreAttributeRegexes =
ExtractCopyIgnoreAttributes(context.Compilation.Assembly)
@ -835,6 +835,8 @@ $@"public sealed class {symbolName}BuilderJsonConverterTo{symbolName}{genericArg
void CheckTypeImmutable(ITypeSymbol type, string typeSource, bool constraintsChecked = false)
{
var typeName = (type as INamedTypeSymbol)?.GetSymbolNames().SymbolNameWithGenerics ?? type.ToString();
if (type is ITypeParameterSymbol typeParameter)
{
if (typeParameter.ConstraintTypes.Any())
@ -850,7 +852,7 @@ $@"public sealed class {symbolName}BuilderJsonConverterTo{symbolName}{genericArg
else
{
builder.AppendLineInvariant(
$"#error {nameof(ImmutableGenerator)}: {typeSource} is of generic type {type} which isn't restricted to immutable. You can also make your class abstract.");
$"#error {nameof(ImmutableGenerator)}: {typeSource} is of generic type {typeName} which isn't restricted to immutable. You can also make your class abstract.");
}
return; // ok
@ -859,22 +861,24 @@ $@"public sealed class {symbolName}BuilderJsonConverterTo{symbolName}{genericArg
if (type.FindAttribute(_immutableBuilderAttributeSymbol) != null)
{
builder.AppendLineInvariant(
$"#error {nameof(ImmutableGenerator)}: {typeSource} type {type} IS A BUILDER! It cannot be used in an immutable entity.");
$"#error {nameof(ImmutableGenerator)}: {typeSource} ({typeName}) is a builder. It cannot be used in an immutable entity.");
}
else if (!type.IsImmutable(_generationOptions.treatArrayAsImmutable, _knownAsImmutableTypes))
{
if (type is IArrayTypeSymbol)
{
builder.AppendLineInvariant(
$"#error {nameof(ImmutableGenerator)}: {typeSource} type {type} is an array, which is not immutable. "
+ "You can treat arrays as immutable by setting a global attribute "
$"#error {nameof(ImmutableGenerator)}: {typeSource} ({typeName}) is an array, which is not immutable. "
+ "You can treat arrays as immutable by setting a global attribute: "
+ "[assembly: Uno.ImmutableGenerationOptions(TreatArrayAsImmutable = true)].");
}
else
{
builder.AppendLineInvariant(
$"#error {nameof(ImmutableGenerator)}: {typeSource} type {type} is not immutable. It cannot be used in an immutable entity.");
$"#error {nameof(ImmutableGenerator)}: {typeSource} ({typeName}) not immutable. It cannot be used in an immutable entity. "
+ "If you know the type can safely be used as immutable, add a global attribyte: "
+ $"[assembly: Uno.TreatAsImmutable(typeof({typeName}))]");
}
}
@ -963,21 +967,21 @@ $@"public sealed class {symbolName}BuilderJsonConverterTo{symbolName}{genericArg
//where (bool) moduleAttribute.ConstructorArguments[0].Value
select (type, moduleAttribute);
private IReadOnlyList<ITypeSymbol> EnumerateKnownAsImmutables()
private IReadOnlyList<ITypeSymbol> EnumerateTreatAsImmutables()
{
var currentModuleAttributes = _context.Compilation.Assembly.GetAttributes();
var referencedAssembliesAttributes =
_context.Compilation.SourceModule.ReferencedAssemblySymbols.SelectMany(a => a.GetAttributes());
var knownTypeAttributes = currentModuleAttributes
var knownToBeImmutableTypes = currentModuleAttributes
.Concat(referencedAssembliesAttributes)
.Where(a => a.AttributeClass.Equals(_immutableKnownAsImmutableAttributeSymbol))
.Where(a => a.AttributeClass.Equals(_immutableTreatAsImmutableAttributeSymbol))
.Select(a => a.ConstructorArguments[0].Value)
.Cast<ITypeSymbol>()
.Distinct()
.ToImmutableArray();
return knownTypeAttributes;
return knownToBeImmutableTypes;
}
}
}

Просмотреть файл

@ -22,7 +22,7 @@ namespace Uno
/// Define a type (usually external) as immutable
/// </summary>
[System.AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public sealed class KnownAsImmutableAttribute : Attribute
public sealed class TreatAsImmutableAttribute : Attribute
{
/// <summary>
/// The type known to be immutable
@ -33,7 +33,7 @@ namespace Uno
/// .ctor
/// </summary>
/// <param name="type"></param>
public KnownAsImmutableAttribute(Type type)
public TreatAsImmutableAttribute(Type type)
{
Type = type;
}