Skip to content

Commit

Permalink
Add client quickfixes via popup menu
Browse files Browse the repository at this point in the history
  • Loading branch information
fourls committed May 9, 2024
1 parent cf4f4fa commit 90b75ab
Show file tree
Hide file tree
Showing 13 changed files with 643 additions and 10 deletions.
21 changes: 18 additions & 3 deletions client/source/DelphiLint.Analyzer.pas
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ TAnalyzerImpl = class(TInterfacedObject, IAnalyzer)
constructor Create;
destructor Destroy; override;

function GetIssues(FileName: string; Line: Integer = -1): TArray<ILiveIssue>;
function GetIssues(FileName: string; Line: Integer = -1; Column: Integer = -1): TArray<ILiveIssue>;

procedure UpdateIssueLine(FilePath: string; OriginalLine: Integer; NewLine: Integer);

Expand Down Expand Up @@ -326,7 +326,22 @@ function TAnalyzerImpl.GetCurrentAnalysis: TCurrentAnalysis;

//______________________________________________________________________________________________________________________

function TAnalyzerImpl.GetIssues(FileName: string; Line: Integer = -1): TArray<ILiveIssue>;
function TAnalyzerImpl.GetIssues(FileName: string; Line: Integer = -1; Column: Integer = -1): TArray<ILiveIssue>;

function Matches(Issue: ILiveIssue): Boolean;
var
AfterStart: Boolean;
BeforeEnd: Boolean;
begin
Result := (Issue.StartLine <= Line) and (Issue.EndLine >= Line);

if Result and (Column <> -1) then begin
AfterStart := (Issue.StartLine < Line) or (Issue.StartLineOffset <= Column);
BeforeEnd := (Issue.EndLine > Line) or (Issue.EndLineOffset >= Column);
Result := AfterStart and BeforeEnd;
end;
end;

var
SanitizedName: string;
Issue: ILiveIssue;
Expand All @@ -342,7 +357,7 @@ function TAnalyzerImpl.GetIssues(FileName: string; Line: Integer = -1): TArray<I
ResultList := TList<ILiveIssue>.Create;
try
for Issue in FActiveIssues[SanitizedName] do begin
if (Line >= Issue.StartLine) and (Line <= Issue.EndLine) then begin
if Matches(Issue) then begin
ResultList.Add(Issue);
end;
end;
Expand Down
18 changes: 17 additions & 1 deletion client/source/DelphiLint.Context.pas
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ TAnalysisStateChangeContext = record
function GetOnAnalysisStateChanged: TEventNotifier<TAnalysisStateChangeContext>;
function GetCurrentAnalysis: TCurrentAnalysis;
function GetInAnalysis: Boolean;
function GetIssues(FileName: string; Line: Integer = -1): TArray<ILiveIssue>;
function GetIssues(FileName: string; Line: Integer = -1; Column: Integer = -1): TArray<ILiveIssue>;
function GetRule(RuleKey: string; AllowRefresh: Boolean = True): TRule;

procedure UpdateIssueLine(FilePath: string; OriginalLine: Integer; NewLine: Integer);
Expand Down Expand Up @@ -103,10 +103,22 @@ TAnalysisStateChangeContext = record
function AddNotifier(Notifier: IIDEViewHandler): Integer;
procedure RemoveNotifier(Index: Integer);
function GetLeftColumn: Integer;
procedure ReplaceText(
Replacement: string;
StartLine: Integer;
StartColumn: Integer;
EndLine: Integer;
EndColumn: Integer
);
function GetColumn: Integer;
function GetRow: Integer;
function GetContextMenu: TPopupMenu;
function Raw: IInterface; // IOTAEditView

property FileName: string read GetFileName;
property LeftColumn: Integer read GetLeftColumn;
property Column: Integer read GetColumn;
property Row: Integer read GetRow;
end;

IIDESourceEditor = interface
Expand Down Expand Up @@ -236,6 +248,10 @@ TLinePaintContext = record
// From IOTAEditorServices
function AddEditorNotifier(Notifier: IIDEEditorHandler): Integer;
procedure RemoveEditorNotifier(const Index: Integer);
function GetTopView: IIDEEditView;

// From INTAEditorServices
function GetTopEditWindow: TCustomForm;

// From INTAEnvironmentOptionsServices
procedure RegisterAddInOptions(const Options: TAddInOptionsBase);
Expand Down
42 changes: 42 additions & 0 deletions client/source/DelphiLint.Handlers.pas
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ interface
uses
System.Generics.Collections
, Vcl.Graphics
, Vcl.Menus
, DelphiLint.Events
, DelphiLint.Context
, DelphiLint.LiveData
, DelphiLint.PopupHook
;

type
Expand Down Expand Up @@ -97,6 +99,7 @@ TEditorHandler = class(THandler, IIDEEditorHandler)
private
FNotifiers: TList<IIDEHandler>;
FTrackers: TObjectList<TLineTracker>;
FPopupHooks: TDictionary<TPopupMenu, TEditorPopupMenuHook>;
FInitedViews: TList<IInterface>;

FOnActiveFileChanged: TEventNotifier<string>;
Expand All @@ -106,6 +109,8 @@ TEditorHandler = class(THandler, IIDEEditorHandler)
procedure InitView(const View: IIDEEditView);
function IsViewInited(const View: IIDEEditView): Boolean;
procedure OnAnalysisStateChanged(const StateChange: TAnalysisStateChangeContext);

procedure OnHookFreed(const Hook: TEditorPopupMenuHook);
public
constructor Create;
destructor Destroy; override;
Expand Down Expand Up @@ -298,6 +303,8 @@ constructor TEditorHandler.Create;
// Once registered with the IDE, notifiers are reference counted
FNotifiers := TList<IIDEHandler>.Create;
FTrackers := TObjectList<TLineTracker>.Create;
// These are components, nominally owned by the context menu
FPopupHooks := TDictionary<TPopupMenu, TEditorPopupMenuHook>.Create;
FInitedViews := TList<IInterface>.Create;
FOnActiveFileChanged := TEventNotifier<string>.Create;

Expand All @@ -309,11 +316,19 @@ constructor TEditorHandler.Create;
destructor TEditorHandler.Destroy;
var
Notifier: IIDEHandler;
Hook: TEditorPopupMenuHook;
begin
for Notifier in FNotifiers do begin
Notifier.Release;
end;

// Although these hooks are owned by the context menu, we need to free them when the plugin is disabled
for Hook in FPopupHooks.Values do begin
Hook.OnFreed.RemoveListener(OnHookFreed);
FreeAndNil(Hook);
end;
FreeAndNil(FPopupHooks);

if ContextValid then begin
Analyzer.OnAnalysisStateChanged.RemoveListener(OnAnalysisStateChanged);
end;
Expand Down Expand Up @@ -368,6 +383,19 @@ procedure TEditorHandler.InitView(const View: IIDEEditView);
end;
end;

procedure InitPopupHook;
var
PopupHook: TEditorPopupMenuHook;
ContextMenu: TPopupMenu;
begin
ContextMenu := View.GetContextMenu;
if not FPopupHooks.ContainsKey(ContextMenu) then begin
PopupHook := TEditorPopupMenuHook.Create(View.GetContextMenu);
PopupHook.OnFreed.AddListener(OnHookFreed);
FPopupHooks.Add(ContextMenu, PopupHook);
end;
end;

procedure InitNotifier;
var
Notifier: TViewHandler;
Expand All @@ -391,6 +419,7 @@ procedure TEditorHandler.InitView(const View: IIDEEditView);
begin
InitTracker;
InitNotifier;
InitPopupHook;
FInitedViews.Add(View.Raw);
end;

Expand Down Expand Up @@ -436,6 +465,19 @@ procedure TEditorHandler.OnAnalysisStateChanged(const StateChange: TAnalysisStat

//______________________________________________________________________________________________________________________

procedure TEditorHandler.OnHookFreed(const Hook: TEditorPopupMenuHook);
var
Menu: TPopupMenu;
begin
for Menu in FPopupHooks.Keys do begin
if FPopupHooks[Menu] = Hook then begin
FPopupHooks.Remove(Menu);
end;
end;
end;

//______________________________________________________________________________________________________________________

procedure TEditorHandler.OnTrackedLineChanged(const ChangedLine: TChangedLine);
begin
Analyzer.UpdateIssueLine(ChangedLine.Tracker.FilePath, ChangedLine.FromLine, ChangedLine.ToLine);
Expand Down
88 changes: 88 additions & 0 deletions client/source/DelphiLint.IDEContext.pas
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ TToolsApiServices = class(TInterfacedObject, IIDEServices)
// From IOTAEditorServices
function AddEditorNotifier(Notifier: IIDEEditorHandler): Integer;
procedure RemoveEditorNotifier(const Index: Integer);
function GetTopView: IIDEEditView;

// From INTAEditorServices
function GetTopEditWindow: TCustomForm;

// From INTAEnvironmentOptionsServices
procedure RegisterAddInOptions(const Options: TAddInOptionsBase);
Expand Down Expand Up @@ -155,6 +159,16 @@ TToolsApiEditView = class(TToolsApiWrapper<IOTAEditView>, IIDEEditView)
function AddNotifier(Notifier: IIDEViewHandler): Integer;
procedure RemoveNotifier(Index: Integer);
function GetLeftColumn: Integer;
procedure ReplaceText(
Replacement: string;
StartLine: Integer;
StartColumn: Integer;
EndLine: Integer;
EndColumn: Integer
);
function GetColumn: Integer;
function GetRow: Integer;
function GetContextMenu: TPopupMenu;
end;

TToolsApiSourceEditor = class(TToolsApiWrapper<IOTASourceEditor>, IIDESourceEditor)
Expand Down Expand Up @@ -432,6 +446,34 @@ function TToolsApiServices.GetToolBar(ToolBarId: string): TToolBar;

//______________________________________________________________________________________________________________________

function TToolsApiServices.GetTopEditWindow: TCustomForm;
var
Window: INTAEditWindow;
begin
Result := nil;

Window := (BorlandIDEServices as INTAEditorServices).GetTopEditWindow;
if Assigned(Window) then begin
Result := Window.GetForm;
end;
end;

//______________________________________________________________________________________________________________________

function TToolsApiServices.GetTopView: IIDEEditView;
var
TopView: IOTAEditView;
begin
TopView := (BorlandIDEServices as IOTAEditorServices).GetTopView;

Result := nil;
if Assigned(TopView) then begin
Result := TToolsApiEditView.Create(TopView);
end;
end;

//______________________________________________________________________________________________________________________

function TToolsApiServices.CreateDockableForm(const CustomForm: TCustomDockableFormBase): TCustomForm;
begin
Result := (BorlandIDEServices as INTAServices).CreateDockableForm(CustomForm);
Expand Down Expand Up @@ -568,6 +610,11 @@ function TToolsApiEditView.GetLineTracker: IIDEEditLineTracker;
Result := TToolsApiEditLineTracker.Create(FRaw.Buffer.GetEditLineTracker);
end;

function TToolsApiEditView.GetRow: Integer;
begin
Result := FRaw.Buffer.EditPosition.Row;
end;

procedure TToolsApiEditView.GoToPosition(const Line: Integer; const Column: Integer);
var
ScrollLine: Integer;
Expand All @@ -594,6 +641,47 @@ procedure TToolsApiEditView.RemoveNotifier(Index: Integer);
FRaw.RemoveNotifier(Index);
end;

procedure TToolsApiEditView.ReplaceText(Replacement: string; StartLine, StartColumn, EndLine, EndColumn: Integer);

procedure MoveCursor(const Line: Integer; const Column: Integer);
var
Pos: TOTAEditPos;
begin
Pos.Col := Column;
Pos.Line := Line;
FRaw.SetCursorPos(Pos);
end;

begin
FRaw.Buffer.EditBlock.Reset;
MoveCursor(StartLine, StartColumn + 1);
FRaw.Buffer.EditBlock.BeginBlock;
MoveCursor(EndLine, EndColumn + 1);
FRaw.Buffer.EditBlock.EndBlock;

FRaw.Buffer.EditPosition.InsertText(Replacement);
MoveCursor(StartLine, StartColumn + 1);
end;

function TToolsApiEditView.GetColumn: Integer;
begin
Result := FRaw.Buffer.EditPosition.Column;
end;

function TToolsApiEditView.GetContextMenu: TPopupMenu;
var
Window: INTAEditWindow;
begin
Window := FRaw.GetEditWindow;

if Assigned(Window) then begin
Result := Window.Form.FindComponent('EditorLocalMenu') as TPopupMenu;
end
else begin
Result := nil;
end;
end;

function TToolsApiEditView.GetFileName: string;
begin
Result := FRaw.Buffer.FileName;
Expand Down
Loading

0 comments on commit 90b75ab

Please sign in to comment.