mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-09 19:35:57 +02:00
codetools: started checking type unitnames
This commit is contained in:
parent
debb889759
commit
35a67fba04
@ -63,7 +63,7 @@ type
|
|||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure Unbind;
|
procedure Unbind;
|
||||||
procedure AddChild(ANode: TLFMTreeNode);
|
procedure AddChild(ANode: TLFMTreeNode);
|
||||||
function GetIdentifier: string;
|
function GetIdentifier: string; virtual;
|
||||||
procedure FindIdentifier(out IdentStart, IdentEnd: integer);
|
procedure FindIdentifier(out IdentStart, IdentEnd: integer);
|
||||||
function GetPath: string;
|
function GetPath: string;
|
||||||
function Next(SkipChildren: Boolean = False): TLFMTreeNode;
|
function Next(SkipChildren: Boolean = False): TLFMTreeNode;
|
||||||
@ -89,6 +89,8 @@ type
|
|||||||
AncestorNode: TObject; // TCodeTreeNode
|
AncestorNode: TObject; // TCodeTreeNode
|
||||||
AncestorContextValid: boolean;
|
AncestorContextValid: boolean;
|
||||||
constructor CreateVirtual; override;
|
constructor CreateVirtual; override;
|
||||||
|
function GetFullName(UnitNameSep: char = '/'; WithName: boolean = true): string;
|
||||||
|
function GetIdentifier: string; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TLFMNameParts }
|
{ TLFMNameParts }
|
||||||
@ -823,7 +825,7 @@ begin
|
|||||||
while not Parser.TokenSymbolIs('END') do begin
|
while not Parser.TokenSymbolIs('END') do begin
|
||||||
if Parser.Token=toEOF then begin
|
if Parser.Token=toEOF then begin
|
||||||
Parser.Error('END not found for'
|
Parser.Error('END not found for'
|
||||||
+' object='+ObjectNode.Name+':'+ObjectNode.TypeName
|
+' object='+ObjectNode.GetFullName
|
||||||
+' starting at line '+IntToStr(ObjectStartLine));
|
+' starting at line '+IntToStr(ObjectStartLine));
|
||||||
end;
|
end;
|
||||||
ProcessObject;
|
ProcessObject;
|
||||||
@ -1015,6 +1017,29 @@ end;
|
|||||||
constructor TLFMObjectNode.CreateVirtual;
|
constructor TLFMObjectNode.CreateVirtual;
|
||||||
begin
|
begin
|
||||||
TheType:=lfmnObject;
|
TheType:=lfmnObject;
|
||||||
|
ChildPos:=-1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLFMObjectNode.GetFullName(UnitNameSep: char; WithName: boolean
|
||||||
|
): string;
|
||||||
|
begin
|
||||||
|
Result:=TypeUnitName;
|
||||||
|
if TypeName<>'' then begin
|
||||||
|
if Result<>'' then
|
||||||
|
Result:=Result+UnitNameSep+TypeName
|
||||||
|
else
|
||||||
|
Result:=TypeName;
|
||||||
|
end;
|
||||||
|
if (not WithName) or (Name='') then exit;
|
||||||
|
if Result<>'' then
|
||||||
|
Result:=Name+':'+Result
|
||||||
|
else
|
||||||
|
Result:=Name+':MissingLFMType';
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLFMObjectNode.GetIdentifier: string;
|
||||||
|
begin
|
||||||
|
Result:=GetFullName;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TLFMPropertyNode }
|
{ TLFMPropertyNode }
|
||||||
@ -1207,11 +1232,23 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TLFMError.IsMissingObjectType: boolean;
|
function TLFMError.IsMissingObjectType: boolean;
|
||||||
|
var
|
||||||
|
ObjNode: TLFMObjectNode;
|
||||||
begin
|
begin
|
||||||
Result:=(ErrorType in [lfmeIdentifierNotFound,lfmeMissingRoot])
|
Result:=(ErrorType in [lfmeIdentifierNotFound,lfmeMissingRoot])
|
||||||
and (Node is TLFMObjectNode)
|
and (Node is TLFMObjectNode);
|
||||||
and (TLFMObjectNode(Node).TypeName<>'')
|
if not Result then exit;
|
||||||
and (TLFMObjectNode(Node).TypeNamePosition=Position);
|
ObjNode:=TLFMObjectNode(Node);
|
||||||
|
if ObjNode.TypeName='' then
|
||||||
|
exit(false);
|
||||||
|
if (Position>=ObjNode.TypeNamePosition)
|
||||||
|
and (Position<ObjNode.TypeNamePosition+length(ObjNode.TypeName)) then
|
||||||
|
exit(true);
|
||||||
|
if (ObjNode.TypeUnitName<>'')
|
||||||
|
and (Position>=ObjNode.TypeUnitNamePosition)
|
||||||
|
and (Position<ObjNode.TypeUnitNamePosition+length(ObjNode.TypeUnitName)) then
|
||||||
|
exit(true);
|
||||||
|
Result:=false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TLFMError.GetNodePath: string;
|
function TLFMError.GetNodePath: string;
|
||||||
|
@ -2434,17 +2434,54 @@ var
|
|||||||
Result:=Result+'('+IntToStr(Caret.Y)+','+IntToStr(Caret.X)+')';
|
Result:=Result+'('+IntToStr(Caret.Y)+','+IntToStr(Caret.X)+')';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function FindClassContext(const ClassName: string): TFindContext;
|
function FindClassContext(LFMObject: TLFMObjectNode): TFindContext;
|
||||||
var
|
var
|
||||||
Params: TFindDeclarationParams;
|
Params: TFindDeclarationParams;
|
||||||
Identifier: PChar;
|
Identifier: PChar;
|
||||||
OldInput: TFindDeclarationInput;
|
OldInput: TFindDeclarationInput;
|
||||||
StartTool: TStandardCodeTool;
|
StartTool: TStandardCodeTool;
|
||||||
|
aClassName: String;
|
||||||
begin
|
begin
|
||||||
Result:=CleanFindContext;
|
Result:=CleanFindContext;
|
||||||
|
aClassName:=LFMObject.TypeName;
|
||||||
|
|
||||||
|
if LFMObject.TypeUnitName<>'' then begin
|
||||||
|
// type with unitname
|
||||||
|
// -> search unit
|
||||||
|
try
|
||||||
|
Result.Tool:=FindCodeToolForUsedUnit(LFMObject.TypeUnitName,'',true);
|
||||||
|
except
|
||||||
|
// ignore search/parse errors
|
||||||
|
on E: ECodeToolError do ;
|
||||||
|
end;
|
||||||
|
if Result.Tool=nil then begin
|
||||||
|
LFMTree.AddError(lfmeIdentifierNotFound,LFMObject,
|
||||||
|
'unit '+LFMObject.TypeUnitName+' not found',LFMObject.TypeUnitNamePosition);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// -> search class in unit interface
|
||||||
|
try
|
||||||
|
Result.Node:=Result.Tool.FindClassNodeInUnit(aClassName,true,false,true,false);
|
||||||
|
except
|
||||||
|
// ignore search/parse errors
|
||||||
|
on E: ECodeToolError do ;
|
||||||
|
end;
|
||||||
|
if (Result.Node=nil)
|
||||||
|
or (not (Result.Node.Desc in AllClasses)) then begin
|
||||||
|
Result.Tool:=nil;
|
||||||
|
LFMTree.AddError(lfmeIdentifierNotFound,LFMObject,
|
||||||
|
'type '+aClassName+' not found',LFMObject.TypeNamePosition);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// type without explicit unitname -> find declaration
|
||||||
Params:=TFindDeclarationParams.Create;
|
Params:=TFindDeclarationParams.Create;
|
||||||
StartTool:=Self;
|
StartTool:=Self;
|
||||||
Identifier:=PChar(Pointer(ClassName));
|
Identifier:=PChar(Pointer(aClassName));
|
||||||
try
|
try
|
||||||
Params.Flags:=[fdfExceptionOnNotFound,
|
Params.Flags:=[fdfExceptionOnNotFound,
|
||||||
fdfSearchInParentNodes,
|
fdfSearchInParentNodes,
|
||||||
@ -2460,13 +2497,17 @@ var
|
|||||||
Params.Load(OldInput,true);
|
Params.Load(OldInput,true);
|
||||||
Result:=Params.NewCodeTool.FindBaseTypeOfNode(Params,Params.NewNode);
|
Result:=Params.NewCodeTool.FindBaseTypeOfNode(Params,Params.NewNode);
|
||||||
if (Result.Node=nil)
|
if (Result.Node=nil)
|
||||||
or (not (Result.Node.Desc in AllClasses)) then
|
or (not (Result.Node.Desc in AllClasses)) then
|
||||||
Result:=CleanFindContext;
|
Result:=CleanFindContext;
|
||||||
end;
|
end;
|
||||||
except
|
except
|
||||||
// ignore search/parse errors
|
// ignore search/parse errors
|
||||||
on E: ECodeToolError do ;
|
on E: ECodeToolError do ;
|
||||||
end;
|
end;
|
||||||
|
if Result.Node=nil then begin
|
||||||
|
LFMTree.AddError(lfmeIdentifierNotFound,LFMObject,
|
||||||
|
'type '+aClassName+' not found',LFMObject.TypeNamePosition);
|
||||||
|
end;
|
||||||
finally
|
finally
|
||||||
Params.Free;
|
Params.Free;
|
||||||
end;
|
end;
|
||||||
@ -2503,7 +2544,7 @@ var
|
|||||||
begin
|
begin
|
||||||
if ChildContext.Node=nil then begin
|
if ChildContext.Node=nil then begin
|
||||||
// this is an extra entry, created via DefineProperties.
|
// this is an extra entry, created via DefineProperties.
|
||||||
// There is no generic way to test such things
|
// this depends on the runtime class, so codetools cannot check it
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2541,11 +2582,12 @@ var
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// ToDo: check if variable/property type exists
|
if LFMObject.TypeUnitName<>'' then begin
|
||||||
|
// ToDo: check unitname
|
||||||
|
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
// find class node
|
// find class node
|
||||||
//debugln(['CheckLFMChildObject searching class node: LFMObjectName="',LFMObjectName,'" ',FindContextToString(CreateFindContext(ChildContext.Tool,DefinitionNode))]);
|
//debugln(['CheckLFMChildObject searching class node: LFMObjectName="',LFMObjectName,'" ',FindContextToString(CreateFindContext(ChildContext.Tool,DefinitionNode))]);
|
||||||
ClassContext:=FindClassNodeForLFMObject(LFMObject,LFMObject.TypeNamePosition,
|
ClassContext:=FindClassNodeForLFMObject(LFMObject,LFMObject.TypeNamePosition,
|
||||||
@ -2553,12 +2595,8 @@ var
|
|||||||
//debugln(['CheckLFMChildObject LFMObjectName="',LFMObjectName,'" class context: ',FindContextToString(ClassContext)]);
|
//debugln(['CheckLFMChildObject LFMObjectName="',LFMObjectName,'" class context: ',FindContextToString(ClassContext)]);
|
||||||
end else begin
|
end else begin
|
||||||
// try the object type
|
// try the object type
|
||||||
ClassContext:=FindClassContext(LFMObject.TypeName);
|
ClassContext:=FindClassContext(LFMObject);
|
||||||
if ClassContext.Node=nil then begin
|
if ClassContext.Node=nil then exit;
|
||||||
// object type not found
|
|
||||||
LFMTree.AddError(lfmeIdentifierNotFound,LFMObject,
|
|
||||||
'type '+LFMObject.TypeName+' not found',LFMObject.TypeNamePosition);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
// check child LFM nodes
|
// check child LFM nodes
|
||||||
if ClassContext.Node<>nil then
|
if ClassContext.Node<>nil then
|
||||||
@ -2672,7 +2710,7 @@ var
|
|||||||
function CheckLFMRoot(RootLFMNode: TLFMTreeNode): boolean;
|
function CheckLFMRoot(RootLFMNode: TLFMTreeNode): boolean;
|
||||||
var
|
var
|
||||||
LookupRootLFMNode: TLFMObjectNode;
|
LookupRootLFMNode: TLFMObjectNode;
|
||||||
LookupRootTypeName: String;
|
LookupRootTypeName, LookupRootTypeUnitName, CurUnitName: String;
|
||||||
RootClassNode: TCodeTreeNode;
|
RootClassNode: TCodeTreeNode;
|
||||||
begin
|
begin
|
||||||
Result:=false;
|
Result:=false;
|
||||||
@ -2693,6 +2731,19 @@ var
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// find root type
|
// find root type
|
||||||
|
LookupRootTypeUnitName:=LookupRootLFMNode.TypeUnitName;
|
||||||
|
if LookupRootTypeUnitName<>'' then begin
|
||||||
|
CurUnitName:=GetSourceName(false);
|
||||||
|
if SameText(CurUnitName,LookupRootTypeUnitName) then begin
|
||||||
|
// unitname fits
|
||||||
|
end else if RootMustBeClassInIntf or RootMustBeClassInUnit then begin
|
||||||
|
LFMTree.AddError(lfmeMissingRoot,LookupRootLFMNode,
|
||||||
|
'unitname '+LookupRootLFMNode.TypeUnitName+' mismatch',
|
||||||
|
LookupRootLFMNode.TypeUnitNamePosition);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
if RootMustBeClassInIntf then begin
|
if RootMustBeClassInIntf then begin
|
||||||
RootClassNode:=FindClassNodeInInterface(LookupRootTypeName,true,false,false);
|
RootClassNode:=FindClassNodeInInterface(LookupRootTypeName,true,false,false);
|
||||||
RootContext:=CleanFindContext;
|
RootContext:=CleanFindContext;
|
||||||
@ -2704,8 +2755,9 @@ var
|
|||||||
RootContext.Node:=RootClassNode;
|
RootContext.Node:=RootClassNode;
|
||||||
RootContext.Tool:=Self;
|
RootContext.Tool:=Self;
|
||||||
end else begin
|
end else begin
|
||||||
RootContext:=FindClassContext(LookupRootTypeName);
|
RootContext:=FindClassContext(LookupRootLFMNode);
|
||||||
RootClassNode:=RootContext.Node;
|
RootClassNode:=RootContext.Node;
|
||||||
|
if RootClassNode=nil then exit;
|
||||||
end;
|
end;
|
||||||
if RootClassNode=nil then begin
|
if RootClassNode=nil then begin
|
||||||
LFMTree.AddError(lfmeMissingRoot,LookupRootLFMNode,
|
LFMTree.AddError(lfmeMissingRoot,LookupRootLFMNode,
|
||||||
|
@ -294,7 +294,7 @@ begin
|
|||||||
AddControls;
|
AddControls;
|
||||||
AddFormUnit(['Button1: TButton']);
|
AddFormUnit(['Button1: TButton']);
|
||||||
FLFMCode:=AddSource('unit1.lfm',LinesToStr([
|
FLFMCode:=AddSource('unit1.lfm',LinesToStr([
|
||||||
'object Form1: Controls/TForm1',
|
'object Form1: unit1/TForm1',
|
||||||
' object Button1: Controls/TButton',
|
' object Button1: Controls/TButton',
|
||||||
' end',
|
' end',
|
||||||
'end'
|
'end'
|
||||||
|
Loading…
Reference in New Issue
Block a user