Skip to content

Commit

Permalink
[dotnet-linker] Enable nullability in numerous files. (#18184)
Browse files Browse the repository at this point in the history
This required some minor refactorings to simplify the changes, but no
behavior should change.
  • Loading branch information
rolfbjarne authored May 4, 2023
1 parent 101f800 commit 791b98c
Show file tree
Hide file tree
Showing 34 changed files with 224 additions and 134 deletions.
8 changes: 8 additions & 0 deletions tools/common/DerivedLinkContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ public class DerivedLinkContext : LinkContext {
// so we need a second dictionary
Dictionary<TypeDefinition, LinkedAwayTypeReference> LinkedAwayTypeMap = new Dictionary<TypeDefinition, LinkedAwayTypeReference> ();

#if NET
public DerivedLinkContext (Xamarin.Linker.LinkerConfiguration configuration, Target target)
: base (configuration)
{
this.Target = target;
}
#endif

public Application App {
get {
return Target.App;
Expand Down
12 changes: 7 additions & 5 deletions tools/dotnet-linker/ApplyPreserveAttributeBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

using Mono.Cecil;

#nullable enable

namespace Mono.Tuner {

public abstract class ApplyPreserveAttributeBase : BaseSubStep {
Expand Down Expand Up @@ -72,16 +74,16 @@ void MarkMethodIfPreserved (MethodDefinition method)
MarkMethod (method, attribute);
}

void MarkMethod (MethodDefinition method, CustomAttribute preserve_attribute)
void MarkMethod (MethodDefinition? method, CustomAttribute? preserve_attribute)
{
if (method == null)
if (method is null)
return;

Mark (method, preserve_attribute);
Annotations.SetAction (method, MethodAction.Parse);
}

void Mark (IMetadataTokenProvider provider, CustomAttribute preserve_attribute)
void Mark (IMetadataTokenProvider provider, CustomAttribute? preserve_attribute)
{
if (IsConditionalAttribute (preserve_attribute)) {
PreserveConditional (provider);
Expand All @@ -103,9 +105,9 @@ void PreserveConditional (IMetadataTokenProvider provider)
Annotations.AddPreservedMethod (method.DeclaringType, method);
}

static bool IsConditionalAttribute (CustomAttribute attribute)
static bool IsConditionalAttribute (CustomAttribute? attribute)
{
if (attribute == null)
if (attribute is null)
return false;

foreach (var named_argument in attribute.Fields)
Expand Down
2 changes: 2 additions & 0 deletions tools/dotnet-linker/BackingFieldDelayHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
using Mono.Linker.Steps;
using Xamarin.Tuner;

#nullable enable

namespace Xamarin.Linker {

// Problems:
Expand Down
16 changes: 12 additions & 4 deletions tools/dotnet-linker/Compat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@
using Xamarin.Linker;
using Xamarin.Utils;

#nullable enable

namespace Xamarin.Bundler {
public partial class Application {
public LinkerConfiguration Configuration { get; private set; }
public string RuntimeConfigurationFile { get; set; }
LinkerConfiguration? configuration;
public LinkerConfiguration Configuration { get => configuration!; }
public string? RuntimeConfigurationFile { get; set; }

public Application (LinkerConfiguration configuration)
{
this.Configuration = configuration;
this.configuration = configuration;
}

public string ProductName {
Expand Down Expand Up @@ -103,7 +106,7 @@ public static string GetArch64Directory (Application app)
throw new NotImplementedException ();
}

public static string SdkRoot {
public static string? SdkRoot {
get => sdk_root;
set => sdk_root = value;
}
Expand All @@ -114,6 +117,11 @@ public static string SdkRoot {
public class DotNetLinkContext {
public LinkerConfiguration LinkerConfiguration;

public DotNetLinkContext (LinkerConfiguration configuration)
{
this.LinkerConfiguration = configuration;
}

public AssemblyAction UserAction {
get { throw new NotImplementedException (); }
set { throw new NotImplementedException (); }
Expand Down
2 changes: 2 additions & 0 deletions tools/dotnet-linker/DotNetResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

using Xamarin.Bundler;

#nullable enable

namespace Xamarin.Linker {
public class DotNetResolver : CoreResolver {
public override AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters)
Expand Down
2 changes: 2 additions & 0 deletions tools/dotnet-linker/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using Mono.Tuner;
using System;

#nullable enable

namespace Xamarin.Linker {
public static class Extensions {
public static bool Inherits (this TypeReference self, string @namespace, string name, IMetadataResolver resolver)
Expand Down
78 changes: 49 additions & 29 deletions tools/dotnet-linker/LinkerConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
Expand All @@ -12,31 +13,31 @@
using Xamarin.Utils;
using Xamarin.Tuner;

using ObjCRuntime;
#nullable enable

namespace Xamarin.Linker {
public class LinkerConfiguration {
string LinkerFile;

public List<Abi> Abis;
public string AOTCompiler;
public string AOTOutputDirectory;
public string CacheDirectory { get; private set; }
public Version DeploymentTarget { get; private set; }
public List<Abi> Abis = new List<Abi> ();
public string AOTCompiler = string.Empty;
public string AOTOutputDirectory = string.Empty;
public string CacheDirectory { get; private set; } = string.Empty;
public Version? DeploymentTarget { get; private set; }
public HashSet<string> FrameworkAssemblies { get; private set; } = new HashSet<string> ();
public string GlobalizationDataFile { get; private set; }
public string IntermediateLinkDir { get; private set; }
public string GlobalizationDataFile { get; private set; } = string.Empty;
public string IntermediateLinkDir { get; private set; } = string.Empty;
public bool InvariantGlobalization { get; private set; }
public string ItemsDirectory { get; private set; }
public string ItemsDirectory { get; private set; } = string.Empty;
public bool IsSimulatorBuild { get; private set; }
public string PartialStaticRegistrarLibrary { get; set; }
public string PartialStaticRegistrarLibrary { get; set; } = string.Empty;
public ApplePlatform Platform { get; private set; }
public string PlatformAssembly { get; private set; }
public string RelativeAppBundlePath { get; private set; }
public Version SdkVersion { get; private set; }
public string SdkRootDirectory { get; private set; }
public string PlatformAssembly { get; private set; } = string.Empty;
public string RelativeAppBundlePath { get; private set; } = string.Empty;
public Version? SdkVersion { get; private set; }
public string SdkRootDirectory { get; private set; } = string.Empty;
public int Verbosity => Driver.Verbosity;
public string XamarinNativeLibraryDirectory { get; private set; }
public string XamarinNativeLibraryDirectory { get; private set; } = string.Empty;

static ConditionalWeakTable<LinkContext, LinkerConfiguration> configurations = new ConditionalWeakTable<LinkContext, LinkerConfiguration> ();

Expand All @@ -46,22 +47,28 @@ public class LinkerConfiguration {
public IList<string> RegistrationMethods { get; set; } = new List<string> ();
public CompilerFlags CompilerFlags;

public LinkContext Context { get; private set; }
LinkContext? context;
public LinkContext Context { get => context!; private set { context = value; } }
public DerivedLinkContext DerivedLinkContext { get; private set; }
public Profile Profile { get; private set; }

// The list of assemblies is populated in CollectAssembliesStep.
public List<AssemblyDefinition> Assemblies = new List<AssemblyDefinition> ();

string user_optimize_flags;
string? user_optimize_flags;

Dictionary<string, List<MSBuildItem>> msbuild_items = new Dictionary<string, List<MSBuildItem>> ();

internal PInvokeWrapperGenerator PInvokeWrapperGenerationState;
internal PInvokeWrapperGenerator? PInvokeWrapperGenerationState;

public static LinkerConfiguration GetInstance (LinkContext context, bool createIfNotFound = true)
public static bool TryGetInstance (LinkContext context, [NotNullWhen (true)] out LinkerConfiguration? configuration)
{
if (!configurations.TryGetValue (context, out var instance) && createIfNotFound) {
return configurations.TryGetValue (context, out configuration);
}

public static LinkerConfiguration GetInstance (LinkContext context)
{
if (!TryGetInstance (context, out var instance)) {
if (!context.TryGetCustomData ("LinkerOptionsFile", out var linker_options_file))
throw new Exception ($"No custom linker options file was passed to the linker (using --custom-data LinkerOptionsFile=...");
instance = new LinkerConfiguration (linker_options_file) {
Expand All @@ -82,9 +89,9 @@ public static LinkerConfiguration GetInstance (LinkContext context, bool createI
LinkerFile = linker_file;

Profile = new BaseProfile (this);
DerivedLinkContext = new DerivedLinkContext { LinkerConfiguration = this, };
Application = new Application (this);
Target = new Target (Application);
DerivedLinkContext = new DerivedLinkContext (this, Target);
CompilerFlags = new CompilerFlags (Target);

var use_llvm = false;
Expand Down Expand Up @@ -266,7 +273,6 @@ public static LinkerConfiguration GetInstance (LinkContext context, bool createI
if (!Enum.TryParse<Abi> (value, out var arch))
throw new InvalidOperationException ($"Unknown target architectures: {value} in {linker_file}");
// Add to the list of Abis as separate entries (instead of a flags enum value), because that way it's easier to enumerate over them.
Abis = new List<Abi> ();
for (var b = 0; b < 32; b++) {
var a = (Abi) (1 << b);
if ((a & arch) == a)
Expand Down Expand Up @@ -322,11 +328,13 @@ public static LinkerConfiguration GetInstance (LinkContext context, bool createI

Application.CreateCache (significantLines.ToArray ());
Application.Cache.Location = CacheDirectory;
Application.DeploymentTarget = DeploymentTarget;
Application.SdkVersion = SdkVersion;
Application.NativeSdkVersion = SdkVersion;
if (DeploymentTarget is not null)
Application.DeploymentTarget = DeploymentTarget;
if (SdkVersion is not null) {
Application.SdkVersion = SdkVersion;
Application.NativeSdkVersion = SdkVersion;
}

DerivedLinkContext.Target = Target;
Target.Abis = Abis;
Target.LinkContext = DerivedLinkContext;
Application.Abis = Abis;
Expand All @@ -351,12 +359,14 @@ public static LinkerConfiguration GetInstance (LinkContext context, bool createI
Application.Initialize ();
}

bool TryParseOptionalBoolean (string input, out bool? value)
bool TryParseOptionalBoolean (string input, [NotNullWhen (true)] out bool? value)
{
value = null;

if (string.IsNullOrEmpty (input))
if (string.IsNullOrEmpty (input)) {
value = true;
return true;
}

if (string.Equals (input, "true", StringComparison.OrdinalIgnoreCase)) {
value = true;
Expand Down Expand Up @@ -480,7 +490,7 @@ public static void Report (LinkContext context, IList<Exception> exceptions)
var list = ErrorHelper.CollectExceptions (exceptions);
var allWarnings = list.All (v => v is ProductException pe && !pe.Error);
if (!allWarnings) {
var instance = GetInstance (context, false);
TryGetInstance (context, out var instance);
var platform = (instance?.Platform)?.ToString () ?? "unknown";
var msg = MessageContainer.CreateCustomErrorMessage (Errors.MX7000 /* An error occured while executing the custom linker steps. Please review the build log for more information. */, 7000, platform);
context.LogMessage (msg);
Expand All @@ -494,4 +504,14 @@ public static void Report (LinkContext context, IList<Exception> exceptions)
public class MSBuildItem {
public string Include;
public Dictionary<string, string> Metadata = new Dictionary<string, string> ();

public MSBuildItem (string include)
{
Include = include;
}
public MSBuildItem (string include, Dictionary<string, string> metadata)
{
Include = include;
Metadata = metadata;
}
}
2 changes: 2 additions & 0 deletions tools/dotnet-linker/MarkIProtocolHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using Mono.Linker;
using Mono.Linker.Steps;

#nullable enable

namespace Xamarin.Linker {
public class MarkIProtocolHandler : ConfigurationAwareMarkHandler {

Expand Down
2 changes: 2 additions & 0 deletions tools/dotnet-linker/SetupStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
using Xamarin.Linker;
using Xamarin.Linker.Steps;

#nullable enable

namespace Xamarin {

public class SetupStep : ConfigurationAwareStep {
Expand Down
4 changes: 3 additions & 1 deletion tools/dotnet-linker/Steps/AttributeIteratorBaseStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using Mono.Cecil;
using Xamarin.Tuner;

#nullable enable

namespace Xamarin.Linker.Steps {

public abstract class AttributeIteratorBaseStep : BaseSubStep {
Expand Down Expand Up @@ -50,7 +52,7 @@ public override void ProcessType (TypeDefinition type)
void ProcessAttributeProviderCollection (IList list)
{
for (int i = 0; i < list.Count; i++)
ProcessAttributeProvider ((ICustomAttributeProvider) list [i]);
ProcessAttributeProvider ((ICustomAttributeProvider) list [i]!);
}

public override void ProcessField (FieldDefinition field)
Expand Down
6 changes: 4 additions & 2 deletions tools/dotnet-linker/Steps/CollectAssembliesStep.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System.Collections.Generic;
using Mono.Cecil;

#nullable enable

namespace Xamarin.Linker {
public class CollectAssembliesStep : ConfigurationAwareStep {
protected override string Name { get; } = "Collect Assemblies";
Expand All @@ -16,8 +18,8 @@ protected override void TryProcess ()
// This step now runs at the very beginning, using reflection to call into the linker to load all
// the referenced assemblies, so that we can then have another step before MarkStep that does the
// custom marking we need to do.
var getReferencedAssemblies = Configuration.Context.GetType ().GetMethod ("GetReferencedAssemblies");
var assemblies = (IEnumerable<AssemblyDefinition>) getReferencedAssemblies.Invoke (Configuration.Context, new object [0]);
var getReferencedAssemblies = Configuration.Context.GetType ().GetMethod ("GetReferencedAssemblies")!;
var assemblies = (IEnumerable<AssemblyDefinition>) getReferencedAssemblies.Invoke (Configuration.Context, new object [0])!;
Configuration.Assemblies.AddRange (assemblies);
}
}
Expand Down
2 changes: 2 additions & 0 deletions tools/dotnet-linker/Steps/CollectUnmarkedMembers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using Mono.Cecil;
using Mono.Linker.Steps;

#nullable enable

namespace Xamarin.Linker {
// The static registrar may need access to information that has been linked away,
// in particular types and interfaces, so we need to store those somewhere
Expand Down
9 changes: 4 additions & 5 deletions tools/dotnet-linker/Steps/ComputeAOTArguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
using System.Linq;
using System.IO;

using Xamarin.Bundler;
using Xamarin.Utils;

#nullable enable

namespace Xamarin.Linker {
public class ComputeAOTArguments : ConfigurationAwareStep {
protected override string Name { get; } = "Compute AOT Arguments";
Expand All @@ -25,9 +26,7 @@ protected override void TryEndProcess ()
if (!isAOTCompiled)
continue;

var item = new MSBuildItem {
Include = Path.Combine (Configuration.IntermediateLinkDir, asm.FileName),
};
var item = new MSBuildItem (Path.Combine (Configuration.IntermediateLinkDir, asm.FileName));

var input = asm.FullPath;
var abis = app.Abis.Select (v => v.AsString ()).ToArray ();
Expand All @@ -38,7 +37,7 @@ protected override void TryEndProcess ()
var aotData = Path.Combine (outputDirectory, arch, Path.GetFileNameWithoutExtension (input) + ".aotdata");
var llvmFile = Configuration.Application.IsLLVM ? Path.Combine (outputDirectory, arch, Path.GetFileName (input) + ".llvm.o") : string.Empty;
var objectFile = Path.Combine (outputDirectory, arch, Path.GetFileName (input) + ".o");
app.GetAotArguments (asm.FullPath, abi, outputDirectory, aotAssembly, llvmFile, aotData, out var processArguments, out var aotArguments, Path.GetDirectoryName (Configuration.AOTCompiler));
app.GetAotArguments (asm.FullPath, abi, outputDirectory, aotAssembly, llvmFile, aotData, out var processArguments, out var aotArguments, Path.GetDirectoryName (Configuration.AOTCompiler)!);
item.Metadata.Add ("Arguments", StringUtils.FormatArguments (aotArguments));
item.Metadata.Add ("ProcessArguments", StringUtils.FormatArguments (processArguments));
item.Metadata.Add ("Abi", abiString);
Expand Down
Loading

6 comments on commit 791b98c

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

Please sign in to comment.