- linux_x64
jobParameters:
testGroup: innerloop
+ testResultsFormat: 'vstest'
timeoutInMinutes: 120
nameSuffix: ILLink_Runtime_Testing
condition:
namespace ILLink.Shared.TrimAnalysis
{
- public readonly partial struct DiagnosticContext
+ internal readonly partial struct DiagnosticContext
{
public readonly MessageOrigin Origin;
private readonly bool _diagnosticsEnabled;
namespace ILCompiler.Dataflow
{
- public readonly struct GenericArgumentDataFlow
+ internal readonly struct GenericArgumentDataFlow
{
private readonly Logger _logger;
private readonly NodeFactory _factory;
namespace ILLink.Shared.TrimAnalysis
{
- public readonly partial struct DiagnosticContext
+ internal readonly partial struct DiagnosticContext
{
public readonly MessageOrigin Origin;
public readonly bool DiagnosticsEnabled;
/// - Single-file warnings (suppressed by RequiresAssemblyFilesAttribute)
/// Note that not all categories are used/supported by all tools, for example the ILLink only handles trimmer warnings and ignores the rest.
/// </summary>
- public readonly partial struct DiagnosticContext
+ internal readonly partial struct DiagnosticContext
{
/// <param name="id">The diagnostic ID, this will be used to determine the category of diagnostic (trimmer, AOT, single-file)</param>
/// <param name="args">The arguments for diagnostic message.</param>
# Avoid redundant accessibility modifiers when they're default
dotnet_style_require_accessibility_modifiers = omit_if_default:suggestion
-### Code Style Analyzers
-
-# IDE0004: Remove unnecessary cast
-dotnet_diagnostic.IDE0004.severity = warning
-
-# IDE0005: Remove unnecessary usings/imports
-dotnet_diagnostic.IDE0005.severity = warning
-
-# IDE0019: Use pattern matching
-dotnet_diagnostic.IDE0019.severity = warning
-
-# IDE0020: Use pattern matching
-dotnet_diagnostic.IDE0020.severity = warning
-
-# IDE0029: Null check can be simplified
-dotnet_diagnostic.IDE0029.severity = warning
-
-# IDE0031: Null check can be simplified
-dotnet_diagnostic.IDE0031.severity = warning
-
-# IDE0035: Remove unreachable code
-dotnet_diagnostic.IDE0035.severity = warning
-
-# IDE0036: Order modifiers
-dotnet_diagnostic.IDE0036.severity = warning
-
-# IDE0039: Prefer local functions over anonymous functions
-dotnet_diagnostic.IDE0039.severity = warning
-
-# IDE0041: Null check can be simplified
-dotnet_diagnostic.IDE0041.severity = warning
-
-# IDE0043: Format string contains invalid placeholder
-dotnet_diagnostic.IDE0043.severity = warning
-
-# IDE0044: Make field readonly
-dotnet_diagnostic.IDE0044.severity = warning
-
-# IDE0047: Parentheses can be removed
-dotnet_diagnostic.IDE0047.severity = warning
-
-# IDE0051: Remove unused private members (no reads or writes)
-dotnet_diagnostic.IDE0051.severity = warning
-
-# IDE0052: Remove unread private member
-dotnet_diagnostic.IDE0052.severity = warning
-
-# IDE0053: Prefer expression bodies for lambdas
-dotnet_diagnostic.IDE0053.severity = warning
-
-# IDE0054: Use compound assignment
-dotnet_diagnostic.IDE0054.severity = warning
-
-# IDE0059: Unnecessary assignment to a value
-dotnet_diagnostic.IDE0059.severity = warning
-
-# IDE0060: Remove unused parameter
-dotnet_diagnostic.IDE0060.severity = warning
-
-# IDE0062: Local function can be made static
-dotnet_diagnostic.IDE0062.severity = none
-
-# IDE0065: Using directives to be placed outside the namespace
-dotnet_diagnostic.IDE0065.severity = warning
-
-# IDE0073: File header
-dotnet_diagnostic.IDE0073.severity = warning
file_header_template = Copyright (c) .NET Foundation and contributors. All rights reserved.\nLicensed under the MIT license. See LICENSE file in the project root for full license information.
-# IDE0074: Use compound assignment
-dotnet_diagnostic.IDE0074.severity = warning
-
-# IDE0082: Convert typeof to nameof
-dotnet_diagnostic.IDE0082.severity = warning
-
-# IDE0083: Use is not pattern matching
-#dotnet_diagnostic.IDE0083.severity = warning // requires new C# for Mono
-
-# IDE0100: Remove redundant equality
-dotnet_diagnostic.IDE0100.severity = none
-
-# IDE0110: Remove unnecessary discard
-dotnet_diagnostic.IDE0110.severity = warning
-
-# IDE0170: Simplify property pattern
-dotnet_diagnostic.IDE0170.severity = none
-
-# IDE0071: Interpolation can be simplified
-dotnet_diagnostic.IDE0071.severity = none
-
-# IDE0200: Lambda expression can be removed
-dotnet_diagnostic.IDE0200.severity = none
-
-## CA analyzer rules
-dotnet_analyzer_diagnostic.category-performance.severity = warning
-dotnet_analyzer_diagnostic.category-maintainability.severity = warning
-dotnet_analyzer_diagnostic.category-reliability.severity = warning
-dotnet_analyzer_diagnostic.category-usage.severity = warning
-#dotnet_analyzer_diagnostic.category-style.severity = warning
-
-# call GC.SuppressFinalize(object)
-dotnet_diagnostic.CA1816.severity = none
-
-# CA1834: Use 'StringBuilder.Append(char)'
-dotnet_diagnostic.CA1834.severity = none
-
-# CA1859: Change return type of method
-dotnet_diagnostic.CA1859.severity = none
-
-# CA1860: Prefer count to 0 rather than 'Any()'
-dotnet_diagnostic.CA1860.severity = none
-
-# RS2008 Ignore analyzer release tracking
-dotnet_diagnostic.RS2008.severity = none
-
-# Exception type is not sufficiently specific
-dotnet_diagnostic.CA2201.severity = none
-
-# xUnit1004: Test methods should not be skipped
-dotnet_diagnostic.xUnit1004.severity = none
-
-# CA1805: Member is explicitly initialized to it's default value
-dotnet_diagnostic.CA1805.severity = none
-
-# CA1066: Implement IEquatable when overriding Equals
-dotnet_diagnostic.CA1066.severity = none
-
-# CA1067: Override Equals because it implements IEquatable
-dotnet_diagnostic.CA1067.severity = none
-
-# CA1311: Specify culture version
-dotnet_diagnostic.CA1311.severity = none
-
-# CA3075: Unsafe overload of method
-dotnet_diagnostic.CA3075.severity = none
-
-## SA analyzer rules
+### Code Style Analyzers
# Access modifier must be declared
dotnet_diagnostic.SA1400.severity = none
-dotnet_diagnostic.SA1129.severity = none
-
-# SA1518: File is required to end with newline character
-dotnet_diagnostic.SA1518.severity = none
-
-# SA1205: Partial elements should declare access modifier
-dotnet_diagnostic.SA1205.severity = none
-
-# SA1027: Tabs and spaces should be used correctly
-dotnet_diagnostic.SA1027.severity = none
-
-# SA1121: Use built-in type alias
-dotnet_diagnostic.SA1121.severity = none
-
-# SA1028: Code should not contain trailing whitespace
-dotnet_diagnostic.SA1028.severity = none
-
-# SA1212: A get accessor appears after a set accessor
-dotnet_diagnostic.SA1212.severity = none
-
-# SA1001: Commas should not be preceded by whitespace
-dotnet_diagnostic.SA1001.severity = none
-
-[src/linker/ref/**/*.cs]
-
-# CA1822: Mark members as static
-dotnet_diagnostic.CA1822.severity = none
-
-# IDE0060: Remove unused parameter
-dotnet_diagnostic.IDE0060.severity = none
-
-[test/**/*.cs]
-dotnet_diagnostic.IDE0060.severity = none
-
-[test/Mono.Linker.Tests/TestCases/Dependencies/WarningSuppressionExpectations*.cs]
dotnet_diagnostic.IDE0073.severity = none
-
-[external**]
-dotnet_diagnostic.IDE0073.severity = none
-
-[external**]
-dotnet_analyzer_diagnostic.severity = none
-generated_code = true
+#pragma warning disable
//
// Options.cs
//
// App-compat: You can use double or single quotes to quote a name, and Fusion (or rather the IdentityAuthority) picks one
// by some algorithm. Rather than guess at it, we use double quotes consistently.
- if (s != s.Trim() || s.Contains("\"") || s.Contains("\'"))
+ if (s != s.Trim() || s.Contains('"') || s.Contains('\''))
needsQuoting = true;
if (needsQuoting)
new KeyValuePair<char, string>('t', "\t"),
};
}
-}
\ No newline at end of file
+}
//
// These helpers convert between the combined flags+contentType+processorArchitecture value and the separated parts.
//
- // Since these are only for trusted callers, they do NOT check for out of bound bits.
+ // Since these are only for trusted callers, they do NOT check for out of bound bits.
//
internal static AssemblyContentType ExtractAssemblyContentType(this AssemblyNameFlags flags)
return (AssemblyNameFlags)(((int)flags) | (((int)contentType) << 9) | ((int)processorArchitecture << 4));
}
}
-}
\ No newline at end of file
+}
}
//
- // Return the next token in assembly name. If you expect the result to be DisplayNameToken.String,
+ // Return the next token in assembly name. If you expect the result to be DisplayNameToken.String,
// use GetNext(out String) instead.
//
internal Token GetNext()
{
- string ignore;
- return GetNext(out ignore);
+ return GetNext(out _);
}
//
- // Return the next token in assembly name. If the result is DisplayNameToken.String,
+ // Return the next token in assembly name. If the result is DisplayNameToken.String,
// sets "tokenString" to the tokenized string.
//
- internal Token GetNext(out string tokenString)
+ internal Token GetNext(out string? tokenString)
{
tokenString = null;
while (char.IsWhiteSpace(_chars[_index]))
private readonly char[] _chars;
private int _index;
}
-}
\ No newline at end of file
+}
AssemblyNameLexer lexer = new AssemblyNameLexer(s);
// Name must come first.
- string name;
+ string? name;
AssemblyNameLexer.Token token = lexer.GetNext(out name);
if (token != AssemblyNameLexer.Token.String)
throw new FileLoadException();
if (string.IsNullOrEmpty(name) || name.IndexOfAny(s_illegalCharactersInSimpleName) != -1)
throw new FileLoadException();
- Version version = null;
- string cultureName = null;
- byte[] pkt = null;
+ Version? version = null;
+ string? cultureName = null;
+ byte[]? pkt = null;
AssemblyNameFlags flags = 0;
List<string> alreadySeen = new List<string>();
{
if (token != AssemblyNameLexer.Token.Comma)
throw new FileLoadException();
- string attributeName;
+ string? attributeName;
token = lexer.GetNext(out attributeName);
if (token != AssemblyNameLexer.Token.String)
throw new FileLoadException();
if (token != AssemblyNameLexer.Token.Equals)
throw new FileLoadException();
- string attributeValue;
+ string? attributeValue;
token = lexer.GetNext(out attributeValue);
if (token != AssemblyNameLexer.Token.String)
throw new FileLoadException();
- if (String.IsNullOrEmpty(attributeName))
+ if (string.IsNullOrEmpty(attributeName))
throw new FileLoadException();
for (int i = 0; i < alreadySeen.Count; i++)
if (alreadySeen[i].Equals(attributeName, StringComparison.OrdinalIgnoreCase))
throw new FileLoadException(); // Cannot specify the same attribute twice.
}
+ Debug.Assert(attributeValue is not null);
alreadySeen.Add(attributeName);
if (attributeName.Equals("Version", StringComparison.OrdinalIgnoreCase))
{
// Desktop compat: If we got here, the attribute name is unknown to us. Ignore it (as long it's not duplicated.)
token = lexer.GetNext();
}
- return new RuntimeAssemblyName(name, version, cultureName, flags, pkt);
+ return new RuntimeAssemblyName(name!, version!, cultureName!, flags, pkt!);
}
private static Version ParseVersion(string attributeValue)
private static readonly char[] s_illegalCharactersInSimpleName = { '/', '\\', ':' };
}
-}
\ No newline at end of file
+}
// Equality - this compares every bit of data in the RuntimeAssemblyName which is acceptable for use as keys in a cache
// where semantic duplication is permissible. This method is *not* meant to define ref->def binding rules or
// assembly binding unification rules.
- public bool Equals(RuntimeAssemblyName other)
+ public bool Equals(RuntimeAssemblyName? other)
{
if (other == null)
return false;
return true;
}
- public sealed override bool Equals(object obj)
+ public sealed override bool Equals(object? obj)
{
- RuntimeAssemblyName other = obj as RuntimeAssemblyName;
+ RuntimeAssemblyName? other = obj as RuntimeAssemblyName;
if (other == null)
return false;
return Equals(other);
}
}
}
-}
\ No newline at end of file
+}
//
internal sealed class TypeLexer
{
- public TypeLexer(String s)
+ public TypeLexer(string s)
{
// Turn the string into a char array with a NUL terminator.
char[] chars = new char[s.Length + 1];
{
SkipWhiteSpace();
int index = _index + 1;
- while (Char.IsWhiteSpace(_chars[index]))
+ while (char.IsWhiteSpace(_chars[index]))
index++;
char c = _chars[index];
return CharToToken(c);
//
// Terminated by the first non-escaped reserved character ('[', ']', '+', '&', '*' or ',')
//
- public String GetNextIdentifier()
+ public string GetNextIdentifier()
{
SkipWhiteSpace();
// Common sense would dictate throwing an ArgumentException but that's not what the desktop CLR does.
// The desktop CLR treats this case by returning FALSE from TypeName::TypeNameParser::GetIdentifier().
// Unfortunately, no one checks this return result. Instead, the CLR keeps parsing (unfortunately, the lexer
- // was left in some strange state by the previous failure but typically, this goes unnoticed) and eventually, tries to resolve
+ // was left in some strange state by the previous failure but typically, this goes unnoticed) and eventually, tries to resolve
// a Type whose name is the empty string. When it can't resolve that type, the CLR throws a TypeLoadException()
// complaining about be unable to find a type with the empty name.
//
// To emulate this accidental behavior, we'll throw a special exception that's caught by the TypeParser.
- //
+ //
throw new IllegalEscapeSequenceException();
}
}
}
_index = src;
- return new String(buffer, 0, dst);
+ return new string(buffer, 0, dst);
}
//
- // Lex the next segment as the assembly name at the end of an assembly-qualified type name. (Do not use for
+ // Lex the next segment as the assembly name at the end of an assembly-qualified type name. (Do not use for
// assembly names embedded inside generic type arguments.)
//
// Terminated by NUL. There are no escape characters defined by the typename lexer (however, AssemblyName
buffer[dst++] = c;
}
_index = src;
- String fullName = new String(buffer, 0, dst);
+ string fullName = new string(buffer, 0, dst);
return AssemblyNameParser.Parse(fullName);
}
//
// Lex the next segment as an assembly name embedded inside a generic argument type.
//
- // Terminated by an unescaped ']'.
+ // Terminated by an unescaped ']'.
//
public RuntimeAssemblyName GetNextEmbeddedAssemblyName()
{
buffer[dst++] = c;
}
_index = src;
- String fullName = new String(buffer, 0, dst);
+ var fullName = new string(buffer, 0, dst);
return AssemblyNameParser.Parse(fullName);
}
}
//
- // The desktop typename parser has a strange attitude towards whitespace. It throws away whitespace between punctuation tokens and whitespace
- // preceeding identifiers or assembly names (and this cannot be escaped away). But whitespace between the end of an identifier
+ // The desktop typename parser has a strange attitude towards whitespace. It throws away whitespace between punctuation tokens and whitespace
+ // preceeding identifiers or assembly names (and this cannot be escaped away). But whitespace between the end of an identifier
// and the punctuation that ends it is *not* ignored.
//
// In other words, GetType(" Foo") searches for "Foo" but GetType("Foo ") searches for "Foo ".
//
private void SkipWhiteSpace()
{
- while (Char.IsWhiteSpace(_chars[_index]))
+ while (char.IsWhiteSpace(_chars[_index]))
_index++;
}
Ampersand = 6, //'&'
Other = 7, //Type identifier, AssemblyName or embedded AssemblyName.
}
-}
\ No newline at end of file
+}
namespace System.Reflection.Runtime.TypeParsing
{
//
- // The TypeName class is the base class for a family of types that represent the nodes in a parse tree for
+ // The TypeName class is the base class for a family of types that represent the nodes in a parse tree for
// assembly-qualified type names.
//
public abstract class TypeName
{
s += sep;
sep = ",";
- AssemblyQualifiedTypeName assemblyQualifiedTypeArgument = genericTypeArgument as AssemblyQualifiedTypeName;
+ AssemblyQualifiedTypeName? assemblyQualifiedTypeArgument = genericTypeArgument as AssemblyQualifiedTypeName;
if (assemblyQualifiedTypeArgument == null || assemblyQualifiedTypeArgument.AssemblyName == null)
s += genericTypeArgument.ToString();
else
return s;
}
}
-}
\ No newline at end of file
+}
namespace System.Reflection.Runtime.TypeParsing
{
//
- // Parser for type names passed to GetType() apis.
+ // Parser for type names passed to GetType() apis.
//
public sealed class TypeParser
{
//
// Parses a typename. The typename may be optionally postpended with a "," followed by a legal assembly name.
//
- public static TypeName ParseTypeName(string s)
+ public static TypeName? ParseTypeName(string s)
{
try
{
//
// Parses a typename. The typename may be optionally postpended with a "," followed by a legal assembly name.
//
- private static TypeName ParseAssemblyQualifiedTypeName(String s)
- {
+ private static TypeName? ParseAssemblyQualifiedTypeName(string s)
+ {
if (string.IsNullOrEmpty(s))
return null;
// Desktop compat: a whitespace-only "typename" qualified by an assembly name throws an ArgumentException rather than
// a TypeLoadException.
int idx = 0;
- while (idx < s.Length && Char.IsWhiteSpace(s[idx]))
+ while (idx < s.Length && char.IsWhiteSpace(s[idx]))
{
idx++;
}
catch (TypeLexer.IllegalEscapeSequenceException)
{
// Emulates a CLR4.5 bug that causes any string that contains an illegal escape sequence to be parsed as the empty string.
- return ParseAssemblyQualifiedTypeName(String.Empty);
+ return ParseAssemblyQualifiedTypeName(string.Empty);
}
}
- private TypeParser(String s)
+ private TypeParser(string s)
{
_lexer = new TypeLexer(s);
}
//
// Foo or Foo+Inner
- //
+ //
private NamedTypeName ParseNamedTypeName()
{
NamedTypeName namedType = ParseNamespaceTypeName();
while (_lexer.Peek == TokenType.Plus)
{
_lexer.Skip();
- String nestedTypeName = _lexer.GetNextIdentifier();
+ string nestedTypeName = _lexer.GetNextIdentifier();
namedType = new NestedTypeName(nestedTypeName, namedType);
}
return namedType;
//
// Non-nested named type.
- //
+ //
private NamespaceTypeName ParseNamespaceTypeName()
{
string fullName = _lexer.GetNextIdentifier();
}
else if (token == TokenType.OpenSqBracket)
{
- RuntimeAssemblyName assemblyName = null;
+ RuntimeAssemblyName? assemblyName = null;
NonQualifiedTypeName typeName = ParseNonQualifiedTypeName();
token = _lexer.GetNextToken();
if (token == TokenType.Comma)
private readonly TypeLexer _lexer;
}
-}
\ No newline at end of file
+}
public sealed override ImmutableArray<string> FixableDiagnosticIds => SupportedDiagnostics.Select (dd => dd.Id).ToImmutableArray ();
- private static LocalizableString CodeFixTitle => new LocalizableResourceString (nameof (Resources.DynamicallyAccessedMembersCodeFixTitle), Resources.ResourceManager, typeof (Resources));
+ private static LocalizableResourceString CodeFixTitle => new LocalizableResourceString (nameof (Resources.DynamicallyAccessedMembersCodeFixTitle), Resources.ResourceManager, typeof (Resources));
private static string FullyQualifiedAttributeName => DynamicallyAccessedMembersAnalyzer.FullyQualifiedDynamicallyAccessedMembersAttribute;
private static readonly string[] AttributeOnReturn = {
DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsParameter.AsString (),
- DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsMethodReturnType.AsString() ,
+ DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsMethodReturnType.AsString(),
DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsField.AsString (),
- DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsThisParameter.AsString () ,
+ DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsThisParameter.AsString (),
DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodReturnValueBetweenOverrides.AsString ()
};
private static readonly string[] AttributeOnGeneric = {
DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsParameter.AsString(),
- DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsMethodReturnType.AsString () ,
+ DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsMethodReturnType.AsString (),
DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsField.AsString(),
DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsThisParameter.AsString(),
DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsGenericParameter.AsString(),
}
}
}
-}
\ No newline at end of file
+}
namespace ILLink.RoslynAnalyzer.DataFlow
{
- public struct CapturedReferenceValue : IEquatable<CapturedReferenceValue>
+ public readonly struct CapturedReferenceValue : IEquatable<CapturedReferenceValue>
{
public readonly IOperation? Reference;
}
public bool Equals (CapturedReferenceValue other) => Reference == other.Reference;
+
+ public override bool Equals (object obj)
+ => obj is CapturedReferenceValue inst && Equals (inst);
+
+ public override int GetHashCode ()
+ => Reference?.GetHashCode () ?? 0;
}
public struct CapturedReferenceLattice : ILattice<CapturedReferenceValue>
{
- public CapturedReferenceValue Top => new CapturedReferenceValue ();
+ public CapturedReferenceValue Top => default;
public CapturedReferenceValue Meet (CapturedReferenceValue left, CapturedReferenceValue right)
{
throw new InvalidOperationException ();
}
}
-}
\ No newline at end of file
+}
public BlockProxy LastBlock (RegionProxy region) =>
new BlockProxy (ControlFlowGraph.Blocks[region.Region.LastBlockOrdinal]);
}
-}
\ No newline at end of file
+}
public bool Equals (InterproceduralState<TValue, TValueLattice> other)
=> Methods.Equals (other.Methods) && HoistedLocals.Equals (other.HoistedLocals);
+ public override bool Equals (object obj)
+ => obj is InterproceduralState<TValue, TValueLattice> inst && Equals (inst);
+
+ public override int GetHashCode ()
+ => throw new NotImplementedException ();
+
public InterproceduralState<TValue, TValueLattice> Clone ()
=> new (Methods.Clone (),
HoistedLocals.Clone (), lattice);
HoistedLocalLattice.Meet (left.HoistedLocals, right.HoistedLocals),
this);
}
-}
\ No newline at end of file
+}
public void InterproceduralAnalyze ()
{
- var methodGroupLattice = new ValueSetLattice<MethodBodyValue> ();
- var hoistedLocalLattice = new DictionaryLattice<LocalKey, Maybe<TValue>, MaybeLattice<TValue, TLattice>> ();
+ ValueSetLattice<MethodBodyValue> methodGroupLattice = default;
+ DictionaryLattice<LocalKey, Maybe<TValue>, MaybeLattice<TValue, TLattice>> hoistedLocalLattice = default;
var interproceduralStateLattice = new InterproceduralStateLattice<TValue, TLattice> (
methodGroupLattice, hoistedLocalLattice);
var interproceduralState = interproceduralStateLattice.Top;
ImmutableDictionary<CaptureId, FlowCaptureKind> lValueFlowCaptures,
InterproceduralState<TValue, TLattice> interproceduralState);
}
-}
\ No newline at end of file
+}
// (don't have specific I*Operation types), such as pointer dereferences.
if (targetOperation.Kind is OperationKind.None)
break;
- throw new NotImplementedException ($"{targetOperation.GetType ().ToString ()}: {targetOperation.Syntax.GetLocation ().GetLineSpan ()}");
+ throw new NotImplementedException ($"{targetOperation.GetType ()}: {targetOperation.Syntax.GetLocation ().GetLineSpan ()}");
}
return Visit (operation.Value, state);
}
if (!operation.GetValueUsageInfo (Method).HasFlag (ValueUsageInfo.Read)) {
// There are known cases where this assert doesn't hold, because LValueFlowCaptureProvider
// produces the wrong result in some cases for flow captures with IsInitialization = true.
- // https://github.com/dotnet/linker/issues/2749
+ // https://github.com/dotnet/linker/issues/2749
// Debug.Assert (IsLValueFlowCapture (operation.Id));
return TopValue;
}
public bool Equals (LocalKey other) => SymbolEqualityComparer.Default.Equals (Local, other.Local) &&
(CaptureId?.Equals (other.CaptureId) ?? other.CaptureId == null);
+ public override bool Equals (object obj)
+ => obj is LocalKey inst && Equals (inst);
+
+ public override int GetHashCode ()
+ => CaptureId is null ? SymbolEqualityComparer.Default.GetHashCode (Local) : CaptureId.GetHashCode ();
+
public override string ToString ()
{
if (Local != null)
public LocalState (TValue defaultValue)
: this (new DefaultValueDictionary<LocalKey, TValue> (defaultValue),
- new DefaultValueDictionary<CaptureId, CapturedReferenceValue> (new CapturedReferenceValue ()))
+ new DefaultValueDictionary<CaptureId, CapturedReferenceValue> (default (CapturedReferenceValue)))
{
}
}
public LocalState (DefaultValueDictionary<LocalKey, TValue> dictionary)
- : this (dictionary, new DefaultValueDictionary<CaptureId, CapturedReferenceValue> (new CapturedReferenceValue ()))
+ : this (dictionary, new DefaultValueDictionary<CaptureId, CapturedReferenceValue> (default (CapturedReferenceValue)))
{
}
public bool Equals (LocalState<TValue> other) => Dictionary.Equals (other.Dictionary);
+ public override bool Equals (object obj)
+ => obj is LocalState<TValue> inst && Equals (inst);
+
public TValue Get (LocalKey key) => Dictionary.Get (key);
+ public override int GetHashCode ()
+ => throw new NotImplementedException ();
+
public void Set (LocalKey key, TValue value) => Dictionary.Set (key, value);
public override string ToString () => Dictionary.ToString ();
public LocalStateLattice (TValueLattice valueLattice)
{
Lattice = new DictionaryLattice<LocalKey, TValue, TValueLattice> (valueLattice);
- CapturedReferenceLattice = new DictionaryLattice<CaptureId, CapturedReferenceValue, CapturedReferenceLattice> (new CapturedReferenceLattice ());
+ CapturedReferenceLattice = new DictionaryLattice<CaptureId, CapturedReferenceValue, CapturedReferenceLattice> (default (CapturedReferenceLattice));
Top = new (Lattice.Top);
}
Debug.Assert (ControlFlowGraph == other.ControlFlowGraph);
return true;
}
+
+ public override bool Equals (object obj)
+ => obj is MethodBodyValue inst && Equals (inst);
+
+ public override int GetHashCode () => SymbolEqualityComparer.Default.GetHashCode (Method);
}
-}
\ No newline at end of file
+}
throw new NotImplementedException ();
var diagnosticContext = new DiagnosticContext (location);
- var requireDynamicallyAccessedMembersAction = new RequireDynamicallyAccessedMembersAction (diagnosticContext, new ReflectionAccessAnalyzer ());
+ var requireDynamicallyAccessedMembersAction = new RequireDynamicallyAccessedMembersAction (diagnosticContext, default (ReflectionAccessAnalyzer));
requireDynamicallyAccessedMembersAction.Invoke (sourceValue, targetWithDynamicallyAccessedMembers);
return diagnosticContext.Diagnostics;
return method.Parameters.Length + (method.HasImplicitThis () ? 1 : 0);
}
}
-}
\ No newline at end of file
+}
public static ValueUsageInfo GetValueUsageInfo (this IOperation operation, ISymbol containingSymbol)
{
/*
- | code | Read | Write | ReadableRef | WritableRef | NonReadWriteRef |
- | x.Prop = 1 | | ✔️ | | | |
- | x.Prop += 1 | ✔️ | ✔️ | | | |
- | x.Prop++ | ✔️ | ✔️ | | | |
- | Foo(x.Prop) | ✔️ | | | | |
- | Foo(x.Prop), | | | ✔️ | | |
- where void Foo(in T v)
- | Foo(out x.Prop) | | | | ✔️ | |
- | Foo(ref x.Prop) | | | ✔️ | ✔️ | |
- | nameof(x) | | | | | ✔️ | ️
- | sizeof(x) | | | | | ✔️ | ️
- | typeof(x) | | | | | ✔️ | ️
- | out var x | | ✔️ | | | | ️
- | case X x: | | ✔️ | | | | ️
- | obj is X x | | ✔️ | | | |
- | ref var x = | | | ✔️ | ✔️ | |
- | ref readonly var x = | | | ✔️ | | |
-
- */
+ | code | Read | Write | ReadableRef | WritableRef | NonReadWriteRef |
+ | x.Prop = 1 | | ✔️ | | | |
+ | x.Prop += 1 | ✔️ | ✔️ | | | |
+ | x.Prop++ | ✔️ | ✔️ | | | |
+ | Foo(x.Prop) | ✔️ | | | | |
+ | Foo(x.Prop), | | | ✔️ | | |
+ where void Foo(in T v)
+ | Foo(out x.Prop) | | | | ✔️ | |
+ | Foo(ref x.Prop) | | | ✔️ | ✔️ | |
+ | nameof(x) | | | | | ✔️ | ️
+ | sizeof(x) | | | | | ✔️ | ️
+ | typeof(x) | | | | | ✔️ | ️
+ | out var x | | ✔️ | | | | ️
+ | case X x: | | ✔️ | | | | ️
+ | obj is X x | | ✔️ | | | |
+ | ref var x = | | | ✔️ | ✔️ | |
+ | ref readonly var x = | | | ✔️ | | |
+ */
if (operation is ILocalReferenceOperation localReference &&
localReference.IsDeclaration &&
!localReference.IsImplicit) // Workaround for https://github.com/dotnet/roslyn/issues/30753
return setMethod;
}
}
-}
\ No newline at end of file
+}
switch (symbol) {
case IFieldSymbol fieldSymbol:
sb.Append (fieldSymbol.ContainingSymbol.ToDisplayString (ILLinkTypeDisplayFormat));
- sb.Append (".");
+ sb.Append ('.');
sb.Append (fieldSymbol.MetadataName);
break;
// don't include the containing type's name. This matches the behavior of
// CSharpErrorMessageFormat.
sb.Append (methodSymbol.ContainingType.ToDisplayString (ILLinkTypeDisplayFormat));
- sb.Append (".");
+ sb.Append ('.');
}
// Format parameter types with only type names.
sb.Append (methodSymbol.ToDisplayString (ILLinkMemberDisplayFormat));
/// </summary>
/// <param name="compilation">Compilation to search for members</param>
/// <returns>A list of special incomptaible members</returns>
- protected virtual ImmutableArray<ISymbol> GetSpecialIncompatibleMembers (Compilation compilation) => new ImmutableArray<ISymbol> ();
+ protected virtual ImmutableArray<ISymbol> GetSpecialIncompatibleMembers (Compilation compilation) => default;
/// <summary>
/// Verifies that the MSBuild requirements to run the analyzer are fulfilled
}
protected override bool VerifyAttributeArguments (AttributeData attribute) => attribute.ConstructorArguments.Length == 0 ||
- attribute.ConstructorArguments.Length >= 1 && attribute.ConstructorArguments[0] is { Type: { SpecialType: SpecialType.System_String } } ctorArg;
+ attribute.ConstructorArguments.Length >= 1 && attribute.ConstructorArguments[0] is { Type.SpecialType: SpecialType.System_String } ctorArg;
protected override string GetMessageFromAttribute (AttributeData requiresAttribute)
{
options.IsMSBuildPropertyValueTrue (MSBuildPropertyOptionNames.EnableAotAnalyzer, compilation);
protected override bool VerifyAttributeArguments (AttributeData attribute) =>
- attribute.ConstructorArguments.Length >= 1 && attribute.ConstructorArguments[0] is { Type: { SpecialType: SpecialType.System_String } } ctorArg;
+ attribute.ConstructorArguments.Length >= 1 && attribute.ConstructorArguments[0] is { Type.SpecialType: SpecialType.System_String } ctorArg;
protected override string GetMessageFromAttribute (AttributeData? requiresAttribute)
{
/// Doesn't check the associated symbol for overrides and virtual methods because the analyzer should warn on mismatched between the property AND the accessors
/// </summary>
/// <param name="member">
- /// Symbol that is either an overriding member or an overriden/virtual member
+ /// Symbol that is either an overriding member or an overriden/virtual member
/// </param>
public static bool IsOverrideInRequiresScope (this ISymbol member, string requiresAttribute)
{
/// <param name="attribute">Attribute data to compare.</param>
/// <returns>True if the validation was successfull; otherwise, returns false.</returns>
public static bool VerifyRequiresUnreferencedCodeAttributeArguments (AttributeData attribute)
- => attribute.ConstructorArguments.Length >= 1 && attribute.ConstructorArguments[0] is { Type: { SpecialType: SpecialType.System_String } } ctorArg;
+ => attribute.ConstructorArguments.Length >= 1 && attribute.ConstructorArguments[0] is { Type.SpecialType: SpecialType.System_String } ctorArg;
public static string GetMessageFromAttribute (AttributeData? requiresAttribute)
{
return MessageFormat.FormatRequiresAttributeMessageArg (message);
}
}
-}
\ No newline at end of file
+}
namespace ILLink.Shared.TrimAnalysis
{
- partial record ArrayValue
+ internal partial record ArrayValue
{
public readonly Dictionary<int, MultiValue> IndexValues;
namespace ILLink.Shared.TrimAnalysis
{
- readonly partial struct DiagnosticContext
+ internal readonly partial struct DiagnosticContext
{
public List<Diagnostic> Diagnostics { get; } = new ();
namespace ILLink.Shared.TrimAnalysis
{
- partial record FieldValue
+ internal partial record FieldValue
{
public FieldValue (IFieldSymbol fieldSymbol) => FieldSymbol = fieldSymbol;
#nullable enable
namespace ILLink.Shared.TrimAnalysis
{
- sealed partial class FlowAnnotations
+ internal sealed partial class FlowAnnotations
{
// In the analyzer there's no stateful data the flow annotations need to store
// so we just create a singleton on demand.
/// This is a System.Type value which represents generic parameter (basically result of typeof(T))
/// Its actual type is unknown, but it can have annotations.
/// </summary>
- partial record GenericParameterValue
+ internal partial record GenericParameterValue
{
public GenericParameterValue (ITypeParameterSymbol typeParameterSymbol) => GenericParameter = new (typeParameterSymbol);
namespace ILLink.Shared.TrimAnalysis
{
- partial struct HandleCallAction
+ internal partial struct HandleCallAction
{
#pragma warning disable CA1822 // Mark members as static - the other partial implementations might need to be instance methods
#pragma warning disable IDE0060 // Unused parameters - the other partial implementation may need the parameter
_operation = operation;
_diagnosticContext = diagnosticContext;
_annotations = FlowAnnotations.Instance;
- _reflectionAccessAnalyzer = new ReflectionAccessAnalyzer ();
+ _reflectionAccessAnalyzer = default;
_requireDynamicallyAccessedMembersAction = new (diagnosticContext, _reflectionAccessAnalyzer);
}
namespace ILLink.Shared.TrimAnalysis
{
- partial record MethodParameterValue
+ internal partial record MethodParameterValue
{
public MethodParameterValue (IParameterSymbol parameterSymbol)
: this (new ParameterProxy (parameterSymbol)) { }
namespace ILLink.Shared.TypeSystemProxy
{
- readonly partial struct MethodProxy
+ internal readonly partial struct MethodProxy
{
public MethodProxy (IMethodSymbol method) => Method = method;
namespace ILLink.Shared.TrimAnalysis
{
- partial record MethodReturnValue
+ internal partial record MethodReturnValue
{
public MethodReturnValue (IMethodSymbol methodSymbol)
{
namespace ILLink.Shared.TypeSystemProxy
{
- partial struct ParameterProxy
+ internal partial struct ParameterProxy
{
public ParameterProxy (IParameterSymbol parameter)
{
namespace ILLink.Shared.TrimAnalysis
{
- partial struct RequireDynamicallyAccessedMembersAction
+ internal partial struct RequireDynamicallyAccessedMembersAction
{
readonly ReflectionAccessAnalyzer _reflectionAccessAnalyzer;
#pragma warning disable CA1822 // Mark members as static - the other partial implementations might need to be instance methods
TypeKind.TypeParameter =>
new NullableValueWithDynamicallyAccessedMembers (new TypeProxy (type),
new GenericParameterValue ((ITypeParameterSymbol) underlyingType)),
- // typeof(Nullable<>)
+ // typeof(Nullable<>)
TypeKind.Error => new SystemTypeValue (new TypeProxy (type)),
TypeKind.Class or TypeKind.Struct or TypeKind.Interface =>
new NullableSystemTypeValue (new TypeProxy (type), new SystemTypeValue (new TypeProxy (underlyingType))),
if (targetValue is not ValueWithDynamicallyAccessedMembers targetWithDynamicallyAccessedMembers)
throw new NotImplementedException ();
- var requireDynamicallyAccessedMembersAction = new RequireDynamicallyAccessedMembersAction (diagnosticContext, new ReflectionAccessAnalyzer ());
+ var requireDynamicallyAccessedMembersAction = new RequireDynamicallyAccessedMembersAction (diagnosticContext, default (ReflectionAccessAnalyzer));
requireDynamicallyAccessedMembersAction.Invoke (sourceValue, targetWithDynamicallyAccessedMembers);
}
}
case SpecialType.System_Byte when constantValue is byte byteConstantValue:
constValue = new ConstIntValue (byteConstantValue);
return true;
- case SpecialType.System_Int16 when constantValue is Int16 int16ConstantValue:
+ case SpecialType.System_Int16 when constantValue is short int16ConstantValue:
constValue = new ConstIntValue (int16ConstantValue);
return true;
- case SpecialType.System_UInt16 when constantValue is UInt16 uint16ConstantValue:
+ case SpecialType.System_UInt16 when constantValue is ushort uint16ConstantValue:
constValue = new ConstIntValue (uint16ConstantValue);
return true;
- case SpecialType.System_Int32 when constantValue is Int32 int32ConstantValue:
+ case SpecialType.System_Int32 when constantValue is int int32ConstantValue:
constValue = new ConstIntValue (int32ConstantValue);
return true;
- case SpecialType.System_UInt32 when constantValue is UInt32 uint32ConstantValue:
+ case SpecialType.System_UInt32 when constantValue is uint uint32ConstantValue:
constValue = new ConstIntValue ((int) uint32ConstantValue);
return true;
}
if (lines == null)
return;
foreach (var line in lines) {
- TraceWrite (new String ('\t', level));
+ TraceWrite (new string ('\t', level));
TraceWriteLine (line);
}
}
/// - Single-file warnings (suppressed by RequiresAssemblyFilesAttribute)
/// Note that not all categories are used/supported by all tools, for example the ILLink only handles trimmer warnings and ignores the rest.
/// </summary>
- public readonly partial struct DiagnosticContext
+ internal readonly partial struct DiagnosticContext
{
/// <param name="id">The diagnostic ID, this will be used to determine the category of diagnostic (trimmer, AOT, single-file)</param>
/// <param name="args">The arguments for diagnostic message.</param>
namespace ILLink.Shared.TrimAnalysis
{
// Shared helpers to go from MethodProxy to dataflow values.
- public partial class FlowAnnotations
+ internal partial class FlowAnnotations
{
internal partial bool MethodRequiresDataFlowAnalysis (MethodProxy method);
/// Helper utility to track feature switch macros in header file
/// This type is used in a dictionary as a key
/// </summary>
- readonly struct FeatureSwitchMembers
+ readonly struct FeatureSwitchMembers : IEquatable<FeatureSwitchMembers>
{
public string Feature { get; }
public string FeatureValue { get; }
}
public override bool Equals (object obj)
- {
- FeatureSwitchMembers other = (FeatureSwitchMembers) obj;
- return other._key.Equals (_key);
- }
+ => obj is FeatureSwitchMembers inst && Equals (inst);
+
+ public bool Equals (FeatureSwitchMembers fsm)
+ => fsm._key == _key;
}
readonly Dictionary<string, string> namespaceDictionary = new Dictionary<string, string> ();
void OutputXml (string iLLinkTrimXmlFilePath, string outputFileName)
{
XmlDocument doc = new XmlDocument ();
- doc.Load (iLLinkTrimXmlFilePath);
+ using (var sr = new StreamReader (iLLinkTrimXmlFilePath)) {
+ XmlReader reader = XmlReader.Create (sr, new XmlReaderSettings () { XmlResolver = null });
+ doc.Load (reader);
+ }
+
XmlElement linkerNode = doc["linker"];
if (featureSwitchMembers.Count > 0) {
private string DotNetPath {
get {
- if (!String.IsNullOrEmpty (_dotnetPath))
+ if (!string.IsNullOrEmpty (_dotnetPath))
return _dotnetPath;
_dotnetPath = Environment.GetEnvironmentVariable (DotNetHostPathEnvironmentName);
- if (String.IsNullOrEmpty (_dotnetPath))
+ if (string.IsNullOrEmpty (_dotnetPath))
throw new InvalidOperationException ($"{DotNetHostPathEnvironmentName} is not set");
return _dotnetPath;
public string ILLinkPath {
get {
- if (!String.IsNullOrEmpty (_illinkPath))
+ if (!string.IsNullOrEmpty (_illinkPath))
return _illinkPath;
#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file
// Add per-assembly optimization arguments
foreach (var optimization in _optimizationNames) {
string optimizationValue = assembly.GetMetadata (optimization);
- if (String.IsNullOrEmpty (optimizationValue))
+ if (string.IsNullOrEmpty (optimizationValue))
continue;
- if (!Boolean.TryParse (optimizationValue, out bool enabled))
+ if (!bool.TryParse (optimizationValue, out bool enabled))
throw new ArgumentException ($"optimization metadata {optimization} must be True or False");
SetOpt (args, optimization, assemblyName, enabled);
// Add per-assembly verbosity arguments
string singleWarn = assembly.GetMetadata ("TrimmerSingleWarn");
- if (!String.IsNullOrEmpty (singleWarn)) {
- if (!Boolean.TryParse (singleWarn, out bool value))
+ if (!string.IsNullOrEmpty (singleWarn)) {
+ if (!bool.TryParse (singleWarn, out bool value))
throw new ArgumentException ($"TrimmerSingleWarn metadata must be True or False");
if (value)
foreach (var customData in CustomData) {
var key = customData.ItemSpec;
var value = customData.GetMetadata ("Value");
- if (String.IsNullOrEmpty (value))
+ if (string.IsNullOrEmpty (value))
throw new ArgumentException ("custom data requires \"Value\" metadata");
args.Append ("--custom-data ").Append (' ').Append (key).Append ('=').AppendLine (Quote (value));
}
foreach (var featureSetting in FeatureSettings) {
var feature = featureSetting.ItemSpec;
var featureValue = featureSetting.GetMetadata ("Value");
- if (String.IsNullOrEmpty (featureValue))
+ if (string.IsNullOrEmpty (featureValue))
throw new ArgumentException ("feature settings require \"Value\" metadata");
args.Append ("--feature ").Append (feature).Append (' ').AppendLine (featureValue);
}
// handle optional before/aftersteps
var beforeStep = customStep.GetMetadata ("BeforeStep");
var afterStep = customStep.GetMetadata ("AfterStep");
- if (!String.IsNullOrEmpty (beforeStep) && !String.IsNullOrEmpty (afterStep))
+ if (!string.IsNullOrEmpty (beforeStep) && !string.IsNullOrEmpty (afterStep))
throw new ArgumentException ("custom step may not have both \"BeforeStep\" and \"AfterStep\" metadata");
- if (!String.IsNullOrEmpty (beforeStep))
+ if (!string.IsNullOrEmpty (beforeStep))
customStepString = $"-{beforeStep}:{customStepString}";
- if (!String.IsNullOrEmpty (afterStep))
+ if (!string.IsNullOrEmpty (afterStep))
customStepString = $"+{afterStep}:{customStepString}";
args.AppendLine (Quote (customStepString));
}
}
}
-}
\ No newline at end of file
+}
namespace ILLink.Shared.TrimAnalysis
{
- partial record ArrayValue
+ internal partial record ArrayValue
{
public static MultiValue Create (MultiValue size, TypeReference elementType)
{
bool first = true;
foreach (var element in IndexValues) {
if (!first) {
- result.Append (",");
+ result.Append (',');
first = false;
}
- result.Append ("(");
+ result.Append ('(');
result.Append (element.Key);
result.Append (",(");
bool firstValue = true;
foreach (var v in element.Value.Value) {
if (firstValue) {
- result.Append (",");
+ result.Append (',');
firstValue = false;
}
return result.ToString ();
}
}
-}
\ No newline at end of file
+}
namespace ILLink.Shared.TrimAnalysis
{
- public readonly partial struct DiagnosticContext
+ internal readonly partial struct DiagnosticContext
{
public readonly MessageOrigin Origin;
public readonly bool DiagnosticsEnabled;
}
// For the purposes of the DynamicallyAccessedMembers type hierarchies
- // we consider interfaces of marked types to be also "marked" in that
+ // we consider interfaces of marked types to be also "marked" in that
// their annotations will be applied to the type regardless if later on
// we decide to remove the interface. This is to keep the complexity of the implementation
// relatively low. In the future it could be possibly optimized.
/// <summary>
/// A representation of a field. Typically a result of ldfld.
/// </summary>
- sealed partial record FieldValue : IValueWithStaticType
+ internal sealed partial record FieldValue : IValueWithStaticType
{
public FieldValue (TypeDefinition? staticType, FieldDefinition fieldToLoad, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
{
public override string ToString () => this.ValueToString (Field, DynamicallyAccessedMemberTypes);
}
-}
\ No newline at end of file
+
+}
namespace ILLink.Shared.TrimAnalysis
{
- sealed partial class FlowAnnotations
+ internal sealed partial class FlowAnnotations
{
readonly LinkContext _context;
readonly Dictionary<TypeDefinition, TypeAnnotations> _annotations = new Dictionary<TypeDefinition, TypeAnnotations> ();
// class, interface, struct can have annotations
DynamicallyAccessedMemberTypes typeAnnotation = GetMemberTypesForDynamicallyAccessedMembersAttribute (type);
- var annotatedFields = new ArrayBuilder<FieldAnnotation> ();
+ ArrayBuilder<FieldAnnotation> annotatedFields = default;
// First go over all fields with an explicit annotation
if (type.HasFields) {
requireDynamicallyAccessedMembersAction.Invoke (value, targetValue);
}
}
-}
\ No newline at end of file
+}
/// This is a System.Type value which represents generic parameter (basically result of typeof(T))
/// Its actual type is unknown, but it can have annotations.
/// </summary>
- partial record GenericParameterValue
+ internal partial record GenericParameterValue
{
public GenericParameterValue (GenericParameter genericParameter, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
{
public override string ToString () => this.ValueToString (GenericParameter, DynamicallyAccessedMemberTypes);
}
-}
\ No newline at end of file
+}
namespace ILLink.Shared.TrimAnalysis
{
- partial struct HandleCallAction
+ internal partial struct HandleCallAction
{
#pragma warning disable CA1822 // Mark members as static - the other partial implementations might need to be instance methods
public static bool operator == (HoistedLocalKey left, HoistedLocalKey right) => left.Equals (right);
public static bool operator != (HoistedLocalKey left, HoistedLocalKey right) => !(left == right);
}
-}
\ No newline at end of file
+}
HoistedLocalsLattice.Meet (left.HoistedLocals, right.HoistedLocals),
this);
}
-}
\ No newline at end of file
+}
}
}
- abstract partial class MethodBodyScanner
+ internal abstract partial class MethodBodyScanner
{
protected readonly LinkContext _context;
protected readonly InterproceduralStateLattice InterproceduralStateLattice;
this.InterproceduralStateLattice = new InterproceduralStateLattice (default, default, context);
}
- internal MultiValue ReturnValue { private set; get; }
+ internal MultiValue ReturnValue { get; private set; }
protected virtual void WarnAboutInvalidILInMethod (MethodBody method, int ilOffset)
{
// Disabled asserts due to a bug
// Debug.Assert (interproceduralState.Count == 1 + calleeMethods.Count ());
// foreach (var method in calleeMethods)
- // Debug.Assert (interproceduralState.Any (kvp => kvp.Key.Method == method));
+ // Debug.Assert (interproceduralState.Any (kvp => kvp.Key.Method == method));
} else {
Debug.Assert (interproceduralState.MethodBodies.Count () == 1);
}
BasicBlockIterator blockIterator = new BasicBlockIterator (methodIL);
- ReturnValue = new ();
+ ReturnValue = default;
foreach (Instruction operation in methodIL.Instructions) {
int curBasicBlock = blockIterator.MoveNext (operation);
if (hasReturnValue) {
StackSlot retValue = PopUnknown (currentStack, 1, methodBody, operation.Offset);
// If the return value is a reference, treat it as the value itself for now
- // We can handle ref return values better later
+ // We can handle ref return values better later
ReturnValue = MultiValueLattice.Meet (ReturnValue, DereferenceValue (retValue.Value, locals, ref interproceduralState));
ValidateNoReferenceToReference (locals, methodBody.Method, operation.Offset);
}
bool isByRef = code == Code.Ldarga || code == Code.Ldarga_S;
isByRef |= paramType.IsByRefOrPointer ();
- isByRef |= param.IsImplicitThis == true && paramType.IsValueType;
+ isByRef |= param.IsImplicitThis && paramType.IsValueType;
StackSlot slot = new StackSlot (
isByRef
/// <summary>
/// A value that came from a method parameter - such as the result of a ldarg.
/// </summary>
- partial record MethodParameterValue : IValueWithStaticType
+ internal partial record MethodParameterValue : IValueWithStaticType
{
public MethodParameterValue (TypeDefinition? staticType, ParameterProxy param, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes, bool overrideIsThis = false)
{
public TypeDefinition? StaticType { get; }
}
-}
\ No newline at end of file
+}
namespace ILLink.Shared.TypeSystemProxy
{
- readonly partial struct MethodProxy : IEquatable<MethodProxy>
+ internal readonly partial struct MethodProxy : IEquatable<MethodProxy>
{
public MethodProxy (MethodDefinition method) => Method = method;
/// <summary>
/// Return value from a method
/// </summary>
- partial record MethodReturnValue : IValueWithStaticType
+ internal partial record MethodReturnValue : IValueWithStaticType
{
public MethodReturnValue (TypeDefinition? staticType, MethodDefinition method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
{
public override string ToString () => this.ValueToString (Method, DynamicallyAccessedMemberTypes);
}
-}
\ No newline at end of file
+}
_markStep.MarkStaticConstructorVisibleToReflection (type, new DependencyInfo (DependencyKind.AccessedViaReflection, origin.Provider), origin);
}
}
-}
\ No newline at end of file
+}
public override bool HandleCall (MethodBody callingMethodBody, MethodReference calledMethod, Instruction operation, ValueNodeList methodParams, out MultiValue methodReturnValue)
{
- methodReturnValue = new ();
-
var reflectionProcessed = _markStep.ProcessReflectionDependency (callingMethodBody, operation);
- if (reflectionProcessed)
+ if (reflectionProcessed) {
+ methodReturnValue = default;
return false;
+ }
Debug.Assert (callingMethodBody.Method == _origin.Provider);
var calledMethodDefinition = _context.TryResolve (calledMethod);
- if (calledMethodDefinition == null)
+ if (calledMethodDefinition == null) {
+ methodReturnValue = default;
return false;
+ }
_origin = _origin.WithInstructionOffset (operation.Offset);
namespace ILLink.Shared.TrimAnalysis
{
- partial struct RequireDynamicallyAccessedMembersAction
+ internal partial struct RequireDynamicallyAccessedMembersAction
{
readonly ReflectionMarker _reflectionMarker;
foreach (Instruction operation in methodIL.Instructions) {
if (!operation.OpCode.IsControlFlowInstruction ())
continue;
- Object value = operation.Operand;
+ object value = operation.Operand;
if (value is Instruction inst) {
branchTargets.Add (inst.Offset);
} else if (value is Instruction[] instructions) {
}
}
}
-}
\ No newline at end of file
+}
out MultiValue _);
}
}
-}
\ No newline at end of file
+}
pattern.MarkAndProduceDiagnostics (reflectionMarker, markStep, _context);
}
}
-}
\ No newline at end of file
+}
public override int GetHashCode ()
{
- HashCode hashCode = new HashCode ();
+ HashCode hashCode = default;
foreach (var item in this)
hashCode.Add (item.GetHashCode ());
return hashCode.ToHashCode ();
continue;
string name = GetAttribute (resourceNav, "name");
- if (String.IsNullOrEmpty (name)) {
+ if (string.IsNullOrEmpty (name)) {
LogWarning (resourceNav, DiagnosticId.XmlMissingNameAttributeInResource);
continue;
}
public override bool IsActiveFor (AssemblyDefinition assembly)
{
- // Only process assemblies which went through marking.
+ // Only process assemblies which went through marking.
// The code relies on MarkStep to identify the useful suppressions.
// Assemblies which didn't go through marking would not produce any warnings and thus would report all suppressions as redundant.
var assemblyAction = Annotations.GetAction (assembly);
{
StringBuilder sb = new StringBuilder ();
sb.Append (meth.ReturnType.FullName);
- sb.Append (" ");
+ sb.Append (' ');
sb.Append (meth.Name);
if (includeGenericParameters && meth.HasGenericParameters) {
- sb.Append ("`");
+ sb.Append ('`');
sb.Append (meth.GenericParameters.Count);
}
- sb.Append ("(");
+ sb.Append ('(');
if (meth.HasMetadataParameters ()) {
int i = 0;
foreach (var p in meth.GetMetadataParameters ()) {
if (i++ > 0)
- sb.Append (",");
+ sb.Append (',');
sb.Append (p.ParameterType.FullName);
}
}
- sb.Append (")");
+ sb.Append (')');
return sb.ToString ();
}
if (accessors.Length > 0) {
for (int i = 0; i < accessors.Length; ++i)
- accessors[i] = accessors[i].ToLower ();
+ accessors[i] = accessors[i].ToLowerInvariant ();
return accessors;
}
(CustomAttribute[]? customAttributes, MessageOrigin[]? origins) ProcessAttributes (XPathNavigator nav, ICustomAttributeProvider provider)
{
- var customAttributesBuilder = new ArrayBuilder<CustomAttribute> ();
- var originsBuilder = new ArrayBuilder<MessageOrigin> ();
+ ArrayBuilder<CustomAttribute> customAttributesBuilder = default;
+ ArrayBuilder<MessageOrigin> originsBuilder = default;
foreach (XPathNavigator attributeNav in nav.SelectChildren ("attribute", string.Empty)) {
if (!ShouldProcessElement (attributeNav))
continue;
//
// public sealed class RemoveAttributeInstancesAttribute : Attribute
// {
- // public RemoveAttributeInstancesAttribute () {}
- // public RemoveAttributeInstancesAttribute (object values) {} // For legacy uses
- // public RemoveAttributeInstancesAttribute (params object[] values) {}
+ // public RemoveAttributeInstancesAttribute () {}
+ // public RemoveAttributeInstancesAttribute (object values) {} // For legacy uses
+ // public RemoveAttributeInstancesAttribute (params object[] values) {}
// }
//
const MethodAttributes ctorAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.Final;
CustomAttributeArgument[] ReadCustomAttributeArguments (XPathNavigator nav, TypeDefinition attributeType)
{
- var args = new ArrayBuilder<CustomAttributeArgument> ();
+ ArrayBuilder<CustomAttributeArgument> args = default;
foreach (XPathNavigator argumentNav in nav.SelectChildren ("argument", string.Empty)) {
CustomAttributeArgument? caa = ReadCustomAttributeArgument (argumentNav, attributeType);
if (typeref is ArrayType arrayTypeRef) {
var elementType = arrayTypeRef.ElementType;
var arrayArgumentIterator = nav.SelectChildren ("argument", string.Empty);
- ArrayBuilder<CustomAttributeArgument> elements = new ArrayBuilder<CustomAttributeArgument> ();
+ ArrayBuilder<CustomAttributeArgument> elements = default;
foreach (XPathNavigator elementNav in arrayArgumentIterator) {
if (ReadCustomAttributeArgument (elementNav, memberWithAttribute) is CustomAttributeArgument arg) {
// To match Cecil, elements of a list that are subclasses of the list type must be boxed in the base type
- // e.g. object[] { 73 } translates to Cecil.CAA { Type: object[] : Value: CAA{ Type: object, Value: CAA{ Type: int, Value: 73} } }
+ // e.g. object[] { 73 } translates to Cecil.CAA { Type: object[] : Value: CAA{ Type: object, Value: CAA{ Type: int, Value: 73} } }
if (arg.Type == elementType) {
elements.Add (arg);
}
}
sb.Append (method.Name);
if (method.HasGenericParameters) {
- sb.Append ("<");
+ sb.Append ('<');
for (int i = 0; i < method.GenericParameters.Count; i++) {
if (i > 0)
- sb.Append (",");
+ sb.Append (',');
sb.Append (method.GenericParameters[i].Name);
}
- sb.Append (">");
+ sb.Append ('>');
}
- sb.Append ("(");
+ sb.Append ('(');
if (method.HasMetadataParameters ()) {
for (int i = 0; i < method.Parameters.Count; i++) {
if (i > 0)
- sb.Append (",");
+ sb.Append (',');
sb.Append (method.Parameters[i].ParameterType.FullName);
}
}
- sb.Append (")");
+ sb.Append (')');
return sb.ToString ();
}
#pragma warning restore RS0030
context.Annotations.SetMembersPreserve (type, members);
}
}
-}
\ No newline at end of file
+}
if (property.Name == "TargetTypeName") {
string targetTypeName = (string) property.Argument.Value;
- TypeName typeName = TypeParser.ParseTypeName (targetTypeName);
+ TypeName? typeName = TypeParser.ParseTypeName (targetTypeName);
if (typeName is AssemblyQualifiedTypeName assemblyQualifiedTypeName) {
AssemblyDefinition? assembly = Context.TryResolve (assemblyQualifiedTypeName.AssemblyName.Name);
return assembly == null ? null : Context.TryResolve (assembly, targetTypeName);
public virtual void Initialize (LinkContext context, MarkContext markContext)
{
InitializeSubSteps (context);
- markContext.RegisterMarkAssemblyAction (assembly => BrowseAssembly (assembly));
+ markContext.RegisterMarkAssemblyAction (BrowseAssembly);
}
static bool HasSubSteps (List<ISubStep> substeps) => substeps?.Count > 0;
public class OutputStep : BaseStep
{
- private Dictionary<UInt16, TargetArchitecture>? architectureMap;
+ private Dictionary<ushort, TargetArchitecture>? architectureMap;
private enum NativeOSOverride
{
TargetArchitecture CalculateArchitecture (TargetArchitecture readyToRunArch)
{
if (architectureMap == null) {
- architectureMap = new Dictionary<UInt16, TargetArchitecture> ();
+ architectureMap = new Dictionary<ushort, TargetArchitecture> ();
foreach (var os in Enum.GetValues (typeof (NativeOSOverride))) {
ushort osVal = (ushort) (NativeOSOverride) os;
foreach (var arch in Enum.GetValues (typeof (TargetArchitecture))) {
{
if (Context.AssemblyListFile != null) {
using (var w = File.CreateText (Context.AssemblyListFile)) {
- w.WriteLine ("[" + String.Join (", ", assembliesWritten.Select (a => "\"" + a + "\"").ToArray ()) + "]");
+ w.WriteLine ("[" + string.Join (", ", assembliesWritten.Select (a => "\"" + a + "\"").ToArray ()) + "]");
}
}
}
Directory.CreateDirectory (Context.OutputDirectory);
}
}
-}
\ No newline at end of file
+}
protected virtual void ProcessField (TypeDefinition type, XPathNavigator nav)
{
string signature = GetSignature (nav);
- if (!String.IsNullOrEmpty (signature)) {
+ if (!string.IsNullOrEmpty (signature)) {
FieldDefinition? field = GetField (type, signature);
if (field == null) {
LogWarning (nav, DiagnosticId.XmlCouldNotFindFieldOnType, signature, type.GetDisplayName ());
}
string name = GetName (nav);
- if (!String.IsNullOrEmpty (name)) {
+ if (!string.IsNullOrEmpty (name)) {
bool foundMatch = false;
if (type.HasFields) {
foreach (FieldDefinition field in type.Fields) {
protected virtual void ProcessMethod (TypeDefinition type, XPathNavigator nav, object? customData)
{
string signature = GetSignature (nav);
- if (!String.IsNullOrEmpty (signature)) {
+ if (!string.IsNullOrEmpty (signature)) {
MethodDefinition? method = GetMethod (type, signature);
if (method == null) {
LogWarning (nav, DiagnosticId.XmlCouldNotFindMethodOnType, signature, type.GetDisplayName ());
}
string name = GetAttribute (nav, NameAttributeName);
- if (!String.IsNullOrEmpty (name)) {
+ if (!string.IsNullOrEmpty (name)) {
bool foundMatch = false;
if (type.HasMethods) {
foreach (MethodDefinition method in type.Methods) {
protected virtual void ProcessEvent (TypeDefinition type, XPathNavigator nav, object? customData)
{
string signature = GetSignature (nav);
- if (!String.IsNullOrEmpty (signature)) {
+ if (!string.IsNullOrEmpty (signature)) {
EventDefinition? @event = GetEvent (type, signature);
if (@event == null) {
LogWarning (nav, DiagnosticId.XmlCouldNotFindEventOnType, signature, type.GetDisplayName ());
}
string name = GetAttribute (nav, NameAttributeName);
- if (!String.IsNullOrEmpty (name)) {
+ if (!string.IsNullOrEmpty (name)) {
bool foundMatch = false;
foreach (EventDefinition @event in type.Events) {
if (@event.Name == name) {
protected virtual void ProcessProperty (TypeDefinition type, XPathNavigator nav, object? customData)
{
string signature = GetSignature (nav);
- if (!String.IsNullOrEmpty (signature)) {
+ if (!string.IsNullOrEmpty (signature)) {
PropertyDefinition? property = GetProperty (type, signature);
if (property == null) {
LogWarning (nav, DiagnosticId.XmlCouldNotFindPropertyOnType, signature, type.GetDisplayName ());
}
string name = GetAttribute (nav, NameAttributeName);
- if (!String.IsNullOrEmpty (name)) {
+ if (!string.IsNullOrEmpty (name)) {
bool foundMatch = false;
foreach (PropertyDefinition property in type.Properties) {
if (property.Name == name) {
{
protected override void Process ()
{
- // Flush all cached messages before the sweep and clean steps are run to be confident
+ // Flush all cached messages before the sweep and clean steps are run to be confident
// that we have all the information needed to gracefully generate the string.
Context.FlushCachedWarnings ();
}
Annotations.Mark (ca, new DependencyInfo (DependencyKind.DisablePrivateReflection, ca));
}
}
-}
\ No newline at end of file
+}
return false;
}
}
-}
\ No newline at end of file
+}
// rewrite the copy to save to update the scopes not to point
// forwarding assembly (facade).
//
- // foo.dll -> facade.dll -> lib.dll
- // copy | copy (delete) | link
+ // foo.dll -> facade.dll -> lib.dll
+ // copy | copy (delete) | link
//
Annotations.SetAction (assembly, AssemblyAction.Save);
continue;
// We can't rely on the context resolution cache anymore, since it may remember methods which are already removed
// So call the direct Resolve here and avoid the cache.
// We want to remove a method from the list of Overrides if:
- // Resolve() is null
- // This can happen for a couple of reasons, but it indicates the method isn't in the final assembly.
- // Resolve also may return a removed value if method.Overrides[i] is a MethodDefinition. In this case, Resolve short circuits and returns `this`.
- // OR
- // ov.DeclaringType is null
- // ov.DeclaringType may be null if Resolve short circuited and returned a removed method. In this case, we want to remove the override.
- // OR
- // ov is in a `link` scope and is unmarked
- // ShouldRemove returns true if the method is unmarked, but we also We need to make sure the override is in a link scope.
- // Only things in a link scope are marked, so ShouldRemove is only valid for items in a `link` scope.
+ // Resolve() is null
+ // This can happen for a couple of reasons, but it indicates the method isn't in the final assembly.
+ // Resolve also may return a removed value if method.Overrides[i] is a MethodDefinition. In this case, Resolve short circuits and returns `this`.
+ // OR
+ // ov.DeclaringType is null
+ // ov.DeclaringType may be null if Resolve short circuited and returned a removed method. In this case, we want to remove the override.
+ // OR
+ // ov is in a `link` scope and is unmarked
+ // ShouldRemove returns true if the method is unmarked, but we also We need to make sure the override is in a link scope.
+ // Only things in a link scope are marked, so ShouldRemove is only valid for items in a `link` scope.
#pragma warning disable RS0030 // Cecil's Resolve is banned - it's necessary when the metadata graph isn't stable
if (method.Overrides[i].Resolve () is not MethodDefinition ov || ov.DeclaringType is null || (IsLinkScope (ov.DeclaringType.Scope) && ShouldRemove (ov)))
method.Overrides.RemoveAt (i);
namespace Mono.Linker
{
-
public enum AssemblyAction
{
// Ignore the assembly
Link,
// Remove the assembly from the output
Delete,
- // Save the assembly/symbols in memory without trimming it.
- // E.g. useful to remove unneeded assembly references (as done in SweepStep),
+ // Save the assembly/symbols in memory without trimming it.
+ // E.g. useful to remove unneeded assembly references (as done in SweepStep),
// resolving [TypeForwardedTo] attributes (like PCL) to their final location
Save,
// Keep all types, methods, and fields but add System.Runtime.BypassNGenAttribute to unmarked methods.
public static readonly DependencyInfo AlreadyMarked = new DependencyInfo (DependencyKind.AlreadyMarked, null);
public static readonly DependencyInfo DisablePrivateReflectionRequirement = new DependencyInfo (DependencyKind.DisablePrivateReflectionRequirement, null);
public bool Equals (DependencyInfo other) => (Kind, Source) == (other.Kind, other.Source);
- public override bool Equals (Object? obj) => obj is DependencyInfo info && this.Equals (info);
+ public override bool Equals (object? obj) => obj is DependencyInfo info && this.Equals (info);
public override int GetHashCode () => (Kind, Source).GetHashCode ();
public static bool operator == (DependencyInfo lhs, DependencyInfo rhs) => lhs.Equals (rhs);
public static bool operator != (DependencyInfo lhs, DependencyInfo rhs) => !lhs.Equals (rhs);
}
}
- private int _nodeIndex = 0;
+ private int _nodeIndex;
void AddNode (string node)
{
// If the containing type is nested within other types.
// e.g. A<T>.B<U>.M<V>(T t, U u, V v) should be M(`0, `1, ``0).
- // Roslyn needs to add generic arities of parents, but the innermost type redeclares
+ // Roslyn needs to add generic arities of parents, but the innermost type redeclares
// all generic parameters so we don't need to add them.
builder.Append ('`');
}
builder.Append ('.');
}
- if (!String.IsNullOrEmpty (typeReference.Namespace))
+ if (!string.IsNullOrEmpty (typeReference.Namespace))
builder.Append (typeReference.Namespace).Append ('.');
// This includes '`n' for mangled generic types
(name, arity) = ParseTypeOrNamespaceName (id, ref index, nameBuilder);
// if we are at the end of the dotted name and still haven't resolved it to
// a type, there are no results.
- if (String.IsNullOrEmpty (name))
+ if (string.IsNullOrEmpty (name))
return;
// no more dots, so don't loop any more
var typeOrNamespaceName = nameBuilder.ToString ();
GetMatchingTypes (module, declaringType: containingType, name: typeOrNamespaceName, arity: arity, results: results, resolver);
Debug.Assert (results.Count <= 1);
- if (results.Any ()) {
+ if (results.Count > 0) {
// the name resolved to a type
var result = results.Single ();
Debug.Assert (result is TypeDefinition);
// loop for dotted names
while (true) {
var name = ParseName (id, ref index);
- if (String.IsNullOrEmpty (name))
+ if (string.IsNullOrEmpty (name))
return;
nameBuilder.Append (name);
return;
foreach (var nestedType in declaringType.NestedTypes) {
- Debug.Assert (String.IsNullOrEmpty (nestedType.Namespace));
+ Debug.Assert (string.IsNullOrEmpty (nestedType.Namespace));
if (nestedType.Name != name)
continue;
numBackslash /= 2;
}
if (numBackslash > 0)
- argBuilder.Append (new String ('\\', numBackslash));
+ argBuilder.Append (new string ('\\', numBackslash));
if (cur < 0 || (!inquote && char.IsWhiteSpace ((char) cur)))
break;
if (copyChar)
private static IEnumerable<int> ProcessWarningCodes (string value)
{
- string Unquote (string arg)
+ static string Unquote (string arg)
{
if (arg.Length > 1 && arg[0] == '"' && arg[arg.Length - 1] == '"')
return arg.Substring (1, arg.Length - 2);
// Don't honor the Condition until we have figured out the behavior for DynamicDependencyAttribute:
// https://github.com/dotnet/linker/issues/1231
// if (!ShouldProcess (context, customAttribute))
- // return null;
+ // return null;
var dynamicDependency = GetDynamicDependency (customAttribute);
if (dynamicDependency != null)
return true;
}
}
-}
\ No newline at end of file
+}
public static string GetAttribute (XPathNavigator nav, string attribute)
{
- return nav.GetAttribute (attribute, String.Empty);
+ return nav.GetAttribute (attribute, string.Empty);
}
}
}
public void SetFeatureValue (string feature, bool value)
{
- Debug.Assert (!String.IsNullOrEmpty (feature));
+ Debug.Assert (!string.IsNullOrEmpty (feature));
FeatureSettings[feature] = value;
}
string origin = Origin?.ToString () ?? originApp;
StringBuilder sb = new StringBuilder ();
- sb.Append (origin).Append (":");
+ sb.Append (origin).Append (':');
if (!string.IsNullOrEmpty (SubCategory))
- sb.Append (" ").Append (SubCategory);
+ sb.Append (' ').Append (SubCategory);
string cat;
switch (Category) {
}
if (!string.IsNullOrEmpty (cat)) {
- sb.Append (" ")
+ sb.Append (' ')
.Append (cat)
.Append (" IL")
// Warning and error messages always have a code.
.Append (Code!.Value.ToString ("D4"))
.Append (": ");
} else {
- sb.Append (" ");
+ sb.Append (' ');
}
if (Origin?.Provider != null) {
StringBuilder sb = new StringBuilder (fileName);
if (sourceLine != 0) {
- sb.Append ("(").Append (sourceLine);
+ sb.Append ('(').Append (sourceLine);
if (sourceColumn != 0)
- sb.Append (",").Append (sourceColumn);
+ sb.Append (',').Append (sourceColumn);
- sb.Append (")");
+ sb.Append (')');
}
return sb.ToString ();
}
// Append parameters
- sb.Append ("(");
+ sb.Append ('(');
if (method.HasMetadataParameters ()) {
#pragma warning disable RS0030 // MethodReference.Parameters is banned -- it's best to leave this as is for now
for (int i = 0; i < method.Parameters.Count - 1; i++)
#pragma warning restore RS0030 // Do not used banned APIs
}
- sb.Append (")");
+ sb.Append (')');
// Insert generic parameters
if (method.HasGenericParameters) {
return string.Compare (this.EntryPoint, other.EntryPoint, StringComparison.Ordinal);
}
}
-}
\ No newline at end of file
+}
namespace Mono.Linker
{
/// <summary>
- /// This attribute name will be the name hardcoded in linker which will remove all
+ /// This attribute name will be the name hardcoded in linker which will remove all
/// attribute usages but not the attribute definition
/// </summary>
[AttributeUsage (
return (td.Attributes & TypeAttributes.Serializable) != 0;
}
}
-}
\ No newline at end of file
+}
if (string.IsNullOrEmpty (typeNameString))
return false;
- TypeName parsedTypeName;
+ TypeName? parsedTypeName;
try {
parsedTypeName = TypeParser.ParseTypeName (typeNameString);
} catch (ArgumentException) {
typeResolutionRecords = null;
return false;
- bool TryResolveTypeName (AssemblyDefinition assemblyDefinition, TypeName typeName, [NotNullWhen (true)] out TypeReference? typeReference, List<TypeResolutionRecord> typeResolutionRecords)
+ bool TryResolveTypeName (AssemblyDefinition assemblyDefinition, TypeName? typeName, [NotNullWhen (true)] out TypeReference? typeReference, List<TypeResolutionRecord> typeResolutionRecords)
{
typeReference = null;
if (assemblyDefinition == null)
return typeReference != null;
}
- TypeReference? ResolveTypeName (AssemblyDefinition assembly, TypeName typeName, List<TypeResolutionRecord> typeResolutionRecords)
+ TypeReference? ResolveTypeName (AssemblyDefinition assembly, TypeName? typeName, List<TypeResolutionRecord> typeResolutionRecords)
{
if (typeName is AssemblyQualifiedTypeName assemblyQualifiedTypeName) {
// In this case we ignore the assembly parameter since the type name has assembly in it
return resolvedType;
}
}
-}
\ No newline at end of file
+}
protected abstract void ProcessExportedType (ExportedType exportedType);
}
-}
\ No newline at end of file
+}
public class Suppression
{
public SuppressMessageInfo SuppressMessageInfo { get; }
- public bool Used { get; set; } = false;
+ public bool Used { get; set; }
public CustomAttribute OriginAttribute { get; }
public ICustomAttributeProvider Provider { get; }
if (!TryDecodeSuppressMessageAttributeData (instance, out info))
continue;
- var scope = info.Scope?.ToLower ();
+ var scope = info.Scope?.ToLowerInvariant ();
if (info.Target == null && (scope == "module" || scope == null)) {
yield return new Suppression (info, originAttribute: instance, provider);
continue;
ILLink5 = 5,
Latest = 9999,
}
-}
\ No newline at end of file
+}
public override void PrintResults (int maxCount)
{
var static_entries = fields.Where (l => l.Value == Access.Write && l.Key.IsStatic).
- OrderBy (l => l.Key, new FieldTypeSizeComparer ()).
+ OrderBy (l => l.Key, default (FieldTypeSizeComparer)).
ThenBy (l => l.Key.DeclaringType.FullName).
Take (maxCount);
if (static_entries.Any ()) {
}
var instance_entries = fields.Where (l => l.Value == Access.Write && !l.Key.IsStatic).
- OrderBy (l => l.Key, new FieldTypeSizeComparer ()).
+ OrderBy (l => l.Key, default (FieldTypeSizeComparer)).
ThenBy (l => l.Key.DeclaringType.FullName).
Take (maxCount);
if (instance_entries.Any ()) {
PrintHeader ("User operators used for null checks");
foreach (var e in entries) {
- Console.WriteLine ($"User operator '{e.Key.ToDisplay ()}' was called {e.Value.Redundant} [{e.Value.Ratio.ToString ("0%")}] times with null values");
+ Console.WriteLine ($"User operator '{e.Key.ToDisplay ()}' was called {e.Value.Redundant} [{e.Value.Ratio:0%}] times with null values");
}
}
}
if (showSize) {
str.Append (" [size: ");
str.Append (method.GetEstimatedSize ());
- str.Append ("]");
+ str.Append (']');
}
return str.ToString ();