codetools: started nested classes, replaced ctnClassType with ctnTypeSection, ctnClassConst with ctnConstSection, class type,const,var sections are now childs of visibility sections

git-svn-id: trunk@29390 -
This commit is contained in:
mattias 2011-02-05 10:09:22 +00:00
parent f714457e24
commit 3943d23f9b
8 changed files with 284 additions and 428 deletions

View File

@ -1530,7 +1530,7 @@ var
ProcNode:=CursorNode;
while (ProcNode<>nil) do begin
if (ProcNode.Desc=ctnProcedure) then begin
SearchedClassname:=ExtractClassNameOfProcNode(ProcNode);
SearchedClassname:=ExtractClassNameOfProcNode(ProcNode,true);
if SearchedClassName<>'' then break;
end;
ProcNode:=ProcNode.Parent;
@ -1591,7 +1591,7 @@ var
end;
MethodDefinition:=SourceChangeCache.BeautifyCodeOptions.
AddClassAndNameToProc(MethodDefinition,
ExtractClassName(AClassNode,false), AnEventName);
ExtractClassName(AClassNode,false,true), AnEventName);
if not InsertAllNewClassParts then
RaiseException(ctsErrorDuringInsertingNewClassParts);
@ -5873,7 +5873,7 @@ begin
else
Indent:=GetLineIndent(Src,ClassSectionNode.Parent.StartPos)
+ASourceChangeCache.BeautifyCodeOptions.Indent;
end else if (ClassSectionNode.Desc in (AllClassBaseSections+[ctnClassType]))
end else if (ClassSectionNode.Desc in AllClassBaseSections)
then begin
// skip keyword
MoveCursorToCleanPos(InsertPos);

View File

@ -96,16 +96,13 @@ const
ctnClassExternal = 42;
ctnClassInheritance = 43;
ctnClassGUID = 44;
ctnClassConst = 45;
ctnClassType = 46;
ctnClassVar = 47;
ctnClassClassVar = 48;
ctnClassPrivate = 49;
ctnClassProtected = 50;
ctnClassPublic = 51;
ctnClassPublished = 52;
ctnProperty = 53;
ctnMethodMap = 54;
ctnClassClassVar = 45; // child of visibility section
ctnClassPrivate = 46; // child of AllClassObjects
ctnClassProtected = 47;
ctnClassPublic = 48;
ctnClassPublished = 49;
ctnProperty = 50; // child of visibility section or AllClassInterfaces
ctnMethodMap = 51; // child of visibility section or AllClassInterfaces
ctnProcedure = 60; // childs: ctnProcedureHead, sections, ctnBeginBlock/ctnAsmBlock
ctnProcedureHead = 61; // childs: ctnParameterList, operator: ctnVarDefinition, operator/function: ctnResultType
@ -156,8 +153,10 @@ const
+ [ctnInterface, ctnImplementation, ctnInitialization, ctnFinalization];
AllClassBaseSections =
[ctnClassPublic,ctnClassPublished,ctnClassPrivate,ctnClassProtected];
AllClassSubSections =
[ctnConstSection, ctnTypeSection, ctnVarSection, ctnClassClassVar];
AllClassSections =
AllClassBaseSections+[ctnClassConst, ctnClassType, ctnClassVar, ctnClassClassVar];
AllClassBaseSections+AllClassSubSections;
AllClassInterfaces = [ctnClassInterface,ctnDispinterface,ctnObjCProtocol];
AllClassObjects = [ctnClass,ctnObject,ctnRecordType,
ctnObjCClass,ctnObjCCategory,ctnCPPClass];
@ -350,9 +349,6 @@ begin
ctnClassPrivate: Result:='Private';
ctnClassProtected: Result:='Protected';
ctnClassPublic: Result:='Public';
ctnClassConst: Result:='Const';
ctnClassType: Result:='Type';
ctnClassVar: Result:='Var';
ctnClassClassVar: Result:='Class Var';
ctnClassAbstract: Result:='abstract';
ctnClassSealed: Result:='sealed';

View File

@ -2180,7 +2180,7 @@ begin
end;
// add class name
ClassStr := NewTool.ExtractClassName(NewNode, False);
ClassStr := NewTool.ExtractClassName(NewNode, False, true);
if ClassStr <> '' then Result := Result + ClassStr + '.';
Result:=Result+NewTool.ExtractDefinitionName(NewNode);
@ -2240,7 +2240,7 @@ begin
if NewNode.Desc = ctnProperty then
begin // add class name
ClassStr := NewTool.ExtractClassName(NewNode, False);
ClassStr := NewTool.ExtractClassName(NewNode, False, True);
if ClassStr <> '' then Result := Result + ClassStr + '.';
end;
@ -2967,7 +2967,7 @@ var
ctnLabelSection, ctnPropertySection,
ctnInterface, ctnImplementation,
ctnClassPublished,ctnClassPublic,ctnClassProtected,ctnClassPrivate,
ctnClassConst,ctnClassType,ctnClassVar,ctnClassClassVar,
ctnClassClassVar,
ctnRecordVariant,
ctnProcedureHead, ctnParameterList,
ctnClassInheritance:
@ -3086,7 +3086,7 @@ begin
ctnLabelSection, ctnPropertySection,
ctnInterface, ctnImplementation,
ctnClassPublic, ctnClassPrivate, ctnClassProtected, ctnClassPublished,
ctnClassConst, ctnClassType, ctnClassVar, ctnClassClassVar,
ctnClassClassVar,
ctnClass, ctnClassInterface, ctnDispinterface, ctnObject,
ctnObjCClass, ctnObjCCategory, ctnObjCProtocol, ctnCPPClass,
ctnRecordType, ctnRecordVariant,

View File

@ -402,7 +402,7 @@ begin
// gather the method bodies
SearchInNodes:=GatherProcNodes(TypeSectionNode,
[phpInUpperCase,phpIgnoreForwards,phpOnlyWithClassname],
ExtractClassName(ClassNode,true));
ExtractClassName(ClassNode,true,true));
try
// remove all corresponding methods
RemoveCorrespondingProcNodes(SearchInNodes,SearchForNodes,false);
@ -524,20 +524,19 @@ begin
end else begin
// procedure is not forward, search on same proc level
{$IFDEF CTDEBUG}
DebugLn('TMethodJumpingCodeTool.FindJumpPoint 4A');
DebugLn('TMethodJumpingCodeTool.FindJumpPoint proc body');
{$ENDIF}
SearchedClassname:=ExtractClassNameOfProcNode(ProcNode);
SearchedClassname:=ExtractClassNameOfProcNode(ProcNode,true);
StartNode:=FindFirstNodeOnSameLvl(ProcNode);
{$IFDEF CTDEBUG}
DebugLn('TMethodJumpingCodeTool.FindJumpPoint 4B ',dbgs(StartNode<>nil),' ',SearchedClassName);
DebugLn('TMethodJumpingCodeTool.FindJumpPoint body to decl: ',dbgs(StartNode<>nil),' Class="',SearchedClassName,'"');
{$ENDIF}
if StartNode=nil then exit;
if SearchedClassname<>'' then begin
// search class node
ClassNode:=FindClassNode(StartNode,UpperCaseStr(SearchedClassName),
true,false);
ClassNode:=FindClassNode(StartNode,SearchedClassName,true,false);
{$IFDEF CTDEBUG}
DebugLn('TMethodJumpingCodeTool.FindJumpPoint 4C ',dbgs(ClassNode<>nil));
DebugLn('TMethodJumpingCodeTool.FindJumpPoint class found: ',dbgs(ClassNode<>nil));
{$ENDIF}
if ClassNode=nil then exit;
// search first class grand child node
@ -567,7 +566,7 @@ begin
TypeSectionNode:=ClassNode.GetTopMostNodeOfType(ctnTypeSection);
SearchForNodes:=GatherProcNodes(TypeSectionNode,
[phpInUpperCase,phpIgnoreForwards,phpOnlyWithClassname],
ExtractClassName(ClassNode,true));
ExtractClassName(ClassNode,true,true));
try
// remove corresponding methods
RemoveCorrespondingProcNodes(SearchForNodes,SearchInNodes,false);
@ -786,7 +785,7 @@ begin
//DebugLn('[TMethodJumpingCodeTool.GatherProcNodes] B');
cmp:=true;
if (phpOnlyWithClassname in Attr) then begin
CurClassName:=ExtractClassNameOfProcNode(ANode);
CurClassName:=ExtractClassNameOfProcNode(ANode,true);
//DebugLn('[TMethodJumpingCodeTool.GatherProcNodes] B2 "',CurClassName,'" =? ',UpperClassName);
if CompareIdentifiers(PChar(UpperClassName),PChar(CurClassName))<>0 then
@ -795,7 +794,7 @@ begin
if cmp and (phpIgnoreMethods in Attr) then begin
if (ANode.GetNodeOfTypes([ctnClass,ctnObject,ctnRecordType,
ctnObjCClass,ctnObjCCategory,ctnCPPClass])<>nil)
or (ExtractClassNameOfProcNode(ANode)<>'')
or (ExtractClassNameOfProcNode(ANode,true)<>'')
then
cmp:=false;
end;

View File

@ -167,20 +167,10 @@ type
function KeyWordFuncClassMethod: boolean;
function KeyWordFuncClassProperty: boolean;
function KeyWordFuncClassIdentifier: boolean;
function KeyWordFuncClassVarTypeClass: boolean;
function KeyWordFuncClassVarTypePacked: boolean;
function KeyWordFuncClassVarTypeBitPacked: boolean;
function KeyWordFuncClassVarTypeRecord: boolean;
function KeyWordFuncClassVarTypeArray: boolean;
function KeyWordFuncClassVarTypeSet: boolean;
function KeyWordFuncClassVarTypeProc: boolean;
function KeyWordFuncClassVarTypeIdent: boolean;
// keyword lists
procedure BuildDefaultKeyWordFunctions; override;
function ParseType(StartPos, WordLen: integer): boolean;
function ParseInnerClass(StartPos, WordLen: integer): boolean;
function ParseClassVarType(StartPos, WordLen: integer): boolean;
function SkipInnerClassInterface(StartPos, WordLen: integer): boolean;
function UnexpectedKeyWord: boolean;
function EndOfSourceExpected: boolean;
// read functions
@ -496,65 +486,6 @@ begin
Result:=KeyWordFuncClassIdentifier;
end;
function TPascalParserTool.ParseClassVarType(StartPos, WordLen: integer
): boolean;
// KeywordFunctions for parsing the type of a variable in a class/object
var
p: PChar;
begin
if StartPos>SrcLen then exit(false);
p:=@Src[StartPos];
case UpChars[p^] of
'A':
if CompareSrcIdentifiers('ARRAY',p) then exit(KeyWordFuncClassVarTypeArray);
'B':
if CompareSrcIdentifiers('BITPACKED',p) then exit(KeyWordFuncClassVarTypeBitPacked);
'C':
if CompareSrcIdentifiers('CLASS',p) then exit(KeyWordFuncClassVarTypeClass);
'F':
if CompareSrcIdentifiers('FUNCTION',p) then exit(KeyWordFuncClassVarTypeProc);
'O':
if CompareSrcIdentifiers('OBJECT',p) then exit(KeyWordFuncClassVarTypeClass);
'P':
case UpChars[p[1]] of
'A': if CompareSrcIdentifiers('PACKED',p) then exit(KeyWordFuncClassVarTypePacked);
'R': if CompareSrcIdentifiers('PROCEDURE',p) then exit(KeyWordFuncClassVarTypeProc);
end;
'R':
if CompareSrcIdentifiers('RECORD',p) then exit(KeyWordFuncClassVarTypeRecord);
'S':
if CompareSrcIdentifiers('SET',p) then exit(KeyWordFuncClassVarTypeSet);
end;
Result:=KeyWordFuncClassVarTypeIdent;
end;
function TPascalParserTool.SkipInnerClassInterface(StartPos, WordLen: integer
): boolean;
// KeyWordFunctions for skipping in a class interface, dispinterface
var
p: PChar;
begin
if StartPos>SrcLen then exit(false);
p:=@Src[StartPos];
case UpChars[p^] of
'E': if CompareSrcIdentifiers(p,'END') then exit(false);
'F': if CompareSrcIdentifiers(p,'FUNCTION') then exit(KeyWordFuncClassMethod);
'P':
if (UpChars[p[1]]='R') and (UpChars[p[2]]='O') then
case UpChars[p[3]] of
'C': if CompareSrcIdentifiers(p,'PROCEDURE') then exit(KeyWordFuncClassMethod);
'P': if CompareSrcIdentifiers(p,'PROPERTY') then exit(KeyWordFuncClassProperty);
end;
'(','[':
begin
ReadTilBracketClose(true);
exit(true);
end;
';': exit(true);
end;
Result:=false;
end;
function TPascalParserTool.UnexpectedKeyWord: boolean;
begin
Result:=false;
@ -804,7 +735,7 @@ function TPascalParserTool.KeyWordFuncClassIdentifier: boolean;
TCompareFunc = function(const Item1, Item2: T): Integer;
}
begin
if CurNode.Desc = ctnClassType then begin
if CurNode.Desc = ctnTypeSection then begin
// create type definition node
CreateChildNode;
CurNode.Desc:=ctnTypeDefinition;
@ -812,7 +743,7 @@ begin
CurNode.EndPos:=CurPos.EndPos;
EndChildNode;
end else
if CurNode.Desc = ctnClassConst then begin
if CurNode.Desc = ctnConstSection then begin
// create const definition node
CreateChildNode;
CurNode.Desc:=ctnConstDefinition;
@ -844,151 +775,15 @@ begin
Result:=true;
end;
function TPascalParserTool.KeyWordFuncClassVarTypeClass: boolean;
// class and object as type are not allowed, because they would have no name
begin
SaveRaiseExceptionFmt(ctsAnonymDefinitionsAreNotAllowed,[GetAtom]);
Result:=false;
end;
function TPascalParserTool.KeyWordFuncClassVarTypePacked: boolean;
// 'packed' record
begin
ReadNextAtom;
if UpAtomIs('RECORD') then
Result:=KeyWordFuncClassVarTypeRecord
else begin
RaiseStringExpectedButAtomFound('"record"');
Result:=true;
end;
end;
function TPascalParserTool.KeyWordFuncClassVarTypeBitPacked: boolean;
// 'bitpacked' array
begin
ReadNextAtom;
if UpAtomIs('ARRAY') then
Result:=KeyWordFuncClassVarTypeArray
else begin
RaiseStringExpectedButAtomFound('"array"');
Result:=true;
end;
end;
function TPascalParserTool.KeyWordFuncClassVarTypeRecord: boolean;
{ read variable type 'record'
examples:
record
i: packed record
j: integer;
k: record end;
case integer of
0: (a: integer);
1,2,3: (b: array[char] of char; c: char);
3: ( d: record
case byte of
10: (i: integer; );
11: (y: byte);
end;
end;
end;
}
var Level: integer;
begin
Level:=1;
while (CurPos.StartPos<=SrcLen) and (Level>0) do begin
ReadNextAtom;
if UpAtomIs('RECORD') then inc(Level)
else if (CurPos.Flag=cafEND) then dec(Level);
end;
if CurPos.StartPos>SrcLen then
SaveRaiseException(ctsEndForRecordNotFound);
Result:=true;
end;
function TPascalParserTool.KeyWordFuncClassVarTypeArray: boolean;
{ read variable type 'array'
examples:
array of array[EnumType] of array [Range] of TypeName;
}
begin
ReadNextAtom;
if CurPos.Flag=cafEdgedBracketOpen then begin
// array[Range]
ReadTilBracketClose(true);
ReadNextAtom;
end;
if not UpAtomIs('OF') then
RaiseCharExpectedButAtomFound('[');
ReadNextAtom;
Result:=ParseClassVarType(CurPos.StartPos,CurPos.EndPos-CurPos.StartPos);
end;
function TPascalParserTool.KeyWordFuncClassVarTypeSet: boolean;
{ read variable type 'set of'
examples:
set of Name
set of (MyEnummy4 := 4 , MyEnummy5);
}
begin
CreateChildNode;
CurNode.Desc:=ctnSetType;
ReadNextAtom;
if not UpAtomIs('OF') then
RaiseStringExpectedButAtomFound('"of"');
ReadNextAtom;
if CurPos.StartPos>SrcLen then
SaveRaiseException(ctsMissingEnumList);
if IsIdentStartChar[Src[CurPos.StartPos]] then
// set of identifier
else if CurPos.Flag=cafRoundBracketOpen then
// set of ()
ReadTilBracketClose(true);
CurNode.EndPos:=CurPos.EndPos;
EndChildNode;
Result:=true;
end;
function TPascalParserTool.KeyWordFuncClassVarTypeProc: boolean;
{ read variable type 'procedure ...' or 'function ... : ...'
examples:
procedure
function : integer;
procedure (a: char) of object;
}
var IsFunction, HasForwardModifier: boolean;
ParseAttr: TParseProcHeadAttributes;
begin
//DebugLn('[TPascalParserTool.KeyWordFuncClassVarTypeProc]');
IsFunction:=UpAtomIs('FUNCTION');
ReadNextAtom;
HasForwardModifier:=false;
ParseAttr:=[pphIsMethod,pphIsType];
if IsFunction then Include(ParseAttr,pphIsFunction);
ReadTilProcedureHeadEnd(ParseAttr,HasForwardModifier);
Result:=true;
end;
function TPascalParserTool.KeyWordFuncClassVarTypeIdent: boolean;
// read variable type <identifier>
begin
if CurPos.StartPos>SrcLen then
SaveRaiseException(ctsMissingTypeIdentifier);
if IsIdentStartChar[Src[CurPos.StartPos]] then
// identifier
else
SaveRaiseException(ctsMissingTypeIdentifier);
Result:=true;
end;
function TPascalParserTool.KeyWordFuncClassSection: boolean;
// change section in a class (public, private, protected, published)
begin
// end last section
if CurNode.Desc in AllClassSubSections then begin
// end sub section
CurNode.EndPos:=CurPos.StartPos;
EndChildNode;
end;
// end last visibility section
CurNode.EndPos:=CurPos.StartPos;
EndChildNode;
// start new section
@ -1009,23 +804,27 @@ end;
function TPascalParserTool.KeyWordFuncClassConstSection: boolean;
begin
// end last section
CurNode.EndPos:=CurPos.StartPos;
EndChildNode;
if CurNode.Desc in AllClassSubSections then begin
// end last sub section
CurNode.EndPos:=CurPos.StartPos;
EndChildNode;
end;
// start new section
CreateChildNode;
CurNode.Desc:=ctnClassConst;
CurNode.Desc:=ctnConstSection;
Result:=true;
end;
function TPascalParserTool.KeyWordFuncClassTypeSection: boolean;
begin
// end last section
CurNode.EndPos:=CurPos.StartPos;
EndChildNode;
if CurNode.Desc in AllClassSubSections then begin
// end last sub section
CurNode.EndPos:=CurPos.StartPos;
EndChildNode;
end;
// start new section
CreateChildNode;
CurNode.Desc:=ctnClassType;
CurNode.Desc:=ctnTypeSection;
Result:=true;
end;
@ -1035,9 +834,11 @@ function TPascalParserTool.KeyWordFuncClassVarSection: boolean;
class var
}
begin
// end last section
CurNode.EndPos:=CurPos.StartPos;
EndChildNode;
if CurNode.Desc in AllClassSubSections then begin
// end last sub section
CurNode.EndPos:=CurPos.StartPos;
EndChildNode;
end;
// start new section
CreateChildNode;
if UpAtomIs('CLASS') then
@ -1046,7 +847,7 @@ begin
ReadNextAtom;
end
else
CurNode.Desc:=ctnClassVar;
CurNode.Desc:=ctnVarSection;
Result:=true;
end;
@ -1100,7 +901,11 @@ function TPascalParserTool.KeyWordFuncClassMethod: boolean;
var IsFunction, HasForwardModifier: boolean;
ParseAttr: TParseProcHeadAttributes;
begin
if not (CurNode.Desc in (AllClassSections+AllClassInterfaces)) then
if (CurNode.Desc in AllClassSubSections)
and (CurNode.Parent.Desc in AllClassBaseSections) then begin
CurNode.EndPos:=CurPos.StartPos;
EndChildNode;
end else if not (CurNode.Desc in (AllClassBaseSections+AllClassInterfaces)) then
RaiseIdentExpectedButAtomFound;
HasForwardModifier:=false;
@ -2210,7 +2015,11 @@ function TPascalParserTool.KeyWordFuncClassProperty: boolean;
end;
begin
if not (CurNode.Desc in (AllClassBaseSections+AllClassInterfaces)) then
if (CurNode.Desc in AllClassSubSections)
and (CurNode.Parent.Desc in AllClassBaseSections) then begin
CurNode.EndPos:=CurPos.StartPos;
EndChildNode;
end else if not (CurNode.Desc in (AllClassBaseSections+AllClassInterfaces)) then
RaiseIdentExpectedButAtomFound;
// create class method node
CreateChildNode;
@ -2457,11 +2266,13 @@ begin
CurNode.SubDesc:=ctnsNeedJITParsing;
end;
ReadNextAtom;
if (CurSection<>ctnInterface) and (CurPos.Flag=cafPoint) then begin
// read procedure name of a class method (the name after the . )
ReadNextAtom;
AtomIsIdentifier(true);
ReadNextAtom;
if (CurSection<>ctnInterface) then begin
while (CurPos.Flag=cafPoint) do begin
// read procedure name of a class method (the name after the . )
ReadNextAtom;
AtomIsIdentifier(true);
ReadNextAtom;
end;
end;
// read rest of procedure head
HasForwardModifier:=false;
@ -3628,6 +3439,7 @@ var
ClassDesc: TCodeTreeNodeDesc;
ClassNode: TCodeTreeNode;
begin
//debugln(['TPascalParserTool.KeyWordFuncTypeClass ',GetAtom,' ',CleanPosToStr(CurPos.StartPos)]);
// class or 'class of' start found
if UpAtomIs('CLASS') then
ClassDesc:=ctnClass
@ -3740,6 +3552,11 @@ begin
end;
ReadNextAtom;
until false;
// end last sub section
if CurNode.Desc in AllClassSubSections then begin
CurNode.EndPos:=CurPos.StartPos;
EndChildNode;
end;
// end last class section (public, private, ...)
CurNode.EndPos:=CurPos.StartPos;
EndChildNode;
@ -3776,6 +3593,7 @@ begin
// place cursor on atom behind
if CurPos.Flag<>cafSemicolon then
ReadNextAtom;
//debugln(['TPascalParserTool.KeyWordFuncTypeClass END ',GetAtom,' ',CleanPosToStr(CurPos.StartPos)]);
Result:=true;
end;

View File

@ -89,7 +89,8 @@ type
Attr: TProcHeadAttributes): string;
function ExtractProcHead(ProcNode: TCodeTreeNode;
Attr: TProcHeadAttributes): string;
function ExtractClassNameOfProcNode(ProcNode: TCodeTreeNode): string;
function ExtractClassNameOfProcNode(ProcNode: TCodeTreeNode;
AddParentClasses: boolean = true): string;
function ProcNodeHasSpecifier(ProcNode: TCodeTreeNode;
ProcSpec: TProcedureSpecifier): boolean;
function GetProcNameIdentifier(ProcNode: TCodeTreeNode): PChar;
@ -125,15 +126,17 @@ type
// classes
function ExtractClassName(ClassNode: TCodeTreeNode;
InUpperCase: boolean): string;
InUpperCase: boolean; WithParents: boolean = true): string;
function ExtractClassInheritance(ClassNode: TCodeTreeNode;
Attr: TProcHeadAttributes): string;
function FindClassNode(StartNode: TCodeTreeNode;
const AClassName: string;
const AClassName: string; // nested: A.B
IgnoreForwards, IgnoreNonForwards: boolean): TCodeTreeNode;
function FindClassNodeBackwards(StartNode: TCodeTreeNode;
const AClassName: string;
IgnoreForwards, IgnoreNonForwards: boolean): TCodeTreeNode;
function FindNestedClass(RootClassNode: TCodeTreeNode;
AClassName: PChar; SkipFirst: boolean): TCodeTreeNode;
function FindClassNode(CursorNode: TCodeTreeNode): TCodeTreeNode;
function FindClassNodeForMethodBody(ProcNode: TCodeTreeNode;
IgnoreForwards, IgnoreNonForwards: boolean): TCodeTreeNode;
@ -180,7 +183,7 @@ type
function ExtractArrayRange(ArrayNode: TCodeTreeNode;
Attr: TProcHeadAttributes): string;
// sections
// module sections
function GetSourceName(DoBuildTree: boolean = true): string;
function GetSourceType: TCodeTreeNodeDesc;
function GetSourceNamePos(var NamePos: TAtomPosition): boolean;
@ -341,6 +344,7 @@ function TPascalReaderTool.ExtractProcName(ProcNode: TCodeTreeNode;
Attr: TProcHeadAttributes): string;
var
ProcHeadNode: TCodeTreeNode;
Part: String;
begin
Result:='';
if [phpWithoutClassName,phpWithoutName]*Attr=
@ -353,39 +357,34 @@ begin
ProcHeadNode:=ProcNode.FirstChild;
if (ProcHeadNode=nil) or (ProcHeadNode.StartPos<1) then exit;
MoveCursorToNodeStart(ProcHeadNode);
ReadNextAtom;
if not AtomIsIdentifier(false) then exit;
if phpInUpperCase in Attr then
Result:=GetUpAtom
else
Result:=GetAtom;
ReadNextAtom;
if (CurPos.Flag=cafPoint) then begin
if (phpWithoutClassName in Attr) then begin
Result:='';
end else begin
if not (phpWithoutName in Attr) then
Result:=Result+'.';
end;
repeat
ReadNextAtom;
if not (phpWithoutName in Attr) then begin
if phpInUpperCase in Attr then
Result:=Result+GetUpAtom
else
Result:=Result+GetAtom;
if not AtomIsIdentifier(false) then exit;
if phpInUpperCase in Attr then
Part:=GetUpAtom
else
Part:=GetAtom;
ReadNextAtom;
if (CurPos.Flag<>cafPoint) then begin
// end of method identifier is the proc name
if phpWithoutName in Attr then exit;
if Result<>'' then Result:=Result+'.';
Result:=Result+Part;
exit;
end;
end else begin
if phpWithoutName in Attr then
Result:='';
end;
if not (phpWithoutClassName in Attr) then begin
// in front of . is class name
if Result<>'' then Result:=Result+'.';
Result:=Result+Part;
end;
until false;
end;
function TPascalReaderTool.ExtractProcHead(ProcNode: TCodeTreeNode;
Attr: TProcHeadAttributes): string;
var
TypeDefNode: TCodeTreeNode;
TheClassName, s: string;
HasClassName, IsProcType: boolean;
IsClassName, IsProcType: boolean;
IsProcedure: Boolean;
IsFunction: Boolean;
IsOperator: Boolean;
@ -402,15 +401,14 @@ begin
if (ProcNode.Desc<>ctnProcedure) and (ProcNode.Desc<>ctnProcedureType) then
exit;
IsProcType:=(ProcNode.Desc=ctnProcedureType);
if (phpAddClassname in Attr) then begin
TheClassName:='';
TypeDefNode:=FindClassOrInterfaceNode(ProcNode);
if TypeDefNode<>nil then begin
TheClassName:=ExtractClassName(TypeDefNode,phpInUpperCase in Attr);
end;
end;
InitExtraction;
// build full class name
TheClassName:='';
if ([phpAddClassname,phpWithoutClassName]*Attr=[phpAddClassName]) then
TheClassName:=ExtractClassName(ProcNode,phpInUpperCase in Attr,true);
// reparse the clean source
InitExtraction;
MoveCursorToNodeStart(ProcNode);
// parse procedure head = start + name + parameterlist + result type ;
ExtractNextAtom(false,Attr);
@ -431,32 +429,41 @@ begin
if not IsProcType then begin
// read name
if (not IsOperator) and (not AtomIsIdentifier(false)) then exit;
ReadNextAtom;
HasClassName:=(CurPos.Flag=cafPoint);
UndoReadNextAtom;
if HasClassName then begin
// read class name
ExtractNextAtom(not (phpWithoutClassName in Attr),Attr);
// read '.'
ExtractNextAtom(not (phpWithoutClassName in Attr),Attr);
// read name
if not AtomIsIdentifier(false) then exit;
ExtractNextAtom(not (phpWithoutName in Attr),Attr);
if TheClassName<>'' then begin
s:=TheClassName+'.';
if phpInUpperCase in Attr then s:=UpperCaseStr(s);
if ExtractStreamEndIsIdentChar then
s:=' '+s;
ExtractMemStream.Write(s[1],length(s));
end;
if [phpWithoutClassName,phpWithoutName]*Attr=[] then begin
// read classname and name
repeat
ExtractNextAtom(true,Attr);
if CurPos.Flag<>cafPoint then break;
ExtractNextAtom(true,Attr);
if not AtomIsIdentifier(false) then exit;
until false;
end else begin
// read name
if (not (phpAddClassname in Attr)) or (TheClassName='') then begin
ExtractNextAtom(not (phpWithoutName in Attr),Attr);
end else begin
// add class name
s:=TheClassName+'.';
if not (phpWithoutName in Attr) then
s:=s+GetAtom;
ExtractNextAtom(false,Attr);
if phpInUpperCase in Attr then s:=UpperCaseStr(s);
if ExtractStreamEndIsIdentChar then
s:=' '+s;
ExtractMemStream.Write(s[1],length(s));
end;
// read only part of name
repeat
ReadNextAtom;
IsClassName:=(CurPos.Flag=cafPoint);
UndoReadNextAtom;
if IsClassName then begin
// read class name
ExtractNextAtom(not (phpWithoutClassName in Attr),Attr);
// read '.'
ExtractNextAtom(not (phpWithoutClassName in Attr),Attr);
if not AtomIsIdentifier(false) then break;
end else begin
// read name
ExtractNextAtom(not (phpWithoutName in Attr),Attr);
break;
end;
until false;
end;
ExtractProcHeadPos:=phepName;
end;
@ -526,31 +533,23 @@ begin
end;
function TPascalReaderTool.ExtractClassName(ClassNode: TCodeTreeNode;
InUpperCase: boolean): string;
var
DefNode: TCodeTreeNode;
InUpperCase, WithParents: boolean): string;
begin
if ClassNode<>nil then begin
ClassNode:=FindClassOrInterfaceNode(ClassNode);
if (ClassNode = nil) then begin
Result := '';
Exit;
Result:='';
while ClassNode<>nil do begin
if ClassNode.Desc in [ctnTypeDefinition,ctnGenericType] then begin
if Result<>'' then Result:='.'+Result;
if ClassNode.Desc=ctnTypeDefinition then
Result:=GetIdentifier(@Src[ClassNode.StartPos])+Result
else if ClassNode.FirstChild<>nil then
Result:=GetIdentifier(@Src[ClassNode.FirstChild.StartPos])+Result;
if not WithParents then break;
end;
ClassNode:=ClassNode.Parent;
end;
DefNode:=ClassNode.Parent;
if (DefNode<>nil) and (DefNode.Desc=ctnGenericType) then
DefNode:=DefNode.FirstChild;
if DefNode=nil then begin
Result:='';
exit;
end;
if InUpperCase then
Result:=UpperCaseStr(GetIdentifier(@Src[DefNode.StartPos]))
else
Result:=GetIdentifier(@Src[DefNode.StartPos]);
end else
Result:='';
if InUpperCase then
Result:=UpperCaseStr(Result);
end;
function TPascalReaderTool.ExtractClassInheritance(
@ -582,23 +581,29 @@ begin
Result:=GetExtraction(phpInUpperCase in Attr);
end;
function TPascalReaderTool.ExtractClassNameOfProcNode(ProcNode: TCodeTreeNode
): string;
var TheClassName: string;
function TPascalReaderTool.ExtractClassNameOfProcNode(ProcNode: TCodeTreeNode;
AddParentClasses: boolean): string;
var
Part: String;
begin
Result:='';
if (ProcNode<>nil) and (ProcNode.Desc=ctnProcedure) then
ProcNode:=ProcNode.FirstChild;
if (ProcNode=nil) or (ProcNode.Desc<>ctnProcedureHead) then exit;
MoveCursorToNodeStart(ProcNode);
ReadNextAtom;
if not AtomIsIdentifier(false) then exit;
TheClassName:=GetAtom;
ReadNextAtom;
if (CurPos.Flag<>cafPoint) then exit;
ReadNextAtom;
if not AtomIsIdentifier(false) then exit;
Result:=TheClassName;
repeat
ReadNextAtom;
if not AtomIsIdentifier(false) then break;
Part:=GetAtom;
ReadNextAtom;
if (CurPos.Flag<>cafPoint) then break;
if Result<>'' then Result:=Result+'.';
Result:=Result+Part;
until false;
if not AddParentClasses then exit;
Part:=ExtractClassName(ProcNode,false,true);
if Part='' then exit;
Result:=Part+'.'+Result;
end;
function TPascalReaderTool.FindProcNode(StartNode: TCodeTreeNode;
@ -658,8 +663,8 @@ begin
end else if NodeIsMethodBody(ProcNode) then begin
//debugln('TPascalReaderTool.FindCorrespondingProcNode Method ',ExtractClassNameOfProcNode(ProcNode));
// in a method body -> search in class
StartNode:=FindClassNodeInUnit(ExtractClassNameOfProcNode(ProcNode),true,
false,false,true);
StartNode:=FindClassNodeInUnit(ExtractClassNameOfProcNode(ProcNode,true),
true,false,false,true);
if StartNode=nil then exit;
if (StartNode<>nil) and (StartNode.Desc in AllClasses)
then begin
@ -866,50 +871,43 @@ begin
if UpAtomIs('CLASS') then ReadNextAtom;
ReadNextAtom; // skip proc keyword
end;
if SkipClassName then begin
if not SkipClassName then exit;
repeat
ReadNextAtom;
if CurPos.Flag=cafPoint then
ReadNextAtom
else
if CurPos.Flag<>cafPoint then begin
UndoReadNextAtom;
end;
break;
end;
ReadNextAtom;
until not AtomIsIdentifier(false);
end;
function TPascalReaderTool.PositionInProcName(ProcNode: TCodeTreeNode;
SkipClassName: boolean; CleanPos: integer): boolean;
var
InFirstAtom: Boolean;
begin
if (ProcNode.Desc=ctnProcedure) and (ProcNode.FirstChild<>nil)
and (ProcNode.FirstChild.Desc=ctnProcedureHead) then
ProcNode:=ProcNode.FirstChild;
if (CleanPos<ProcNode.StartPos) or (CleanPos>ProcNode.EndPos) then exit(false);
MoveCursorToNodeStart(ProcNode);
ReadNextAtom;
if (ProcNode.Desc=ctnProcedure) then begin
if UpAtomIs('CLASS') then ReadNextAtom;
ReadNextAtom; // skip proc keyword
end;
if CurPos.Flag<>cafWord then exit(false);
// now CurPos is either the classname or the procname
InFirstAtom:=(CleanPos>=CurPos.StartPos) and (CleanPos<=CurPos.EndPos);
ReadNextAtom;
// read point
if CurPos.Flag<>cafPoint then begin
// procname without classname
exit(InFirstAtom);
if CleanPos<CurPos.StartPos then exit(false);
while CurPos.Flag=cafWord do begin
ReadNextAtom;
if CurPos.Flag<>cafPoint then begin
UndoReadNextAtom;
break;
end;
ReadNextAtom;
end;
// there is a classname
if (CleanPos>=CurPos.StartPos) and (CleanPos<=CurPos.EndPos)
and (not SkipClassName) then
exit(true); // position at point
// now read the procname
ReadNextAtom;
if CurPos.Flag<>cafWord then exit(false); // no valid procname
if (CleanPos>=CurPos.StartPos) and (CleanPos<=CurPos.EndPos) then
exit(true); // position at procname
if (not SkipClassName) and InFirstAtom then
exit(true); // position at classname
Result:=false;
// CurPos is now on the proc name
if CleanPos>CurPos.EndPos then exit(false);
if SkipClassName and (CleanPos<CurPos.StartPos) then exit(false);
Result:=true;
end;
function TPascalReaderTool.PositionInFuncResultName(ProcNode: TCodeTreeNode;
@ -938,14 +936,10 @@ begin
end else begin
MoveCursorToNodeStart(ProcNode);
ReadNextAtom;
if AtomIsIdentifier(false) then begin
// read name
while AtomIsIdentifier(false) do begin
ReadNextAtom;
if (CurPos.Flag<>cafPoint) then break;
ReadNextAtom;
if (CurPos.Flag=cafPoint) then begin
// read method name
ReadNextAtom;
ReadNextAtom;
end;
end;
if CurPos.Flag=cafRoundBracketOpen then
if not ReadTilBracketClose(false) then exit;
@ -1023,13 +1017,12 @@ begin
if ProcNode=nil then exit;
end;
MoveCursorToNodeStart(ProcNode);
ReadNextAtom;
if not AtomIsIdentifier(false) then exit;
Result:=@Src[CurPos.StartPos];
ReadNextAtom;
if not AtomIsChar('.') then exit;
ReadNextAtom;
Result:=@Src[CurPos.StartPos];
repeat
ReadNextAtom;
if not AtomIsIdentifier(false) then exit(nil);
Result:=@Src[CurPos.StartPos];
ReadNextAtom;
until CurPos.Flag<>cafPoint;
end;
function TPascalReaderTool.ExtractNode(ANode: TCodeTreeNode;
@ -1372,14 +1365,15 @@ end;
function TPascalReaderTool.FindClassNode(StartNode: TCodeTreeNode;
const AClassName: string; IgnoreForwards, IgnoreNonForwards: boolean
): TCodeTreeNode;
// search for types on same level,
// with type class and classname = SearchedClassName
// search for class like types on same level
var
ANode, CurClassNode: TCodeTreeNode;
NameNode: TCodeTreeNode;
p: PChar;
begin
ANode:=StartNode;
Result:=nil;
p:=PChar(AClassName);
while (ANode<>nil) do begin
if ANode.Desc in [ctnTypeDefinition,ctnGenericType] then begin
CurClassNode:=FindTypeNodeOfDefinition(ANode);
@ -1393,10 +1387,8 @@ begin
NameNode:=ANode;
if ANode.Desc=ctnGenericType then
NameNode:=ANode.FirstChild;
if CompareIdentifiers(PChar(Pointer(AClassName)),
@Src[NameNode.StartPos])=0
then begin
Result:=CurClassNode;
if CompareIdentifiers(p,@Src[NameNode.StartPos])=0 then begin
Result:=FindNestedClass(CurClassNode,p,true);
exit;
end;
end;
@ -1429,8 +1421,10 @@ function TPascalReaderTool.FindClassNodeBackwards(StartNode: TCodeTreeNode;
var
ANode: TCodeTreeNode;
CurClassNode: TCodeTreeNode;
p: PChar;
begin
ANode:=StartNode;
p:=PChar(AClassName);
while ANode<>nil do begin
if ANode.Desc=ctnTypeDefinition then begin
CurClassNode:=ANode.FirstChild;
@ -1441,10 +1435,8 @@ begin
and (not (IgnoreNonForwards
and ((CurClassNode.SubDesc and ctnsForwardDeclaration)=0)))
then begin
if CompareIdentifiers(PChar(Pointer(AClassName)),
@Src[ANode.StartPos])=0
then begin
Result:=CurClassNode;
if CompareIdentifiers(p,@Src[ANode.StartPos])=0 then begin
Result:=FindNestedClass(CurClassNode,p,true);
exit;
end;
end;
@ -1463,6 +1455,53 @@ begin
Result:=nil;
end;
function TPascalReaderTool.FindNestedClass(RootClassNode: TCodeTreeNode;
AClassName: PChar; SkipFirst: boolean): TCodeTreeNode;
var
p: PChar;
Node: TCodeTreeNode;
EndNode: TCodeTreeNode;
begin
Result:=nil;
if RootClassNode=nil then exit;
if AClassName=nil then exit;
p:=AClassName;
if SkipFirst then begin
while IsIdentChar[p^] do inc(p);
if p^=#0 then exit(RootClassNode);
if p^<>'.' then exit;
inc(p);
end;
//debugln(['TPascalReaderTool.FindNestedClass p="',p,'"']);
if not IsIdentStartChar[p^] then exit;
EndNode:=RootClassNode.NextSkipChilds;
Node:=RootClassNode.Next;
while Node<>EndNode do begin
// debugln(['TPascalReaderTool.FindNestedClass Node=',node.DescAsString]);
if Node.Desc in [ctnTypeDefinition,ctnGenericType] then begin
if (Node.LastChild<>nil) and (Node.LastChild.Desc in AllClasses) then begin
if ((Node.Desc=ctnTypeDefinition)
and (CompareIdentifierPtrs(p,@Src[Node.StartPos])=0))
or ((Node.FirstChild.Desc=ctnGenericName)
and (CompareIdentifierPtrs(p,@Src[Node.FirstChild.StartPos])=0))
then begin
// class found
Node:=Node.LastChild;
while IsIdentChar[p^] do inc(p);
if p^=#0 then exit(Node);
if p^<>'.' then exit;
Result:=FindNestedClass(Node,p+1,false);
exit;
end;
end;
end;
if Node.Desc in AllClassSections then
Node:=Node.Next
else
Node:=Node.NextSkipChilds;
end;
end;
function TPascalReaderTool.FindClassNode(CursorNode: TCodeTreeNode
): TCodeTreeNode;
begin
@ -1485,7 +1524,7 @@ var
ProcClassName: String;
begin
Result:=nil;
ProcClassName:=ExtractClassNameOfProcNode(ProcNode);
ProcClassName:=ExtractClassNameOfProcNode(ProcNode,true);
if ProcClassName='' then exit;
Result:=FindClassNodeBackwards(ProcNode,ProcClassName,IgnoreForwards,
IgnoreNonForwards);
@ -1757,7 +1796,10 @@ begin
if ProcNode.Desc=ctnProcedureHead then
ProcNode:=ProcNode.Parent;
if ProcNode.Desc<>ctnProcedure then exit;
Result:=CompareIdentifiers('operator',@Src[ProcNode.StartPos])=0;
MoveCursorToNodeStart(ProcNode);
ReadNextAtom;
if UpAtomIs('CLASS') then ReadNextAtom;
Result:=UpAtomIs('OPERATOR');
end;
function TPascalReaderTool.NodeIsResultIdentifier(Node: TCodeTreeNode
@ -2161,12 +2203,12 @@ begin
ProcNode:=ProcNode.FirstChild;
MoveCursorToNodeStart(ProcNode);
ReadNextAtom; // read name
ReadNextAtom;
if AtomIsChar('.') then begin
while CurPos.Flag=cafWord do begin
ReadNextAtom;
if CurPos.Flag<>cafPoint then break;
ReadNextAtom;
end;
Result:=AtomIsChar('(');
Result:=CurPos.Flag=cafRoundBracketOpen;
end;
procedure TPascalReaderTool.MoveCursorToUsesStart(UsesNode: TCodeTreeNode);

View File

@ -2321,12 +2321,12 @@ var
if (IdentContext.Node<>nil) and IdentifierNotPublished then begin
LFMTree.AddError(lfmeIdentifierNotPublished,LFMNode,
'identifier '+IdentName+' is not published in class '
+'"'+ClassContext.Tool.ExtractClassName(ClassContext.Node,false)+'"',
+'"'+ClassContext.Tool.ExtractClassName(ClassContext.Node,false,true)+'"',
DefaultErrorPosition);
end else begin
LFMTree.AddError(lfmeIdentifierNotFound,LFMNode,
'identifier '+IdentName+' not found in class '
+'"'+ClassContext.Tool.ExtractClassName(ClassContext.Node,false)+'"',
+'"'+ClassContext.Tool.ExtractClassName(ClassContext.Node,false,true)+'"',
DefaultErrorPosition);
end;
end;

View File

@ -1105,7 +1105,7 @@ begin
end;
end;
ctnClassConst..ctnClassPublished:
ctnClassClassVar..ctnClassPublished:
begin
if (cefcUnsortedClassVisibility in ObserverCats)
and (CodeNode.PriorBrother<>nil)
@ -2212,24 +2212,25 @@ const
ctnTypeSection,
ctnTypeDefinition,ctnGenericType:
Result:=1;
ctnVarSection,ctnConstSection,ctnResStrSection,ctnLabelSection,
ctnVarDefinition,ctnConstDefinition,ctnProperty:
ctnConstSection,ctnConstDefinition:
Result:=2;
ctnVarSection,ctnClassClassVar,ctnResStrSection,ctnLabelSection,
ctnVarDefinition:
Result:=3;
ctnInterface,ctnImplementation,ctnProgram,ctnPackage,ctnLibrary,
ctnProcedure:
Result:=3;
ctnUsesSection:
Result:=4;
ctnProperty:
Result:=5;
ctnUsesSection:
Result:=6;
// class sections
ctnClassConst,
ctnClassType,
ctnClassVar,
ctnClassClassVar,
ctnClassGUID,
ctnClassPrivate,
ctnClassProtected,
ctnClassPublic,
ctnClassPublished : Result:=Desc-ctnClassConst;
ctnClassPublished : Result:=Desc-ctnClassGUID;
else Result:=10000;
end;