codetools: implemented finding the expression type of a constant

git-svn-id: trunk@9584 -
This commit is contained in:
mattias 2006-07-10 17:03:32 +00:00
parent 6df73a9fb9
commit ab98d4268e
7 changed files with 245 additions and 47 deletions

3
.gitattributes vendored
View File

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

View File

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

View File

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

View 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>

View 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.

View 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.

View File

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