Skip to content

Commit

Permalink
Add function definition hints on mouseover for [Code] functions and c…
Browse files Browse the repository at this point in the history
…lass members. Always shows all matching class members instead of just those of the object's class.

Todo: Missing are 'procedure' and 'function' headers and also those without parameters.
  • Loading branch information
martijnlaan committed Jan 16, 2025
1 parent 9b3b79d commit 9f9b841
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 46 deletions.
115 changes: 70 additions & 45 deletions Projects/Src/IDE.MainForm.pas
Original file line number Diff line number Diff line change
Expand Up @@ -5605,19 +5605,20 @@ procedure TMainForm.MemoCharAdded(Sender: TObject; Ch: AnsiChar);

procedure TMainForm.MemoHintShow(Sender: TObject; var Info: TScintHintInfo);

function GetCodeVariableDebugEntryFromFileLineCol(FileIndex, Line, Col: Integer): PVariableDebugEntry;
function GetCodeVariableDebugEntryFromFileLineCol(FileIndex, Line, Col: Integer; out DebugEntry: PVariableDebugEntry): Boolean;
var
I: Integer;
begin
{ FVariableDebugEntries uses 1-based line and column numbers }
Inc(Line);
Inc(Col);
Result := nil;
Result := False;
for I := 0 to FVariableDebugEntriesCount-1 do begin
if (FVariableDebugEntries[I].FileIndex = FileIndex) and
(FVariableDebugEntries[I].LineNumber = Line) and
(FVariableDebugEntries[I].Col = Col) then begin
Result := @FVariableDebugEntries[I];
DebugEntry := @FVariableDebugEntries[I];
Result := True;
Break;
end;
end;
Expand All @@ -5639,6 +5640,15 @@ procedure TMainForm.MemoHintShow(Sender: TObject; var Info: TScintHintInfo);
Result := Length(U);
end;

function FindVarOrFuncRange(const Pos: Integer): TScintRange;
begin
{ Note: The GetPositionAfter is needed so that when the mouse is over a '.'
between two words, it won't match the word to the left of the '.' }
FActiveMemo.SetDefaultWordChars;
Result.StartPos := FActiveMemo.GetWordStartPosition(FActiveMemo.GetPositionAfter(Pos), True);
Result.EndPos := FActiveMemo.GetWordEndPosition(Pos, True);
end;

function FindConstRange(const Pos: Integer): TScintRange;
var
BraceLevel, ConstStartPos, Line, LineEndPos, I: Integer;
Expand Down Expand Up @@ -5679,60 +5689,75 @@ procedure TMainForm.MemoHintShow(Sender: TObject; var Info: TScintHintInfo);
end;
end;

var
Pos, Line, I, J: Integer;
Output: String;
DebugEntry: PVariableDebugEntry;
ConstRange: TScintRange;
procedure UpdateInfo(var Info: TScintHintInfo; const HintStr: String; const Range: TScintRange; const Memo: TIDEScintEdit);
begin
Info.HintStr := HintStr;
Info.CursorRect.TopLeft := Memo.GetPointFromPosition(Range.StartPos);
Info.CursorRect.BottomRight := Memo.GetPointFromPosition(Range.EndPos);
Info.CursorRect.Bottom := Info.CursorRect.Top + Memo.LineHeight;
Info.HideTimeout := High(Integer); { infinite }
end;

begin
if FDebugClientWnd = 0 then
Exit;
Pos := FActiveMemo.GetPositionFromPoint(Info.CursorPos, True, True);
var Pos := FActiveMemo.GetPositionFromPoint(Info.CursorPos, True, True);
if Pos < 0 then
Exit;
Line := FActiveMemo.GetLineFromPosition(Pos);

{ Check if cursor is over a [Code] variable }
if (FActiveMemo is TIDEScintFileEdit) and
(FMemosStyler.GetSectionFromLineState(FActiveMemo.Lines.State[Line]) = scCode) then begin
{ Note: The '+ 1' is needed so that when the mouse is over a '.'
between two words, it won't match the word to the left of the '.' }
FActiveMemo.SetDefaultWordChars;
I := FActiveMemo.GetWordStartPosition(Pos + 1, True);
J := FActiveMemo.GetWordEndPosition(Pos, True);
if J > I then begin
DebugEntry := GetCodeVariableDebugEntryFromFileLineCol((FActiveMemo as TIDEScintFileEdit).CompilerFileIndex,
Line, GetCodeColumnFromPosition(I));
if DebugEntry <> nil then begin
var Line := FActiveMemo.GetLineFromPosition(Pos);

{ Check if cursor is over a [Code] variable or function }
if FMemosStyler.GetSectionFromLineState(FActiveMemo.Lines.State[Line]) = scCode then begin
var VarOrFuncRange := FindVarOrFuncRange(Pos);
if VarOrFuncRange.EndPos > VarOrFuncRange.StartPos then begin
var HintStr := '';
var DebugEntry: PVariableDebugEntry;
if (FActiveMemo is TIDEScintFileEdit) and (FDebugClientWnd <> 0) and
GetCodeVariableDebugEntryFromFileLineCol((FActiveMemo as TIDEScintFileEdit).CompilerFileIndex,
Line, GetCodeColumnFromPosition(VarOrFuncRange.StartPos), DebugEntry) then begin
var Output: String;
case EvaluateVariableEntry(DebugEntry, Output) of
1: Info.HintStr := Output;
2: Info.HintStr := Output;
1: HintStr := Output;
2: HintStr := Output;
else
Info.HintStr := 'Unknown error';
HintStr := 'Unknown error';
end;
end else begin
var Name := FActiveMemo.GetTextRange(VarOrFuncRange.StartPos, VarOrFuncRange.EndPos);
var ClassMember := False;
var Index := 0;
var Count: Integer;
var Definition := FMemosStyler.GetScriptFunctionDefinition(ClassMember, Name, Index, Count);
if Definition = '' then begin
ClassMember := not ClassMember;
Definition := FMemosStyler.GetScriptFunctionDefinition(ClassMember, Name, Index, Count);
end;
Info.CursorRect.TopLeft := FActiveMemo.GetPointFromPosition(I);
Info.CursorRect.BottomRight := FActiveMemo.GetPointFromPosition(J);
Info.CursorRect.Bottom := Info.CursorRect.Top + FActiveMemo.LineHeight;
Info.HideTimeout := High(Integer); { infinite }
while Index < Count-1 do begin
Inc(Index);
Definition := Definition + #13 + FMemosStyler.GetScriptFunctionDefinition(ClassMember, Name, Index);
end;
HintStr := String(Definition);
end;

if HintStr <> '' then begin
UpdateInfo(Info, HintStr, VarOrFuncRange, FActiveMemo);
Exit;
end;
end;
end;

{ Check if cursor is over a constant }
ConstRange := FindConstRange(Pos);
if ConstRange.EndPos > ConstRange.StartPos then begin
Info.HintStr := FActiveMemo.GetTextRange(ConstRange.StartPos, ConstRange.EndPos);
case EvaluateConstant(Info.HintStr, Output) of
1: Info.HintStr := Info.HintStr + ' = "' + Output + '"';
2: Info.HintStr := Info.HintStr + ' = Exception: ' + Output;
else
Info.HintStr := Info.HintStr + ' = Unknown error';
if FDebugClientWnd <> 0 then begin
{ Check if cursor is over a constant }
var ConstRange := FindConstRange(Pos);
if ConstRange.EndPos > ConstRange.StartPos then begin
var HintStr := FActiveMemo.GetTextRange(ConstRange.StartPos, ConstRange.EndPos);
var Output: String;
case EvaluateConstant(Info.HintStr, Output) of
1: HintStr := HintStr + ' = "' + Output + '"';
2: HintStr := HintStr + ' = Exception: ' + Output;
else
HintStr := HintStr + ' = Unknown error';
end;
UpdateInfo(Info, HintStr, ConstRange, FActiveMemo);
end;
Info.CursorRect.TopLeft := FActiveMemo.GetPointFromPosition(ConstRange.StartPos);
Info.CursorRect.BottomRight := FActiveMemo.GetPointFromPosition(ConstRange.EndPos);
Info.CursorRect.Bottom := Info.CursorRect.Top + FActiveMemo.LineHeight;
Info.HideTimeout := High(Integer); { infinite }
end;
end;

Expand Down
12 changes: 11 additions & 1 deletion Projects/Src/IDE.ScintStylerInnoSetup.pas
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@ TInnoSetupStyler = class(TScintCustomStyler)
class function IsParamSection(const Section: TInnoSetupStylerSection): Boolean;
class function IsSymbolStyle(const Style: TScintStyleNumber): Boolean;
function GetScriptFunctionDefinition(const ClassMember: Boolean;
const Name: String; const Index: Integer; out Count: Integer): AnsiString;
const Name: String; const Index: Integer; out Count: Integer): AnsiString; overload;
function GetScriptFunctionDefinition(const ClassMember: Boolean;
const Name: String; const Index: Integer): AnsiString; overload;
function SectionHasFlag(const Section: TInnoSetupStylerSection; const Flag: String): Boolean;
property ConstantsWordList: AnsiString read FConstantsWordList;
property EventFunctionsWordList[Procedures: Boolean]: AnsiString read GetEventFunctionsWordList;
Expand Down Expand Up @@ -938,6 +940,14 @@ function TInnoSetupStyler.GetScriptFunctionDefinition(const ClassMember: Boolean
end;
end;

function TInnoSetupStyler.GetScriptFunctionDefinition(
const ClassMember: Boolean; const Name: String;
const Index: Integer): AnsiString;
begin
var Count: Integer;
Result := GetScriptFunctionDefinition(ClassMember, Name, Index, Count);
end;

function TInnoSetupStyler.GetScriptWordList(
ClassOrRecordMembers: Boolean): AnsiString;
begin
Expand Down

0 comments on commit 9f9b841

Please sign in to comment.