cody: declare var

git-svn-id: trunk@30934 -
This commit is contained in:
mattias 2011-05-27 17:24:02 +00:00
parent 0d7033d5fd
commit b87cbc31f1
7 changed files with 188 additions and 37 deletions

View File

@ -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

View File

@ -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

View File

@ -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))]);

View File

@ -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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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;

View File

@ -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)

View File

@ -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;