IDE now checks, if all files of the package exists

git-svn-id: trunk@9309 -
This commit is contained in:
mattias 2006-05-19 16:27:15 +00:00
parent 7ed0ada460
commit dc4d7c5d38
10 changed files with 376 additions and 108 deletions

View File

@ -55,7 +55,7 @@ type
PCodeXYPosition = ^TCodeXYPosition; PCodeXYPosition = ^TCodeXYPosition;
TCommonAtomFlag = ( TCommonAtomFlag = (
cafNone, cafNone, // = none of the below
cafSemicolon, cafEqual, cafColon, cafComma, cafPoint, cafSemicolon, cafEqual, cafColon, cafComma, cafPoint,
cafRoundBracketOpen, cafRoundBracketClose, cafRoundBracketOpen, cafRoundBracketClose,
cafEdgedBracketOpen, cafEdgedBracketClose, cafEdgedBracketOpen, cafEdgedBracketClose,

View File

@ -2175,7 +2175,7 @@ begin
repeat repeat
ALastAtomEnd:=CurPos.EndPos; ALastAtomEnd:=CurPos.EndPos;
ReadNextAtom; ReadNextAtom;
until (CurPos.EndPos>ALineEnd) or (CurPos.Flag=cafNone); until (CurPos.EndPos>ALineEnd) or (CurPos.StartPos>SrcLen);
end else begin end else begin
ALineStart:=Srclen+1; ALineStart:=Srclen+1;
ALineEnd:=Srclen+1; ALineEnd:=Srclen+1;

View File

@ -6691,6 +6691,7 @@ function TFindDeclarationTool.CheckParameterSyntax(CursorNode: TCodeTreeNode;
// check for Identifier(expr,expr,...,expr,VarName // check for Identifier(expr,expr,...,expr,VarName
// or Identifier[expr,expr,...,expr,VarName // or Identifier[expr,expr,...,expr,VarName
// ParameterIndex is 0 based // ParameterIndex is 0 based
{off $DEFINE VerboseCPS}
procedure RaiseBracketNotOpened; procedure RaiseBracketNotOpened;
begin begin
@ -6707,16 +6708,16 @@ function TFindDeclarationTool.CheckParameterSyntax(CursorNode: TCodeTreeNode;
BracketAtom: TAtomPosition; BracketAtom: TAtomPosition;
begin begin
BracketAtom:=CurPos; BracketAtom:=CurPos;
//DebugLn('CheckBrackets ',GetAtom,' ',dbgs(BracketAtom)); {$IFDEF VerboseCPS}DebugLn('CheckBrackets ',GetAtom,' ',dbgs(BracketAtom));{$ENDIF}
repeat repeat
ReadNextAtom; ReadNextAtom;
if CurPos.Flag in [cafRoundBracketOpen,cafEdgedBracketOpen] then begin if CurPos.Flag in [cafRoundBracketOpen,cafEdgedBracketOpen] then begin
if (LastAtoms.GetValueAt(0).Flag=cafWord) then begin if (LastAtoms.GetValueAt(0).Flag=cafWord) then begin
//DebugLn('CheckBrackets check word+bracket open'); {$IFDEF VerboseCPS}DebugLn('CheckBrackets check word+bracket open');{$ENDIF}
UndoReadNextAtom; UndoReadNextAtom;
if CheckIdentifierAndParameterList() then exit(true); if CheckIdentifierAndParameterList() then exit(true);
end else begin end else begin
//DebugLn('CheckBrackets check bracket open'); {$IFDEF VerboseCPS}DebugLn('CheckBrackets check bracket open');{$ENDIF}
if CheckBrackets then exit(true); if CheckBrackets then exit(true);
end; end;
end else if CurPos.Flag in [cafRoundBracketClose,cafEdgedBracketClose] end else if CurPos.Flag in [cafRoundBracketClose,cafEdgedBracketClose]
@ -6725,14 +6726,14 @@ function TFindDeclarationTool.CheckParameterSyntax(CursorNode: TCodeTreeNode;
=(CurPos.Flag=cafRoundBracketClose) =(CurPos.Flag=cafRoundBracketClose)
then begin then begin
// closing bracket found, but the variable was not in them // closing bracket found, but the variable was not in them
//DebugLn('CheckBrackets bracket closed'); {$IFDEF VerboseCPS}DebugLn('CheckBrackets bracket closed');{$ENDIF}
exit(false); exit(false);
end else begin end else begin
// invalid closing bracket found // invalid closing bracket found
RaiseBracketNotOpened; RaiseBracketNotOpened;
end; end;
end; end;
until (CurPos.EndPos>CleanCursorPos) or (CurPos.Flag=cafNone); until (CurPos.EndPos>CleanCursorPos);
Result:=false; Result:=false;
end; end;
@ -6746,20 +6747,20 @@ function TFindDeclarationTool.CheckParameterSyntax(CursorNode: TCodeTreeNode;
Result:=false; Result:=false;
CurProcNameAtom:=CurPos; CurProcNameAtom:=CurPos;
CurParameterIndex:=0; CurParameterIndex:=0;
//DebugLn('CheckIdentifierAndParameterList START ',GetAtom,' ',dbgs(CurProcNameAtom)); {$IFDEF VerboseCPS}DebugLn('CheckIdentifierAndParameterList START ',GetAtom,' ',dbgs(CurProcNameAtom));{$ENDIF}
ReadNextAtom; ReadNextAtom;
if CurPos.Flag in [cafRoundBracketOpen,cafEdgedBracketOpen] then begin if CurPos.Flag in [cafRoundBracketOpen,cafEdgedBracketOpen] then begin
BracketAtom:=CurPos; BracketAtom:=CurPos;
ParameterStart:=CurPos.EndPos; ParameterStart:=CurPos.EndPos;
//DebugLn('CheckIdentifierAndParameterList Bracket=',GetAtom); {$IFDEF VerboseCPS}DebugLn('CheckIdentifierAndParameterList Bracket=',GetAtom);{$ENDIF}
repeat repeat
ReadNextAtom; ReadNextAtom;
//DebugLn('CheckIdentifierAndParameterList ',GetAtom); {$IFDEF VerboseCPS}DebugLn('CheckIdentifierAndParameterList Atom=',GetAtom);{$ENDIF}
if CurPos.EndPos>=CleanCursorPos then begin if CurPos.EndPos>=CleanCursorPos then begin
// parameter found => search parameter expression bounds e.g. ', parameter ,' // parameter found => search parameter expression bounds e.g. ', parameter ,'
// important: this function should work, even the code behind // important: this function should work, even the code behind
// CleanCursorPos is buggy // CleanCursorPos is buggy
//DebugLn('CheckIdentifierAndParameterList Parameter found, search range ...'); {$IFDEF VerboseCPS}DebugLn('CheckIdentifierAndParameterList Parameter found, search range ...');{$ENDIF}
ProcNameAtom:=CurProcNameAtom; ProcNameAtom:=CurProcNameAtom;
ParameterIndex:=CurParameterIndex; ParameterIndex:=CurParameterIndex;
ParameterAtom.StartPos:=ParameterStart; ParameterAtom.StartPos:=ParameterStart;
@ -6767,7 +6768,7 @@ function TFindDeclarationTool.CheckParameterSyntax(CursorNode: TCodeTreeNode;
MoveCursorToCleanPos(ParameterStart); MoveCursorToCleanPos(ParameterStart);
repeat repeat
ReadNextAtom; ReadNextAtom;
//DebugLn('CheckIdentifierAndParameterList parameter atom ',GetAtom); {$IFDEF VerboseCPS}DebugLn('CheckIdentifierAndParameterList parameter atom ',GetAtom);{$ENDIF}
if (CurPos.Flag in [cafRoundBracketOpen,cafEdgedBracketOpen]) then if (CurPos.Flag in [cafRoundBracketOpen,cafEdgedBracketOpen]) then
ReadTilBracketClose(false) ReadTilBracketClose(false)
else else
@ -6778,7 +6779,7 @@ function TFindDeclarationTool.CheckParameterSyntax(CursorNode: TCodeTreeNode;
and (not LastUpAtomIs(0,'INHERITED'))) then and (not LastUpAtomIs(0,'INHERITED'))) then
begin begin
// end of parameter expression found // end of parameter expression found
//DebugLn('CheckIdentifierAndParameterList end of parameter found'); {$IFDEF VerboseCPS}DebugLn('CheckIdentifierAndParameterList end of parameter found');{$ENDIF}
exit(true); exit(true);
end else begin end else begin
// atom belongs to the parameter expression // atom belongs to the parameter expression
@ -6790,22 +6791,22 @@ function TFindDeclarationTool.CheckParameterSyntax(CursorNode: TCodeTreeNode;
end; end;
if (CurPos.Flag in [cafRoundBracketOpen,cafEdgedBracketOpen]) then begin if (CurPos.Flag in [cafRoundBracketOpen,cafEdgedBracketOpen]) then begin
if (LastAtoms.GetValueAt(0).Flag=cafWord) then begin if (LastAtoms.GetValueAt(0).Flag=cafWord) then begin
//DebugLn('CheckIdentifierAndParameterList check word+bracket open'); {$IFDEF VerboseCPS}DebugLn('CheckIdentifierAndParameterList check word+bracket open');{$ENDIF}
UndoReadNextAtom; UndoReadNextAtom;
if CheckIdentifierAndParameterList() then exit(true); if CheckIdentifierAndParameterList() then exit(true);
end else begin end else begin
//DebugLn('CheckIdentifierAndParameterList check bracket open'); {$IFDEF VerboseCPS}DebugLn('CheckIdentifierAndParameterList check bracket open');{$ENDIF}
if CheckBrackets then exit(true); if CheckBrackets then exit(true);
end; end;
end end
else if CurPos.Flag in [cafRoundBracketClose,cafEdgedBracketClose] then else if CurPos.Flag in [cafRoundBracketClose,cafEdgedBracketClose] then
begin begin
//DebugLn('CheckIdentifierAndParameterList check bracket close'); {$IFDEF VerboseCPS}DebugLn('CheckIdentifierAndParameterList check bracket close');{$ENDIF}
if (BracketAtom.Flag=cafRoundBracketOpen) if (BracketAtom.Flag=cafRoundBracketOpen)
=(CurPos.Flag=cafRoundBracketClose) =(CurPos.Flag=cafRoundBracketClose)
then begin then begin
// parameter list ended in front of Variable => continue search // parameter list ended in front of Variable => continue search
//DebugLn('CheckIdentifierAndParameterList parm list ended in front of cursor'); {$IFDEF VerboseCPS}DebugLn('CheckIdentifierAndParameterList parm list ended in front of cursor');{$ENDIF}
exit; exit;
end else begin end else begin
// invalid closing bracket found // invalid closing bracket found
@ -6817,8 +6818,8 @@ function TFindDeclarationTool.CheckParameterSyntax(CursorNode: TCodeTreeNode;
ParameterStart:=CurPos.EndPos; ParameterStart:=CurPos.EndPos;
inc(CurParameterIndex); inc(CurParameterIndex);
end; end;
//DebugLn('CheckIdentifierAndParameterList ',GetAtom); {$IFDEF VerboseCPS}DebugLn('CheckIdentifierAndParameterList After parsing atom: atom=',GetAtom);{$ENDIF}
until (CurPos.EndPos>CleanCursorPos) or (CurPos.Flag=cafNone); until (CurPos.EndPos>CleanCursorPos);
end; end;
end; end;
@ -6830,7 +6831,7 @@ begin
MoveCursorToNodeStart(CursorNode); MoveCursorToNodeStart(CursorNode);
repeat repeat
ReadNextAtom; ReadNextAtom;
//DebugLn('TCodeCompletionCodeTool.CheckParameterSyntax ',GetAtom,' ',dbgs(CurPos.EndPos),'<',dbgs(CleanCursorPos)); {$IFDEF VerboseCPS}DebugLn('TCodeCompletionCodeTool.CheckParameterSyntax ',GetAtom,' ',dbgs(CurPos.EndPos),'<',dbgs(CleanCursorPos));{$ENDIF}
if CurPos.EndPos>CleanCursorPos then exit; if CurPos.EndPos>CleanCursorPos then exit;
if (CurPos.Flag in [cafRoundBracketOpen,cafEdgedBracketOpen]) if (CurPos.Flag in [cafRoundBracketOpen,cafEdgedBracketOpen])
and (LastAtoms.GetValueAt(0).Flag=cafWord) then begin and (LastAtoms.GetValueAt(0).Flag=cafWord) then begin

View File

@ -3110,7 +3110,7 @@ begin
CurKeyWordFuncList:=ClassInterfaceKeyWordFuncList; CurKeyWordFuncList:=ClassInterfaceKeyWordFuncList;
try try
repeat repeat
if CurPos.Flag in [cafEnd,cafNone] then break; if (CurPos.Flag=cafEnd) or (CurPos.StartPos>SrcLen) then break;
if not DoAtom then break; if not DoAtom then break;
ReadNextAtom; ReadNextAtom;
until false; until false;

View File

@ -4,8 +4,10 @@ object CodeContextFrm: TCodeContextFrm
Caption = 'CodeContextFrm' Caption = 'CodeContextFrm'
ClientHeight = 300 ClientHeight = 300
ClientWidth = 400 ClientWidth = 400
KeyPreview = True
OnCreate = FormCreate OnCreate = FormCreate
OnDestroy = FormDestroy OnDestroy = FormDestroy
OnKeyDown = FormKeyDown
OnPaint = FormPaint OnPaint = FormPaint
PixelsPerInch = 112 PixelsPerInch = 112
HorzScrollBar.Page = 399 HorzScrollBar.Page = 399

View File

@ -3,8 +3,9 @@
LazarusResources.Add('TCodeContextFrm','FORMDATA',[ LazarusResources.Add('TCodeContextFrm','FORMDATA',[
'TPF0'#15'TCodeContextFrm'#14'CodeContextFrm'#11'BorderIcons'#11#0#11'BorderS' 'TPF0'#15'TCodeContextFrm'#14'CodeContextFrm'#11'BorderIcons'#11#0#11'BorderS'
+'tyle'#7#6'bsNone'#7'Caption'#6#14'CodeContextFrm'#12'ClientHeight'#3','#1#11 +'tyle'#7#6'bsNone'#7'Caption'#6#14'CodeContextFrm'#12'ClientHeight'#3','#1#11
+'ClientWidth'#3#144#1#8'OnCreate'#7#10'FormCreate'#9'OnDestroy'#7#11'FormDes' +'ClientWidth'#3#144#1#10'KeyPreview'#9#8'OnCreate'#7#10'FormCreate'#9'OnDest'
+'troy'#7'OnPaint'#7#9'FormPaint'#13'PixelsPerInch'#2'p'#18'HorzScrollBar.Pag' +'roy'#7#11'FormDestroy'#9'OnKeyDown'#7#11'FormKeyDown'#7'OnPaint'#7#9'FormPa'
+'e'#3#143#1#18'VertScrollBar.Page'#3'+'#1#4'Left'#3'"'#1#6'Height'#3','#1#3 +'int'#13'PixelsPerInch'#2'p'#18'HorzScrollBar.Page'#3#143#1#18'VertScrollBar'
+'Top'#3#163#0#5'Width'#3#144#1#0#0 +'.Page'#3'+'#1#4'Left'#3'"'#1#6'Height'#3','#1#3'Top'#3#163#0#5'Width'#3#144
+#1#0#0
]); ]);

View File

@ -36,10 +36,10 @@ unit CodeContextForm;
interface interface
uses uses
Classes, SysUtils, LCLProc, LResources, Forms, Controls, Graphics, Dialogs, Classes, SysUtils, Types, LCLProc, LResources, Forms, Controls, Graphics,
LCLType, LCLIntf, Dialogs, LCLType, LCLIntf,
SynEdit, CodeCache, FindDeclarationTool, IdentCompletionTool, CodeTree, BasicCodeTools, LinkScanner, CodeCache, FindDeclarationTool,
CodeAtom, PascalParserTool, CodeToolManager, IdentCompletionTool, CodeTree, CodeAtom, PascalParserTool, CodeToolManager,
SrcEditorIntf; SrcEditorIntf;
type type
@ -49,11 +49,14 @@ type
TCodeContextFrm = class(TForm) TCodeContextFrm = class(TForm)
procedure FormCreate(Sender: TObject); procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject); procedure FormDestroy(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormPaint(Sender: TObject); procedure FormPaint(Sender: TObject);
private private
FHints: TStrings; FHints: TStrings;
FProcNameCodeXYPos: TCodeXYPosition; FProcNameCodeXYPos: TCodeXYPosition;
procedure CreateHints(const CodeContexts: TCodeContextInfo); procedure CreateHints(const CodeContexts: TCodeContextInfo);
procedure ClearMarksInHints;
procedure MarkCurrentParameterInHints(ParameterIndex: integer); // 0 based
procedure CalculateHintsBounds(const CodeContexts: TCodeContextInfo); procedure CalculateHintsBounds(const CodeContexts: TCodeContextInfo);
procedure DrawHints(var MaxWidth, MaxHeight: Integer; Draw: boolean); procedure DrawHints(var MaxWidth, MaxHeight: Integer; Draw: boolean);
public public
@ -64,22 +67,22 @@ type
var var
CodeContextFrm: TCodeContextFrm = nil; CodeContextFrm: TCodeContextFrm = nil;
function ShowCodeContext(Code: TCodeBuffer; Editor: TSynEdit): boolean; function ShowCodeContext(Code: TCodeBuffer): boolean;
implementation implementation
function ShowCodeContext(Code: TCodeBuffer; Editor: TSynEdit): boolean; function ShowCodeContext(Code: TCodeBuffer): boolean;
var var
LogCaretXY: TPoint; LogCaretXY: TPoint;
CodeContexts: TCodeContextInfo; CodeContexts: TCodeContextInfo;
begin begin
Result:=false; Result:=false;
LogCaretXY:=Editor.LogicalCaretXY; LogCaretXY:=SourceEditorWindow.ActiveEditor.CursorTextXY;
CodeContexts:=nil; CodeContexts:=nil;
try try
if not CodeToolBoss.FindCodeContext(Code,LogCaretXY.X,LogCaretXY.Y, if (not CodeToolBoss.FindCodeContext(Code,LogCaretXY.X,LogCaretXY.Y,
CodeContexts) CodeContexts))
then or (CodeContexts=nil) or (CodeContexts.Count=0) then
exit; exit;
DebugLn('ShowCodeContext show'); DebugLn('ShowCodeContext show');
{$IFNDEF EnableCodeContext} {$IFNDEF EnableCodeContext}
@ -89,6 +92,7 @@ begin
CodeContextFrm:=TCodeContextFrm.Create(nil); CodeContextFrm:=TCodeContextFrm.Create(nil);
CodeContextFrm.SetCodeContexts(CodeContexts); CodeContextFrm.SetCodeContexts(CodeContexts);
CodeContextFrm.Visible:=true; CodeContextFrm.Visible:=true;
Result:=true;
finally finally
CodeContexts.Free; CodeContexts.Free;
end; end;
@ -106,6 +110,12 @@ begin
FreeAndNil(FHints); FreeAndNil(FHints);
end; end;
procedure TCodeContextFrm.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (Key=VK_ESCAPE) and (Shift=[]) then Close;
end;
procedure TCodeContextFrm.FormPaint(Sender: TObject); procedure TCodeContextFrm.FormPaint(Sender: TObject);
var var
DrawWidth: LongInt; DrawWidth: LongInt;
@ -161,11 +171,158 @@ begin
if (s[p] in [',',';',':']) and (s[p+1]<>' ') then if (s[p] in [',',';',':']) and (s[p+1]<>' ') then
System.Insert(' ',s,p+1); System.Insert(' ',s,p+1);
end; end;
// mark the mark characters
for p:=length(s) downto 1 do
if s[p]='\' then
System.Insert('\',s,p+1);
FHints.Add(Trim(s)); FHints.Add(Trim(s));
end; end;
MarkCurrentParameterInHints(CodeContexts.ParameterIndex-1);
DebugLn('TCodeContextFrm.UpdateHints ',FHints.Text); DebugLn('TCodeContextFrm.UpdateHints ',FHints.Text);
end; end;
procedure TCodeContextFrm.ClearMarksInHints;
// remove all marks except the \\ marks
var
i: Integer;
s: string;
p: Integer;
begin
for i:=0 to FHints.Count-1 do begin
s:=FHints[i];
p:=1;
while p<length(s) do begin
if s[p]<>'\' then
inc(p) // normal character
else if s[p+1]='\' then
inc(p,2) // '\\'
else begin
System.Delete(s,p,2); // remove mark
end;
end;
FHints[i]:=s;
end;
end;
procedure TCodeContextFrm.MarkCurrentParameterInHints(ParameterIndex: integer);
function MarkCurrentParameterInHint(const s: string): string;
var
p: Integer;
CurrentMark: Char;
procedure Mark(NewMark: char; Position: integer);
begin
if p=Position then
CurrentMark:=NewMark;
System.Insert('\'+NewMark,Result,Position);
if Position<=p then
inc(p,2);
//DebugLn('Mark Position=',dbgs(Position),' p=',dbgs(p),' CurrentMark="',CurrentMark,'" ',copy(Result,1,Position+2));
end;
var
BracketLevel: Integer;
CurParameterIndex: Integer;
WordStart: LongInt;
WordEnd: LongInt;
ModifierStart: LongInt;
ModifierEnd: LongInt;
SearchingType: Boolean;
ReadingType: Boolean;
begin
Result:=s;
BracketLevel:=0;
CurParameterIndex:=0;
CurrentMark:='*';
ReadingType:=false;
SearchingType:=false;
ModifierStart:=-1;
ModifierEnd:=-1;
p:=1;
while (p<=length(Result)) do begin
//DebugLn('MarkCurrentParameterInHint p=',dbgs(p),' "',Result[p],'" BracketLevel=',dbgs(BracketLevel),' CurParameterIndex=',dbgs(CurParameterIndex),' ReadingType=',dbgs(ReadingType),' SearchingType=',dbgs(SearchingType));
case Result[p] of
'(','{':
inc(BracketLevel);
')','}':
begin
if (BracketLevel=1) then begin
if CurrentMark<>'*' then
Mark('*',p);
exit;
end;
dec(BracketLevel);
end;
',':
if BracketLevel=1 then begin
inc(CurParameterIndex);
end;
':':
if BracketLevel=1 then begin
// names ended, type started
if SearchingType then
Mark('b',p);
ReadingType:=true;
SearchingType:=false;
end;
';':
if BracketLevel=1 then begin
// type ended, next parameter started
if CurrentMark<>'*' then
Mark('*',p);
SearchingType:=false;
ReadingType:=false;
ModifierStart:=-1;
inc(CurParameterIndex);
end;
'''':
repeat
inc(p);
until (p>=length(Result)) or (Result[p]='''');
'a'..'z','A'..'Z','_':
if (BracketLevel=1) and (not ReadingType) then begin
WordStart:=p;
while (p<=length(Result)) and (IsIdentChar[Result[p]]) do
inc(p);
WordEnd:=p;
//DebugLn('MarkCurrentParameterInHint Word=',copy(Result,WordStart,WordEnd-WordStart));
if (CompareIdentifiers('const',@Result[WordStart])=0)
or (CompareIdentifiers('out',@Result[WordStart])=0)
or (CompareIdentifiers('var',@Result[WordStart])=0) then begin
// modifier
ModifierStart:=WordStart;
ModifierEnd:=WordEnd;
end else begin
// parameter name
if ParameterIndex=CurParameterIndex then begin
// mark parameter
Mark('*',WordEnd); // mark WordEnd before WordStart !
Mark('b',WordStart);
// mark modifier
if ModifierStart>0 then begin
Mark('*',ModifierEnd); // mark ModifierEnd before ModifierStart !
Mark('b',ModifierStart);
end;
// search type
SearchingType:=true;
end;
end;
dec(p);
end;
end;
inc(p);
end;
end;
var
i: Integer;
begin
ClearMarksInHints;
for i:=0 to FHints.Count-1 do
FHints[i]:=MarkCurrentParameterInHint(FHints[i]);
end;
procedure TCodeContextFrm.CalculateHintsBounds(const procedure TCodeContextFrm.CalculateHintsBounds(const
CodeContexts: TCodeContextInfo); CodeContexts: TCodeContextInfo);
var var
@ -219,22 +376,126 @@ end;
procedure TCodeContextFrm.DrawHints(var MaxWidth, MaxHeight: Integer; procedure TCodeContextFrm.DrawHints(var MaxWidth, MaxHeight: Integer;
Draw: boolean); Draw: boolean);
var var
BackgroundColor, TextColor: TColor;
i: Integer;
NewMaxHeight: Integer;
Flags: Cardinal;
CurRect: TRect;
s: string;
CurTextRect: TRect;
HorizontalSpace: Integer; HorizontalSpace: Integer;
VerticalSpace: Integer; VerticalSpace: Integer;
BackgroundColor, TextColor, TextBColor: TColor;
procedure DrawHint(const Line: string; var AHintRect: TRect);
var
ATextRect: TRect;
TokenStart: Integer;
TokenRect: TRect;
TokenSize: TPoint;
TokenPos: TPoint;
TokenEnd: LongInt;
UsedWidth: Integer; // maximum right token position
LineHeight: Integer; // current line height
LastTokenEnd: LongInt;
begin
ATextRect:=Rect(AHintRect.Left+HorizontalSpace,
AHintRect.Top+VerticalSpace,
AHintRect.Right-HorizontalSpace,
AHintRect.Bottom-VerticalSpace);
UsedWidth:=0;
LineHeight:=0;
TokenPos:=Point(ATextRect.Left,ATextRect.Top);
TokenEnd:=1;
while (TokenEnd<=length(Line)) do begin
LastTokenEnd:=TokenEnd;
ReadRawNextPascalAtom(Line,TokenEnd,TokenStart);
if TokenEnd<=LastTokenEnd then break;
if Line[TokenStart]='\' then begin
// mark found
if TokenStart>LastTokenEnd then begin
// there is a gap between last token and this token -> draw that first
TokenEnd:=TokenStart;
end else begin
inc(TokenStart);
if TokenStart>length(Line) then break;
TokenEnd:=TokenStart+1;
// the token is a mark
case Line[TokenStart] of
'*':
begin
// switch to normal font
Canvas.Font.Color:=TextColor;
//DebugLn('DrawHint normal');
continue;
end;
'b':
begin
// switch to bold font
Canvas.Font.Color:=TextBColor;
//DebugLn('DrawHint blue');
continue;
end;
else
// the token is a normal character -> paint it
end;
end;
end;
//DebugLn('DrawHint Token="',copy(Line,TokenStart,TokenEnd-TokenStart),'"');
// calculate token size
TokenRect:=Bounds(0,0,12345,1234);
DrawText(Canvas.Handle,@Line[LastTokenEnd],TokenEnd-LastTokenEnd,TokenRect,
DT_SINGLELINE+DT_CALCRECT+DT_NOCLIP);
TokenSize:=Point(TokenRect.Right,TokenRect.Bottom);
if (LineHeight>0) and (TokenPos.X+TokenRect.Right>ATextRect.Right) then
begin
// token does not fit into line -> break line
// fill end of line
if Draw and (TokenPos.X<AHintRect.Right) then begin
Canvas.FillRect(Rect(TokenPos.X,TokenPos.Y-VerticalSpace,
AHintRect.Right,TokenPos.Y+LineHeight+VerticalSpace));
end;
TokenPos:=Point(ATextRect.Left,TokenPos.y+LineHeight+VerticalSpace);
LineHeight:=0;
end;
// token fits into line
// => draw token
OffsetRect(TokenRect,TokenPos.x,TokenPos.y);
if Draw then begin
Canvas.FillRect(Rect(TokenRect.Left,TokenRect.Top-VerticalSpace,
TokenRect.Right,TokenRect.Bottom+VerticalSpace));
DrawText(Canvas.Handle,@Line[LastTokenEnd],TokenEnd-LastTokenEnd,TokenRect,
DT_SINGLELINE+DT_NOCLIP);
end;
// update LineHeight and UsedWidth
if LineHeight<TokenSize.y then
LineHeight:=TokenSize.y;
inc(TokenPos.X,TokenSize.x);
if UsedWidth<TokenPos.X then
UsedWidth:=TokenPos.X;
end;
// fill end of line
if Draw and (TokenPos.X<AHintRect.Right) and (LineHeight>0) then begin
Canvas.FillRect(Rect(TokenPos.X,TokenPos.Y-VerticalSpace,
AHintRect.Right,TokenPos.Y+LineHeight+VerticalSpace));
end;
if (not Draw) and (UsedWidth>0) then
AHintRect.Right:=UsedWidth+HorizontalSpace;
AHintRect.Bottom:=TokenPos.Y+LineHeight+VerticalSpace;
end;
var
i: Integer;
NewMaxHeight: Integer;
NewMaxWidth: Integer; NewMaxWidth: Integer;
CurHintRect: TRect;
begin begin
//DebugLn('TCodeContextFrm.DrawHints DrawWidth=',dbgs(MaxWidth),' DrawHeight=',dbgs(MaxHeight),' Draw=',dbgs(Draw)); //DebugLn('TCodeContextFrm.DrawHints DrawWidth=',dbgs(MaxWidth),' DrawHeight=',dbgs(MaxHeight),' Draw=',dbgs(Draw));
if Draw then begin if Draw then begin
// TODO: make colors configurable and theme dependent // TODO: make colors configurable and theme dependent
BackgroundColor:=clWhite; BackgroundColor:=clWhite;
TextColor:=clBlack; TextColor:=clDkGray;
TextBColor:=clBlack;
end; end;
HorizontalSpace:=2; HorizontalSpace:=2;
VerticalSpace:=2; VerticalSpace:=2;
@ -242,39 +503,28 @@ begin
if Draw then begin if Draw then begin
Canvas.Brush.Color:=BackgroundColor; Canvas.Brush.Color:=BackgroundColor;
Canvas.Font.Color:=TextColor; Canvas.Font.Color:=TextColor;
Canvas.Pen.Color:=clBlack;
end; end;
NewMaxWidth:=0; NewMaxWidth:=0;
NewMaxHeight:=0; NewMaxHeight:=0;
for i:=0 to FHints.Count-1 do begin for i:=0 to FHints.Count-1 do begin
if Draw and (NewMaxHeight>=MaxHeight) then break; if Draw and (NewMaxHeight>=MaxHeight) then break;
s:=FHints[i]; CurHintRect:=Rect(0,NewMaxHeight,MaxWidth,MaxHeight);
Flags:=DT_WordBreak; DrawHint(FHints[i],CurHintRect);
CurTextRect:=Rect(0,NewMaxHeight,MaxWidth,MaxHeight);
OffsetRect(CurTextRect,HorizontalSpace,VerticalSpace);
// calculate height
DrawText(Canvas.Handle,PChar(s),Length(s),CurTextRect,Flags+DT_CalcRect);
if Draw then
CurRect:=Rect(0,NewMaxHeight,MaxWidth,CurTextRect.Bottom+VerticalSpace)
else
CurRect:=Rect(0,NewMaxHeight,
CurTextRect.Right+HorizontalSpace,
CurTextRect.Bottom+VerticalSpace);
//DebugLn('TCodeContextFrm.DrawHints i=',dbgs(i),' CurTextRect=',dbgs(CurTextRect),' CurRect=',dbgs(CurRect),' s="',s,'"'); //DebugLn('TCodeContextFrm.DrawHints i=',dbgs(i),' CurTextRect=',dbgs(CurTextRect),' CurRect=',dbgs(CurRect),' s="',s,'"');
if CurRect.Right>NewMaxWidth then if CurHintRect.Right>NewMaxWidth then
NewMaxWidth:=CurRect.Right; NewMaxWidth:=CurHintRect.Right;
if Draw then begin NewMaxHeight:=CurHintRect.Bottom;
// draw text and background
Canvas.FillRect(CurRect);
DrawText(Canvas.Handle, PChar(s), Length(s), CurTextRect, Flags);
end;
NewMaxHeight:=CurRect.Bottom;
end; end;
if Draw then begin if Draw then begin
// fill rest of form
if NewMaxHeight<MaxHeight then
Canvas.FillRect(Rect(0,NewMaxHeight,MaxWidth,MaxHeight));
// draw frame around window // draw frame around window
Canvas.Pen.Color:=TextColor;
Canvas.Frame(Rect(0,0,MaxWidth-1,MaxHeight-1)); Canvas.Frame(Rect(0,0,MaxWidth-1,MaxHeight-1));
end; end;
if not Draw then begin if not Draw then begin
// adjust max width and height
if NewMaxWidth<MaxWidth then if NewMaxWidth<MaxWidth then
MaxWidth:=NewMaxWidth; MaxWidth:=NewMaxWidth;
if NewMaxHeight<MaxHeight then if NewMaxHeight<MaxHeight then

View File

@ -2316,6 +2316,13 @@ resourcestring
+'does not correspond to the package name %s%s%s in the file.%sChange ' +'does not correspond to the package name %s%s%s in the file.%sChange '
+'package name to %s%s%s?'; +'package name to %s%s%s?';
lisPkgMangSavePackage2 = 'Save package?'; lisPkgMangSavePackage2 = 'Save package?';
lisPkgMangPackageFileMissing = 'Package file missing';
lisPkgMangTheFileOfPackageIsMissing = 'The file %s%s%s%sof package %s is '
+'missing.';
lisPkgMangPackageFileNotSaved = 'Package file not saved';
lisPkgMangTheFileOfPackageNeedsToBeSavedFirst = 'The file %s%s%s%sof '
+'package %s needs to be saved first.';
lisPkgMangIgnoreAndSavePackageNow = 'Ignore and save package now';
lisPkgMangPackageChangedSave = 'Package %s%s%s changed. Save?'; lisPkgMangPackageChangedSave = 'Package %s%s%s changed. Save?';
lisPkgMangErrorWritingPackage = 'Error Writing Package'; lisPkgMangErrorWritingPackage = 'Error Writing Package';
lisPkgMangUnableToWritePackageToFileError = 'Unable to write package %s%s%s%' lisPkgMangUnableToWritePackageToFileError = 'Unable to write package %s%s%s%'

View File

@ -11136,7 +11136,7 @@ begin
writeln('[TMainIDE.DoShowCodeContext] ************'); writeln('[TMainIDE.DoShowCodeContext] ************');
{$ENDIF} {$ENDIF}
{$IFDEF IDE_MEM_CHECK}CheckHeapWrtMemCnt('TMainIDE.DoShowCodeContext A');{$ENDIF} {$IFDEF IDE_MEM_CHECK}CheckHeapWrtMemCnt('TMainIDE.DoShowCodeContext A');{$ENDIF}
Result:=ShowCodeContext(ActiveUnitInfo.Source,ActiveSrcEdit.EditorComponent); Result:=ShowCodeContext(ActiveUnitInfo.Source);
if not Result then begin if not Result then begin
if JumpToError then if JumpToError then
DoJumpToCodeToolBossError; DoJumpToCodeToolBossError;

View File

@ -271,6 +271,7 @@ type
function DoClosePackageEditor(APackage: TLazPackage): TModalResult; override; function DoClosePackageEditor(APackage: TLazPackage): TModalResult; override;
function DoCloseAllPackageEditors: TModalResult; override; function DoCloseAllPackageEditors: TModalResult; override;
function DoAddActiveUnitToAPackage: TModalResult; function DoAddActiveUnitToAPackage: TModalResult;
function WarnAboutMissingPackageFiles(APackage: TLazPackage): TModalResult;
// package compilation // package compilation
function DoCompileProjectDependencies(AProject: TProject; function DoCompileProjectDependencies(AProject: TProject;
@ -2706,48 +2707,6 @@ end;
function TPkgManager.DoSavePackage(APackage: TLazPackage; function TPkgManager.DoSavePackage(APackage: TLazPackage;
Flags: TPkgSaveFlags): TModalResult; Flags: TPkgSaveFlags): TModalResult;
function WarnAboutMissingPackageFiles: TModalResult;
var
i: Integer;
AFile: TPkgFile;
AFilename: String;
begin
Result:=mrOk;
for i:=0 to APackage.FileCount-1 do begin
AFile:=APackage.Files[i];
if AFile.FileType=pftVirtualUnit then continue;
AFilename:=AFile.Filename;
if System.Pos('$(',AFilename)>0 then begin
// filename contains macros -> skip
end;
if FilenameIsAbsolute(AFilename) then begin
if not FileExistsCached(AFilename) then begin
if not APackage.IsVirtual then
AFilename:=CreateRelativePath(AFilename,APackage.Directory);
Result:=QuestionDlg('Package file missing',
'The file "'+AFilename+'"'#13
+'of package '+APackage.IDAsString+' is missing.',
mtWarning,[mrIgnore,mrAbort],0);
if Result<>mrAbort then
Result:=mrOk;
// one warning is enough
exit;
end;
end else begin
if not APackage.IsVirtual then begin
// an unsaved file
Result:=QuestionDlg('Package file not saved',
'The file "'+AFilename+'"'#13
+'of package '+APackage.IDAsString+' needs to be saved first.',
mtWarning,[mrIgnore,'Ignore and save package now',mrAbort],0);
if Result<>mrAbort then
Result:=mrOk;
end;
end;
end;
end;
var var
XMLConfig: TXMLConfig; XMLConfig: TXMLConfig;
PkgLink: TPackageLink; PkgLink: TPackageLink;
@ -2779,7 +2738,7 @@ begin
end; end;
// warn about missing files // warn about missing files
Result:=WarnAboutMissingPackageFiles; Result:=WarnAboutMissingPackageFiles(APackage);
if Result<>mrOk then exit; if Result<>mrOk then exit;
// save editor files to codetools // save editor files to codetools
@ -2972,6 +2931,9 @@ begin
if Result<>mrOk then exit; if Result<>mrOk then exit;
end; end;
Result:=WarnAboutMissingPackageFiles(APackage);
if Result<>mrOk then exit;
PackageGraph.BeginUpdate(false); PackageGraph.BeginUpdate(false);
try try
// automatically compile required packages // automatically compile required packages
@ -3849,6 +3811,51 @@ begin
Result:=ShowAddFileToAPackageDlg(Filename,TheUnitName,HasRegisterProc); Result:=ShowAddFileToAPackageDlg(Filename,TheUnitName,HasRegisterProc);
end; end;
function TPkgManager.WarnAboutMissingPackageFiles(APackage: TLazPackage
): TModalResult;
var
i: Integer;
AFile: TPkgFile;
AFilename: String;
begin
Result:=mrOk;
for i:=0 to APackage.FileCount-1 do begin
AFile:=APackage.Files[i];
if AFile.FileType=pftVirtualUnit then continue;
AFilename:=AFile.Filename;
if System.Pos('$(',AFilename)>0 then begin
// filename contains macros -> skip
end;
if (not APackage.IsVirtual) and FilenameIsAbsolute(AFilename) then
APackage.LongenFilename(AFilename);
if FilenameIsAbsolute(AFilename) then begin
if not FileExistsCached(AFilename) then begin
if not APackage.IsVirtual then
AFilename:=CreateRelativePath(AFilename,APackage.Directory);
Result:=QuestionDlg(lisPkgMangPackageFileMissing,
Format(lisPkgMangTheFileOfPackageIsMissing, ['"', AFilename, '"',
#13, APackage.IDAsString]),
mtWarning,[mrIgnore,mrAbort],0);
if Result<>mrAbort then
Result:=mrOk;
// one warning is enough
exit;
end;
end else begin
if not APackage.IsVirtual then begin
// an unsaved file
Result:=QuestionDlg(lisPkgMangPackageFileNotSaved,
Format(lisPkgMangTheFileOfPackageNeedsToBeSavedFirst, ['"',
AFilename, '"', #13, APackage.IDAsString]),
mtWarning, [mrIgnore, lisPkgMangIgnoreAndSavePackageNow, mrAbort], 0
);
if Result<>mrAbort then
Result:=mrOk;
end;
end;
end;
end;
function TPkgManager.DoInstallPackage(APackage: TLazPackage): TModalResult; function TPkgManager.DoInstallPackage(APackage: TLazPackage): TModalResult;
var var
PkgList: TList; PkgList: TList;