codetools: started ability to load code completion snippets from an xml files, thanks to Don Ziesig, patch #15922

git-svn-id: trunk@42177 -
This commit is contained in:
mattias 2013-07-22 22:08:53 +00:00
parent 30837a8e7d
commit e02c8ef2c8
18 changed files with 982 additions and 189 deletions

2
.gitattributes vendored
View File

@ -675,6 +675,8 @@ components/codetools/changedeclarationtool.pas svneol=native#text/plain
components/codetools/codeatom.pas svneol=native#text/pascal
components/codetools/codebeautifier.pas svneol=native#text/plain
components/codetools/codecache.pas svneol=native#text/pascal
components/codetools/codecompletiontemplater.pas svneol=native#text/plain
components/codetools/codecompletiontemplates.xml svneol=native#text/plain
components/codetools/codecompletiontool.pas svneol=native#text/pascal
components/codetools/codegraph.pas svneol=native#text/plain
components/codetools/codeindex.pas svneol=native#text/plain

View File

@ -0,0 +1,432 @@
{
***************************************************************************
* *
* This source is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This code is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* General Public License for more details. *
* *
* A copy of the GNU General Public License is available on the World *
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
* obtain it by writing to the Free Software Foundation, *
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
***************************************************************************
Author: Donald Ziesig
Abstract
TTemplateExpander provides xml templates to replace the hard-coded
pascal snippets used by TCodeCompletionCodeTool.
The xml file fragment for the Setter method:
<templates>
*
*
*
<template name="SetterMethod">
procedure <ClassName>.<AccessParam/>(<PropVarName/>: <PropType/>);<br/>
begin
<indent/>if <VarName/>=<PropVarName/> then Exit;<br/>
<indent/><VarName/>:=<PropVarName/>;<br/>
end;<br/>
</template>
*
*
*
</templates>
produces pascal:
procedure TMyClass.SetMyVar(AValue: MyType);
begin
if AValue=MyVar then Exit;
MyVar:=AValue;
end;
===============================================================================
The following xml tags are implemented:
<if var="SomeBool"> ... </if> generates pascal code if string value of
the argument named "SomeBool" is "true".
<ifnot var="SomeBool" ... </ifnot> generates pascal code if string value of
the argument named "SomeBool" is not "true"
<else> ... </else> must immediately follow </if> or </ifnot>.
generates pascal code if the negation of
the previous tag is true.
<count var="SomeVar"> ... </count> generates pascal code for zero or more
values of the string argument "SomeVar".
The values are encoded as a single string
of the form "Arg0?Arg1?...ArgN?" (Yeah, I
know. See the comments below about a hack.)
<indent/> is replaced by the appropriate Indent string.
<br/> is replaced by the appropriate LineEnd string.
<SomeVar/> is replaced by the string element of ArgVal
which corresponds to the string element of
ArgName.
}
unit CodeCompletionTemplater;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, laz2_DOM, laz2_XMLRead, LazFileUtils, LazUTF8Classes,
CodeCache, FileProcs;
type
{ TTemplateExpander }
TTemplateExpander = class
private
FCode: TCodeBuffer;
fCodeChangeStep: Integer;
procedure LoadCode;
procedure SetCode(AValue: TCodeBuffer);
protected
XMLDoc : TXMLDocument;
Root : TDOMNode;
function ArgCount(Args: String): Integer;
function ArgN(Args: String; Index : Integer) : String;
function ExpandTemplate(Template: TDOMNode;
LineEnd, Indent : String;
ArgName: array of String;
ArgVal: array of const;
CountIndex: Integer = -1): String;
function FindTemplate(TemplateName: String): TDOMNode;
public
constructor Create;
destructor Destroy; override;
function Expand(TemplateName : String;
LineEnd, Indent : String;
ArgName : array of String;
ArgVal : array of const): String;
function TemplateExists(TemplateName: String): Boolean;
property Doc: TXMLDocument read XMLDoc;
property Code: TCodeBuffer read FCode write SetCode;
procedure ReloadCode;
end;
var
Expander : TTemplateExpander; // will be set by CodeToolBoss
implementation
{ TTemplateExpander }
//
// ArgCount and ArgN are part of a hack to overcome the fact that
// "array of const" can not contain another array.
//
// instead of a convenient ['a',...,['x1,'x2'],...,'z'] we must use something
// like ['a',...,'x1?x2?',...'z'] (which is what I chose just for simplicity)
//
function TTemplateExpander.ArgCount(Args: String): Integer;
var
I : Integer;
begin
Result := 0;
for I := 1 to Length(Args) do
if Args[I] = '?' then
Inc(Result);
end;
function TTemplateExpander.ArgN(Args: String; Index: Integer): String;
var
I : Integer;
P : Integer;
S : String;
begin
S := Args;
for I := 0 to pred(Index) do
begin
P := Pos('?',S);
S := Copy(S,P+1,65535);
end;
P := Pos('?',S);
Result := Copy(S,1,P-1);
end;
constructor TTemplateExpander.Create;
begin
fCodeChangeStep:=CTInvalidChangeStamp;
end;
destructor TTemplateExpander.Destroy;
begin
FCode:=nil;
FreeAndNil(XMLDoc);
end;
function TTemplateExpander.Expand(TemplateName: String; LineEnd,
Indent: String; ArgName: array of String; ArgVal: array of const): String;
var
Template : TDOMNode;
begin
Template := FindTemplate(TemplateName);
if Template = nil then
raise Exception.Create('Template "' + TemplateName + '" not found in TemplateExpander.');
Result := ExpandTemplate(Template, #13#10, ' ', ArgName, ArgVal);
end;
function TTemplateExpander.ExpandTemplate(Template: TDOMNode; LineEnd,
Indent: String; ArgName: array of String; ArgVal: array of const;
CountIndex : Integer): String;
// Sequential search of ArgName array to return corresponding element
// of the ArgVal array (appropriately processed if it simulates being
// an array itself.
function GetArgValue(Name : String; Index : Integer = -1): String;
var
I : Integer;
S : String;
begin
for I := 0 to pred(Length(ArgName)) do
if ArgName[I] = Name then
begin
S := AnsiString(ArgVal[I].VAnsiString);
if (Index < 0) or (Pos('?',S) = 0) then
Result := S
else
Result := ArgN(S, Index);
exit;
end;
raise Exception.Create('ExpandTemplate could not find Argument named "' + Name + '"');
end;
function GetBoolArgValue(Name : String; Index : Integer = -1): Boolean;
var
I : Integer;
begin
for I := 0 to pred(Length(ArgName)) do
if ArgName[I] = Name then
begin
Result := ArgVal[I].VBoolean;
exit;
end;
raise Exception.Create('ExpandTemplate could not find Argument named "' + Name + '"');
end;
function GetNodeValue(Node : TDOMNode; Required : Boolean = True): String;
var
Len : Integer;
begin
Result := '';
Len := Node.Attributes.Length;
if Required then
if Len = 0 then
raise Exception.Create('Missing attribute tag for node "' + Node.NodeName + '"');
if Len > 0 then
Result := Node.Attributes.Item[0].NodeValue;
end;
var
Node : TDOMNode;
N : String;
S : String;
Name : String;
R : String; // for debugger
PrevNode : TDOMNode;
CommentFlag : Boolean;
CountArgs : String;
NArgs : Integer;
I : Integer;
begin
R := '';
PrevNode := nil;
Node := Template.FirstChild;
while Node <> nil do
begin
N := Node.NodeName;
S := Node.NodeValue;
CommentFlag := False;
// plain text in the xml file is copied directly to the output (almost).
if N = '#text' then
begin
if Pos(#10, S) = 1 then // Hack to work around XML parser that leaves
S := Copy(S,2,65535); // A new-line when text appears in first
R := R + S; // column of the XML file.
end
// indent the text using the string argument Indent
else if N = 'indent' then
begin
Name := GetNodeValue(Node, False);
if Name = '' then
R := R + Indent
else
R := R + GetArgValue(Name);
end
// add the line break using the string argument LineEnd
else if N = 'br' then
R := R + LineEnd
// process the xml 'if' tag
else if (N = 'if') then
begin
Name := GetNodeValue(Node); //Node.Attributes.Item[0].NodeValue;
if GetBoolArgValue(Name) then
R := R + ExpandTemplate(Node, LineEnd,Indent,ArgName,ArgVal);
end
// process the xml 'ifnot' tag
else if (N = 'ifnot') then
begin
Name := GetNodeValue(Node); //Node.Attributes.Item[0].NodeValue;
if not GetBoolArgValue(Name) then
R := R + ExpandTemplate(Node, LineEnd,Indent,ArgName,ArgVal);
end
// process the xml 'else' tag. This is sneaky. The else tag must (almost)
// immediately follow the closing of either the 'if' or 'ifnot' tags. (The
// exception allows comments to intervene)
//
// The original implementation used separate 'else' and 'elsenot' tags, but
// the xml file got so confusing at times that it was better to add some
// nasty looking code here to make the xml neater.
else if N = 'else' then
begin
if PrevNode = nil then
raise Exception.Create('Expander: "else" without "if" or "ifnot"');
if PrevNode.NodeName = 'if' then
begin
Name := GetNodeValue(PrevNode); //PrevNode.Attributes.Item[0].NodeValue;
if GetBoolArgValue(Name) then
R := R + ExpandTemplate(Node, LineEnd,Indent,ArgName,ArgVal);
end
else if PrevNode.NodeName = 'ifnot' then
begin
Name := GetNodeValue(PrevNode); //PrevNode.Attributes.Item[0].NodeValue;
if not GetBoolArgValue(Name) then
R := R + ExpandTemplate(Node, LineEnd,Indent,ArgName,ArgVal);
end
else
raise Exception.Create('Expander: mis-placed "else" following ' + PrevNode.NodeName);
end
// process the xml 'count' tag. This implements multiple lines to be generated
// from array or list data in the pascal code. This was originally needed to
// implement the 'AssignMethod' template.
else if N = 'count' then
begin
Name := GetNodeValue(Node); //Node.Attributes.Item[0].NodeValue;
CountArgs := GetArgValue(Name);
NArgs := ArgCount(CountArgs);
for I := 0 to pred(Nargs) do
R := R + ExpandTemplate(Node, LineEnd,Indent,ArgName,ArgVal, I);
end
// process all other xml tags (less comment) as requests for the pascal variable
// specified by the tag name: e.g., <ClassName/> will look for an argument name
// of ClassName in the ArgNames array and get the corresponding value from the
// ArgVals array;
else if N <> '#comment' then
R := R + GetArgValue(N, CountIndex)
{$IFDEF DebugTemplate }
else
begin
R := R + '{ ' + Node.NodeValue + ' }';
CommentFlag := True;
end;
{$ELSE DebugTemplate}
else
CommentFlag := True;
{$ENDIF DebugTemplate}
// ignore the comment nodes in subsequent processing.
if not CommentFlag then PrevNode := Node;
Node := Node.NextSibling;
end;
Result := R;
end;
function TTemplateExpander.FindTemplate(TemplateName : String): TDOMNode;
var
N : String;
begin
if not Assigned(Root) then
begin
Result := nil;
exit;
end;
if Root.NodeName <> 'templates' then
raise Exception.Create('Root node of codetools TemplateExpander = "' + Root.NodeName + '", "templates" expected.');
// Sequential search of list of templates.
Result := Root.FirstChild;
while Result <> nil do
begin
N := Result.NodeName;
if N <> '#comment' then // ignores first level comments
begin
if N <> 'template' then
raise Exception.Create('template node of codetools TemplateExpander = "' + N + '", "template" expected.');
if Result.Attributes.Item[0].NodeValue = TemplateName then
break;
end;
Result := Result.NextSibling;
end;
end;
procedure TTemplateExpander.LoadCode;
var
ms: TMemoryStream;
begin
if Code=nil then begin
fCodeChangeStep:=CTInvalidChangeStamp;
exit;
end;
fCodeChangeStep:=Code.ChangeStep;
Root:=nil;
FreeAndNil(XMLDoc);
ms:=TMemoryStream.Create;
try
Code.SaveToStream(ms);
ms.Position:=0;
ReadXMLFile(XMLDoc, ms);
Root := XMLDoc.DocumentElement;
finally
ms.Free;
end;
end;
procedure TTemplateExpander.SetCode(AValue: TCodeBuffer);
begin
if FCode=AValue then Exit;
FCode:=AValue;
LoadCode;
end;
function TTemplateExpander.TemplateExists(TemplateName: String): Boolean;
begin
ReloadCode;
Result := FindTemplate(TemplateName) <> nil;
end;
procedure TTemplateExpander.ReloadCode;
begin
if Code=nil then exit;
if Code.ChangeStep=fCodeChangeStep then exit;
LoadCode;
end;
end.

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<!--
The first of any duplicated templates is the one that will be used.
This allows backups to be saved in this file.
-->
<template name="SetterMethod">
procedure <ClassName/>.<AccessParam/>(<PropVarName/>: <PropType/>);<br/>
begin<br/>
<indent/>if <VarName/>=<PropVarName/> then Exit;<br/>
<indent/><VarName/>:=<PropVarName/>;<br/>
end;
</template>
<template name="AssignMethodDef">
procedure <ProcName/>(<ParamName/>: <ParamType/> );<if var="Override"> override;</if>
</template>
<template name="AssignMethod">
procedure <ClassName/>.<ProcName/>(<ParamName/>: <ParamType/>);<br/>
<ifnot var="SameType">
var<br/>
<indent/><SrcVar/>: <ClassName/>;<br/>
</ifnot>
begin<br/>
<if var="CallInherited0">
<indent/>inherited <ProcName/>(<ParamName/>);<br/>
</if>
<ifnot var="SameType">
<indent/>if <ParamName/> is <ClassName/> then<br/>
<indent/>begin<br/>
<indent/><indent/><SrcVar/> := <ClassName/>(<ParamName/>);<br/>
</ifnot>
<count var="NodeExt">
<indent/><indent/><NodeExt/> := <SrcVar/>.<NodeExt/>;<br/>
</count>
<ifnot var="SameType">
<if var="CallInherited1">
<indent/>end<br/>
<indent/>else<br/>
<indent/><indent/>inherited <ProcName/>(<ParamName/>);<br/>
</if>
<else>
<indent/>end;<br/>
</else>
</ifnot>
end;
</template>
<template name="PrettyColon">: </template>
</templates>

View File

@ -77,6 +77,7 @@ interface
{off $DEFINE VerboseCompleteMethod}
{off $DEFINE VerboseCompleteLocalVarAssign}
{off $DEFINE VerboseCompleteEventAssign}
{$DEFINE UseXMLTemplates}
uses
{$IFDEF MEM_CHECK}
@ -85,7 +86,7 @@ uses
Classes, SysUtils, FileProcs, CodeToolsStrConsts, CodeTree, CodeAtom,
CodeCache, CustomCodeTool, PascalParserTool, MethodJumpTool,
FindDeclarationTool, KeywordFuncLists, CodeToolsStructs, BasicCodeTools,
LinkScanner, SourceChanger, CodeGraph, AVL_Tree;
LinkScanner, SourceChanger, CodeGraph, AVL_Tree, codecompletiontemplater;
type
TNewClassPart = (ncpPrivateProcs, ncpPrivateVars,
@ -137,6 +138,7 @@ type
fNewMainUsesSectionUnits: TAVLTree; // tree of AnsiString
procedure AddNewPropertyAccessMethodsToClassProcs(ClassProcs: TAVLTree;
const TheClassName: string);
procedure SetSetPropertyVariablename(AValue: string);
function UpdateProcBodySignature(ProcBodyNodes: TAVLTree;
const BodyNodeExt: TCodeTreeNodeExtension;
ProcAttrCopyDefToBody: TProcHeadAttributes; var ProcsCopied: boolean;
@ -363,7 +365,7 @@ type
public
// Options
property SetPropertyVariablename: string read FSetPropertyVariablename
write FSetPropertyVariablename;
write SetSetPropertyVariablename;
property CompleteProperties: boolean read FCompleteProperties
write FCompleteProperties;
property AddInheritedCodeToOverrideMethod: boolean
@ -456,6 +458,12 @@ begin
FSourceChangeCache.MainScanner:=Scanner;
end;
procedure TCodeCompletionCodeTool.SetSetPropertyVariablename(aValue: string);
begin
if FSetPropertyVariablename=aValue then Exit;
FSetPropertyVariablename:=aValue;
end;
function TCodeCompletionCodeTool.OnTopLvlIdentifierFound(
Params: TFindDeclarationParams; const FoundContext: TFindContext
): TIdentifierFoundResult;
@ -1067,8 +1075,17 @@ begin
+'invalid target for a var');
end;
InsertTxt:=VariableName+':'+VariableType+';';
{$IFDEF UseXMLTemplates}
if ( Expander <> nil ) and Expander.TemplateExists('PrettyColon') then
begin
InsertTxt:=VariableName+Expander.Expand('PrettyColon','','',[],[])+VariableType+';';
end
else
{$ENDIF}
begin
InsertTxt:=VariableName+':'+VariableType+';';
//DebugLn(['TCodeCompletionCodeTool.AddLocalVariable C InsertTxt="',InsertTxt,'" ParentNode=',ParentNode.DescAsString,' HeaderNode=',HeaderNode.DescAsString,' OtherSectionNode=',OtherSectionNode.DescAsString,' VarSectionNode=',VarSectionNode.DescAsString,' CursorNode=',CursorNode.DescAsString]);
end;
if (VarSectionNode<>nil) then begin
// there is already a var section
@ -2641,6 +2658,9 @@ var
Params: TFindDeclarationParams;
ParamName: String;
// create param list without brackets
{$IFDEF UseXMLTemplates}
Colon : String;
{$ENDIF}
begin
Result:='';
CleanList:='';
@ -2684,8 +2704,20 @@ begin
Result:=Result+';';
CleanList:=CleanList+';';
end;
Result:=Result+ParamName+':'+ParamType;
CleanList:=CleanList+ParamType;
{$IFDEF UseXMLTemplates}
if assigned( Expander ) and Expander.TemplateExists('PrettyColon') then
begin
Colon := Expander.Expand('PrettyColon', '','', // Doesn't use linebreak or indentation
[], [] );
Result:=Result+ParamName+Colon+ParamType;
CleanList:=CleanList+Colon+ParamType;
end
else
{$ENDIF UseXMLTemplates}
begin
Result:=Result+ParamName+':'+ParamType;
CleanList:=CleanList+':'+ParamType;
end;
// next
MoveCursorToCleanPos(ExprEndPos);
ReadNextAtom;
@ -2806,7 +2838,20 @@ const
// prepend 'procedure' keyword
if IsFunction then
ProcCode:='function '+ProcCode+':'+FuncType+';'
begin
{$IFDEF UseXMLTemplates}
if ( Expander <> nil ) and Expander.TemplateExists('PrettyColon') then
begin
ProcCode:= 'function '+ProcCode+
Expander.Expand('PrettyColon','','',[],[])
+FuncType+';';
end
else
{$ENDIF}
begin
ProcCode:='function '+ProcCode+':'+FuncType+';';
end;
end
else
ProcCode:='procedure '+ProcCode+';';
CleanProcHead:=CleanProcHead+';';
@ -2998,6 +3043,15 @@ begin
CodeCompleteSrcChgCache:=SourceChangeCache;
// check if variable already exists
if not VarExistsInCodeCompleteClass(UpperCaseStr(VarName)) then begin
{$IFDEF UseXMLTemplates}
if ( Expander <> nil ) and Expander.TemplateExists('PrettyColon') then
begin
AddClassInsertion(UpperCaseStr(VarName),
VarName+Expander.Expand('PrettyColon','','',[],[])+VarType+';',VarName,ncpPublishedVars);
end
else
{$ENDIF}
AddClassInsertion(UpperCaseStr(VarName),
VarName+':'+VarType+';',VarName,ncpPublishedVars);
if not InsertAllNewClassParts then
@ -5803,6 +5857,9 @@ var
SrcVar: String;
i: Integer;
Beauty: TBeautifyCodeOptions;
{$IFDEF UseXMLTemplates}
NodeExtsStr: String;
{$ENDIF}
begin
Result:=false;
NewPos:=CleanCodeXYPosition;
@ -5812,67 +5869,114 @@ begin
Beauty:=SourceChanger.BeautifyCodeOptions;
aClassName:=ExtractClassName(ClassNode,false);
CleanDef:=ProcName+'('+ParamType+');';
Def:='procedure '+ProcName+'('+ParamName+':'+ParamType+');';
if OverrideMod then Def:=Def+'override;';
{$IFDEF UseXMLTemplates}
if assigned( Expander ) and Expander.TemplateExists('AssignMethodDef') then
begin
Def := Expander.Expand('AssignMethodDef', '','', // Doesn't use linebreak or indentation
['ProcName', 'ParamName', 'ParamType', 'Override' ],
[ ProcName, ParamName, ParamType, OverrideMod ] );
end else
{$ENDIF UseXMLTemplates}
begin
Def:='procedure '+ProcName+'('+ParamName+':'+ParamType+');';
if OverrideMod then Def:=Def+'override;';
end;
SrcVar:=ParamName;
// create the proc header
SameType:=CompareIdentifiers(PChar(aClassName),PChar(ParamType))=0;
e:=SourceChanger.BeautifyCodeOptions.LineEnd;
Indent:=0;
IndentStep:=SourceChanger.BeautifyCodeOptions.Indent;
ProcBody:='procedure '+aClassName+'.'+ProcName+'('+ParamName+':'+ParamType+');'+e;
if not SameType then begin
// add local variable
SrcVar:=LocalVarName;
if SrcVar='' then
SrcVar:='aSource';
if CompareIdentifiers(PChar(SrcVar),PChar(ParamName))=0 then begin
if CompareIdentifiers(PChar(SrcVar),'aSource')=0 then
SrcVar:='aSrc'
else
{$IFDEF UseXMLTemplates}
if assigned(Expander) and Expander.TemplateExists('AssignMethod') then begin
if not SameType then begin
// add local variable
SrcVar:=LocalVarName;
if SrcVar='' then
SrcVar:='aSource';
if CompareIdentifiers(PChar(SrcVar),PChar(ParamName))=0 then begin
if CompareIdentifiers(PChar(SrcVar),'aSource')=0 then
SrcVar:='aSrc'
else
SrcVar:='aSource';
end;
end;
// add assignments
NodeExtsStr := '';
if MemberNodeExts<>nil then begin
for i:=0 to MemberNodeExts.Count-1 do
begin
NodeExt:=TCodeTreeNodeExtension(MemberNodeExts[i]);
NodeExtsStr := NodeExtsStr + NodeExt.Txt + '?';
end;
end;
ProcBody := Expander.Expand( 'AssignMethod',e,GetIndentStr(Indent),
['ClassName', 'ProcName', 'ParamName', 'ParamType',
'SameType', 'SrcVar', 'Inherited0', 'Inherited1',
'NodeExt' ],
[ aClassName, ProcName, ParamName, ParamType,
SameType, SrcVar,
CallInherited and (not CallInheritedOnlyInElse),
CallInherited and CallInheritedOnlyInElse,
NodeExtsStr ] );
end
else
{$ENDIF UseXMLTemplates}
begin
ProcBody:='procedure '+aClassName+'.'+ProcName+'('+ParamName+':'+ParamType+');'+e;
if not SameType then begin
// add local variable
SrcVar:=LocalVarName;
if SrcVar='' then
SrcVar:='aSource';
if CompareIdentifiers(PChar(SrcVar),PChar(ParamName))=0 then begin
if CompareIdentifiers(PChar(SrcVar),'aSource')=0 then
SrcVar:='aSrc'
else
SrcVar:='aSource';
end;
ProcBody:=ProcBody+'var'+e
+Beauty.GetIndentStr(Indent+IndentStep)+SrcVar+':'+aClassName+';'+e;
end;
ProcBody:=ProcBody+'var'+e
+Beauty.GetIndentStr(Indent+IndentStep)+SrcVar+':'+aClassName+';'+e;
end;
ProcBody:=ProcBody+'begin'+e;
inc(Indent,IndentStep);
// call inherited
if CallInherited and (not CallInheritedOnlyInElse) then
ProcBody:=ProcBody
+Beauty.GetIndentStr(Indent)+'inherited '+ProcName+'('+ParamName+');'+e;
if not SameType then begin
// add a parameter check to the new procedure
ProcBody:=ProcBody
+Beauty.GetIndentStr(Indent)+'if '+ParamName+' is '+aClassName+' then'+e
+Beauty.GetIndentStr(Indent)+'begin'+e;
ProcBody:=ProcBody+'begin'+e;
inc(Indent,IndentStep);
ProcBody:=ProcBody+Beauty.GetIndentStr(Indent)+SrcVar+':='+aClassName+'('+ParamName+');'+e;
end;
// add assignments
if MemberNodeExts<>nil then begin
for i:=0 to MemberNodeExts.Count-1 do begin
NodeExt:=TCodeTreeNodeExtension(MemberNodeExts[i]);
// add assignment
ProcBody:=ProcBody+Beauty.GetIndentStr(Indent)+NodeExt.Txt+':='+SrcVar+'.'+NodeExt.Txt+';'+e;
end;
end;
// call inherited
if CallInherited and (not CallInheritedOnlyInElse) then
ProcBody:=ProcBody
+Beauty.GetIndentStr(Indent)+'inherited '+ProcName+'('+ParamName+');'+e;
if not SameType then begin
// close if block
dec(Indent,IndentStep);
if CallInherited and CallInheritedOnlyInElse then begin
ProcBody:=ProcBody+Beauty.GetIndentStr(Indent)+'end else'+e
+Beauty.GetIndentStr(Indent+IndentStep)+'inherited '+ProcName+'('+ParamName+');'+e;
end else begin
ProcBody:=ProcBody+Beauty.GetIndentStr(Indent)+'end;'+e
if not SameType then begin
// add a parameter check to the new procedure
ProcBody:=ProcBody
+Beauty.GetIndentStr(Indent)+'if '+ParamName+' is '+aClassName+' then'+e
+Beauty.GetIndentStr(Indent)+'begin'+e;
inc(Indent,IndentStep);
ProcBody:=ProcBody+Beauty.GetIndentStr(Indent)+SrcVar+':='+aClassName+'('+ParamName+');'+e;
end;
// add assignments
if MemberNodeExts<>nil then begin
for i:=0 to MemberNodeExts.Count-1 do begin
NodeExt:=TCodeTreeNodeExtension(MemberNodeExts[i]);
// add assignment
ProcBody:=ProcBody+Beauty.GetIndentStr(Indent)+NodeExt.Txt+':='+SrcVar+'.'+NodeExt.Txt+';'+e;
end;
end;
if not SameType then begin
// close if block
dec(Indent,IndentStep);
if CallInherited and CallInheritedOnlyInElse then begin
ProcBody:=ProcBody+Beauty.GetIndentStr(Indent)+'end else'+e
+Beauty.GetIndentStr(Indent+IndentStep)+'inherited '+ProcName+'('+ParamName+');'+e;
end else begin
ProcBody:=ProcBody+Beauty.GetIndentStr(Indent)+'end;'+e
end;
end;
// close procedure body
ProcBody:=ProcBody+'end;';
end;
// close procedure body
ProcBody:=ProcBody+'end;';
if not InitClassCompletion(ClassNode,SourceChanger) then exit;
ProcBody:=SourceChanger.BeautifyCodeOptions.BeautifyStatement(ProcBody,0);
@ -6851,19 +6955,33 @@ var
end;
}
ProcBody:=
'procedure '
+ExtractClassName(PropNode.Parent.Parent,false)+'.'+AccessParam
+'('+SetPropertyVariablename+':'+PropType+');'
+BeautifyCodeOpts.LineEnd
+'begin'+BeautifyCodeOpts.LineEnd
+BeautifyCodeOpts.GetIndentStr(BeautifyCodeOpts.Indent)
+'if '+VariableName+'='+SetPropertyVariablename+' then Exit;'
{$IFDEF UseXMLTemplates}
if assigned(Expander) and Expander.TemplateExists('SetterMethod') then
begin
debugln(['CompleteWriteSpecifier ', 'USING template for SetterMethod']);
ProcBody := Expander.Expand( 'SetterMethod',
BeautifyCodeOpts.LineEnd,
GetIndentStr(BeautifyCodeOpts.Indent),
['ClassName', 'AccessParam','PropVarName', 'PropType','VarName'],
[ExtractClassName(PropNode.Parent.Parent,false), AccessParam, SetPropertyVariablename, PropType, VariableName] );
end
else
{$ENDIF}
begin
ProcBody:=
'procedure '
+ExtractClassName(PropNode.Parent.Parent,false)+'.'+AccessParam
+'('+SetPropertyVariablename+':'+PropType+');'
+BeautifyCodeOpts.LineEnd
+BeautifyCodeOpts.GetIndentStr(BeautifyCodeOpts.Indent)
+VariableName+':='+SetPropertyVariablename+';'
+BeautifyCodeOpts.LineEnd
+'end;';
+'begin'+BeautifyCodeOpts.LineEnd
+BeautifyCodeOpts.GetIndentStr(BeautifyCodeOpts.Indent)
+'if '+VariableName+'='+SetPropertyVariablename+' then Exit;'
+BeautifyCodeOpts.LineEnd
+BeautifyCodeOpts.GetIndentStr(BeautifyCodeOpts.Indent)
+VariableName+':='+SetPropertyVariablename+';'
+BeautifyCodeOpts.LineEnd
+'end;';
end;
if IsClassProp then
ProcBody:='class '+ProcBody;
end;
@ -8921,6 +9039,5 @@ begin
FAddInheritedCodeToOverrideMethod:=true;
end;
end.

View File

@ -46,7 +46,7 @@ uses
EventCodeTool, CodeTree, CodeAtom, SourceChanger, DefineTemplates, CodeCache,
ExprEval, LinkScanner, KeywordFuncLists, FindOverloads, CodeBeautifier,
FindDeclarationCache, DirectoryCacher, AVL_Tree,
PPUCodeTools, LFMTrees, DirectivesTree,
PPUCodeTools, LFMTrees, DirectivesTree, codecompletiontemplater,
PascalParserTool, CodeToolsConfig, CustomCodeTool, FindDeclarationTool,
IdentCompletionTool, StdCodeTools, ResourceCodeTool, CodeToolsStructs,
CTUnitGraph, CodeTemplatesTool, ExtractProcTool;
@ -88,6 +88,7 @@ type
FCatchExceptions: boolean;
FChangeStep: integer;
FCheckFilesOnDisk: boolean;
FCodeCompletionTemplateFileName: String;
FCodeNodeTreeChangeStep: integer;
FCompleteProperties: boolean;
FCurCodeTool: TCodeTool; // current codetool
@ -141,8 +142,10 @@ type
procedure SetAbortable(const AValue: boolean);
procedure SetAddInheritedCodeToOverrideMethod(const AValue: boolean);
procedure SetCheckFilesOnDisk(NewValue: boolean);
procedure SetCodeCompletionTemplateFileName(AValue: String);
procedure SetCompleteProperties(const AValue: boolean);
procedure SetIndentSize(NewValue: integer);
procedure SetSetPropertyVariablename(AValue: string);
procedure SetTabWidth(const AValue: integer);
procedure SetUseTabs(AValue: boolean);
procedure SetVisibleEditorLines(NewValue: integer);
@ -279,7 +282,7 @@ type
property IndentSize: integer read FIndentSize write SetIndentSize;
property JumpCentered: boolean read FJumpCentered write SetJumpCentered;
property SetPropertyVariablename: string
read FSetPropertyVariablename write FSetPropertyVariablename;
read FSetPropertyVariablename write SetSetPropertyVariablename;
property VisibleEditorLines: integer
read FVisibleEditorLines write SetVisibleEditorLines;
property TabWidth: integer read FTabWidth write SetTabWidth;
@ -290,6 +293,10 @@ type
read FAddInheritedCodeToOverrideMethod
write SetAddInheritedCodeToOverrideMethod;
// code completion templates
property CodeCompletionTemplateFileName : String read FCodeCompletionTemplateFileName
write SetCodeCompletionTemplateFileName;
// source changing
procedure BeginUpdate;
function EndUpdate: boolean;
@ -5431,6 +5438,29 @@ begin
FCurCodeTool.CheckFilesOnDisk:=NewValue;
end;
procedure TCodeToolManager.SetCodeCompletionTemplateFileName(AValue: String);
var
OldValue: String;
Code: TCodeBuffer;
begin
AValue:=CleanAndExpandFilename(AValue);
if FCodeCompletionTemplateFileName=AValue then Exit;
OldValue:=FCodeCompletionTemplateFileName;
FCodeCompletionTemplateFileName:=AValue;
if CompareFilenames(FCodeCompletionTemplateFileName,OldValue)=0 then exit;
if (FCodeCompletionTemplateFileName<>'') then
Code:=LoadFile(FCodeCompletionTemplateFileName,true,false)
else
Code:=nil;
if Code<>nil then begin
if Expander=nil then
Expander:=TTemplateExpander.Create;
Expander.Code:=Code;
end else begin
FreeAndNil(Expander);
end;
end;
procedure TCodeToolManager.SetCompleteProperties(const AValue: boolean);
begin
if CompleteProperties=AValue then exit;
@ -5479,6 +5509,12 @@ begin
FCurCodeTool.JumpCentered:=NewValue;
end;
procedure TCodeToolManager.SetSetPropertyVariablename(aValue: string);
begin
if FSetPropertyVariablename=aValue then Exit;
FSetPropertyVariablename:=aValue;
end;
procedure TCodeToolManager.SetCursorBeyondEOL(NewValue: boolean);
begin
if NewValue=FCursorBeyondEOL then exit;

View File

@ -1,4 +1,4 @@
<?xml version="1.0"?>
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<Package Version="4">
<Name Value="CodeTools"/>
@ -29,7 +29,7 @@
<License Value="GPL-2
"/>
<Version Major="1" Release="1"/>
<Files Count="60">
<Files Count="61">
<Item1>
<Filename Value="Makefile"/>
<Type Value="Text"/>
@ -269,8 +269,12 @@
</Item59>
<Item60>
<Filename Value="ctunitgroupgraph.pas"/>
<UnitName Value="ctunitgroupgraph"/>
<UnitName Value="CTUnitGroupGraph"/>
</Item60>
<Item61>
<Filename Value="codecompletiontemplater.pas"/>
<UnitName Value="codecompletiontemplater"/>
</Item61>
</Files>
<LazDoc Paths="docs"/>
<i18n>

View File

@ -19,7 +19,7 @@ uses
SourceChanger, SourceLog, StdCodeTools, OtherIdentifierTree,
CodeToolsCfgScript, CTXMLFixFragment, CTUnitGraph, ChangeDeclarationTool,
CodeToolsFPCMsgs, UnitDictionary, ctloadlaz, CTUnitGroupGraph,
LazarusPackageIntf;
CodeCompletionTemplater, LazarusPackageIntf;
implementation

View File

@ -1,12 +1,10 @@
object CodeMacroPromptDlg: TCodeMacroPromptDlg
Caption = 'CodeMacroPromptDlg'
ClientHeight = 300
ClientWidth = 400
PixelsPerInch = 112
HorzScrollBar.Page = 399
VertScrollBar.Page = 299
Left = 290
Height = 300
Top = 163
Width = 400
HorzScrollBar.Page = 399
VertScrollBar.Page = 299
Caption = 'CodeMacroPromptDlg'
LCLVersion = '1.1'
end

View File

@ -32,7 +32,7 @@ interface
uses
Classes, SysUtils, LCLProc, Forms, Controls, Graphics, Dialogs,
BasicCodeTools,
BasicCodeTools, CodeToolManager,
SynEditAutoComplete, SynPluginTemplateEdit, SynPluginSyncronizedEditBase, SynEdit,
MacroIntf, LazIDEIntf, SrcEditorIntf;
@ -114,6 +114,10 @@ implementation
{$R *.lfm}
const
MaxLevel = 10; // prevent cycling
@ -463,12 +467,12 @@ var
Pattern: String;
LineText: String;
Parser: TLazTemplateParser;
CodeToolBossOriginalIndent : Integer; // So I don't break anything else (hopefully)
begin
Result:=false;
//debugln('ExecuteCodeTemplate ',dbgsName(SrcEdit),' ',dbgsName(SrcEdit.EditorControl));
AEditor:=SrcEdit.EditorControl as TSynEdit;
Pattern:=TemplateValue;
Parser := TLazTemplateParser.Create(Pattern);
AEditor.BeginUpdate;
try
@ -498,8 +502,17 @@ begin
Parser.EnableMacros := Attributes.IndexOfName(CodeTemplateEnableMacros)>=0;
Parser.KeepSubIndent := Attributes.IndexOfName(CodeTemplateKeepSubIndent)>=0;
Parser.Indent := BaseIndent;
LazarusIDE.SaveSourceEditorChangesToCodeCache(nil);
if not Parser.SubstituteCodeMacros(SrcEdit) then exit;
CodeToolBossOriginalIndent := CodeToolBoss.IndentSize;
if Parser.KeepSubIndent then
CodeToolBoss.IndentSize := BaseIndent // Use additional indentation
else
CodeToolBoss.IndentSize := 0; // Use current indentation
try
LazarusIDE.SaveSourceEditorChangesToCodeCache(nil);
if not Parser.SubstituteCodeMacros(SrcEdit) then exit;
finally
CodeToolBoss.IndentSize := CodeToolBossOriginalIndent;
end;
s:=AEditor.Lines[p.y-1];
if TokenStartX>length(s) then

View File

@ -1,7 +1,7 @@
object CodeTemplateDialog: TCodeTemplateDialog
Left = 332
Height = 542
Top = 224
Top = 174
Width = 497
ActiveControl = FilenameEdit
BorderIcons = [biSystemMenu]
@ -11,7 +11,7 @@ object CodeTemplateDialog: TCodeTemplateDialog
OnClose = FormClose
OnCreate = FormCreate
Position = poScreenCenter
LCLVersion = '0.9.31'
LCLVersion = '1.1'
object FilenameGroupBox: TGroupBox
Left = 6
Height = 51
@ -20,13 +20,13 @@ object CodeTemplateDialog: TCodeTemplateDialog
Align = alTop
BorderSpacing.Around = 6
Caption = 'FilenameGroupBox'
ClientHeight = 33
ClientHeight = 31
ClientWidth = 481
TabOrder = 0
object FilenameEdit: TEdit
AnchorSideRight.Control = FilenameButton
Left = 9
Height = 21
Height = 26
Top = 4
Width = 435
Anchors = [akTop, akLeft, akRight]
@ -41,7 +41,7 @@ object CodeTemplateDialog: TCodeTemplateDialog
AnchorSideBottom.Side = asrBottom
Left = 449
Height = 23
Top = 2
Top = 7
Width = 26
Anchors = [akRight, akBottom]
BorderSpacing.Right = 6
@ -58,7 +58,7 @@ object CodeTemplateDialog: TCodeTemplateDialog
Align = alTop
BorderSpacing.Around = 6
Caption = 'TemplatesGroupBox'
ClientHeight = 149
ClientHeight = 147
ClientWidth = 481
TabOrder = 1
object TemplateListBox: TListBox
@ -68,7 +68,7 @@ object CodeTemplateDialog: TCodeTemplateDialog
AnchorSideBottom.Control = TemplatesGroupBox
AnchorSideBottom.Side = asrBottom
Left = 6
Height = 137
Height = 135
Top = 6
Width = 315
Anchors = [akTop, akLeft, akRight, akBottom]
@ -78,7 +78,9 @@ object CodeTemplateDialog: TCodeTemplateDialog
BorderSpacing.Bottom = 6
ItemHeight = 0
OnSelectionChange = TemplateListBoxSelectionChange
ScrollWidth = 311
TabOrder = 0
TopIndex = -1
end
object AddButton: TButton
AnchorSideTop.Control = TemplateListBox
@ -132,20 +134,20 @@ object CodeTemplateDialog: TCodeTemplateDialog
AnchorSideRight.Control = Owner
AnchorSideBottom.Control = FilenameGroupBox
Left = 6
Height = 268
Height = 262
Top = 236
Width = 485
Align = alClient
BorderSpacing.Around = 6
Caption = 'EditTemplateGroupBox'
ClientHeight = 250
ClientHeight = 242
ClientWidth = 481
TabOrder = 2
object UseMacrosCheckBox: TCheckBox
Left = 6
Height = 17
Height = 22
Top = 6
Width = 117
Width = 171
BorderSpacing.Bottom = 7
Caption = 'UseMacrosCheckBox'
ParentShowHint = False
@ -158,10 +160,10 @@ object CodeTemplateDialog: TCodeTemplateDialog
AnchorSideTop.Control = UseMacrosCheckBox
AnchorSideTop.Side = asrCenter
AnchorSideRight.Side = asrBottom
Left = 149
Height = 23
Left = 203
Height = 28
Top = 3
Width = 116
Width = 144
AutoSize = True
BorderSpacing.Left = 20
BorderSpacing.Around = 6
@ -177,8 +179,8 @@ object CodeTemplateDialog: TCodeTemplateDialog
AnchorSideBottom.Control = EditTemplateGroupBox
AnchorSideBottom.Side = asrBottom
Left = 6
Height = 146
Top = 98
Height = 137
Top = 99
Width = 469
BorderSpacing.Around = 6
Anchors = [akTop, akLeft, akRight, akBottom]
@ -604,6 +606,12 @@ object CodeTemplateDialog: TCodeTemplateDialog
'TemplateSynEdit'
)
VisibleSpecialChars = [vscSpace, vscTabAtLast]
SelectedColor.BackPriority = 50
SelectedColor.ForePriority = 50
SelectedColor.FramePriority = 50
SelectedColor.BoldPriority = 50
SelectedColor.ItalicPriority = 50
SelectedColor.UnderlinePriority = 50
BracketHighlightStyle = sbhsBoth
BracketMatchColor.Background = clNone
BracketMatchColor.Foreground = clNone
@ -639,6 +647,8 @@ object CodeTemplateDialog: TCodeTemplateDialog
object TSynGutterSeparator
Width = 2
MouseActions = <>
MarkupInfo.Background = clWhite
MarkupInfo.Foreground = clGray
end
object TSynGutterCodeFolding
MouseActions = <
@ -700,8 +710,8 @@ object CodeTemplateDialog: TCodeTemplateDialog
AnchorSideRight.Control = EditTemplateGroupBox
AnchorSideRight.Side = asrBottom
Left = 6
Height = 39
Top = 53
Height = 30
Top = 63
Width = 469
Anchors = [akTop, akLeft, akRight]
AutoFill = True
@ -725,9 +735,9 @@ object CodeTemplateDialog: TCodeTemplateDialog
AnchorSideTop.Control = UseMacrosCheckBox
AnchorSideTop.Side = asrBottom
Left = 6
Height = 17
Top = 30
Width = 139
Height = 22
Top = 35
Width = 202
BorderSpacing.Top = 6
Caption = 'KeepSubIndentCheckBox'
ParentShowHint = False
@ -737,8 +747,8 @@ object CodeTemplateDialog: TCodeTemplateDialog
end
object ButtonPanel: TButtonPanel
Left = 6
Height = 26
Top = 510
Height = 32
Top = 504
Width = 485
OKButton.Name = 'OKButton'
OKButton.DefaultCaption = True

View File

@ -502,6 +502,7 @@ var
CaretXY: TPoint;
p: integer;
i: Integer;
Indent : String;
begin
List:=TStringList.Create;
try
@ -529,9 +530,10 @@ begin
exit;
end;
Indent := StringOfChar(' ',CodeToolBoss.IndentSize);
Value:='';
for i:=0 to List.Count-1 do
Value:=Value+List[i]+': ;'+LineEnding;
Value:=Value+ Indent + List[i]+': ;'+LineEnding;
finally
List.Free;
end;
@ -1230,7 +1232,7 @@ begin
TemplateSynEdit.Lines.BeginUpdate;
TemplateSynEdit.Lines.Clear;
//debugln('TCodeTemplateDialog.ShowCurCodeTemplate A a=',dbgs(a));
// debugln('TCodeTemplateDialog.ShowCurCodeTemplate A a=',dbgs(a));
if a >= 0
then begin
EditTemplateGroupBox.Caption:=dbgstr(SynAutoComplete.Completions[a])

View File

@ -38,10 +38,12 @@ uses
Classes, SysUtils, LazConf, FileUtil, Laz2_XMLCfg, lazutf8classes,
LResources, Forms, Controls, Buttons, LclProc, ExtCtrls,
Dialogs, CodeToolManager, DefineTemplates, SourceChanger, SynEdit,
IDEOptionsIntf, IDEOptionDefs, LazarusIDEStrConsts, IDEProcs;
IDEOptionsIntf, MacroIntf, IDEOptionDefs, LazarusIDEStrConsts, IDEProcs;
const
DefaultIndentationFilename = 'laz_indentation.pas'; // in directory GetPrimaryConfigPath
DefaultCodeCompletionFilename =
'$(LazarusDir)'+PathDelim+'components'+PathDelim+'codetools'+PathDelim+'codecompletiontemplates.xml';
type
@ -106,7 +108,12 @@ type
fIndentationFilename: String;
FIndentContextSensitive: boolean;
// code completion templates
FCodeCompletionTemplateFileName : String;
procedure SetCodeCompletionTemplateFileName(aValue: String);
procedure SetFilename(const AValue: string);
procedure SetSetPropertyVariablename(aValue: string);
public
class function GetGroupCaption:string; override;
class function GetInstance: TAbstractIDEOptions; override;
@ -194,7 +201,7 @@ type
property PrivateVariablePrefix: string
read FPrivateVariablePrefix write FPrivateVariablePrefix;
property SetPropertyVariablename: string
read FSetPropertyVariablename write FSetPropertyVariablename;
read FSetPropertyVariablename write SetSetPropertyVariablename;
property UsesInsertPolicy: TUsesInsertPolicy
read FUsesInsertPolicy write FUsesInsertPolicy;
@ -221,6 +228,10 @@ type
read fIndentationFileName write fIndentationFileName;
property IndentContextSensitive: boolean read FIndentContextSensitive
write FIndentContextSensitive;
// code completion templates
property CodeCompletionTemplateFileName : String read FCodeCompletionTemplateFileName
write SetCodeCompletionTemplateFileName;
end;
var
@ -482,6 +493,11 @@ begin
FIndentContextSensitive :=
XMLConfig.GetValue('CodeToolsOptions/Indentation/ContextSensitive',true);
// code completion templates
FCodeCompletionTemplateFileName :=
XMLConfig.GetValue('CodeToolsOptions/CodeCompletionTemplate/FileName'
, DefaultCodeCompletionFilename);
XMLConfig.Free;
except
on E: Exception do begin
@ -619,6 +635,10 @@ begin
XMLConfig.SetDeleteValue('CodeToolsOptions/Indentation/ContextSensitive'
, FIndentContextSensitive, true);
// code completion templates
XMLConfig.SetDeleteValue('CodeToolsOptions/CodeCompletionTemplate/FileName'
, FCodeCompletionTemplateFileName, DefaultCodeCompletionFilename);
XMLConfig.Flush;
XMLConfig.Free;
except
@ -628,6 +648,13 @@ begin
end;
end;
procedure TCodeToolsOptions.SetCodeCompletionTemplateFileName(aValue: String);
begin
aValue:=TrimFilename(aValue);
if FCodeCompletionTemplateFileName=aValue then Exit;
FCodeCompletionTemplateFileName:=aValue;
end;
procedure TCodeToolsOptions.SetFilename(const AValue: string);
begin
FFilename:=AValue;
@ -641,11 +668,18 @@ begin
GetPrimaryConfigPath+'/'+DefaultCodeToolsOptsFile);
CopySecondaryConfigFile(DefaultCodeToolsOptsFile);
if (not FileExistsCached(ConfFileName)) then begin
debugln('Looking for code tools config file: "' + ConfFileName + '"');
debugln(UTF8ToConsole(lisCompilerNOTECodetoolsConfigFileNotFoundUsingDefaults));
end;
FFilename:=ConfFilename;
end;
procedure TCodeToolsOptions.SetSetPropertyVariablename(aValue: string);
begin
if FSetPropertyVariablename=aValue then Exit;
FSetPropertyVariablename:=aValue;
end;
procedure TCodeToolsOptions.Assign(Source: TPersistent);
var
CodeToolsOpts: TCodeToolsOptions absolute Source;
@ -770,6 +804,9 @@ begin
fIndentationFilename:=
TrimFilename(GetPrimaryConfigPath+PathDelim+DefaultIndentationFilename);
FIndentContextSensitive:=true;
// code completion templates
fCodeCompletionTemplateFileName := DefaultCodeCompletionFilename;
end;
procedure TCodeToolsOptions.ClearGlobalDefineTemplates;
@ -882,6 +919,7 @@ procedure TCodeToolsOptions.AssignTo(Dest: TPersistent);
var
Boss: TCodeToolManager absolute Dest;
Beauty: TBeautifyCodeOptions absolute Dest;
aFilename: String;
begin
if Dest is TCodeToolManager then
begin
@ -895,6 +933,13 @@ begin
// CreateCode - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AssignTo(Boss.SourceChangeCache.BeautifyCodeOptions);
Boss.SetPropertyVariablename:=SetPropertyVariablename;
//
aFilename:=CodeCompletionTemplateFileName;
IDEMacros.SubstituteMacros(aFilename);
aFilename:=TrimFilename(aFilename);
if (aFilename<>'') and not FilenameIsAbsolute(aFilename) then
aFilename:=TrimFilename(AppendPathDelim(GetPrimaryConfigPath)+aFilename);
Boss.CodeCompletionTemplateFileName:=aFilename;
end
else
if Dest is TBeautifyCodeOptions then

View File

@ -1,10 +1,10 @@
object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFrame
Left = 0
Height = 455
Height = 431
Top = 0
Width = 572
ClientHeight = 455
ClientWidth = 572
Width = 575
ClientHeight = 431
ClientWidth = 575
TabOrder = 0
Visible = False
DesignLeft = 336
@ -41,7 +41,7 @@ object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFra
Left = 256
Height = 100
Top = 0
Width = 316
Width = 319
Anchors = [akTop, akLeft, akRight]
AutoFill = True
AutoSize = True
@ -63,9 +63,9 @@ object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFra
AnchorSideTop.Control = ClassPartInsertPolicyRadioGroup
AnchorSideTop.Side = asrBottom
Left = 6
Height = 18
Height = 24
Top = 106
Width = 249
Width = 227
BorderSpacing.Around = 6
Caption = 'MixMethodsAndPropertiesCheckBox'
TabOrder = 2
@ -75,9 +75,9 @@ object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFra
AnchorSideTop.Control = UpdateAllMethodSignaturesCheckBox
AnchorSideTop.Side = asrBottom
Left = 6
Height = 18
Top = 154
Width = 228
Height = 24
Top = 166
Width = 204
BorderSpacing.Around = 6
Caption = 'ClassHeaderCommentsCheckBox'
TabOrder = 3
@ -90,23 +90,23 @@ object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFra
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Side = asrBottom
Left = 0
Height = 168
Top = 202
Width = 572
Height = 184
Top = 226
Width = 575
Anchors = [akTop, akLeft, akRight]
AutoSize = True
BorderSpacing.Top = 6
Caption = 'PropertyCompletionGroupBox'
ClientHeight = 146
ClientWidth = 564
ClientHeight = 167
ClientWidth = 571
TabOrder = 4
object PropertyCompletionCheckBox: TCheckBox
AnchorSideLeft.Control = PropertyCompletionGroupBox
AnchorSideTop.Control = PropertyCompletionGroupBox
Left = 6
Height = 18
Height = 24
Top = 6
Width = 208
Width = 192
BorderSpacing.Around = 6
Caption = 'PropertyCompletionCheckBox'
TabOrder = 0
@ -118,24 +118,24 @@ object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFra
AnchorSideRight.Control = PropertyCompletionGroupBox
AnchorSideRight.Side = asrBottom
Left = 6
Height = 110
Top = 30
Width = 552
Height = 125
Top = 36
Width = 559
Anchors = [akTop, akLeft, akRight]
AutoSize = True
BorderSpacing.Around = 6
BevelOuter = bvNone
ChildSizing.Layout = cclTopToBottomThenLeftToRight
ChildSizing.ControlsPerLine = 5
ClientHeight = 110
ClientWidth = 552
ClientHeight = 125
ClientWidth = 559
TabOrder = 1
object SetPropertyVariablenameLabel: TLabel
AnchorSideTop.Side = asrCenter
Left = 11
Height = 16
Top = 3
Width = 191
Height = 15
Top = 5
Width = 171
BorderSpacing.Right = 6
BorderSpacing.CellAlignHorizontal = ccaRightBottom
BorderSpacing.CellAlignVertical = ccaCenter
@ -144,10 +144,10 @@ object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFra
end
object PrivateVariablePrefixLabel: TLabel
AnchorSideTop.Side = asrCenter
Left = 39
Height = 16
Top = 25
Width = 163
Left = 36
Height = 15
Top = 30
Width = 146
BorderSpacing.Right = 6
BorderSpacing.CellAlignHorizontal = ccaRightBottom
BorderSpacing.CellAlignVertical = ccaCenter
@ -157,9 +157,9 @@ object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFra
object PropertyStoredIdentPostfixLabel: TLabel
AnchorSideTop.Side = asrCenter
Left = 0
Height = 16
Top = 47
Width = 202
Height = 15
Top = 55
Width = 182
BorderSpacing.Right = 6
BorderSpacing.CellAlignHorizontal = ccaRightBottom
BorderSpacing.CellAlignVertical = ccaCenter
@ -168,10 +168,10 @@ object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFra
end
object PropertyWriteIdentPrefixLabel: TLabel
AnchorSideTop.Side = asrCenter
Left = 15
Height = 16
Top = 69
Width = 187
Left = 11
Height = 15
Top = 80
Width = 171
BorderSpacing.Right = 6
BorderSpacing.CellAlignHorizontal = ccaRightBottom
BorderSpacing.CellAlignVertical = ccaCenter
@ -180,10 +180,10 @@ object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFra
end
object PropertyReadIdentPrefixLabel: TLabel
AnchorSideTop.Side = asrCenter
Left = 17
Height = 16
Top = 91
Width = 185
Left = 14
Height = 15
Top = 105
Width = 168
BorderSpacing.Right = 6
BorderSpacing.CellAlignHorizontal = ccaRightBottom
BorderSpacing.CellAlignVertical = ccaCenter
@ -193,8 +193,8 @@ object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFra
object SetPropertyVariablenameEdit: TEdit
AnchorSideTop.Side = asrBottom
AnchorSideRight.Side = asrBottom
Left = 208
Height = 22
Left = 188
Height = 25
Top = 0
Width = 80
TabOrder = 0
@ -203,9 +203,9 @@ object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFra
object PrivateVariablePrefixEdit: TEdit
AnchorSideTop.Side = asrBottom
AnchorSideRight.Side = asrBottom
Left = 208
Height = 22
Top = 22
Left = 188
Height = 25
Top = 25
Width = 80
TabOrder = 1
Text = 'PrivateVariablePrefixEdit'
@ -213,9 +213,9 @@ object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFra
object PropertyStoredIdentPostfixEdit: TEdit
AnchorSideTop.Side = asrBottom
AnchorSideRight.Side = asrBottom
Left = 208
Height = 22
Top = 44
Left = 188
Height = 25
Top = 50
Width = 80
TabOrder = 2
Text = 'PropertyStoredIdentPostfixEdit'
@ -223,9 +223,9 @@ object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFra
object PropertyWriteIdentPrefixEdit: TEdit
AnchorSideTop.Side = asrBottom
AnchorSideRight.Side = asrBottom
Left = 208
Height = 22
Top = 66
Left = 188
Height = 25
Top = 75
Width = 80
TabOrder = 3
Text = 'PropertyWriteIdentPrefixEdit'
@ -233,9 +233,9 @@ object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFra
object PropertyReadIdentPrefixEdit: TEdit
AnchorSideTop.Side = asrBottom
AnchorSideRight.Side = asrBottom
Left = 208
Height = 22
Top = 88
Left = 188
Height = 25
Top = 100
Width = 80
TabOrder = 4
Text = 'PropertyReadIdentPrefixEdit'
@ -247,9 +247,9 @@ object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFra
AnchorSideTop.Control = ClassHeaderCommentsCheckBox
AnchorSideTop.Side = asrBottom
Left = 6
Height = 18
Top = 178
Width = 283
Height = 24
Top = 196
Width = 251
BorderSpacing.Around = 6
Caption = 'ClassImplementationCommentsCheckBox'
TabOrder = 5
@ -259,9 +259,9 @@ object CodetoolsClassCompletionOptionsFrame: TCodetoolsClassCompletionOptionsFra
AnchorSideTop.Control = MixMethodsAndPropertiesCheckBox
AnchorSideTop.Side = asrBottom
Left = 6
Height = 18
Top = 130
Width = 257
Height = 24
Top = 136
Width = 235
BorderSpacing.Around = 6
Caption = 'UpdateAllMethodSignaturesCheckBox'
TabOrder = 6

View File

@ -25,7 +25,7 @@ unit codetools_classcompletion_options;
interface
uses
Classes, SysUtils, FileUtil, Forms, ExtCtrls, StdCtrls,
Classes, SysUtils, FileUtil, Forms, ExtCtrls, StdCtrls, Buttons, Dialogs,
SourceChanger, CodeToolsOptions, LazarusIDEStrConsts, IDEOptionsIntf;
type
@ -53,7 +53,6 @@ type
SetPropertyVariablenameLabel: TLabel;
UpdateAllMethodSignaturesCheckBox: TCheckBox;
private
{ private declarations }
public
function GetTitle: String; override;
procedure Setup(ADialog: TAbstractOptionsEditorDialog); override;

View File

@ -39,7 +39,7 @@ object CodetoolsCodeCreationOptionsFrame: TCodetoolsCodeCreationOptionsFrame
Left = 6
Height = 24
Top = 112
Width = 261
Width = 217
BorderSpacing.Around = 6
Caption = 'ForwardProcsKeepOrderCheckBox'
TabOrder = 1
@ -78,7 +78,7 @@ object CodetoolsCodeCreationOptionsFrame: TCodetoolsCodeCreationOptionsFrame
Left = 6
Height = 24
Top = 254
Width = 279
Width = 231
BorderSpacing.Left = 6
BorderSpacing.Top = 6
Caption = 'UpdateMultiProcSignaturesCheckBox'
@ -91,9 +91,51 @@ object CodetoolsCodeCreationOptionsFrame: TCodetoolsCodeCreationOptionsFrame
Left = 6
Height = 24
Top = 278
Width = 315
Width = 261
BorderSpacing.Left = 6
Caption = 'UpdateOtherProcSignaturesCaseCheckBox'
TabOrder = 4
end
object TemplateFileLabel: TLabel
AnchorSideLeft.Control = UpdateOtherProcSignaturesCaseCheckBox
AnchorSideTop.Control = TemplateFileEdit
AnchorSideTop.Side = asrCenter
Left = 6
Height = 15
Top = 307
Width = 100
Caption = 'TemplateFileLabel'
ParentColor = False
end
object TemplateFileEdit: TEdit
AnchorSideLeft.Control = TemplateFileLabel
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = UpdateOtherProcSignaturesCaseCheckBox
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = TemplateFileBrowseButton
Left = 106
Height = 25
Top = 302
Width = 439
Anchors = [akTop, akLeft, akRight]
TabOrder = 5
Text = 'TemplateFileEdit'
end
object TemplateFileBrowseButton: TButton
AnchorSideTop.Control = TemplateFileEdit
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = TemplateFileEdit
AnchorSideBottom.Side = asrBottom
Left = 545
Height = 25
Top = 302
Width = 21
Anchors = [akTop, akRight, akBottom]
AutoSize = True
BorderSpacing.Right = 6
Caption = '...'
OnClick = TemplateFileBrowseButtonClick
TabOrder = 6
end
end

View File

@ -25,8 +25,9 @@ unit codetools_codecreation_options;
interface
uses
Classes, SysUtils, FileUtil, Forms, ExtCtrls, StdCtrls,
SourceChanger, CodeToolsOptions, LazarusIDEStrConsts, IDEOptionsIntf;
Classes, SysUtils, FileUtil, Forms, ExtCtrls, StdCtrls, Dialogs,
SourceChanger, CodeToolsOptions, LazarusIDEStrConsts, IDEOptionsIntf,
IDEDialogs;
type
@ -35,9 +36,13 @@ type
TCodetoolsCodeCreationOptionsFrame = class(TAbstractIDEOptionsEditor)
ForwardProcsInsertPolicyRadioGroup: TRadioGroup;
ForwardProcsKeepOrderCheckBox: TCheckBox;
TemplateFileBrowseButton: TButton;
TemplateFileEdit: TEdit;
TemplateFileLabel: TLabel;
UpdateMultiProcSignaturesCheckBox: TCheckBox;
UpdateOtherProcSignaturesCaseCheckBox: TCheckBox;
UsesInsertPolicyRadioGroup: TRadioGroup;
procedure TemplateFileBrowseButtonClick(Sender: TObject);
private
public
function GetTitle: String; override;
@ -53,6 +58,26 @@ implementation
{ TCodetoolsCodeCreationOptionsFrame }
procedure TCodetoolsCodeCreationOptionsFrame.TemplateFileBrowseButtonClick(
Sender: TObject);
var
OpenDialog: TOpenDialog;
begin
OpenDialog:=TOpenDialog.Create(nil);
try
InitIDEFileDialog(OpenDialog);
OpenDialog.Title:=lisChooseAFileWithCodeToolsTemplates;
OpenDialog.Options:=OpenDialog.Options+[ofFileMustExist];
OpenDialog.Filter:=lisCodetoolsTemplateFile+' (*.xml)|*.xml|'+dlgAllFiles+
'|'+GetAllFilesMask;
if OpenDialog.Execute then
TemplateFileEdit.Text:=OpenDialog.FileName;
finally
StoreIDEFileDialog(OpenDialog);
OpenDialog.Free;
end;
end;
function TCodetoolsCodeCreationOptionsFrame.GetTitle: String;
begin
Result := dlgCodeCreation;
@ -73,10 +98,6 @@ begin
end;
ForwardProcsKeepOrderCheckBox.Caption:=dlgForwardProcsKeepOrder;
UpdateMultiProcSignaturesCheckBox.Caption:=
lisCTOUpdateMultipleProcedureSignatures;
UpdateOtherProcSignaturesCaseCheckBox.Caption:=
lisUpdateOtherProcedureSignaturesWhenOnlyLetterCaseHa;
with UsesInsertPolicyRadioGroup do begin
Caption:=lisNewUnitsAreAddedToUsesSections;
@ -90,6 +111,13 @@ begin
EndUpdate;
end;
end;
UpdateMultiProcSignaturesCheckBox.Caption:=
lisCTOUpdateMultipleProcedureSignatures;
UpdateOtherProcSignaturesCaseCheckBox.Caption:=
lisUpdateOtherProcedureSignaturesWhenOnlyLetterCaseHa;
TemplateFileLabel.Caption:=lisTemplateFile;
end;
procedure TCodetoolsCodeCreationOptionsFrame.ReadSettings(
@ -106,8 +134,6 @@ begin
end;
ForwardProcsKeepOrderCheckBox.Checked := KeepForwardProcOrder;
UpdateMultiProcSignaturesCheckBox.Checked:=UpdateMultiProcSignatures;
UpdateOtherProcSignaturesCaseCheckBox.Checked:=UpdateOtherProcSignaturesCase;
case UsesInsertPolicy of
uipFirst: UsesInsertPolicyRadioGroup.ItemIndex:=0;
@ -118,6 +144,11 @@ begin
//uipAlphabetically:
UsesInsertPolicyRadioGroup.ItemIndex:=4;
end;
UpdateMultiProcSignaturesCheckBox.Checked:=UpdateMultiProcSignatures;
UpdateOtherProcSignaturesCaseCheckBox.Checked:=UpdateOtherProcSignaturesCase;
TemplateFileEdit.Text:=CodeCompletionTemplateFileName;
end;
end;
@ -133,8 +164,6 @@ begin
end;
KeepForwardProcOrder := ForwardProcsKeepOrderCheckBox.Checked;
UpdateMultiProcSignatures:=UpdateMultiProcSignaturesCheckBox.Checked;
UpdateOtherProcSignaturesCase:=UpdateOtherProcSignaturesCaseCheckBox.Checked;
case UsesInsertPolicyRadioGroup.ItemIndex of
0: UsesInsertPolicy:=uipFirst;
@ -143,6 +172,11 @@ begin
3: UsesInsertPolicy:=uipLast;
else UsesInsertPolicy:=uipAlphabetically;
end;
UpdateMultiProcSignatures:=UpdateMultiProcSignaturesCheckBox.Checked;
UpdateOtherProcSignaturesCase:=UpdateOtherProcSignaturesCaseCheckBox.Checked;
CodeCompletionTemplateFileName:=TemplateFileEdit.Text;
end;
end;

View File

@ -1346,6 +1346,7 @@ resourcestring
dlgDelTemplate = 'Delete template ';
dlgChsCodeTempl = 'Choose code template file (*.dci)';
dlgAllFiles = 'All files';
lisCodetoolsTemplateFile = 'Codetools template file';
lisExecutable = 'Executable';
lisEditorFileTypes = 'Editor file types';
lisPkgMgrNew = 'new';
@ -1994,6 +1995,8 @@ resourcestring
dlgCOCfgCmpMessages = 'Messages';
lisChooseAnFPCMessageFile = 'Choose an FPC message file';
lisFPCMessageFile = 'FPC message file';
lisChooseAFileWithCodeToolsTemplates = 'Choose a file with CodeTools '
+'templates';
dlgCOOther = 'Other';
dlgCOInherited = 'Inherited';
dlgCOCompilerCommands = 'Compiler Commands';
@ -5796,6 +5799,7 @@ resourcestring
+'signatures';
lisUpdateOtherProcedureSignaturesWhenOnlyLetterCaseHa = 'Update other '
+'procedure signatures when only letter case has changed';
lisTemplateFile = 'Template file';
implementation

View File

@ -1,4 +1,4 @@
inherited SourceNotebook: TSourceNotebook
object SourceNotebook: TSourceNotebook
Left = 533
Height = 300
Top = 374
@ -8,10 +8,11 @@ inherited SourceNotebook: TSourceNotebook
ClientHeight = 300
ClientWidth = 400
OnMouseUp = FormMouseUp
object StatusBar: TStatusBar[0]
LCLVersion = '1.1'
object StatusBar: TStatusBar
Left = 0
Height = 23
Top = 277
Height = 21
Top = 279
Width = 400
Panels = <
item