mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-22 16:19:36 +02:00
MG: enhanced code caching, fixed CursorToCleanPos and beautify statement
git-svn-id: trunk@522 -
This commit is contained in:
parent
29511ac4bb
commit
8c514a5ded
@ -60,13 +60,15 @@ type
|
||||
procedure SetFilename(const Value: string);
|
||||
procedure SetScanner(const Value: TLinkScanner);
|
||||
procedure SetIsDeleted(const NewValue: boolean);
|
||||
procedure MakeFileDateValid;
|
||||
public
|
||||
property Scanner: TLinkScanner read FScanner write SetScanner;
|
||||
property LastIncludedByFile: string
|
||||
read FLastIncludedByFile write FLastIncludedByFile;
|
||||
property Filename: string read FFilename write SetFilename;
|
||||
function LoadFromFile(const AFilename: string): boolean; override;
|
||||
function Reload: boolean;
|
||||
function Reload: boolean; // = LoadFromFile(Filename)
|
||||
function Revert: boolean; // ignore changes and reload source
|
||||
function SaveToFile(const AFilename: string): boolean; override;
|
||||
function Save: boolean;
|
||||
property FileDateValid: boolean read FFileDateValid;
|
||||
@ -74,6 +76,7 @@ type
|
||||
function FileDateOnDisk: longint;
|
||||
function FileNeedsUpdate: boolean;
|
||||
function FileOnDiskNeedsUpdate: boolean;
|
||||
function FileOnDiskHasChanged: boolean;
|
||||
property OnSetScanner: TNotifyEvent read FOnSetScanner write FOnSetScanner;
|
||||
property OnSetFilename: TNotifyEvent read FOnSetFilename write FOnSetFilename;
|
||||
property IsVirtual: boolean read FIsVirtual;
|
||||
@ -225,10 +228,10 @@ end;
|
||||
|
||||
function TCodeCache.LoadFile(const AFilename: string): TCodeBuffer;
|
||||
// search file in cache
|
||||
// WARING: this will not check, if file on disk is newer
|
||||
begin
|
||||
Result:=FindFile(AFilename);
|
||||
if Result=nil then begin
|
||||
// load new buffer
|
||||
Result:=TCodeBuffer.Create;
|
||||
Result.Filename:=AFilename;
|
||||
if (not FileExists(AFilename)) or (not Result.LoadFromFile(AFilename)) then
|
||||
@ -243,6 +246,7 @@ begin
|
||||
LastIncludedByFile:=Self.LastIncludedByFile(AFilename);
|
||||
end;
|
||||
end else if Result.IsDeleted then begin
|
||||
// file in cache, but marked as deleted -> load from disk
|
||||
if (not FileExists(AFilename)) or (not Result.LoadFromFile(AFilename)) then
|
||||
begin
|
||||
Result:=nil;
|
||||
@ -382,12 +386,8 @@ begin
|
||||
end;
|
||||
|
||||
function TCodeCache.OnScannerCheckFileOnDisk(Code: pointer): boolean;
|
||||
var Buf: TCodeBuffer;
|
||||
begin
|
||||
Buf:=TCodeBuffer(Code);
|
||||
Result:=(not Buf.FileNeedsUpdate) and Buf.FileOnDiskNeedsUpdate;
|
||||
if Result then
|
||||
Result:=Buf.LoadFromFile(Buf.Filename);
|
||||
Result:=TCodeBuffer(Code).Reload;
|
||||
end;
|
||||
|
||||
procedure TCodeCache.OnScannerIncludeCode(ParentCode, IncludeCode: pointer);
|
||||
@ -589,20 +589,16 @@ begin
|
||||
end;
|
||||
if not IsVirtual then begin
|
||||
if CompareFilenames(AFilename,Filename)=0 then begin
|
||||
//writeln('****** [TCodeBuffer.LoadFromFile] ',Filename,' ',FFileDateValid,' ',FFileDate,',',FileAge(Filename),',',FFileChangeStep,',',ChangeStep);
|
||||
if (not FFileDateValid) or (FFileChangeStep<>ChangeStep)
|
||||
or (FFileDate<>FileAge(Filename)) then begin
|
||||
Result:=inherited LoadFromFile(AFilename)
|
||||
//writeln('****** [TCodeBuffer.LoadFromFile] ',Filename,' FileDateValid=',FileDateValid,' ',FFileDate,',',FileAge(Filename),',',FFileChangeStep,',',ChangeStep,', NeedsUpdate=',FileNeedsUpdate);
|
||||
if FileNeedsUpdate then begin
|
||||
Result:=inherited LoadFromFile(AFilename);
|
||||
if Result then MakeFileDateValid;
|
||||
end else
|
||||
Result:=true;
|
||||
if FIsDeleted then FIsDeleted:=not Result;
|
||||
if Result then begin
|
||||
FFileChangeStep:=ChangeStep;
|
||||
FFileDateValid:=true;
|
||||
FFileDate:=FileAge(Filename);
|
||||
end;
|
||||
end else begin
|
||||
Result:=inherited LoadFromFile(AFilename)
|
||||
Result:=inherited LoadFromFile(AFilename);
|
||||
if Result then MakeFileDateValid;
|
||||
end;
|
||||
end else
|
||||
Result:=false;
|
||||
@ -614,11 +610,7 @@ begin
|
||||
//writeln('TCodeBuffer.SaveToFile ',Filename,' -> ',AFilename,' ',Result);
|
||||
if CompareFilenames(AFilename,Filename)=0 then begin
|
||||
if FIsDeleted then FIsDeleted:=not Result;
|
||||
if Result then begin
|
||||
FFileChangeStep:=ChangeStep;
|
||||
FFileDateValid:=true;
|
||||
FFileDate:=FileAge(Filename);
|
||||
end;
|
||||
if Result then MakeFileDateValid;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -627,6 +619,16 @@ begin
|
||||
Result:=LoadFromFile(Filename);
|
||||
end;
|
||||
|
||||
function TCodeBuffer.Revert: boolean;
|
||||
// ignore changes and reload source
|
||||
begin
|
||||
if not IsVirtual then begin
|
||||
Result:=inherited LoadFromFile(Filename);
|
||||
if Result then MakeFileDateValid;
|
||||
end else
|
||||
Result:=false;
|
||||
end;
|
||||
|
||||
function TCodeBuffer.Save: boolean;
|
||||
begin
|
||||
if not IsVirtual then
|
||||
@ -671,23 +673,41 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCodeBuffer.MakeFileDateValid;
|
||||
begin
|
||||
FFileChangeStep:=ChangeStep;
|
||||
FFileDateValid:=true;
|
||||
FFileDate:=FileAge(Filename);
|
||||
end;
|
||||
|
||||
function TCodeBuffer.FileDateOnDisk: longint;
|
||||
begin
|
||||
Result:=FileAge(Filename);
|
||||
end;
|
||||
|
||||
function TCodeBuffer.FileNeedsUpdate: boolean;
|
||||
// file needs update, if file is not modified and file on disk is changed
|
||||
begin
|
||||
if FileDateValid then
|
||||
Result:=(FileDateOnDisk>FileDate)
|
||||
Result:=(not Modified) and (FFileChangeStep=ChangeStep)
|
||||
and (FileDateOnDisk>FileDate)
|
||||
else
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
function TCodeBuffer.FileOnDiskNeedsUpdate: boolean;
|
||||
// file on disk needs update, if file is modified
|
||||
begin
|
||||
if FileDateValid then
|
||||
Result:=(FFileChangeStep<>ChangeStep) or (FFileDate<>FileDateOnDisk)
|
||||
Result:=Modified or (FFileChangeStep<>ChangeStep)
|
||||
else
|
||||
Result:=false;
|
||||
end;
|
||||
|
||||
function TCodeBuffer.FileOnDiskHasChanged: boolean;
|
||||
begin
|
||||
if FileDateValid then
|
||||
Result:=(FileDateOnDisk<>FileDate)
|
||||
else
|
||||
Result:=false;
|
||||
end;
|
||||
|
@ -218,13 +218,13 @@ var Parts: array[TPropPart] of TAtomPosition;
|
||||
|
||||
function ReadSimpleSpec(SpecWord, SpecParam: TPropPart): boolean;
|
||||
begin
|
||||
if Parts[SpecWord].StartPos>=1 then begin
|
||||
Result:=false;
|
||||
exit;
|
||||
end;
|
||||
if Parts[SpecWord].StartPos>=1 then
|
||||
RaiseException('property specifier already defined: '+GetAtom);
|
||||
Parts[SpecWord]:=CurPos;
|
||||
ReadNextAtom;
|
||||
Result:=AtomIsWord;
|
||||
if not Result then
|
||||
RaiseException('expected identifier but '+GetAtom+' found');
|
||||
if WordIsPropertySpecifier.DoItUpperCase(UpperSrc,CurPos.StartPos,
|
||||
CurPos.EndPos-CurPos.StartPos) then exit;
|
||||
Parts[SpecParam]:=CurPos;
|
||||
@ -250,12 +250,12 @@ writeln('[TCodeCompletionCodeTool.CompleteProperty] Checking Property ',GetAtom)
|
||||
// read parameter list '[ ... ]'
|
||||
Parts[ppParamList].StartPos:=CurPos.StartPos;
|
||||
InitExtraction;
|
||||
if not ReadParamList(false,true,[phpInUpperCase,phpWithoutBrackets])
|
||||
if not ReadParamList(true,true,[phpInUpperCase,phpWithoutBrackets])
|
||||
then begin
|
||||
{$IFDEF CTDEBUG}
|
||||
writeln('[TCodeCompletionCodeTool.CompleteProperty] error parsing param list');
|
||||
{$ENDIF}
|
||||
exit;
|
||||
RaiseException('error in paramlist');
|
||||
end;
|
||||
CleanParamList:=GetExtraction;
|
||||
Parts[ppParamList].EndPos:=CurPos.EndPos;
|
||||
@ -273,22 +273,26 @@ writeln('[TCodeCompletionCodeTool.CompleteProperty] no type : found -> ignore pr
|
||||
if (CurPos.StartPos>PropNode.EndPos)
|
||||
or UpAtomIs('END') or AtomIsChar(';') or (not AtomIsIdentifier(false))
|
||||
or AtomIsKeyWord then begin
|
||||
// no type name found -> ignore this property
|
||||
{$IFDEF CTDEBUG}
|
||||
writeln('[TCodeCompletionCodeTool.CompleteProperty] error: no type name found');
|
||||
{$ENDIF}
|
||||
Result:=true;
|
||||
exit;
|
||||
end;
|
||||
Parts[ppType]:=CurPos;
|
||||
// read specifiers
|
||||
ReadNextAtom;
|
||||
if UpAtomIs('INDEX') then begin
|
||||
if Parts[ppIndexWord].StartPos>=1 then exit;
|
||||
if Parts[ppIndexWord].StartPos>=1 then
|
||||
RaiseException('index specifier redefined');
|
||||
Parts[ppIndexWord]:=CurPos;
|
||||
ReadNextAtom;
|
||||
if WordIsPropertySpecifier.DoItUpperCase(UpperSrc,CurPos.StartPos,
|
||||
CurPos.EndPos-CurPos.StartPos) then exit;
|
||||
CurPos.EndPos-CurPos.StartPos) then
|
||||
RaiseException('index parameter expected, but '+GetAtom+' found');
|
||||
Parts[ppIndex].StartPos:=CurPos.StartPos;
|
||||
if not ReadConstant(false,false,[]) then exit;
|
||||
if not ReadConstant(true,false,[]) then exit;
|
||||
Parts[ppIndex].EndPos:=LastAtoms.GetValueAt(0).EndPos;
|
||||
end;
|
||||
if UpAtomIs('READ') and not ReadSimpleSpec(ppReadWord,ppRead) then exit;
|
||||
@ -300,24 +304,28 @@ writeln('[TCodeCompletionCodeTool.CompleteProperty] error: no type name found');
|
||||
if not ReadSimpleSpec(ppStoredWord,ppStored) then
|
||||
exit;
|
||||
end else if UpAtomIs('DEFAULT') then begin
|
||||
if Parts[ppDefaultWord].StartPos>=1 then exit;
|
||||
if Parts[ppDefaultWord].StartPos>=1 then
|
||||
RaiseException('default specifier redefined');
|
||||
Parts[ppDefaultWord]:=CurPos;
|
||||
ReadNextAtom;
|
||||
if WordIsPropertySpecifier.DoItUpperCase(UpperSrc,CurPos.StartPos,
|
||||
CurPos.EndPos-CurPos.StartPos) then exit;
|
||||
CurPos.EndPos-CurPos.StartPos) then
|
||||
RaiseException('default parameter expected, but '+GetAtom+' found');
|
||||
Parts[ppDefault].StartPos:=CurPos.StartPos;
|
||||
if not ReadConstant(false,false,[]) then exit;
|
||||
if not ReadConstant(true,false,[]) then exit;
|
||||
Parts[ppDefault].EndPos:=LastAtoms.GetValueAt(0).EndPos;
|
||||
end else if UpAtomIs('IMPLEMENTS') then begin
|
||||
if not ReadSimpleSpec(ppImplementsWord,ppImplements) then exit;
|
||||
end else if UpAtomIs('NODEFAULT') then begin
|
||||
if Parts[ppNoDefaultWord].StartPos>=1 then exit;
|
||||
if Parts[ppNoDefaultWord].StartPos>=1 then
|
||||
RaiseException('nodefault specifier defined twice');
|
||||
Parts[ppNoDefaultWord]:=CurPos;
|
||||
ReadNextAtom;
|
||||
end else
|
||||
exit;
|
||||
RaiseException('; expected, but '+GetAtom+' found');
|
||||
end;
|
||||
if (CurPos.StartPos>PropNode.EndPos) then exit;
|
||||
if (CurPos.StartPos>PropNode.EndPos) then
|
||||
RaiseException('Reparsing error (Complete Property)');
|
||||
PropType:=copy(Src,Parts[ppType].StartPos,
|
||||
Parts[ppType].EndPos-Parts[ppType].StartPos);
|
||||
// check read specifier
|
||||
@ -370,14 +378,14 @@ writeln('[TCodeCompletionCodeTool.CompleteProperty] CleanAccessFunc ',CleanAcces
|
||||
MoveCursorToCleanPos(Parts[ppParamList].StartPos);
|
||||
ReadNextAtom;
|
||||
InitExtraction;
|
||||
if not ReadParamList(false,true,[phpWithParameterNames,
|
||||
if not ReadParamList(true,true,[phpWithParameterNames,
|
||||
phpWithoutBrackets,phpWithVarModifiers,
|
||||
phpWithComments])
|
||||
then begin
|
||||
{$IFDEF CTDEBUG}
|
||||
writeln('[TCodeCompletionCodeTool.CompleteProperty] Error reading param list');
|
||||
{$ENDIF}
|
||||
exit;
|
||||
RaiseException('error in parameter list');
|
||||
end;
|
||||
ParamList:=GetExtraction;
|
||||
if (Parts[ppIndexWord].StartPos<1) then begin
|
||||
@ -483,11 +491,11 @@ writeln('[TCodeCompletionCodeTool.CompleteProperty] write specifier needed');
|
||||
MoveCursorToCleanPos(Parts[ppParamList].StartPos);
|
||||
ReadNextAtom;
|
||||
InitExtraction;
|
||||
if not ReadParamList(false,true,[phpWithParameterNames,
|
||||
if not ReadParamList(true,true,[phpWithParameterNames,
|
||||
phpWithoutBrackets,phpWithVarModifiers,
|
||||
phpWithComments])
|
||||
then
|
||||
exit;
|
||||
RaiseException('error in param list');
|
||||
ParamList:=GetExtraction;
|
||||
if (Parts[ppIndexWord].StartPos<1) then begin
|
||||
// param list, no index
|
||||
@ -706,7 +714,9 @@ var
|
||||
ProcCode:=ANodeExt.ExtTxt1;
|
||||
ProcCode:=ASourceChangeCache.BeautifyCodeOptions.AddClassNameToProc(
|
||||
ProcCode,TheClassName);
|
||||
{$IFDEF CTDEBUG}
|
||||
writeln('>>> InsertProcBody ',TheClassName,' "',ProcCode,'"');
|
||||
{$ENDIF}
|
||||
ProcCode:=ASourceChangeCache.BeautifyCodeOptions.BeautifyProc(
|
||||
ProcCode,Indent,true);
|
||||
ASourceChangeCache.Replace(gtEmptyLine,gtEmptyLine,InsertPos,InsertPos,
|
||||
@ -729,6 +739,7 @@ begin
|
||||
{$IFDEF CTDEBUG}
|
||||
writeln('TCodeCompletionCodeTool.CreateMissingProcBodies Gather existing method bodies ... ');
|
||||
{$ENDIF}
|
||||
Result:=false;
|
||||
// gather existing class proc bodies
|
||||
TypeSectionNode:=ClassNode.Parent;
|
||||
if (TypeSectionNode<>nil) and (TypeSectionNode.Parent<>nil)
|
||||
@ -791,17 +802,20 @@ writeln('TCodeCompletionCodeTool.CreateMissingProcBodies Gather existing method
|
||||
// class is in interface section
|
||||
// -> insert at the end of the implementation section
|
||||
ImplementationNode:=FindImplementationNode;
|
||||
if ImplementationNode=nil then exit;
|
||||
if ImplementationNode=nil then
|
||||
RaiseException('implementation node not found');
|
||||
Indent:=GetLineIndent(Src,ImplementationNode.StartPos);
|
||||
InsertPos:=ImplementationNode.EndPos;
|
||||
end else begin
|
||||
// class is not in interface section
|
||||
// -> insert at the end of the type section
|
||||
ANode:=ClassNode.Parent; // type definition
|
||||
if ANode=nil then exit;
|
||||
if ANode=nil then
|
||||
RaiseException('class node without parent node');
|
||||
if ANode.Parent.Desc=ctnTypeSection then
|
||||
ANode:=ANode.Parent; // type section
|
||||
if ANode=nil then exit;
|
||||
if ANode=nil then
|
||||
RaiseException('type section of class section not found');
|
||||
Indent:=GetLineIndent(Src,ANode.StartPos);
|
||||
InsertPos:=ANode.EndPos;
|
||||
end;
|
||||
@ -919,21 +933,24 @@ var CleanCursorPos, Dummy, Indent, insertPos: integer;
|
||||
ANodeExt: TCodeTreeNodeExtension;
|
||||
begin
|
||||
Result:=false;
|
||||
if (SourceChangeCache=nil) then exit;
|
||||
if (SourceChangeCache=nil) then
|
||||
RaiseException('need a SourceChangeCache');
|
||||
// in a class or in a forward proc?
|
||||
BuildTree(false);
|
||||
if not EndOfSourceFound then exit;
|
||||
if not EndOfSourceFound then
|
||||
RaiseException('End of Source not found');
|
||||
ASourceChangeCache:=SourceChangeCache;
|
||||
SourceChangeCache.MainScanner:=Scanner;
|
||||
// find the CursorPos in cleaned source
|
||||
Dummy:=CaretToCleanPos(CursorPos, CleanCursorPos);
|
||||
if (Dummy<>0) and (Dummy<>-1) then exit;
|
||||
if (Dummy<>0) and (Dummy<>-1) then
|
||||
RaiseException('cursor pos outside of code');
|
||||
// find CodeTreeNode at cursor
|
||||
CursorNode:=FindDeepestNodeAtPos(CleanCursorPos);
|
||||
if CursorNode=nil then
|
||||
exit;
|
||||
RaiseException('no valid node found at cursor');
|
||||
{$IFDEF CTDEBUG}
|
||||
writeln('TCodeCompletionCodeTool.CompleteCode A ',NodeDescriptionAsString(CursorNode.Desc));
|
||||
writeln('TCodeCompletionCodeTool.CompleteCode A CleanCursorPos=',CleanCursorPos,' NodeDesc=',NodeDescriptionAsString(CursorNode.Desc));
|
||||
{$ENDIF}
|
||||
ImplementationNode:=FindImplementationNode;
|
||||
if ImplementationNode=nil then ImplementationNode:=Tree.Root;
|
||||
@ -957,7 +974,8 @@ writeln('TCodeCompletionCodeTool.CompleteCode C ',CleanCursorPos,', |',copy(Src,
|
||||
StartNode:=ClassNode.FirstChild;
|
||||
while (StartNode<>nil) and (StartNode.FirstChild=nil) do
|
||||
StartNode:=StartNode.NextBrother;
|
||||
if StartNode=nil then exit;
|
||||
if StartNode=nil then
|
||||
RaiseException('error parsing class');
|
||||
StartNode:=StartNode.FirstChild;
|
||||
JumpToProc:='';
|
||||
try
|
||||
@ -973,7 +991,8 @@ writeln('TCodeCompletionCodeTool.CompleteCode Complete Properties ... ');
|
||||
while ANode<>nil do begin
|
||||
if ANode.Desc=ctnProperty then begin
|
||||
// check if property is complete
|
||||
if not CompleteProperty(ANode) then exit;
|
||||
if not CompleteProperty(ANode) then
|
||||
RaiseException('unable to complete property');
|
||||
end;
|
||||
ANode:=ANode.NextBrother;
|
||||
end;
|
||||
@ -984,19 +1003,22 @@ writeln('TCodeCompletionCodeTool.CompleteCode Complete Properties ... ');
|
||||
writeln('TCodeCompletionCodeTool.CompleteCode Insert new variables and methods ... ');
|
||||
{$ENDIF}
|
||||
// insert all new variables and procs definitions
|
||||
if not InsertAllNewClassParts then exit;
|
||||
if not InsertAllNewClassParts then
|
||||
RaiseException('error during inserting new class parts');
|
||||
|
||||
{$IFDEF CTDEBUG}
|
||||
writeln('TCodeCompletionCodeTool.CompleteCode Insert new method bodies ... ');
|
||||
{$ENDIF}
|
||||
// insert all missing proc bodies
|
||||
if not CreateMissingProcBodies then exit;
|
||||
if not CreateMissingProcBodies then
|
||||
RaiseException('error during creation of new proc bodies');
|
||||
|
||||
{$IFDEF CTDEBUG}
|
||||
writeln('TCodeCompletionCodeTool.CompleteCode Apply ... ');
|
||||
{$ENDIF}
|
||||
// apply the changes and jump to first new proc body
|
||||
if not SourceChangeCache.Apply then exit;
|
||||
if not SourceChangeCache.Apply then
|
||||
RaiseException('unable to apply changes');
|
||||
|
||||
if JumpToProc<>'' then begin
|
||||
// there was a new proc body
|
||||
@ -1004,25 +1026,31 @@ writeln('TCodeCompletionCodeTool.CompleteCode Apply ... ');
|
||||
|
||||
// reparse code
|
||||
BuildTree(false);
|
||||
if not EndOfSourceFound then exit;
|
||||
if not EndOfSourceFound then
|
||||
RaiseException('End of source not found');
|
||||
// find the CursorPos in cleaned source
|
||||
Dummy:=CaretToCleanPos(CursorPos, CleanCursorPos);
|
||||
if (Dummy<>0) and (Dummy<>-1) then exit;
|
||||
if (Dummy<>0) and (Dummy<>-1) then
|
||||
RaiseException('cursor pos outside of code');
|
||||
// find CodeTreeNode at cursor
|
||||
CursorNode:=FindDeepestNodeAtPos(CleanCursorPos);
|
||||
if CursorNode=nil then exit;
|
||||
if CursorNode=nil then
|
||||
RaiseException('no valid node found at cursor');
|
||||
|
||||
ClassNode:=CursorNode;
|
||||
while (ClassNode<>nil) and (ClassNode.Desc<>ctnClass) do
|
||||
ClassNode:=ClassNode.Parent;
|
||||
if ClassNode=nil then exit;
|
||||
if ClassNode=nil then
|
||||
RaiseException('oops, I loosed your class');
|
||||
ANode:=ClassNode.Parent;
|
||||
if ANode=nil then exit;
|
||||
if ANode=nil then
|
||||
RaiseException('class without parent node');
|
||||
if (ANode.Parent<>nil) and (ANode.Parent.Desc=ctnTypeSection) then
|
||||
ANode:=ANode.Parent;
|
||||
ProcNode:=FindProcNode(ANode,JumpToProc,
|
||||
[phpInUpperCase,phpIgnoreForwards]);
|
||||
if ProcNode=nil then exit;
|
||||
if ProcNode=nil then
|
||||
RaiseException('new proc body not found');
|
||||
Result:=FindJumpPointInProcNode(ProcNode,NewPos,NewTopLine);
|
||||
exit;
|
||||
end else begin
|
||||
@ -1046,12 +1074,18 @@ writeln('TCodeCompletionCodeTool.CompleteCode Apply ... ');
|
||||
end;
|
||||
|
||||
end else begin
|
||||
{$IFDEF CTDEBUG}
|
||||
writeln('TCodeCompletionCodeTool.CompleteCode not in-a-class ... ');
|
||||
{$ENDIF}
|
||||
// then test if forward proc
|
||||
ProcNode:=CursorNode;
|
||||
if ProcNode.Desc=ctnProcedureHead then ProcNode:=ProcNode.Parent;
|
||||
if (ProcNode.Desc=ctnProcedure)
|
||||
and (ProcNode.SubDesc=ctnsForwardDeclaration) then begin
|
||||
// Node is forward Proc
|
||||
{$IFDEF CTDEBUG}
|
||||
writeln('TCodeCompletionCodeTool.CompleteCode in a forward procedure ... ');
|
||||
{$ENDIF}
|
||||
|
||||
// check if proc already exists
|
||||
ProcCode:=ExtractProcHead(ProcNode,[phpInUpperCase]);
|
||||
@ -1059,6 +1093,9 @@ writeln('TCodeCompletionCodeTool.CompleteCode Apply ... ');
|
||||
[phpInUpperCase])<>nil
|
||||
then exit;
|
||||
|
||||
{$IFDEF CTDEBUG}
|
||||
writeln('TCodeCompletionCodeTool.CompleteCode Body not found -> create it ... ');
|
||||
{$ENDIF}
|
||||
// -> create proc body at end of implementation
|
||||
|
||||
Indent:=GetLineIndent(Src,ImplementationNode.StartPos);
|
||||
@ -1068,7 +1105,8 @@ writeln('TCodeCompletionCodeTool.CompleteCode Apply ... ');
|
||||
else begin
|
||||
// insert in front of main program begin..end.
|
||||
StartNode:=ImplementationNode.LastChild;
|
||||
if (StartNode=nil) or (StartNode.Desc<>ctnBeginBlock) then exit;
|
||||
if (StartNode=nil) or (StartNode.Desc<>ctnBeginBlock) then
|
||||
RaiseException('main Begin..End block not found');
|
||||
InsertPos:=FindLineEndOrCodeInFrontOfPosition(Src,StartNode.StartPos,
|
||||
Scanner.NestedComments);
|
||||
end;
|
||||
@ -1076,16 +1114,23 @@ writeln('TCodeCompletionCodeTool.CompleteCode Apply ... ');
|
||||
// build nice proc
|
||||
ProcCode:=ExtractProcHead(ProcNode,[phpWithStart,phpWithVarModifiers,
|
||||
phpWithParameterNames,phpWithResultType,phpWithComments]);
|
||||
if ProcCode='' then exit;
|
||||
if ProcCode='' then
|
||||
RaiseException('unable to reparse proc node');
|
||||
ProcCode:=SourceChangeCache.BeautifyCodeOptions.BeautifyProc(ProcCode,
|
||||
Indent,true);
|
||||
if not SourceChangeCache.Replace(gtEmptyLine,gtEmptyLine,
|
||||
InsertPos,InsertPos,ProcCode) then exit;
|
||||
if not SourceChangeCache.Apply then exit;
|
||||
InsertPos,InsertPos,ProcCode) then
|
||||
RaiseException('unable to insert new proc body');
|
||||
if not SourceChangeCache.Apply then
|
||||
RaiseException('unable to apply changes');
|
||||
|
||||
// reparse code and find jump point into new proc
|
||||
Result:=FindJumpPoint(CursorPos,NewPos,NewTopLine);
|
||||
exit;
|
||||
end else begin
|
||||
{$IFDEF CTDEBUG}
|
||||
writeln('TCodeCompletionCodeTool.CompleteCode nothing to complete ... ');
|
||||
{$ENDIF}
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
@ -97,7 +97,8 @@ type
|
||||
property SourceExtensions: string
|
||||
read FSourceExtensions write FSourceExtensions;
|
||||
function FindFile(const ExpandedFilename: string): TCodeBuffer;
|
||||
function LoadFile(const ExpandedFilename: string): TCodeBuffer;
|
||||
function LoadFile(const ExpandedFilename: string;
|
||||
UpdateFromDisk, Revert: boolean): TCodeBuffer;
|
||||
function CreateFile(const AFilename: string): TCodeBuffer;
|
||||
function SaveBufferAs(OldBuffer: TCodeBuffer;const ExpandedFilename: string;
|
||||
var NewBuffer: TCodeBuffer): boolean;
|
||||
@ -299,9 +300,19 @@ begin
|
||||
Result:=SourceCache.FindFile(ExpandedFilename);
|
||||
end;
|
||||
|
||||
function TCodeToolManager.LoadFile(const ExpandedFilename: string): TCodeBuffer;
|
||||
function TCodeToolManager.LoadFile(const ExpandedFilename: string;
|
||||
UpdateFromDisk, Revert: boolean): TCodeBuffer;
|
||||
begin
|
||||
{$IFDEF CTDEBUG}
|
||||
writeln('>>>>>>>>>>>>>>> [TCodeToolManager.LoadFile] ',ExpandedFilename,' Update=',UpdateFromDisk,' Revert=',Revert);
|
||||
{$ENDIF}
|
||||
Result:=SourceCache.LoadFile(ExpandedFilename);
|
||||
if Result<>nil then begin
|
||||
if Revert then
|
||||
Result.Revert
|
||||
else if UpdateFromDisk then
|
||||
Result.Reload;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCodeToolManager.CreateFile(const AFilename: string): TCodeBuffer;
|
||||
|
@ -877,11 +877,14 @@ end;
|
||||
function TCustomCodeTool.CaretToCleanPos(Caret: TCodeXYPosition;
|
||||
var CleanPos: integer): integer;
|
||||
begin
|
||||
//writeln('TCustomCodeTool.CaretToCleanPos A ',Caret.Code.Filename,' ',Caret.Code.SourceLength);
|
||||
Caret.Code.LineColToPosition(Caret.Y,Caret.X,CleanPos);
|
||||
//writeln('TCustomCodeTool.CaretToCleanPos B ',CleanPos,',',Caret.Y,',',Caret.X);
|
||||
if (CleanPos>=1) then
|
||||
Result:=Scanner.CursorToCleanPos(CleanPos,Caret.Code,CleanPos)
|
||||
else
|
||||
Result:=-2; // x,y beyond source
|
||||
//writeln('TCustomCodeTool.CaretToCleanPos C CleanPos=',CleanPos,' Result=',Result);
|
||||
end;
|
||||
|
||||
function TCustomCodeTool.CleanPosToCaret(CleanPos: integer;
|
||||
|
@ -46,6 +46,7 @@ uses
|
||||
type
|
||||
TFindDeclarationTool = class(TPascalParserTool)
|
||||
public
|
||||
//function FindDeclaration(CursorPos: TCodeXYPosition; var NewPos: TCodeXYPosition; var NewTopLine: integer): boolean;
|
||||
|
||||
end;
|
||||
|
||||
|
@ -1446,31 +1446,32 @@ var i, j: integer;
|
||||
begin
|
||||
i:=0;
|
||||
while i<LinkCount do begin
|
||||
//writeln('[TLinkScanner.CursorToCleanPos] A ACursorPos=',ACursorPos,', Code=',Links[i].Code=ACode,', Links[i].SrcPos=',Links[i].SrcPos,', Links[i].CleanedPos=',Links[i].CleanedPos);
|
||||
if (Links[i].Code=ACode) and (Links[i].SrcPos<=ACursorPos) then begin
|
||||
ACleanPos:=ACursorPos-Links[i].SrcPos+Links[i].CleanedPos;
|
||||
j:=i+1;
|
||||
while (j<LinkCount) and (Links[j].Code<>ACode) do inc(j);
|
||||
if (j<LinkCount) then begin
|
||||
// there is a link after in the same code
|
||||
if ACleanPos<Links[j].CleanedPos then begin
|
||||
Result:=0; exit; // valid position
|
||||
end else begin
|
||||
// search next ...
|
||||
//writeln('[TLinkScanner.CursorToCleanPos] B ACleanPos=',ACleanPos);
|
||||
if i+1<LinkCount then begin
|
||||
//writeln('[TLinkScanner.CursorToCleanPos] C Links[i+1].CleanedPos=',Links[i+1].CleanedPos);
|
||||
if ACleanPos<Links[i+1].CleanedPos then begin
|
||||
Result:=0; // valid position
|
||||
exit;
|
||||
end;
|
||||
j:=i+1;
|
||||
while (j<LinkCount) and (Links[j].Code<>ACode) do inc(j);
|
||||
//writeln('[TLinkScanner.CursorToCleanPos] D j=',j);
|
||||
if (j<LinkCount) and (Links[j].SrcPos>ACursorPos) then begin
|
||||
Result:=-1; // CursorPos was skipped, CleanPos is between two links
|
||||
exit;
|
||||
end;
|
||||
// search next
|
||||
i:=j-1;
|
||||
end else begin
|
||||
// last link in Cursor Code
|
||||
if i+1<LinkCount then begin
|
||||
if ACleanPos<Links[i+1].CleanedPos then
|
||||
Result:=0 // valid position
|
||||
else
|
||||
Result:=1; // cursor beyond scanned code
|
||||
end else begin
|
||||
// in last link
|
||||
if ACleanPos<=length(FCleanedSrc) then
|
||||
Result:=0 // valid position
|
||||
else
|
||||
Result:=1; // cursor beyond scanned code
|
||||
end;
|
||||
// in last link
|
||||
//writeln('[TLinkScanner.CursorToCleanPos] E length(FCleanedSrc)=',length(FCleanedSrc));
|
||||
if ACleanPos<=length(FCleanedSrc) then
|
||||
Result:=0 // valid position
|
||||
else
|
||||
Result:=1; // cursor beyond scanned code
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
@ -601,7 +601,7 @@ begin
|
||||
KeyWordPolicy:=wpLowerCase;
|
||||
IdentifierPolicy:=wpNone;
|
||||
DoNotSplitLineBefore:=[atColon,atComma,atSemicolon,atPoint];
|
||||
DoNotSplitLineAfter:=[atColon,atAt,atPoint];
|
||||
DoNotSplitLineAfter:=[atColon,atAt,atPoint,atKeyWord];
|
||||
DoInsertSpaceBefore:=[];
|
||||
DoInsertSpaceAfter:=[atColon,atComma,atSemicolon];
|
||||
PropertyReadIdentPrefix:='Get';
|
||||
@ -766,7 +766,8 @@ begin
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end else
|
||||
CurAtomType:=atNone;
|
||||
AtomEnd:=CurPos;
|
||||
end;
|
||||
|
||||
@ -808,17 +809,25 @@ begin
|
||||
CurLineLen:=length(Result);
|
||||
LastAtomType:=atNone;
|
||||
while (CurPos<=SrcLen) do begin
|
||||
ReadNextAtom;
|
||||
CurAtom:=copy(Src,AtomStart,AtomEnd-AtomStart);
|
||||
if ((CurAtomType in DoInsertSpaceBefore) and (not (LastAtomType=atSpace)))
|
||||
or ((CurAtomType<>atSpace) and (LastAtomType in DoInsertSpaceAfter)) then
|
||||
repeat
|
||||
ReadNextAtom;
|
||||
CurAtom:=copy(Src,AtomStart,AtomEnd-AtomStart);
|
||||
if CurAtom=' ' then
|
||||
AddAtom(Result,' ')
|
||||
else
|
||||
break;
|
||||
until false;
|
||||
if ((Result='') or (Result[length(Result)]<>' '))
|
||||
and ((CurAtomType in DoInsertSpaceBefore)
|
||||
or (LastAtomType in DoInsertSpaceAfter)) then
|
||||
AddAtom(Result,' ');
|
||||
if (not (CurAtomType in DoNotSplitLineBefore))
|
||||
and (not (LastAtomType in DoNotSplitLineAfter)) then
|
||||
LastSplitPos:=length(Result)+1;
|
||||
//writeln(' CurPos=',CurPos,' CurAtom="',CurAtom,
|
||||
//'" CurAtomType=',AtomTypeNames[CurAtomType],' LastAtomType=',AtomTypeNames[LastAtomType],
|
||||
//' ',LastAtomType in DoInsertSpaceAfter);
|
||||
{writeln('SPLIT LINE CurPos=',CurPos,' CurAtom="',CurAtom,
|
||||
'" CurAtomType=',AtomTypeNames[CurAtomType],' LastAtomType=',AtomTypeNames[LastAtomType],
|
||||
' ',LastAtomType in DoInsertSpaceAfter,' LastSplitPos=',LastSplitPos,
|
||||
' ..."',copy(Result,length(Result)-10,10),'"'); }
|
||||
AddAtom(Result,CurAtom);
|
||||
LastAtomType:=CurAtomType;
|
||||
end;
|
||||
|
@ -359,7 +359,7 @@ end;
|
||||
|
||||
procedure TSourceLog.SetSource(const NewSrc: string);
|
||||
begin
|
||||
//writeln('TSourceLog.SetSource ',length(NewSrc));
|
||||
//writeln('TSourceLog.SetSource A ',length(NewSrc),' LineCount=',fLineCount,' SrcLen=',fSrcLen);
|
||||
if NewSrc<>FSource then begin
|
||||
Clear;
|
||||
FSource:=NewSrc;
|
||||
@ -382,11 +382,11 @@ begin
|
||||
+Txt
|
||||
+copy(FSource,Pos,length(FSource)-Pos+1);
|
||||
FSrcLen:=length(FSource);
|
||||
FLineCount:=-1;
|
||||
for i:=0 to FMarkers.Count-1 do begin
|
||||
if (not Markers[i].Deleted) then
|
||||
NewSrcLogEntry.AdjustPosition(Markers[i].NewPosition);
|
||||
end;
|
||||
FLineCount:=-1;
|
||||
FModified:=true;
|
||||
IncreaseChangeStep;
|
||||
end;
|
||||
@ -402,6 +402,7 @@ begin
|
||||
NotifyHooks(NewSrcLogEntry);
|
||||
System.Delete(FSource,Pos,Len);
|
||||
FSrcLen:=length(FSource);
|
||||
FLineCount:=-1;
|
||||
for i:=0 to FMarkers.Count-1 do begin
|
||||
if (Markers[i].Deleted=false) then begin
|
||||
if (Markers[i].NewPosition<=Pos) and (Markers[i].NewPosition<Pos+Len) then
|
||||
@ -411,7 +412,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
FLineCount:=-1;
|
||||
FModified:=true;
|
||||
IncreaseChangeStep;
|
||||
end;
|
||||
@ -438,6 +438,7 @@ begin
|
||||
+Txt
|
||||
+copy(FSource,Pos+Len,length(FSource)-Pos-Len+1);
|
||||
FSrcLen:=length(FSource);
|
||||
FLineCount:=-1;
|
||||
for i:=0 to FMarkers.Count-1 do begin
|
||||
if (Markers[i].Deleted=false) then begin
|
||||
if (Markers[i].NewPosition<=Pos) and (Markers[i].NewPosition<Pos+Len) then
|
||||
@ -448,7 +449,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
FLineCount:=-1;
|
||||
FModified:=true;
|
||||
IncreaseChangeStep;
|
||||
end;
|
||||
@ -474,11 +474,11 @@ begin
|
||||
+copy(FSource,MoveTo,length(FSource)-MoveTo+1);
|
||||
end;
|
||||
FSrcLen:=length(FSource);
|
||||
FLineCount:=-1;
|
||||
for i:=0 to FMarkers.Count-1 do begin
|
||||
if (Markers[i].Deleted=false) then
|
||||
NewSrcLogEntry.AdjustPosition(Markers[i].NewPosition);
|
||||
end;
|
||||
FLineCount:=-1;
|
||||
FModified:=true;
|
||||
IncreaseChangeStep;
|
||||
end;
|
||||
@ -527,6 +527,7 @@ end;
|
||||
procedure TSourceLog.BuildLineRanges;
|
||||
var p,line:integer;
|
||||
begin
|
||||
//writeln('[TSourceLog.BuildLineRanges] A Self=',HexStr(Cardinal(Self),8),',LineCount=',FLineCount,' Len=',SourceLength);
|
||||
if FLineCount>=0 then exit;
|
||||
if FLineRanges<>nil then begin
|
||||
FreeMem(FLineRanges);
|
||||
@ -572,6 +573,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
//writeln('[TSourceLog.BuildLineRanges] END ',FLineCount);
|
||||
end;
|
||||
|
||||
procedure TSourceLog.LineColToPosition(Line, Column: integer;
|
||||
@ -666,6 +668,7 @@ function TSourceLog.SaveToFile(const Filename: string): boolean;
|
||||
var
|
||||
fs: TFileStream;
|
||||
begin
|
||||
//writeln('TSourceLog.SaveToFile Self=',HexStr(Cardinal(Self),8));
|
||||
Result:=true;
|
||||
try
|
||||
fs:=TFileStream.Create(Filename, fmCreate);
|
||||
@ -721,6 +724,7 @@ begin
|
||||
for y:=0 to sl.Count-1 do inc(fSrcLen,length(sl[y]));
|
||||
fSource:='';
|
||||
SetLength(fSource,fSrcLen);
|
||||
fLineCount:=-1;
|
||||
p:=1;
|
||||
for y:=0 to sl.Count-1 do begin
|
||||
s:=sl[y];
|
||||
@ -768,6 +772,7 @@ begin
|
||||
SetLength(fSource,fSrcLen);
|
||||
s.Read(fSource[1],fSrcLen);
|
||||
end;
|
||||
fLineCount:=-1;
|
||||
DecreaseHookLock;
|
||||
end;
|
||||
|
||||
|
46
ide/main.pp
46
ide/main.pp
@ -344,7 +344,7 @@ type
|
||||
function DoSaveCodeBufferToFile(ABuffer: TCodeBuffer;
|
||||
const AFilename: string; IsPartOfProject:boolean): TModalResult;
|
||||
function DoLoadCodeBuffer(var ACodeBuffer: TCodeBuffer;
|
||||
const AFilename: string): TModalResult;
|
||||
const AFilename: string; UpdateFromDisk, Revert: boolean): TModalResult;
|
||||
function DoBackupFile(const Filename:string;
|
||||
IsPartOfProject:boolean): TModalResult;
|
||||
procedure UpdateCaption;
|
||||
@ -2357,11 +2357,13 @@ CodeToolBoss.SourceCache.WriteAllFileNames;
|
||||
{$IFDEF IDE_DEBUG}
|
||||
writeln('TMainIDE.DoSaveEditorUnit B2 ',ResourceCode<>nil);
|
||||
{$ENDIF}
|
||||
if ResourceCode<>nil then
|
||||
LFMCode:=
|
||||
CodeToolBoss.LoadFile(ChangeFileExt(ResourceCode.Filename,'.lfm'))
|
||||
else
|
||||
LFMCode:=nil;
|
||||
LFMCode:=nil;
|
||||
if ResourceCode<>nil then begin
|
||||
Result:=DoLoadCodeBuffer(LFMCode,
|
||||
ChangeFileExt(ResourceCode.Filename,'.lfm'),false,false);
|
||||
if Result<>mrOk then exit;
|
||||
Result:=mrCancel;
|
||||
end;
|
||||
end else
|
||||
ResourceCode:=nil;
|
||||
|
||||
@ -2720,7 +2722,7 @@ CheckHeap(IntToStr(GetMem_Cnt));
|
||||
Result:=mrOk;
|
||||
exit;
|
||||
end;
|
||||
Result:=DoLoadCodeBuffer(NewBuf,AFileName);
|
||||
Result:=DoLoadCodeBuffer(NewBuf,AFileName,true,true);
|
||||
if Result<>mrOk then exit;
|
||||
NewUnitInfo.Source:=NewBuf;
|
||||
if (Ext='.pp') or (Ext='.pas') then
|
||||
@ -2732,7 +2734,7 @@ CheckHeap(IntToStr(GetMem_Cnt));
|
||||
Result:=DoOpenProjectFile(AFilename);
|
||||
exit;
|
||||
end;
|
||||
Result:=DoLoadCodeBuffer(PreReadBuf,AFileName);
|
||||
Result:=DoLoadCodeBuffer(PreReadBuf,AFileName,true,true);
|
||||
if Result<>mrOk then exit;
|
||||
Result:=mrCancel;
|
||||
// check if unit is a program
|
||||
@ -2818,17 +2820,21 @@ writeln('[TMainIDE.DoOpenEditorFile] C');
|
||||
// this is a unit -> try to find the lfm file
|
||||
LFMFilename:=ChangeFileExt(NewUnitInfo.Filename,'.lfm');
|
||||
NewBuf:=nil;
|
||||
if FileExists(LFMFilename) then
|
||||
NewBuf:=CodeToolBoss.LoadFile(LFMFilename)
|
||||
else begin
|
||||
if FileExists(LFMFilename) then begin
|
||||
Result:=DoLoadCodeBuffer(NewBuf,LFMFilename,true,false);
|
||||
if Result<>mrOk then exit;
|
||||
Result:=mrCancel;
|
||||
end else begin
|
||||
i:=-1;
|
||||
NewBuf:=CodeToolBoss.FindNextResourceFile(NewUnitInfo.Source,i);
|
||||
if NewBuf<>nil then begin
|
||||
LFMFilename:=ChangeFileExt(NewBuf.Filename,'.lfm');
|
||||
if FileExists(LFMFilename) then
|
||||
NewBuf:=CodeToolBoss.LoadFile(LFMFilename)
|
||||
else
|
||||
NewBuf:=nil;
|
||||
NewBuf:=nil;
|
||||
if FileExists(LFMFilename) then begin
|
||||
Result:=DoLoadCodeBuffer(NewBuf,LFMFilename,true,false);
|
||||
if Result<>mrOk then exit;
|
||||
Result:=mrCancel;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -3472,7 +3478,8 @@ CheckHeap(IntToStr(GetMem_Cnt));
|
||||
writeln('TMainIDE.DoOpenProjectFile B2');
|
||||
if Project.MainUnit>=0 then begin
|
||||
// read MainUnit Source
|
||||
Result:=DoLoadCodeBuffer(NewBuf,Project.Units[Project.MainUnit].Filename);
|
||||
Result:=DoLoadCodeBuffer(NewBuf,Project.Units[Project.MainUnit].Filename,
|
||||
true,true);
|
||||
writeln('TMainIDE.DoOpenProjectFile B3');
|
||||
if Result=mrIgnore then Result:=mrAbort;
|
||||
if Result=mrAbort then exit;
|
||||
@ -4164,13 +4171,13 @@ begin
|
||||
end;
|
||||
|
||||
function TMainIDE.DoLoadCodeBuffer(var ACodeBuffer: TCodeBuffer;
|
||||
const AFilename: string): TModalResult;
|
||||
const AFilename: string; UpdateFromDisk, Revert: boolean): TModalResult;
|
||||
var
|
||||
ACaption,AText:string;
|
||||
begin
|
||||
repeat
|
||||
writeln('[TMainIDE.DoLoadCodeBuffer] A ',AFilename);
|
||||
ACodeBuffer:=CodeToolBoss.LoadFile(AFilename);
|
||||
ACodeBuffer:=CodeToolBoss.LoadFile(AFilename,UpdateFromDisk,Revert);
|
||||
if ACodeBuffer<>nil then begin
|
||||
ACodeBuffer.Reload;
|
||||
Result:=mrOk;
|
||||
@ -5270,6 +5277,9 @@ end.
|
||||
{ =============================================================================
|
||||
|
||||
$Log$
|
||||
Revision 1.179 2001/12/13 23:09:57 lazarus
|
||||
MG: enhanced code caching, fixed CursorToCleanPos and beautify statement
|
||||
|
||||
Revision 1.178 2001/12/12 16:49:14 lazarus
|
||||
Added code to disable save button when the active unit is not "modified".
|
||||
Shane
|
||||
|
@ -364,7 +364,7 @@ var
|
||||
NewSource: TCodeBuffer;
|
||||
begin
|
||||
repeat
|
||||
NewSource:=CodeToolBoss.LoadFile(fFilename);
|
||||
NewSource:=CodeToolBoss.LoadFile(fFilename,true,false);
|
||||
if NewSource=nil then begin
|
||||
ACaption:='Read error';
|
||||
AText:='Unable to read file "'+fFilename+'"!';
|
||||
@ -1269,6 +1269,9 @@ end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.45 2001/12/13 23:09:58 lazarus
|
||||
MG: enhanced code caching, fixed CursorToCleanPos and beautify statement
|
||||
|
||||
Revision 1.44 2001/12/02 11:03:36 lazarus
|
||||
MG: added default pascal file extension option
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user