CodeTools: CodeCompletion: include templates (optional). Issue #34389

git-svn-id: trunk@62240 -
This commit is contained in:
ondrej 2019-11-15 19:26:51 +00:00
parent 86a7065f15
commit d3e927b65c
8 changed files with 331 additions and 252 deletions

View File

@ -2901,255 +2901,258 @@ begin
ActivateGlobalWriteLock; ActivateGlobalWriteLock;
try try
InitCollectIdentifiers(CursorPos,IdentifierList); try
IdentStartXY:=FindIdentifierStartPos(CursorPos); InitCollectIdentifiers(CursorPos,IdentifierList);
IdentStartXY:=FindIdentifierStartPos(CursorPos);
if CheckCursorInCompilerDirective(IdentStartXY) then exit(true); if CheckCursorInCompilerDirective(IdentStartXY) then exit(true);
if not ParseSourceTillCollectionStart(IdentStartXY,CleanCursorPos,CursorNode, if not ParseSourceTillCollectionStart(IdentStartXY,CleanCursorPos,CursorNode,
IdentStartPos,IdentEndPos) then IdentStartPos,IdentEndPos) then
Exit; Exit;
Params:=TFindDeclarationParams.Create(Self,CursorNode); Params:=TFindDeclarationParams.Create(Self,CursorNode);
try try
if CleanCursorPos=0 then ; if CleanCursorPos=0 then ;
if IdentStartPos>0 then begin if IdentStartPos>0 then begin
MoveCursorToCleanPos(IdentStartPos);
ReadNextAtom;
CurrentIdentifierList.StartAtom:=CurPos;
end;
MoveCursorToCleanPos(IdentStartPos); MoveCursorToCleanPos(IdentStartPos);
ReadNextAtom;
CurrentIdentifierList.StartAtom:=CurPos;
end;
MoveCursorToCleanPos(IdentStartPos);
ReadPriorAtom;
IdentifierPath := '';
while CurPos.Flag = cafPoint do
begin
ReadPriorAtom; ReadPriorAtom;
if CurPos.Flag <> cafWord then IdentifierPath := '';
Break; while CurPos.Flag = cafPoint do
IdentifierPath := GetUpAtom + '.' + IdentifierPath;
ReadPriorAtom;
end;
// find context
GatherContext:=CreateFindContext(Self,CursorNode);
{$IFDEF CTDEBUG}
DebugLn('TIdentCompletionTool.GatherIdentifiers B',
' CleanCursorPos=',CleanPosToStr(CleanCursorPos),
' IdentStartPos=',CleanPosToStr(IdentStartPos),' IdentEndPos=',CleanPosToStr(IdentEndPos),
' Ident=',copy(Src,IdentStartPos,IdentEndPos-IdentStartPos),
' GatherContext=',FindContextToString(GatherContext));
{$ENDIF}
CurrentIdentifierList.NewMemberVisibility:=GetClassVisibility(CursorNode);
if CursorNode.Desc in [ctnUsesSection,ctnUseUnit,ctnUseUnitNamespace,ctnUseUnitClearName] then begin
GatherUnitNames(IdentifierPath);
MoveCursorToCleanPos(IdentEndPos);
ReadNextAtom;
if (CurPos.Flag=cafWord) and (not UpAtomIs('IN')) then begin
// add comma
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfNeedsEndComma];
end;
end else if (CursorNode.Desc in AllSourceTypes)
and (PositionsInSameLine(Src,CursorNode.StartPos,IdentStartPos)) then begin
GatherSourceNames(GatherContext);
end else begin
FindCollectionContext(Params,IdentStartPos,CursorNode,
ExprType,ContextExprStartPos,StartInSubContext,
HasInheritedKeyword);
//debugln(['TIdentCompletionTool.GatherIdentifiers FindCollectionContext ',ExprTypeToString(ExprType)]);
GatherContext := ExprType.Context;
// find class and ancestors if existing (needed for protected identifiers)
if (GatherContext.Tool = Self) or HasInheritedKeyword then
begin begin
FindContextClassAndAncestorsAndExtendedClassOfHelper(IdentStartXY, FICTClassAndAncestorsAndExtClassOfHelper);
end;
CursorContext:=CreateFindContext(Self,CursorNode);
GatherContextKeywords(CursorContext,IdentStartPos,Beautifier);
// check for incomplete context
// context bracket level
CurrentIdentifierList.StartBracketLvl:=
GetBracketLvl(Src,CursorNode.StartPos,IdentStartPos,
Scanner.NestedComments);
if CursorNode.Desc in AllPascalStatements then begin
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfStartInStatement];
end;
// context in front of
StartPosOfVariable:=FindStartOfTerm(IdentStartPos,NodeTermInType(CursorNode));
if StartPosOfVariable>0 then begin
if StartPosOfVariable=IdentStartPos then begin
// cursor is at start of an operand
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfStartOfOperand];
end else begin
MoveCursorToCleanPos(IdentStartPos);
ReadPriorAtom;
if CurPos.Flag=cafPoint then
// cursor is behind a point
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfStartIsSubIdent];
end;
MoveCursorToCleanPos(StartPosOfVariable);
ReadPriorAtom; ReadPriorAtom;
CurrentIdentifierList.StartAtomInFront:=CurPos; if CurPos.Flag <> cafWord then
if (ilcfStartInStatement in CurrentIdentifierList.ContextFlags) Break;
then begin IdentifierPath := GetUpAtom + '.' + IdentifierPath;
// check if LValue ReadPriorAtom;
if (CurPos.Flag in [cafSemicolon,cafEnd,cafColon]) end;
or UpAtomIs('BEGIN')
or UpAtomIs('TRY') or UpAtomIs('FINALLY') or UpAtomIs('EXCEPT') // find context
or UpAtomIs('FOR') or UpAtomIs('DO') or UpAtomIs('THEN') GatherContext:=CreateFindContext(Self,CursorNode);
or UpAtomIs('REPEAT') or UpAtomIs('ASM') or UpAtomIs('ELSE') {$IFDEF CTDEBUG}
then begin DebugLn('TIdentCompletionTool.GatherIdentifiers B',
' CleanCursorPos=',CleanPosToStr(CleanCursorPos),
' IdentStartPos=',CleanPosToStr(IdentStartPos),' IdentEndPos=',CleanPosToStr(IdentEndPos),
' Ident=',copy(Src,IdentStartPos,IdentEndPos-IdentStartPos),
' GatherContext=',FindContextToString(GatherContext));
{$ENDIF}
CurrentIdentifierList.NewMemberVisibility:=GetClassVisibility(CursorNode);
if CursorNode.Desc in [ctnUsesSection,ctnUseUnit,ctnUseUnitNamespace,ctnUseUnitClearName] then begin
GatherUnitNames(IdentifierPath);
MoveCursorToCleanPos(IdentEndPos);
ReadNextAtom;
if (CurPos.Flag=cafWord) and (not UpAtomIs('IN')) then begin
// add comma
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfNeedsEndComma];
end;
end else if (CursorNode.Desc in AllSourceTypes)
and (PositionsInSameLine(Src,CursorNode.StartPos,IdentStartPos)) then begin
GatherSourceNames(GatherContext);
end else begin
FindCollectionContext(Params,IdentStartPos,CursorNode,
ExprType,ContextExprStartPos,StartInSubContext,
HasInheritedKeyword);
//debugln(['TIdentCompletionTool.GatherIdentifiers FindCollectionContext ',ExprTypeToString(ExprType)]);
GatherContext := ExprType.Context;
// find class and ancestors if existing (needed for protected identifiers)
if (GatherContext.Tool = Self) or HasInheritedKeyword then
begin
FindContextClassAndAncestorsAndExtendedClassOfHelper(IdentStartXY, FICTClassAndAncestorsAndExtClassOfHelper);
end;
CursorContext:=CreateFindContext(Self,CursorNode);
GatherContextKeywords(CursorContext,IdentStartPos,Beautifier);
// check for incomplete context
// context bracket level
CurrentIdentifierList.StartBracketLvl:=
GetBracketLvl(Src,CursorNode.StartPos,IdentStartPos,
Scanner.NestedComments);
if CursorNode.Desc in AllPascalStatements then begin
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfStartInStatement];
end;
// context in front of
StartPosOfVariable:=FindStartOfTerm(IdentStartPos,NodeTermInType(CursorNode));
if StartPosOfVariable>0 then begin
if StartPosOfVariable=IdentStartPos then begin
// cursor is at start of an operand
CurrentIdentifierList.ContextFlags:= CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfStartOfStatement]; CurrentIdentifierList.ContextFlags+[ilcfStartOfOperand];
end else begin
MoveCursorToCleanPos(IdentStartPos);
ReadPriorAtom;
if CurPos.Flag=cafPoint then
// cursor is behind a point
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfStartIsSubIdent];
end; end;
// check if expression MoveCursorToCleanPos(StartPosOfVariable);
if UpAtomIs('IF') or UpAtomIs('CASE') or UpAtomIs('WHILE') ReadPriorAtom;
or UpAtomIs('UNTIL') CurrentIdentifierList.StartAtomInFront:=CurPos;
if (ilcfStartInStatement in CurrentIdentifierList.ContextFlags)
then begin then begin
// todo: check at start of expression, not only in front of variable // check if LValue
CurrentIdentifierList.ContextFlags:= if (CurPos.Flag in [cafSemicolon,cafEnd,cafColon])
CurrentIdentifierList.ContextFlags+[ilcfIsExpression, ilcfDontAllowProcedures]; or UpAtomIs('BEGIN')
or UpAtomIs('TRY') or UpAtomIs('FINALLY') or UpAtomIs('EXCEPT')
or UpAtomIs('FOR') or UpAtomIs('DO') or UpAtomIs('THEN')
or UpAtomIs('REPEAT') or UpAtomIs('ASM') or UpAtomIs('ELSE')
then begin
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfStartOfStatement];
end;
// check if expression
if UpAtomIs('IF') or UpAtomIs('CASE') or UpAtomIs('WHILE')
or UpAtomIs('UNTIL')
then begin
// todo: check at start of expression, not only in front of variable
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfIsExpression, ilcfDontAllowProcedures];
end;
// check if procedure is allowed
if (CurPos.Flag in [cafEdgedBracketOpen, cafEqual, cafOtherOperator])
or ((Scanner.CompilerMode<>cmDelphi) and (CurPos.Flag in [cafAssignment, cafComma, cafRoundBracketOpen])) // "MyEvent := MyProc;" and "o.Test(MyProc)" is supported only in Delphi mode
then
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfDontAllowProcedures];
end; end;
// check if procedure is allowed end;
if (CurPos.Flag in [cafEdgedBracketOpen, cafEqual, cafOtherOperator]) // context behind
or ((Scanner.CompilerMode<>cmDelphi) and (CurPos.Flag in [cafAssignment, cafComma, cafRoundBracketOpen])) // "MyEvent := MyProc;" and "o.Test(MyProc)" is supported only in Delphi mode if (IdentEndPos<SrcLen) then begin
MoveCursorToCleanPos(IdentEndPos);
//debugln(['TIdentCompletionTool.GatherIdentifiers "',dbgstr(Src,IdentStartPos,IdentEndPos-IdentStartPos),'"']);
InFrontOfDirective:=(CurPos.StartPos<SrcLen) and (Src[CurPos.StartPos]='{')
and (Src[CurPos.StartPos+1]='$');
ReadNextAtom;
// check end of line
if (not InFrontOfDirective)
and (CursorPos.Code.LineColIsOutside(CursorPos.Y,CursorPos.X)
or (not PositionsInSameLine(Src,IdentEndPos,CurPos.StartPos)))
then then
CurrentIdentifierList.ContextFlags:= CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfDontAllowProcedures]; CurrentIdentifierList.ContextFlags+[ilcfEndOfLine];
end;
end;
// context behind
if (IdentEndPos<SrcLen) then begin
MoveCursorToCleanPos(IdentEndPos);
//debugln(['TIdentCompletionTool.GatherIdentifiers "',dbgstr(Src,IdentStartPos,IdentEndPos-IdentStartPos),'"']);
InFrontOfDirective:=(CurPos.StartPos<SrcLen) and (Src[CurPos.StartPos]='{')
and (Src[CurPos.StartPos+1]='$');
ReadNextAtom;
// check end of line CurrentIdentifierList.StartAtomBehind:=CurPos;
if (not InFrontOfDirective) // check if a semicolon is needed or forbidden at the end
and (CursorPos.Code.LineColIsOutside(CursorPos.Y,CursorPos.X) if InFrontOfDirective
or (not PositionsInSameLine(Src,IdentEndPos,CurPos.StartPos))) or (CurrentIdentifierList.StartBracketLvl>0)
then or (CurPos.Flag in [cafSemicolon, cafEqual, cafColon, cafComma,
CurrentIdentifierList.ContextFlags:= cafPoint, cafRoundBracketOpen, cafRoundBracketClose,
CurrentIdentifierList.ContextFlags+[ilcfEndOfLine]; cafEdgedBracketOpen, cafEdgedBracketClose])
or ((CurPos.Flag in [cafWord,cafNone])
CurrentIdentifierList.StartAtomBehind:=CurPos; and (UpAtomIs('ELSE')
// check if a semicolon is needed or forbidden at the end or UpAtomIs('THEN')
if InFrontOfDirective or UpAtomIs('DO')
or (CurrentIdentifierList.StartBracketLvl>0) or UpAtomIs('TO')
or (CurPos.Flag in [cafSemicolon, cafEqual, cafColon, cafComma, or UpAtomIs('OF')
cafPoint, cafRoundBracketOpen, cafRoundBracketClose, or WordIsBinaryOperator.DoItCaseInsensitive(Src,
cafEdgedBracketOpen, cafEdgedBracketClose]) CurPos.StartPos,CurPos.EndPos-CurPos.StartPos)))
or ((CurPos.Flag in [cafWord,cafNone])
and (UpAtomIs('ELSE')
or UpAtomIs('THEN')
or UpAtomIs('DO')
or UpAtomIs('TO')
or UpAtomIs('OF')
or WordIsBinaryOperator.DoItCaseInsensitive(Src,
CurPos.StartPos,CurPos.EndPos-CurPos.StartPos)))
then begin
// do not add semicolon
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfNoEndSemicolon];
end;
// check if in statement
if (ilcfStartInStatement in CurrentIdentifierList.ContextFlags) then
begin
// check if a semicolon is needed at the end
if (not (ilcfNoEndSemicolon in CurrentIdentifierList.ContextFlags))
then begin then begin
// do not add semicolon
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfNoEndSemicolon];
end;
// check if in statement
if (ilcfStartInStatement in CurrentIdentifierList.ContextFlags) then
begin
// check if a semicolon is needed at the end // check if a semicolon is needed at the end
if (CurPos.Flag in [cafEnd]) if (not (ilcfNoEndSemicolon in CurrentIdentifierList.ContextFlags))
or WordIsBlockKeyWord.DoItCaseInsensitive(Src,
CurPos.StartPos,CurPos.EndPos-CurPos.StartPos)
or ((CurPos.Flag=cafWord)
and (not PositionsInSameLine(Src,IdentEndPos,CurPos.StartPos)))
then begin then begin
// add semicolon // check if a semicolon is needed at the end
CurrentIdentifierList.ContextFlags:= if (CurPos.Flag in [cafEnd])
CurrentIdentifierList.ContextFlags+[ilcfNeedsEndSemicolon]; or WordIsBlockKeyWord.DoItCaseInsensitive(Src,
CurPos.StartPos,CurPos.EndPos-CurPos.StartPos)
or ((CurPos.Flag=cafWord)
and (not PositionsInSameLine(Src,IdentEndPos,CurPos.StartPos)))
then begin
// add semicolon
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfNeedsEndSemicolon];
end;
end; end;
end; end;
end; // check missing 'do' after 'with'
// check missing 'do' after 'with' if CurrentIdentifierList.StartUpAtomInFrontIs('WITH')
if CurrentIdentifierList.StartUpAtomInFrontIs('WITH') and (not CurrentIdentifierList.StartUpAtomBehindIs('DO'))
and (not CurrentIdentifierList.StartUpAtomBehindIs('DO')) and (not CurrentIdentifierList.StartUpAtomBehindIs('AS'))
and (not CurrentIdentifierList.StartUpAtomBehindIs('AS')) and (CurrentIdentifierList.StartBracketLvl=0)
and (CurrentIdentifierList.StartBracketLvl=0) and (not (CurrentIdentifierList.StartAtomBehind.Flag in
and (not (CurrentIdentifierList.StartAtomBehind.Flag in [cafComma,cafPoint,cafRoundBracketOpen,cafEdgedBracketOpen]))
[cafComma,cafPoint,cafRoundBracketOpen,cafEdgedBracketOpen])) and (not CurrentIdentifierList.StartUpAtomBehindIs('^'))
and (not CurrentIdentifierList.StartUpAtomBehindIs('^')) then
then CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfNeedsDo];
end else begin
// end of source
CurrentIdentifierList.ContextFlags:= CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfNeedsDo]; CurrentIdentifierList.ContextFlags+[ilcfEndOfLine];
end else begin end;
// end of source
CurrentIdentifierList.ContextFlags:= // search and gather identifiers in context
CurrentIdentifierList.ContextFlags+[ilcfEndOfLine]; if (GatherContext.Tool<>nil) and (GatherContext.Node<>nil) then begin
{$IFDEF CTDEBUG}
DebugLn('TIdentCompletionTool.GatherIdentifiers D CONTEXT: ',
GatherContext.Tool.MainFilename,
' ',GatherContext.Node.DescAsString,
' "',StringToPascalConst(copy(GatherContext.Tool.Src,GatherContext.Node.StartPos,50)),'"');
{$ENDIF}
// gather all identifiers in context
Params.ContextNode:=GatherContext.Node;
Params.SetIdentifier(Self,nil,@CollectAllIdentifiers);
Params.Flags:=[fdfSearchInAncestors,fdfCollect,fdfFindVariable,fdfSearchInHelpers];
if (Params.ContextNode.Desc=ctnInterface) and StartInSubContext then
Include(Params.Flags,fdfIgnoreUsedUnits);
if not StartInSubContext then
Include(Params.Flags,fdfSearchInParentNodes);
if Params.ContextNode.Desc in AllClasses then
Exclude(Params.Flags,fdfSearchInParentNodes);
{$IFDEF CTDEBUG}
DebugLn('TIdentCompletionTool.GatherIdentifiers F');
{$ENDIF}
CurrentIdentifierList.Context:=GatherContext;
if GatherContext.Node.Desc=ctnIdentifier then
Params.Flags:=Params.Flags+[fdfIgnoreCurContextNode];
GatherContext.Tool.FindIdentifierInContext(Params);
end else
if ExprType.Desc in xtAllTypeHelperTypes then
begin
// gather all identifiers in cursor context for basic types (strings etc.)
Params.ContextNode:=CursorNode;
Params.SetIdentifier(Self,nil,@CollectAllIdentifiers);
Params.Flags:=[fdfSearchInAncestors,fdfCollect,fdfFindVariable,fdfSearchInHelpers];
CurrentIdentifierList.Context:=CursorContext;
FindIdentifierInBasicTypeHelpers(ExprType.Desc, Params);
end;
// check for procedure/method declaration context
CheckProcedureDeclarationContext;
// add useful identifiers
{$IFDEF CTDEBUG}
DebugLn('TIdentCompletionTool.GatherIdentifiers G');
{$ENDIF}
GatherUsefulIdentifiers(IdentStartPos,CursorContext,GatherContext);
end; end;
// search and gather identifiers in context Result:=true;
if (GatherContext.Tool<>nil) and (GatherContext.Node<>nil) then begin finally
{$IFDEF CTDEBUG} FreeListOfPFindContext(FICTClassAndAncestorsAndExtClassOfHelper);
DebugLn('TIdentCompletionTool.GatherIdentifiers D CONTEXT: ', FreeAndNil(FIDCTFoundPublicProperties);
GatherContext.Tool.MainFilename, Params.Free;
' ',GatherContext.Node.DescAsString, ClearIgnoreErrorAfter;
' "',StringToPascalConst(copy(GatherContext.Tool.Src,GatherContext.Node.StartPos,50)),'"');
{$ENDIF}
// gather all identifiers in context
Params.ContextNode:=GatherContext.Node;
Params.SetIdentifier(Self,nil,@CollectAllIdentifiers);
Params.Flags:=[fdfSearchInAncestors,fdfCollect,fdfFindVariable,fdfSearchInHelpers];
if (Params.ContextNode.Desc=ctnInterface) and StartInSubContext then
Include(Params.Flags,fdfIgnoreUsedUnits);
if not StartInSubContext then
Include(Params.Flags,fdfSearchInParentNodes);
if Params.ContextNode.Desc in AllClasses then
Exclude(Params.Flags,fdfSearchInParentNodes);
{$IFDEF CTDEBUG}
DebugLn('TIdentCompletionTool.GatherIdentifiers F');
{$ENDIF}
CurrentIdentifierList.Context:=GatherContext;
if GatherContext.Node.Desc=ctnIdentifier then
Params.Flags:=Params.Flags+[fdfIgnoreCurContextNode];
GatherContext.Tool.FindIdentifierInContext(Params);
end else
if ExprType.Desc in xtAllTypeHelperTypes then
begin
// gather all identifiers in cursor context for basic types (strings etc.)
Params.ContextNode:=CursorNode;
Params.SetIdentifier(Self,nil,@CollectAllIdentifiers);
Params.Flags:=[fdfSearchInAncestors,fdfCollect,fdfFindVariable,fdfSearchInHelpers];
CurrentIdentifierList.Context:=CursorContext;
FindIdentifierInBasicTypeHelpers(ExprType.Desc, Params);
end;
// check for procedure/method declaration context
CheckProcedureDeclarationContext;
// add useful identifiers
{$IFDEF CTDEBUG}
DebugLn('TIdentCompletionTool.GatherIdentifiers G');
{$ENDIF}
GatherUsefulIdentifiers(IdentStartPos,CursorContext,GatherContext);
GatherUserIdentifiers(CurrentIdentifierList.ContextFlags);
end; end;
Result:=true;
finally finally
FreeListOfPFindContext(FICTClassAndAncestorsAndExtClassOfHelper); GatherUserIdentifiers(CurrentIdentifierList.ContextFlags);
FreeAndNil(FIDCTFoundPublicProperties);
Params.Free;
ClearIgnoreErrorAfter;
end; end;
finally finally
DeactivateGlobalWriteLock; DeactivateGlobalWriteLock;

View File

@ -124,6 +124,7 @@ type
FIdentComplAutoStartAfterPoint: boolean; FIdentComplAutoStartAfterPoint: boolean;
FIdentComplAutoUseSingleIdent: boolean; FIdentComplAutoUseSingleIdent: boolean;
FIdentComplUseContainsFilter: Boolean; FIdentComplUseContainsFilter: Boolean;
FIdentComplIncludeCodeTemplates: Boolean;
FIdentComplIncludeWords: TIdentComplIncludeWords; FIdentComplIncludeWords: TIdentComplIncludeWords;
FIdentComplShowIcons: Boolean; FIdentComplShowIcons: Boolean;
@ -256,6 +257,8 @@ type
write FIdentComplAutoUseSingleIdent; write FIdentComplAutoUseSingleIdent;
property IdentComplUseContainsFilter: boolean read FIdentComplUseContainsFilter property IdentComplUseContainsFilter: boolean read FIdentComplUseContainsFilter
write FIdentComplUseContainsFilter; write FIdentComplUseContainsFilter;
property IdentComplIncludeCodeTemplates: boolean read FIdentComplIncludeCodeTemplates
write FIdentComplIncludeCodeTemplates;
property IdentComplIncludeWords: TIdentComplIncludeWords read FIdentComplIncludeWords property IdentComplIncludeWords: TIdentComplIncludeWords read FIdentComplIncludeWords
write FIdentComplIncludeWords; write FIdentComplIncludeWords;
property IdentComplShowIcons: boolean read FIdentComplShowIcons property IdentComplShowIcons: boolean read FIdentComplShowIcons
@ -574,6 +577,8 @@ begin
'CodeToolsOptions/IdentifierCompletion/AutoUseSingleIdent',true); 'CodeToolsOptions/IdentifierCompletion/AutoUseSingleIdent',true);
FIdentComplUseContainsFilter:=XMLConfig.GetValue( FIdentComplUseContainsFilter:=XMLConfig.GetValue(
'CodeToolsOptions/IdentifierCompletion/UseContainsFilter',true); 'CodeToolsOptions/IdentifierCompletion/UseContainsFilter',true);
FIdentComplIncludeCodeTemplates:=XMLConfig.GetValue(
'CodeToolsOptions/IdentifierCompletion/IncludeCodeTemplates',true);
FIdentComplIncludeWords:=IdentComplIncludeWordsNamesToEnum(XMLConfig.GetValue( FIdentComplIncludeWords:=IdentComplIncludeWordsNamesToEnum(XMLConfig.GetValue(
'CodeToolsOptions/IdentifierCompletion/IncludeWords', 'CodeToolsOptions/IdentifierCompletion/IncludeWords',
IdentComplIncludeWordsNames[icwIncludeFromAllUnits])); IdentComplIncludeWordsNames[icwIncludeFromAllUnits]));
@ -749,6 +754,8 @@ begin
FIdentComplAutoUseSingleIdent,true); FIdentComplAutoUseSingleIdent,true);
XMLConfig.SetDeleteValue('CodeToolsOptions/IdentifierCompletion/UseContainsFilter', XMLConfig.SetDeleteValue('CodeToolsOptions/IdentifierCompletion/UseContainsFilter',
FIdentComplUseContainsFilter,true); FIdentComplUseContainsFilter,true);
XMLConfig.SetDeleteValue('CodeToolsOptions/IdentifierCompletion/IncludeCodeTemplates',
FIdentComplIncludeCodeTemplates,true);
XMLConfig.SetDeleteValue('CodeToolsOptions/IdentifierCompletion/IncludeWords', XMLConfig.SetDeleteValue('CodeToolsOptions/IdentifierCompletion/IncludeWords',
IdentComplIncludeWordsNames[FIdentComplIncludeWords], IdentComplIncludeWordsNames[FIdentComplIncludeWords],
IdentComplIncludeWordsNames[icwIncludeFromAllUnits]); IdentComplIncludeWordsNames[icwIncludeFromAllUnits]);
@ -903,6 +910,7 @@ begin
FIdentComplAutoStartAfterPoint:=CodeToolsOpts.FIdentComplAutoStartAfterPoint; FIdentComplAutoStartAfterPoint:=CodeToolsOpts.FIdentComplAutoStartAfterPoint;
FIdentComplAutoUseSingleIdent:=CodeToolsOpts.FIdentComplAutoUseSingleIdent; FIdentComplAutoUseSingleIdent:=CodeToolsOpts.FIdentComplAutoUseSingleIdent;
FIdentComplUseContainsFilter:=CodeToolsOpts.FIdentComplUseContainsFilter; FIdentComplUseContainsFilter:=CodeToolsOpts.FIdentComplUseContainsFilter;
FIdentComplIncludeCodeTemplates:=CodeToolsOpts.FIdentComplIncludeCodeTemplates;
FIdentComplShowIcons:=CodeToolsOpts.FIdentComplShowIcons; FIdentComplShowIcons:=CodeToolsOpts.FIdentComplShowIcons;
FIdentComplAddParameterBrackets:=CodeToolsOpts.FIdentComplAddParameterBrackets; FIdentComplAddParameterBrackets:=CodeToolsOpts.FIdentComplAddParameterBrackets;
FIdentComplReplaceIdentifier:=CodeToolsOpts.FIdentComplReplaceIdentifier; FIdentComplReplaceIdentifier:=CodeToolsOpts.FIdentComplReplaceIdentifier;
@ -970,6 +978,7 @@ begin
FIdentComplAutoStartAfterPoint:=true; FIdentComplAutoStartAfterPoint:=true;
FIdentComplAutoUseSingleIdent:=true; FIdentComplAutoUseSingleIdent:=true;
FIdentComplUseContainsFilter:=true; FIdentComplUseContainsFilter:=true;
FIdentComplIncludeCodeTemplates:=true;
FIdentComplShowIcons:=false; FIdentComplShowIcons:=false;
FIdentComplAddParameterBrackets:=true; FIdentComplAddParameterBrackets:=true;
FIdentComplReplaceIdentifier:=true; FIdentComplReplaceIdentifier:=true;
@ -1056,6 +1065,7 @@ begin
and (FIdentComplAutoStartAfterPoint=CodeToolsOpts.FIdentComplAutoStartAfterPoint) and (FIdentComplAutoStartAfterPoint=CodeToolsOpts.FIdentComplAutoStartAfterPoint)
and (FIdentComplAutoUseSingleIdent=CodeToolsOpts.FIdentComplAutoUseSingleIdent) and (FIdentComplAutoUseSingleIdent=CodeToolsOpts.FIdentComplAutoUseSingleIdent)
and (FIdentComplUseContainsFilter=CodeToolsOpts.FIdentComplUseContainsFilter) and (FIdentComplUseContainsFilter=CodeToolsOpts.FIdentComplUseContainsFilter)
and (FIdentComplIncludeCodeTemplates=CodeToolsOpts.FIdentComplIncludeCodeTemplates)
and (FIdentComplShowIcons=CodeToolsOpts.FIdentComplShowIcons) and (FIdentComplShowIcons=CodeToolsOpts.FIdentComplShowIcons)
and (FIdentComplAddParameterBrackets=CodeToolsOpts.FIdentComplAddParameterBrackets) and (FIdentComplAddParameterBrackets=CodeToolsOpts.FIdentComplAddParameterBrackets)
and (FIdentComplReplaceIdentifier=CodeToolsOpts.FIdentComplReplaceIdentifier) and (FIdentComplReplaceIdentifier=CodeToolsOpts.FIdentComplReplaceIdentifier)

View File

@ -78,12 +78,12 @@ object CodetoolsIndentifierCompletionOptionsFrame: TCodetoolsIndentifierCompleti
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 0 Left = 0
Height = 19 Height = 19
Top = 344 Top = 365
Width = 124 Width = 124
Caption = 'ICReplaceCheckBox' Caption = 'ICReplaceCheckBox'
ParentShowHint = False ParentShowHint = False
ShowHint = True ShowHint = True
TabOrder = 12 TabOrder = 13
end end
object ICAddDoCheckBox: TCheckBox object ICAddDoCheckBox: TCheckBox
AnchorSideLeft.Control = Owner AnchorSideLeft.Control = Owner
@ -174,7 +174,7 @@ object CodetoolsIndentifierCompletionOptionsFrame: TCodetoolsIndentifierCompleti
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 0 Left = 0
Height = 15 Height = 15
Top = 329 Top = 350
Width = 537 Width = 537
Caption = 'ICMiscDividerBevel' Caption = 'ICMiscDividerBevel'
Anchors = [akTop, akLeft, akRight] Anchors = [akTop, akLeft, akRight]
@ -189,12 +189,12 @@ object CodetoolsIndentifierCompletionOptionsFrame: TCodetoolsIndentifierCompleti
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 0 Left = 0
Height = 19 Height = 19
Top = 363 Top = 384
Width = 151 Width = 151
Caption = 'ICJumpToErrorCheckBox' Caption = 'ICJumpToErrorCheckBox'
ParentShowHint = False ParentShowHint = False
ShowHint = True ShowHint = True
TabOrder = 13 TabOrder = 14
end end
object ICAutoUseSingleIdent: TCheckBox object ICAutoUseSingleIdent: TCheckBox
AnchorSideLeft.Control = Owner AnchorSideLeft.Control = Owner
@ -223,13 +223,13 @@ object CodetoolsIndentifierCompletionOptionsFrame: TCodetoolsIndentifierCompleti
end end
object ICAppearanceDividerBevel: TDividerBevel object ICAppearanceDividerBevel: TDividerBevel
AnchorSideLeft.Control = Owner AnchorSideLeft.Control = Owner
AnchorSideTop.Control = ICAddWordsComboBox AnchorSideTop.Control = ICIncludeCodeTemplatesCheckBox
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 0 Left = 0
Height = 15 Height = 15
Top = 293 Top = 314
Width = 537 Width = 537
Caption = 'ICAppearanceDividerBevel' Caption = 'ICAppearanceDividerBevel'
Anchors = [akTop, akLeft, akRight] Anchors = [akTop, akLeft, akRight]
@ -243,10 +243,10 @@ object CodetoolsIndentifierCompletionOptionsFrame: TCodetoolsIndentifierCompleti
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
Left = 0 Left = 0
Height = 19 Height = 19
Top = 308 Top = 329
Width = 222 Width = 222
Caption = 'ICUseIconsInCompletionBoxCheckBox' Caption = 'ICUseIconsInCompletionBoxCheckBox'
TabOrder = 11 TabOrder = 12
end end
object ICContentDividerBevel: TDividerBevel object ICContentDividerBevel: TDividerBevel
AnchorSideLeft.Control = Owner AnchorSideLeft.Control = Owner
@ -289,4 +289,16 @@ object CodetoolsIndentifierCompletionOptionsFrame: TCodetoolsIndentifierCompleti
Style = csDropDownList Style = csDropDownList
TabOrder = 10 TabOrder = 10
end end
object ICIncludeCodeTemplatesCheckBox: TCheckBox
AnchorSideLeft.Control = Owner
AnchorSideTop.Control = ICAddWordsComboBox
AnchorSideTop.Side = asrBottom
Left = 0
Height = 19
Top = 293
Width = 205
BorderSpacing.Top = 2
Caption = 'ICIncludeCodeTemplatesCheckBox'
TabOrder = 11
end
end end

View File

@ -44,6 +44,7 @@ type
ICContainsFilterCheckBox: TCheckBox; ICContainsFilterCheckBox: TCheckBox;
ICAddDoCheckBox: TCheckBox; ICAddDoCheckBox: TCheckBox;
ICAutoAddParameterBracketsCheckBox: TCheckBox; ICAutoAddParameterBracketsCheckBox: TCheckBox;
ICIncludeCodeTemplatesCheckBox: TCheckBox;
ICMiscDividerBevel: TDividerBevel; ICMiscDividerBevel: TDividerBevel;
ICOpenDividerBevel: TDividerBevel; ICOpenDividerBevel: TDividerBevel;
ICAutoStartAfterPointCheckBox: TCheckBox; ICAutoStartAfterPointCheckBox: TCheckBox;
@ -110,6 +111,7 @@ begin
dlgIncludeWordsToIdentCompl_IncludeFromAllUnits+LineEnding+ dlgIncludeWordsToIdentCompl_IncludeFromAllUnits+LineEnding+
dlgIncludeWordsToIdentCompl_IncludeFromCurrentUnit+LineEnding+ dlgIncludeWordsToIdentCompl_IncludeFromCurrentUnit+LineEnding+
dlgIncludeWordsToIdentCompl_DontInclude; dlgIncludeWordsToIdentCompl_DontInclude;
ICIncludeCodeTemplatesCheckBox.Caption := dlgIncludeCodeTemplatesToIdentCompl;
ICAppearanceDividerBevel.Caption:=lisAppearance; ICAppearanceDividerBevel.Caption:=lisAppearance;
ICUseIconsInCompletionBoxCheckBox.Caption := dlgUseIconsInCompletionBox; ICUseIconsInCompletionBoxCheckBox.Caption := dlgUseIconsInCompletionBox;
@ -138,6 +140,7 @@ begin
ICSortForHistoryCheckBox.Checked:=IdentComplSortForHistory; ICSortForHistoryCheckBox.Checked:=IdentComplSortForHistory;
ICSortForScopeCheckBox.Checked:=IdentComplSortForScope; ICSortForScopeCheckBox.Checked:=IdentComplSortForScope;
ICContainsFilterCheckBox.Checked:=IdentComplUseContainsFilter; ICContainsFilterCheckBox.Checked:=IdentComplUseContainsFilter;
ICIncludeCodeTemplatesCheckBox.Checked:=IdentComplIncludeCodeTemplates;
ICUseIconsInCompletionBoxCheckBox.Checked:=IdentComplShowIcons; ICUseIconsInCompletionBoxCheckBox.Checked:=IdentComplShowIcons;
case IdentComplIncludeWords of case IdentComplIncludeWords of
icwIncludeFromAllUnits: ICAddWordsComboBox.ItemIndex:=0; icwIncludeFromAllUnits: ICAddWordsComboBox.ItemIndex:=0;
@ -165,6 +168,7 @@ begin
IdentComplSortForHistory:=ICSortForHistoryCheckBox.Checked; IdentComplSortForHistory:=ICSortForHistoryCheckBox.Checked;
IdentComplSortForScope:=ICSortForScopeCheckBox.Checked; IdentComplSortForScope:=ICSortForScopeCheckBox.Checked;
IdentComplUseContainsFilter:=ICContainsFilterCheckBox.Checked; IdentComplUseContainsFilter:=ICContainsFilterCheckBox.Checked;
IdentComplIncludeCodeTemplates:=ICIncludeCodeTemplatesCheckBox.Checked;
IdentComplShowIcons:=ICUseIconsInCompletionBoxCheckBox.Checked; IdentComplShowIcons:=ICUseIconsInCompletionBoxCheckBox.Checked;
case ICAddWordsComboBox.ItemIndex of case ICAddWordsComboBox.ItemIndex of
0: IdentComplIncludeWords := icwIncludeFromAllUnits; 0: IdentComplIncludeWords := icwIncludeFromAllUnits;

View File

@ -2055,6 +2055,7 @@ resourcestring
dlgIncludeWordsToIdentCompl_IncludeFromAllUnits = 'from all units'; dlgIncludeWordsToIdentCompl_IncludeFromAllUnits = 'from all units';
dlgIncludeWordsToIdentCompl_IncludeFromCurrentUnit = 'from current unit'; dlgIncludeWordsToIdentCompl_IncludeFromCurrentUnit = 'from current unit';
dlgIncludeWordsToIdentCompl_DontInclude = 'don''t include'; dlgIncludeWordsToIdentCompl_DontInclude = 'don''t include';
dlgIncludeCodeTemplatesToIdentCompl = 'Include code templates';
dlgMarkupUserDefined = 'User defined markup'; dlgMarkupUserDefined = 'User defined markup';
dlgMarkupUserDefinedNoLists = 'No lists'; dlgMarkupUserDefinedNoLists = 'No lists';

View File

@ -667,6 +667,7 @@ type
function OIHelpProvider: TAbstractIDEHTMLProvider; function OIHelpProvider: TAbstractIDEHTMLProvider;
procedure DoAddWordsToIdentCompletion(Sender: TIdentifierList; procedure DoAddWordsToIdentCompletion(Sender: TIdentifierList;
FilteredList: TFPList; PriorityCount: Integer); FilteredList: TFPList; PriorityCount: Integer);
procedure DoAddCodeTemplatesToIdentCompletion;
// form editor and designer // form editor and designer
procedure DoBringToFrontFormOrUnit; procedure DoBringToFrontFormOrUnit;
procedure DoBringToFrontFormOrInspector(ForceInspector: boolean); procedure DoBringToFrontFormOrInspector(ForceInspector: boolean);
@ -2053,6 +2054,8 @@ procedure TMainIDE.CodeToolBossGatherUserIdentifiers(
); );
begin begin
FIdentifierWordCompletionEnabled := not (ilcfStartIsSubIdent in ContextFlags); FIdentifierWordCompletionEnabled := not (ilcfStartIsSubIdent in ContextFlags);
if not (ilcfStartIsSubIdent in ContextFlags) then
DoAddCodeTemplatesToIdentCompletion;
end; end;
procedure TMainIDE.CodeToolBossGatherUserIdentifiersToFilteredList( procedure TMainIDE.CodeToolBossGatherUserIdentifiersToFilteredList(
@ -7297,6 +7300,24 @@ begin
AbortBuild; AbortBuild;
end; end;
procedure TMainIDE.DoAddCodeTemplatesToIdentCompletion;
var
New: TCodeTemplateIdentifierListItem;
I: Integer;
begin
if not CodeToolsOpts.IdentComplIncludeCodeTemplates then
Exit;
for I := 0 to SourceEditorManager.CodeTemplateModul.Completions.Count-1 do
begin
New := TCodeTemplateIdentifierListItem.Create(CodeTemplateCompatibility, False, CodeTemplateHistoryIndex,
PChar(SourceEditorManager.CodeTemplateModul.Completions[I]),
CodeTemplateLevel, nil, nil, ctnCodeTemplate);
New.Comment := SourceEditorManager.CodeTemplateModul.CompletionComments[I];
CodeToolBoss.IdentifierList.Add(New);
end;
end;
procedure TMainIDE.DoCompile; procedure TMainIDE.DoCompile;
var var
ASrcEdit: TSourceEditor; ASrcEdit: TSourceEditor;

View File

@ -56,7 +56,7 @@ uses
LazStringUtils, LazStringUtils,
// codetools // codetools
BasicCodeTools, CodeBeautifier, CodeToolManager, CodeCache, SourceLog, BasicCodeTools, CodeBeautifier, CodeToolManager, CodeCache, SourceLog,
LinkScanner, CodeTree, SourceChanger, LinkScanner, CodeTree, SourceChanger, IdentCompletionTool,
// synedit // synedit
SynEditLines, SynEditStrConst, SynEditTypes, SynEdit, SynEditLines, SynEditStrConst, SynEditTypes, SynEdit,
SynEditHighlighter, SynEditAutoComplete, SynEditKeyCmds, SynCompletion, SynEditHighlighter, SynEditAutoComplete, SynEditKeyCmds, SynCompletion,
@ -1204,8 +1204,6 @@ type
procedure OnSourceMarksAction(AMark: TSourceMark; {%H-}AAction: TMarksAction); procedure OnSourceMarksAction(AMark: TSourceMark; {%H-}AAction: TMarksAction);
procedure OnSourceMarksGetSynEdit(Sender: TObject; aFilename: string; procedure OnSourceMarksGetSynEdit(Sender: TObject; aFilename: string;
var aSynEdit: TSynEdit); var aSynEdit: TSynEdit);
property CodeTemplateModul: TSynEditAutoComplete
read FCodeTemplateModul write FCodeTemplateModul;
// goto dialog // goto dialog
function GotoDialog: TfrmGoto; function GotoDialog: TfrmGoto;
public public
@ -1216,6 +1214,8 @@ type
AnID: Integer = -1 AnID: Integer = -1
): TSourceNotebook; ): TSourceNotebook;
function SenderToEditor(Sender: TObject): TSourceEditor; function SenderToEditor(Sender: TObject): TSourceEditor;
property CodeTemplateModul: TSynEditAutoComplete
read FCodeTemplateModul write FCodeTemplateModul;
private private
// Context-Menu // Context-Menu
procedure CloseOtherPagesClicked(Sender: TObject); procedure CloseOtherPagesClicked(Sender: TObject);
@ -2427,6 +2427,7 @@ var
OldCompletionType: TCompletionType; OldCompletionType: TCompletionType;
prototypeAdded: boolean; prototypeAdded: boolean;
SourceNoteBook: TSourceNotebook; SourceNoteBook: TSourceNotebook;
IdentItem: TIdentifierListItem;
Begin Begin
{$IFDEF VerboseIDECompletionBox} {$IFDEF VerboseIDECompletionBox}
DebugLnEnter(['TSourceNotebook.ccComplete START']); DebugLnEnter(['TSourceNotebook.ccComplete START']);
@ -2444,22 +2445,29 @@ Begin
SourceStart,SourceEnd,KeyChar,Shift); SourceStart,SourceEnd,KeyChar,Shift);
Manager.FActiveCompletionPlugin:=nil; Manager.FActiveCompletionPlugin:=nil;
end else begin end else begin
IdentItem:=CodeToolBoss.IdentifierList.FilteredItems[Position];
// add to history // add to history
CodeToolBoss.IdentifierHistory.Add( CodeToolBoss.IdentifierHistory.Add(IdentItem);
CodeToolBoss.IdentifierList.FilteredItems[Position]); if IdentItem is TCodeTemplateIdentifierListItem then
// get value
NewValue:=GetIdentCompletionValue(Self, KeyChar, ValueType, CursorToLeft);
if ValueType=icvIdentifier then ;
// insert value plus special chars like brackets, semicolons, ...
if ValueType <> icvNone then
Editor.TextBetweenPointsEx[SourceStart, SourceEnd, scamEnd] := NewValue;
if ValueType in [icvProcWithParams,icvIndexedProp] then
prototypeAdded := true;
if CursorToLeft>0 then
begin begin
NewCaretXY:=Editor.CaretXY; if IdentItem.Identifier<>'' then
dec(NewCaretXY.X,CursorToLeft); Manager.CodeTemplateModul.ExecuteCompletion(IdentItem.Identifier, Editor);
Editor.CaretXY:=NewCaretXY; end else
begin
// get value
NewValue:=GetIdentCompletionValue(Self, KeyChar, ValueType, CursorToLeft);
if ValueType=icvIdentifier then ;
// insert value plus special chars like brackets, semicolons, ...
if ValueType <> icvNone then
Editor.TextBetweenPointsEx[SourceStart, SourceEnd, scamEnd] := NewValue;
if ValueType in [icvProcWithParams,icvIndexedProp] then
prototypeAdded := true;
if CursorToLeft>0 then
begin
NewCaretXY:=Editor.CaretXY;
dec(NewCaretXY.X,CursorToLeft);
Editor.CaretXY:=NewCaretXY;
end;
end; end;
ccSelection := ''; ccSelection := '';
Value:=''; Value:='';

View File

@ -90,6 +90,11 @@ type
procedure BeautifyIdentifier(IdentList: TIdentifierList); override; procedure BeautifyIdentifier(IdentList: TIdentifierList); override;
end; end;
TCodeTemplateIdentifierListItem = class(TIdentifierListItem)
public
Comment: string;
end;
procedure SetupTextConverters; procedure SetupTextConverters;
procedure FreeTextConverters; procedure FreeTextConverters;
@ -128,7 +133,11 @@ function BreakLinesInText(const s: string; MaxLineLength: integer): string;
const const
ctnWord = ctnUser + 1; ctnWord = ctnUser + 1;
ctnCodeTemplate = ctnUser + 2;
WordCompatibility = icompUnknown; WordCompatibility = icompUnknown;
CodeTemplateCompatibility = icompUnknown;
CodeTemplateHistoryIndex = High(Integer);
CodeTemplateLevel = High(Integer);
implementation implementation
@ -497,6 +506,12 @@ begin
s:='text'; s:='text';
end; end;
ctnCodeTemplate:
begin
AColor:=clGray;
s:='template';
end;
ctnNone: ctnNone:
if not UseImages then if not UseImages then
begin begin
@ -704,6 +719,11 @@ begin
s := s + ':' + IdentItem.ResultType; s := s + ':' + IdentItem.ResultType;
s:=s+';' s:=s+';'
end; end;
ctnCodeTemplate:
begin
if IdentItem is TCodeTemplateIdentifierListItem then
s:=' - '+TCodeTemplateIdentifierListItem(IdentItem).Comment;
end;
end; end;
end; end;