Skip to content
This repository was archived by the owner on Dec 12, 2024. It is now read-only.

Commit 53a1c36

Browse files
Merge pull request #544 from xamarin/attributes-from-xml
Read XML into attributes.
2 parents ac5e424 + 380f956 commit 53a1c36

File tree

7 files changed

+265
-22
lines changed

7 files changed

+265
-22
lines changed

Diff for: SwiftReflector/SwiftInterfaceReflector/SwiftInterfaceReflector.cs

+11-4
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ public class SwiftInterfaceReflector : SwiftInterfaceBaseListener {
104104
internal const string kLabel = "Label";
105105
internal const string kLiteral = "Literal";
106106
internal const string kSeparator = "Separator";
107-
internal const string kVersion = "Version";
108107
internal const string kSublist = "Sublist";
109108
internal const string kValue = "Value";
110109

@@ -994,9 +993,17 @@ XElement ToAttributeParameter (Balanced_tokenContext context)
994993
return literal;
995994
}
996995

997-
if (context.Platform_name_platform_version () != null) {
998-
var version = new XElement (kAttribute, new XAttribute (kKind, kVersion),
999-
new XAttribute (kValue, context.Platform_name_platform_version ().GetText ()));
996+
// make the operator look like a label
997+
if (context.@operator () != null) {
998+
var label = new XElement (kAttributeParameter, new XAttribute (kKind, kLabel),
999+
new XAttribute (kValue, context.@operator ().GetText ()));
1000+
return label;
1001+
}
1002+
1003+
if (context.any_punctuation_for_balanced_token () != null) {
1004+
var label = new XElement (kAttributeParameter, new XAttribute (kKind, kLabel),
1005+
new XAttribute (kValue, context.any_punctuation_for_balanced_token ().GetText ()));
1006+
return label;
10001007
}
10011008

10021009
return null;

Diff for: SwiftReflector/SwiftReflector.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@
180180
<Compile Include="SwiftXmlReflection\OperatorDeclaration.cs" />
181181
<Compile Include="TypeMapping\ModuleDatabase.cs" />
182182
<Compile Include="SwiftInterfaceReflector\IModuleLoader.cs" />
183+
<Compile Include="SwiftXmlReflection\AttributeDeclaration.cs" />
183184
</ItemGroup>
184185
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
185186
<ItemGroup>
+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Xml.Linq;
7+
using Dynamo;
8+
using System.Linq;
9+
10+
namespace SwiftReflector.SwiftXmlReflection {
11+
public class AttributeDeclaration {
12+
public AttributeDeclaration (string name)
13+
{
14+
Name = Exceptions.ThrowOnNull (name, nameof (name));
15+
Parameters = new List<AttributeParameter> ();
16+
}
17+
18+
public AttributeDeclaration (AttributeDeclaration other)
19+
: this (other.Name)
20+
{
21+
foreach (var parameter in other.Parameters)
22+
Parameters.Add (DuplicateOf (parameter));
23+
}
24+
25+
public static AttributeDeclaration FromXElement (XElement elem)
26+
{
27+
var decl = new AttributeDeclaration (elem.Attribute ("name").Value);
28+
var parameters = elem.Element ("attributeparameterlist");
29+
if (parameters == null)
30+
return decl;
31+
FromAttributeParameterList (parameters, decl.Parameters);
32+
return decl;
33+
}
34+
35+
internal static void FromAttributeParameterList (XElement parameters, List<AttributeParameter> outlist)
36+
{
37+
foreach (var parameterElem in parameters.Elements ("attributeparameter")) {
38+
var parameter = AttributeParameter.FromXElement (parameterElem);
39+
outlist.Add (parameter);
40+
}
41+
}
42+
43+
public static AttributeParameter DuplicateOf(AttributeParameter other)
44+
{
45+
switch (other.Kind) {
46+
case AttributeParameterKind.Label:
47+
return new AttributeParameterLabel ((AttributeParameterLabel)other);
48+
case AttributeParameterKind.Literal:
49+
return new AttributeParameterLiteral ((AttributeParameterLiteral)other);
50+
case AttributeParameterKind.Sublist:
51+
return new AttributeParameterSublist ((AttributeParameterSublist)other);
52+
case AttributeParameterKind.Unknown:
53+
return new AttributeParameter ();
54+
default:
55+
throw new ArgumentOutOfRangeException (nameof (other), other.Kind.ToString ());
56+
}
57+
}
58+
59+
public string Name { get; private set; }
60+
public List<AttributeParameter> Parameters { get; private set; }
61+
}
62+
63+
public class AttributeParameter {
64+
public static AttributeParameter FromXElement (XElement elem)
65+
{
66+
switch (elem.Attribute ("kind").Value) {
67+
case "Label":
68+
return new AttributeParameterLabel (elem.Attribute ("Value").Value);
69+
case "Literal":
70+
return new AttributeParameterLiteral (elem.Attribute ("Value").Value);
71+
case "Sublist":
72+
return AttributeParameterSublist.SublistFromXElement (elem);
73+
default:
74+
return new AttributeParameter ();
75+
}
76+
}
77+
78+
public virtual AttributeParameterKind Kind => AttributeParameterKind.Unknown;
79+
}
80+
81+
public class AttributeParameterLabel : AttributeParameter {
82+
public AttributeParameterLabel (string label)
83+
{
84+
Label = Exceptions.ThrowOnNull (label, nameof (label));
85+
}
86+
87+
public AttributeParameterLabel (AttributeParameterLabel other)
88+
: this (other.Label)
89+
{
90+
}
91+
92+
public override AttributeParameterKind Kind => AttributeParameterKind.Label;
93+
public string Label { get; private set; }
94+
}
95+
96+
public class AttributeParameterLiteral : AttributeParameter {
97+
public AttributeParameterLiteral (string literal)
98+
{
99+
Literal = Exceptions.ThrowOnNull (literal, nameof (literal));
100+
}
101+
102+
public AttributeParameterLiteral (AttributeParameterLiteral other)
103+
: this (other.Literal)
104+
{
105+
}
106+
107+
public override AttributeParameterKind Kind => AttributeParameterKind.Literal;
108+
public string Literal { get; private set; }
109+
}
110+
111+
public class AttributeParameterSublist : AttributeParameter {
112+
public AttributeParameterSublist ()
113+
{
114+
Parameters = new List<AttributeParameter> ();
115+
}
116+
117+
public AttributeParameterSublist (AttributeParameterSublist other)
118+
: this ()
119+
{
120+
Parameters.AddRange (other.Parameters.Select (prm => AttributeDeclaration.DuplicateOf (prm)));
121+
}
122+
123+
public static AttributeParameterSublist SublistFromXElement (XElement elem)
124+
{
125+
var sublist = new AttributeParameterSublist ();
126+
var parameters = elem.Element ("attributeparameterlist");
127+
if (parameters == null)
128+
return sublist;
129+
AttributeDeclaration.FromAttributeParameterList (parameters, sublist.Parameters);
130+
return sublist;
131+
}
132+
133+
public override AttributeParameterKind Kind => AttributeParameterKind.Sublist;
134+
public List<AttributeParameter> Parameters { get; private set; }
135+
}
136+
}

Diff for: SwiftReflector/SwiftXmlReflection/BaseDeclaration.cs

+11
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public class BaseDeclaration {
1515
protected BaseDeclaration ()
1616
{
1717
Generics = new GenericDeclarationCollection ();
18+
Attributes = new List<AttributeDeclaration> ();
1819
}
1920

2021
protected BaseDeclaration (BaseDeclaration other)
@@ -25,6 +26,7 @@ protected BaseDeclaration (BaseDeclaration other)
2526
Parent = other.Parent;
2627
ParentExtension = other.ParentExtension;
2728
Generics = new GenericDeclarationCollection ();
29+
Attributes = new List<AttributeDeclaration> ();
2830
}
2931

3032
public string Name { get; set; }
@@ -39,6 +41,7 @@ public bool ContainsGenericParameters {
3941
return Generics.Count () > 0;
4042
}
4143
}
44+
public List<AttributeDeclaration> Attributes { get; private set; }
4245

4346
public bool IsTypeSpecBoundGeneric (TypeSpec sp)
4447
{
@@ -499,9 +502,17 @@ public static BaseDeclaration FromXElement (XElement elem, ModuleDeclaration mod
499502
break;
500503
}
501504
decl.Generics.AddRange (generics);
505+
decl.Attributes.AddRange (AttributesFromXElement (elem.Element ("attributes")));
502506
return decl;
503507
}
504508

509+
internal static IEnumerable<AttributeDeclaration> AttributesFromXElement (XElement elem)
510+
{
511+
if (elem == null)
512+
return Enumerable.Empty<AttributeDeclaration> ();
513+
return elem.Elements ("attribute").Select (attr => AttributeDeclaration.FromXElement (attr));
514+
}
515+
505516
public virtual string ToFullyQualifiedName (bool includeModule = true)
506517
{
507518
var sb = new StringBuilder ();

Diff for: SwiftReflector/SwiftXmlReflection/Enums.cs

+8
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,13 @@ public enum ConstraintKind {
7070
Inherits,
7171
Equal
7272
}
73+
74+
public enum AttributeParameterKind {
75+
None,
76+
Label,
77+
Literal,
78+
Sublist,
79+
Unknown,
80+
}
7381
}
7482

Diff for: swiftinterfaceparser/SwiftInterface.g4

+1-18
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ balanced_token :
291291
| OpLBrace balanced_tokens OpRBrace
292292
| label_identifier
293293
| literal
294-
| Platform_name_platform_version
294+
| operator
295295
| any_punctuation_for_balanced_token
296296
;
297297

@@ -465,23 +465,6 @@ fragment Identifier_characters : Identifier_character+ ;
465465
466466
Implicit_parameter_name : '$' Decimal_digits ;
467467
468-
Platform_name_platform_version : Platform_name WS Platform_version ;
469-
470-
fragment Platform_name :
471-
'iOS'
472-
| 'iOSApplicationExtension'
473-
| 'macOS'
474-
| 'macOSApplicationExtension'
475-
| 'watchOS'
476-
| 'tvOS'
477-
;
478-
479-
fragment Platform_version :
480-
Pure_decimal_digits
481-
| Pure_decimal_digits OpDot Pure_decimal_digits
482-
| Pure_decimal_digits OpDot Pure_decimal_digits OpDot Pure_decimal_digits
483-
;
484-
485468
generic_parameter_clause : OpLess generic_parameter_list OpGreater ;
486469
generic_parameter_list : generic_parameter (OpComma generic_parameter)* ;
487470
generic_parameter : type_name

Diff for: tests/tom-swifty-test/XmlReflectionTests/SwiftInterfaceParserTests.cs

+97
Original file line numberDiff line numberDiff line change
@@ -303,5 +303,102 @@ public override init () { }
303303
.Where (el => el.Attribute ("name").Value == "objc").FirstOrDefault ();
304304
Assert.IsNotNull (attribute, "no function attribute");
305305
}
306+
307+
[Test]
308+
public void HasAttributeDeclarations ()
309+
{
310+
var swiftCode = @"
311+
import Foundation
312+
@objc
313+
public class Foo : NSObject {
314+
public override init () { }
315+
}
316+
";
317+
SwiftInterfaceReflector reflector;
318+
var module = ReflectToModules (swiftCode, "SomeModule", out reflector).FirstOrDefault (mod => mod.Name == "SomeModule");
319+
Assert.IsNotNull (module, "no module");
320+
321+
var cl = module.Classes.FirstOrDefault (c => c.Name == "Foo");
322+
Assert.IsNotNull (cl, "no class");
323+
324+
Assert.AreEqual (2, cl.Attributes.Count, "wrong number of attributes");
325+
326+
var attr = cl.Attributes.FirstOrDefault (at => at.Name == "objc");
327+
Assert.IsNotNull (attr, "no objc attribute");
328+
}
329+
330+
331+
[Test]
332+
public void HasAttributeObjCSelectorParameter ()
333+
{
334+
var swiftCode = @"
335+
import Foundation
336+
@objc
337+
public class Foo : NSObject {
338+
public override init () { }
339+
@objc(narwhal)
340+
public func DoSomething () -> Int {
341+
return 1
342+
}
343+
}
344+
";
345+
SwiftInterfaceReflector reflector;
346+
var module = ReflectToModules (swiftCode, "SomeModule", out reflector).FirstOrDefault (mod => mod.Name == "SomeModule");
347+
Assert.IsNotNull (module, "no module");
348+
349+
var cl = module.Classes.FirstOrDefault (c => c.Name == "Foo");
350+
Assert.IsNotNull (cl, "no class");
351+
352+
var method = cl.Members.OfType<FunctionDeclaration> ().FirstOrDefault (fn => fn.Name == "DoSomething");
353+
Assert.IsNotNull (method, "no method");
354+
355+
Assert.AreEqual (1, method.Attributes.Count, "wrong number of attributes");
356+
357+
var attr = method.Attributes.FirstOrDefault (at => at.Name == "objc");
358+
Assert.IsNotNull (attr, "no objc attribute");
359+
var attrParam = attr.Parameters [0] as AttributeParameterLabel;
360+
Assert.IsNotNull (attrParam, "not a label");
361+
Assert.AreEqual (attrParam.Label, "narwhal", "wrong label");
362+
}
363+
364+
[Test]
365+
public void HasAvailableAttributeAll ()
366+
{
367+
var swiftCode = @"
368+
import Foundation
369+
370+
371+
public class Foo {
372+
public init () { }
373+
@available (*, unavailable)
374+
public func DoSomething () -> Int {
375+
return 1
376+
}
377+
}
378+
";
379+
SwiftInterfaceReflector reflector;
380+
var module = ReflectToModules (swiftCode, "SomeModule", out reflector).FirstOrDefault (mod => mod.Name == "SomeModule");
381+
Assert.IsNotNull (module, "no module");
382+
383+
var cl = module.Classes.FirstOrDefault (c => c.Name == "Foo");
384+
Assert.IsNotNull (cl, "no class");
385+
386+
var method = cl.Members.OfType<FunctionDeclaration> ().FirstOrDefault (fn => fn.Name == "DoSomething");
387+
Assert.IsNotNull (method, "no method");
388+
389+
Assert.AreEqual (1, method.Attributes.Count, "wrong number of attributes");
390+
var attr = method.Attributes [0];
391+
Assert.AreEqual (attr.Name, "available");
392+
Assert.AreEqual (3, attr.Parameters.Count, "wrong number of parameters");
393+
var label = attr.Parameters [0] as AttributeParameterLabel;
394+
Assert.IsNotNull (label, "not a label at 0");
395+
Assert.AreEqual ("*", label.Label, "not a star");
396+
label = attr.Parameters [1] as AttributeParameterLabel;
397+
Assert.IsNotNull (label, "not a label at 1");
398+
Assert.AreEqual (",", label.Label, "not a comma");
399+
label = attr.Parameters [2] as AttributeParameterLabel;
400+
Assert.IsNotNull (label, "not a label at 2");
401+
Assert.AreEqual ("unavailable", label.Label, "not unavailable");
402+
}
306403
}
307404
}

0 commit comments

Comments
 (0)