CodeGenerator.cs 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266
  1. //
  2. // System.CodeDom.Compiler.CodeGenerator.cs
  3. //
  4. // Authors:
  5. // Miguel de Icaza ([email protected])
  6. // Daniel Stodden ([email protected])
  7. // Gonzalo Paniagua Javier ([email protected])
  8. // Andreas Nahr ([email protected])
  9. // Marek Safar ([email protected])
  10. //
  11. // (C) 2001-2003 Ximian, Inc.
  12. //
  13. //
  14. // Permission is hereby granted, free of charge, to any person obtaining
  15. // a copy of this software and associated documentation files (the
  16. // "Software"), to deal in the Software without restriction, including
  17. // without limitation the rights to use, copy, modify, merge, publish,
  18. // distribute, sublicense, and/or sell copies of the Software, and to
  19. // permit persons to whom the Software is furnished to do so, subject to
  20. // the following conditions:
  21. //
  22. // The above copyright notice and this permission notice shall be
  23. // included in all copies or substantial portions of the Software.
  24. //
  25. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  26. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  27. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  28. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  29. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  30. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  31. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  32. //
  33. using System.Globalization;
  34. using System.CodeDom;
  35. using System.Reflection;
  36. using System.IO;
  37. using System.Collections;
  38. namespace System.CodeDom.Compiler {
  39. public abstract class CodeGenerator : ICodeGenerator
  40. {
  41. private IndentedTextWriter output;
  42. private CodeGeneratorOptions options;
  43. private CodeTypeMember currentMember;
  44. private CodeTypeDeclaration currentType;
  45. //
  46. // Constructors
  47. //
  48. protected CodeGenerator()
  49. {
  50. }
  51. //
  52. // Properties
  53. //
  54. protected CodeTypeMember CurrentMember {
  55. get {
  56. return currentMember;
  57. }
  58. }
  59. protected string CurrentMemberName {
  60. get {
  61. if (currentType == null)
  62. return null;
  63. return currentMember.Name;
  64. }
  65. }
  66. protected string CurrentTypeName {
  67. get {
  68. if (currentType == null)
  69. return null;
  70. return currentType.Name;
  71. }
  72. }
  73. protected int Indent {
  74. get {
  75. return output.Indent;
  76. }
  77. set {
  78. output.Indent = value;
  79. }
  80. }
  81. protected bool IsCurrentClass {
  82. get {
  83. if (currentType == null)
  84. return false;
  85. return currentType.IsClass && !(currentType is CodeTypeDelegate);
  86. }
  87. }
  88. protected bool IsCurrentDelegate {
  89. get {
  90. return currentType is CodeTypeDelegate;
  91. }
  92. }
  93. protected bool IsCurrentEnum {
  94. get {
  95. if (currentType == null)
  96. return false;
  97. return currentType.IsEnum;
  98. }
  99. }
  100. protected bool IsCurrentInterface {
  101. get {
  102. if (currentType == null)
  103. return false;
  104. return currentType.IsInterface;
  105. }
  106. }
  107. protected bool IsCurrentStruct {
  108. get {
  109. if (currentType == null)
  110. return false;
  111. return currentType.IsStruct;
  112. }
  113. }
  114. protected abstract string NullToken {
  115. get;
  116. }
  117. protected CodeGeneratorOptions Options {
  118. get {
  119. return options;
  120. }
  121. }
  122. protected TextWriter Output {
  123. get {
  124. return output;
  125. }
  126. }
  127. //
  128. // Methods
  129. //
  130. protected virtual void ContinueOnNewLine (string st)
  131. {
  132. output.WriteLine (st);
  133. }
  134. /*
  135. * Code Generation methods
  136. */
  137. protected abstract void GenerateArgumentReferenceExpression (CodeArgumentReferenceExpression e);
  138. protected abstract void GenerateArrayCreateExpression (CodeArrayCreateExpression e);
  139. protected abstract void GenerateArrayIndexerExpression (CodeArrayIndexerExpression e);
  140. protected abstract void GenerateAssignStatement (CodeAssignStatement s);
  141. protected abstract void GenerateAttachEventStatement (CodeAttachEventStatement s);
  142. protected abstract void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes);
  143. protected abstract void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes);
  144. protected abstract void GenerateBaseReferenceExpression (CodeBaseReferenceExpression e);
  145. protected virtual void GenerateBinaryOperatorExpression (CodeBinaryOperatorExpression e)
  146. {
  147. output.Write ('(');
  148. GenerateExpression (e.Left);
  149. output.Write (' ');
  150. OutputOperator (e.Operator);
  151. output.Write (' ');
  152. GenerateExpression (e.Right);
  153. output.Write (')');
  154. }
  155. protected abstract void GenerateCastExpression (CodeCastExpression e);
  156. protected abstract void GenerateComment (CodeComment comment);
  157. protected virtual void GenerateCommentStatement (CodeCommentStatement statement)
  158. {
  159. GenerateComment (statement.Comment);
  160. }
  161. protected virtual void GenerateCommentStatements (CodeCommentStatementCollection statements)
  162. {
  163. foreach (CodeCommentStatement comment in statements)
  164. GenerateCommentStatement (comment);
  165. }
  166. protected virtual void GenerateCompileUnit (CodeCompileUnit compileUnit)
  167. {
  168. GenerateCompileUnitStart (compileUnit);
  169. CodeAttributeDeclarationCollection attributes = compileUnit.AssemblyCustomAttributes;
  170. if (attributes.Count != 0) {
  171. foreach (CodeAttributeDeclaration att in attributes) {
  172. GenerateAttributeDeclarationsStart (attributes);
  173. output.Write ("assembly: ");
  174. OutputAttributeDeclaration (att);
  175. GenerateAttributeDeclarationsEnd (attributes);
  176. }
  177. output.WriteLine ();
  178. }
  179. foreach (CodeNamespace ns in compileUnit.Namespaces)
  180. GenerateNamespace (ns);
  181. GenerateCompileUnitEnd (compileUnit);
  182. }
  183. protected virtual void GenerateCompileUnitEnd (CodeCompileUnit compileUnit)
  184. {
  185. #if NET_2_0
  186. if (compileUnit.EndDirectives.Count > 0)
  187. GenerateDirectives (compileUnit.EndDirectives);
  188. #endif
  189. }
  190. protected virtual void GenerateCompileUnitStart (CodeCompileUnit compileUnit)
  191. {
  192. #if NET_2_0
  193. if (compileUnit.StartDirectives.Count > 0) {
  194. GenerateDirectives (compileUnit.StartDirectives);
  195. Output.WriteLine ();
  196. }
  197. #endif
  198. }
  199. protected abstract void GenerateConditionStatement (CodeConditionStatement s);
  200. protected abstract void GenerateConstructor (CodeConstructor x, CodeTypeDeclaration d);
  201. protected virtual void GenerateDecimalValue (Decimal d)
  202. {
  203. Output.Write (d.ToString (CultureInfo.InvariantCulture));
  204. }
  205. protected abstract void GenerateDelegateCreateExpression (CodeDelegateCreateExpression e);
  206. protected abstract void GenerateDelegateInvokeExpression (CodeDelegateInvokeExpression e);
  207. protected virtual void GenerateDirectionExpression (CodeDirectionExpression e)
  208. {
  209. OutputDirection (e.Direction);
  210. output.Write (' ');
  211. GenerateExpression (e.Expression);
  212. }
  213. protected virtual void GenerateDoubleValue (Double d)
  214. {
  215. Output.Write (d.ToString (CultureInfo.InvariantCulture));
  216. }
  217. protected abstract void GenerateEntryPointMethod (CodeEntryPointMethod m, CodeTypeDeclaration d);
  218. protected abstract void GenerateEvent (CodeMemberEvent ev, CodeTypeDeclaration d);
  219. protected abstract void GenerateEventReferenceExpression (CodeEventReferenceExpression e);
  220. protected void GenerateExpression (CodeExpression e)
  221. {
  222. if (e == null)
  223. throw new ArgumentNullException ("Value cannot be null.");
  224. CodeArgumentReferenceExpression argref = e as CodeArgumentReferenceExpression;
  225. if (argref != null) {
  226. GenerateArgumentReferenceExpression (argref);
  227. return;
  228. }
  229. CodeArrayCreateExpression mkarray = e as CodeArrayCreateExpression;
  230. if (mkarray != null) {
  231. GenerateArrayCreateExpression (mkarray);
  232. return;
  233. }
  234. CodeArrayIndexerExpression arrayidx = e as CodeArrayIndexerExpression;
  235. if (arrayidx != null) {
  236. GenerateArrayIndexerExpression (arrayidx);
  237. return;
  238. }
  239. CodeBaseReferenceExpression baseref = e as CodeBaseReferenceExpression;
  240. if (baseref != null) {
  241. GenerateBaseReferenceExpression (baseref);
  242. return;
  243. }
  244. CodeBinaryOperatorExpression binary = e as CodeBinaryOperatorExpression;
  245. if (binary != null) {
  246. GenerateBinaryOperatorExpression (binary);
  247. return;
  248. }
  249. CodeCastExpression cast = e as CodeCastExpression;
  250. if (cast != null) {
  251. GenerateCastExpression (cast);
  252. return;
  253. }
  254. CodeDelegateCreateExpression mkdel = e as CodeDelegateCreateExpression;
  255. if (mkdel != null) {
  256. GenerateDelegateCreateExpression (mkdel);
  257. return;
  258. }
  259. CodeDelegateInvokeExpression delinvoke = e as CodeDelegateInvokeExpression;
  260. if (delinvoke != null) {
  261. GenerateDelegateInvokeExpression (delinvoke);
  262. return;
  263. }
  264. CodeDirectionExpression direction = e as CodeDirectionExpression;
  265. if (direction != null) {
  266. GenerateDirectionExpression (direction);
  267. return;
  268. }
  269. CodeEventReferenceExpression eventref = e as CodeEventReferenceExpression;
  270. if ( eventref != null ) {
  271. GenerateEventReferenceExpression( eventref );
  272. return;
  273. }
  274. CodeFieldReferenceExpression fieldref = e as CodeFieldReferenceExpression;
  275. if (fieldref != null) {
  276. GenerateFieldReferenceExpression (fieldref);
  277. return;
  278. }
  279. CodeIndexerExpression idx = e as CodeIndexerExpression;
  280. if (idx != null) {
  281. GenerateIndexerExpression (idx);
  282. return;
  283. }
  284. CodeMethodInvokeExpression methodinv = e as CodeMethodInvokeExpression;
  285. if (methodinv != null) {
  286. GenerateMethodInvokeExpression (methodinv);
  287. return;
  288. }
  289. CodeMethodReferenceExpression methodref = e as CodeMethodReferenceExpression;
  290. if (methodref != null) {
  291. GenerateMethodReferenceExpression (methodref);
  292. return;
  293. }
  294. CodeObjectCreateExpression objref = e as CodeObjectCreateExpression;
  295. if (objref != null) {
  296. GenerateObjectCreateExpression (objref);
  297. return;
  298. }
  299. CodeParameterDeclarationExpression param = e as CodeParameterDeclarationExpression;
  300. if (param != null) {
  301. GenerateParameterDeclarationExpression (param);
  302. return;
  303. }
  304. CodePrimitiveExpression primitive = e as CodePrimitiveExpression;
  305. if (primitive != null) {
  306. GeneratePrimitiveExpression (primitive);
  307. return;
  308. }
  309. CodePropertyReferenceExpression propref = e as CodePropertyReferenceExpression;
  310. if (propref != null) {
  311. GeneratePropertyReferenceExpression (propref);
  312. return;
  313. }
  314. CodePropertySetValueReferenceExpression propset = e as CodePropertySetValueReferenceExpression;
  315. if (propset != null) {
  316. GeneratePropertySetValueReferenceExpression (propset);
  317. return;
  318. }
  319. CodeSnippetExpression snippet = e as CodeSnippetExpression;
  320. if (snippet != null) {
  321. GenerateSnippetExpression (snippet);
  322. return;
  323. }
  324. CodeThisReferenceExpression thisref = e as CodeThisReferenceExpression;
  325. if (thisref != null) {
  326. GenerateThisReferenceExpression (thisref);
  327. return;
  328. }
  329. CodeTypeOfExpression typeOf = e as CodeTypeOfExpression;
  330. if (typeOf != null) {
  331. GenerateTypeOfExpression (typeOf);
  332. return;
  333. }
  334. CodeTypeReferenceExpression typeref = e as CodeTypeReferenceExpression;
  335. if (typeref != null) {
  336. GenerateTypeReferenceExpression (typeref);
  337. return;
  338. }
  339. CodeVariableReferenceExpression varref = e as CodeVariableReferenceExpression;
  340. if (varref != null) {
  341. GenerateVariableReferenceExpression (varref);
  342. return;
  343. }
  344. throw new ArgumentException ("Element type " + e + " is not supported.");
  345. }
  346. protected abstract void GenerateExpressionStatement (CodeExpressionStatement statement);
  347. protected abstract void GenerateField (CodeMemberField f);
  348. protected abstract void GenerateFieldReferenceExpression (CodeFieldReferenceExpression e);
  349. protected abstract void GenerateGotoStatement (CodeGotoStatement statement);
  350. protected abstract void GenerateIndexerExpression (CodeIndexerExpression e);
  351. protected abstract void GenerateIterationStatement (CodeIterationStatement s);
  352. protected abstract void GenerateLabeledStatement (CodeLabeledStatement statement);
  353. protected abstract void GenerateLinePragmaStart (CodeLinePragma p);
  354. protected abstract void GenerateLinePragmaEnd (CodeLinePragma p);
  355. protected abstract void GenerateMethod (CodeMemberMethod m, CodeTypeDeclaration d);
  356. protected abstract void GenerateMethodInvokeExpression (CodeMethodInvokeExpression e);
  357. protected abstract void GenerateMethodReferenceExpression (CodeMethodReferenceExpression e);
  358. protected abstract void GenerateMethodReturnStatement (CodeMethodReturnStatement e);
  359. protected virtual void GenerateNamespace (CodeNamespace ns)
  360. {
  361. foreach (CodeCommentStatement statement in ns.Comments)
  362. GenerateCommentStatement (statement);
  363. GenerateNamespaceStart (ns);
  364. foreach (CodeNamespaceImport import in ns.Imports) {
  365. if (import.LinePragma != null)
  366. GenerateLinePragmaStart (import.LinePragma);
  367. GenerateNamespaceImport (import);
  368. if (import.LinePragma != null)
  369. GenerateLinePragmaEnd (import.LinePragma);
  370. }
  371. output.WriteLine();
  372. foreach (CodeTypeDeclaration type in ns.Types) {
  373. GenerateType (type);
  374. output.WriteLine();
  375. }
  376. GenerateNamespaceEnd (ns);
  377. }
  378. protected abstract void GenerateNamespaceStart (CodeNamespace ns);
  379. protected abstract void GenerateNamespaceEnd (CodeNamespace ns);
  380. protected abstract void GenerateNamespaceImport (CodeNamespaceImport i);
  381. protected void GenerateNamespaceImports (CodeNamespace e)
  382. {
  383. foreach (CodeNamespaceImport import in e.Imports) {
  384. if (import.LinePragma != null)
  385. GenerateLinePragmaStart (import.LinePragma);
  386. GenerateNamespaceImport (import);
  387. if (import.LinePragma != null)
  388. GenerateLinePragmaEnd (import.LinePragma);
  389. }
  390. }
  391. protected void GenerateNamespaces (CodeCompileUnit e)
  392. {
  393. foreach (CodeNamespace ns in e.Namespaces)
  394. GenerateNamespace (ns);
  395. }
  396. protected abstract void GenerateObjectCreateExpression (CodeObjectCreateExpression e);
  397. protected virtual void GenerateParameterDeclarationExpression (CodeParameterDeclarationExpression e)
  398. {
  399. if (e.CustomAttributes != null && e.CustomAttributes.Count > 0)
  400. OutputAttributeDeclarations (e.CustomAttributes);
  401. OutputDirection (e.Direction);
  402. OutputType (e.Type);
  403. output.Write (' ');
  404. output.Write (e.Name);
  405. }
  406. protected virtual void GeneratePrimitiveExpression (CodePrimitiveExpression e)
  407. {
  408. if (e.Value == null) {
  409. output.Write (NullToken);
  410. return;
  411. }
  412. Type type = e.Value.GetType ();
  413. if (type == typeof (bool)) {
  414. output.Write (e.Value.ToString ().ToLower (CultureInfo.InvariantCulture));
  415. } else if (type == typeof (char)) {
  416. output.Write ("'" + e.Value.ToString () + "'");
  417. } else if (type == typeof (string)) {
  418. output.Write (QuoteSnippetString ((string) e.Value));
  419. } else if (type == typeof (byte) || type == typeof (sbyte) || type == typeof (short) ||
  420. type == typeof (int) || type == typeof (long) || type == typeof (float) ||
  421. type == typeof (double) || type == typeof (decimal)) {
  422. // All of these should be IFormatable, I am just being safe/slow
  423. IFormattable formattable = e.Value as IFormattable;
  424. if (formattable != null)
  425. output.Write (formattable.ToString (null, CultureInfo.InvariantCulture));
  426. else
  427. output.Write (e.Value.ToString ());
  428. if (type == typeof (float))
  429. output.Write ("f");
  430. } else {
  431. throw new ArgumentException ("Value type (" + type + ") is not a primitive type");
  432. }
  433. }
  434. protected abstract void GenerateProperty (CodeMemberProperty p, CodeTypeDeclaration d);
  435. protected abstract void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression e);
  436. protected abstract void GeneratePropertySetValueReferenceExpression (CodePropertySetValueReferenceExpression e);
  437. protected abstract void GenerateRemoveEventStatement (CodeRemoveEventStatement statement);
  438. protected virtual void GenerateSingleFloatValue (Single s)
  439. {
  440. output.Write (s.ToString(CultureInfo.InvariantCulture));
  441. }
  442. protected virtual void GenerateSnippetCompileUnit (CodeSnippetCompileUnit e)
  443. {
  444. if (e.LinePragma != null)
  445. GenerateLinePragmaStart (e.LinePragma);
  446. output.WriteLine (e.Value);
  447. if (e.LinePragma != null)
  448. GenerateLinePragmaEnd (e.LinePragma);
  449. }
  450. protected abstract void GenerateSnippetExpression (CodeSnippetExpression e);
  451. protected abstract void GenerateSnippetMember (CodeSnippetTypeMember m);
  452. protected virtual void GenerateSnippetStatement (CodeSnippetStatement s)
  453. {
  454. output.WriteLine (s.Value);
  455. }
  456. protected void GenerateStatement (CodeStatement s)
  457. {
  458. bool handled = false;
  459. #if NET_2_0
  460. if (s.StartDirectives.Count > 0)
  461. GenerateDirectives (s.StartDirectives);
  462. #endif
  463. if (s.LinePragma != null)
  464. GenerateLinePragmaStart (s.LinePragma);
  465. CodeAssignStatement assign = s as CodeAssignStatement;
  466. if (assign != null) {
  467. GenerateAssignStatement (assign);
  468. handled = true;
  469. }
  470. CodeAttachEventStatement attach = s as CodeAttachEventStatement;
  471. if (attach != null) {
  472. GenerateAttachEventStatement (attach);
  473. handled = true;
  474. }
  475. CodeCommentStatement comment = s as CodeCommentStatement;
  476. if (comment != null) {
  477. GenerateCommentStatement (comment);
  478. handled = true;
  479. }
  480. CodeConditionStatement condition = s as CodeConditionStatement;
  481. if (condition != null) {
  482. GenerateConditionStatement (condition);
  483. handled = true;
  484. }
  485. CodeExpressionStatement expression = s as CodeExpressionStatement;
  486. if (expression != null) {
  487. GenerateExpressionStatement (expression);
  488. handled = true;
  489. }
  490. CodeGotoStatement gotostmt = s as CodeGotoStatement;
  491. if (gotostmt != null) {
  492. GenerateGotoStatement (gotostmt);
  493. handled = true;
  494. }
  495. CodeIterationStatement iteration = s as CodeIterationStatement;
  496. if (iteration != null) {
  497. GenerateIterationStatement (iteration);
  498. handled = true;
  499. }
  500. CodeLabeledStatement label = s as CodeLabeledStatement;
  501. if (label != null) {
  502. GenerateLabeledStatement (label);
  503. handled = true;
  504. }
  505. CodeMethodReturnStatement returnstmt = s as CodeMethodReturnStatement;
  506. if (returnstmt != null) {
  507. GenerateMethodReturnStatement (returnstmt);
  508. handled = true;
  509. }
  510. CodeRemoveEventStatement remove = s as CodeRemoveEventStatement;
  511. if (remove != null) {
  512. GenerateRemoveEventStatement (remove);
  513. handled = true;
  514. }
  515. CodeSnippetStatement snippet = s as CodeSnippetStatement;
  516. if (snippet != null) {
  517. GenerateSnippetStatement (snippet);
  518. handled = true;
  519. }
  520. CodeThrowExceptionStatement exception = s as CodeThrowExceptionStatement;
  521. if (exception != null) {
  522. GenerateThrowExceptionStatement (exception);
  523. handled = true;
  524. }
  525. CodeTryCatchFinallyStatement trycatch = s as CodeTryCatchFinallyStatement;
  526. if (trycatch != null) {
  527. GenerateTryCatchFinallyStatement (trycatch);
  528. handled = true;
  529. }
  530. CodeVariableDeclarationStatement declaration = s as CodeVariableDeclarationStatement;
  531. if (declaration != null) {
  532. GenerateVariableDeclarationStatement (declaration);
  533. handled = true;
  534. }
  535. if (!handled)
  536. throw new ArgumentException ("Element type " + s + " is not supported.");
  537. if (s.LinePragma != null)
  538. GenerateLinePragmaEnd (s.LinePragma);
  539. #if NET_2_0
  540. if (s.EndDirectives.Count > 0)
  541. GenerateDirectives (s.EndDirectives);
  542. #endif
  543. }
  544. protected void GenerateStatements (CodeStatementCollection c)
  545. {
  546. foreach (CodeStatement statement in c)
  547. GenerateStatement (statement);
  548. }
  549. protected abstract void GenerateThisReferenceExpression (CodeThisReferenceExpression e);
  550. protected abstract void GenerateThrowExceptionStatement (CodeThrowExceptionStatement s);
  551. protected abstract void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement s);
  552. protected abstract void GenerateTypeEnd (CodeTypeDeclaration declaration);
  553. protected abstract void GenerateTypeConstructor (CodeTypeConstructor constructor);
  554. protected virtual void GenerateTypeOfExpression (CodeTypeOfExpression e)
  555. {
  556. output.Write ("typeof(");
  557. OutputType (e.Type);
  558. output.Write (")");
  559. }
  560. protected virtual void GenerateTypeReferenceExpression (CodeTypeReferenceExpression e)
  561. {
  562. OutputType (e.Type);
  563. }
  564. protected void GenerateTypes (CodeNamespace e)
  565. {
  566. foreach (CodeTypeDeclaration type in e.Types)
  567. GenerateType (type);
  568. }
  569. protected abstract void GenerateTypeStart (CodeTypeDeclaration declaration);
  570. protected abstract void GenerateVariableDeclarationStatement (CodeVariableDeclarationStatement e);
  571. protected abstract void GenerateVariableReferenceExpression (CodeVariableReferenceExpression e);
  572. //
  573. // Other members
  574. //
  575. /*
  576. * Output Methods
  577. */
  578. protected virtual void OutputAttributeArgument (CodeAttributeArgument argument)
  579. {
  580. string name = argument.Name;
  581. if (name != null) {
  582. output.Write (name);
  583. output.Write ('=');
  584. }
  585. GenerateExpression (argument.Value);
  586. }
  587. private void OutputAttributeDeclaration (CodeAttributeDeclaration attribute)
  588. {
  589. output.Write (attribute.Name.Replace ('+', '.'));
  590. output.Write ('(');
  591. IEnumerator enumerator = attribute.Arguments.GetEnumerator();
  592. if (enumerator.MoveNext()) {
  593. CodeAttributeArgument argument = (CodeAttributeArgument)enumerator.Current;
  594. OutputAttributeArgument (argument);
  595. while (enumerator.MoveNext()) {
  596. output.Write (',');
  597. argument = (CodeAttributeArgument)enumerator.Current;
  598. OutputAttributeArgument (argument);
  599. }
  600. }
  601. output.Write (')');
  602. }
  603. protected virtual void OutputAttributeDeclarations (CodeAttributeDeclarationCollection attributes)
  604. {
  605. GenerateAttributeDeclarationsStart (attributes);
  606. IEnumerator enumerator = attributes.GetEnumerator();
  607. if (enumerator.MoveNext()) {
  608. CodeAttributeDeclaration attribute = (CodeAttributeDeclaration)enumerator.Current;
  609. OutputAttributeDeclaration (attribute);
  610. while (enumerator.MoveNext()) {
  611. attribute = (CodeAttributeDeclaration)enumerator.Current;
  612. output.WriteLine (',');
  613. OutputAttributeDeclaration (attribute);
  614. }
  615. }
  616. GenerateAttributeDeclarationsEnd (attributes);
  617. }
  618. protected virtual void OutputDirection (FieldDirection direction)
  619. {
  620. switch (direction) {
  621. case FieldDirection.In:
  622. //output.Write ("in ");
  623. break;
  624. case FieldDirection.Out:
  625. output.Write ("out ");
  626. break;
  627. case FieldDirection.Ref:
  628. output.Write ("ref ");
  629. break;
  630. }
  631. }
  632. protected virtual void OutputExpressionList (CodeExpressionCollection expressions)
  633. {
  634. OutputExpressionList (expressions, false);
  635. }
  636. protected virtual void OutputExpressionList (CodeExpressionCollection expressions,
  637. bool newLineBetweenItems)
  638. {
  639. IEnumerator enumerator = expressions.GetEnumerator();
  640. if (enumerator.MoveNext()) {
  641. CodeExpression expression = (CodeExpression)enumerator.Current;
  642. GenerateExpression (expression);
  643. while (enumerator.MoveNext()) {
  644. expression = (CodeExpression)enumerator.Current;
  645. output.Write (',');
  646. if (newLineBetweenItems)
  647. output.WriteLine ();
  648. else
  649. output.Write (' ');
  650. GenerateExpression (expression);
  651. }
  652. }
  653. }
  654. protected virtual void OutputFieldScopeModifier (MemberAttributes attributes)
  655. {
  656. if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
  657. output.Write ("new ");
  658. switch (attributes & MemberAttributes.ScopeMask) {
  659. case MemberAttributes.Static:
  660. output.Write ("static ");
  661. break;
  662. case MemberAttributes.Const:
  663. output.Write ("const ");
  664. break;
  665. }
  666. }
  667. protected virtual void OutputIdentifier (string ident)
  668. {
  669. output.Write (ident);
  670. }
  671. protected virtual void OutputMemberAccessModifier (MemberAttributes attributes)
  672. {
  673. switch (attributes & MemberAttributes.AccessMask) {
  674. case MemberAttributes.Assembly:
  675. output.Write ("internal ");
  676. break;
  677. case MemberAttributes.FamilyAndAssembly:
  678. #if NET_2_0
  679. output.Write ("internal ");
  680. #else
  681. output.Write ("/*FamANDAssem*/ internal ");
  682. #endif
  683. break;
  684. case MemberAttributes.Family:
  685. output.Write ("protected ");
  686. break;
  687. case MemberAttributes.FamilyOrAssembly:
  688. output.Write ("protected internal ");
  689. break;
  690. case MemberAttributes.Private:
  691. output.Write ("private ");
  692. break;
  693. case MemberAttributes.Public:
  694. output.Write ("public ");
  695. break;
  696. }
  697. }
  698. protected virtual void OutputMemberScopeModifier (MemberAttributes attributes)
  699. {
  700. if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
  701. output.Write( "new " );
  702. switch (attributes & MemberAttributes.ScopeMask) {
  703. case MemberAttributes.Abstract:
  704. output.Write ("abstract ");
  705. break;
  706. case MemberAttributes.Final:
  707. // Do nothing
  708. break;
  709. case MemberAttributes.Static:
  710. output.Write ("static ");
  711. break;
  712. case MemberAttributes.Override:
  713. output.Write ("override ");
  714. break;
  715. default:
  716. //
  717. // FUNNY! if the scope value is
  718. // rubbish (0 or >Const), and access
  719. // is public or protected, make it
  720. // "virtual".
  721. //
  722. // i'm not sure whether this is 100%
  723. // correct, but it seems to be MS
  724. // behavior.
  725. //
  726. // On .NET 2.0, internal members
  727. // are also marked "virtual".
  728. //
  729. MemberAttributes access = attributes & MemberAttributes.AccessMask;
  730. if (access == MemberAttributes.Public ||
  731. #if NET_2_0
  732. access == MemberAttributes.Family || access == MemberAttributes.Assembly)
  733. #else
  734. access == MemberAttributes.Family)
  735. #endif
  736. output.Write ("virtual ");
  737. break;
  738. }
  739. }
  740. protected virtual void OutputOperator (CodeBinaryOperatorType op)
  741. {
  742. switch (op) {
  743. case CodeBinaryOperatorType.Add:
  744. output.Write ("+");
  745. break;
  746. case CodeBinaryOperatorType.Subtract:
  747. output.Write ("-");
  748. break;
  749. case CodeBinaryOperatorType.Multiply:
  750. output.Write ("*");
  751. break;
  752. case CodeBinaryOperatorType.Divide:
  753. output.Write ("/");
  754. break;
  755. case CodeBinaryOperatorType.Modulus:
  756. output.Write ("%");
  757. break;
  758. case CodeBinaryOperatorType.Assign:
  759. output.Write ("=");
  760. break;
  761. case CodeBinaryOperatorType.IdentityInequality:
  762. output.Write ("!=");
  763. break;
  764. case CodeBinaryOperatorType.IdentityEquality:
  765. output.Write ("==");
  766. break;
  767. case CodeBinaryOperatorType.ValueEquality:
  768. output.Write ("==");
  769. break;
  770. case CodeBinaryOperatorType.BitwiseOr:
  771. output.Write ("|");
  772. break;
  773. case CodeBinaryOperatorType.BitwiseAnd:
  774. output.Write ("&");
  775. break;
  776. case CodeBinaryOperatorType.BooleanOr:
  777. output.Write ("||");
  778. break;
  779. case CodeBinaryOperatorType.BooleanAnd:
  780. output.Write ("&&");
  781. break;
  782. case CodeBinaryOperatorType.LessThan:
  783. output.Write ("<");
  784. break;
  785. case CodeBinaryOperatorType.LessThanOrEqual:
  786. output.Write ("<=");
  787. break;
  788. case CodeBinaryOperatorType.GreaterThan:
  789. output.Write (">");
  790. break;
  791. case CodeBinaryOperatorType.GreaterThanOrEqual:
  792. output.Write (">=");
  793. break;
  794. }
  795. }
  796. protected virtual void OutputParameters (CodeParameterDeclarationExpressionCollection parameters)
  797. {
  798. bool first = true;
  799. foreach (CodeParameterDeclarationExpression expr in parameters) {
  800. if (first)
  801. first = false;
  802. else
  803. output.Write (", ");
  804. GenerateExpression (expr);
  805. }
  806. }
  807. protected abstract void OutputType (CodeTypeReference t);
  808. protected virtual void OutputTypeAttributes (TypeAttributes attributes,
  809. bool isStruct,
  810. bool isEnum)
  811. {
  812. switch (attributes & TypeAttributes.VisibilityMask) {
  813. case TypeAttributes.NotPublic:
  814. // private by default
  815. break;
  816. case TypeAttributes.Public:
  817. case TypeAttributes.NestedPublic:
  818. output.Write ("public ");
  819. break;
  820. case TypeAttributes.NestedPrivate:
  821. output.Write ("private ");
  822. break;
  823. }
  824. if (isStruct)
  825. output.Write ("struct ");
  826. else if (isEnum)
  827. output.Write ("enum ");
  828. else {
  829. if ((attributes & TypeAttributes.Interface) != 0)
  830. output.Write ("interface ");
  831. else if (currentType is CodeTypeDelegate)
  832. output.Write ("delegate ");
  833. else {
  834. if ((attributes & TypeAttributes.Sealed) != 0)
  835. output.Write ("sealed ");
  836. if ((attributes & TypeAttributes.Abstract) != 0)
  837. output.Write ("abstract ");
  838. output.Write ("class ");
  839. }
  840. }
  841. }
  842. protected virtual void OutputTypeNamePair (CodeTypeReference type,
  843. string name)
  844. {
  845. OutputType (type);
  846. output.Write (' ');
  847. output.Write (name);
  848. }
  849. protected abstract string QuoteSnippetString (string value);
  850. /*
  851. * ICodeGenerator
  852. */
  853. protected abstract string CreateEscapedIdentifier (string value);
  854. string ICodeGenerator.CreateEscapedIdentifier (string value)
  855. {
  856. return CreateEscapedIdentifier (value);
  857. }
  858. protected abstract string CreateValidIdentifier (string value);
  859. string ICodeGenerator.CreateValidIdentifier (string value)
  860. {
  861. return CreateValidIdentifier (value);
  862. }
  863. private void InitOutput (TextWriter output, CodeGeneratorOptions options)
  864. {
  865. if (options == null)
  866. options = new CodeGeneratorOptions ();
  867. this.output = new IndentedTextWriter (output, options.IndentString);
  868. this.options = options;
  869. }
  870. void ICodeGenerator.GenerateCodeFromCompileUnit (CodeCompileUnit compileUnit,
  871. TextWriter output,
  872. CodeGeneratorOptions options)
  873. {
  874. InitOutput (output, options);
  875. if (compileUnit is CodeSnippetCompileUnit) {
  876. GenerateSnippetCompileUnit ((CodeSnippetCompileUnit) compileUnit);
  877. } else {
  878. GenerateCompileUnit (compileUnit);
  879. }
  880. }
  881. void ICodeGenerator.GenerateCodeFromExpression (CodeExpression expression,
  882. TextWriter output,
  883. CodeGeneratorOptions options)
  884. {
  885. InitOutput (output, options);
  886. GenerateExpression (expression);
  887. }
  888. void ICodeGenerator.GenerateCodeFromNamespace (CodeNamespace ns,
  889. TextWriter output,
  890. CodeGeneratorOptions options)
  891. {
  892. InitOutput (output, options);
  893. GenerateNamespace (ns);
  894. }
  895. void ICodeGenerator.GenerateCodeFromStatement (CodeStatement statement,
  896. TextWriter output,
  897. CodeGeneratorOptions options)
  898. {
  899. InitOutput (output, options);
  900. GenerateStatement (statement);
  901. }
  902. void ICodeGenerator.GenerateCodeFromType (CodeTypeDeclaration type,
  903. TextWriter output,
  904. CodeGeneratorOptions options)
  905. {
  906. InitOutput (output, options);
  907. GenerateType (type);
  908. }
  909. private void GenerateType (CodeTypeDeclaration type)
  910. {
  911. this.currentType = type;
  912. #if NET_2_0
  913. if (type.StartDirectives.Count > 0)
  914. GenerateDirectives (type.StartDirectives);
  915. #endif
  916. foreach (CodeCommentStatement statement in type.Comments)
  917. GenerateCommentStatement (statement);
  918. if (type.LinePragma != null)
  919. GenerateLinePragmaStart (type.LinePragma);
  920. GenerateTypeStart (type);
  921. CodeTypeMember[] members = new CodeTypeMember[type.Members.Count];
  922. type.Members.CopyTo (members, 0);
  923. #if NET_2_0
  924. if (!Options.VerbatimOrder)
  925. #endif
  926. {
  927. int[] order = new int[members.Length];
  928. for (int n = 0; n < members.Length; n++)
  929. order[n] = Array.IndexOf (memberTypes, members[n].GetType ()) * members.Length + n;
  930. Array.Sort (order, members);
  931. }
  932. // WARNING: if anything is missing in the foreach loop and you add it, add the type in
  933. // its corresponding place in CodeTypeMemberComparer class (below)
  934. CodeTypeDeclaration subtype = null;
  935. foreach (CodeTypeMember member in members) {
  936. CodeTypeMember prevMember = this.currentMember;
  937. this.currentMember = member;
  938. if (prevMember != null && subtype == null) {
  939. if (prevMember.LinePragma != null)
  940. GenerateLinePragmaEnd (prevMember.LinePragma);
  941. #if NET_2_0
  942. if (prevMember.EndDirectives.Count > 0)
  943. GenerateDirectives (prevMember.EndDirectives);
  944. #endif
  945. }
  946. if (options.BlankLinesBetweenMembers)
  947. output.WriteLine ();
  948. subtype = member as CodeTypeDeclaration;
  949. if (subtype != null) {
  950. GenerateType (subtype);
  951. this.currentType = type;
  952. continue;
  953. }
  954. #if NET_2_0
  955. if (currentMember.StartDirectives.Count > 0)
  956. GenerateDirectives (currentMember.StartDirectives);
  957. #endif
  958. foreach (CodeCommentStatement statement in member.Comments)
  959. GenerateCommentStatement (statement);
  960. if (member.LinePragma != null)
  961. GenerateLinePragmaStart (member.LinePragma);
  962. CodeMemberEvent eventm = member as CodeMemberEvent;
  963. if (eventm != null) {
  964. GenerateEvent (eventm, type);
  965. continue;
  966. }
  967. CodeMemberField field = member as CodeMemberField;
  968. if (field != null) {
  969. GenerateField (field);
  970. continue;
  971. }
  972. CodeEntryPointMethod epmethod = member as CodeEntryPointMethod;
  973. if (epmethod != null) {
  974. GenerateEntryPointMethod (epmethod, type);
  975. continue;
  976. }
  977. CodeTypeConstructor typeCtor = member as CodeTypeConstructor;
  978. if (typeCtor != null) {
  979. GenerateTypeConstructor (typeCtor);
  980. continue;
  981. }
  982. CodeConstructor ctor = member as CodeConstructor;
  983. if (ctor != null) {
  984. GenerateConstructor (ctor, type);
  985. continue;
  986. }
  987. CodeMemberMethod method = member as CodeMemberMethod;
  988. if (method != null) {
  989. GenerateMethod (method, type);
  990. continue;
  991. }
  992. CodeMemberProperty property = member as CodeMemberProperty;
  993. if (property != null) {
  994. GenerateProperty (property, type);
  995. continue;
  996. }
  997. CodeSnippetTypeMember snippet = member as CodeSnippetTypeMember;
  998. if (snippet != null) {
  999. GenerateSnippetMember (snippet);
  1000. continue;
  1001. }
  1002. this.currentMember = prevMember;
  1003. }
  1004. // Hack because of previous continue usage
  1005. if (currentMember != null && !(currentMember is CodeTypeDeclaration)) {
  1006. if (currentMember.LinePragma != null)
  1007. GenerateLinePragmaEnd (currentMember.LinePragma);
  1008. #if NET_2_0
  1009. if (currentMember.EndDirectives.Count > 0)
  1010. GenerateDirectives (currentMember.EndDirectives);
  1011. #endif
  1012. }
  1013. this.currentType = type;
  1014. GenerateTypeEnd (type);
  1015. if (type.LinePragma != null)
  1016. GenerateLinePragmaEnd (type.LinePragma);
  1017. #if NET_2_0
  1018. if (type.EndDirectives.Count > 0)
  1019. GenerateDirectives (type.EndDirectives);
  1020. #endif
  1021. }
  1022. protected abstract string GetTypeOutput (CodeTypeReference type);
  1023. string ICodeGenerator.GetTypeOutput (CodeTypeReference type)
  1024. {
  1025. return GetTypeOutput (type);
  1026. }
  1027. protected abstract bool IsValidIdentifier (string value);
  1028. bool ICodeGenerator.IsValidIdentifier (string value)
  1029. {
  1030. return IsValidIdentifier (value);
  1031. }
  1032. public static bool IsValidLanguageIndependentIdentifier (string value)
  1033. {
  1034. if (value == null)
  1035. return false;
  1036. if (value.Equals (string.Empty))
  1037. return false;
  1038. switch (char.GetUnicodeCategory (value[0]))
  1039. {
  1040. case UnicodeCategory.LetterNumber:
  1041. case UnicodeCategory.LowercaseLetter:
  1042. case UnicodeCategory.TitlecaseLetter:
  1043. case UnicodeCategory.UppercaseLetter:
  1044. case UnicodeCategory.OtherLetter:
  1045. case UnicodeCategory.ModifierLetter:
  1046. case UnicodeCategory.ConnectorPunctuation:
  1047. if (value.Length > 1)
  1048. {
  1049. for (int x = 0; x < value.Length; x++)
  1050. {
  1051. switch (char.GetUnicodeCategory (value[x]))
  1052. {
  1053. case UnicodeCategory.LetterNumber:
  1054. case UnicodeCategory.LowercaseLetter:
  1055. case UnicodeCategory.TitlecaseLetter:
  1056. case UnicodeCategory.UppercaseLetter:
  1057. case UnicodeCategory.OtherLetter:
  1058. case UnicodeCategory.ModifierLetter:
  1059. case UnicodeCategory.ConnectorPunctuation:
  1060. case UnicodeCategory.DecimalDigitNumber:
  1061. case UnicodeCategory.NonSpacingMark:
  1062. case UnicodeCategory.SpacingCombiningMark:
  1063. case UnicodeCategory.Format:
  1064. return true;
  1065. }
  1066. return false;
  1067. }
  1068. }
  1069. else
  1070. return true;
  1071. break;
  1072. }
  1073. return false;
  1074. }
  1075. protected abstract bool Supports (GeneratorSupport supports);
  1076. bool ICodeGenerator.Supports (GeneratorSupport value)
  1077. {
  1078. return Supports (value);
  1079. }
  1080. protected virtual void ValidateIdentifier (string value)
  1081. {
  1082. if (!(IsValidIdentifier (value)))
  1083. throw new ArgumentException ("Identifier is invalid", "value");
  1084. }
  1085. [MonoTODO]
  1086. public static void ValidateIdentifiers (CodeObject e)
  1087. {
  1088. throw new NotImplementedException();
  1089. }
  1090. void ICodeGenerator.ValidateIdentifier (string value)
  1091. {
  1092. ValidateIdentifier (value);
  1093. }
  1094. // The position in the array determines the order in which those
  1095. // kind of CodeTypeMembers are generated. Less is more ;-)
  1096. static Type [] memberTypes = { typeof (CodeMemberField),
  1097. typeof (CodeSnippetTypeMember),
  1098. typeof (CodeTypeConstructor),
  1099. typeof (CodeConstructor),
  1100. typeof (CodeMemberProperty),
  1101. typeof (CodeMemberEvent),
  1102. typeof (CodeMemberMethod),
  1103. typeof (CodeTypeDeclaration),
  1104. typeof (CodeEntryPointMethod)
  1105. };
  1106. #if NET_2_0
  1107. protected virtual void GenerateDirectives (CodeDirectiveCollection directives)
  1108. {
  1109. }
  1110. #endif
  1111. }
  1112. }