5 // Copyright (c) 2007-2008 Jiri Moudry, Pascal Craponne
\r
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
\r
8 // of this software and associated documentation files (the "Software"), to deal
\r
9 // in the Software without restriction, including without limitation the rights
\r
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
\r
11 // copies of the Software, and to permit persons to whom the Software is
\r
12 // furnished to do so, subject to the following conditions:
\r
14 // The above copyright notice and this permission notice shall be included in
\r
15 // all copies or substantial portions of the Software.
\r
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
\r
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
\r
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
\r
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\r
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
\r
27 using System.Collections.Generic;
\r
32 using DbMetal.Generator;
\r
34 namespace DbMetal.Generator
\r
37 /// Base class for writing code.
\r
38 /// Divided in 3 Parts:
\r
39 /// - Code line writing (with indentation)
\r
40 /// - Code formatting (returning a literal type)
\r
41 /// - Code writing (comment line, field, property, event...)
\r
43 public abstract class CodeWriter : TextWriter
\r
45 // required by TextWriter
\r
46 public override Encoding Encoding
\r
50 return TextWriter.Encoding;
\r
54 public string IndentationPattern { get; set; }
\r
56 private readonly StringBuilder buffer = new StringBuilder(10 << 10);
\r
57 private int currentindentation = 0;
\r
59 protected TextWriter TextWriter;
\r
61 protected CodeWriter(TextWriter textWriter)
\r
63 IndentationPattern = "\t";
\r
64 TextWriter = textWriter;
\r
69 protected bool IsFullLine()
\r
71 int endIndex = buffer.Length - CoreNewLine.Length;
\r
74 for (int i = 0; i < CoreNewLine.Length; i++)
\r
76 if (buffer[endIndex + i] != CoreNewLine[i])
\r
82 protected string GetLine()
\r
84 string line = buffer.ToString();
\r
85 buffer.Remove(0, buffer.Length);
\r
89 protected abstract bool MustIndent(string line);
\r
90 protected abstract bool MustUnindent(string line);
\r
93 /// In the end, all output comes to this
\r
95 /// <param name="value"></param>
\r
96 public override void Write(char value)
\r
98 buffer.Append(value);
\r
101 string line = GetLine();
\r
102 string rawLine = Trim(line);
\r
103 // unindent before...
\r
104 if (MustUnindent(rawLine))
\r
105 currentindentation--;
\r
106 WriteLine(rawLine, currentindentation);
\r
108 if (MustIndent(rawLine))
\r
109 currentindentation++;
\r
113 protected virtual string Trim(string line)
\r
115 return line.Trim();
\r
118 protected virtual void WriteLine(string rawLine, int indentation)
\r
120 if (!string.IsNullOrEmpty(rawLine))
\r
122 for (int indentationCount = 0; indentationCount < indentation; indentationCount++)
\r
124 TextWriter.Write(IndentationPattern);
\r
127 TextWriter.WriteLine(rawLine);
\r
130 public virtual string GetEnumType(string name)
\r
135 public abstract IDisposable WriteEnum(SpecificationDefinition specificationDefinition, string name);
\r
137 public virtual void WriteEnum(SpecificationDefinition specificationDefinition, string name, IDictionary<string, int> values)
\r
139 using (WriteEnum(specificationDefinition, name))
\r
141 var orderedValues = from nv in values orderby nv.Value select nv;
\r
142 int currentValue = 1;
\r
143 foreach (var nameValue in orderedValues)
\r
145 if (nameValue.Value == currentValue)
\r
146 WriteLine(string.Format("{0},", nameValue.Key));
\r
149 currentValue = nameValue.Value;
\r
150 WriteLine(string.Format("{0} = {1},", nameValue.Key, nameValue.Value));
\r
159 #region Code generation
\r
161 // A language sometimes generates complementary text, such as "{" and "}", or "#region"/"#endregion"
\r
163 protected class NestedInstruction : IDisposable
\r
165 private readonly Action endAction;
\r
167 public NestedInstruction(Action end)
\r
172 public void Dispose()
\r
179 /// Registers an "end block" (written on Dispose() call)
\r
181 /// <param name="end"></param>
\r
182 /// <returns></returns>
\r
183 protected IDisposable EndAction(Action end)
\r
185 return new NestedInstruction(end);
\r
190 #region Code generation - Language write
\r
192 public abstract void WriteCommentLine(string line);
\r
193 public virtual void WriteCommentLines(string comments)
\r
195 string[] commentLines = comments.Split('\n');
\r
196 foreach (string commentLine in commentLines)
\r
198 WriteCommentLine(commentLine.TrimEnd());
\r
203 /// Registers namespace to be written
\r
205 /// <param name="name"></param>
\r
206 public abstract void WriteUsingNamespace(string name);
\r
207 public abstract IDisposable WriteNamespace(string name);
\r
208 public abstract IDisposable WriteClass(SpecificationDefinition specificationDefinition, string name,
\r
209 string baseClass, params string[] interfaces);
\r
211 public abstract IDisposable WriteRegion(string name);
\r
212 public abstract IDisposable WriteAttribute(AttributeDefinition attributeDefinition);
\r
214 public abstract IDisposable WriteCtor(SpecificationDefinition specificationDefinition, string name,
\r
215 ParameterDefinition[] parameters, IList<string> baseCallParameters);
\r
216 public abstract IDisposable WriteMethod(SpecificationDefinition specificationDefinition, string name, Type returnType,
\r
217 params ParameterDefinition[] parameters);
\r
219 public abstract IDisposable WriteProperty(SpecificationDefinition specificationDefinition, string name, string propertyType);
\r
220 public abstract void WriteAutomaticPropertyGetSet();
\r
221 public abstract IDisposable WritePropertyGet();
\r
222 public abstract IDisposable WritePropertySet();
\r
224 public abstract void WritePropertyWithBackingField(SpecificationDefinition specificationDefinition, string name, string propertyType, bool privateSetter);
\r
225 public virtual void WritePropertyWithBackingField(SpecificationDefinition specificationDefinition, string name, string propertyType)
\r
227 WritePropertyWithBackingField(specificationDefinition, name, propertyType, false);
\r
230 public abstract void WriteField(SpecificationDefinition specificationDefinition, string name, string fieldType);
\r
232 public abstract void WriteEvent(SpecificationDefinition specificationDefinition, string name, string eventDelegate);
\r
234 public abstract IDisposable WriteIf(string expression);
\r
238 #region Code generation - Language construction
\r
240 public abstract string GetCastExpression(string value, string castType, bool hardCast);
\r
242 public virtual string GetLiteralValue(object value)
\r
245 return GetNullExpression();
\r
246 if (value is string)
\r
247 return string.Format("\"{0}\"", value);
\r
248 return value.ToString();
\r
251 public virtual string GetLiteralType(Type type)
\r
256 public virtual string GetLiteralFullType(Type type)
\r
258 return type.FullName;
\r
261 public virtual string GetMemberExpression(string obj, string member)
\r
263 return string.Format("{0}.{1}", obj, member);
\r
266 public virtual string GetReturnStatement(string expression)
\r
268 if (expression == null)
\r
269 return GetStatement("return");
\r
270 return GetStatement(string.Format("return {0}", expression));
\r
274 /// Returns the specified variable as a safe expression
\r
276 /// <param name="name"></param>
\r
277 /// <returns></returns>
\r
278 public abstract string GetVariableExpression(string name);
\r
280 public virtual string GetNewExpression(string ctor)
\r
282 return string.Format("new {0}", ctor);
\r
285 public virtual string GetThisExpression()
\r
290 public virtual string GetDeclarationExpression(string variable, string type)
\r
292 return string.Format("{0} {1}", type, variable);
\r
295 public virtual string GetAssignmentExpression(string variable, string expression)
\r
297 return string.Format("{0} = {1}", variable, expression);
\r
300 public abstract string GetArray(string array, string literalIndex);
\r
302 public virtual string GetMethodCallExpression(string method, params string[] literalParameters)
\r
304 return string.Format("{0}({1})", method, string.Join(", ", literalParameters));
\r
307 public virtual string GetStatement(string expression)
\r
312 public abstract string GetPropertySetValueExpression();
\r
314 public abstract string GetNullExpression();
\r
316 public abstract string GetGenericName(string baseName, string type);
\r
318 public abstract string GetDifferentExpression(string a, string b);
\r
319 public abstract string GetEqualExpression(string a, string b);
\r
321 public abstract string GetXOrExpression(string a, string b);
\r
322 public abstract string GetAndExpression(string a, string b);
\r
324 public abstract string GetTernaryExpression(string conditionExpression, string trueExpression, string falseExpression);
\r
326 public abstract string GetNullValueExpression(string literalType);
\r
331 /// Returns a code that throw the given expression
\r
333 /// <param name="throwExpression"></param>
\r
334 /// <returns></returns>
\r
335 public abstract string GetThrowStatement(string throwExpression);
\r
338 /// Returns a declaration and assignement expression
\r
340 /// <param name="variableType"></param>
\r
341 /// <param name="variableName"></param>
\r
342 /// <param name="expression"></param>
\r
343 /// <returns></returns>
\r
344 public abstract string GetVariableDeclarationInitialization(string variableType, string variableName, string expression);
\r
347 /// Writes the raw if.
\r
349 /// <param name="expression">The expression.</param>
\r
350 public abstract void WriteRawIf(string expression);
\r
353 /// Writes the raw else.
\r
355 public abstract void WriteRawElse();
\r
358 /// Writes the raw endif.
\r
360 public abstract void WriteRawEndif();
\r