Skip to content

Commit 0293360

Browse files
authored
[Xamarin.Android.Tools.Bytecode] NRT Support (#913)
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
1 parent e85564c commit 0293360

25 files changed

+422
-344
lines changed

src/Xamarin.Android.Tools.Bytecode/Annotation.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ public sealed class Annotation
1212
ushort typeIndex;
1313
public string Type => ((ConstantPoolUtf8Item) ConstantPool [typeIndex]).Value;
1414

15-
public IList<KeyValuePair<string, AnnotationElementValue>>
16-
Values { get; } = new List<KeyValuePair<string, AnnotationElementValue>> ();
15+
public IList<KeyValuePair<string, AnnotationElementValue?>>
16+
Values { get; } = new List<KeyValuePair<string, AnnotationElementValue?>> ();
1717

1818
public Annotation (ConstantPool constantPool, Stream stream)
1919
{
@@ -25,7 +25,7 @@ public Annotation (ConstantPool constantPool, Stream stream)
2525
var elementNameIndex = stream.ReadNetworkUInt16 ();
2626
var elementName = ((ConstantPoolUtf8Item) ConstantPool [elementNameIndex]).Value;
2727
var elementValue = AnnotationElementValue.Create (constantPool, stream);
28-
Values.Add (new KeyValuePair<string, AnnotationElementValue> (elementName, elementValue));
28+
Values.Add (new KeyValuePair<string, AnnotationElementValue?> (elementName, elementValue));
2929
}
3030
}
3131

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

45-
void Append (KeyValuePair<string, AnnotationElementValue> value)
45+
void Append (KeyValuePair<string, AnnotationElementValue?> value)
4646
{
4747
values.Append (value.Key).Append (": ");
4848
values.Append (value.Value);

src/Xamarin.Android.Tools.Bytecode/AnnotationElementValue.cs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ namespace Xamarin.Android.Tools.Bytecode
99
// https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.16.1
1010
public abstract class AnnotationElementValue
1111
{
12-
public virtual string ToEncodedString () => ToString ();
12+
public virtual string? ToEncodedString () => ToString ();
1313

14-
public static AnnotationElementValue Create (ConstantPool constantPool, Stream stream)
14+
public static AnnotationElementValue? Create (ConstantPool constantPool, Stream stream)
1515
{
1616
var tag = stream.ReadNetworkByte ();
1717

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

3939
var values = new List<AnnotationElementValue> ();
4040

41-
for (var i = 0; i < numValues; i++)
42-
values.Add (Create (constantPool, stream));
41+
for (var i = 0; i < numValues; i++) {
42+
var v = Create (constantPool, stream);
43+
if (v == null)
44+
continue;
45+
values.Add (v);
46+
}
4347

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

8084
public class AnnotationElementEnum : AnnotationElementValue
8185
{
82-
public string TypeName { get; set; }
83-
public string ConstantName { get; set; }
86+
public string? TypeName { get; set; }
87+
public string? ConstantName { get; set; }
8488

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

8892
public class AnnotationElementClassInfo : AnnotationElementValue
8993
{
90-
public string ClassInfo { get; set; }
94+
public string? ClassInfo { get; set; }
9195

92-
public override string ToString () => ClassInfo;
96+
public override string? ToString () => ClassInfo;
9397
}
9498

9599
public class AnnotationElementAnnotation : AnnotationElementValue
96100
{
97-
public Annotation Annotation { get; set; }
101+
public Annotation? Annotation { get; set; }
98102

99-
public override string ToString () => Annotation.ToString ();
103+
public override string? ToString () => Annotation?.ToString ();
100104
}
101105

102106
public class AnnotationElementArray : AnnotationElementValue
103107
{
104-
public AnnotationElementValue[] Values { get; set; }
108+
public AnnotationElementValue[]? Values { get; set; }
105109

106-
public override string ToString () => $"[{string.Join (", ", Values.Select (v => v.ToString ()))}]";
110+
public override string ToString () => Values == null
111+
? "[]"
112+
: $"[{string.Join (", ", Values.Select (v => v.ToString ()))}]";
107113

108-
public override string ToEncodedString () => $"[{string.Join (", ", Values.Select (v => v.ToEncodedString ()))}]";
114+
public override string? ToEncodedString () => Values == null
115+
? "[]"
116+
: $"[{string.Join (", ", Values.Select (v => v.ToEncodedString ()))}]";
109117
}
110118

111119
public class AnnotationElementConstant : AnnotationElementValue
112120
{
113-
public string Value { get; set; }
121+
public string? Value { get; set; }
114122

115-
public override string ToString () => Value;
123+
public override string? ToString () => Value;
116124
}
117125

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

122-
public override string ToEncodedString ()
130+
public override string? ToEncodedString ()
123131
{
124-
return $"\"{Convert.ToBase64String (Encoding.UTF8.GetBytes (Value))}\"";
132+
return $"\"{Convert.ToBase64String (Encoding.UTF8.GetBytes (Value ?? ""))}\"";
125133
}
126134
}
127135
}

src/Xamarin.Android.Tools.Bytecode/AttributeInfo.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ public IEnumerable<AttributeInfo> GetInfos (string name)
2626
return this.Where (a => a.Name == name);
2727
}
2828

29-
public T Get<T> ()
29+
public T? Get<T> ()
3030
where T : AttributeInfo
3131
{
32-
return (T) GetInfos (AttributeInfo.GetAttributeName<T>()).SingleOrDefault ();
32+
return (T?) GetInfos (AttributeInfo.GetAttributeName<T>()).SingleOrDefault ();
3333
}
3434
}
3535

@@ -88,7 +88,7 @@ public string Name {
8888

8989
internal static string GetAttributeName<T>()
9090
{
91-
string value;
91+
string? value;
9292
if (AttributeNames.TryGetValue (typeof(T), out value)) {
9393
return value;
9494
}
@@ -244,7 +244,7 @@ public ConstantPoolClassItem Class {
244244
get {return (ConstantPoolClassItem) ConstantPool [classIndex];}
245245
}
246246

247-
public ConstantPoolNameAndTypeItem Method {
247+
public ConstantPoolNameAndTypeItem? Method {
248248
get {return methodIndex == 0 ? null : (ConstantPoolNameAndTypeItem) ConstantPool [methodIndex];}
249249
}
250250

@@ -351,7 +351,7 @@ public ConstantPoolClassItem OuterClass {
351351
get {return (ConstantPoolClassItem) ConstantPool [outerClassInfoIndex];}
352352
}
353353

354-
public string InnerName {
354+
public string? InnerName {
355355
get {
356356
if (innerNameIndex == 0)
357357
// anonymous class
@@ -360,7 +360,7 @@ public string InnerName {
360360
}
361361
}
362362

363-
public string OuterClassName => OuterClass?.Name?.Value;
363+
public string? OuterClassName => OuterClass?.Name?.Value;
364364

365365
public override string ToString ()
366366
{
@@ -447,7 +447,7 @@ public MethodParameterInfo (ConstantPool constantPool)
447447
ConstantPool = constantPool;
448448
}
449449

450-
public string Name {
450+
public string? Name {
451451
get {
452452
if (nameIndex == 0)
453453
return null;

src/Xamarin.Android.Tools.Bytecode/ClassFile.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections;
33
using System.Collections.Generic;
44
using System.Collections.ObjectModel;
5+
using System.Diagnostics.CodeAnalysis;
56
using System.IO;
67
using System.Linq;
78

@@ -23,7 +24,7 @@ public sealed class ClassFile {
2324
public Methods Methods;
2425
public AttributeCollection Attributes;
2526

26-
ClassSignature signature;
27+
ClassSignature? signature;
2728

2829

2930
public ClassFile (Stream stream)
@@ -100,14 +101,17 @@ public string PackageName {
100101

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

103-
public string SourceFileName {
104+
public string? SourceFileName {
104105
get {
105106
var sourceFile = Attributes.Get<SourceFileAttribute> ();
106107
return sourceFile == null ? null : sourceFile.FileName;
107108
}
108109
}
109110

110-
public bool TryGetEnclosingMethodInfo (out string declaringClass, out string declaringMethod, out string declaringDescriptor)
111+
public bool TryGetEnclosingMethodInfo (
112+
[NotNullWhen (true)] out string? declaringClass,
113+
out string? declaringMethod,
114+
out string? declaringDescriptor)
111115
{
112116
declaringClass = declaringMethod = declaringDescriptor = null;
113117

@@ -122,7 +126,7 @@ public bool TryGetEnclosingMethodInfo (out string declaringClass, out string dec
122126
return true;
123127
}
124128

125-
public ClassSignature GetSignature ()
129+
public ClassSignature? GetSignature ()
126130
{
127131
if (this.signature != null)
128132
return this.signature;
@@ -161,7 +165,7 @@ public IList<InnerClassInfo> InnerClasses {
161165
}
162166
}
163167

164-
public InnerClassInfo InnerClass {
168+
public InnerClassInfo? InnerClass {
165169
get {
166170
return InnerClasses.SingleOrDefault (c => c.InnerClass == ThisClass);
167171
}
@@ -189,7 +193,7 @@ public bool IsEnum {
189193
get {return (AccessFlags & ClassAccessFlags.Enum) != 0;}
190194
}
191195

192-
public override string ToString () => ThisClass?.Name.Value;
196+
public override string? ToString () => ThisClass?.Name.Value;
193197
}
194198

195199
[Flags]

src/Xamarin.Android.Tools.Bytecode/ClassPath.cs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,17 @@ public class ClassPath {
2525

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

28-
public string ApiSource { get; set; }
28+
public string? ApiSource { get; set; }
2929

30-
public IEnumerable<string> DocumentationPaths { get; set; }
30+
public IEnumerable<string>? DocumentationPaths { get; set; }
3131

32-
public string AndroidFrameworkPlatform { get; set; }
32+
public string? AndroidFrameworkPlatform { get; set; }
3333

3434
public bool AutoRename { get; set; }
3535

36-
public ClassPath (string path = null)
36+
public ClassPath (string? path = null)
3737
{
38-
if (string.IsNullOrEmpty (path))
38+
if (path == null || string.IsNullOrEmpty (path))
3939
return;
4040

4141
Load (path);
@@ -138,14 +138,14 @@ public static bool IsJmodFile (string jmodFile)
138138
}
139139
}
140140

141-
XAttribute GetApiSource ()
141+
XAttribute? GetApiSource ()
142142
{
143143
if (string.IsNullOrEmpty (ApiSource))
144144
return null;
145145
return new XAttribute ("api-source", ApiSource);
146146
}
147147

148-
XAttribute GetPlatform ()
148+
XAttribute? GetPlatform ()
149149
{
150150
if (string.IsNullOrEmpty (AndroidFrameworkPlatform))
151151
return null;
@@ -286,20 +286,27 @@ void FixupParametersFromDocs (XElement api, string path)
286286
var elements = api.XPathSelectElements ("./package/class[@visibility = 'public' or @visibility = 'protected']").ToList ();
287287
elements.AddRange (api.XPathSelectElements ("./package/interface[@visibility = 'public' or @visibility = 'protected']"));
288288
foreach (var elem in elements) {
289-
var currentpackage = elem.Parent.Attribute ("name").Value;
290-
var className = elem.Attribute ("name").Value;
289+
var currentpackage = elem.Parent?.Attribute ("name")?.Value ?? "";
290+
var className = elem.Attribute ("name")?.Value;
291+
292+
if (className == null)
293+
continue;
291294

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

295298
foreach (var method in methodsAndConstructors) {
296-
var currentMethod = method.Attribute ("name").Value;
299+
var currentMethod = method.Attribute ("name")?.Value;
300+
if (currentMethod == null)
301+
continue;
297302

298303
var parameterElements = method.Elements ("parameter").ToList ();
299-
if (!parameterElements.Select (x => x.Attribute ("name").Value).Any (p => IsGeneratedName (p)))
304+
if (!parameterElements.Select (x => x.Attribute ("name")?.Value).Any (p => p != null && IsGeneratedName (p)))
300305
continue;
301306

302-
var parameters = parameterElements.Select (p => p.Attribute ("type").Value);
307+
var parameters = parameterElements
308+
.Select (p => p.Attribute ("type")?.Value!)
309+
.Where (p => p != null);
303310

304311
if (!parameters.Any ())
305312
continue;
@@ -308,7 +315,10 @@ void FixupParametersFromDocs (XElement api, string path)
308315
if (pnames == null || pnames.Length != parameterElements.Count)
309316
continue;
310317
for (int i = 0; i < parameterElements.Count; i++) {
311-
parameterElements [i].Attribute ("name").Value = pnames [i];
318+
var a = parameterElements [i].Attribute ("name");
319+
if (a == null)
320+
continue;
321+
a.Value = pnames [i];
312322
}
313323
}
314324
}

src/Xamarin.Android.Tools.Bytecode/ConstantPool.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public ConstantPool (Stream stream)
1818

1919
// indexes are one-based;
2020
// "The constant_pool table is indexed from 1 to constant_pool_count-1."
21-
Add (null);
21+
Add (null!);
2222
int constant_pool_count = stream.ReadNetworkUInt16 ();
2323
for (int i = 1; i < constant_pool_count; ++i) {
2424
var entry = ConstantPoolItem.CreateFromStream (this, stream);

src/Xamarin.Android.Tools.Bytecode/Fields.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public sealed class FieldInfo {
3333
public ConstantPool ConstantPool {get; private set;}
3434
public FieldAccessFlags AccessFlags {get; private set;}
3535
public AttributeCollection Attributes {get; private set;}
36-
public string KotlinType { get; set; }
36+
public string? KotlinType {get; set;}
3737

3838
public FieldInfo (ConstantPool constantPool, Stream stream)
3939
{
@@ -56,7 +56,7 @@ public string Descriptor {
5656
}
5757
}
5858

59-
public string GetSignature ()
59+
public string? GetSignature ()
6060
{
6161
var signature = Attributes.Get<SignatureAttribute> ();
6262
return signature != null ? signature.Value : null;

0 commit comments

Comments
 (0)