2

我正在编写一个与 Delphi DWScript一起使用的 IDE ,现在有一个简单的可调试脚本。我现在想突出显示源代码中的可执行行(如 Delphi 源代码左侧的蓝点)。挖掘示例/信息我看到有一个程序'SymbolDictionary',我可以在其中调用'FindSymbolUsage(suReference)' - 这似乎给了我'被引用'的符号位置,我想我可以用'再次调用它suImplementation' 以获取有分配的行。这让我意识到,虽然我可以理解 ContextMap 和 SymbolDictionary 的结构和目的实际上是什么。有没有人列出脚本的可执行行号的示例?

我的初出茅庐的代码在下面复制,正在等待关键分析:-) 谢谢

  TExecutableLines = class( TObject )
    constructor Create;
    destructor  Destroy; override;
  PRIVATE
    FLines : TBits;
    function GetIsExecutable(ALineNumber: integer): boolean;
    procedure SetIsExecutable(ALineNumber: integer; const Value: boolean);
  PUBLIC
    procedure Clear;

    procedure Evaluate( AProgram : IdwsProgram; const AUnitName : string );

    property  IsExecutable[ALineNumber : integer] : boolean
                read GetIsExecutable
                write SetIsExecutable;
  end;





{ TExecutableLines }

procedure TExecutableLines.Clear;
begin
  FLines.Size := 0;
  FLines.Size := 1024;
end;

constructor TExecutableLines.Create;
begin
  inherited;

  FLines := TBits.Create;
end;

destructor TExecutableLines.Destroy;
begin
  FreeAndnil( FLines );
  inherited;
end;

procedure TExecutableLines.Evaluate(AProgram: IdwsProgram; const AUnitName : string);
var
  I : integer;
  Pos : TSymbolPosition;
begin
  Clear;
  For I := 0 to AProgram.SymbolDictionary.Count-1 do
    begin
    Pos := AProgram.SymbolDictionary.FindSymbolPosList(
      AProgram.SymbolDictionary[I].Symbol ).FindUsage( suReference);
    if Pos <> nil then
      If Pos.ScriptPos.IsMainModule then
        IsExecutable[ Pos.ScriptPos.Line ] := True
       else
         if SameText( Pos.UnitName, AUnitName ) then
            IsExecutable[ Pos.ScriptPos.Line ] := True
    end;

end;

function TExecutableLines.GetIsExecutable(ALineNumber: integer): boolean;
begin
  if ALineNumber = 0 then
    raise Exception.Create('Lines numbers are 1..n' );

  if ALineNumber < FLines.Size then
    Result := FLines[ALineNumber]
   else
     Result := False;
end;

procedure TExecutableLines.SetIsExecutable(ALineNumber: integer;
  const Value: boolean);
begin
  if ALineNumber = 0 then
    raise Exception.Create('Lines numbers are 1..n' );

  if ALineNumber >= FLines.Size then
    FLines.Size := ALineNumber+1;
  FLines[ALineNumber] := Value;
end;
4

1 回答 1

3

TdwsSymbolDictionary 有不同的用途,主要是知道在哪里(如果)声明或使用符号,以及简化重命名重构等事情(请参阅http://delphitools.info/2011/02/19/spotlight-on-tsymboldictionary /)。

TdwsSourceContextMap 用于了解源代码中的代码“块”在哪里(fi 类声明开始和结束的位置,函数实现开始和结束的位置等),“跳转”到代码中的某个位置都很有用,或者根据符号知道光标在哪里。

你所追求的是另一个信息,它是与编译表达式相对应的行。为此,您需要查看编译的内容,TExprBase.SubExpr/SubExprCount 是您的主力,或者包装它们的实用函数 RecursiveEnumerateSubExprs。使用该函数,您可以查看程序中的所有表达式,从 TdwsProgram.Expr 和 TdwsProgram.InitExpr 开始(您可以将 IdwsProgram 转换为 TdwsProgram 以获取这些属性)。

这些是您可以设置断点的地方。

作为一个例子,假设你有

1.   function Dummy : Integer;
2.   var i : Integer;
3.   begin
4.      while i<10 do begin
5.         Inc(i);
6.         if i>5 then
7.            break;
8.      end;
9.   end;

然后,如果我没记错的话(突然这样做):

  • 符号字典将在 1 处列出“Dummy”的声明,在 1 和 2 处列出“Integer”的使用,在 2 处列出“i”的声明,在 4、5 和 6 处列出“i”的使用。

  • 上下文映射将包含函数块、主块和 while 循环。

  • 编译表达式的行将是 2 (.InitExpr) 和 4, 5, 6 & 7 (.Expr)

于 2011-09-02T07:50:34.887 回答