mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-30 10:50:53 +02:00
cody: declare var
git-svn-id: trunk@30934 -
This commit is contained in:
parent
0d7033d5fd
commit
b87cbc31f1
@ -313,12 +313,15 @@ type
|
||||
out ExistingDefinition: TFindContext; // next existing definition
|
||||
out ListOfPFindContext: TFPList; // possible classes
|
||||
out NewExprType: TExpressionType; out NewType: string): boolean; // false = not at an identifier
|
||||
function DeclareVariable(InsertPos: TCodeXYPosition;
|
||||
function DeclareVariableNearBy(InsertPos: TCodeXYPosition;
|
||||
const VariableName, NewType, NewUnitName: string;
|
||||
Visibility: TCodeTreeNodeDesc;
|
||||
SourceChangeCache: TSourceChangeCache;
|
||||
LevelPos: TCodeXYPosition // optional
|
||||
): boolean;
|
||||
function DeclareVariableAt(CursorPos: TCodeXYPosition;
|
||||
const VariableName, NewType, NewUnitName: string;
|
||||
SourceChangeCache: TSourceChangeCache): boolean;
|
||||
|
||||
// custom class completion
|
||||
function InitClassCompletion(const AClassName: string;
|
||||
@ -5482,8 +5485,8 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCodeCompletionCodeTool.DeclareVariable(InsertPos: TCodeXYPosition;
|
||||
const VariableName, NewType, NewUnitName: string;
|
||||
function TCodeCompletionCodeTool.DeclareVariableNearBy(
|
||||
InsertPos: TCodeXYPosition; const VariableName, NewType, NewUnitName: string;
|
||||
Visibility: TCodeTreeNodeDesc; SourceChangeCache: TSourceChangeCache;
|
||||
LevelPos: TCodeXYPosition): boolean;
|
||||
var
|
||||
@ -5496,7 +5499,9 @@ var
|
||||
LevelCleanPos: integer;
|
||||
begin
|
||||
Result:=false;
|
||||
debugln(['TCodeCompletionCodeTool.DeclareVariable InsertPos=',dbgs(InsertPos),' Name="',VariableName,'" Type="',NewType,'" Unit=',NewUnitName]);
|
||||
{$IFDEF CTDEBUG}
|
||||
debugln(['TCodeCompletionCodeTool.DeclareVariableNearBy InsertPos=',dbgs(InsertPos),' Name="',VariableName,'" Type="',NewType,'" Unit=',NewUnitName]);
|
||||
{$ENDIF}
|
||||
BuildTreeAndGetCleanPos(InsertPos,CleanCursorPos);
|
||||
CursorNode:=FindDeepestNodeAtPos(CleanCursorPos,true);
|
||||
CaretToCleanPos(LevelPos,LevelCleanPos);
|
||||
@ -5509,7 +5514,7 @@ begin
|
||||
InitClassCompletion(Node,SourceChangeCache);
|
||||
// check if variable already exists
|
||||
if VarExistsInCodeCompleteClass(UpperCaseStr(VariableName)) then begin
|
||||
debugln(['TCodeCompletionCodeTool.DeclareVariable member already exists: ',VariableName,' Class=',ExtractClassName(Node,false)]);
|
||||
debugln(['TCodeCompletionCodeTool.DeclareVariableNearBy member already exists: ',VariableName,' Class=',ExtractClassName(Node,false)]);
|
||||
exit;
|
||||
end;
|
||||
ClassPart:=ncpPublishedVars;
|
||||
@ -5525,7 +5530,7 @@ begin
|
||||
if (NewUnitName<>'')
|
||||
and (not AddUnitToMainUsesSection(NewUnitName,'',SourceChangeCache)) then
|
||||
begin
|
||||
debugln(['TCodeCompletionCodeTool.DeclareVariable AddUnitToMainUsesSection for new class memeber failed']);
|
||||
debugln(['TCodeCompletionCodeTool.DeclareVariableNearBy AddUnitToMainUsesSection for new class memeber failed']);
|
||||
exit;
|
||||
end;
|
||||
// apply the changes
|
||||
@ -5539,6 +5544,122 @@ begin
|
||||
NewPos,NewTopLine,SourceChangeCache,LevelCleanPos);
|
||||
end;
|
||||
|
||||
function TCodeCompletionCodeTool.DeclareVariableAt(CursorPos: TCodeXYPosition;
|
||||
const VariableName, NewType, NewUnitName: string;
|
||||
SourceChangeCache: TSourceChangeCache): boolean;
|
||||
var
|
||||
CleanCursorPos: integer;
|
||||
CursorNode: TCodeTreeNode;
|
||||
NewCode: String;
|
||||
FrontGap: TGapTyp;
|
||||
AfterGap: TGapTyp;
|
||||
InsertPos: Integer;
|
||||
Indent: Integer;
|
||||
Node: TCodeTreeNode;
|
||||
NeedSection: Boolean;
|
||||
begin
|
||||
Result:=false;
|
||||
{$IFDEF CTDEBUG}
|
||||
debugln(['TCodeCompletionCodeTool.DeclareVariableAt CursorPos=',dbgs(CursorPos),' Name="',VariableName,'" Type="',NewType,'" Unit=',NewUnitName]);
|
||||
{$ENDIF}
|
||||
BuildTreeAndGetCleanPos(CursorPos,CleanCursorPos);
|
||||
CursorNode:=FindDeepestNodeAtPos(CleanCursorPos,true);
|
||||
SourceChangeCache.MainScanner:=Scanner;
|
||||
InsertPos:=CleanCursorPos;
|
||||
Indent:=0;
|
||||
FrontGap:=gtNewLine;
|
||||
AfterGap:=gtNewLine;
|
||||
{$IFDEF CTDEBUG}
|
||||
debugln(['TCodeCompletionCodeTool.DeclareVariableAt CursorNode=',CursorNode.DescAsString]);
|
||||
{$ENDIF}
|
||||
NewCode:=VariableName+':'+NewType+';';
|
||||
NeedSection:=false;
|
||||
if CursorNode.Desc=ctnVarDefinition then begin
|
||||
// insert in front of another var
|
||||
CursorNode:=GetFirstGroupVarNode(CursorNode);
|
||||
InsertPos:=CursorNode.StartPos;
|
||||
Indent:=GetLineIndent(Src,InsertPos);
|
||||
end else if CursorNode.Desc in (AllClassBaseSections
|
||||
+[ctnVarSection,ctnRecordType,ctnClassClassVar])
|
||||
then begin
|
||||
// insert into a var section
|
||||
if (CursorNode.FirstChild=nil)
|
||||
or (CursorNode.FirstChild.StartPos>InsertPos) then begin
|
||||
MoveCursorToNodeStart(CursorNode);
|
||||
ReadNextAtom;
|
||||
if (CurPos.EndPos<CursorNode.EndPos)
|
||||
and ((CursorNode.FirstChild=nil) or (CursorNode.FirstChild.StartPos>CurPos.EndPos))
|
||||
and (InsertPos<CurPos.EndPos) then
|
||||
InsertPos:=CurPos.EndPos;
|
||||
end;
|
||||
if CursorNode.FirstChild<>nil then
|
||||
Indent:=GetLineIndent(Src,CursorNode.FirstChild.StartPos)
|
||||
else
|
||||
Indent:=GetLineIndent(Src,CursorNode.StartPos)
|
||||
+SourceChangeCache.BeautifyCodeOptions.Indent;
|
||||
end else if CursorNode.Desc in [ctnProcedure,ctnInterface,ctnImplementation,
|
||||
ctnProgram,ctnLibrary,ctnPackage]
|
||||
then begin
|
||||
Node:=CursorNode.FirstChild;
|
||||
// make sure to insert behind uses section and proc header
|
||||
if (Node<>nil) and (Node.Desc in [ctnUsesSection,ctnProcedureHead]) then
|
||||
begin
|
||||
if (Node<>nil) and (InsertPos<Node.EndPos) then
|
||||
InsertPos:=Node.EndPos;
|
||||
end;
|
||||
// find node in front
|
||||
while (Node<>nil) and (Node.NextBrother<>nil)
|
||||
and (Node.NextBrother.StartPos<InsertPos) do
|
||||
Node:=Node.NextBrother;
|
||||
if (Node<>nil) and (Node.Desc=ctnVarSection) then begin
|
||||
// append to a var section
|
||||
if Node.LastChild<>nil then
|
||||
Indent:=GetLineIndent(Src,Node.LastChild.StartPos)
|
||||
else
|
||||
Indent:=GetLineIndent(Src,Node.StartPos)
|
||||
+SourceChangeCache.BeautifyCodeOptions.Indent;
|
||||
end else begin
|
||||
// start a new var section
|
||||
NeedSection:=true;
|
||||
if Node<>nil then
|
||||
Indent:=GetLineIndent(Src,Node.StartPos)
|
||||
else if CursorNode.FirstChild<>nil then
|
||||
Indent:=GetLineIndent(Src,CursorNode.FirstChild.StartPos)
|
||||
else
|
||||
Indent:=GetLineIndent(Src,CursorNode.StartPos);
|
||||
end;
|
||||
end else begin
|
||||
// default: add the variable at cursor
|
||||
NeedSection:=true;
|
||||
end;
|
||||
if NeedSection then
|
||||
NewCode:='var'+SourceChangeCache.BeautifyCodeOptions.LineEnd
|
||||
+GetIndentStr(SourceChangeCache.BeautifyCodeOptions.Indent)+NewCode;
|
||||
NewCode:=SourceChangeCache.BeautifyCodeOptions.BeautifyStatement(NewCode,
|
||||
Indent,[bcfIndentExistingLineBreaks]);
|
||||
|
||||
SourceChangeCache.BeginUpdate;
|
||||
try
|
||||
if (NewUnitName<>'') then begin
|
||||
if not AddUnitToMainUsesSection(NewUnitName,'',SourceChangeCache) then begin
|
||||
debugln(['TCodeCompletionCodeTool.DeclareVariableAt AddUnitToMainUsesSection failed']);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
{$IFDEF VerboseCompletionAdds}
|
||||
debugln(['TCodeCompletionCodeTool.DeclareVariableAt NewCode="',dbgstr(NewCode),'"']);
|
||||
{$ENDIF}
|
||||
if not SourceChangeCache.Replace(FrontGap,AfterGap,InsertPos,InsertPos,NewCode)
|
||||
then exit;
|
||||
Result:=true;
|
||||
finally
|
||||
if not Result then
|
||||
SourceChangeCache.Clear;
|
||||
if not SourceChangeCache.EndUpdate then
|
||||
Result:=false;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCodeCompletionCodeTool.GatherPublishedMethods(
|
||||
ClassNode: TCodeTreeNode; out ListOfPFindContext: TFPList): boolean;
|
||||
var
|
||||
|
@ -515,11 +515,13 @@ type
|
||||
out ExistingDefinition: TFindContext; // next existing definition
|
||||
out ListOfPFindContext: TFPList; // possible classes
|
||||
out NewExprType: TExpressionType; out NewType: string): boolean; // false = not at an identifier or syntax error
|
||||
function DeclareVariable(Code: TCodeBuffer; X,Y: integer;
|
||||
function DeclareVariableNearBy(Code: TCodeBuffer; X,Y: integer;
|
||||
const VariableName, NewType, NewUnitName: string;
|
||||
Visibility: TCodeTreeNodeDesc;
|
||||
LvlPosCode: TCodeBuffer = nil; LvlPosX: integer = 0; LvlPosY: integer = 0
|
||||
): boolean;
|
||||
function DeclareVariableAt(Code: TCodeBuffer; X,Y: integer;
|
||||
const VariableName, NewType, NewUnitName: string): boolean;
|
||||
function FindRedefinitions(Code: TCodeBuffer;
|
||||
out TreeOfCodeTreeNodeExt: TAVLTree; WithEnums: boolean): boolean;
|
||||
function RemoveRedefinitions(Code: TCodeBuffer;
|
||||
@ -3656,15 +3658,15 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCodeToolManager.DeclareVariable(Code: TCodeBuffer; X, Y: integer;
|
||||
const VariableName, NewType, NewUnitName: string;
|
||||
Visibility: TCodeTreeNodeDesc;
|
||||
LvlPosCode: TCodeBuffer; LvlPosX: integer; LvlPosY: integer): boolean;
|
||||
function TCodeToolManager.DeclareVariableNearBy(Code: TCodeBuffer; X,
|
||||
Y: integer; const VariableName, NewType, NewUnitName: string;
|
||||
Visibility: TCodeTreeNodeDesc; LvlPosCode: TCodeBuffer; LvlPosX: integer;
|
||||
LvlPosY: integer): boolean;
|
||||
var
|
||||
CursorPos, LvlPos: TCodeXYPosition;
|
||||
begin
|
||||
{$IFDEF CTDEBUG}
|
||||
DebugLn(['TCodeToolManager.DeclareVariable A ',Code.Filename,' X=',X,' Y=',Y]);
|
||||
DebugLn(['TCodeToolManager.DeclareVariableNearBy A ',Code.Filename,' X=',X,' Y=',Y]);
|
||||
{$ENDIF}
|
||||
Result:=false;
|
||||
if not InitCurCodeTool(Code) then exit;
|
||||
@ -3675,13 +3677,34 @@ begin
|
||||
LvlPos.X:=LvlPosX;
|
||||
LvlPos.Y:=LvlPosY;
|
||||
try
|
||||
Result:=FCurCodeTool.DeclareVariable(CursorPos,VariableName,
|
||||
Result:=FCurCodeTool.DeclareVariableNearBy(CursorPos,VariableName,
|
||||
NewType,NewUnitName,Visibility,SourceChangeCache,LvlPos);
|
||||
except
|
||||
on e: Exception do Result:=HandleException(e);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCodeToolManager.DeclareVariableAt(Code: TCodeBuffer; X, Y: integer;
|
||||
const VariableName, NewType, NewUnitName: string): boolean;
|
||||
var
|
||||
CursorPos: TCodeXYPosition;
|
||||
begin
|
||||
{$IFDEF CTDEBUG}
|
||||
DebugLn(['TCodeToolManager.DeclareVariableNearBy A ',Code.Filename,' X=',X,' Y=',Y]);
|
||||
{$ENDIF}
|
||||
Result:=false;
|
||||
if not InitCurCodeTool(Code) then exit;
|
||||
CursorPos.Code:=Code;
|
||||
CursorPos.X:=X;
|
||||
CursorPos.Y:=Y;
|
||||
try
|
||||
Result:=FCurCodeTool.DeclareVariableAt(CursorPos,VariableName,
|
||||
NewType,NewUnitName,SourceChangeCache);
|
||||
except
|
||||
on e: Exception do Result:=HandleException(e);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCodeToolManager.FindRedefinitions(Code: TCodeBuffer; out
|
||||
TreeOfCodeTreeNodeExt: TAVLTree; WithEnums: boolean): boolean;
|
||||
begin
|
||||
|
@ -2476,7 +2476,10 @@ end;
|
||||
function TCustomCodeTool.CaretToCleanPos(const Caret: TCodeXYPosition;
|
||||
out CleanPos: integer): integer;
|
||||
begin
|
||||
CleanPos:=0;
|
||||
if Caret.Code=nil then begin
|
||||
CleanPos:=0;
|
||||
exit(-2);
|
||||
end;
|
||||
//DebugLn(['TCustomCodeTool.CaretToCleanPos A ',Caret.Code.Filename,' ',Caret.Y,',',Caret.X,' ',Caret.Code.SourceLength]);
|
||||
Caret.Code.LineColToPosition(Caret.Y,Caret.X,CleanPos);
|
||||
//DebugLn(['TCustomCodeTool.CaretToCleanPos B ',CleanPos,',',Caret.Y,',',Caret.X,' ',dbgstr(copy(Caret.Code.Source,CleanPos-20,20)),'|',dbgstr(copy(Caret.Code.Source,CleanPos,20))]);
|
||||
|
@ -97,10 +97,7 @@ begin
|
||||
crsDeclareVariable,
|
||||
CleanIDEShortCut,CleanIDEShortCut,nil,@ShowDeclareVariableDialog);
|
||||
RegisterIDEMenuCommand(SrcEditSubMenuRefactor, 'DeclareVariable',
|
||||
crsDeclareVariable2, nil, nil, DeclareVariableCommand)
|
||||
{$IFNDEF EnableCodyExperiments}
|
||||
.Visible:=false
|
||||
{$ENDIF};
|
||||
crsDeclareVariable2, nil, nil, DeclareVariableCommand);
|
||||
|
||||
|
||||
// Refactor menu - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -413,7 +413,7 @@ begin
|
||||
SetLength(Result,l);
|
||||
MemStream.Read(Result[1],l);
|
||||
end;
|
||||
debugln(['TCodyClipboardData.ReadString Result="',Result,'"']);
|
||||
//debugln(['TCodyClipboardData.ReadString Result="',Result,'"']);
|
||||
end;
|
||||
|
||||
procedure TCodyClipboardData.Execute(SrcEdit: TSourceEditorInterface;
|
||||
@ -511,7 +511,6 @@ function TCody.WriteToClipboard(Data: TCodyClipboardData; AClipboard: TClipboard
|
||||
var
|
||||
MemStream: TMemoryStream;
|
||||
ID: ShortString;
|
||||
s: string;
|
||||
begin
|
||||
if AClipboard=nil then AClipboard:=Clipboard;
|
||||
AClipboard.AsText:=Data.AsText;
|
||||
@ -523,10 +522,6 @@ begin
|
||||
MemStream.Write(ID[0],length(ID)+1);
|
||||
Data.WriteToStream(MemStream);
|
||||
MemStream.Position:=0;
|
||||
SetLength(s,MemStream.Size);
|
||||
MemStream.Read(s[1],length(s));
|
||||
debugln(['TCody.WriteToClipboard Stream=',dbgstr(s)]);
|
||||
MemStream.Position:=0;
|
||||
Result:=AClipboard.AddFormat(ClipboardFormatId,MemStream);
|
||||
finally
|
||||
MemStream.Free;
|
||||
|
@ -28,8 +28,6 @@
|
||||
ToDo:
|
||||
- guess parameter
|
||||
- guess j:=<i>
|
||||
- Extend uses section when adding to a class
|
||||
- paste from clipboard
|
||||
}
|
||||
unit DeclareVarDlg;
|
||||
|
||||
@ -41,7 +39,7 @@ uses
|
||||
Classes, SysUtils, LCLProc, contnrs, LResources, Forms, Controls, Graphics,
|
||||
Dialogs, ButtonPanel, StdCtrls, ExtCtrls,
|
||||
IDEDialogs, LazIDEIntf, SrcEditorIntf,
|
||||
FileProcs, CodeToolManager, FindDeclarationTool, CodeTree,
|
||||
FileProcs, CodeToolManager, FindDeclarationTool, CodeTree, CodeCache,
|
||||
KeywordFuncLists, BasicCodeTools, CodeAtom,
|
||||
CodyUtils, CodyStrConsts;
|
||||
|
||||
@ -215,10 +213,27 @@ end;
|
||||
|
||||
procedure TCodyClipboardDeclareVar.Execute(SrcEdit: TSourceEditorInterface;
|
||||
LogXY: TPoint);
|
||||
var
|
||||
OldChange: Boolean;
|
||||
Code: TCodeBuffer;
|
||||
begin
|
||||
debugln(['TCodyClipboardDeclareVar.Execute ']);
|
||||
//debugln(['TCodyClipboardDeclareVar.Execute ']);
|
||||
if not LazarusIDE.BeginCodeTools then exit;
|
||||
|
||||
SrcEdit.Selection:=AsText;
|
||||
Code:=SrcEdit.CodeToolsBuffer as TCodeBuffer;
|
||||
|
||||
OldChange:=LazarusIDE.OpenEditorsOnCodeToolChange;
|
||||
try
|
||||
LazarusIDE.OpenEditorsOnCodeToolChange:=true;
|
||||
if not CodeToolBoss.DeclareVariableAt(Code,LogXY.X,LogXY.Y,
|
||||
VarName,VarType,TheUnitName)
|
||||
then begin
|
||||
debugln(['TCodyClipboardDeclareVar.Execute Error']);
|
||||
LazarusIDE.DoJumpToCodeToolBossError;
|
||||
end;
|
||||
finally
|
||||
LazarusIDE.OpenEditorsOnCodeToolChange:=OldChange;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TCodyDeclareVarTarget }
|
||||
@ -382,6 +397,8 @@ begin
|
||||
Result:=ShowModal=mrOk;
|
||||
|
||||
if Result then begin
|
||||
if not LazarusIDE.BeginCodeTools then exit;
|
||||
|
||||
NewType:=Trim(TypeEdit.Text);
|
||||
Target:=TCodyDeclareVarTarget(Targets[WhereRadioGroup.ItemIndex]);
|
||||
|
||||
@ -406,7 +423,7 @@ begin
|
||||
try
|
||||
OldSrcEdit:=SourceEditorManagerIntf.ActiveEditor;
|
||||
LazarusIDE.OpenEditorsOnCodeToolChange:=true;
|
||||
if not CodeToolBoss.DeclareVariable(
|
||||
if not CodeToolBoss.DeclareVariableNearBy(
|
||||
CodePos.Code,CodePos.X,CodePos.Y,
|
||||
Identifier,NewType,UnitOfType,Target.Visibility,
|
||||
Target.NodeStartPos.Code,Target.NodeStartPos.X,Target.NodeStartPos.Y)
|
||||
|
@ -1804,14 +1804,9 @@ end;
|
||||
|
||||
function TPascalReaderTool.ClassSectionNodeStartsWithWord(ANode: TCodeTreeNode
|
||||
): boolean;
|
||||
var p: integer;
|
||||
begin
|
||||
Result:=false;
|
||||
if ANode=nil then exit;
|
||||
p:=ANode.StartPos;
|
||||
while (p<ANode.EndPos) and (IsIdentChar[Src[p]]) do inc(p);
|
||||
if (p=ANode.StartPos) then exit;
|
||||
Result:=true;
|
||||
Result:=(ANode<>nil) and (ANode.StartPos<ANode.EndPos)
|
||||
and (IsIdentStartChar[Src[ANode.StartPos]]);
|
||||
end;
|
||||
|
||||
function TPascalReaderTool.IsClassNode(Node: TCodeTreeNode): boolean;
|
||||
|
Loading…
Reference in New Issue
Block a user