From 3ac5fef89bc5ed6a29ea76224788462d08c21dcb Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Tue, 15 Sep 2015 14:00:23 +0200 Subject: [PATCH 1/6] sw-1 --- lazproj/coedit.lpi | 6 ++- lazproj/coedit.lpr | 2 +- src/ce_dast.pas | 76 +++++++++++++++++++++++++++++++++++++ src/ce_editor.pas | 94 ++++++++++++++++------------------------------ src/ce_synmemo.pas | 71 ++++++++++++++++++++++++++++++---- 5 files changed, 178 insertions(+), 71 deletions(-) create mode 100644 src/ce_dast.pas diff --git a/lazproj/coedit.lpi b/lazproj/coedit.lpi index 4a164a90..82a73a3e 100644 --- a/lazproj/coedit.lpi +++ b/lazproj/coedit.lpi @@ -135,7 +135,7 @@ - + @@ -356,6 +356,10 @@ + + + + diff --git a/lazproj/coedit.lpr b/lazproj/coedit.lpr index 876402f1..b6d2f23b 100644 --- a/lazproj/coedit.lpr +++ b/lazproj/coedit.lpr @@ -10,7 +10,7 @@ uses ce_observer, ce_libman, ce_tools, ce_dcd, ce_main, ce_writableComponent, ce_symstring, ce_staticmacro, ce_inspectors, ce_editoroptions, ce_dockoptions, ce_shortcutseditor, ce_mru, ce_processes, ce_dubproject, ce_dialogs, -ce_dubprojeditor; +ce_dubprojeditor, ce_dast; {$R *.res} diff --git a/src/ce_dast.pas b/src/ce_dast.pas new file mode 100644 index 00000000..b0d42138 --- /dev/null +++ b/src/ce_dast.pas @@ -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. + diff --git a/src/ce_editor.pas b/src/ce_editor.pas index 390f4c34..efa6cc27 100644 --- a/src/ce_editor.pas +++ b/src/ce_editor.pas @@ -6,7 +6,7 @@ interface uses 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, ce_widget, ce_interfaces, ce_synmemo, ce_dlang, ce_common, ce_dcd, ce_observer; @@ -43,7 +43,6 @@ type procedure mnuedJum2DeclClick(Sender: TObject); procedure PageControlChange(Sender: TObject); protected - procedure updateDelayed; override; procedure updateImperative; override; private fKeyChanged: boolean; @@ -172,8 +171,6 @@ begin fDoc := aDoc; pageControl.ActivePage := sheet; focusedEditorChanged; - beginDelayedUpdate; - updateImperative; end; procedure TCEEditorWidget.docClosing(aDoc: TCESynMemo); @@ -195,16 +192,16 @@ begin if aDoc = fDoc then exit; fDoc := aDoc; focusedEditorChanged; - beginDelayedUpdate; - updateImperative; + beginImperativeUpdate; + endImperativeUpdate; end; procedure TCEEditorWidget.docChanged(aDoc: TCESynMemo); begin if fDoc <> aDoc then exit; fKeyChanged := true; - beginDelayedUpdate; - updateImperative; + beginImperativeUpdate; + endImperativeUpdate; end; {$ENDREGION} @@ -281,23 +278,28 @@ begin if (pageControl.ActivePage.Caption = '') then begin fKeyChanged := true; - beginDelayedUpdate; + beginImperativeUpdate; + endImperativeUpdate; end; end; procedure TCEEditorWidget.PageControlChange(Sender: TObject); begin - updateImperative; + beginImperativeUpdate; + endImperativeUpdate; end; procedure TCEEditorWidget.memoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin case Key of 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; if fKeyChanged then - beginDelayedUpdate + begin + beginImperativeUpdate; + endImperativeUpdate; + end else if (Key = VK_UP) and (shift = [ssShift,ssCtrl]) then getSymbolLoc; end; @@ -317,19 +319,21 @@ end; procedure TCEEditorWidget.memoKeyPress(Sender: TObject; var Key: char); begin fKeyChanged := true; - beginDelayedUpdate; + beginImperativeUpdate; + endImperativeUpdate; end; procedure TCEEditorWidget.memoMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin - beginDelayedUpdate; - updateImperative; + beginImperativeUpdate; + endImperativeUpdate; end; procedure TCEEditorWidget.memoMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if not (ssLeft in Shift) then exit; - beginDelayedUpdate; + beginImperativeUpdate; + endImperativeUpdate; end; procedure TCEEditorWidget.memoCtrlClick(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); @@ -372,8 +376,8 @@ end; procedure TCEEditorWidget.updateImperative; const modstr: array[boolean] of string = ('...', 'MODIFIED'); -//var - //md: string; +var + md: string; begin if fDoc = nil then begin 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[1].Text := modstr[fDoc.modified]; editorStatus.Panels[2].Text := fDoc.fileName; - // TODO-cEditor: set tab caption directly (e.g one start, if reload last docs) - //if Visible then if pageControl.ActivePage <> nil then - //if pageControl.ActivePage.Caption = '' then - //begin - // if fDoc.isDSource then - // begin - // lex(fDoc.Lines.Text, fTokList, @lexFindToken); - // md := getModuleName(fTokList); - // fTokList.Clear; - // end; - // if md = '' then md := extractFileName(fDoc.fileName); - // pageControl.ActivePage.Caption := md; - //end; + if fKeyChanged then + begin + md := ''; + if fDoc.isDSource and (fDoc.ast <> 0) then + md := moduleName(fDoc.ast); + if md = '' then + md := extractFileName(fDoc.fileName); + pageControl.ActivePage.Caption := md; + end; + fKeyChanged := false; end; end; @@ -410,37 +411,6 @@ begin fModStart := false; 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} {$REGION Editor context menu ---------------------------------------------------} diff --git a/src/ce_synmemo.pas b/src/ce_synmemo.pas index 4ae41a13..dd5e30e7 100644 --- a/src/ce_synmemo.pas +++ b/src/ce_synmemo.pas @@ -8,7 +8,8 @@ uses Classes, SysUtils, controls,lcltype, Forms, graphics, ExtCtrls, crc, SynPluginSyncroEdit, SynCompletion, SynEditKeyCmds, LazSynEditText, SynEdit, 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 @@ -77,6 +78,9 @@ type TCESynMemo = class(TSynEdit) private + fScanning: boolean; + fCanScan: boolean; + fAst: TAstHandle; fFilename: string; fModified: boolean; fFileDate: double; @@ -94,6 +98,7 @@ type fHintDelay: Integer; fAutoDotDelay: Integer; fHintTimer: TIdleTimer; + fAstTimer: TIdleTimer; fAutoDotTimer: TIdleTimer; fCanShowHint: boolean; fCanAutoDot: boolean; @@ -103,6 +108,8 @@ type fCompletion: TSynCompletion; fD2Highlighter: TSynD2Syn; fTxtHighlighter: TSynTxtSyn; + function getIfScanning: boolean; + function getAstHandle: TAstHandle; function getMouseFileBytePos: Integer; procedure changeNotify(Sender: TObject); procedure identifierToD2Syn; @@ -111,6 +118,7 @@ type class procedure cleanCache; static; procedure setDefaultFontSize(aValue: Integer); procedure getCallTips; + procedure AstTimerEvent(sender: TObject); procedure HintTimerEvent(sender: TObject); procedure AutoDotTimerEvent(sender: TObject); procedure InitHintWins; @@ -161,6 +169,7 @@ type property isProjectSource: boolean read fIsConfig; property isTemporary: boolean read getIfTemp; property TextView; + property ast: TAstHandle read GetAstHandle; // property MouseStart: Integer read getMouseFileBytePos; property D2Highlighter: TSynD2Syn read fD2Highlighter; @@ -169,6 +178,8 @@ type procedure SetDefaultCoeditKeystrokes(ed: TSynEdit); + procedure astScanned(param: pointer); cdecl; + var D2Syn: TSynD2Syn; // used as model to set the options when no editor exists. LfmSyn: TSynLfmSyn; @@ -179,12 +190,6 @@ implementation uses 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 -------------------------------------------------------} constructor TCESynMemoCache.create(aComponent: TComponent); begin @@ -365,6 +370,12 @@ begin fDefaultFontSize := 10; 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; InitHintWins; fHintDelay := 200; @@ -441,6 +452,8 @@ begin if fileExists(fTempFileName) then sysutils.DeleteFile(fTempFileName); // + deleteAst(fAst); + // inherited; end; @@ -583,7 +596,50 @@ begin 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 ------------------------------------------------------------} +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; begin if fCallTipWin = nil then begin @@ -723,6 +779,7 @@ procedure TCESynMemo.changeNotify(Sender: TObject); begin identifierToD2Syn; fModified := true; + fCanScan := true; fPositions.store; subjDocChanged(TCEMultiDocSubject(fMultiDocSubject), self); end; From 7e50d1ba77390f277748d56c461aba285d9beb5e Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Tue, 15 Sep 2015 18:44:37 +0200 Subject: [PATCH 2/6] sw-2 - adapter symbol list widget - compared to previous system errors and warnings are missing --- cedast/build/cedast.coedit | 2 +- cedast/src/ast.d | 47 ++++++++++++++---------- cedast/src/common.d | 5 --- src/ce_symlist.pas | 74 +++++++++++++------------------------- 4 files changed, 53 insertions(+), 75 deletions(-) diff --git a/cedast/build/cedast.coedit b/cedast/build/cedast.coedit index 1516a19b..052a500e 100644 --- a/cedast/build/cedast.coedit +++ b/cedast/build/cedast.coedit @@ -6,7 +6,7 @@ object CurrentProject: TCENativeProject debugingOptions.codeviewDexts = True messagesOptions.additionalWarnings = True outputOptions.binaryKind = sharedlib - pathsOptions.outputFilename = '..\..\lazproj\cedast.dll' + pathsOptions.outputFilename = '..\bin\cedast.dll' end> Sources.Strings = ( '..\src\cedast.d' diff --git a/cedast/src/ast.d b/cedast/src/ast.d index 1c7530d2..a6a7dc79 100644 --- a/cedast/src/ast.d +++ b/cedast/src/ast.d @@ -8,7 +8,14 @@ import common; private { - enum AstInfos {ModuleName, ErrorsJson, ErrorsPas, SymsJson, SymsPas} + enum AstInfos + { + ModuleName, + ErrorsJson, ErrorsPas, + SymsJson, SymsPas, + TodosJson, TodosPas + } + alias CachedInfos = EnumSet!(AstInfos, Set8); enum SymbolType @@ -378,36 +385,38 @@ public: final string moduleName() { - string result; - - if (!scanned) - return result; - if (AstInfos.ModuleName in cachedInfos) - return modName; - - cachedInfos += AstInfos.ModuleName; - if (mod.moduleDeclaration) - foreach(Token t; mod.moduleDeclaration.moduleName.identifiers) - result ~= t.text ~ "."; - - if (result.length) - modName = result[0 .. $-1]; + if (scanned && AstInfos.ModuleName !in cachedInfos) + { + string result; + cachedInfos += AstInfos.ModuleName; + if (mod.moduleDeclaration) + foreach(Token t; mod.moduleDeclaration.moduleName.identifiers) + result ~= t.text ~ "."; + if (result.length) + modName = result[0 .. $-1]; + } return modName; } final ubyte[] todoListPas() { - return null; + if (scanned && AstInfos.TodosPas !in cachedInfos) + { + } + return todosPas; } final ubyte[] todoListJson() { - return null; + if (scanned && AstInfos.TodosJson !in cachedInfos) + { + } + return todosJson; } final ubyte[] symbolListPas() { - if (AstInfos.SymsPas !in cachedInfos) + if (scanned && AstInfos.SymsPas !in cachedInfos) { cachedInfos += AstInfos.SymsPas; SymbolListBuilder slb = construct!SymbolListBuilder(mod); @@ -419,7 +428,7 @@ public: final ubyte[] symbolListJson() { - if (AstInfos.SymsJson !in cachedInfos) + if (scanned && AstInfos.SymsJson !in cachedInfos) { cachedInfos += AstInfos.SymsJson; SymbolListBuilder slb = construct!SymbolListBuilder(mod); diff --git a/cedast/src/common.d b/cedast/src/common.d index fa485ca8..8c8a65ed 100644 --- a/cedast/src/common.d +++ b/cedast/src/common.d @@ -11,8 +11,3 @@ enum SerializationFormat : byte json, pascal } - -enum logcall = q{ - import std.file; - append("cedast_log.txt", cast(ubyte[])(__PRETTY_FUNCTION__ ~ "\r\n")); -}; diff --git a/src/ce_symlist.pas b/src/ce_symlist.pas index f6b985c6..83e0a0dc 100644 --- a/src/ce_symlist.pas +++ b/src/ce_symlist.pas @@ -6,8 +6,8 @@ interface uses Classes, SysUtils, TreeFilterEdit, Forms, Controls, Graphics, ExtCtrls, Menus, - ComCtrls, ce_widget, jsonparser, process, actnlist, Buttons, Clipbrd, LCLProc, - ce_common, ce_observer, ce_synmemo, ce_interfaces, ce_writableComponent, ce_processes; + ComCtrls, ce_widget, jsonparser, actnlist, Buttons, Clipbrd, LCLProc, + ce_common, ce_observer, ce_synmemo, ce_interfaces, ce_writableComponent, ce_dast; type @@ -112,11 +112,9 @@ type procedure TreeFilterEdit1MouseEnter(Sender: TObject); procedure TreeKeyPress(Sender: TObject; var Key: char); private - fHasToolExe: boolean; fOptions: TCESymbolListOptions; fSyms: TSymbolList; fMsgs: ICEMessagesDisplay; - fToolProc: TCEProcess; fActCopyIdent: TAction; fActRefresh: TAction; fActRefreshOnChange: TAction; @@ -131,6 +129,7 @@ type fSmartFilter: boolean; fAutoExpandErrors: boolean; fSortSymbols: boolean; + fSymStream: TMemoryStream; ndAlias, ndClass, ndEnum, ndFunc, ndUni: TTreeNode; ndImp, ndIntf, ndMix, ndStruct, ndTmp: TTreeNode; ndVar, ndWarn, ndErr: TTreeNode; @@ -144,9 +143,7 @@ type procedure clearTree; procedure expandCurrentDeclaration; // - procedure checkIfHasToolExe; - procedure callToolProc; - procedure toolTerminated(sender: TObject); + procedure refreshFromAst; // procedure docNew(aDoc: TCESynMemo); procedure docClosing(aDoc: TCESynMemo); @@ -180,7 +177,6 @@ implementation const OptsFname = 'symbollist.txt'; - toolExeName = 'cesyms' + exeExt; {$REGION Serializable symbols---------------------------------------------------} constructor TSymbol.create(ACollection: TCollection); @@ -318,7 +314,6 @@ begin fAutoRefresh := false; fRefreshOnFocus := true; fRefreshOnChange := false; - checkIfHasToolExe; // fActCopyIdent := TAction.Create(self); fActCopyIdent.OnExecute:=@actCopyIdentExecute; @@ -348,6 +343,7 @@ begin inherited; // allow empty name if owner is nil fSyms := TSymbolList.create(nil); + fSymStream := TMemoryStream.Create; // fOptions := TCESymbolListOptions.Create(self); fOptions.Name:= 'symbolListOptions'; @@ -388,8 +384,8 @@ destructor TCESymbolListWidget.destroy; begin EntitiesConnector.removeObserver(self); // - killProcess(fToolProc); fSyms.Free; + fSymStream.Free; // fOptions.saveToFile(getCoeditDocPath + OptsFname); fOptions.Free; @@ -400,10 +396,9 @@ end; procedure TCESymbolListWidget.SetVisible(Value: boolean); begin inherited; - checkIfHasToolExe; getMessageDisplay(fMsgs); if Value then - callToolProc; + refreshFromAst; end; {$ENDREGION} @@ -434,7 +429,7 @@ end; procedure TCESymbolListWidget.actRefreshExecute(Sender: TObject); begin if Updating then exit; - callToolProc; + refreshFromAst; end; procedure TCESymbolListWidget.actAutoRefreshExecute(Sender: TObject); @@ -483,7 +478,7 @@ procedure TCESymbolListWidget.optionedEvent(anEvent: TOptionEditorEvent); begin if anEvent <> oeeAccept then exit; fOptions.AssignTo(self); - callToolProc; + refreshFromAst; end; function TCESymbolListWidget.optionedOptionsModified: boolean; @@ -514,7 +509,7 @@ begin if not Visible then exit; // if fAutoRefresh then beginDelayedUpdate - else if fRefreshOnFocus then callToolProc; + else if fRefreshOnFocus then refreshFromAst; end; procedure TCESymbolListWidget.docChanged(aDoc: TCESynMemo); @@ -523,7 +518,7 @@ begin if not Visible then exit; // if fAutoRefresh then beginDelayedUpdate - else if fRefreshOnChange then callToolProc; + else if fRefreshOnChange then refreshFromAst; // //expandCurrentDeclaration; end; @@ -533,7 +528,7 @@ end; procedure TCESymbolListWidget.updateDelayed; begin if not fAutoRefresh then exit; - callToolProc; + refreshFromAst; end; procedure TCESymbolListWidget.btnRefreshClick(Sender: TObject); @@ -645,34 +640,7 @@ begin fDoc.SelectLine; end; -procedure TCESymbolListWidget.checkIfHasToolExe; -begin - fHasToolExe := exeInSysPath(toolExeName); -end; - -procedure TCESymbolListWidget.callToolProc; -var - str: string; -begin - if not fHasToolExe then exit; - if fDoc = nil then exit; - if fDoc.Lines.Count = 0 then exit; - if not fDoc.isDSource then exit; - // - killProcess(fToolProc); - fToolProc := TCEProcess.Create(nil); - fToolProc.ShowWindow := swoHIDE; - fToolProc.Options := [poUsePipes]; - fToolProc.Executable := exeFullName(toolExeName); - fToolProc.OnTerminate := @toolTerminated; - fToolProc.CurrentDirectory := ExtractFileDir(Application.ExeName); - fToolProc.Execute; - str := fDoc.Text; - fToolProc.Input.Write(str[1], length(str)); - fToolProc.CloseInput; -end; - -procedure TCESymbolListWidget.toolTerminated(sender: TObject); +procedure TCESymbolListWidget.refreshFromAst; // function getCatNode(node: TTreeNode; stype: TSymbolType ): TTreeNode; // @@ -732,16 +700,22 @@ end; // var i: Integer; + ptr: PByte; + len: NativeUint = 0; begin if ndAlias = nil then exit; clearTree; updateVisibleCat; - if fDoc = nil then exit; // - fToolProc.OnTerminate := nil; - fToolProc.OnReadData := nil; - fToolProc.OutputStack.Position:=0; - fSyms.LoadFromTool(fToolProc.OutputStack); + if not dastAvailable then exit; + if fDoc = nil then exit; + if fDoc.ast = 0 then exit; + // + ptr := symbolList(fDoc.ast, len, TSerializationFormat.pas); + fSymStream.clear; + fSymStream.Write(ptr^, len); + fSymStream.Position:=0; + fSyms.LoadFromTool(fSymStream); // tree.BeginUpdate; for i := 0 to fSyms.symbols.Count-1 do From 22b9b8d47a62c23ed03b55844fbe8bc0fd248bf8 Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Tue, 15 Sep 2015 23:07:37 +0200 Subject: [PATCH 3/6] fix error when dast not found --- src/ce_synmemo.pas | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/ce_synmemo.pas b/src/ce_synmemo.pas index dd5e30e7..5e56f6c3 100644 --- a/src/ce_synmemo.pas +++ b/src/ce_synmemo.pas @@ -370,11 +370,14 @@ begin fDefaultFontSize := 10; 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; + if dastAvailable then + begin + fAst := newAST(self, @astScanned); + fAstTimer := TIdleTimer.Create(self); + fAstTimer.Interval:= 2000; + fAstTimer.OnTimer:= @AstTimerEvent; + fAstTimer.Enabled:=true; + end; // ShowHint := false; InitHintWins; @@ -452,7 +455,8 @@ begin if fileExists(fTempFileName) then sysutils.DeleteFile(fTempFileName); // - deleteAst(fAst); + if dastAvailable then + deleteAst(fAst); // inherited; end; From 375c96df017df1c764bb8e581b2795bb4508de46 Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Tue, 15 Sep 2015 23:24:23 +0200 Subject: [PATCH 4/6] added config to build so lib under linux --- cedast/build/cedast.coedit | 25 ++++++++++++++++++++----- cedast/build/nux-postbuild.sh | 1 + 2 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 cedast/build/nux-postbuild.sh diff --git a/cedast/build/cedast.coedit b/cedast/build/cedast.coedit index 052a500e..78786834 100644 --- a/cedast/build/cedast.coedit +++ b/cedast/build/cedast.coedit @@ -6,14 +6,29 @@ object CurrentProject: TCENativeProject debugingOptions.codeviewDexts = True messagesOptions.additionalWarnings = True outputOptions.binaryKind = sharedlib - pathsOptions.outputFilename = '..\bin\cedast.dll' + pathsOptions.outputFilename = '../bin/cedast.so' + end + item + name = 'linux-dbg' + debugingOptions.debug = True + debugingOptions.codeviewDexts = True + messagesOptions.additionalWarnings = True + outputOptions.binaryKind = obj + pathsOptions.outputFilename = '../bin/cedast.o' + otherOptions.customOptions.Strings = ( + '-fPIC' + ) + postBuildProcess.executable = 'sh' + postBuildProcess.parameters.Strings = ( + '/nux-postbuild.sh' + ) end> Sources.Strings = ( - '..\src\cedast.d' - '..\src\common.d' - '..\src\ast.d' + '../src/cedast.d' + '../src/common.d' + '../src/ast.d' ) - ConfigurationIndex = 0 + ConfigurationIndex = 1 LibraryAliases.Strings = ( 'libdparse' 'iz' diff --git a/cedast/build/nux-postbuild.sh b/cedast/build/nux-postbuild.sh new file mode 100644 index 00000000..f52d1688 --- /dev/null +++ b/cedast/build/nux-postbuild.sh @@ -0,0 +1 @@ +dmd ../bin/cedast.o -of../bin/cedast.so -shared -defaultlib=libphobos2.so From 95fae8efbb3b270c5e1458a288474c75fef9f4ca Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Wed, 16 Sep 2015 02:49:53 +0200 Subject: [PATCH 5/6] work on #39 for the linux platform --- cedast/build/cedast.coedit | 4 ++-- cedast/build/nux-postbuild.sh | 2 +- cedast/src/ast.d | 15 +++++++++------ cedast/src/cedast.d | 11 +++++++++-- cedast/src/common.d | 4 +++- lazproj/coedit.lpi | 1 - src/ce_dast.pas | 14 ++++++-------- src/ce_symlist.pas | 1 + src/ce_synmemo.pas | 1 + 9 files changed, 32 insertions(+), 21 deletions(-) diff --git a/cedast/build/cedast.coedit b/cedast/build/cedast.coedit index 78786834..c029f46c 100644 --- a/cedast/build/cedast.coedit +++ b/cedast/build/cedast.coedit @@ -13,6 +13,7 @@ object CurrentProject: TCENativeProject debugingOptions.debug = True debugingOptions.codeviewDexts = True messagesOptions.additionalWarnings = True + messagesOptions.tlsInformations = True outputOptions.binaryKind = obj pathsOptions.outputFilename = '../bin/cedast.o' otherOptions.customOptions.Strings = ( @@ -30,7 +31,6 @@ object CurrentProject: TCENativeProject ) ConfigurationIndex = 1 LibraryAliases.Strings = ( - 'libdparse' - 'iz' + '*' ) end diff --git a/cedast/build/nux-postbuild.sh b/cedast/build/nux-postbuild.sh index f52d1688..ee838ad9 100644 --- a/cedast/build/nux-postbuild.sh +++ b/cedast/build/nux-postbuild.sh @@ -1 +1 @@ -dmd ../bin/cedast.o -of../bin/cedast.so -shared -defaultlib=libphobos2.so +dmd ../bin/cedast.o /home/basile/Dev/dproj/Iz/lib/iz.a /home/basile/Dev/metad/libs/libdparse.a -of../bin/cedast.so -shared -defaultlib=libphobos2.so diff --git a/cedast/src/ast.d b/cedast/src/ast.d index a6a7dc79..e6017fd5 100644 --- a/cedast/src/ast.d +++ b/cedast/src/ast.d @@ -1,7 +1,7 @@ module ast; import std.d.lexer, std.d.parser, std.d.ast; -import std.json, std.array, std.conv, std.parallelism; +import std.json, std.array, std.conv, std.parallelism, std.concurrency; import iz.enumset, iz.memory; import common; @@ -323,7 +323,7 @@ private: ubyte[] todosJson; ubyte[] symsPas; ubyte[] symsJson; - static AstError*[] errors; + __gshared static AstError*[] errors; final static void parserError(string fname, size_t line, size_t col, string msg, bool isErr) { @@ -349,6 +349,7 @@ private: mod = parseModule(getTokensForParser(src, config, &strcache), fname, null, &parserError); if (notif) notif(notifparam); scanned = true; + } public: @@ -366,7 +367,8 @@ public: try src = cast(ubyte[]) read(fname, size_t.max); catch(Exception e){} scanned = false; - task(&taskScan).executeInNewThread; + version(Windows)task(&taskScan).executeInNewThread; + else taskScan; } final void scanBuffer(ubyte[] buffer) @@ -374,7 +376,8 @@ public: resetCachedInfo; src = buffer.dup; scanned = false; - task(&taskScan).executeInNewThread; + version(Windows) task(&taskScan).executeInNewThread; + else taskScan; } @property AstNotification notification(){return notif;} @@ -393,7 +396,7 @@ public: foreach(Token t; mod.moduleDeclaration.moduleName.identifiers) result ~= t.text ~ "."; if (result.length) - modName = result[0 .. $-1]; + modName = result[0 .. $-1].idup; } return modName; } @@ -421,7 +424,7 @@ public: cachedInfos += AstInfos.SymsPas; SymbolListBuilder slb = construct!SymbolListBuilder(mod); scope(exit) destruct(slb); - symsPas = cast(ubyte[]) slb.serializePas(); + symsPas = cast(ubyte[]) slb.serializePas().dup; } return symsPas; } diff --git a/cedast/src/cedast.d b/cedast/src/cedast.d index 876c8192..562a8dc6 100644 --- a/cedast/src/cedast.d +++ b/cedast/src/cedast.d @@ -4,11 +4,19 @@ import core.runtime, common, ast; import iz.memory; __gshared Ast[] modules; +__gshared bool init; +void tryInit() +{ + if (init) return; + Runtime.initialize; + init = true; +} extern(C) export AstHandle newAst(void* param, AstNotification clbck) { + version(linux) tryInit; AstHandle result; try { @@ -134,7 +142,7 @@ version(Windows) final switch (ulReason) { case DLL_PROCESS_ATTACH: - Runtime.initialize; + tryInit; g_hInst = hInstance; dll_process_attach( hInstance, true ); break; @@ -155,4 +163,3 @@ version(Windows) return true; } } - diff --git a/cedast/src/common.d b/cedast/src/common.d index 8c8a65ed..cdb171e3 100644 --- a/cedast/src/common.d +++ b/cedast/src/common.d @@ -1,8 +1,10 @@ module common; +extern(C): + alias AstHandle = ptrdiff_t; -alias AstNotification = extern(C) void function(void* param); +alias AstNotification = void function(void* param); __gshared immutable AstHandle invalidAstHandle = 0; diff --git a/lazproj/coedit.lpi b/lazproj/coedit.lpi index 82a73a3e..bd8c8abd 100644 --- a/lazproj/coedit.lpi +++ b/lazproj/coedit.lpi @@ -112,7 +112,6 @@ - diff --git a/src/ce_dast.pas b/src/ce_dast.pas index b0d42138..34354ba7 100644 --- a/src/ce_dast.pas +++ b/src/ce_dast.pas @@ -5,7 +5,7 @@ unit ce_dast; interface uses - dynlibs, forms; + dynlibs, sysutils, ce_common; type @@ -44,14 +44,14 @@ var implementation var - dastHdl: TLibHandle; + dastHdl: TLibHandle = 0; + fname: string; initialization - if application.GetOptionValue('cedast') = 'off' then - exit; - - dastHdl := LoadLibrary('cedast'); + fname := exeFullName('cedast' + dynExt); + if FileExists(fname) then + dastHdl := LoadLibrary(fname); if dastHdl <> NilHandle then begin newAST := TNewAst(GetProcAddress(dastHdl, 'newAst')); @@ -60,13 +60,11 @@ initialization 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 diff --git a/src/ce_symlist.pas b/src/ce_symlist.pas index 83e0a0dc..897f7dbb 100644 --- a/src/ce_symlist.pas +++ b/src/ce_symlist.pas @@ -712,6 +712,7 @@ begin if fDoc.ast = 0 then exit; // ptr := symbolList(fDoc.ast, len, TSerializationFormat.pas); + if len = 0 then exit; fSymStream.clear; fSymStream.Write(ptr^, len); fSymStream.Position:=0; diff --git a/src/ce_synmemo.pas b/src/ce_synmemo.pas index 5e56f6c3..24baecb7 100644 --- a/src/ce_synmemo.pas +++ b/src/ce_synmemo.pas @@ -377,6 +377,7 @@ begin fAstTimer.Interval:= 2000; fAstTimer.OnTimer:= @AstTimerEvent; fAstTimer.Enabled:=true; + fAstTimer.AutoEnabled:=true; end; // ShowHint := false; From f6eae34679d4ed088e10992db7f1b0f95202cc63 Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Thu, 17 Sep 2015 02:57:54 +0200 Subject: [PATCH 6/6] increased idle timer frequency for ast rescan --- src/ce_synmemo.pas | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ce_synmemo.pas b/src/ce_synmemo.pas index 24baecb7..40d02b2d 100644 --- a/src/ce_synmemo.pas +++ b/src/ce_synmemo.pas @@ -112,6 +112,7 @@ type function getAstHandle: TAstHandle; function getMouseFileBytePos: Integer; procedure changeNotify(Sender: TObject); + procedure editedNotify(Sender: TSynEditStrings;aLinePos, aBytePos, aCount, aLineBrkCnt: Integer; aText: string); procedure identifierToD2Syn; procedure saveCache; procedure loadCache; @@ -374,7 +375,7 @@ begin begin fAst := newAST(self, @astScanned); fAstTimer := TIdleTimer.Create(self); - fAstTimer.Interval:= 2000; + fAstTimer.Interval:= 200; fAstTimer.OnTimer:= @AstTimerEvent; fAstTimer.Enabled:=true; fAstTimer.AutoEnabled:=true; @@ -437,6 +438,7 @@ begin fFilename := ''; fModified := false; TextBuffer.AddNotifyHandler(senrUndoRedoAdded, @changeNotify); + //TextBuffer.AddEditHandler(@editedNotify); // fPositions := TCESynMemoPositions.create(self); fMultiDocSubject := TCEMultiDocSubject.create; @@ -789,6 +791,11 @@ begin subjDocChanged(TCEMultiDocSubject(fMultiDocSubject), self); end; +procedure TCESynMemo.editedNotify(Sender: TSynEditStrings;aLinePos, aBytePos, aCount, aLineBrkCnt: Integer; aText: string); +begin + fCanScan := true; +end; + procedure TCESynMemo.loadFromFile(const aFilename: string); var ext: string;