xpCodeGen.pas
上传用户:yjb1804
上传日期:2021-01-30
资源大小:3105k
文件大小:10k
源码类别:

Email服务器

开发平台:

Delphi

  1. unit xpCodeGen;
  2. (*
  3.  * The contents of this file are subject to the Mozilla Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/MPL/
  7.  *
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  *
  13.  * This code was inspired to expidite the creation of unit tests
  14.  * for use the Dunit test frame work.
  15.  *
  16.  * The Initial Developer of XPGen is Michael A. Johnson.
  17.  * Portions created The Initial Developer is Copyright (C) 2000.
  18.  * Portions created by The DUnit Group are Copyright (C) 2000.
  19.  * All rights reserved.
  20.  *
  21.  * Contributor(s):
  22.  * Michael A. Johnson <majohnson@golden.net>
  23.  * Juanco A馿z <juanco@users.sourceforge.net>
  24.  * Chris Morris <chrismo@users.sourceforge.net>
  25.  * Jeff Moore <JeffMoore@users.sourceforge.net>
  26.  * The DUnit group at SourceForge <http://dunit.sourceforge.net>
  27.  *
  28.  *)
  29. {
  30. Unit        : xpCodeGen
  31. Description : This unit is responsible for generating output code from a sequence
  32.               of parse nodes generated by the parser
  33. Programmer  : mike
  34. Date        : 06-Jul-2000
  35. }
  36. interface
  37. uses
  38.   classes,
  39.   ParseDef,
  40.   xpParse;
  41. type
  42.   DriverSrcOutput = class
  43.   public
  44.     procedure OutputStart(NameOfUnit: string); virtual; abstract;
  45.     procedure OutputSrcCode(srcLine: string); virtual; abstract;
  46.     procedure OutputFinish; virtual; abstract;
  47.   end;
  48.   DriverSrcOutputTstrings = class(DriverSrcOutput)
  49.     fOutputStrings: TStrings;
  50.   public
  51.     constructor Create(newtarget: TStrings);
  52.     destructor Destroy; override;
  53.     procedure OutputStart(NameOfUnit: string); override;
  54.     procedure OutputSrcCode(srcLine: string); override;
  55.     procedure OutputFinish; override;
  56.   end;
  57.   DriverSrcOutputText = class(DriverSrcOutputTstrings)
  58.   protected
  59.     SourceCodeBuffer: TStringList;
  60.   public
  61.     constructor Create;
  62.     destructor Destroy; override;
  63.     function Text: string;
  64.   end;
  65.   SrcGenExternalTest = class
  66.   protected
  67.     fNameOfUnit: string;
  68.     ftestMethodPrefix: string;
  69.     fTestUnitPrefix: string;
  70.     fTestClassPrefix: string;
  71.     fOutputDriver: DriverSrcOutput;
  72.   public
  73.     constructor Create(newUnitName: string; driver: DriverSrcOutput);
  74.     destructor Destroy; override;
  75.     procedure GenerateCode(ParseNodeList: TList); virtual;
  76.   end;
  77. implementation
  78. uses
  79.   SysUtils;
  80. { DriverSrcOutputTstrings }
  81. constructor DriverSrcOutputTstrings.Create(newtarget: TStrings);
  82. begin
  83.   inherited Create;
  84.   fOutputStrings := newtarget;
  85. end;
  86. destructor DriverSrcOutputTstrings.Destroy;
  87. begin
  88.   inherited Destroy;
  89. end;
  90. procedure DriverSrcOutputTstrings.OutputFinish;
  91. begin
  92.   { it's necessary to provide an implementation because of the pure virtual designation }
  93. end;
  94. procedure DriverSrcOutputTstrings.OutputSrcCode(srcLine: string);
  95. begin
  96.   foutputStrings.Add(srcLine);
  97. end;
  98. procedure DriverSrcOutputTstrings.OutputStart(NameOfUnit: string);
  99. begin
  100.   { it's necessary to provide an implementation because of the pure virtual designation }
  101.   foutputStrings.clear;
  102. end;
  103. { SrcGenExternalTest }
  104. constructor SrcGenExternalTest.Create(newUnitName: string; driver:
  105.   DriverSrcOutput);
  106. begin
  107.   ftestMethodPrefix := 'Verify';
  108.   fTestUnitPrefix := 'Test_';
  109.   fTestClassPrefix := 'Check_';
  110.   fNameOfUnit := newUnitName;
  111.   fOutputDriver := driver;
  112.   inherited Create;
  113. end;
  114. destructor SrcGenExternalTest.Destroy;
  115. begin
  116.   inherited Destroy;
  117. end;
  118. procedure SrcGenExternalTest.GenerateCode(ParseNodeList: TList);
  119. {
  120. Procedure   : SrcGenExternalTest.GenerateCode
  121. Description : generates output based on the parsednodes found in the parse step
  122. Input       : ParseNodeList: TList
  123. Programmer  : mike
  124. Date        : 07-Jul-2000
  125. }
  126. var
  127.   methodIter,
  128.     NodeIter: integer;
  129.   parseNode: TParseNodeClass;
  130. begin
  131.   if assigned(foutputDriver) then
  132.     begin
  133.       with foutputDriver do
  134.         begin
  135.           OutputStart(fNameOfUnit);
  136.           OutputSrcCode('unit ' + fTestUnitPrefix + fNameOfUnit + ';');
  137.           OutputSrcCode('');
  138.           OutputSrcCode('interface');
  139.           OutputSrcCode('');
  140.           OutputSrcCode('uses');
  141.           OutputSrcCode('  ' + 'TestFramework' + ',');
  142.           OutputSrcCode('  ' + 'SysUtils' + ',');
  143.           OutputSrcCode('  ' + fNameOfUnit + ';');
  144.           OutputSrcCode('');
  145.           OutputSrcCode('type');
  146.           { generate crack classes for accessing protected methods }
  147.           for nodeIter := 0 to ParseNodeList.count - 1 do
  148.             begin
  149.               ParseNode := ParseNodeList[nodeIter];
  150.               if (ParseNode.PubMethodList.count > 0) or
  151.                 (ParseNode.PrtMethodList.count > 0) then
  152.                 begin
  153.                   OutputSrcCode('');
  154.                   OutputSrcCode('CRACK_' + ParseNode.NameClass + ' = class(' +
  155.                     ParseNode.NameClass + ');');
  156.                 end;
  157.             end;
  158.           for nodeIter := 0 to ParseNodeList.count - 1 do
  159.             begin
  160.               ParseNode := ParseNodeList[nodeIter];
  161.               if (ParseNode.PubMethodList.count > 0) or
  162.                 (ParseNode.PrtMethodList.count > 0) then
  163.                 begin
  164.                   OutputSrcCode('');
  165.                   OutputSrcCode(fTestClassPrefix + ParseNode.NameClass +
  166.                     ' = class(TTestCase)');
  167.                   OutputSrcCode('public');
  168.                   OutputSrcCode('   procedure setUp;  override;');
  169.                   OutputSrcCode('   procedure tearDown; override;');
  170.                   OutputSrcCode('published');
  171.                   { test the public/published/automated methods }
  172.                   for methodIter := 0 to ParseNode.PubMethodList.count - 1 do
  173.                     begin
  174.                       OutputSrcCode('   procedure ' + ftestMethodPrefix +
  175.                         ParseNode.PubMethodList[methodIter] + ';');
  176.                     end;
  177.                   { test the protected methods too }
  178.                   for methodIter := 0 to ParseNode.PrtMethodList.count - 1 do
  179.                     begin
  180.                       OutputSrcCode('   procedure ' + ftestMethodPrefix +
  181.                         ParseNode.PrtMethodList[methodIter] + ';');
  182.                     end;
  183.                   OutputSrcCode('end;');
  184.                 end;
  185.             end;
  186.           OutputSrcCode('');
  187.           OutputSrcCode('function Suite : ITestSuite;');
  188.           OutputSrcCode('');
  189.           OutputSrcCode('implementation');
  190.           OutputSrcCode('');
  191.           { write the implemention for the test suite }
  192.           OutputSrcCode('function Suite : ITestSuite;');
  193.           OutputSrcCode('begin');
  194.           outputSrcCode('  result := TTestSuite.Create(''' + fNameOfUnit +
  195.             ' Tests'');');
  196.           { add each test method to the suite for this unit }
  197.           for nodeIter := 0 to ParseNodeList.count - 1 do
  198.             begin
  199.               ParseNode := ParseNodeList[nodeIter];
  200.               if (ParseNode.PubMethodList.count > 0) or
  201.                 (ParseNode.PrtMethodList.count > 0) then
  202.                 begin
  203.                   OutputSrcCode('');
  204.                   OutputSrcCode(format('  result.addTest(testSuiteOf(%s%s));',
  205.                     [fTestClassPrefix, ParseNode.NameClass]));
  206.                 end;
  207.             end;
  208.           OutputSrcCode('end;');
  209.           { write the implementation for each of the test classes }
  210.           for nodeIter := 0 to ParseNodeList.count - 1 do
  211.             begin
  212.               ParseNode := ParseNodeList[nodeIter];
  213.               if (ParseNode.PubMethodList.count > 0) or
  214.                 (ParseNode.PrtMethodList.count > 0) then
  215.                 begin
  216.                   OutputSrcCode('');
  217.                   OutputSrcCode('procedure ' + fTestClassPrefix +
  218.                     ParseNode.NameClass + '.setUp;');
  219.                   OutputSrcCode('begin');
  220.                   OutputSrcCode('end;');
  221.                   OutputSrcCode('');
  222.                   OutputSrcCode('procedure ' + fTestClassPrefix +
  223.                     ParseNode.NameClass + '.tearDown;');
  224.                   OutputSrcCode('begin');
  225.                   OutputSrcCode('end;');
  226.                   { generate public,automated and published methods }
  227.                   for methodIter := 0 to ParseNode.PubMethodList.count - 1 do
  228.                     begin
  229.                       OutputSrcCode('');
  230.                       OutputSrcCode('procedure ' + fTestClassPrefix +
  231.                         ParseNode.NameClass + '.' + fTestMethodPrefix +
  232.                         ParseNode.PubMethodList[methodIter] + ';');
  233.                       OutputSrcCode('begin');
  234.                       OutputSrcCode('   fail(''Test Not Implemented Yet'');');
  235.                       OutputSrcCode('end;');
  236.                     end;
  237.                   { generate for the protected ones too }
  238.                   for methodIter := 0 to ParseNode.PrtMethodList.count - 1 do
  239.                     begin
  240.                       OutputSrcCode('');
  241.                       OutputSrcCode('procedure ' + fTestClassPrefix +
  242.                         ParseNode.NameClass + '.' + fTestMethodPrefix +
  243.                         ParseNode.PrtMethodList[methodIter] + ';');
  244.                       OutputSrcCode('begin');
  245.                       OutputSrcCode('   fail(''Test Not Implemented Yet'');');
  246.                       OutputSrcCode('end;');
  247.                     end;
  248.                 end;
  249.             end;
  250.           OutputSrcCode('');
  251.           OutputSrcCode('end.');
  252.           OutputFinish;
  253.         end;
  254.     end;
  255. end;
  256. { DriverSrcOutputText }
  257. constructor DriverSrcOutputText.Create;
  258. begin
  259.   { create a stub where this data can be held }
  260.   SourceCodeBuffer := TStringList.Create;
  261.   inherited create(SourceCodeBuffer);
  262. end;
  263. destructor DriverSrcOutputText.Destroy;
  264. begin
  265.   SourceCodeBuffer.Free;
  266.   inherited Destroy;
  267. end;
  268. function DriverSrcOutputText.Text: string;
  269. var
  270.   sourceLineIter: integer;
  271. begin
  272.   result := '';
  273.   { generate text when there is something to output }
  274.   if SourceCodeBuffer.Count > 0 then
  275.     begin
  276.       result := SourceCodeBuffer[0];
  277.       { output any other text that we need }
  278.       for sourceLineIter := 1 to SourceCodeBuffer.Count - 1 do
  279.         begin
  280.           result := result + #13 + SourceCodeBuffer[sourceLineIter];
  281.         end;
  282.     end;
  283. end;
  284. end.