codetools: completeblock: begin ;, bug #16836

git-svn-id: trunk@26452 -
This commit is contained in:
mattias 2010-07-04 07:23:42 +00:00
parent 70b09d3d69
commit e454ee7c16
3 changed files with 60 additions and 10 deletions

View File

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

View File

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

View File

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