Skip to content

Commit

Permalink
[Xamarin.Android.Tools.Bytecode] NRT Support (dotnet#913)
Browse files Browse the repository at this point in the history
Context: 3226a4b
Context: 7068f4b

Enable [C# 8 Nullable Reference Types][0] for
`Xamarin.Android.Tools.Bytecode.dll`.

Fix various warnings emitted by string globalization code analyzers.

[0]: https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references
  • Loading branch information
jonpryor authored Nov 16, 2021
1 parent e85564c commit 0293360
Show file tree
Hide file tree
Showing 25 changed files with 422 additions and 344 deletions.
8 changes: 4 additions & 4 deletions src/Xamarin.Android.Tools.Bytecode/Annotation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ public sealed class Annotation
ushort typeIndex;
public string Type => ((ConstantPoolUtf8Item) ConstantPool [typeIndex]).Value;

public IList<KeyValuePair<string, AnnotationElementValue>>
Values { get; } = new List<KeyValuePair<string, AnnotationElementValue>> ();
public IList<KeyValuePair<string, AnnotationElementValue?>>
Values { get; } = new List<KeyValuePair<string, AnnotationElementValue?>> ();

public Annotation (ConstantPool constantPool, Stream stream)
{
Expand All @@ -25,7 +25,7 @@ public Annotation (ConstantPool constantPool, Stream stream)
var elementNameIndex = stream.ReadNetworkUInt16 ();
var elementName = ((ConstantPoolUtf8Item) ConstantPool [elementNameIndex]).Value;
var elementValue = AnnotationElementValue.Create (constantPool, stream);
Values.Add (new KeyValuePair<string, AnnotationElementValue> (elementName, elementValue));
Values.Add (new KeyValuePair<string, AnnotationElementValue?> (elementName, elementValue));
}
}

Expand All @@ -42,7 +42,7 @@ public override string ToString ()
values.Append ("}");
return $"Annotation('{Type}', {values})";

void Append (KeyValuePair<string, AnnotationElementValue> value)
void Append (KeyValuePair<string, AnnotationElementValue?> value)
{
values.Append (value.Key).Append (": ");
values.Append (value.Value);
Expand Down
42 changes: 25 additions & 17 deletions src/Xamarin.Android.Tools.Bytecode/AnnotationElementValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ namespace Xamarin.Android.Tools.Bytecode
// https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.16.1
public abstract class AnnotationElementValue
{
public virtual string ToEncodedString () => ToString ();
public virtual string? ToEncodedString () => ToString ();

public static AnnotationElementValue Create (ConstantPool constantPool, Stream stream)
public static AnnotationElementValue? Create (ConstantPool constantPool, Stream stream)
{
var tag = stream.ReadNetworkByte ();

Expand All @@ -38,8 +38,12 @@ public static AnnotationElementValue Create (ConstantPool constantPool, Stream s

var values = new List<AnnotationElementValue> ();

for (var i = 0; i < numValues; i++)
values.Add (Create (constantPool, stream));
for (var i = 0; i < numValues; i++) {
var v = Create (constantPool, stream);
if (v == null)
continue;
values.Add (v);
}

return new AnnotationElementArray { Values = values.ToArray () };
}
Expand Down Expand Up @@ -79,49 +83,53 @@ public static AnnotationElementValue Create (ConstantPool constantPool, Stream s

public class AnnotationElementEnum : AnnotationElementValue
{
public string TypeName { get; set; }
public string ConstantName { get; set; }
public string? TypeName { get; set; }
public string? ConstantName { get; set; }

public override string ToString () => $"Enum({TypeName}.{ConstantName})";
}

public class AnnotationElementClassInfo : AnnotationElementValue
{
public string ClassInfo { get; set; }
public string? ClassInfo { get; set; }

public override string ToString () => ClassInfo;
public override string? ToString () => ClassInfo;
}

public class AnnotationElementAnnotation : AnnotationElementValue
{
public Annotation Annotation { get; set; }
public Annotation? Annotation { get; set; }

public override string ToString () => Annotation.ToString ();
public override string? ToString () => Annotation?.ToString ();
}

public class AnnotationElementArray : AnnotationElementValue
{
public AnnotationElementValue[] Values { get; set; }
public AnnotationElementValue[]? Values { get; set; }

public override string ToString () => $"[{string.Join (", ", Values.Select (v => v.ToString ()))}]";
public override string ToString () => Values == null
? "[]"
: $"[{string.Join (", ", Values.Select (v => v.ToString ()))}]";

public override string ToEncodedString () => $"[{string.Join (", ", Values.Select (v => v.ToEncodedString ()))}]";
public override string? ToEncodedString () => Values == null
? "[]"
: $"[{string.Join (", ", Values.Select (v => v.ToEncodedString ()))}]";
}

public class AnnotationElementConstant : AnnotationElementValue
{
public string Value { get; set; }
public string? Value { get; set; }

public override string ToString () => Value;
public override string? ToString () => Value;
}

public class AnnotationStringElementConstant : AnnotationElementConstant
{
public override string ToString () => $"\"{Value}\"";

public override string ToEncodedString ()
public override string? ToEncodedString ()
{
return $"\"{Convert.ToBase64String (Encoding.UTF8.GetBytes (Value))}\"";
return $"\"{Convert.ToBase64String (Encoding.UTF8.GetBytes (Value ?? ""))}\"";
}
}
}
14 changes: 7 additions & 7 deletions src/Xamarin.Android.Tools.Bytecode/AttributeInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ public IEnumerable<AttributeInfo> GetInfos (string name)
return this.Where (a => a.Name == name);
}

public T Get<T> ()
public T? Get<T> ()
where T : AttributeInfo
{
return (T) GetInfos (AttributeInfo.GetAttributeName<T>()).SingleOrDefault ();
return (T?) GetInfos (AttributeInfo.GetAttributeName<T>()).SingleOrDefault ();
}
}

Expand Down Expand Up @@ -88,7 +88,7 @@ public string Name {

internal static string GetAttributeName<T>()
{
string value;
string? value;
if (AttributeNames.TryGetValue (typeof(T), out value)) {
return value;
}
Expand Down Expand Up @@ -244,7 +244,7 @@ public ConstantPoolClassItem Class {
get {return (ConstantPoolClassItem) ConstantPool [classIndex];}
}

public ConstantPoolNameAndTypeItem Method {
public ConstantPoolNameAndTypeItem? Method {
get {return methodIndex == 0 ? null : (ConstantPoolNameAndTypeItem) ConstantPool [methodIndex];}
}

Expand Down Expand Up @@ -351,7 +351,7 @@ public ConstantPoolClassItem OuterClass {
get {return (ConstantPoolClassItem) ConstantPool [outerClassInfoIndex];}
}

public string InnerName {
public string? InnerName {
get {
if (innerNameIndex == 0)
// anonymous class
Expand All @@ -360,7 +360,7 @@ public string InnerName {
}
}

public string OuterClassName => OuterClass?.Name?.Value;
public string? OuterClassName => OuterClass?.Name?.Value;

public override string ToString ()
{
Expand Down Expand Up @@ -447,7 +447,7 @@ public MethodParameterInfo (ConstantPool constantPool)
ConstantPool = constantPool;
}

public string Name {
public string? Name {
get {
if (nameIndex == 0)
return null;
Expand Down
16 changes: 10 additions & 6 deletions src/Xamarin.Android.Tools.Bytecode/ClassFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;

Expand All @@ -23,7 +24,7 @@ public sealed class ClassFile {
public Methods Methods;
public AttributeCollection Attributes;

ClassSignature signature;
ClassSignature? signature;


public ClassFile (Stream stream)
Expand Down Expand Up @@ -100,14 +101,17 @@ public string PackageName {

public string FullJniName => "L" + ThisClass.Name.Value + ";";

public string SourceFileName {
public string? SourceFileName {
get {
var sourceFile = Attributes.Get<SourceFileAttribute> ();
return sourceFile == null ? null : sourceFile.FileName;
}
}

public bool TryGetEnclosingMethodInfo (out string declaringClass, out string declaringMethod, out string declaringDescriptor)
public bool TryGetEnclosingMethodInfo (
[NotNullWhen (true)] out string? declaringClass,
out string? declaringMethod,
out string? declaringDescriptor)
{
declaringClass = declaringMethod = declaringDescriptor = null;

Expand All @@ -122,7 +126,7 @@ public bool TryGetEnclosingMethodInfo (out string declaringClass, out string dec
return true;
}

public ClassSignature GetSignature ()
public ClassSignature? GetSignature ()
{
if (this.signature != null)
return this.signature;
Expand Down Expand Up @@ -161,7 +165,7 @@ public IList<InnerClassInfo> InnerClasses {
}
}

public InnerClassInfo InnerClass {
public InnerClassInfo? InnerClass {
get {
return InnerClasses.SingleOrDefault (c => c.InnerClass == ThisClass);
}
Expand Down Expand Up @@ -189,7 +193,7 @@ public bool IsEnum {
get {return (AccessFlags & ClassAccessFlags.Enum) != 0;}
}

public override string ToString () => ThisClass?.Name.Value;
public override string? ToString () => ThisClass?.Name.Value;
}

[Flags]
Expand Down
36 changes: 23 additions & 13 deletions src/Xamarin.Android.Tools.Bytecode/ClassPath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@ public class ClassPath {

IList<ClassFile> classFiles = new List<ClassFile> ();

public string ApiSource { get; set; }
public string? ApiSource { get; set; }

public IEnumerable<string> DocumentationPaths { get; set; }
public IEnumerable<string>? DocumentationPaths { get; set; }

public string AndroidFrameworkPlatform { get; set; }
public string? AndroidFrameworkPlatform { get; set; }

public bool AutoRename { get; set; }

public ClassPath (string path = null)
public ClassPath (string? path = null)
{
if (string.IsNullOrEmpty (path))
if (path == null || string.IsNullOrEmpty (path))
return;

Load (path);
Expand Down Expand Up @@ -138,14 +138,14 @@ public static bool IsJmodFile (string jmodFile)
}
}

XAttribute GetApiSource ()
XAttribute? GetApiSource ()
{
if (string.IsNullOrEmpty (ApiSource))
return null;
return new XAttribute ("api-source", ApiSource);
}

XAttribute GetPlatform ()
XAttribute? GetPlatform ()
{
if (string.IsNullOrEmpty (AndroidFrameworkPlatform))
return null;
Expand Down Expand Up @@ -286,20 +286,27 @@ void FixupParametersFromDocs (XElement api, string path)
var elements = api.XPathSelectElements ("./package/class[@visibility = 'public' or @visibility = 'protected']").ToList ();
elements.AddRange (api.XPathSelectElements ("./package/interface[@visibility = 'public' or @visibility = 'protected']"));
foreach (var elem in elements) {
var currentpackage = elem.Parent.Attribute ("name").Value;
var className = elem.Attribute ("name").Value;
var currentpackage = elem.Parent?.Attribute ("name")?.Value ?? "";
var className = elem.Attribute ("name")?.Value;

if (className == null)
continue;

var methodsAndConstructors = elem.XPathSelectElements ("./method[@visibility = 'public' or @visibility = 'protected']").ToList ();
methodsAndConstructors.AddRange (elem.XPathSelectElements ("./constructor[@visibility = 'public' or @visibility = 'protected']"));

foreach (var method in methodsAndConstructors) {
var currentMethod = method.Attribute ("name").Value;
var currentMethod = method.Attribute ("name")?.Value;
if (currentMethod == null)
continue;

var parameterElements = method.Elements ("parameter").ToList ();
if (!parameterElements.Select (x => x.Attribute ("name").Value).Any (p => IsGeneratedName (p)))
if (!parameterElements.Select (x => x.Attribute ("name")?.Value).Any (p => p != null && IsGeneratedName (p)))
continue;

var parameters = parameterElements.Select (p => p.Attribute ("type").Value);
var parameters = parameterElements
.Select (p => p.Attribute ("type")?.Value!)
.Where (p => p != null);

if (!parameters.Any ())
continue;
Expand All @@ -308,7 +315,10 @@ void FixupParametersFromDocs (XElement api, string path)
if (pnames == null || pnames.Length != parameterElements.Count)
continue;
for (int i = 0; i < parameterElements.Count; i++) {
parameterElements [i].Attribute ("name").Value = pnames [i];
var a = parameterElements [i].Attribute ("name");
if (a == null)
continue;
a.Value = pnames [i];
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Xamarin.Android.Tools.Bytecode/ConstantPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public ConstantPool (Stream stream)

// indexes are one-based;
// "The constant_pool table is indexed from 1 to constant_pool_count-1."
Add (null);
Add (null!);
int constant_pool_count = stream.ReadNetworkUInt16 ();
for (int i = 1; i < constant_pool_count; ++i) {
var entry = ConstantPoolItem.CreateFromStream (this, stream);
Expand Down
4 changes: 2 additions & 2 deletions src/Xamarin.Android.Tools.Bytecode/Fields.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public sealed class FieldInfo {
public ConstantPool ConstantPool {get; private set;}
public FieldAccessFlags AccessFlags {get; private set;}
public AttributeCollection Attributes {get; private set;}
public string KotlinType { get; set; }
public string? KotlinType {get; set;}

public FieldInfo (ConstantPool constantPool, Stream stream)
{
Expand All @@ -56,7 +56,7 @@ public string Descriptor {
}
}

public string GetSignature ()
public string? GetSignature ()
{
var signature = Attributes.Get<SignatureAttribute> ();
return signature != null ? signature.Value : null;
Expand Down
Loading

0 comments on commit 0293360

Please sign in to comment.