2 // Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
3 // All rights reserved.
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
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.
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.
30 using Boo
.Lang
.Compiler
.Ast
;
35 /// Creates a property over a field.
37 public class PropertyAttribute
: Boo
.Lang
.Compiler
.AbstractAstAttribute
39 protected ReferenceExpression _propertyName
;
41 protected Expression _setPreCondition
;
43 protected BoolLiteralExpression _protected
;
45 protected BoolLiteralExpression _observable
;
47 protected ListLiteralExpression _attributes
;
49 public PropertyAttribute(ReferenceExpression propertyName
) : this(propertyName
, null)
53 public PropertyAttribute(ReferenceExpression propertyName
, Expression setPreCondition
)
55 if (null == propertyName
)
57 throw new ArgumentNullException("propertyName");
59 _propertyName
= propertyName
;
60 _setPreCondition
= setPreCondition
;
63 public BoolLiteralExpression Protected
76 protected bool IsProtected
80 if (null == _protected
)
84 return _protected
.Value
;
88 public BoolLiteralExpression Observable
101 protected bool IsObservable
105 if (null == _observable
)
109 return _observable
.Value
;
113 protected string ChangedEventName
117 return _propertyName
.Name
+ "Changed";
121 public ListLiteralExpression Attributes
134 override public void Apply(Node node
)
136 Field f
= node
as Field
;
139 InvalidNodeForAttribute("Field");
143 Property p
= new Property();
146 p
.Modifiers
|= TypeMemberModifiers
.Static
;
150 p
.Modifiers
|= TypeMemberModifiers
.Protected
;
152 p
.Name
= _propertyName
.Name
;
154 p
.Getter
= CreateGetter(f
);
155 p
.Setter
= CreateSetter(f
);
156 p
.LexicalInfo
= LexicalInfo
;
158 if (Attributes
!= null && Attributes
.Items
.Count
> 0)
160 foreach (Expression item
in Attributes
.Items
)
162 p
.Attributes
.Add(ConvertExpressionToAttribute(item
));
166 f
.DeclaringType
.Members
.Add(p
);
170 f
.DeclaringType
.Members
.Add(CreateChangedEvent(f
));
174 static public Boo
.Lang
.Compiler
.Ast
.Attribute
ConvertExpressionToAttribute(
177 Boo
.Lang
.Compiler
.Ast
.Attribute att
=
178 new Boo
.Lang
.Compiler
.Ast
.Attribute(item
.LexicalInfo
);
179 if (item
is MethodInvocationExpression
)
181 MethodInvocationExpression m
= (MethodInvocationExpression
)item
;
182 att
.Name
= m
.Target
.ToString();
183 att
.Arguments
= m
.Arguments
;
184 att
.NamedArguments
= m
.NamedArguments
;
188 att
.Name
= item
.ToString();
193 virtual protected Method
CreateGetter(Field f
)
197 Method getter
= new Method();
199 getter
.Body
.Statements
.Add(
202 new ReferenceExpression(f
.Name
),
208 virtual protected Method
CreateSetter(Field f
)
210 Method setter
= new Method();
213 if (null != _setPreCondition
)
217 _setPreCondition
.LexicalInfo
,
218 AstUtil
.CreateMethodInvocationExpression(
219 AstUtil
.CreateReferenceExpression("System.ArgumentException"),
220 new StringLiteralExpression("precondition '" +
221 _setPreCondition
.ToString() +
223 new StatementModifier(
224 StatementModifierType
.Unless
,
228 new BinaryExpression(
230 BinaryOperatorType
.Assign
,
231 new MemberReferenceExpression(
234 new ReferenceExpression("value")
240 MethodInvocationExpression mie
= new MethodInvocationExpression(
241 new ReferenceExpression(ChangedEventName
));
242 mie
.Arguments
.Add(new SelfLiteralExpression());
244 new MemberReferenceExpression(
245 new MemberReferenceExpression(
246 new ReferenceExpression("System"),
249 setter
.Body
.Add(mie
);
254 private Expression
CreateRefTarget(Field f
)
256 if (f
.IsStatic
) return new ReferenceExpression(LexicalInfo
, f
.DeclaringType
.Name
);
257 return new SelfLiteralExpression(LexicalInfo
);
260 protected Event
CreateChangedEvent(Field f
)
262 Event e
= new Event(_observable
.LexicalInfo
);
263 e
.Name
= ChangedEventName
;
264 e
.Type
= CodeBuilder
.CreateTypeReference(f
.LexicalInfo
, typeof(System
.EventHandler
));