This commit is contained in:
Basile Burg 2015-09-15 14:00:23 +02:00
parent 2a9fb832bc
commit 3ac5fef89b
5 changed files with 178 additions and 71 deletions

View File

@ -135,7 +135,7 @@
<PackageName Value="LCL"/> <PackageName Value="LCL"/>
</Item6> </Item6>
</RequiredPackages> </RequiredPackages>
<Units Count="42"> <Units Count="43">
<Unit0> <Unit0>
<Filename Value="coedit.lpr"/> <Filename Value="coedit.lpr"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
@ -356,6 +356,10 @@
<HasResources Value="True"/> <HasResources Value="True"/>
<ResourceBaseClass Value="Form"/> <ResourceBaseClass Value="Form"/>
</Unit41> </Unit41>
<Unit42>
<Filename Value="..\src\ce_dast.pas"/>
<IsPartOfProject Value="True"/>
</Unit42>
</Units> </Units>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>

View File

@ -10,7 +10,7 @@ uses
ce_observer, ce_libman, ce_tools, ce_dcd, ce_main, ce_writableComponent, ce_observer, ce_libman, ce_tools, ce_dcd, ce_main, ce_writableComponent,
ce_symstring, ce_staticmacro, ce_inspectors, ce_editoroptions, ce_dockoptions, ce_symstring, ce_staticmacro, ce_inspectors, ce_editoroptions, ce_dockoptions,
ce_shortcutseditor, ce_mru, ce_processes, ce_dubproject, ce_dialogs, ce_shortcutseditor, ce_mru, ce_processes, ce_dubproject, ce_dialogs,
ce_dubprojeditor; ce_dubprojeditor, ce_dast;
{$R *.res} {$R *.res}

76
src/ce_dast.pas Normal file
View File

@ -0,0 +1,76 @@
unit ce_dast;
{$I ce_defines.inc}
interface
uses
dynlibs, forms;
type
TAstHandle = type NativeInt;
TAstNotification = procedure(param: Pointer); cdecl;
{$Z1}
TSerializationFormat = (json, pas);
// Returns an ID to a D AST. clbsk is the proc called with param when scanning is achieved.
TNewAst = function(param: Pointer; clbck: TAstNotification): TAstHandle; cdecl;
// Deletes the D AST identified by hdl.
TDeleteAst = procedure(hdl: TAstHandle); cdecl;
// Uses D AST identified by hsdl to parse filename.
TScanFile = procedure(hdl: TAstHandle; filename: PChar); cdecl;
// Uses D AST identified by hsdl to parse the buffer of length len.
TScanBuffer = procedure(hdl: TAstHandle; buffer: PByte; len: NativeUint); cdecl;
// Returns the name of the module identified by hdl.
TModuleName = function(hdl: TAstHandle): PChar; cdecl;
// Returns the list of the declarations in the module identified by hdl.
TSymbolList = function(hdl: TAstHandle; var len: NativeUint ; fmt: TSerializationFormat): PByte; cdecl;
var
newAST: TNewAst;
deleteAST: TDeleteAst;
scanFile: TScanFile;
scanBuffer: TScanBuffer;
moduleName: TModuleName;
symbolList: TSymbolList;
dastAvailable: boolean;
implementation
var
dastHdl: TLibHandle;
initialization
if application.GetOptionValue('cedast') = 'off' then
exit;
dastHdl := LoadLibrary('cedast');
if dastHdl <> NilHandle then
begin
newAST := TNewAst(GetProcAddress(dastHdl, 'newAst'));
deleteAST := TDeleteAst(GetProcAddress(dastHdl, 'deleteAst'));
scanFile := TScanFile(GetProcAddress(dastHdl, 'scanFile'));
scanBuffer := TScanBuffer(GetProcAddress(dastHdl, 'scanBuffer'));
moduleName := TModuleName(GetProcAddress(dastHdl, 'moduleName'));
symbolList := TSymbolList(GetProcAddress(dastHdl, 'symbolList'));
symbolList := TSymbolList(GetProcAddress(dastHdl, 'symbolList'));
//
dastAvailable := assigned(newAST) and assigned(deleteAST) and assigned(scanFile)
and assigned(scanBuffer) and assigned(moduleName) and assigned(symbolList);
end;
finalization
{$IFDEF RELEASE}
if dastHdl <> NilHandle then
UnloadLibrary(dastHdl);
{$ENDIF}
end.

View File

@ -6,7 +6,7 @@ interface
uses uses
Classes, SysUtils, FileUtil, ExtendedNotebook, Forms, Controls, lcltype, Classes, SysUtils, FileUtil, ExtendedNotebook, Forms, Controls, lcltype,
Graphics, SynEditKeyCmds, ComCtrls, SynEditHighlighter, ExtCtrls, Menus, Graphics, SynEditKeyCmds, ComCtrls, SynEditHighlighter, ExtCtrls, Menus, ce_dast,
SynMacroRecorder, SynPluginSyncroEdit, SynEdit, SynHighlighterMulti, ce_dialogs, SynMacroRecorder, SynPluginSyncroEdit, SynEdit, SynHighlighterMulti, ce_dialogs,
ce_widget, ce_interfaces, ce_synmemo, ce_dlang, ce_common, ce_dcd, ce_observer; ce_widget, ce_interfaces, ce_synmemo, ce_dlang, ce_common, ce_dcd, ce_observer;
@ -43,7 +43,6 @@ type
procedure mnuedJum2DeclClick(Sender: TObject); procedure mnuedJum2DeclClick(Sender: TObject);
procedure PageControlChange(Sender: TObject); procedure PageControlChange(Sender: TObject);
protected protected
procedure updateDelayed; override;
procedure updateImperative; override; procedure updateImperative; override;
private private
fKeyChanged: boolean; fKeyChanged: boolean;
@ -172,8 +171,6 @@ begin
fDoc := aDoc; fDoc := aDoc;
pageControl.ActivePage := sheet; pageControl.ActivePage := sheet;
focusedEditorChanged; focusedEditorChanged;
beginDelayedUpdate;
updateImperative;
end; end;
procedure TCEEditorWidget.docClosing(aDoc: TCESynMemo); procedure TCEEditorWidget.docClosing(aDoc: TCESynMemo);
@ -195,16 +192,16 @@ begin
if aDoc = fDoc then exit; if aDoc = fDoc then exit;
fDoc := aDoc; fDoc := aDoc;
focusedEditorChanged; focusedEditorChanged;
beginDelayedUpdate; beginImperativeUpdate;
updateImperative; endImperativeUpdate;
end; end;
procedure TCEEditorWidget.docChanged(aDoc: TCESynMemo); procedure TCEEditorWidget.docChanged(aDoc: TCESynMemo);
begin begin
if fDoc <> aDoc then exit; if fDoc <> aDoc then exit;
fKeyChanged := true; fKeyChanged := true;
beginDelayedUpdate; beginImperativeUpdate;
updateImperative; endImperativeUpdate;
end; end;
{$ENDREGION} {$ENDREGION}
@ -281,23 +278,28 @@ begin
if (pageControl.ActivePage.Caption = '') then if (pageControl.ActivePage.Caption = '') then
begin begin
fKeyChanged := true; fKeyChanged := true;
beginDelayedUpdate; beginImperativeUpdate;
endImperativeUpdate;
end; end;
end; end;
procedure TCEEditorWidget.PageControlChange(Sender: TObject); procedure TCEEditorWidget.PageControlChange(Sender: TObject);
begin begin
updateImperative; beginImperativeUpdate;
endImperativeUpdate;
end; end;
procedure TCEEditorWidget.memoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure TCEEditorWidget.memoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin begin
case Key of case Key of
VK_CLEAR,VK_RETURN,VK_BACK : fKeyChanged := true; VK_CLEAR,VK_RETURN,VK_BACK : fKeyChanged := true;
VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT: updateImperative; VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT: fKeyChanged := true;
end; end;
if fKeyChanged then if fKeyChanged then
beginDelayedUpdate begin
beginImperativeUpdate;
endImperativeUpdate;
end
else if (Key = VK_UP) and (shift = [ssShift,ssCtrl]) then else if (Key = VK_UP) and (shift = [ssShift,ssCtrl]) then
getSymbolLoc; getSymbolLoc;
end; end;
@ -317,19 +319,21 @@ end;
procedure TCEEditorWidget.memoKeyPress(Sender: TObject; var Key: char); procedure TCEEditorWidget.memoKeyPress(Sender: TObject; var Key: char);
begin begin
fKeyChanged := true; fKeyChanged := true;
beginDelayedUpdate; beginImperativeUpdate;
endImperativeUpdate;
end; end;
procedure TCEEditorWidget.memoMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure TCEEditorWidget.memoMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin begin
beginDelayedUpdate; beginImperativeUpdate;
updateImperative; endImperativeUpdate;
end; end;
procedure TCEEditorWidget.memoMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure TCEEditorWidget.memoMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin begin
if not (ssLeft in Shift) then exit; if not (ssLeft in Shift) then exit;
beginDelayedUpdate; beginImperativeUpdate;
endImperativeUpdate;
end; end;
procedure TCEEditorWidget.memoCtrlClick(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure TCEEditorWidget.memoCtrlClick(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
@ -372,8 +376,8 @@ end;
procedure TCEEditorWidget.updateImperative; procedure TCEEditorWidget.updateImperative;
const const
modstr: array[boolean] of string = ('...', 'MODIFIED'); modstr: array[boolean] of string = ('...', 'MODIFIED');
//var var
//md: string; md: string;
begin begin
if fDoc = nil then begin if fDoc = nil then begin
editorStatus.Panels[0].Text := ''; editorStatus.Panels[0].Text := '';
@ -383,19 +387,16 @@ begin
editorStatus.Panels[0].Text := format('%d : %d | %d', [fDoc.CaretY, fDoc.CaretX, fDoc.SelEnd - fDoc.SelStart]); editorStatus.Panels[0].Text := format('%d : %d | %d', [fDoc.CaretY, fDoc.CaretX, fDoc.SelEnd - fDoc.SelStart]);
editorStatus.Panels[1].Text := modstr[fDoc.modified]; editorStatus.Panels[1].Text := modstr[fDoc.modified];
editorStatus.Panels[2].Text := fDoc.fileName; editorStatus.Panels[2].Text := fDoc.fileName;
// TODO-cEditor: set tab caption directly (e.g one start, if reload last docs) if fKeyChanged then
//if Visible then if pageControl.ActivePage <> nil then begin
//if pageControl.ActivePage.Caption = '' then md := '';
//begin if fDoc.isDSource and (fDoc.ast <> 0) then
// if fDoc.isDSource then md := moduleName(fDoc.ast);
// begin if md = '' then
// lex(fDoc.Lines.Text, fTokList, @lexFindToken); md := extractFileName(fDoc.fileName);
// md := getModuleName(fTokList); pageControl.ActivePage.Caption := md;
// fTokList.Clear; end;
// end; fKeyChanged := false;
// if md = '' then md := extractFileName(fDoc.fileName);
// pageControl.ActivePage.Caption := md;
//end;
end; end;
end; end;
@ -410,37 +411,6 @@ begin
fModStart := false; fModStart := false;
end; end;
end; end;
procedure TCEEditorWidget.updateDelayed;
var
md: string;
begin
if fDoc = nil then exit;
updateImperative;
if not fKeyChanged then exit;
//
fKeyChanged := false;
if fDoc.Lines.Count = 0 then exit;
//
md := '';
if fDoc.isDSource then
begin
fTokList.Clear;
lex(fDoc.Lines.Text, fTokList, @lexFindToken);
md := getModuleName(fTokList);
end;
if md = '' then md := extractFileName(fDoc.fileName);
pageControl.ActivePage.Caption := md;
//
fTokList.Clear;
fErrList.Clear;
// when a widget saves a temp file & syncro mode is on:
// - editor is saved
// - gutter is updated (green bar indicating a saved block)
// - syncroedit icon is hidden
if fDoc.syncroEdit.Active then
fDoc.Refresh;
end;
{$ENDREGION} {$ENDREGION}
{$REGION Editor context menu ---------------------------------------------------} {$REGION Editor context menu ---------------------------------------------------}

View File

@ -8,7 +8,8 @@ uses
Classes, SysUtils, controls,lcltype, Forms, graphics, ExtCtrls, crc, Classes, SysUtils, controls,lcltype, Forms, graphics, ExtCtrls, crc,
SynPluginSyncroEdit, SynCompletion, SynEditKeyCmds, LazSynEditText, SynEdit, SynPluginSyncroEdit, SynCompletion, SynEditKeyCmds, LazSynEditText, SynEdit,
SynHighlighterLFM, SynEditHighlighter, SynEditMouseCmds, SynEditFoldedView, SynHighlighterLFM, SynEditHighlighter, SynEditMouseCmds, SynEditFoldedView,
ce_common, ce_observer, ce_writableComponent, ce_d2syn, ce_txtsyn, ce_dialogs; ce_common, ce_observer, ce_writableComponent, ce_d2syn, ce_txtsyn, ce_dialogs,
ce_dast;
type type
@ -77,6 +78,9 @@ type
TCESynMemo = class(TSynEdit) TCESynMemo = class(TSynEdit)
private private
fScanning: boolean;
fCanScan: boolean;
fAst: TAstHandle;
fFilename: string; fFilename: string;
fModified: boolean; fModified: boolean;
fFileDate: double; fFileDate: double;
@ -94,6 +98,7 @@ type
fHintDelay: Integer; fHintDelay: Integer;
fAutoDotDelay: Integer; fAutoDotDelay: Integer;
fHintTimer: TIdleTimer; fHintTimer: TIdleTimer;
fAstTimer: TIdleTimer;
fAutoDotTimer: TIdleTimer; fAutoDotTimer: TIdleTimer;
fCanShowHint: boolean; fCanShowHint: boolean;
fCanAutoDot: boolean; fCanAutoDot: boolean;
@ -103,6 +108,8 @@ type
fCompletion: TSynCompletion; fCompletion: TSynCompletion;
fD2Highlighter: TSynD2Syn; fD2Highlighter: TSynD2Syn;
fTxtHighlighter: TSynTxtSyn; fTxtHighlighter: TSynTxtSyn;
function getIfScanning: boolean;
function getAstHandle: TAstHandle;
function getMouseFileBytePos: Integer; function getMouseFileBytePos: Integer;
procedure changeNotify(Sender: TObject); procedure changeNotify(Sender: TObject);
procedure identifierToD2Syn; procedure identifierToD2Syn;
@ -111,6 +118,7 @@ type
class procedure cleanCache; static; class procedure cleanCache; static;
procedure setDefaultFontSize(aValue: Integer); procedure setDefaultFontSize(aValue: Integer);
procedure getCallTips; procedure getCallTips;
procedure AstTimerEvent(sender: TObject);
procedure HintTimerEvent(sender: TObject); procedure HintTimerEvent(sender: TObject);
procedure AutoDotTimerEvent(sender: TObject); procedure AutoDotTimerEvent(sender: TObject);
procedure InitHintWins; procedure InitHintWins;
@ -161,6 +169,7 @@ type
property isProjectSource: boolean read fIsConfig; property isProjectSource: boolean read fIsConfig;
property isTemporary: boolean read getIfTemp; property isTemporary: boolean read getIfTemp;
property TextView; property TextView;
property ast: TAstHandle read GetAstHandle;
// //
property MouseStart: Integer read getMouseFileBytePos; property MouseStart: Integer read getMouseFileBytePos;
property D2Highlighter: TSynD2Syn read fD2Highlighter; property D2Highlighter: TSynD2Syn read fD2Highlighter;
@ -169,6 +178,8 @@ type
procedure SetDefaultCoeditKeystrokes(ed: TSynEdit); procedure SetDefaultCoeditKeystrokes(ed: TSynEdit);
procedure astScanned(param: pointer); cdecl;
var var
D2Syn: TSynD2Syn; // used as model to set the options when no editor exists. D2Syn: TSynD2Syn; // used as model to set the options when no editor exists.
LfmSyn: TSynLfmSyn; LfmSyn: TSynLfmSyn;
@ -179,12 +190,6 @@ implementation
uses uses
ce_interfaces, ce_staticmacro, ce_dcd, SynEditHighlighterFoldBase; ce_interfaces, ce_staticmacro, ce_dcd, SynEditHighlighterFoldBase;
function TCEEditorHintWindow.CalcHintRect(MaxWidth: Integer; const AHint: String; AData: Pointer): TRect;
begin
Font.Size:= FontSize;
result := inherited CalcHintRect(MaxWidth, AHint, AData);
end;
{$REGION TCESynMemoCache -------------------------------------------------------} {$REGION TCESynMemoCache -------------------------------------------------------}
constructor TCESynMemoCache.create(aComponent: TComponent); constructor TCESynMemoCache.create(aComponent: TComponent);
begin begin
@ -365,6 +370,12 @@ begin
fDefaultFontSize := 10; fDefaultFontSize := 10;
SetDefaultCoeditKeystrokes(Self); // not called in inherited if owner = nil ! SetDefaultCoeditKeystrokes(Self); // not called in inherited if owner = nil !
// //
fAst := newAST(self, @astScanned);
fAstTimer := TIdleTimer.Create(self);
fAstTimer.Interval:= 2000;
fAstTimer.OnTimer:= @AstTimerEvent;
fAstTimer.Enabled:=true;
//
ShowHint := false; ShowHint := false;
InitHintWins; InitHintWins;
fHintDelay := 200; fHintDelay := 200;
@ -441,6 +452,8 @@ begin
if fileExists(fTempFileName) then if fileExists(fTempFileName) then
sysutils.DeleteFile(fTempFileName); sysutils.DeleteFile(fTempFileName);
// //
deleteAst(fAst);
//
inherited; inherited;
end; end;
@ -583,7 +596,50 @@ begin
end; end;
end; end;
{$REGION AST Scanner -----------------------------------------------------------}
procedure astScanned(param: pointer); cdecl;
begin
with TCESynMemo(param) do
begin
fScanning := false;
end;
end;
function TCESynMemo.getAstHandle: TAstHandle;
begin
if getIfScanning then result := 0
else result := fAst;
end;
function TCESynMemo.getIfScanning: boolean;
begin
exit(fScanning);
end;
procedure TCESynMemo.AstTimerEvent(sender: TObject);
var
buff: string;
len: NativeUint;
begin
if not fCanScan then exit;
fCanScan := false;
if fAst = 0 then exit;
//
buff := Lines.Text;
len := length(buff);
if len = 0 then exit;
fScanning := true;
scanBuffer(fast, @buff[1], len);
end;
{$ENDREGION --------------------------------------------------------------------}
{$REGION DDoc hints ------------------------------------------------------------} {$REGION DDoc hints ------------------------------------------------------------}
function TCEEditorHintWindow.CalcHintRect(MaxWidth: Integer; const AHint: String; AData: Pointer): TRect;
begin
Font.Size:= FontSize;
result := inherited CalcHintRect(MaxWidth, AHint, AData);
end;
procedure TCESynMemo.InitHintWins; procedure TCESynMemo.InitHintWins;
begin begin
if fCallTipWin = nil then begin if fCallTipWin = nil then begin
@ -723,6 +779,7 @@ procedure TCESynMemo.changeNotify(Sender: TObject);
begin begin
identifierToD2Syn; identifierToD2Syn;
fModified := true; fModified := true;
fCanScan := true;
fPositions.store; fPositions.store;
subjDocChanged(TCEMultiDocSubject(fMultiDocSubject), self); subjDocChanged(TCEMultiDocSubject(fMultiDocSubject), self);
end; end;