Componentes.Terceros.jcl/official/2.1.1/experts/stacktraceviewer/JclStackTraceViewerStackCodeUtils.pas

271 lines
9.7 KiB
ObjectPascal
Raw Permalink Normal View History

{**************************************************************************************************}
{ }
{ Project JEDI Code Library (JCL) }
{ }
{ The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
{ you may not use this file except in compliance with the License. You may obtain a copy of the }
{ License at http://www.mozilla.org/MPL/ }
{ }
{ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF }
{ ANY KIND, either express or implied. See the License for the specific language governing rights }
{ and limitations under the License. }
{ }
{ The Original Code is JclStackTraceViewerStackCodeUtils.pas. }
{ }
{ The Initial Developer of the Original Code is Uwe Schuster. }
{ Portions created by Uwe Schuster are Copyright (C) 2009 Uwe Schuster. All rights reserved. }
{ }
{ Contributor(s): }
{ Uwe Schuster (uschuster) }
{ }
{**************************************************************************************************}
{ }
{ Last modified: $Date:: 2009-08-25 20:22:46 +0200 (mar., 25 août 2009) $ }
{ Revision: $Rev:: 2969 $ }
{ Author: $Author:: outchy $ }
{ }
{**************************************************************************************************}
unit JclStackTraceViewerStackCodeUtils;
{$I jcl.inc}
interface
uses
SysUtils,
{$IFNDEF BDS}
Windows, Classes,
{$ENDIF ~BDS}
ActiveX, ToolsAPI,
{$IFDEF UNITVERSIONING}
JclUnitVersioning,
{$ENDIF UNITVERSIONING}
JclOtaUtils,
JclStackTraceViewerAPI;
function FindModule(const AFileName: string): string;
function FindModuleAndProject(const AFileName: string; var AProjectName: string): string;
function GetFileEditorContent(const AFileName: string): IStream;
procedure JumpToCode(AStackViewItem: IJclLocationInfo);
{$IFDEF UNITVERSIONING}
const
UnitVersioning: TUnitVersionInfo = (
RCSfile: '$URL: https://jcl.svn.sourceforge.net/svnroot/jcl/tags/JCL-2.1-Build3536/jcl/experts/stacktraceviewer/JclStackTraceViewerStackCodeUtils.pas $';
Revision: '$Revision: 2969 $';
Date: '$Date: 2009-08-25 20:22:46 +0200 (mar., 25 août 2009) $';
LogPath: 'JCL\experts\stacktraceviewer';
Extra: '';
Data: nil
);
{$ENDIF UNITVERSIONING}
implementation
function FindModuleInfoInProject(AProject: IOTAProject; const AFileName: string): IOTAModuleInfo;
var
I, P: Integer;
ModuleInfo: IOTAModuleInfo;
S, S2: string;
begin
Result := nil;
if AProject.GetModuleCount > 0 then
begin
S := UpperCase(AFileName);
for I := 0 to Pred(AProject.GetModuleCount) do
begin
ModuleInfo := AProject.GetModule(I);
if Assigned(ModuleInfo) then
begin
S2 := UpperCase(ModuleInfo.FileName);
P := Pos(S, S2);
if (P > 0) and (P = Length(S2) - Length(S) + 1) then
begin
Result := ModuleInfo;
Break;
end;
end;
end;
end;
end;
function FindModule(const AFileName: string): string;
var
Dummy: string;
begin
Result := FindModuleAndProject(AFilename, Dummy);
end;
function FindModuleInfoAndProject(const AFileName: string; var AProjectName: string): IOTAModuleInfo;
var
I: Integer;
ProjectGroup: IOTAProjectGroup;
begin
Result := nil;
AProjectName := '';
{$IFDEF BDS}
ProjectGroup := (BorlandIDEServices as IOTAModuleServices).MainProjectGroup;
{$ELSE ~BDS}
ProjectGroup := TJclOTAExpertBase.GetProjectGroup;
{$ENDIF ~BDS}
if Assigned(ProjectGroup) then
for I := 0 to ProjectGroup.ProjectCount - 1 do
begin
Result := FindModuleInfoInProject(ProjectGroup.Projects[I], AFileName);
if Assigned(Result) then
begin
AProjectName := ProjectGroup.Projects[I].FileName;
Break;
end;
end;
end;
function FindModuleAndProject(const AFileName: string; var AProjectName: string): string;
var
ModuleInfo: IOTAModuleInfo;
begin
ModuleInfo := FindModuleInfoAndProject(AFileName, AProjectName);
if Assigned(ModuleInfo) then
Result := ModuleInfo.FileName
else
Result := '';
end;
function GetFileEditorContent(const AFileName: string): IStream;
var
I: Integer;
Module: IOTAModule;
{$IFDEF BDS}
EditorContent: IOTAEditorContent;
{$ELSE ~BDS}
ContentPos, ReadCount, BufferSize: Integer;
Buffer: Pointer;
ModuleSourceEditor: IOTASourceEditor;
ModuleReader: IOTAEditReader;
S: TStream;
SA: TStreamAdapter;
{$ENDIF ~BDS}
begin
Result := nil;
Module := (BorlandIDEServices as IOTAModuleServices).FindModule(AFileName);
if Assigned(Module) then
begin
{$IFDEF BDS}
for I := 0 to Module.ModuleFileCount - 1 do
if Supports(Module.ModuleFileEditors[I], IOTAEditorContent, EditorContent) then
begin
Result := EditorContent.Content;
Break;
end;
{$ELSE ~BDS}
for I := 0 to Module.GetModuleFileCount - 1 do
if Supports(Module.GetModuleFileEditor(I), IOTASourceEditor, ModuleSourceEditor) then
begin
ModuleReader := ModuleSourceEditor.CreateReader;
if Assigned(ModuleReader) then
begin
ContentPos := 0;
BufferSize := 4096;
SA := TStreamAdapter.Create(TMemoryStream.Create, soOwned);
S := SA.Stream;
Result := SA;
GetMem(Buffer, BufferSize);
try
ReadCount := BufferSize;
while ReadCount = BufferSize do
begin
ReadCount := ModuleReader.GetText(ContentPos, Buffer, ReadCount);
if ReadCount > 0 then
begin
Inc(ContentPos, BufferSize);
S.Write(Buffer^, ReadCount);
end;
end;
finally
FreeMem(Buffer);
end;
end;
Break;
end;
{$ENDIF ~BDS}
end;
end;
procedure JumpToCode(AStackViewItem: IJclLocationInfo);
var
S, FileName, ProjectName: string;
Module: IOTAModule;
ModuleInfo: IOTAModuleInfo;
SourceEditor: IOTASourceEditor;
I, LineNumber: Integer;
EditPos: TOTAEditPos;
PreparedLocationInfo: IJclPreparedLocationInfo;
begin
if Assigned(AStackViewItem) then
begin
if AStackViewItem.QueryInterface(IJclPreparedLocationInfo, PreparedLocationInfo) <> S_OK then
PreparedLocationInfo := nil;
FileName := AStackViewItem.SourceName;
ModuleInfo := FindModuleInfoAndProject(FileName, ProjectName);
if Assigned(ModuleInfo) then
begin
S := ModuleInfo.FileName;
if (S <> '') and Assigned(BorlandIDEServices) then
begin
{$IFDEF BDS}
Module := (BorlandIDEServices as IOTAModuleServices).OpenModule(S);
{$ELSE ~BDS}
Module := ModuleInfo.OpenModule;
{$ENDIF ~BDS}
end;
end
else
if Assigned(PreparedLocationInfo) and PreparedLocationInfo.FoundFile then
begin
{$IFDEF BDS}
Module := (BorlandIDEServices as IOTAModuleServices).OpenModule(PreparedLocationInfo.FileName);
{$ELSE ~BDS}
(BorlandIDEServices as IOTAActionServices).OpenFile(PreparedLocationInfo.FileName);
Module := (BorlandIDEServices as IOTAModuleServices).FindModule(PreparedLocationInfo.FileName);
{$ENDIF ~BDS}
end;
if Assigned(Module) then
begin
{$IFDEF BDS}
Module.Show;
{$ENDIF BDS}
for I := 0 to Module.GetModuleFileCount - 1 do
if Supports(Module.GetModuleFileEditor(I), IOTASourceEditor, SourceEditor) then
begin
SourceEditor.Show;
if SourceEditor.EditViewCount > 0 then
begin
if Assigned(PreparedLocationInfo) and (PreparedLocationInfo.TranslatedLineNumber > 0) then
LineNumber := PreparedLocationInfo.TranslatedLineNumber
else
LineNumber := AStackViewItem.LineNumber;
if LineNumber > 0 then
begin
SourceEditor.EditViews[0].Center(LineNumber, 1);
EditPos.Line := LineNumber;
EditPos.Col := 1;
SourceEditor.EditViews[0].CursorPos := EditPos;
end;
end;
Break;
end;
end;
end;
end;
{$IFDEF UNITVERSIONING}
initialization
RegisterUnitVersion(HInstance, UnitVersioning);
finalization
UnregisterUnitVersion(HInstance);
{$ENDIF UNITVERSIONING}
end.