Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Teach GenApi to understand nullability #2679

Merged
merged 17 commits into from
Sep 27, 2019
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
264 changes: 223 additions & 41 deletions src/Microsoft.Cci.Extensions/Extensions/CSharp/CSharpCciExtensions.cs

Large diffs are not rendered by default.

100 changes: 100 additions & 0 deletions src/Microsoft.Cci.Extensions/Extensions/CustomAttributeProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
using System;
using System.Reflection.Metadata;
using SRMetadataReader = System.Reflection.Metadata.MetadataReader;
using SRPrimitiveTypeCode = System.Reflection.Metadata.PrimitiveTypeCode;

namespace Microsoft.Cci.Extensions
{
public class CustomAttributeTypeProvider : ICustomAttributeTypeProvider<string>
{
public string GetSystemType()
{
return "[System.Runtime]System.Type";
}

public bool IsSystemType(string type)
{
return type == "[System.Runtime]System.Type" // encountered as typeref
|| Type.GetType(type) == typeof(Type); // encountered as serialized to reflection notation
}

public string GetTypeFromSerializedName(string name)
{
return name;
}

public string GetPrimitiveType(SRPrimitiveTypeCode typeCode)
{
switch (typeCode)
{
case SRPrimitiveTypeCode.Boolean:
return "bool";

case SRPrimitiveTypeCode.Byte:
return "uint8";

case SRPrimitiveTypeCode.Char:
return "char";

case SRPrimitiveTypeCode.Double:
return "float64";

case SRPrimitiveTypeCode.Int16:
return "int16";

case SRPrimitiveTypeCode.Int32:
return "int32";

case SRPrimitiveTypeCode.Int64:
return "int64";

case SRPrimitiveTypeCode.IntPtr:
return "native int";

case SRPrimitiveTypeCode.Object:
return "object";

case SRPrimitiveTypeCode.SByte:
return "int8";

case SRPrimitiveTypeCode.Single:
return "float32";

case SRPrimitiveTypeCode.String:
return "string";

case SRPrimitiveTypeCode.TypedReference:
return "typedref";

case SRPrimitiveTypeCode.UInt16:
return "uint16";

case SRPrimitiveTypeCode.UInt32:
return "uint32";

case SRPrimitiveTypeCode.UInt64:
return "uint64";

case SRPrimitiveTypeCode.UIntPtr:
return "native uint";

case SRPrimitiveTypeCode.Void:
return "void";

default:
throw new ArgumentOutOfRangeException(nameof(typeCode));
}
}

public string GetSZArrayType(string elementType)
{
return elementType + "[]";
}

public SRPrimitiveTypeCode GetUnderlyingEnumType(string type) => default; // We only use this for compiler attributes that take a primitive type as a parameter.

public string GetTypeFromDefinition(SRMetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind = 0) => null; // We only use this for compiler attributes that take a primitive type as a parameter.

public string GetTypeFromReference(SRMetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind = 0) => null; // We only use this for compiler attributes that take a primitive type as a parameter.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ public class ExcludeAttributesFilter : PublicOnlyCciFilter
{
private readonly HashSet<string> _attributeDocIds;

public ExcludeAttributesFilter(IEnumerable<string> attributeDocIds)
: base(false)
public ExcludeAttributesFilter(IEnumerable<string> attributeDocIds, bool includeForwardedTypes = false)
: base(excludeAttributes: false, includeForwardedTypes: includeForwardedTypes)
{
_attributeDocIds = new HashSet<string>(attributeDocIds);
}

public ExcludeAttributesFilter(string attributeDocIdFile)
: base(false)
public ExcludeAttributesFilter(string attributeDocIdFile, bool includeForwardedTypes = false)
: base(excludeAttributes: false, includeForwardedTypes: includeForwardedTypes)
{
_attributeDocIds = DocIdExtensions.ReadDocIds(attributeDocIdFile);
}
Expand Down
8 changes: 7 additions & 1 deletion src/Microsoft.Cci.Extensions/Filters/PublicOnlyCciFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ public class PublicOnlyCciFilter : ICciFilter
{
public PublicOnlyCciFilter(bool excludeAttributes = true)
{
this.ExcludeAttributes = excludeAttributes;
ExcludeAttributes = excludeAttributes;
}

public PublicOnlyCciFilter(bool excludeAttributes, bool includeForwardedTypes)
{
ExcludeAttributes = excludeAttributes;
IncludeForwardedTypes = includeForwardedTypes;
}

public bool IncludeForwardedTypes { get; set; }
Expand Down
2 changes: 2 additions & 0 deletions src/Microsoft.Cci.Extensions/HostEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Reflection.PortableExecutable;
using Microsoft.Cci;

namespace Microsoft.Cci.Extensions
Expand Down
5 changes: 4 additions & 1 deletion src/Microsoft.Cci.Extensions/Microsoft.Cci.Extensions.csproj
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<DisableImplicitAssetTargetFallback>true</DisableImplicitAssetTargetFallback>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<AssetTargetFallback>$(PackageTargetFallback)portable-net45+win8;</AssetTargetFallback>
<ExcludeFromSourceBuild>true</ExcludeFromSourceBuild>
<IsPackable>true</IsPackable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<PropertyGroup>
Expand All @@ -17,6 +18,8 @@
<PackageReference Include="Microsoft.Composition" Version="1.0.30" />
<PackageReference Include="System.Diagnostics.Contracts" Version="4.3.0" />
<PackageReference Include="System.Diagnostics.TraceSource" Version="4.0.0" />
<PackageReference Include="System.Reflection.Metadata" Version="1.6.0" />
<PackageReference Include="System.Memory" Version="4.5.3" />
</ItemGroup>

</Project>
64 changes: 64 additions & 0 deletions src/Microsoft.Cci.Extensions/SRMetadataPEReaderCache.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection.PortableExecutable;
using System.Reflection.Metadata;
using System.Text;
using SRMetadataReader = System.Reflection.Metadata.MetadataReader;

namespace Microsoft.Cci.Extensions
{

public class SRMetadataPEReaderCache : IDisposable
safern marked this conversation as resolved.
Show resolved Hide resolved
{
private bool _disposed;

private Dictionary<string, (FileStream, PEReader)> _cache = null;

public SRMetadataReader GetMetadataReader(string assemblyPath)
{
if (_cache == null)
{
_cache = new Dictionary<string, (FileStream, PEReader)>();
safern marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
if (_cache.TryGetValue(assemblyPath, out (FileStream _, PEReader peReader) value))
{
return value.peReader.GetMetadataReader();
}
}

FileStream stream = File.OpenRead(assemblyPath);
PEReader peReader = new PEReader(stream);

_cache.Add(assemblyPath, (stream, peReader));
safern marked this conversation as resolved.
Show resolved Hide resolved
return peReader.GetMetadataReader();
}

protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (_cache != null)
{
foreach ((FileStream stream, PEReader reader) in _cache.Values)
{
stream.Dispose();
reader.Dispose();
}

_cache.Clear();
}

_disposed = true;
}
}

public void Dispose()
{
Dispose(true);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,17 +133,18 @@ public void WriteAttributes(IEnumerable<ICustomAttribute> attributes, bool write
WriteAttribute(attribute, prefix);
first = false;
}
WriteSymbol("]");
WriteSymbol("]", addSpace: writeInline);
if (!writeInline)
_writer.WriteLine();

}

public void WriteAttribute(ICustomAttribute attribute, string prefix = null, SecurityAction action = SecurityAction.ActionNil)
{
if (!string.IsNullOrEmpty(prefix))
{
WriteKeyword(prefix);
WriteSymbol(":");
WriteKeyword(prefix, noSpace: true);
WriteSymbol(":", addSpace: true);
}
WriteTypeName(attribute.Constructor.ContainingType, noSpace: true); // Should we strip Attribute from name?

Expand Down Expand Up @@ -402,17 +403,6 @@ private static bool ExcludeSpecialAttribute(ICustomAttribute c)
return false;
}

private static bool IsDynamic(IEnumerable<ICustomAttribute> attributes)
{
foreach (var attribute in attributes)
{
if (attribute.Type.AreEquivalent("System.Runtime.CompilerServices.DynamicAttribute"))
return true;
}

return false;
}

private bool IncludeAttribute(ICustomAttribute attribute)
{
if (ExcludeSpecialAttribute(attribute))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ private void WriteEventDefinition(IEventDefinition evnt)
}

WriteKeyword("event");
WriteTypeName(evnt.Type);
WriteTypeName(evnt.Type, evnt.Attributes);
WriteIdentifier(evnt.Name);

if (_forCompilation && !evnt.IsAbstract())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections;
using System.Collections.Generic;
using Microsoft.Cci.Extensions.CSharp;

Expand Down Expand Up @@ -51,7 +52,8 @@ private void WriteFieldDefinition(IFieldDefinition field)
if (!field.IsCompileTimeConstant && field.GetHiddenBaseField(_filter) != Dummy.Field)
WriteKeyword("new");

WriteTypeName(field.Type);
// If it is a dummy field we call the override that ignores reference type nullability
WriteTypeName(field.Type, field.Attributes, includeReferenceTypeNullability: !(field is DummyPrivateField));

string name = field.Name.Value;
if (name.Contains("<") || name.Contains(">"))
Expand Down Expand Up @@ -95,6 +97,8 @@ public class DummyPrivateField : IFieldDefinition
private ITypeDefinition _parentType;
private ITypeReference _type;
private IName _name;
private IEnumerable<ICustomAttribute> _attributes = System.Linq.Enumerable.Empty<ICustomAttribute>();
private bool _isReadOnly;

public DummyPrivateField(ITypeDefinition parentType, ITypeReference type, string name)
{
Expand All @@ -103,6 +107,12 @@ public DummyPrivateField(ITypeDefinition parentType, ITypeReference type, string
_name = new NameTable().GetNameFor(name);
}

public DummyPrivateField(ITypeDefinition parentType, ITypeReference type, string name, IEnumerable<ICustomAttribute> attributes, bool isReadOnly) : this(parentType, type, name)
{
_attributes = attributes;
_isReadOnly = isReadOnly;
}

public uint BitLength => 0;

public IMetadataConstant CompileTimeValue => null;
Expand All @@ -119,7 +129,7 @@ public DummyPrivateField(ITypeDefinition parentType, ITypeReference type, string

public bool IsNotSerialized => false;

public bool IsReadOnly => _parentType.Attributes.HasIsReadOnlyAttribute();
public bool IsReadOnly => _isReadOnly || _parentType.Attributes.HasIsReadOnlyAttribute();

public bool IsRuntimeSpecial => false;

Expand Down Expand Up @@ -157,7 +167,7 @@ public DummyPrivateField(ITypeDefinition parentType, ITypeReference type, string

public ITypeDefinitionMember ResolvedTypeDefinitionMember { get { throw new System.NotImplementedException(); } }

public IEnumerable<ICustomAttribute> Attributes => System.Linq.Enumerable.Empty<ICustomAttribute>();
public IEnumerable<ICustomAttribute> Attributes => _attributes;

public IEnumerable<ILocation> Locations { get { throw new System.NotImplementedException(); } }

Expand Down
Loading