From 8e7ba111c333270a71ca629eee40dec796211598 Mon Sep 17 00:00:00 2001 From: mattias Date: Sun, 10 Oct 2010 23:17:00 +0000 Subject: [PATCH] IDE: added sourcemarklings git-svn-id: trunk@27646 - --- ide/msgview.pp | 64 +++++++++++++++++- ide/sourceeditor.pp | 137 +++++++++++++++++++++++++++++++++++++- ide/sourcemarks.pas | 4 +- ideintf/srceditorintf.pas | 82 +++++++++++++++++++++-- 4 files changed, 274 insertions(+), 13 deletions(-) diff --git a/ide/msgview.pp b/ide/msgview.pp index d175f7739c..0d1ef72acd 100644 --- a/ide/msgview.pp +++ b/ide/msgview.pp @@ -43,12 +43,23 @@ uses LCLProc, LCLType, ClipBrd, Controls, Dialogs, FileUtil, Forms, Menus, ExtCtrls, StdCtrls, ComCtrls, Graphics, CodeToolManager, - IDEImagesIntf, IDEExternToolIntf, IDECommands, MenuIntf, IDEMsgIntf, LazIDEIntf, - DialogProcs, EnvironmentOpts, + IDEImagesIntf, IDEExternToolIntf, IDECommands, MenuIntf, IDEMsgIntf, + SrcEditorIntf, LazIDEIntf, + DialogProcs, EnvironmentOpts, SourceMarks, LazarusIDEStrConsts, IDEOptionDefs, IDEProcs, InputHistory, infobuild, KeyMapping; type + + { TMessageViewMarklings } + + TMessageViewMarklings = class(TSourceMarklingProducer) + private + public + function GetMarklings(aFilename: string; + out FreeList, FreeMarklings: boolean): TFPList; override; + end; + TLazMsgLineFlag = ( lmlfHasQuickFixValid, lmlfHasQuickFix @@ -99,6 +110,7 @@ type procedure OnQuickFixClick(Sender: TObject); private FItems: TFPList; // list of TLazMessageLine + FMarklings: TMessageViewMarklings; FVisibleItems: TFPList; // list of TLazMessageLine (visible Items of FItems) FSrcPositions: TAVLTree;// tree of TLazMessageLine sorted for Filename and LineNumber FLastLineIsProgress: boolean; @@ -176,6 +188,7 @@ type read FOnSelectionChanged write FOnSelectionChanged; property Items[Index: integer]: TLazMessageLine read GetItems; property VisibleItems[Index: integer]: TLazMessageLine read GetVisibleItems; + property Marklings: TMessageViewMarklings read FMarklings; end; var @@ -335,6 +348,9 @@ begin MsgCopyAllIDEMenuCommand.OnClick := @CopyAllMenuItemClick; MsgCopyAllAndHiddenIDEMenuCommand.OnClick := @CopyAllAndHiddenMenuItemClick; MsgSaveAllToFileIDEMenuCommand.OnClick := @SaveAllToFileMenuItemClick; + + FMarklings:=TMessageViewMarklings.Create(Self); + SourceEditorManagerIntf.RegisterMarklingProducer(FMarklings); end; destructor TMessagesView.Destroy; @@ -429,7 +445,7 @@ begin NewMsg := TLazMessageLine.Create; FItems.Add(NewMsg); end; - + NewMsg.Msg := Msg; NewMsg.Directory := CurDir; NewMsg.Position := FItems.Count-1; @@ -439,6 +455,7 @@ begin if NewMsg.Parts=nil then NewMsg.Parts:=TStringList.Create; NewMsg.Parts.Assign(Parts); + NewMsg.Filename:=Parts.Values['Filename']; end; //DebugLn('TMessagesView.Add FItems.Count=',dbgs(FItems.Count),' OriginalIndex=',dbgs(OriginalIndex)); @@ -467,6 +484,10 @@ begin end; //ConsistencyCheck; Changed; + + //debugln(['TMessagesView.Add ',NewMsg.Filename,' ',NewMsg.LineNumber,',',NewMsg.Column,' ',NewMsg.Msg]); + if NewMsg.Filename<>'' then + Marklings.InvalidateFile(NewMsg.Filename); end; procedure TMessagesView.AddMsg(const Msg, CurDir: string; OriginalIndex: integer; @@ -1309,4 +1330,41 @@ begin GetSourcePosition(FFilename, FLineNumber, FColumn); end; +{ TMessageViewMarklings } + +function TMessageViewMarklings.GetMarklings(aFilename: string; out FreeList, + FreeMarklings: boolean): TFPList; +var + i: Integer; + Msg: TLazMessageLine; + aType: TSourceMarklingType; + Markling: TSourceMarkling; + TypeStr: string; +begin + Result:=TFPList.Create; + FreeList:=true; + FreeMarklings:=true; + for i:=0 to MessagesView.VisibleItemCount-1 do + begin + Msg:=MessagesView.VisibleItems[i]; + //debugln(['TMessageViewMarklings.GetMarklings ',CompareFilenames(Msg.Filename,aFilename),' ',Msg.Filename,' ',Msg.LineNumber,',',Msg.Column,' ',Msg.Msg]); + if CompareFilenames(Msg.Filename,aFilename)=0 then + begin + aType:=smtHint; + if Msg.Parts<>nil then + begin + TypeStr:=Msg.Parts.Values['Type']; + if TypeStr='Error' then + aType:=smtError + else if TypeStr='Warning' then + aType:=smtWarning + else if TypeStr='Note' then + aType:=smtNote; + end; + Markling:=TSourceMarkling.Create(Self,i,Msg.LineNumber,Msg.Column,aType); + Result.Add(Markling); + end; + end; +end; + end. diff --git a/ide/sourceeditor.pp b/ide/sourceeditor.pp index 378f20109b..d862c0fd87 100644 --- a/ide/sourceeditor.pp +++ b/ide/sourceeditor.pp @@ -147,6 +147,7 @@ type end; TSourceEditor = class; + { TSourceEditorSharedValues } TSourceEditorSharedValues = class @@ -168,6 +169,7 @@ type FExecutionMark: TSourceMark; FExecutionLine: integer; FMarksRequested: Boolean; + FMarklingsValid: boolean; public UpdatingExecutionMark: Integer; procedure CreateExecutionMark; @@ -835,6 +837,7 @@ type function GetSourceWindowByLastFocused(Index: Integer): TSourceEditorWindowInterface; procedure SetActiveSourceWindowIndex(const AValue: integer); protected + fProducers: TFPList; // list of TSourceMarklingProducer FChangeNotifyLists: Array [TsemChangeReason] of TMethodList; function GetActiveSourceWindow: TSourceEditorWindowInterface; override; procedure SetActiveSourceWindow(const AValue: TSourceEditorWindowInterface); override; @@ -846,6 +849,7 @@ type procedure DoEditorStatusChanged(AEditor: TSourceEditor); function GetSourceEditors(Index: integer): TSourceEditorInterface; override; function GetUniqueSourceEditors(Index: integer): TSourceEditorInterface; override; + function GetMarklingProducers(Index: integer): TSourceMarklingProducer; override; public // Windows function SourceWindowWithEditor(const AEditor: TSourceEditorInterface): TSourceEditorWindowInterface; @@ -894,6 +898,12 @@ type destructor Destroy; override; procedure RegisterChangeEvent(AReason: TsemChangeReason; AHandler: TNotifyEvent); override; procedure UnRegisterChangeEvent(AReason: TsemChangeReason; AHandler: TNotifyEvent); override; + // producers + function MarklingProducerCount: integer; override; + procedure RegisterMarklingProducer(aProducer: TSourceMarklingProducer); override; + procedure UnregisterMarklingProducer(aProducer: TSourceMarklingProducer); override; + procedure InvalidateMarklingsOfAllFiles(aProducer: TSourceMarklingProducer); override; + procedure InvalidateMarklings(aProducer: TSourceMarklingProducer; aFilename: string); override; public procedure IncUpdateLock; procedure DecUpdateLock; @@ -995,6 +1005,7 @@ type function FindUniquePageName(FileName:string; IgnoreEditor: TSourceEditor):string; function SomethingModified: boolean; procedure HideHint; + procedure OnIdle(Sender: TObject; var Done: Boolean); procedure LockAllEditorsInSourceChangeCache; procedure UnlockAllEditorsInSourceChangeCache; procedure CloseFile(AEditor: TSourceEditorInterface); @@ -7865,6 +7876,12 @@ begin FCompletionPlugins.Clear; end; +function TSourceEditorManagerBase.GetMarklingProducers(Index: integer + ): TSourceMarklingProducer; +begin + Result:=TSourceMarklingProducer(fProducers[Index]); +end; + function TSourceEditorManagerBase.GetActiveCompletionPlugin: TSourceEditorCompletionPlugin; begin Result := FActiveCompletionPlugin; @@ -7983,6 +8000,8 @@ begin fCompletionPlugins.Remove(AComponent); if ActiveCompletionPlugin = AComponent then DeactivateCompletionForm; + if AComponent is TSourceMarklingProducer then + fProducers.Remove(AComponent); end; end; @@ -7998,13 +8017,18 @@ begin FCompletionPlugins := TFPList.Create; FUpdateLock := 0; FActiveEditorLock := 0; + fProducers := TFPList.Create; inherited; end; destructor TSourceEditorManagerBase.Destroy; var - i: TsemChangeReason; + i: integer; + cr: TsemChangeReason; begin + for i:=MarklingProducerCount-1 downto 0 do + MarklingProducers[i].Free; + FreeAndNil(fProducers); FActiveWindow := nil; FreeCompletionPlugins; FreeSourceWindows; @@ -8012,8 +8036,8 @@ begin FreeAndNil(FCompletionPlugins); FreeAndNil(FSourceWindowList); FreeAndNil(FSourceWindowByFocusList); - for i := low(TsemChangeReason) to high(TsemChangeReason) do - FChangeNotifyLists[i].Free;; + for cr := low(TsemChangeReason) to high(TsemChangeReason) do + FChangeNotifyLists[cr].Free;; inherited Destroy; end; @@ -8029,6 +8053,72 @@ begin FChangeNotifyLists[AReason].Remove(TMethod(AHandler)); end; +function TSourceEditorManagerBase.MarklingProducerCount: integer; +begin + Result:=fProducers.Count; +end; + +procedure TSourceEditorManagerBase.RegisterMarklingProducer( + aProducer: TSourceMarklingProducer); +begin + if fProducers.IndexOf(aProducer)>=0 then + RaiseException('TSourceEditorManagerBase.RegisterProducer already registered'); + fProducers.Add(aProducer); + FreeNotification(aProducer); +end; + +procedure TSourceEditorManagerBase.UnregisterMarklingProducer( + aProducer: TSourceMarklingProducer); +var + i: LongInt; +begin + i:=fProducers.IndexOf(aProducer); + if i<0 then exit; + fProducers.Delete(i); + RemoveFreeNotification(aProducer); +end; + +procedure TSourceEditorManagerBase.InvalidateMarklingsOfAllFiles( + aProducer: TSourceMarklingProducer); +var + SrcWnd: TSourceEditorWindowInterface; + i: Integer; + j: Integer; + SrcEdit: TSourceEditor; +begin + if aProducer=nil then exit; + for i := 0 to SourceWindowCount - 1 do + begin + SrcWnd:=SourceWindows[i]; + for j:=0 to SrcWnd.Count-1 do + begin + SrcEdit:=TSourceEditor(SrcWnd[j]); + SrcEdit.FSharedValues.FMarklingsValid:=false; + end; + end; +end; + +procedure TSourceEditorManagerBase.InvalidateMarklings( + aProducer: TSourceMarklingProducer; aFilename: string); +var + SrcWnd: TSourceEditorWindowInterface; + i: Integer; + j: Integer; + SrcEdit: TSourceEditor; +begin + if aProducer=nil then exit; + for i := 0 to SourceWindowCount - 1 do + begin + SrcWnd:=SourceWindows[i]; + for j:=0 to SrcWnd.Count-1 do + begin + SrcEdit:=TSourceEditor(SrcWnd[j]); + if CompareFilenames(SrcEdit.FileName,aFilename)=0 then + SrcEdit.FSharedValues.FMarklingsValid:=false; + end; + end; +end; + procedure TSourceEditorManagerBase.IncUpdateLock; var i: Integer; @@ -8547,6 +8637,44 @@ begin SourceWindows[i].HideHint; end; +procedure TSourceEditorManager.OnIdle(Sender: TObject; var Done: Boolean); +var + SrcEdit: TSourceEditor; + i: Integer; + aFilename: String; + FreeList, FreeMarklings: boolean; + Marklings: TFPList; + j: Integer; + Markling: TSourceMarkling; +begin + SrcEdit:=ActiveEditor; + if not SrcEdit.FSharedValues.FMarklingsValid then + begin + //debugln(['TSourceEditorManager.OnIdle ',MarklingProducerCount]); + aFilename:=SrcEdit.FileName; + SrcEdit.EditorComponent.BeginUpdate; + for i:=0 to MarklingProducerCount-1 do + begin + Marklings:=MarklingProducers[i].GetMarklings(aFilename,FreeList,FreeMarklings); + for j:=0 to Marklings.Count-1 do + begin + Markling:=TSourceMarkling(Marklings[j]); + if Markling=nil then ; + // ToDo: add mark to synedit + //debugln(['TSourceEditorManager.OnIdle ',Markling.Id,' ',Markling.Line,',',Markling.Column]); + + end; + if FreeMarklings then + for j:=0 to Marklings.Count-1 do + TObject(Marklings[j]).Free; + if FreeList then + Marklings.Free; + end; + SrcEdit.EditorComponent.EndUpdate; + SrcEdit.FSharedValues.FMarklingsValid:=true; + end; +end; + procedure TSourceEditorManager.LockAllEditorsInSourceChangeCache; // lock all sourceeditors that are to be modified by the CodeToolBoss var @@ -8848,10 +8976,13 @@ begin nil,@CreateSourceWindow,'250','100','+70%','+70%', NonModalIDEWindowNames[nmiwMainIDEName],alBottom, true,@GetDefaultLayout); + + Application.AddOnIdleHandler(@OnIdle); end; destructor TSourceEditorManager.Destroy; begin + Application.RemoveAllHandlersOfObject(Self); inherited Destroy; end; diff --git a/ide/sourcemarks.pas b/ide/sourcemarks.pas index 0f3ef83cb6..f1539d9ff3 100644 --- a/ide/sourcemarks.pas +++ b/ide/sourcemarks.pas @@ -39,7 +39,9 @@ interface uses Classes, SysUtils, LCLProc, LResources, Graphics, GraphType, Controls, Menus, - AVL_Tree, SynEdit, SynEditMarks, IDEProcs, MenuIntf, SrcEditorIntf, EditorOptions; + AVL_Tree, FileProcs, SynEdit, SynEditMarks, + MenuIntf, SrcEditorIntf, + IDEProcs, EditorOptions; type TSourceMarks = class; diff --git a/ideintf/srceditorintf.pas b/ideintf/srceditorintf.pas index e0a6e07b83..e890677d23 100644 --- a/ideintf/srceditorintf.pas +++ b/ideintf/srceditorintf.pas @@ -23,6 +23,43 @@ uses Classes, SysUtils, LCLProc, FileUtil, LCLType, Forms, Controls, Graphics, ProjectIntf; +type + TSourceMarklingType = ( + smtHint, // something is unusual or awkward + smtNote, // something could be wrong or is not optimized + smtWarning, // something is probably wrong or likely to fail + smtError // something is definitely wrong + ); + + { TSourceMarklingProducer } + + TSourceMarklingProducer = class(TComponent) + public + procedure InvalidateAllFiles; + procedure InvalidateFile(aFilename: string); + function GetMarklings(aFilename: string; + out FreeList, FreeMarklings: boolean): TFPList; virtual; abstract; + end; + + { TSourceMarkling } + + TSourceMarkling = class + private + FColumn: integer; + FProducer: TSourceMarklingProducer; + FId: integer; + FLine: integer; + fType: TSourceMarklingType; + public + constructor Create(aProducer: TSourceMarklingProducer; + TheID, aLine, aColumn: integer; aType: TSourceMarklingType); + property Producer: TSourceMarklingProducer read FProducer; + property Id: integer read FId; + property Line: integer read FLine; + property Column: integer read FColumn; + property TheType: TSourceMarklingType read fType; + end; + type TSrcEditSearchOption = ( sesoMatchCase, @@ -219,18 +256,19 @@ type TSourceEditorManagerInterface = class(TComponent) protected function GetActiveSourceWindow: TSourceEditorWindowInterface; virtual; abstract; - virtual; abstract; procedure SetActiveSourceWindow(const AValue: TSourceEditorWindowInterface); - virtual; abstract; + virtual; abstract; function GetSourceWindows(Index: integer): TSourceEditorWindowInterface; - virtual; abstract; + virtual; abstract; function GetActiveEditor: TSourceEditorInterface; virtual; abstract; procedure SetActiveEditor(const AValue: TSourceEditorInterface); - virtual; abstract; + virtual; abstract; function GetSourceEditors(Index: integer): TSourceEditorInterface; - virtual; abstract; + virtual; abstract; function GetUniqueSourceEditors(Index: integer): TSourceEditorInterface; - virtual; abstract; + virtual; abstract; + function GetMarklingProducers(Index: integer): TSourceMarklingProducer; + virtual; abstract; public // List of SourceEditorWindows function SourceWindowWithEditor(const AEditor: TSourceEditorInterface): TSourceEditorWindowInterface; @@ -274,6 +312,14 @@ type public procedure RegisterChangeEvent(AReason: TsemChangeReason; AHandler: TNotifyEvent); virtual; abstract; procedure UnRegisterChangeEvent(AReason: TsemChangeReason; AHandler: TNotifyEvent); virtual; abstract; + public + // source marklings + function MarklingProducerCount: integer; virtual; abstract; + property MarklingProducers[Index: integer]: TSourceMarklingProducer read GetMarklingProducers; + procedure RegisterMarklingProducer(aProducer: TSourceMarklingProducer); virtual; abstract; + procedure UnregisterMarklingProducer(aProducer: TSourceMarklingProducer); virtual; abstract; + procedure InvalidateMarklingsOfAllFiles(aProducer: TSourceMarklingProducer); virtual; abstract; + procedure InvalidateMarklings(aProducer: TSourceMarklingProducer; aFilename: string); virtual; abstract; end; @@ -563,5 +609,29 @@ begin Result:=Point(0,0); end; +{ TSourceMarkling } + +constructor TSourceMarkling.Create(aProducer: TSourceMarklingProducer; TheID, + aLine, aColumn: integer; aType: TSourceMarklingType); +begin + FProducer:=aProducer; + FLine:=aLine; + FColumn:=aColumn; + FId:=TheID; + fType:=aType; +end; + +{ TSourceMarklingProducer } + +procedure TSourceMarklingProducer.InvalidateAllFiles; +begin + SourceEditorManagerIntf.InvalidateMarklingsOfAllFiles(Self); +end; + +procedure TSourceMarklingProducer.InvalidateFile(aFilename: string); +begin + SourceEditorManagerIntf.InvalidateMarklings(Self,aFilename); +end; + end.