mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-02 13:19:49 +01:00
codetools: implemented finding the expression type of a constant
git-svn-id: trunk@9584 -
This commit is contained in:
parent
6df73a9fb9
commit
ab98d4268e
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -62,6 +62,8 @@ components/codetools/directorycacher.pas svneol=native#text/plain
|
||||
components/codetools/eventcodetool.pas svneol=native#text/pascal
|
||||
components/codetools/examples/addmethod.lpi svneol=native#text/plain
|
||||
components/codetools/examples/addmethod.lpr svneol=native#text/plain
|
||||
components/codetools/examples/codecompletion.lpi svneol=native#text/plain
|
||||
components/codetools/examples/codecompletion.lpr svneol=native#text/plain
|
||||
components/codetools/examples/finddeclaration.lpi svneol=native#text/plain
|
||||
components/codetools/examples/finddeclaration.lpr svneol=native#text/plain
|
||||
components/codetools/examples/fixfilenames.lpi svneol=native#text/plain
|
||||
@ -73,6 +75,7 @@ components/codetools/examples/methodjumping.pas svneol=native#text/plain
|
||||
components/codetools/examples/scanexamples/BigLettersUnit.pas svneol=native#text/plain
|
||||
components/codetools/examples/scanexamples/brokenfilenames.pas svneol=native#text/plain
|
||||
components/codetools/examples/scanexamples/brokenincfiles.inc svneol=native#text/plain
|
||||
components/codetools/examples/scanexamples/completion1.pas svneol=native#text/plain
|
||||
components/codetools/examples/scanexamples/empty.inc svneol=native#text/plain
|
||||
components/codetools/examples/scanexamples/getcontextexample.pas svneol=native#text/plain
|
||||
components/codetools/examples/scanexamples/simpleunit1.pas svneol=native#text/plain
|
||||
|
||||
@ -175,7 +175,7 @@ type
|
||||
public
|
||||
constructor Create;
|
||||
function CompleteCode(CursorPos: TCodeXYPosition; OldTopLine: integer;
|
||||
var NewPos: TCodeXYPosition; var NewTopLine: integer;
|
||||
out NewPos: TCodeXYPosition; out NewTopLine: integer;
|
||||
SourceChangeCache: TSourceChangeCache): boolean;
|
||||
function AddPublishedVariable(const UpperClassName,VarName, VarType: string;
|
||||
SourceChangeCache: TSourceChangeCache): boolean; override;
|
||||
@ -2418,7 +2418,7 @@ begin
|
||||
end;
|
||||
|
||||
function TCodeCompletionCodeTool.CompleteCode(CursorPos: TCodeXYPosition;
|
||||
OldTopLine: integer; var NewPos: TCodeXYPosition; var NewTopLine: integer;
|
||||
OldTopLine: integer; out NewPos: TCodeXYPosition; out NewTopLine: integer;
|
||||
SourceChangeCache: TSourceChangeCache): boolean;
|
||||
var CleanCursorPos, Indent, insertPos: integer;
|
||||
CursorNode, ProcNode, ImplementationNode, SectionNode, AClassNode,
|
||||
@ -2944,6 +2944,8 @@ begin
|
||||
if (SourceChangeCache=nil) then
|
||||
RaiseException('need a SourceChangeCache');
|
||||
BuildTreeAndGetCleanPos(trAll,CursorPos, CleanCursorPos,[]);
|
||||
NewPos:=CleanCodeXYPosition;
|
||||
NewTopLine:=0;
|
||||
|
||||
// find CodeTreeNode at cursor
|
||||
// skip newline chars
|
||||
|
||||
@ -393,8 +393,8 @@ type
|
||||
// code completion = auto class completion, auto forward proc completion,
|
||||
// local var assignment completion, event assignment completion
|
||||
function CompleteCode(Code: TCodeBuffer; X,Y,TopLine: integer;
|
||||
var NewCode: TCodeBuffer;
|
||||
var NewX, NewY, NewTopLine: integer): boolean;
|
||||
out NewCode: TCodeBuffer;
|
||||
out NewX, NewY, NewTopLine: integer): boolean;
|
||||
|
||||
// custom class completion
|
||||
function InitClassCompletion(Code: TCodeBuffer;
|
||||
@ -2614,7 +2614,7 @@ begin
|
||||
end;
|
||||
|
||||
function TCodeToolManager.CompleteCode(Code: TCodeBuffer; X,Y,TopLine: integer;
|
||||
var NewCode: TCodeBuffer; var NewX, NewY, NewTopLine: integer): boolean;
|
||||
out NewCode: TCodeBuffer; out NewX, NewY, NewTopLine: integer): boolean;
|
||||
var
|
||||
CursorPos: TCodeXYPosition;
|
||||
NewPos: TCodeXYPosition;
|
||||
|
||||
44
components/codetools/examples/codecompletion.lpi
Normal file
44
components/codetools/examples/codecompletion.lpi
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0"?>
|
||||
<CONFIG>
|
||||
<ProjectOptions>
|
||||
<PathDelim Value="/"/>
|
||||
<Version Value="5"/>
|
||||
<General>
|
||||
<SessionStorage Value="InProjectDir"/>
|
||||
<MainUnit Value="0"/>
|
||||
<IconPath Value="./"/>
|
||||
<TargetFileExt Value=""/>
|
||||
<Title Value="finddeclaration"/>
|
||||
</General>
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
||||
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
|
||||
</PublishOptions>
|
||||
<RunParams>
|
||||
<local>
|
||||
<FormatVersion Value="1"/>
|
||||
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
||||
</local>
|
||||
</RunParams>
|
||||
<Units Count="1">
|
||||
<Unit0>
|
||||
<Filename Value="codecompletion.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="CodeCompletion"/>
|
||||
</Unit0>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
<Version Value="5"/>
|
||||
<SearchPaths>
|
||||
<OtherUnitFiles Value="$(LazarusDir)/components/codetools/units/$(TargetCPU)-$(TargetOS)/;scanexamples/"/>
|
||||
</SearchPaths>
|
||||
<CodeGeneration>
|
||||
<Generate Value="Faster"/>
|
||||
</CodeGeneration>
|
||||
<Other>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
</CONFIG>
|
||||
86
components/codetools/examples/codecompletion.lpr
Normal file
86
components/codetools/examples/codecompletion.lpr
Normal file
@ -0,0 +1,86 @@
|
||||
{
|
||||
***************************************************************************
|
||||
* *
|
||||
* This source is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This code is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* *
|
||||
* A copy of the GNU General Public License is available on the World *
|
||||
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
||||
* obtain it by writing to the Free Software Foundation, *
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
Author: Mattias Gaertner
|
||||
|
||||
Abstract:
|
||||
Simple demonstrating, how to setup the codetools, FPC and Lazarus Source
|
||||
directory to complete code.
|
||||
}
|
||||
program CodeCompletion;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
uses
|
||||
Classes, SysUtils, CodeCache, CodeToolManager, DefineTemplates,
|
||||
CodeToolsConfig;
|
||||
|
||||
const
|
||||
ConfigFilename = 'codetools.config';
|
||||
var
|
||||
Options: TCodeToolsOptions;
|
||||
NewCode: TCodeBuffer;
|
||||
NewX, NewY, NewTopLine: integer;
|
||||
Code: TCodeBuffer;
|
||||
begin
|
||||
// setup the Options
|
||||
Options:=TCodeToolsOptions.Create;
|
||||
|
||||
// To not parse the FPC sources every time, the options are saved to a file.
|
||||
if FileExists(ConfigFilename) then
|
||||
Options.LoadFromFile(ConfigFilename);
|
||||
|
||||
// setup your paths
|
||||
Options.FPCPath:='/usr/bin/ppc386';
|
||||
Options.FPCSrcDir:=ExpandFileName('~/freepascal/fpc');
|
||||
Options.LazarusSrcDir:=ExpandFileName('~/pascal/lazarus');
|
||||
|
||||
// optional: ProjectDir and TestPascalFile exists only to easily test some
|
||||
// things.
|
||||
Options.ProjectDir:=GetCurrentDir+'/scanexamples/';
|
||||
Options.TestPascalFile:=Options.ProjectDir+'completion1.pas';
|
||||
|
||||
// init the codetools
|
||||
if not Options.UnitLinkListValid then
|
||||
writeln('Scanning FPC sources may take a while ...');
|
||||
CodeToolBoss.Init(Options);
|
||||
|
||||
// save the options and the FPC unit links results.
|
||||
Options.SaveToFile(ConfigFilename);
|
||||
|
||||
// Example: find declaration of 'TObject'
|
||||
|
||||
// Step 1: load the file
|
||||
Code:=CodeToolBoss.LoadFile(Options.TestPascalFile,false,false);
|
||||
if Code=nil then
|
||||
raise Exception.Create('loading failed '+Options.TestPascalFile);
|
||||
|
||||
// Step 2: find declaration
|
||||
if CodeToolBoss.CompleteCode(Code,3,36,20,NewCode,NewX,NewY,NewTopLine) then
|
||||
begin
|
||||
writeln('Code completed: ',NewCode.Filename,' Line=',NewY,' Column=',NewX);
|
||||
writeln(Code.Source);
|
||||
end else begin
|
||||
writeln('Code completion failed: ',CodeToolBoss.ErrorMessage);
|
||||
end;
|
||||
|
||||
Options.Free;
|
||||
end.
|
||||
|
||||
40
components/codetools/examples/scanexamples/completion1.pas
Normal file
40
components/codetools/examples/scanexamples/completion1.pas
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
***************************************************************************
|
||||
* *
|
||||
* This source is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This code is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* *
|
||||
* A copy of the GNU General Public License is available on the World *
|
||||
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
||||
* obtain it by writing to the Free Software Foundation, *
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
Author: Mattias Gaertner
|
||||
}
|
||||
unit Completion1;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils;
|
||||
|
||||
implementation
|
||||
|
||||
procedure DoSomething;
|
||||
begin
|
||||
s:='Path'+PathDelim;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
@ -4942,10 +4942,10 @@ var
|
||||
// find base type
|
||||
Exclude(Params.Flags,fdfFunctionResult);
|
||||
{$IFDEF ShowExprEval}
|
||||
DebugLn('ResolveBaseTypeOfIdentifier ExprType=',ExprTypeToString(ExprType));
|
||||
DebugLn(' ResolveBaseTypeOfIdentifier ExprType=',ExprTypeToString(ExprType));
|
||||
{$ENDIF}
|
||||
ExprType:=ExprType.Context.Tool.ConvertNodeToExpressionType(
|
||||
ExprType.Context.Node,Params);
|
||||
ExprType.Context.Node,Params);
|
||||
if (ExprType.Desc=xtContext)
|
||||
and (ExprType.Context.Node.Desc in [ctnProcedure,ctnProcedureHead]) then
|
||||
begin
|
||||
@ -5029,7 +5029,7 @@ var
|
||||
Params.Flags:=[fdfSearchInAncestors,fdfExceptionOnNotFound]
|
||||
+(fdfGlobals*Params.Flags);
|
||||
if ExprType.Context.Node=StartContext.Node then begin
|
||||
// there is no special context -> also search in parent contexts
|
||||
// there is no special context -> search in parent contexts too
|
||||
Params.Flags:=Params.Flags
|
||||
+[fdfSearchInParentNodes,fdfIgnoreCurContextNode];
|
||||
end else begin
|
||||
@ -5049,7 +5049,7 @@ var
|
||||
// search ...
|
||||
Params.SetIdentifier(Self,@Src[CurAtom.StartPos],@CheckSrcIdentifier);
|
||||
{$IFDEF ShowExprEval}
|
||||
DebugLn('ResolveIdentifier Ident="',GetIdentifier(Params.Identifier),'"');
|
||||
DebugLn(' ResolveIdentifier Ident="',GetIdentifier(Params.Identifier),'"');
|
||||
{$ENDIF}
|
||||
if ExprType.Context.Tool.FindIdentifierInContext(Params) then begin
|
||||
if not Params.NewCodeTool.NodeIsConstructor(Params.NewNode) then begin
|
||||
@ -5487,56 +5487,79 @@ begin
|
||||
DebugLn('[TFindDeclarationTool.ConvertNodeToExpressionType] B',
|
||||
' Expr=',ExprTypeToString(Result));
|
||||
{$ENDIF}
|
||||
if Node.Desc=ctnRangeType then begin
|
||||
// range type -> convert to special expression type
|
||||
case Node.Desc of
|
||||
ctnRangeType:
|
||||
begin
|
||||
// range type -> convert to special expression type
|
||||
|
||||
// ToDo: ppu, ppw, dcu files
|
||||
// ToDo: ppu, ppw, dcu files
|
||||
|
||||
MoveCursorToNodeStart(Node);
|
||||
MoveCursorToNodeStart(Node);
|
||||
|
||||
// ToDo: check for circles
|
||||
// ToDo: check for circles
|
||||
|
||||
Params.Save(OldInput);
|
||||
Params.ContextNode:=Node;
|
||||
Result:=ReadOperandTypeAtCursor(Params);
|
||||
Params.Load(OldInput);
|
||||
Result.Context:=CreateFindContext(Self,Node);
|
||||
end;
|
||||
|
||||
Params.Save(OldInput);
|
||||
Params.ContextNode:=Node;
|
||||
Result:=ReadOperandTypeAtCursor(Params);
|
||||
Params.Load(OldInput);
|
||||
Result.Context:=CreateFindContext(Self,Node);
|
||||
end else if (Node.Desc=ctnConstDefinition) and (Node.FirstChild=nil) then
|
||||
begin
|
||||
// const -> convert to special expression type
|
||||
ctnConstDefinition:
|
||||
begin
|
||||
// const -> convert to special expression type
|
||||
|
||||
// ToDo: ppu, ppw, dcu files
|
||||
// ToDo: ppu, ppw, dcu files
|
||||
|
||||
MoveCursorToNodeStart(Node);
|
||||
MoveCursorToNodeStart(Node);
|
||||
|
||||
ReadNextAtom;
|
||||
if not AtomIsIdentifier(false) then exit;
|
||||
ReadNextAtom;
|
||||
if not (CurPos.Flag in [cafEqual,cafColon]) then exit;
|
||||
ReadNextAtom;
|
||||
ReadNextAtom;
|
||||
if not AtomIsIdentifier(false) then exit;
|
||||
ReadNextAtom;
|
||||
if not (CurPos.Flag in [cafEqual,cafColon]) then exit;
|
||||
ReadNextAtom;
|
||||
|
||||
// ToDo: check for circles
|
||||
// ToDo: check for circles
|
||||
|
||||
Params.Save(OldInput);
|
||||
Params.ContextNode:=Node;
|
||||
Result:=ReadOperandTypeAtCursor(Params);
|
||||
Params.Load(OldInput);
|
||||
Result.Context:=CreateFindContext(Self,Node);
|
||||
end else if Node.Desc=ctnIdentifier then begin
|
||||
Params.Save(OldInput);
|
||||
Params.ContextNode:=Node;
|
||||
Result:=ReadOperandTypeAtCursor(Params);
|
||||
Params.Load(OldInput);
|
||||
Result.Context:=CreateFindContext(Self,Node);
|
||||
end;
|
||||
|
||||
ctnIdentifier:
|
||||
begin
|
||||
|
||||
// ToDo: ppu, ppw, dcu files
|
||||
// ToDo: ppu, ppw, dcu files
|
||||
|
||||
MoveCursorToNodeStart(Node);
|
||||
ReadNextAtom;
|
||||
ConvertIdentifierAtCursor;
|
||||
end else if (Node.Desc=ctnProperty) or (Node.Desc=ctnGlobalProperty) then
|
||||
begin
|
||||
|
||||
// ToDo: ppu, ppw, dcu files
|
||||
|
||||
ExtractPropType(Node,false,true);
|
||||
if CurPos.Flag<>cafEdgedBracketOpen then
|
||||
MoveCursorToNodeStart(Node);
|
||||
ReadNextAtom;
|
||||
ConvertIdentifierAtCursor;
|
||||
end;
|
||||
|
||||
ctnProperty,ctnGlobalProperty:
|
||||
begin
|
||||
|
||||
// ToDo: ppu, ppw, dcu files
|
||||
|
||||
ExtractPropType(Node,false,true);
|
||||
if CurPos.Flag<>cafEdgedBracketOpen then
|
||||
ConvertIdentifierAtCursor;
|
||||
end;
|
||||
|
||||
ctnConstant:
|
||||
begin
|
||||
|
||||
// ToDo: ppu, ppw, dcu files
|
||||
|
||||
MoveCursorToNodeStart(Node);
|
||||
Params.Save(OldInput);
|
||||
Params.ContextNode:=Node;
|
||||
Result:=ReadOperandTypeAtCursor(Params);
|
||||
Params.Load(OldInput);
|
||||
Result.Context:=CreateFindContext(Self,Node);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user