diff --git a/components/codetools/basiccodetools.pas b/components/codetools/basiccodetools.pas index 393123df45..a641002834 100644 --- a/components/codetools/basiccodetools.pas +++ b/components/codetools/basiccodetools.pas @@ -3739,6 +3739,7 @@ begin end; function CodeIsOnlySpace(const ACode: string; FromPos, ToPos: integer): boolean; +// from FromPos to including ToPos var SrcLen: integer; CodePos: integer; diff --git a/components/codetools/pascalparsertool.pas b/components/codetools/pascalparsertool.pas index dc4b7c800b..beead86566 100644 --- a/components/codetools/pascalparsertool.pas +++ b/components/codetools/pascalparsertool.pas @@ -695,12 +695,14 @@ begin RaiseException( 'TPascalParserTool.BuildSubTreeForBeginBlock: BeginNode.Desc=' +BeginNode.DescAsString); - if (BeginNode.FirstChild<>nil) - or ((BeginNode.SubDesc and ctnsNeedJITParsing)=0) then + if (BeginNode.SubDesc and ctnsNeedJITParsing)=0 then // block already parsed exit; // avoid endless loop BeginNode.SubDesc:=BeginNode.SubDesc and (not ctnsNeedJITParsing); + if (BeginNode.FirstChild<>nil) then + // block already parsed + exit; OldPhase:=CurrentPhase; CurrentPhase:=CodeToolPhaseParse; @@ -716,13 +718,14 @@ begin MaxPos:=SrcLen; repeat ReadNextAtom; - if UpAtomIs('WITH') then - ReadWithStatement(true,true); - if UpAtomIs('ON') then + if BlockStatementStartKeyWordFuncList.DoItUppercase(UpperSrc,CurPos.StartPos, + CurPos.EndPos-CurPos.StartPos) then + begin + if not ReadTilBlockEnd(false,true) then RaiseEndOfSourceExpected; + end else if UpAtomIs('WITH') then + ReadWithStatement(true,true) + else if UpAtomIs('ON') then ReadOnStatement(true,true); - if UpAtomIs('CASE') then begin - // ToDo - end; until (CurPos.StartPos>=MaxPos); CurrentPhase:=OldPhase; except @@ -2129,7 +2132,8 @@ function TPascalParserTool.ReadTilBlockEnd( var BlockType: TEndBlockType; TryType: TTryType; BlockStartPos: integer; - + Desc: TCodeTreeNodeDesc; + procedure SaveRaiseExceptionWithBlockStartHint(const AMessage: string); var CaretXY: TCodeXYPosition; begin @@ -2173,9 +2177,11 @@ var BlockType: TEndBlockType; begin Result:=true; TryType:=ttNone; - if CurPos.Flag=cafBEGIN then - BlockType:=ebtBegin - else if UpAtomIs('REPEAT') then + Desc:=ctnNone; + if CurPos.Flag=cafBEGIN then begin + BlockType:=ebtBegin; + Desc:=ctnBeginBlock; + end else if UpAtomIs('REPEAT') then BlockType:=ebtRepeat else if UpAtomIs('TRY') then BlockType:=ebtTry @@ -2187,6 +2193,13 @@ begin BlockType:=ebtRecord else RaiseUnknownBlockType; + if (Desc<>ctnNone) then begin + if CreateNodes then begin + CreateChildNode; + CurNode.Desc:=Desc; + end else + Desc:=ctnNone; + end; BlockStartPos:=CurPos.StartPos; repeat ReadNextAtom; @@ -2202,6 +2215,10 @@ begin RaiseStrExpectedWithBlockStartHint('"until"'); if (BlockType=ebtTry) and (TryType=ttNone) then RaiseStrExpectedWithBlockStartHint('"finally"'); + if Desc<>ctnNone then begin + CurNode.EndPos:=CurPos.EndPos; + EndChildNode; + end; ReadNextAtom; if (CurPos.Flag=cafPoint) and (BlockType<>ebtBegin) then begin RaiseCharExpectedButAtomFound(';'); @@ -2218,9 +2235,13 @@ begin if (BlockType<>ebtRecord) or (not UpAtomIs('CASE')) then ReadTilBlockEnd(false,CreateNodes); end else if UpAtomIs('UNTIL') then begin - if BlockType=ebtRepeat then - break; - RaiseStrExpectedWithBlockStartHint('"end"'); + if BlockType<>ebtRepeat then + RaiseStrExpectedWithBlockStartHint('"end"'); + if Desc<>ctnNone then begin + CurNode.EndPos:=CurPos.EndPos; + EndChildNode; + end; + break; end else if UpAtomIs('FINALLY') then begin if (BlockType=ebtTry) and (TryType=ttNone) then begin if StopOnBlockMiddlePart then break; diff --git a/ide/codeexplopts.pas b/ide/codeexplopts.pas index d4926820ce..f119d4fba8 100644 --- a/ide/codeexplopts.pas +++ b/ide/codeexplopts.pas @@ -72,6 +72,7 @@ type cefcEmptyProcs, // procs without code (can contain comments) cefcNestedProcs, // procs with a lot of nested sub procs cefcUnnamedConsts, // numbers, strings in statements + cefcEmptyBlocks, // empty begin..end block (not even a comment) cefcPublishedPropWithoutDefault, // published properties without default specifier cefcUnsortedClassVisibility, // public,private,protected,published keywords are not sorted cefcEmptyClassSections, // empty public,private,protected,published section @@ -206,6 +207,7 @@ const 'EmptyProcs', 'NestedProcs', 'UnnamedConsts', + 'EmptyBlocks', 'PublishedPropWithoutDefault', 'UnsortedClassVisibility', 'EmptyClassSections', @@ -277,6 +279,7 @@ begin cefcEmptyProcs: Result:=lisCEEmptyProcedures; cefcNestedProcs: Result:=lisCEManyNestedProcedures; cefcUnnamedConsts: Result:=lisCEUnnamedConstants; + cefcEmptyBlocks: Result:=lisCEEmptyBlocks; cefcPublishedPropWithoutDefault: Result:=lisCEPublishedPropertyWithoutDefault; cefcUnsortedClassVisibility: Result:=lisCEUnsortedVisibility; cefcEmptyClassSections: Result:=lisCEEmptyClassSections; diff --git a/ide/codeexplorer.pas b/ide/codeexplorer.pas index d44fc9e208..13345bc9af 100644 --- a/ide/codeexplorer.pas +++ b/ide/codeexplorer.pas @@ -857,6 +857,8 @@ begin case CodeNode.Desc of ctnBeginBlock: begin + if (CodeNode.SubDesc and ctnsNeedJITParsing)<>0 then + Tool.BuildSubTreeForBeginBlock(CodeNode); if (cefcLongProcs in Figures) and (CodeNode.Parent.Desc=ctnProcedure) then begin LineCnt:=LineEndCount(Tool.Src,CodeNode.StartPos,CodeNode.EndPos,i); @@ -881,6 +883,12 @@ begin and (not CodeNode.HasParentOfType(ctnBeginBlock)) then begin FindFigureConstants(Tool,CodeNode,CodeNode.StartPos,CodeNode.EndPos); end; + if (cefcEmptyBlocks in Figures) + and CodeIsOnlySpace(Tool.Src,CodeNode.StartPos+length('begin'), + CodeNode.EndPos-length('end')-1) + then begin + AddCodeNode(cefcEmptyBlocks,CodeNode); + end; end; ctnProcedure: diff --git a/ide/lazarusidestrconsts.pas b/ide/lazarusidestrconsts.pas index d2657b0773..5a8fa23c6d 100644 --- a/ide/lazarusidestrconsts.pas +++ b/ide/lazarusidestrconsts.pas @@ -4165,6 +4165,7 @@ resourcestring lisCEFigureCharConst = 'Search for unnamed char constants'; lisCEIgnoreFigureConstants = 'Ignore next unnamed constants'; lisCEIgnoreFigConstInFuncs = 'Ignore constants in next functions'; + lisCEEmptyBlocks = 'Empty blocks'; implementation