PageRenderTime 54ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/Dependencies/boo/src/Boo.Lang.Compiler/Steps/BindAndApplyAttributes.cs

https://github.com/w4x/boolangstudio
C# | 418 lines | 339 code | 48 blank | 31 comment | 50 complexity | 7117f1c8c9316b17efc03a9463189a6b MD5 | raw file
Possible License(s): GPL-2.0
  1. #region license
  2. // Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without modification,
  6. // are permitted provided that the following conditions are met:
  7. //
  8. // * Redistributions of source code must retain the above copyright notice,
  9. // this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above copyright notice,
  11. // this list of conditions and the following disclaimer in the documentation
  12. // and/or other materials provided with the distribution.
  13. // * Neither the name of Rodrigo B. de Oliveira nor the names of its
  14. // contributors may be used to endorse or promote products derived from this
  15. // software without specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  18. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  21. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  25. // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. #endregion
  28. namespace Boo.Lang.Compiler.Steps
  29. {
  30. using System;
  31. using Boo.Lang.Compiler.Ast;
  32. using Boo.Lang.Compiler;
  33. using Boo.Lang.Compiler.TypeSystem;
  34. using Boo.Lang.Compiler.Util;
  35. using Reflection = System.Reflection;
  36. class ApplyAttributeTask : ITask
  37. {
  38. CompilerContext _context;
  39. Boo.Lang.Compiler.Ast.Attribute _attribute;
  40. Type _type;
  41. Node _targetNode;
  42. public ApplyAttributeTask(CompilerContext context, Boo.Lang.Compiler.Ast.Attribute attribute, Type type)
  43. {
  44. _context = context;
  45. _attribute = attribute;
  46. _type = type;
  47. _targetNode = GetTargetNode();
  48. }
  49. private Node GetTargetNode()
  50. {
  51. Module module = _attribute.ParentNode as Module;
  52. if (module != null && module.AssemblyAttributes.ContainsNode(_attribute))
  53. {
  54. return module.ParentNode;
  55. }
  56. return _attribute.ParentNode;
  57. }
  58. public void Execute()
  59. {
  60. try
  61. {
  62. IAstAttribute aa = CreateAstAttributeInstance();
  63. if (null != aa)
  64. {
  65. aa.Initialize(_context);
  66. using (aa)
  67. {
  68. aa.Apply(_targetNode);
  69. }
  70. }
  71. }
  72. catch (Exception x)
  73. {
  74. _context.TraceError(x);
  75. _context.Errors.Add(CompilerErrorFactory.AttributeApplicationError(x, _attribute, _type));
  76. System.Console.WriteLine(x.StackTrace);
  77. }
  78. }
  79. public IAstAttribute CreateAstAttributeInstance()
  80. {
  81. object[] parameters = _attribute.Arguments.Count > 0 ? _attribute.Arguments.ToArray() : new object[0];
  82. IAstAttribute aa = null;
  83. try
  84. {
  85. aa = (IAstAttribute)Activator.CreateInstance(_type, parameters);
  86. }
  87. catch (MissingMethodException x)
  88. {
  89. _context.Errors.Add(CompilerErrorFactory.MissingConstructor(x, _attribute, _type, parameters));
  90. return null;
  91. }
  92. aa.Attribute = _attribute;
  93. if (_attribute.NamedArguments.Count > 0)
  94. {
  95. bool initialized = true;
  96. foreach (ExpressionPair p in _attribute.NamedArguments)
  97. {
  98. bool success = SetFieldOrProperty(aa, p);
  99. initialized = initialized && success;
  100. }
  101. if (!initialized)
  102. {
  103. return null;
  104. }
  105. }
  106. return aa;
  107. }
  108. bool SetFieldOrProperty(IAstAttribute aa, ExpressionPair p)
  109. {
  110. ReferenceExpression name = p.First as ReferenceExpression;
  111. if (null == name)
  112. {
  113. _context.Errors.Add(CompilerErrorFactory.NamedParameterMustBeIdentifier(p));
  114. return false;
  115. }
  116. else
  117. {
  118. Reflection.MemberInfo[] members = _type.FindMembers(
  119. Reflection.MemberTypes.Property | Reflection.MemberTypes.Field,
  120. Reflection.BindingFlags.Instance | Reflection.BindingFlags.Public,
  121. Type.FilterName, name.Name);
  122. if (members.Length > 0)
  123. {
  124. if (members.Length > 1)
  125. {
  126. _context.Errors.Add(CompilerErrorFactory.AmbiguousReference(name, members));
  127. return false;
  128. }
  129. else
  130. {
  131. Reflection.MemberInfo m = members[0];
  132. Reflection.PropertyInfo property = m as Reflection.PropertyInfo;
  133. if (null != property)
  134. {
  135. property.SetValue(aa, p.Second, null);
  136. }
  137. else
  138. {
  139. Reflection.FieldInfo field = m as Reflection.FieldInfo;
  140. if (null != field)
  141. {
  142. field.SetValue(aa, p.Second);
  143. }
  144. else
  145. {
  146. throw new InvalidOperationException();
  147. }
  148. }
  149. }
  150. }
  151. else
  152. {
  153. _context.Errors.Add(CompilerErrorFactory.NotAPublicFieldOrProperty(name, name.Name, _type.FullName));
  154. return false;
  155. }
  156. }
  157. return true;
  158. }
  159. }
  160. /// <summary>
  161. /// Step 2. Processes AST attributes.
  162. /// </summary>
  163. public class BindAndApplyAttributes : AbstractNamespaceSensitiveTransformerCompilerStep
  164. {
  165. TaskList _tasks;
  166. System.Text.StringBuilder _buffer = new System.Text.StringBuilder();
  167. IType _astAttributeInterface;
  168. Boo.Lang.List _elements = new Boo.Lang.List();
  169. public BindAndApplyAttributes()
  170. {
  171. _tasks = new TaskList();
  172. }
  173. override public void Run()
  174. {
  175. _astAttributeInterface = TypeSystemServices.Map(typeof(IAstAttribute));
  176. int step = 0;
  177. while (step < Parameters.MaxAttributeSteps)
  178. {
  179. Visit(CompileUnit);
  180. if (0 == _tasks.Count)
  181. {
  182. break;
  183. }
  184. _tasks.Flush();
  185. ++step;
  186. }
  187. }
  188. override public void OnModule(Boo.Lang.Compiler.Ast.Module module)
  189. {
  190. EnterNamespace((INamespace)TypeSystemServices.GetEntity(module));
  191. try
  192. {
  193. Visit(module.Members);
  194. Visit(module.Globals);
  195. Visit(module.Attributes);
  196. Visit(module.AssemblyAttributes);
  197. }
  198. finally
  199. {
  200. LeaveNamespace();
  201. }
  202. }
  203. void VisitTypeDefinition(TypeDefinition node)
  204. {
  205. Visit(node.Members);
  206. Visit(node.Attributes);
  207. }
  208. override public void OnClassDefinition(ClassDefinition node)
  209. {
  210. VisitTypeDefinition(node);
  211. }
  212. override public void OnInterfaceDefinition(InterfaceDefinition node)
  213. {
  214. VisitTypeDefinition(node);
  215. }
  216. override public void OnStructDefinition(StructDefinition node)
  217. {
  218. VisitTypeDefinition(node);
  219. }
  220. override public void OnEnumDefinition(EnumDefinition node)
  221. {
  222. VisitTypeDefinition(node);
  223. }
  224. override public void OnBlock(Block node)
  225. {
  226. // No need to visit blocks
  227. }
  228. override public void OnAttribute(Boo.Lang.Compiler.Ast.Attribute attribute)
  229. {
  230. if (null != attribute.Entity)
  231. {
  232. return;
  233. }
  234. _elements.Clear();
  235. if (!NameResolutionService.ResolveQualifiedName(_elements, BuildAttributeName(attribute.Name, true)))
  236. {
  237. if (!NameResolutionService.ResolveQualifiedName(_elements, BuildAttributeName(attribute.Name, false)))
  238. {
  239. NameResolutionService.ResolveQualifiedName(_elements, attribute.Name);
  240. }
  241. }
  242. if (_elements.Count == 0)
  243. {
  244. string suggestion = NameResolutionService.GetMostSimilarTypeName(BuildAttributeName(attribute.Name, true));
  245. if (null == suggestion)
  246. suggestion = NameResolutionService.GetMostSimilarTypeName(BuildAttributeName(attribute.Name, false));
  247. Error(attribute, CompilerErrorFactory.UnknownAttribute(attribute, attribute.Name, suggestion));
  248. return;
  249. }
  250. if (_elements.Count > 1)
  251. {
  252. Error(attribute, CompilerErrorFactory.AmbiguousReference(
  253. attribute,
  254. attribute.Name,
  255. _elements));
  256. return;
  257. }
  258. // if _elements.Count == 1
  259. IEntity tag = (IEntity)_elements[0];
  260. if (EntityType.Type != tag.EntityType)
  261. {
  262. Error(attribute, CompilerErrorFactory.NameNotType(attribute, attribute.Name, null));
  263. return;
  264. }
  265. IType attributeType = ((ITypedEntity)tag).Type;
  266. if (IsAstAttribute(attributeType))
  267. {
  268. ExternalType externalType = attributeType as ExternalType;
  269. if (null == externalType)
  270. {
  271. Error(attribute, CompilerErrorFactory.AstAttributeMustBeExternal(attribute, attributeType.FullName));
  272. }
  273. else
  274. {
  275. ScheduleAttributeApplication(attribute, externalType.ActualType);
  276. RemoveCurrentNode();
  277. }
  278. }
  279. else
  280. {
  281. if (!IsSystemAttribute(attributeType))
  282. {
  283. Error(attribute, CompilerErrorFactory.TypeNotAttribute(attribute, attributeType.FullName));
  284. }
  285. else
  286. {
  287. // remember the attribute's type
  288. attribute.Name = attributeType.FullName;
  289. attribute.Entity = attributeType;
  290. CheckAttributeParameters(attribute);
  291. }
  292. }
  293. }
  294. private void CheckAttributeParameters(Boo.Lang.Compiler.Ast.Attribute node)
  295. {
  296. foreach(Expression e in node.Arguments)
  297. {
  298. if (e.NodeType == NodeType.BinaryExpression
  299. && ((BinaryExpression)e).Operator == BinaryOperatorType.Assign)
  300. {
  301. Error(node, CompilerErrorFactory.ColonInsteadOfEquals(node));
  302. }
  303. }
  304. }
  305. override public void LeaveProperty(Property node)
  306. {
  307. if (node.Name == "self")
  308. {
  309. node.Name = "Item";
  310. }
  311. if (node.Name == "Item" && node.Parameters.Count > 0 && !node.IsStatic)
  312. {
  313. TypeDefinition t = node.ParentNode as TypeDefinition;
  314. if (t != null)
  315. {
  316. bool already_has_attribute = false;
  317. foreach(Boo.Lang.Compiler.Ast.Attribute a in t.Attributes)
  318. {
  319. if (a.Name.IndexOf("DefaultMember") >= 0)
  320. {
  321. already_has_attribute = true;
  322. break;
  323. }
  324. }
  325. if (!already_has_attribute)
  326. {
  327. Boo.Lang.Compiler.Ast.Attribute att = new Boo.Lang.Compiler.Ast.Attribute(t.LexicalInfo);
  328. att.Name = Types.DefaultMemberAttribute.FullName;
  329. att.Arguments.Add(new StringLiteralExpression(node.Name));
  330. t.Attributes.Add(att);
  331. Visit(att);
  332. }
  333. }
  334. }
  335. }
  336. void Error(Boo.Lang.Compiler.Ast.Attribute node, CompilerError error)
  337. {
  338. node.Entity = TypeSystemServices.ErrorEntity;
  339. Errors.Add(error);
  340. }
  341. void ScheduleAttributeApplication(Boo.Lang.Compiler.Ast.Attribute attribute, Type type)
  342. {
  343. _tasks.Add(new ApplyAttributeTask(_context, attribute, type));
  344. }
  345. string BuildAttributeName(string name, bool forcePascalNaming)
  346. {
  347. _buffer.Length = 0;
  348. if (forcePascalNaming && !Char.IsUpper(name[0]))
  349. {
  350. _buffer.Append(Char.ToUpper(name[0]));
  351. _buffer.Append(name.Substring(1));
  352. _buffer.Append("Attribute");
  353. }
  354. else
  355. {
  356. _buffer.Append(name);
  357. _buffer.Append("Attribute");
  358. }
  359. return _buffer.ToString();
  360. }
  361. bool IsSystemAttribute(IType type)
  362. {
  363. return TypeSystemServices.IsAttribute(type);
  364. }
  365. bool IsAstAttribute(IType type)
  366. {
  367. return _astAttributeInterface.IsAssignableFrom(type);
  368. }
  369. }
  370. }