CodeGenerator.cs 29 KB

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