mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-12 14:00:38 +02:00
codetools: added InsertStatements
git-svn-id: trunk@47837 -
This commit is contained in:
parent
7110836ddc
commit
f4c1725bcd
@ -86,7 +86,7 @@ uses
|
|||||||
CodeCache, CustomCodeTool, PascalParserTool, MethodJumpTool,
|
CodeCache, CustomCodeTool, PascalParserTool, MethodJumpTool,
|
||||||
FindDeclarationTool, KeywordFuncLists, CodeToolsStructs, BasicCodeTools,
|
FindDeclarationTool, KeywordFuncLists, CodeToolsStructs, BasicCodeTools,
|
||||||
LinkScanner, SourceChanger, CodeGraph, AVL_Tree, contnrs,
|
LinkScanner, SourceChanger, CodeGraph, AVL_Tree, contnrs,
|
||||||
CodeCompletionTemplater;
|
CodeCompletionTemplater, StdCodeTools;
|
||||||
|
|
||||||
type
|
type
|
||||||
TNewClassPart = (ncpPrivateProcs, ncpPrivateVars,
|
TNewClassPart = (ncpPrivateProcs, ncpPrivateVars,
|
||||||
@ -117,14 +117,6 @@ const
|
|||||||
);
|
);
|
||||||
|
|
||||||
type
|
type
|
||||||
TInsertStatementPosDescription = class
|
|
||||||
public
|
|
||||||
InsertPos: integer;
|
|
||||||
CodeXYPos: TCodeXYPosition;
|
|
||||||
FrontGap, AfterGap: TGapTyp;
|
|
||||||
Description: string;
|
|
||||||
end;
|
|
||||||
|
|
||||||
TCodeCompletionCodeTool = class;
|
TCodeCompletionCodeTool = class;
|
||||||
|
|
||||||
{ TCodeCompletionCodeTool }
|
{ TCodeCompletionCodeTool }
|
||||||
@ -6134,6 +6126,11 @@ begin
|
|||||||
InsertPosDesc:=TInsertStatementPosDescription.Create;
|
InsertPosDesc:=TInsertStatementPosDescription.Create;
|
||||||
InsertPosDesc.InsertPos:=BeginNode.StartPos+length('begin');
|
InsertPosDesc.InsertPos:=BeginNode.StartPos+length('begin');
|
||||||
CleanPosToCaret(InsertPosDesc.InsertPos,InsertPosDesc.CodeXYPos);
|
CleanPosToCaret(InsertPosDesc.InsertPos,InsertPosDesc.CodeXYPos);
|
||||||
|
InsertPosDesc.Indent:=GetLineIndent(Src,BeginNode.StartPos);
|
||||||
|
if SourceChangeCache<>nil then
|
||||||
|
inc(InsertPosDesc.Indent,SourceChangeCache.BeautifyCodeOptions.Indent)
|
||||||
|
else
|
||||||
|
inc(InsertPosDesc.Indent,2);
|
||||||
InsertPosDesc.FrontGap:=gtNewLine;
|
InsertPosDesc.FrontGap:=gtNewLine;
|
||||||
InsertPosDesc.AfterGap:=gtNewLine;
|
InsertPosDesc.AfterGap:=gtNewLine;
|
||||||
InsertPosDesc.Description:='After BEGIN keyword';
|
InsertPosDesc.Description:='After BEGIN keyword';
|
||||||
|
@ -528,18 +528,14 @@ type
|
|||||||
SectionCode: TCodeBuffer; SectionX, SectionY: integer;
|
SectionCode: TCodeBuffer; SectionX, SectionY: integer;
|
||||||
const NewIdentifier, NewValue: string;
|
const NewIdentifier, NewValue: string;
|
||||||
InsertPolicy: TResourcestringInsertPolicy): boolean;
|
InsertPolicy: TResourcestringInsertPolicy): boolean;
|
||||||
procedure ImproveStringConstantStart(const ACode: string;
|
|
||||||
var StartPos: integer);
|
|
||||||
procedure ImproveStringConstantEnd(const ACode: string;
|
|
||||||
var EndPos: integer);
|
|
||||||
|
|
||||||
// expressions
|
// expressions
|
||||||
function GetStringConstBounds(Code: TCodeBuffer; X,Y: integer;
|
function GetStringConstBounds(Code: TCodeBuffer; X,Y: integer;
|
||||||
var StartCode: TCodeBuffer; var StartX, StartY: integer;
|
var StartCode: TCodeBuffer; var StartX, StartY: integer;
|
||||||
var EndCode: TCodeBuffer; var EndX, EndY: integer;
|
var EndCode: TCodeBuffer; var EndX, EndY: integer;
|
||||||
ResolveComments: boolean): boolean;
|
ResolveComments: boolean): boolean;
|
||||||
function ReplaceCode(Code: TCodeBuffer; StartX, StartY: integer;
|
procedure ImproveStringConstantStart(const ACode: string; var StartPos: integer);
|
||||||
EndX, EndY: integer; const NewCode: string): boolean;
|
procedure ImproveStringConstantEnd(const ACode: string; var EndPos: integer);
|
||||||
function ExtractOperand(Code: TCodeBuffer; X,Y: integer;
|
function ExtractOperand(Code: TCodeBuffer; X,Y: integer;
|
||||||
out Operand: string; WithPostTokens, WithAsOperator,
|
out Operand: string; WithPostTokens, WithAsOperator,
|
||||||
WithoutTrailingPoints: boolean): boolean;
|
WithoutTrailingPoints: boolean): boolean;
|
||||||
@ -574,6 +570,8 @@ type
|
|||||||
): boolean;
|
): boolean;
|
||||||
function DeclareVariableAt(Code: TCodeBuffer; X,Y: integer;
|
function DeclareVariableAt(Code: TCodeBuffer; X,Y: integer;
|
||||||
const VariableName, NewType, NewUnitName: string): boolean;
|
const VariableName, NewType, NewUnitName: string): boolean;
|
||||||
|
|
||||||
|
// simplifications
|
||||||
function FindRedefinitions(Code: TCodeBuffer;
|
function FindRedefinitions(Code: TCodeBuffer;
|
||||||
out TreeOfCodeTreeNodeExt: TAVLTree; WithEnums: boolean): boolean;
|
out TreeOfCodeTreeNodeExt: TAVLTree; WithEnums: boolean): boolean;
|
||||||
function RemoveRedefinitions(Code: TCodeBuffer;
|
function RemoveRedefinitions(Code: TCodeBuffer;
|
||||||
@ -607,12 +605,17 @@ type
|
|||||||
out AllRemoved: boolean;
|
out AllRemoved: boolean;
|
||||||
const Attr: TProcHeadAttributes;
|
const Attr: TProcHeadAttributes;
|
||||||
out RemovedProcHeads: TStrings): boolean;
|
out RemovedProcHeads: TStrings): boolean;
|
||||||
function FindUnusedUnits(Code: TCodeBuffer; Units: TStrings): boolean;
|
|
||||||
|
|
||||||
// custom class completion
|
// custom class completion
|
||||||
function InitClassCompletion(Code: TCodeBuffer;
|
function InitClassCompletion(Code: TCodeBuffer;
|
||||||
const AClassName: string; out CodeTool: TCodeTool): boolean;
|
const AClassName: string; out CodeTool: TCodeTool): boolean;
|
||||||
|
|
||||||
|
// insert/replace
|
||||||
|
function ReplaceCode(Code: TCodeBuffer; StartX, StartY: integer;
|
||||||
|
EndX, EndY: integer; const NewCode: string): boolean;
|
||||||
|
function InsertStatements(InsertPos: TInsertStatementPosDescription;
|
||||||
|
const Statements: string): boolean;
|
||||||
|
|
||||||
// extract proc (creates a new procedure from code in selection)
|
// extract proc (creates a new procedure from code in selection)
|
||||||
function CheckExtractProc(Code: TCodeBuffer;
|
function CheckExtractProc(Code: TCodeBuffer;
|
||||||
const StartPoint, EndPoint: TPoint;
|
const StartPoint, EndPoint: TPoint;
|
||||||
@ -689,6 +692,7 @@ type
|
|||||||
function FindUnitSource(Code: TCodeBuffer;
|
function FindUnitSource(Code: TCodeBuffer;
|
||||||
const AnUnitName, AnUnitInFilename: string): TCodeBuffer;
|
const AnUnitName, AnUnitInFilename: string): TCodeBuffer;
|
||||||
function CreateUsesGraph: TUsesGraph;
|
function CreateUsesGraph: TUsesGraph;
|
||||||
|
function FindUnusedUnits(Code: TCodeBuffer; Units: TStrings): boolean;
|
||||||
|
|
||||||
// resources
|
// resources
|
||||||
property OnFindDefinePropertyForContext: TOnFindDefinePropertyForContext
|
property OnFindDefinePropertyForContext: TOnFindDefinePropertyForContext
|
||||||
@ -3026,6 +3030,21 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCodeToolManager.InsertStatements(
|
||||||
|
InsertPos: TInsertStatementPosDescription; const Statements: string): boolean;
|
||||||
|
begin
|
||||||
|
Result:=false;
|
||||||
|
{$IFDEF CTDEBUG}
|
||||||
|
DebugLn('TCodeToolManager.InsertStatements A ',Code.Filename,' Line=',Y,',Col=',X);
|
||||||
|
{$ENDIF}
|
||||||
|
if not InitCurCodeTool(InsertPos.CodeXYPos.Code) then exit;
|
||||||
|
try
|
||||||
|
Result:=FCurCodeTool.InsertStatements(InsertPos,Statements,SourceChangeCache);
|
||||||
|
except
|
||||||
|
on e: Exception do HandleException(e);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TCodeToolManager.ExtractOperand(Code: TCodeBuffer; X, Y: integer; out
|
function TCodeToolManager.ExtractOperand(Code: TCodeBuffer; X, Y: integer; out
|
||||||
Operand: string; WithPostTokens, WithAsOperator,
|
Operand: string; WithPostTokens, WithAsOperator,
|
||||||
WithoutTrailingPoints: boolean): boolean;
|
WithoutTrailingPoints: boolean): boolean;
|
||||||
|
@ -200,9 +200,6 @@ type
|
|||||||
procedure BeginParsingAndGetCleanPos(
|
procedure BeginParsingAndGetCleanPos(
|
||||||
Range: TLinkScannerRange; CursorPos: TCodeXYPosition;
|
Range: TLinkScannerRange; CursorPos: TCodeXYPosition;
|
||||||
out CleanCursorPos: integer);
|
out CleanCursorPos: integer);
|
||||||
procedure BeginParsingAndGetCleanPosOLD(
|
|
||||||
OnlyInterfaceNeeded: boolean; CursorPos: TCodeXYPosition;
|
|
||||||
out CleanCursorPos: integer);
|
|
||||||
|
|
||||||
function StringIsKeyWord(const Word: string): boolean;
|
function StringIsKeyWord(const Word: string): boolean;
|
||||||
|
|
||||||
@ -2008,19 +2005,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCustomCodeTool.BeginParsingAndGetCleanPosOLD(
|
|
||||||
OnlyInterfaceNeeded: boolean; CursorPos: TCodeXYPosition;
|
|
||||||
out CleanCursorPos: integer);
|
|
||||||
var
|
|
||||||
Range: TLinkScannerRange;
|
|
||||||
begin
|
|
||||||
if OnlyInterfaceNeeded then
|
|
||||||
Range:=lsrImplementationStart
|
|
||||||
else
|
|
||||||
Range:=lsrEnd;
|
|
||||||
BeginParsingAndGetCleanPos(Range,CursorPos,CleanCursorPos);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TCustomCodeTool.IgnoreErrorAfterPositionIsInFrontOfLastErrMessage: boolean;
|
function TCustomCodeTool.IgnoreErrorAfterPositionIsInFrontOfLastErrMessage: boolean;
|
||||||
var
|
var
|
||||||
IgnoreErrorAfterCleanPos: integer;
|
IgnoreErrorAfterCleanPos: integer;
|
||||||
@ -2754,7 +2738,7 @@ procedure TCustomCodeTool.GetCleanPosInfo(CodePosInFront, CleanPos: integer;
|
|||||||
ResolveComments: if CleanPos is in a comment, parse again in the comment (not recursive)
|
ResolveComments: if CleanPos is in a comment, parse again in the comment (not recursive)
|
||||||
SameArea: area around CleanPos, either an atom, comment, directive or space
|
SameArea: area around CleanPos, either an atom, comment, directive or space
|
||||||
if CleanPos<CodePosInFront then CleanAtomPosition
|
if CleanPos<CodePosInFront then CleanAtomPosition
|
||||||
if CleanPos>SrcLen then CurPos.StartPos>SrcLen
|
if CleanPos>SrcLen then SameArea.StartPos>SrcLen
|
||||||
}
|
}
|
||||||
var
|
var
|
||||||
ANode: TCodeTreeNode;
|
ANode: TCodeTreeNode;
|
||||||
|
@ -30,7 +30,8 @@ program initvariable;
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, contnrs, CodeCache, CodeToolManager, DefineTemplates,
|
Classes, SysUtils, contnrs, CodeCache, CodeToolManager, DefineTemplates,
|
||||||
FileProcs, CodeToolsConfig, CodeToolsStructs, CodeCompletionTool, initvars1;
|
FileProcs, CodeToolsConfig, CodeToolsStructs, CodeCompletionTool,
|
||||||
|
StdCodeTools, initvars1;
|
||||||
|
|
||||||
const
|
const
|
||||||
ConfigFilename = 'codetools.config';
|
ConfigFilename = 'codetools.config';
|
||||||
@ -87,6 +88,16 @@ begin
|
|||||||
writeln(CodeXYPos.Code.Filename,'(',CodeXYPos.Y,',',CodeXYPos.X,'): ',Description);
|
writeln(CodeXYPos.Code.Filename,'(',CodeXYPos.Y,',',CodeXYPos.X,'): ',Description);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// insert the first statement at the first position
|
||||||
|
InsertPosDesc:=TInsertStatementPosDescription(InsertPositions[0]);
|
||||||
|
if not CodeToolBoss.InsertStatements(InsertPosDesc,Statements[0]) then begin
|
||||||
|
writeln('CodeToolBoss.InsertStatements failed');
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
writeln('New source (not saved to disk):');
|
||||||
|
writeln(Code.Source);
|
||||||
|
|
||||||
finally
|
finally
|
||||||
Statements.Free;
|
Statements.Free;
|
||||||
InsertPositions.Free;
|
InsertPositions.Free;
|
||||||
|
@ -57,6 +57,15 @@ uses
|
|||||||
CustomCodeTool, CodeToolsStructs, LazFileUtils;
|
CustomCodeTool, CodeToolsStructs, LazFileUtils;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
TInsertStatementPosDescription = class
|
||||||
|
public
|
||||||
|
InsertPos: integer;
|
||||||
|
Indent: integer;
|
||||||
|
CodeXYPos: TCodeXYPosition;
|
||||||
|
FrontGap, AfterGap: TGapTyp;
|
||||||
|
Description: string;
|
||||||
|
end;
|
||||||
|
|
||||||
TUsesSection = (usMain, usImplementation);
|
TUsesSection = (usMain, usImplementation);
|
||||||
|
|
||||||
TOnFindDefinePropertyForContext = procedure(Sender: TObject;
|
TOnFindDefinePropertyForContext = procedure(Sender: TObject;
|
||||||
@ -222,11 +231,10 @@ type
|
|||||||
function RemoveIdentifierDefinition(const CursorPos: TCodeXYPosition;
|
function RemoveIdentifierDefinition(const CursorPos: TCodeXYPosition;
|
||||||
SourceChangeCache: TSourceChangeCache): boolean;
|
SourceChangeCache: TSourceChangeCache): boolean;
|
||||||
|
|
||||||
function InsertStatements(const CursorPos: TCodeXYPosition;
|
function InsertStatements(InsertPos: TInsertStatementPosDescription;
|
||||||
Statements: string; FrontGap, AfterGap: TGapTyp;
|
Statements: string; SourceChangeCache: TSourceChangeCache): boolean;
|
||||||
SourceChangeCache: TSourceChangeCache): boolean;
|
|
||||||
function InsertStatements(CleanPos: integer;
|
function InsertStatements(CleanPos: integer;
|
||||||
Statements: string; FrontGap, AfterGap: TGapTyp;
|
Statements: string; Indent: integer; FrontGap, AfterGap: TGapTyp;
|
||||||
SourceChangeCache: TSourceChangeCache): boolean;
|
SourceChangeCache: TSourceChangeCache): boolean;
|
||||||
|
|
||||||
// blocks (e.g. begin..end)
|
// blocks (e.g. begin..end)
|
||||||
@ -4966,20 +4974,20 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TStandardCodeTool.InsertStatements(const CursorPos: TCodeXYPosition;
|
function TStandardCodeTool.InsertStatements(
|
||||||
Statements: string; FrontGap, AfterGap: TGapTyp;
|
InsertPos: TInsertStatementPosDescription; Statements: string;
|
||||||
SourceChangeCache: TSourceChangeCache): boolean;
|
SourceChangeCache: TSourceChangeCache): boolean;
|
||||||
var
|
var
|
||||||
CleanCursorPos: integer;
|
CleanCursorPos: integer;
|
||||||
begin
|
begin
|
||||||
BeginParsingAndGetCleanPos(lsrEnd,CursorPos,CleanCursorPos);
|
BeginParsingAndGetCleanPos(lsrEnd,InsertPos.CodeXYPos,CleanCursorPos);
|
||||||
Result:=InsertStatements(CleanCursorPos,Statements,FrontGap,AfterGap,
|
Result:=InsertStatements(CleanCursorPos,Statements,InsertPos.Indent,
|
||||||
SourceChangeCache);
|
InsertPos.FrontGap,InsertPos.AfterGap,SourceChangeCache);
|
||||||
Result:=SourceChangeCache.Apply;
|
Result:=SourceChangeCache.Apply;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TStandardCodeTool.InsertStatements(CleanPos: integer;
|
function TStandardCodeTool.InsertStatements(CleanPos: integer;
|
||||||
Statements: string; FrontGap, AfterGap: TGapTyp;
|
Statements: string; Indent: integer; FrontGap, AfterGap: TGapTyp;
|
||||||
SourceChangeCache: TSourceChangeCache): boolean;
|
SourceChangeCache: TSourceChangeCache): boolean;
|
||||||
{
|
{
|
||||||
ToDo: check for "uses" in Statements and extend uses section
|
ToDo: check for "uses" in Statements and extend uses section
|
||||||
@ -4989,19 +4997,31 @@ function TStandardCodeTool.InsertStatements(CleanPos: integer;
|
|||||||
}
|
}
|
||||||
var
|
var
|
||||||
Node: TCodeTreeNode;
|
Node: TCodeTreeNode;
|
||||||
|
SameArea: TAtomPosition;
|
||||||
|
BeautifyFlags: TBeautifyCodeFlags;
|
||||||
begin
|
begin
|
||||||
Node:=FindDeepestNodeAtPos(CleanPos,true);
|
Node:=FindDeepestNodeAtPos(CleanPos,true);
|
||||||
if not (Node.Desc in AllPascalStatements) then begin
|
if not (Node.Desc in AllPascalStatements) then begin
|
||||||
MoveCursorToCleanPos(CleanPos);
|
MoveCursorToCleanPos(CleanPos);
|
||||||
RaiseException('invalid position for insertion');
|
RaiseException('invalid position for insertion of statements');
|
||||||
end;
|
end;
|
||||||
if Node.Desc=ctnBeginBlock then
|
if Node.Desc=ctnBeginBlock then
|
||||||
Node:=BuildSubTreeAndFindDeepestNodeAtPos(Node,CleanPos,true);
|
Node:=BuildSubTreeAndFindDeepestNodeAtPos(Node,CleanPos,true);
|
||||||
|
|
||||||
// ToDo: check for CleanPos
|
GetCleanPosInfo(Node.StartPos,CleanPos,false,SameArea);
|
||||||
|
if (SameArea.StartPos>SrcLen) or (not IsSpaceChar[Src[SameArea.StartPos]])
|
||||||
|
then begin
|
||||||
|
MoveCursorToCleanPos(CleanPos);
|
||||||
|
RaiseException('invalid position for insertion of statements');
|
||||||
|
end;
|
||||||
|
|
||||||
SourceChangeCache.MainScanner:=Scanner;
|
SourceChangeCache.MainScanner:=Scanner;
|
||||||
|
BeautifyFlags:=[bcfIndentExistingLineBreaks];
|
||||||
|
if FrontGap in [gtNone,gtSpace] then
|
||||||
|
include(BeautifyFlags,bcfDoNotIndentFirstLine);
|
||||||
|
Statements:=SourceChangeCache.BeautifyCodeOptions.BeautifyStatement(
|
||||||
|
Statements,Indent,BeautifyFlags);
|
||||||
|
|
||||||
Result:=SourceChangeCache.Replace(FrontGap,AfterGap,CleanPos,CleanPos,Statements);
|
Result:=SourceChangeCache.Replace(FrontGap,AfterGap,CleanPos,CleanPos,Statements);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user