Merge pull request #961 from ermshiperete/bug-xamarin-18118
[mono.git] / mcs / class / System.Xaml / System.Xaml / XamlLanguage.cs
1 //
2 // Copyright (C) 2010 Novell Inc. http://novell.com
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //
23 using System;
24 using System.Collections.Generic;
25 using System.Collections.ObjectModel;
26 using System.Globalization;
27 using System.Linq;
28 using System.Reflection;
29 using System.Xaml.Schema;
30 using System.Windows.Markup;
31
32 [assembly:XmlnsDefinition (System.Xaml.XamlLanguage.Xaml2006Namespace, "System.Windows.Markup")] // FIXME: verify.
33
34 namespace System.Xaml
35 {
36         public static class XamlLanguage
37         {
38                 public const string Xaml2006Namespace = "http://schemas.microsoft.com/winfx/2006/xaml";
39                 public const string Xml1998Namespace = "http://www.w3.org/XML/1998/namespace";
40                 internal const string Xmlns2000Namespace = "http://www.w3.org/2000/xmlns/";
41
42                 // FIXME: I'm not sure if these "special names" should be resolved like this. I couldn't find any rule so far.
43                 internal static readonly SpecialTypeNameList SpecialNames;
44
45                 internal class SpecialTypeNameList : List<SpecialTypeName>
46                 {
47                         internal SpecialTypeNameList ()
48                         {
49                                 Add (new SpecialTypeName ("Member", XamlLanguage.Member));
50                                 Add (new SpecialTypeName ("Property", XamlLanguage.Property));
51                         }
52
53                         public XamlType Find (string name, string ns)
54                         {
55                                 if (ns != XamlLanguage.Xaml2006Namespace)
56                                         return null;
57                                 var stn = this.FirstOrDefault (s => s.Name == name);
58                                 return stn != null ? stn.Type : null;
59                         }
60                 }
61
62                 internal class SpecialTypeName
63                 {
64                         public SpecialTypeName (string name, XamlType type)
65                         {
66                                 Name = name;
67                                 Type = type;
68                         }
69                         
70                         public string Name { get; private set; }
71                         public XamlType Type { get; private set; }
72                 }
73
74                 static readonly XamlSchemaContext sctx = new XamlSchemaContext (new Assembly [] {typeof (XamlType).Assembly});
75
76                 static XamlType XT<T> ()
77                 {
78                         return sctx.GetXamlType (typeof (T));
79                 }
80
81                 internal static readonly bool InitializingDirectives;
82                 internal static readonly bool InitializingTypes;
83
84                 static XamlLanguage ()
85                 {
86                         InitializingTypes = true;
87
88                         // types
89
90                         Array = XT<ArrayExtension> ();
91                         Boolean = XT<bool> ();
92                         Byte = XT<byte> ();
93                         Char = XT<char> ();
94                         Decimal = XT<decimal> ();
95                         Double = XT<double> ();
96                         Int16 = XT<short> ();
97                         Int32 = XT<int> ();
98                         Int64 = XT<long> ();
99                         Member = XT<MemberDefinition> ();
100                         Null = XT<NullExtension> ();
101                         Object = XT<object> ();
102                         Property = XT<PropertyDefinition> ();
103                         Reference = XT<Reference> ();
104                         Single = XT<float> ();
105                         Static = XT<StaticExtension> ();
106                         String = XT<string> ();
107                         TimeSpan = XT<TimeSpan> ();
108                         Type = XT<TypeExtension> ();
109                         Uri = XT<Uri> ();
110                         XData = XT<XData> ();
111
112                         InitializingTypes = false;
113
114                         AllTypes = new ReadOnlyCollection<XamlType> (new XamlType [] {Array, Boolean, Byte, Char, Decimal, Double, Int16, Int32, Int64, Member, Null, Object, Property, Reference, Single, Static, String, TimeSpan, Type, Uri, XData});
115
116                         // directives
117
118                         // Looks like predefined XamlDirectives have no ValueSerializer. 
119                         // To handle this situation, differentiate them from non-primitive XamlMembers.
120                         InitializingDirectives = true;
121
122                         var nss = new string [] {XamlLanguage.Xaml2006Namespace};
123                         var nssXml = new string [] {XamlLanguage.Xml1998Namespace};
124
125                         Arguments = new XamlDirective (nss, "Arguments", XT<List<object>> (), null, AllowedMemberLocations.Any);
126                         AsyncRecords = new XamlDirective (nss, "AsyncRecords", XT<string> (), null, AllowedMemberLocations.Attribute);
127                         Base = new XamlDirective (nssXml, "base", XT<string> (), null, AllowedMemberLocations.Attribute);
128                         Class = new XamlDirective (nss, "Class", XT<string> (), null, AllowedMemberLocations.Attribute);
129                         ClassAttributes = new XamlDirective (nss, "ClassAttributes", XT<List<Attribute>> (), null, AllowedMemberLocations.MemberElement);
130                         ClassModifier = new XamlDirective (nss, "ClassModifier", XT<string> (), null, AllowedMemberLocations.Attribute);
131                         Code = new XamlDirective (nss, "Code", XT<string> (), null, AllowedMemberLocations.Attribute);
132                         ConnectionId = new XamlDirective (nss, "ConnectionId", XT<string> (), null, AllowedMemberLocations.Any);
133                         FactoryMethod = new XamlDirective (nss, "FactoryMethod", XT<string> (), null, AllowedMemberLocations.Any);
134                         FieldModifier = new XamlDirective (nss, "FieldModifier", XT<string> (), null, AllowedMemberLocations.Attribute);
135                         Initialization = new XamlDirective (nss, "_Initialization", XT<object> (), null, AllowedMemberLocations.Any);
136                         Items = new XamlDirective (nss, "_Items", XT<List<object>> (), null, AllowedMemberLocations.Any);
137                         Key = new XamlDirective (nss, "Key", XT<object> (), null, AllowedMemberLocations.Any);
138                         Lang = new XamlDirective (nssXml, "lang", XT<string> (), null, AllowedMemberLocations.Attribute);
139                         Members = new XamlDirective (nss, "Members", XT<List<MemberDefinition>> (), null, AllowedMemberLocations.MemberElement);
140                         Name = new XamlDirective (nss, "Name", XT<string> (), null, AllowedMemberLocations.Attribute);
141                         PositionalParameters = new XamlDirective (nss, "_PositionalParameters", XT<List<object>> (), null, AllowedMemberLocations.Any);
142                         Space = new XamlDirective (nssXml, "space", XT<string> (), null, AllowedMemberLocations.Attribute);
143                         Subclass = new XamlDirective (nss, "Subclass", XT<string> (), null, AllowedMemberLocations.Attribute);
144                         SynchronousMode = new XamlDirective (nss, "SynchronousMode", XT<string> (), null, AllowedMemberLocations.Attribute);
145                         Shared = new XamlDirective (nss, "Shared", XT<string> (), null, AllowedMemberLocations.Attribute);
146                         TypeArguments = new XamlDirective (nss, "TypeArguments", XT<string> (), null, AllowedMemberLocations.Attribute);
147                         Uid = new XamlDirective (nss, "Uid", XT<string> (), null, AllowedMemberLocations.Attribute);
148                         UnknownContent = new XamlDirective (nss, "_UnknownContent", XT<object> (), null, AllowedMemberLocations.MemberElement) { InternalIsUnknown = true };
149
150                         AllDirectives = new ReadOnlyCollection<XamlDirective> (new XamlDirective [] {Arguments, AsyncRecords, Base, Class, ClassAttributes, ClassModifier, Code, ConnectionId, FactoryMethod, FieldModifier, Initialization, Items, Key, Lang, Members, Name, PositionalParameters, Space, Subclass, SynchronousMode, Shared, TypeArguments, Uid, UnknownContent});
151
152                         InitializingDirectives = false;
153
154                         SpecialNames = new SpecialTypeNameList ();
155                 }
156
157                 static readonly string [] xaml_nss = new string [] {Xaml2006Namespace};
158
159                 public static IList<string> XamlNamespaces {
160                         get { return xaml_nss; }
161                 }
162
163                 static readonly string [] xml_nss = new string [] {Xml1998Namespace};
164
165                 public static IList<string> XmlNamespaces {
166                         get { return xml_nss; }
167                 }
168
169                 public static ReadOnlyCollection<XamlDirective> AllDirectives { get; private set; }
170
171                 public static XamlDirective Arguments { get; private set; }
172                 public static XamlDirective AsyncRecords { get; private set; }
173                 public static XamlDirective Base { get; private set; }
174                 public static XamlDirective Class { get; private set; }
175                 public static XamlDirective ClassAttributes { get; private set; }
176                 public static XamlDirective ClassModifier { get; private set; }
177                 public static XamlDirective Code { get; private set; }
178                 public static XamlDirective ConnectionId { get; private set; }
179                 public static XamlDirective FactoryMethod { get; private set; }
180                 public static XamlDirective FieldModifier { get; private set; }
181                 public static XamlDirective Initialization { get; private set; }
182                 public static XamlDirective Items { get; private set; }
183                 public static XamlDirective Key { get; private set; }
184                 public static XamlDirective Lang { get; private set; }
185                 public static XamlDirective Members { get; private set; }
186                 public static XamlDirective Name { get; private set; }
187                 public static XamlDirective PositionalParameters { get; private set; }
188                 public static XamlDirective Subclass { get; private set; }
189                 public static XamlDirective SynchronousMode { get; private set; }
190                 public static XamlDirective Shared { get; private set; }
191                 public static XamlDirective Space { get; private set; }
192                 public static XamlDirective TypeArguments { get; private set; }
193                 public static XamlDirective Uid { get; private set; }
194                 public static XamlDirective UnknownContent { get; private set; }
195
196                 public static ReadOnlyCollection<XamlType> AllTypes { get; private set; }
197
198                 public static XamlType Array { get; private set; }
199                 public static XamlType Boolean { get; private set; }
200                 public static XamlType Byte { get; private set; }
201                 public static XamlType Char { get; private set; }
202                 public static XamlType Decimal { get; private set; }
203                 public static XamlType Double { get; private set; }
204                 public static XamlType Int16 { get; private set; }
205                 public static XamlType Int32 { get; private set; }
206                 public static XamlType Int64 { get; private set; }
207                 public static XamlType Member { get; private set; }
208                 public static XamlType Null { get; private set; }
209                 public static XamlType Object { get; private set; }
210                 public static XamlType Property { get; private set; }
211                 public static XamlType Reference { get; private set; }
212                 public static XamlType Single { get; private set; }
213                 public static XamlType Static { get; private set; }
214                 public static XamlType String { get; private set; }
215                 public static XamlType TimeSpan { get; private set; }
216                 public static XamlType Type { get; private set; }
217                 public static XamlType Uri { get; private set; }
218                 public static XamlType XData { get; private set; }
219
220                 internal static bool IsValidXamlName (string name)
221                 {
222                         if (string.IsNullOrEmpty (name))
223                                 return false;
224                         if (!IsValidXamlName (name [0], true))
225                                 return false;
226                         foreach (char c in name)
227                                 if (!IsValidXamlName (c, false))
228                                         return false;
229                         return true;
230                 }
231
232                 static bool IsValidXamlName (char c, bool first)
233                 {
234                         if (c == '_')
235                                 return true;
236                         switch (char.GetUnicodeCategory (c)) {
237                         case UnicodeCategory.LowercaseLetter:
238                         case UnicodeCategory.UppercaseLetter:
239                         case UnicodeCategory.TitlecaseLetter:
240                         case UnicodeCategory.OtherLetter:
241                         case UnicodeCategory.LetterNumber:
242                                 return true;
243                         case UnicodeCategory.NonSpacingMark:
244                         case UnicodeCategory.DecimalDigitNumber:
245                         case UnicodeCategory.SpacingCombiningMark:
246                         case UnicodeCategory.ModifierLetter:
247                                 return !first;
248                         default:
249                                 return false;
250                         }
251                 }
252         }
253 }