mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-07 09:58:15 +02:00
codetools: completeblock: begin ;, bug #16836
git-svn-id: trunk@26452 -
This commit is contained in:
parent
70b09d3d69
commit
e454ee7c16
@ -100,7 +100,7 @@ type
|
|||||||
procedure Add(NewAtom: TAtomPosition); inline;
|
procedure Add(NewAtom: TAtomPosition); inline;
|
||||||
procedure UndoLastAdd; inline;
|
procedure UndoLastAdd; inline;
|
||||||
function GetValueAt(RelativePos:integer): TAtomPosition; inline;
|
function GetValueAt(RelativePos:integer): TAtomPosition; inline;
|
||||||
// 0=current 1=prior current ...
|
// 0=current last 1=prior current ...
|
||||||
// for LastAtoms: 0 is the last atom
|
// for LastAtoms: 0 is the last atom
|
||||||
function Count: integer; inline;
|
function Count: integer; inline;
|
||||||
property Size: integer read FSize write SetSize;
|
property Size: integer read FSize write SetSize;
|
||||||
|
@ -250,6 +250,7 @@ type
|
|||||||
// read atoms
|
// read atoms
|
||||||
function AtomIs(const AnAtom: shortstring): boolean;
|
function AtomIs(const AnAtom: shortstring): boolean;
|
||||||
function UpAtomIs(const AnAtom: shortstring): boolean;
|
function UpAtomIs(const AnAtom: shortstring): boolean;
|
||||||
|
function UpAtomIs(const AtomPos: TAtomPosition; const AnAtom: shortstring): boolean; overload;
|
||||||
function ReadNextAtomIs(const AnAtom: shortstring): boolean; {$IFDEF UseInline}inline;{$ENDIF}
|
function ReadNextAtomIs(const AnAtom: shortstring): boolean; {$IFDEF UseInline}inline;{$ENDIF}
|
||||||
function ReadNextUpAtomIs(const AnAtom: shortstring): boolean; {$IFDEF UseInline}inline;{$ENDIF}
|
function ReadNextUpAtomIs(const AnAtom: shortstring): boolean; {$IFDEF UseInline}inline;{$ENDIF}
|
||||||
function ReadNextAtomIsChar(const c: char): boolean; {$IFDEF UseInline}inline;{$ENDIF}
|
function ReadNextAtomIsChar(const c: char): boolean; {$IFDEF UseInline}inline;{$ENDIF}
|
||||||
@ -583,6 +584,25 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCustomCodeTool.UpAtomIs(const AtomPos: TAtomPosition;
|
||||||
|
const AnAtom: shortstring): boolean;
|
||||||
|
var
|
||||||
|
AnAtomLen, i: integer;
|
||||||
|
p: PChar;
|
||||||
|
begin
|
||||||
|
Result:=false;
|
||||||
|
AnAtomLen:=length(AnAtom);
|
||||||
|
if AnAtomLen<>AtomPos.EndPos-AtomPos.StartPos then exit;
|
||||||
|
if (AtomPos.EndPos<=SrcLen+1) and (AtomPos.StartPos>=1) then begin
|
||||||
|
p:=@Src[AtomPos.StartPos];
|
||||||
|
for i:=1 to AnAtomLen do begin
|
||||||
|
if AnAtom[i]<>UpChars[p^] then exit;
|
||||||
|
inc(p);
|
||||||
|
end;
|
||||||
|
Result:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TCustomCodeTool.ReadNextAtomIs(const AnAtom: shortstring): boolean;
|
function TCustomCodeTool.ReadNextAtomIs(const AnAtom: shortstring): boolean;
|
||||||
begin
|
begin
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
|
@ -5591,6 +5591,7 @@ var
|
|||||||
Indent: Integer;
|
Indent: Integer;
|
||||||
CursorBlockInnerIndent, CursorBlockOuterIndent: LongInt;
|
CursorBlockInnerIndent, CursorBlockOuterIndent: LongInt;
|
||||||
CursorBlock: TBlock;
|
CursorBlock: TBlock;
|
||||||
|
AtomInFrontOfCursor: TAtomPosition;
|
||||||
BehindCursorBlock: Boolean; // atom is behind cursor block
|
BehindCursorBlock: Boolean; // atom is behind cursor block
|
||||||
InCursorBlock: Boolean;
|
InCursorBlock: Boolean;
|
||||||
NeedCompletion: Boolean;
|
NeedCompletion: Boolean;
|
||||||
@ -5600,6 +5601,9 @@ var
|
|||||||
FrontGap: TGapTyp;
|
FrontGap: TGapTyp;
|
||||||
BeautifyFlags: TBeautifyCodeFlags;
|
BeautifyFlags: TBeautifyCodeFlags;
|
||||||
BehindPos: LongInt;
|
BehindPos: LongInt;
|
||||||
|
CursorInEmptyStatement: Boolean;
|
||||||
|
FromPos: LongInt;
|
||||||
|
ToPos: LongInt;
|
||||||
|
|
||||||
function EndBlockIsOk: boolean;
|
function EndBlockIsOk: boolean;
|
||||||
begin
|
begin
|
||||||
@ -5621,6 +5625,8 @@ var
|
|||||||
CursorBlock.StartPos:=0;
|
CursorBlock.StartPos:=0;
|
||||||
BehindCursorBlock:=false;
|
BehindCursorBlock:=false;
|
||||||
NeedCompletion:=false;
|
NeedCompletion:=false;
|
||||||
|
AtomInFrontOfCursor.StartPos:=0;
|
||||||
|
CursorInEmptyStatement:=false;
|
||||||
repeat
|
repeat
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
|
|
||||||
@ -5628,7 +5634,7 @@ var
|
|||||||
if (Stack.Top>=0) and (Stack.Stack[Stack.Top].InnerIndent<0)
|
if (Stack.Top>=0) and (Stack.Stack[Stack.Top].InnerIndent<0)
|
||||||
and (not PositionsInSameLine(Src,Stack.Stack[Stack.Top].StartPos,CurPos.StartPos))
|
and (not PositionsInSameLine(Src,Stack.Stack[Stack.Top].StartPos,CurPos.StartPos))
|
||||||
then begin
|
then begin
|
||||||
// the first atom of this block on a new line
|
// the first atom of this block is on a new line
|
||||||
Stack.Stack[Stack.Top].InnerIndent:=GetLineIndent(Src,CurPos.StartPos);
|
Stack.Stack[Stack.Top].InnerIndent:=GetLineIndent(Src,CurPos.StartPos);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -5643,6 +5649,15 @@ var
|
|||||||
CursorBlock:=Stack.Stack[CursorBlockLvl];
|
CursorBlock:=Stack.Stack[CursorBlockLvl];
|
||||||
CursorBlockOuterIndent:=GetLineIndent(Src,CursorBlock.StartPos);
|
CursorBlockOuterIndent:=GetLineIndent(Src,CursorBlock.StartPos);
|
||||||
CursorBlockInnerIndent:=Stack.Stack[Stack.Top].InnerIndent;
|
CursorBlockInnerIndent:=Stack.Stack[Stack.Top].InnerIndent;
|
||||||
|
AtomInFrontOfCursor:=LastAtoms.GetValueAt(0);
|
||||||
|
if (CurPos.Flag=cafSemicolon)
|
||||||
|
and ((AtomInFrontOfCursor.Flag=cafSemicolon)
|
||||||
|
or (CursorBlock.StartPos=AtomInFrontOfCursor.StartPos))
|
||||||
|
and (FindNextNonSpace(Src,AtomInFrontOfCursor.EndPos)=CurPos.StartPos)
|
||||||
|
then begin
|
||||||
|
// cursor in empty statement
|
||||||
|
CursorInEmptyStatement:=true;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
//DebugLn(['ReadStatements CursorBlockLvl=',CursorBlockLvl,' Indent=',CursorBlockIndent]);
|
//DebugLn(['ReadStatements CursorBlockLvl=',CursorBlockLvl,' Indent=',CursorBlockIndent]);
|
||||||
end;
|
end;
|
||||||
@ -5758,6 +5773,7 @@ var
|
|||||||
if TopBlockType(Stack)=btCaseOf then
|
if TopBlockType(Stack)=btCaseOf then
|
||||||
BeginBlock(Stack,btCaseColon,CurPos.StartPos);
|
BeginBlock(Stack,btCaseColon,CurPos.StartPos);
|
||||||
cafSemicolon:
|
cafSemicolon:
|
||||||
|
// todo: close btRoundBracket, btEdgedBracket
|
||||||
while TopBlockType(Stack) in [btCaseColon,btIf,btIfElse] do begin
|
while TopBlockType(Stack) in [btCaseColon,btIf,btIfElse] do begin
|
||||||
if not EndBlockIsOk then exit;
|
if not EndBlockIsOk then exit;
|
||||||
end;
|
end;
|
||||||
@ -5791,14 +5807,17 @@ var
|
|||||||
end else if UpAtomIs('IF') then begin
|
end else if UpAtomIs('IF') then begin
|
||||||
BeginBlock(Stack,btIf,CurPos.StartPos);
|
BeginBlock(Stack,btIf,CurPos.StartPos);
|
||||||
end else if UpAtomIs('THEN') then begin
|
end else if UpAtomIs('THEN') then begin
|
||||||
|
// todo: close brackets
|
||||||
if TopBlockType(Stack)=btIf then
|
if TopBlockType(Stack)=btIf then
|
||||||
Stack.Stack[Stack.Top].InnerIndent:=-1;
|
Stack.Stack[Stack.Top].InnerIndent:=-1;
|
||||||
end else if UpAtomIs('CASE') then begin
|
end else if UpAtomIs('CASE') then begin
|
||||||
BeginBlock(Stack,btCase,CurPos.StartPos)
|
BeginBlock(Stack,btCase,CurPos.StartPos)
|
||||||
end else if UpAtomIs('OF') then begin
|
end else if UpAtomIs('OF') then begin
|
||||||
|
// todo: close brackets
|
||||||
if TopBlockType(Stack)=btCase then
|
if TopBlockType(Stack)=btCase then
|
||||||
BeginBlock(Stack,btCaseOf,CurPos.StartPos);
|
BeginBlock(Stack,btCaseOf,CurPos.StartPos);
|
||||||
end else if UpAtomIs('ELSE') then begin
|
end else if UpAtomIs('ELSE') then begin
|
||||||
|
// todo: close brackets
|
||||||
case TopBlockType(Stack) of
|
case TopBlockType(Stack) of
|
||||||
btIf:
|
btIf:
|
||||||
begin
|
begin
|
||||||
@ -5836,6 +5855,8 @@ var
|
|||||||
end else if UpAtomIs('PROCEDURE') or UpAtomIs('FUNCTION')
|
end else if UpAtomIs('PROCEDURE') or UpAtomIs('FUNCTION')
|
||||||
or UpAtomIs('CONSTRUCTOR') or UpAtomIs('DESTRUCTOR')
|
or UpAtomIs('CONSTRUCTOR') or UpAtomIs('DESTRUCTOR')
|
||||||
or UpAtomIs('VAR') or UpAtomIs('TYPE') or UpAtomIs('CONST')
|
or UpAtomIs('VAR') or UpAtomIs('TYPE') or UpAtomIs('CONST')
|
||||||
|
or UpAtomIs('RESOURCESTRING') or UpAtomIs('LABEL') or UpAtomIs('CLASS')
|
||||||
|
or UpAtomIs('INITIALIZATION') or UpAtomIs('FINALIZATION')
|
||||||
then begin
|
then begin
|
||||||
// unexpected keyword => block not closed
|
// unexpected keyword => block not closed
|
||||||
{$IFDEF ShowCompleteBlock}
|
{$IFDEF ShowCompleteBlock}
|
||||||
@ -5896,7 +5917,8 @@ var
|
|||||||
// check code behind
|
// check code behind
|
||||||
BehindPos:=FindNextNonSpace(Src,InsertPos);
|
BehindPos:=FindNextNonSpace(Src,InsertPos);
|
||||||
if BehindPos<=SrcLen then begin
|
if BehindPos<=SrcLen then begin
|
||||||
if PositionsInSameLine(Src,InsertPos,BehindPos) then begin
|
if (not CursorInEmptyStatement)
|
||||||
|
and PositionsInSameLine(Src,InsertPos,BehindPos) then begin
|
||||||
// target line not empty
|
// target line not empty
|
||||||
{$IFDEF ShowCompleteBlock}
|
{$IFDEF ShowCompleteBlock}
|
||||||
DebugLn(['CompleteStatements target line not empty => skip']);
|
DebugLn(['CompleteStatements target line not empty => skip']);
|
||||||
@ -5916,30 +5938,38 @@ var
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
NewCode:='';
|
NewCode:=';';
|
||||||
FrontGap:=gtEmptyLine;
|
FrontGap:=gtEmptyLine;
|
||||||
AfterGap:=gtNewLine;
|
AfterGap:=gtNewLine;
|
||||||
|
FromPos:=InsertPos;
|
||||||
|
ToPos:=InsertPos;
|
||||||
BeautifyFlags:=[bcfIndentExistingLineBreaks];
|
BeautifyFlags:=[bcfIndentExistingLineBreaks];
|
||||||
|
if CursorInEmptyStatement and (BehindPos<=SrcLen) then begin
|
||||||
|
// replace the empty statement
|
||||||
|
FrontGap:=gtNewLine;
|
||||||
|
ToPos:=BehindPos;
|
||||||
|
end;
|
||||||
case CursorBlock.Typ of
|
case CursorBlock.Typ of
|
||||||
btBegin,btFinally,btExcept,btAsm,btCaseOf,btCaseElse:
|
btBegin,btFinally,btExcept,btAsm,btCaseOf,btCaseElse:
|
||||||
NewCode:='end;';
|
NewCode:='end'+NewCode;
|
||||||
btRepeat:
|
btRepeat:
|
||||||
NewCode:='until ;';
|
NewCode:='until '+NewCode;
|
||||||
btTry:
|
btTry:
|
||||||
NewCode:='finally'+SourceChangeCache.BeautifyCodeOptions.LineEnd
|
NewCode:='finally'+SourceChangeCache.BeautifyCodeOptions.LineEnd
|
||||||
+'end;';
|
+'end'+NewCode;
|
||||||
btCaseColon:
|
btCaseColon:
|
||||||
begin
|
begin
|
||||||
NewCode:=';';
|
|
||||||
FrontGap:=gtNone;
|
FrontGap:=gtNone;
|
||||||
AfterGap:=gtNone;
|
AfterGap:=gtNone;
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
if (CursorBlockLvl=0) and (AfterGap=gtNewLine) then
|
if (CursorBlockLvl=0) and (AfterGap=gtNewLine) then begin
|
||||||
|
// top level => insert empty lines between top level structures
|
||||||
AfterGap:=gtEmptyLine;
|
AfterGap:=gtEmptyLine;
|
||||||
if not Replace(NewCode,InsertPos,InsertPos,Indent,FrontGap,AfterGap,
|
end;
|
||||||
|
if not Replace(NewCode,FromPos,ToPos,Indent,FrontGap,AfterGap,
|
||||||
BeautifyFlags) then exit;
|
BeautifyFlags) then exit;
|
||||||
end;
|
end;
|
||||||
Result:=true;
|
Result:=true;
|
||||||
|
Loading…
Reference in New Issue
Block a user