CodeGenerator.cs 31 KB

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