CodeGenerator.cs 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  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. if (e.Value is bool) {
  345. output.Write (e.Value.ToString ().ToLower ());
  346. return;
  347. }
  348. output.Write (e.Value);
  349. }
  350. protected abstract void GenerateProperty (CodeMemberProperty p, CodeTypeDeclaration d);
  351. protected abstract void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression e);
  352. protected abstract void GeneratePropertySetValueReferenceExpression( CodePropertySetValueReferenceExpression e );
  353. protected abstract void GenerateRemoveEventStatement( CodeRemoveEventStatement statement );
  354. protected abstract void GenerateSnippetExpression( CodeSnippetExpression e );
  355. protected abstract void GenerateSnippetMember( CodeSnippetTypeMember m );
  356. protected virtual void GenerateSnippetStatement( CodeSnippetStatement s )
  357. {
  358. output.Write( s.Value );
  359. }
  360. protected void GenerateStatement( CodeStatement s )
  361. {
  362. CodeAssignStatement assign = s as CodeAssignStatement;
  363. if ( assign != null ) {
  364. GenerateAssignStatement( assign );
  365. return;
  366. }
  367. CodeAttachEventStatement attach = s as CodeAttachEventStatement;
  368. if ( attach != null ) {
  369. GenerateAttachEventStatement( attach );
  370. return;
  371. }
  372. CodeCommentStatement comment = s as CodeCommentStatement;
  373. if ( comment != null ) {
  374. GenerateCommentStatement( comment );
  375. return;
  376. }
  377. CodeConditionStatement condition = s as CodeConditionStatement;
  378. if ( condition != null ) {
  379. GenerateConditionStatement( condition );
  380. return;
  381. }
  382. CodeExpressionStatement expression = s as CodeExpressionStatement;
  383. if ( expression != null ) {
  384. GenerateExpressionStatement( expression );
  385. return;
  386. }
  387. CodeGotoStatement gotostmt = s as CodeGotoStatement;
  388. if ( gotostmt != null ) {
  389. GenerateGotoStatement( gotostmt );
  390. return;
  391. }
  392. CodeIterationStatement iteration = s as CodeIterationStatement;
  393. if ( iteration != null ) {
  394. GenerateIterationStatement( iteration );
  395. return;
  396. }
  397. CodeLabeledStatement label = s as CodeLabeledStatement;
  398. if ( label != null ) {
  399. GenerateLabeledStatement( label );
  400. return;
  401. }
  402. CodeMethodReturnStatement returnstmt = s as CodeMethodReturnStatement;
  403. if ( returnstmt != null ) {
  404. GenerateMethodReturnStatement( returnstmt );
  405. return;
  406. }
  407. CodeRemoveEventStatement remove = s as CodeRemoveEventStatement;
  408. if ( remove != null ) {
  409. GenerateRemoveEventStatement( remove );
  410. return;
  411. }
  412. CodeSnippetStatement snippet = s as CodeSnippetStatement;
  413. if ( snippet != null ) {
  414. GenerateSnippetStatement( snippet );
  415. return;
  416. }
  417. CodeThrowExceptionStatement exception = s as CodeThrowExceptionStatement;
  418. if ( exception != null ) {
  419. GenerateThrowExceptionStatement( exception );
  420. return;
  421. }
  422. CodeTryCatchFinallyStatement trycatch = s as CodeTryCatchFinallyStatement;
  423. if ( trycatch != null ) {
  424. GenerateTryCatchFinallyStatement( trycatch );
  425. return;
  426. }
  427. CodeVariableDeclarationStatement declaration = s as CodeVariableDeclarationStatement;
  428. if ( declaration != null ) {
  429. GenerateVariableDeclarationStatement( declaration );
  430. return;
  431. }
  432. }
  433. protected void GenerateStatements( CodeStatementCollection c )
  434. {
  435. foreach ( CodeStatement statement in c )
  436. GenerateStatement( statement );
  437. }
  438. protected abstract void GenerateThisReferenceExpression (CodeThisReferenceExpression e);
  439. protected abstract void GenerateThrowExceptionStatement (CodeThrowExceptionStatement s);
  440. protected abstract void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement s);
  441. protected abstract void GenerateTypeEnd( CodeTypeDeclaration declaration );
  442. protected abstract void GenerateTypeConstructor( CodeTypeConstructor constructor );
  443. protected virtual void GenerateTypeOfExpression (CodeTypeOfExpression e)
  444. {
  445. output.Write( "typeof(" );
  446. OutputType( e.Type );
  447. output.Write( ")" );
  448. }
  449. protected virtual void GenerateTypeReferenceExpression (CodeTypeReferenceExpression e)
  450. {
  451. OutputType( e.Type );
  452. }
  453. protected abstract void GenerateTypeStart( CodeTypeDeclaration declaration );
  454. protected abstract void GenerateVariableDeclarationStatement (CodeVariableDeclarationStatement e);
  455. protected abstract void GenerateVariableReferenceExpression( CodeVariableReferenceExpression e );
  456. //
  457. // Other members
  458. //
  459. /*
  460. * Output Methods
  461. */
  462. protected virtual void OutputAttributeArgument( CodeAttributeArgument argument )
  463. {
  464. string name = argument.Name;
  465. if ( name != null ) {
  466. output.Write( name );
  467. output.Write( '=' );
  468. }
  469. GenerateExpression( argument.Value );
  470. }
  471. private void OutputAttributeDeclaration( CodeAttributeDeclaration attribute )
  472. {
  473. output.Write( attribute.Name );
  474. output.Write( '(' );
  475. IEnumerator enumerator = attribute.Arguments.GetEnumerator();
  476. if ( enumerator.MoveNext() ) {
  477. CodeAttributeArgument argument = (CodeAttributeArgument)enumerator.Current;
  478. OutputAttributeArgument( argument );
  479. while ( enumerator.MoveNext() ) {
  480. output.Write( ',' );
  481. argument = (CodeAttributeArgument)enumerator.Current;
  482. OutputAttributeArgument( argument );
  483. }
  484. }
  485. output.Write( ')' );
  486. }
  487. protected virtual void OutputAttributeDeclarations( CodeAttributeDeclarationCollection attributes )
  488. {
  489. GenerateAttributeDeclarationsStart( attributes );
  490. IEnumerator enumerator = attributes.GetEnumerator();
  491. if ( enumerator.MoveNext() ) {
  492. CodeAttributeDeclaration attribute = (CodeAttributeDeclaration)enumerator.Current;
  493. OutputAttributeDeclaration( attribute );
  494. while ( enumerator.MoveNext() ) {
  495. attribute = (CodeAttributeDeclaration)enumerator.Current;
  496. output.WriteLine( ',' );
  497. OutputAttributeDeclaration( attribute );
  498. }
  499. }
  500. GenerateAttributeDeclarationsEnd( attributes );
  501. }
  502. protected virtual void OutputDirection( FieldDirection direction )
  503. {
  504. switch ( direction ) {
  505. case FieldDirection.In:
  506. //output.Write( "in " );
  507. break;
  508. case FieldDirection.Out:
  509. output.Write( "out " );
  510. break;
  511. case FieldDirection.Ref:
  512. output.Write( "ref " );
  513. break;
  514. }
  515. }
  516. protected virtual void OutputExpressionList( CodeExpressionCollection expressions )
  517. {
  518. OutputExpressionList( expressions, false );
  519. }
  520. protected virtual void OutputExpressionList( CodeExpressionCollection expressions,
  521. bool newLineBetweenItems )
  522. {
  523. IEnumerator enumerator = expressions.GetEnumerator();
  524. if ( enumerator.MoveNext() ) {
  525. CodeExpression expression = (CodeExpression)enumerator.Current;
  526. GenerateExpression( expression );
  527. while ( enumerator.MoveNext() ) {
  528. expression = (CodeExpression)enumerator.Current;
  529. output.Write( ',' );
  530. if ( newLineBetweenItems )
  531. output.WriteLine();
  532. else
  533. output.Write( ' ' );
  534. GenerateExpression( expression );
  535. }
  536. }
  537. }
  538. protected virtual void OutputFieldScopeModifier( MemberAttributes attributes )
  539. {
  540. if ( (attributes & MemberAttributes.VTableMask) == MemberAttributes.New )
  541. output.Write( "new " );
  542. switch ( attributes & MemberAttributes.ScopeMask ) {
  543. case MemberAttributes.Static:
  544. output.Write( "static " );
  545. break;
  546. case MemberAttributes.Const:
  547. output.Write( "const " );
  548. break;
  549. }
  550. }
  551. protected virtual void OutputIdentifier( string ident )
  552. {
  553. output.Write (ident);
  554. }
  555. protected virtual void OutputMemberAccessModifier( MemberAttributes attributes )
  556. {
  557. switch ( attributes & MemberAttributes.AccessMask ) {
  558. case MemberAttributes.Assembly:
  559. output.Write( "internal " );
  560. break;
  561. case MemberAttributes.FamilyAndAssembly:
  562. output.Write( "/* FamAndAssem */ internal " );
  563. break;
  564. case MemberAttributes.Family:
  565. output.Write( "protected " );
  566. break;
  567. case MemberAttributes.FamilyOrAssembly:
  568. output.Write( "protected internal " );
  569. break;
  570. case MemberAttributes.Private:
  571. output.Write( "private " );
  572. break;
  573. case MemberAttributes.Public:
  574. output.Write( "public " );
  575. break;
  576. }
  577. }
  578. protected virtual void OutputMemberScopeModifier( MemberAttributes attributes )
  579. {
  580. if ( (attributes & MemberAttributes.VTableMask) == MemberAttributes.New )
  581. output.Write( "new " );
  582. switch ( attributes & MemberAttributes.ScopeMask ) {
  583. case MemberAttributes.Abstract:
  584. output.Write( "abstract " );
  585. break;
  586. case MemberAttributes.Final:
  587. // Do nothing
  588. break;
  589. case MemberAttributes.Static:
  590. output.Write( "static " );
  591. break;
  592. case MemberAttributes.Override:
  593. output.Write( "override " );
  594. break;
  595. default:
  596. //
  597. // FUNNY! if the scope value is
  598. // rubbish (0 or >Const), and access
  599. // is public or protected, make it
  600. // "virtual".
  601. //
  602. // i'm not sure whether this is 100%
  603. // correct, but it seems to be MS
  604. // behavior.
  605. //
  606. MemberAttributes access = attributes & MemberAttributes.AccessMask;
  607. if ( access == MemberAttributes.Public ||
  608. access == MemberAttributes.Family )
  609. output.Write( "virtual " );
  610. break;
  611. }
  612. }
  613. protected virtual void OutputOperator( CodeBinaryOperatorType op )
  614. {
  615. switch (op) {
  616. case CodeBinaryOperatorType.Add:
  617. output.Write ("+");
  618. break;
  619. case CodeBinaryOperatorType.Subtract:
  620. output.Write ("-");
  621. break;
  622. case CodeBinaryOperatorType.Multiply:
  623. output.Write ("*");
  624. break;
  625. case CodeBinaryOperatorType.Divide:
  626. output.Write ("/");
  627. break;
  628. case CodeBinaryOperatorType.Modulus:
  629. output.Write ("%");
  630. break;
  631. case CodeBinaryOperatorType.Assign:
  632. output.Write ("=");
  633. break;
  634. case CodeBinaryOperatorType.IdentityInequality:
  635. output.Write ("!=");
  636. break;
  637. case CodeBinaryOperatorType.IdentityEquality:
  638. output.Write ("==");
  639. break;
  640. case CodeBinaryOperatorType.ValueEquality:
  641. output.Write ("==");
  642. break;
  643. case CodeBinaryOperatorType.BitwiseOr:
  644. output.Write ("|");
  645. break;
  646. case CodeBinaryOperatorType.BitwiseAnd:
  647. output.Write ("&");
  648. break;
  649. case CodeBinaryOperatorType.BooleanOr:
  650. output.Write ("||");
  651. break;
  652. case CodeBinaryOperatorType.BooleanAnd:
  653. output.Write ("&&");
  654. break;
  655. case CodeBinaryOperatorType.LessThan:
  656. output.Write ("<");
  657. break;
  658. case CodeBinaryOperatorType.LessThanOrEqual:
  659. output.Write ("<=");
  660. break;
  661. case CodeBinaryOperatorType.GreaterThan:
  662. output.Write (">");
  663. break;
  664. case CodeBinaryOperatorType.GreaterThanOrEqual:
  665. output.Write (">=");
  666. break;
  667. }
  668. }
  669. protected virtual void OutputParameters( CodeParameterDeclarationExpressionCollection parameters )
  670. {
  671. bool first = true;
  672. foreach (CodeParameterDeclarationExpression expr in parameters) {
  673. GenerateExpression (expr);
  674. if (first)
  675. first = false;
  676. else
  677. output.Write (", ");
  678. }
  679. }
  680. protected abstract void OutputType( CodeTypeReference t );
  681. protected virtual void OutputTypeAttributes( TypeAttributes attributes,
  682. bool isStruct,
  683. bool isEnum )
  684. {
  685. switch ( attributes & TypeAttributes.VisibilityMask ) {
  686. case TypeAttributes.NotPublic:
  687. // private by default
  688. break;
  689. case TypeAttributes.Public:
  690. case TypeAttributes.NestedPublic:
  691. output.Write( "public " );
  692. break;
  693. case TypeAttributes.NestedPrivate:
  694. output.Write( "private " );
  695. break;
  696. }
  697. if ( isStruct )
  698. output.Write( "struct " );
  699. else if ( isEnum )
  700. output.Write( "enum " );
  701. else {
  702. if ( (attributes & TypeAttributes.Interface) != 0 )
  703. output.Write( "interface " );
  704. else {
  705. if ( (attributes & TypeAttributes.Sealed) != 0 )
  706. output.Write( "sealed " );
  707. if ( (attributes & TypeAttributes.Abstract) != 0 )
  708. output.Write( "abstract " );
  709. output.Write( "class " );
  710. }
  711. }
  712. }
  713. protected virtual void OutputTypeNamePair( CodeTypeReference type,
  714. string name )
  715. {
  716. OutputType( type );
  717. output.Write( ' ' );
  718. output.Write( name );
  719. }
  720. protected abstract string QuoteSnippetString( string value );
  721. /*
  722. * ICodeGenerator
  723. */
  724. protected abstract string CreateEscapedIdentifier( string value );
  725. string ICodeGenerator.CreateEscapedIdentifier( string value )
  726. {
  727. return CreateEscapedIdentifier( value );
  728. }
  729. protected abstract string CreateValidIdentifier( string value );
  730. string ICodeGenerator.CreateValidIdentifier( string value )
  731. {
  732. return CreateValidIdentifier( value );
  733. }
  734. private void InitOutput( TextWriter output, CodeGeneratorOptions options )
  735. {
  736. if ( options == null )
  737. options = new CodeGeneratorOptions();
  738. this.output = new IndentedTextWriter( output, options.IndentString );
  739. this.options = options;
  740. }
  741. public virtual void GenerateCodeFromCompileUnit( CodeCompileUnit compileUnit,
  742. TextWriter output,
  743. CodeGeneratorOptions options )
  744. {
  745. InitOutput( output, options );
  746. GenerateCompileUnit( compileUnit );
  747. }
  748. [MonoTODO]
  749. public virtual void GenerateCodeFromExpression( CodeExpression expression,
  750. TextWriter output,
  751. CodeGeneratorOptions options )
  752. {
  753. InitOutput( output, options );
  754. }
  755. public virtual void GenerateCodeFromNamespace( CodeNamespace ns,
  756. TextWriter output,
  757. CodeGeneratorOptions options )
  758. {
  759. InitOutput( output, options );
  760. GenerateNamespace( ns );
  761. }
  762. public virtual void GenerateCodeFromStatement( CodeStatement statement,
  763. TextWriter output,
  764. CodeGeneratorOptions options )
  765. {
  766. InitOutput( output, options );
  767. }
  768. public virtual void GenerateCodeFromType( CodeTypeDeclaration type,
  769. TextWriter output,
  770. CodeGeneratorOptions options )
  771. {
  772. CodeTypeDeclaration prevType = this.currentType;
  773. this.currentType = type;
  774. InitOutput( output, options );
  775. GenerateTypeStart( type );
  776. CodeTypeMember [] members = new CodeTypeMember [type.Members.Count];
  777. type.Members.CopyTo (members, 0);
  778. Array.Sort (members, CodeTypeMemberComparer.Default);
  779. // WARNING: if anything is missing in the foreach loop and you add it, add the type in
  780. // its corresponding place in CodeTypeMemberComparer class (below)
  781. foreach ( CodeTypeMember member in members ) {
  782. CodeTypeMember prevMember = this.currentMember;
  783. this.currentMember = member;
  784. if ( options.BlankLinesBetweenMembers )
  785. output.WriteLine();
  786. CodeMemberEvent eventm = member as CodeMemberEvent;
  787. if ( eventm != null ) {
  788. GenerateEvent( eventm, type );
  789. continue;
  790. }
  791. CodeMemberField field = member as CodeMemberField;
  792. if ( field != null ) {
  793. GenerateField( field );
  794. continue;
  795. }
  796. CodeEntryPointMethod epmethod = member as CodeEntryPointMethod;
  797. if ( epmethod != null ) {
  798. GenerateEntryPointMethod( epmethod, type );
  799. continue;
  800. }
  801. CodeTypeConstructor typeCtor = member as CodeTypeConstructor;
  802. if (typeCtor != null) {
  803. GenerateTypeConstructor (typeCtor);
  804. continue;
  805. }
  806. CodeConstructor ctor = member as CodeConstructor;
  807. if (ctor != null) {
  808. GenerateConstructor (ctor, type);
  809. continue;
  810. }
  811. CodeMemberMethod method = member as CodeMemberMethod;
  812. if ( method != null ) {
  813. GenerateMethod( method, type );
  814. continue;
  815. }
  816. CodeMemberProperty property = member as CodeMemberProperty;
  817. if ( property != null ) {
  818. GenerateProperty( property, type );
  819. continue;
  820. }
  821. CodeSnippetTypeMember snippet = member as CodeSnippetTypeMember;
  822. if ( snippet != null ) {
  823. GenerateSnippetMember( snippet );
  824. continue;
  825. }
  826. CodeTypeDeclaration subtype = member as CodeTypeDeclaration;
  827. if ( subtype != null ) {
  828. GenerateCodeFromType( subtype, output, options );
  829. continue;
  830. }
  831. this.currentMember = prevMember;
  832. }
  833. GenerateTypeEnd( type );
  834. this.currentType = prevType;
  835. }
  836. protected abstract string GetTypeOutput( CodeTypeReference type );
  837. string ICodeGenerator.GetTypeOutput( CodeTypeReference type )
  838. {
  839. return GetTypeOutput( type );
  840. }
  841. protected abstract bool IsValidIdentifier( string value );
  842. bool ICodeGenerator.IsValidIdentifier( string value )
  843. {
  844. return IsValidIdentifier( value );
  845. }
  846. protected abstract bool Supports( GeneratorSupport supports );
  847. bool ICodeGenerator.Supports( GeneratorSupport value )
  848. {
  849. return Supports( value );
  850. }
  851. [MonoTODO]
  852. protected virtual void ValidateIdentifier( string value )
  853. {
  854. throw new NotImplementedException();
  855. }
  856. void ICodeGenerator.ValidateIdentifier( string value )
  857. {
  858. ValidateIdentifier( value );
  859. }
  860. class CodeTypeMemberComparer : IComparer
  861. {
  862. private CodeTypeMemberComparer () {}
  863. static CodeTypeMemberComparer instance = new CodeTypeMemberComparer ();
  864. // The position in the array determines the order in which those
  865. // kind of CodeTypeMembers are generated. Less is more ;-)
  866. static Type [] memberTypes = { typeof (CodeMemberField),
  867. typeof (CodeSnippetTypeMember),
  868. typeof (CodeTypeConstructor),
  869. typeof (CodeConstructor),
  870. typeof (CodeMemberProperty),
  871. typeof (CodeMemberEvent),
  872. typeof (CodeMemberMethod),
  873. typeof (CodeTypeDeclaration),
  874. typeof (CodeEntryPointMethod)
  875. };
  876. public IComparer Default {
  877. get { return instance; }
  878. }
  879. int IComparer.Compare (object x, object y)
  880. {
  881. int xindex = Array.IndexOf (memberTypes, x.GetType ());
  882. int yindex = Array.IndexOf (memberTypes, y.GetType ());
  883. return xindex - yindex;
  884. }
  885. }
  886. }
  887. }