CodeGenerator.cs 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294
  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;
  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. output.Write ("/* FamAndAssem */ internal ");
  679. break;
  680. case MemberAttributes.Family:
  681. output.Write ("protected ");
  682. break;
  683. case MemberAttributes.FamilyOrAssembly:
  684. output.Write ("protected internal ");
  685. break;
  686. case MemberAttributes.Private:
  687. output.Write ("private ");
  688. break;
  689. case MemberAttributes.Public:
  690. output.Write ("public ");
  691. break;
  692. }
  693. }
  694. protected virtual void OutputMemberScopeModifier (MemberAttributes attributes)
  695. {
  696. if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
  697. output.Write( "new " );
  698. switch (attributes & MemberAttributes.ScopeMask) {
  699. case MemberAttributes.Abstract:
  700. output.Write ("abstract ");
  701. break;
  702. case MemberAttributes.Final:
  703. // Do nothing
  704. break;
  705. case MemberAttributes.Static:
  706. output.Write ("static ");
  707. break;
  708. case MemberAttributes.Override:
  709. output.Write ("override ");
  710. break;
  711. default:
  712. //
  713. // FUNNY! if the scope value is
  714. // rubbish (0 or >Const), and access
  715. // is public or protected, make it
  716. // "virtual".
  717. //
  718. // i'm not sure whether this is 100%
  719. // correct, but it seems to be MS
  720. // behavior.
  721. //
  722. MemberAttributes access = attributes & MemberAttributes.AccessMask;
  723. if (access == MemberAttributes.Public ||
  724. access == MemberAttributes.Family)
  725. output.Write ("virtual ");
  726. break;
  727. }
  728. }
  729. protected virtual void OutputOperator (CodeBinaryOperatorType op)
  730. {
  731. switch (op) {
  732. case CodeBinaryOperatorType.Add:
  733. output.Write ("+");
  734. break;
  735. case CodeBinaryOperatorType.Subtract:
  736. output.Write ("-");
  737. break;
  738. case CodeBinaryOperatorType.Multiply:
  739. output.Write ("*");
  740. break;
  741. case CodeBinaryOperatorType.Divide:
  742. output.Write ("/");
  743. break;
  744. case CodeBinaryOperatorType.Modulus:
  745. output.Write ("%");
  746. break;
  747. case CodeBinaryOperatorType.Assign:
  748. output.Write ("=");
  749. break;
  750. case CodeBinaryOperatorType.IdentityInequality:
  751. output.Write ("!=");
  752. break;
  753. case CodeBinaryOperatorType.IdentityEquality:
  754. output.Write ("==");
  755. break;
  756. case CodeBinaryOperatorType.ValueEquality:
  757. output.Write ("==");
  758. break;
  759. case CodeBinaryOperatorType.BitwiseOr:
  760. output.Write ("|");
  761. break;
  762. case CodeBinaryOperatorType.BitwiseAnd:
  763. output.Write ("&");
  764. break;
  765. case CodeBinaryOperatorType.BooleanOr:
  766. output.Write ("||");
  767. break;
  768. case CodeBinaryOperatorType.BooleanAnd:
  769. output.Write ("&&");
  770. break;
  771. case CodeBinaryOperatorType.LessThan:
  772. output.Write ("<");
  773. break;
  774. case CodeBinaryOperatorType.LessThanOrEqual:
  775. output.Write ("<=");
  776. break;
  777. case CodeBinaryOperatorType.GreaterThan:
  778. output.Write (">");
  779. break;
  780. case CodeBinaryOperatorType.GreaterThanOrEqual:
  781. output.Write (">=");
  782. break;
  783. }
  784. }
  785. protected virtual void OutputParameters (CodeParameterDeclarationExpressionCollection parameters)
  786. {
  787. bool first = true;
  788. foreach (CodeParameterDeclarationExpression expr in parameters) {
  789. if (first)
  790. first = false;
  791. else
  792. output.Write (", ");
  793. GenerateExpression (expr);
  794. }
  795. }
  796. protected abstract void OutputType (CodeTypeReference t);
  797. protected virtual void OutputTypeAttributes (TypeAttributes attributes,
  798. bool isStruct,
  799. bool isEnum)
  800. {
  801. switch (attributes & TypeAttributes.VisibilityMask) {
  802. case TypeAttributes.NotPublic:
  803. // private by default
  804. break;
  805. case TypeAttributes.Public:
  806. case TypeAttributes.NestedPublic:
  807. output.Write ("public ");
  808. break;
  809. case TypeAttributes.NestedPrivate:
  810. output.Write ("private ");
  811. break;
  812. }
  813. if (!IsCurrentClass)
  814. OutputExtraTypeAttribute (currentType);
  815. if (isStruct)
  816. output.Write ("struct ");
  817. else if (isEnum)
  818. output.Write ("enum ");
  819. else {
  820. if ((attributes & TypeAttributes.Interface) != 0)
  821. output.Write ("interface ");
  822. else if (currentType is CodeTypeDelegate)
  823. output.Write ("delegate ");
  824. else {
  825. if ((attributes & TypeAttributes.Sealed) != 0)
  826. output.Write ("sealed ");
  827. if ((attributes & TypeAttributes.Abstract) != 0)
  828. output.Write ("abstract ");
  829. OutputExtraTypeAttribute (currentType);
  830. output.Write ("class ");
  831. }
  832. }
  833. }
  834. internal virtual void OutputExtraTypeAttribute (CodeTypeDeclaration type)
  835. {
  836. }
  837. protected virtual void OutputTypeNamePair (CodeTypeReference type,
  838. string name)
  839. {
  840. OutputType (type);
  841. output.Write (' ');
  842. output.Write (name);
  843. }
  844. protected abstract string QuoteSnippetString (string value);
  845. /*
  846. * ICodeGenerator
  847. */
  848. protected abstract string CreateEscapedIdentifier (string value);
  849. string ICodeGenerator.CreateEscapedIdentifier (string value)
  850. {
  851. return CreateEscapedIdentifier (value);
  852. }
  853. protected abstract string CreateValidIdentifier (string value);
  854. string ICodeGenerator.CreateValidIdentifier (string value)
  855. {
  856. return CreateValidIdentifier (value);
  857. }
  858. private void InitOutput (TextWriter output, CodeGeneratorOptions options)
  859. {
  860. if (options == null)
  861. options = new CodeGeneratorOptions ();
  862. this.output = new IndentedTextWriter (output, options.IndentString);
  863. this.options = options;
  864. }
  865. void ICodeGenerator.GenerateCodeFromCompileUnit (CodeCompileUnit compileUnit,
  866. TextWriter output,
  867. CodeGeneratorOptions options)
  868. {
  869. InitOutput (output, options);
  870. if (compileUnit is CodeSnippetCompileUnit) {
  871. GenerateSnippetCompileUnit ((CodeSnippetCompileUnit) compileUnit);
  872. } else {
  873. GenerateCompileUnit (compileUnit);
  874. }
  875. }
  876. void ICodeGenerator.GenerateCodeFromExpression (CodeExpression expression,
  877. TextWriter output,
  878. CodeGeneratorOptions options)
  879. {
  880. InitOutput (output, options);
  881. GenerateExpression (expression);
  882. }
  883. void ICodeGenerator.GenerateCodeFromNamespace (CodeNamespace ns,
  884. TextWriter output,
  885. CodeGeneratorOptions options)
  886. {
  887. InitOutput (output, options);
  888. GenerateNamespace (ns);
  889. }
  890. void ICodeGenerator.GenerateCodeFromStatement (CodeStatement statement,
  891. TextWriter output,
  892. CodeGeneratorOptions options)
  893. {
  894. InitOutput (output, options);
  895. GenerateStatement (statement);
  896. }
  897. void ICodeGenerator.GenerateCodeFromType (CodeTypeDeclaration type,
  898. TextWriter output,
  899. CodeGeneratorOptions options)
  900. {
  901. InitOutput (output, options);
  902. GenerateType (type);
  903. }
  904. private void GenerateType (CodeTypeDeclaration type)
  905. {
  906. #if NET_2_0
  907. if (type.StartDirectives.Count > 0)
  908. GenerateDirectives (type.StartDirectives);
  909. #endif
  910. foreach (CodeCommentStatement statement in type.Comments)
  911. GenerateCommentStatement (statement);
  912. if (type.LinePragma != null)
  913. GenerateLinePragmaStart (type.LinePragma);
  914. CodeTypeDelegate del = type as CodeTypeDelegate;
  915. if (del != null)
  916. GenerateDelegate (del);
  917. else
  918. GenerateNonDelegateType (type);
  919. if (type.LinePragma != null)
  920. GenerateLinePragmaEnd (type.LinePragma);
  921. #if NET_2_0
  922. if (type.EndDirectives.Count > 0)
  923. GenerateDirectives (type.EndDirectives);
  924. #endif
  925. }
  926. private void GenerateDelegate (CodeTypeDelegate type)
  927. {
  928. CodeTypeDeclaration prevType = this.currentType;
  929. this.currentType = type;
  930. GenerateTypeStart (type);
  931. OutputParameters (type.Parameters);
  932. GenerateTypeEnd (type);
  933. this.currentType = prevType;
  934. }
  935. private void GenerateNonDelegateType (CodeTypeDeclaration type)
  936. {
  937. CodeTypeDeclaration prevType = this.currentType;
  938. this.currentType = type;
  939. GenerateTypeStart (type);
  940. CodeTypeMember [] members = new CodeTypeMember [type.Members.Count];
  941. type.Members.CopyTo (members, 0);
  942. #if NET_2_0
  943. if (!Options.VerbatimOrder)
  944. #endif
  945. {
  946. int[] order = new int[members.Length];
  947. for (int n=0; n<members.Length; n++)
  948. order[n] = Array.IndexOf(memberTypes, members[n].GetType()) * members.Length + n;
  949. Array.Sort (order, members);
  950. }
  951. // WARNING: if anything is missing in the foreach loop and you add it, add the type in
  952. // its corresponding place in CodeTypeMemberComparer class (below)
  953. CodeTypeDeclaration subtype = null;
  954. foreach (CodeTypeMember member in members)
  955. {
  956. CodeTypeMember prevMember = this.currentMember;
  957. this.currentMember = member;
  958. if (prevMember != null && subtype == null) {
  959. if (prevMember.LinePragma != null)
  960. GenerateLinePragmaEnd (prevMember.LinePragma);
  961. #if NET_2_0
  962. if (prevMember.EndDirectives.Count > 0)
  963. GenerateDirectives (prevMember.EndDirectives);
  964. #endif
  965. }
  966. if (options.BlankLinesBetweenMembers)
  967. output.WriteLine ();
  968. subtype = member as CodeTypeDeclaration;
  969. if (subtype != null) {
  970. GenerateType (subtype);
  971. continue;
  972. }
  973. #if NET_2_0
  974. if (currentMember.StartDirectives.Count > 0)
  975. GenerateDirectives (currentMember.StartDirectives);
  976. #endif
  977. foreach (CodeCommentStatement statement in member.Comments)
  978. GenerateCommentStatement (statement);
  979. if (member.LinePragma != null)
  980. GenerateLinePragmaStart (member.LinePragma);
  981. CodeMemberEvent eventm = member as CodeMemberEvent;
  982. if (eventm != null)
  983. {
  984. GenerateEvent (eventm, type);
  985. continue;
  986. }
  987. CodeMemberField field = member as CodeMemberField;
  988. if (field != null)
  989. {
  990. GenerateField (field);
  991. continue;
  992. }
  993. CodeEntryPointMethod epmethod = member as CodeEntryPointMethod;
  994. if (epmethod != null)
  995. {
  996. GenerateEntryPointMethod (epmethod, type);
  997. continue;
  998. }
  999. CodeTypeConstructor typeCtor = member as CodeTypeConstructor;
  1000. if (typeCtor != null)
  1001. {
  1002. GenerateTypeConstructor (typeCtor);
  1003. continue;
  1004. }
  1005. CodeConstructor ctor = member as CodeConstructor;
  1006. if (ctor != null)
  1007. {
  1008. GenerateConstructor (ctor, type);
  1009. continue;
  1010. }
  1011. CodeMemberMethod method = member as CodeMemberMethod;
  1012. if (method != null)
  1013. {
  1014. GenerateMethod (method, type);
  1015. continue;
  1016. }
  1017. CodeMemberProperty property = member as CodeMemberProperty;
  1018. if (property != null)
  1019. {
  1020. GenerateProperty (property, type);
  1021. continue;
  1022. }
  1023. CodeSnippetTypeMember snippet = member as CodeSnippetTypeMember;
  1024. if (snippet != null)
  1025. {
  1026. GenerateSnippetMember (snippet);
  1027. continue;
  1028. }
  1029. this.currentMember = prevMember;
  1030. }
  1031. // Hack because of previous continue usage
  1032. if (currentMember != null && !(currentMember is CodeTypeDeclaration)) {
  1033. if (currentMember.LinePragma != null)
  1034. GenerateLinePragmaEnd (currentMember.LinePragma);
  1035. #if NET_2_0
  1036. if (currentMember.EndDirectives.Count > 0)
  1037. GenerateDirectives (currentMember.EndDirectives);
  1038. #endif
  1039. }
  1040. GenerateTypeEnd (type);
  1041. this.currentType = prevType;
  1042. }
  1043. protected abstract string GetTypeOutput (CodeTypeReference type);
  1044. string ICodeGenerator.GetTypeOutput (CodeTypeReference type)
  1045. {
  1046. return GetTypeOutput (type);
  1047. }
  1048. protected abstract bool IsValidIdentifier (string value);
  1049. bool ICodeGenerator.IsValidIdentifier (string value)
  1050. {
  1051. return IsValidIdentifier (value);
  1052. }
  1053. public static bool IsValidLanguageIndependentIdentifier (string value)
  1054. {
  1055. if (value == null)
  1056. return false;
  1057. if (value.Equals (string.Empty))
  1058. return false;
  1059. switch (char.GetUnicodeCategory (value[0]))
  1060. {
  1061. case UnicodeCategory.LetterNumber:
  1062. case UnicodeCategory.LowercaseLetter:
  1063. case UnicodeCategory.TitlecaseLetter:
  1064. case UnicodeCategory.UppercaseLetter:
  1065. case UnicodeCategory.OtherLetter:
  1066. case UnicodeCategory.ModifierLetter:
  1067. case UnicodeCategory.ConnectorPunctuation:
  1068. if (value.Length > 1)
  1069. {
  1070. for (int x = 0; x < value.Length; x++)
  1071. {
  1072. switch (char.GetUnicodeCategory (value[x]))
  1073. {
  1074. case UnicodeCategory.LetterNumber:
  1075. case UnicodeCategory.LowercaseLetter:
  1076. case UnicodeCategory.TitlecaseLetter:
  1077. case UnicodeCategory.UppercaseLetter:
  1078. case UnicodeCategory.OtherLetter:
  1079. case UnicodeCategory.ModifierLetter:
  1080. case UnicodeCategory.ConnectorPunctuation:
  1081. case UnicodeCategory.DecimalDigitNumber:
  1082. case UnicodeCategory.NonSpacingMark:
  1083. case UnicodeCategory.SpacingCombiningMark:
  1084. case UnicodeCategory.Format:
  1085. return true;
  1086. }
  1087. return false;
  1088. }
  1089. }
  1090. else
  1091. return true;
  1092. break;
  1093. }
  1094. return false;
  1095. }
  1096. protected abstract bool Supports (GeneratorSupport supports);
  1097. bool ICodeGenerator.Supports (GeneratorSupport value)
  1098. {
  1099. return Supports (value);
  1100. }
  1101. protected virtual void ValidateIdentifier (string value)
  1102. {
  1103. if (!(IsValidIdentifier (value)))
  1104. throw new ArgumentException ("Identifier is invalid", "value");
  1105. }
  1106. [MonoTODO]
  1107. public static void ValidateIdentifiers (CodeObject e)
  1108. {
  1109. throw new NotImplementedException();
  1110. }
  1111. void ICodeGenerator.ValidateIdentifier (string value)
  1112. {
  1113. ValidateIdentifier (value);
  1114. }
  1115. // The position in the array determines the order in which those
  1116. // kind of CodeTypeMembers are generated. Less is more ;-)
  1117. static Type [] memberTypes = { typeof (CodeMemberField),
  1118. typeof (CodeSnippetTypeMember),
  1119. typeof (CodeTypeConstructor),
  1120. typeof (CodeConstructor),
  1121. typeof (CodeMemberProperty),
  1122. typeof (CodeMemberEvent),
  1123. typeof (CodeMemberMethod),
  1124. typeof (CodeTypeDeclaration),
  1125. typeof (CodeEntryPointMethod)
  1126. };
  1127. #if NET_2_0
  1128. protected virtual void GenerateDirectives (CodeDirectiveCollection directives)
  1129. {
  1130. }
  1131. #endif
  1132. }
  1133. }