2019-08-23 11:56:54 -07:00
# include "BfAutoComplete.h"
# include "BfParser.h"
# include "BfExprEvaluator.h"
# include "BfSourceClassifier.h"
# include "BfResolvePass.h"
# include "BfFixits.h"
2020-10-08 09:41:05 -07:00
# include "BfResolvedTypeUtils.h"
2022-03-15 16:33:30 -07:00
# include "CeMachine.h"
# include "CeDebugger.h"
2019-08-23 11:56:54 -07:00
2021-12-08 22:08:57 +01:00
# define FTS_FUZZY_MATCH_IMPLEMENTATION
2021-12-15 11:01:14 +01:00
# include "../third_party/FtsFuzzyMatch.h"
2021-12-29 00:27:25 +01:00
# include "BeefySysLib/util/UTF8.h"
2021-12-08 22:08:57 +01:00
2019-08-23 11:56:54 -07:00
# pragma warning(disable:4996)
using namespace llvm ;
USING_NS_BF ;
AutoCompleteBase : : AutoCompleteBase ( )
{
mIsGetDefinition = false ;
mIsAutoComplete = true ;
2021-12-25 20:14:23 +01:00
mDoFuzzyAutoComplete = false ;
2019-08-23 11:56:54 -07:00
mInsertStartIdx = - 1 ;
mInsertEndIdx = - 1 ;
}
AutoCompleteBase : : ~ AutoCompleteBase ( )
{
Clear ( ) ;
}
2021-12-28 11:52:02 -05:00
AutoCompleteEntry * AutoCompleteBase : : AddEntry ( const AutoCompleteEntry & entry , const StringImpl & filter )
2021-12-20 13:35:58 +01:00
{
uint8 matches [ 256 ] ;
2022-07-26 13:27:03 -04:00
2021-12-20 13:35:58 +01:00
if ( ! DoesFilterMatch ( entry . mDisplay , filter . c_str ( ) , entry . mScore , matches , 256 ) | | ( entry . mNamePrefixCount < 0 ) )
return NULL ;
2022-01-01 13:17:53 +01:00
entry . mMatchesLength = mDoFuzzyAutoComplete ? u8_strlen ( ( char * ) filter . c_str ( ) ) : 0 ;
2021-12-29 00:27:25 +01:00
entry . mMatches = ( entry . mMatchesLength > 0 ) ? matches : nullptr ;
2021-12-18 22:28:44 +01:00
2021-12-20 13:35:58 +01:00
auto result = AddEntry ( entry ) ;
2022-07-26 13:27:03 -04:00
2021-12-20 13:35:58 +01:00
// Reset matches because the array will be invalid after return
entry . mMatches = nullptr ;
entry . mMatchesLength = 0 ;
return result ;
2021-11-29 08:38:42 -08:00
}
2021-12-28 11:52:02 -05:00
AutoCompleteEntry * AutoCompleteBase : : AddEntry ( const AutoCompleteEntry & entry , const char * filter )
2021-11-29 08:38:42 -08:00
{
2021-12-18 22:28:44 +01:00
uint8 matches [ 256 ] ;
if ( ! DoesFilterMatch ( entry . mDisplay , filter , entry . mScore , matches , 256 ) | | ( entry . mNamePrefixCount < 0 ) )
2021-11-29 08:38:42 -08:00
return NULL ;
2021-12-18 22:28:44 +01:00
2022-01-01 13:17:53 +01:00
entry . mMatchesLength = mDoFuzzyAutoComplete ? u8_strlen ( ( char * ) filter ) : 0 ;
2021-12-29 00:27:25 +01:00
entry . mMatches = ( entry . mMatchesLength > 0 ) ? matches : nullptr ;
2021-12-18 22:28:44 +01:00
2021-12-20 13:35:58 +01:00
auto result = AddEntry ( entry ) ;
2021-12-18 22:28:44 +01:00
2021-12-20 13:35:58 +01:00
// Reset matches because the array will be invalid after return
entry . mMatches = nullptr ;
entry . mMatchesLength = 0 ;
2021-12-18 22:28:44 +01:00
2021-12-20 13:35:58 +01:00
return result ;
2019-08-23 11:56:54 -07:00
}
AutoCompleteEntry * AutoCompleteBase : : AddEntry ( const AutoCompleteEntry & entry )
2021-12-18 22:28:44 +01:00
{
2019-08-23 11:56:54 -07:00
if ( mEntriesSet . mAllocSize = = 0 )
{
mEntriesSet . Reserve ( 128 ) ;
}
AutoCompleteEntry * insertedEntry = NULL ;
if ( mEntriesSet . TryAdd ( entry , & insertedEntry ) )
{
insertedEntry - > mEntryType = entry . mEntryType ;
2022-07-26 13:27:03 -04:00
const char * display = entry . mDisplay ;
2021-11-29 08:38:42 -08:00
int size = ( int ) strlen ( display ) + 1 ;
2019-08-23 11:56:54 -07:00
insertedEntry - > mDisplay = ( char * ) mAlloc . AllocBytes ( size ) ;
2021-11-29 08:38:42 -08:00
memcpy ( ( char * ) insertedEntry - > mDisplay , display , size ) ;
2021-12-18 22:28:44 +01:00
2021-12-29 00:27:25 +01:00
if ( entry . mMatchesLength > 0 )
2022-07-26 13:27:03 -04:00
{
2021-12-29 00:27:25 +01:00
insertedEntry - > mMatches = ( uint8 * ) mAlloc . AllocBytes ( insertedEntry - > mMatchesLength ) ;
memcpy ( ( char * ) insertedEntry - > mMatches , entry . mMatches , insertedEntry - > mMatchesLength ) ;
}
2019-08-23 11:56:54 -07:00
}
return insertedEntry ;
}
2021-12-08 22:08:57 +01:00
bool AutoCompleteBase : : DoesFilterMatch ( const char * entry , const char * filter , int & score , uint8 * matches , int maxMatches )
2021-12-18 22:28:44 +01:00
{
2019-08-23 11:56:54 -07:00
if ( mIsGetDefinition )
{
int entryLen = ( int ) strlen ( entry ) ;
if ( entry [ entryLen - 1 ] = = ' = ' )
return ( strncmp ( filter , entry , entryLen - 1 ) = = 0 ) ;
return ( strcmp ( filter , entry ) = = 0 ) ;
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
if ( ! mIsAutoComplete )
return false ;
2021-12-08 22:08:57 +01:00
if ( filter [ 0 ] = = ' \0 ' )
2019-08-23 11:56:54 -07:00
return true ;
int filterLen = ( int ) strlen ( filter ) ;
int entryLen = ( int ) strlen ( entry ) ;
2021-12-08 22:08:57 +01:00
if ( filterLen > entryLen )
return false ;
2021-12-25 20:14:23 +01:00
if ( mDoFuzzyAutoComplete )
{
return fts : : fuzzy_match ( filter , entry , score , matches , maxMatches ) ;
2021-12-08 22:08:57 +01:00
}
2021-12-25 20:14:23 +01:00
else
{
bool hasUnderscore = false ;
bool checkInitials = filterLen > 1 ;
for ( int i = 0 ; i < ( int ) filterLen ; i + + )
{
char c = filter [ i ] ;
if ( c = = ' _ ' )
hasUnderscore = true ;
else if ( islower ( ( uint8 ) filter [ i ] ) )
checkInitials = false ;
}
if ( hasUnderscore )
return strnicmp ( filter , entry , filterLen ) = = 0 ;
char initialStr [ 256 ] ;
char * initialStrP = initialStr ;
2021-12-08 22:08:57 +01:00
2021-12-25 20:14:23 +01:00
//String initialStr;
bool prevWasUnderscore = false ;
for ( int entryIdx = 0 ; entryIdx < entryLen ; entryIdx + + )
{
char entryC = entry [ entryIdx ] ;
if ( entryC = = ' _ ' )
{
prevWasUnderscore = true ;
continue ;
}
if ( ( entryIdx = = 0 ) | | ( prevWasUnderscore ) | | ( isupper ( ( uint8 ) entryC ) | | ( isdigit ( ( uint8 ) entryC ) ) ) )
{
if ( strnicmp ( filter , entry + entryIdx , filterLen ) = = 0 )
return true ;
if ( checkInitials )
* ( initialStrP + + ) = entryC ;
}
prevWasUnderscore = false ;
if ( filterLen = = 1 )
break ; // Don't check inners for single-character case
}
if ( ! checkInitials )
return false ;
* ( initialStrP + + ) = 0 ;
return strnicmp ( filter , initialStr , filterLen ) = = 0 ;
}
2019-08-23 11:56:54 -07:00
}
void AutoCompleteBase : : Clear ( )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
//mEntries.clear();
mAlloc . Clear ( ) ;
mEntriesSet . Clear ( ) ;
}
//////////////////////////////////////////////////////////////////////////
2021-12-25 20:14:23 +01:00
BfAutoComplete : : BfAutoComplete ( BfResolveType resolveType , bool doFuzzyAutoComplete )
2019-08-23 11:56:54 -07:00
{
mResolveType = resolveType ;
mModule = NULL ;
mCompiler = NULL ;
mSystem = NULL ;
mIsCapturingMethodMatchInfo = false ;
mIgnoreFixits = false ;
mHasFriendSet = false ;
mUncertain = false ;
2020-09-11 10:33:16 -07:00
mForceAllowNonStatic = false ;
2022-07-26 13:27:03 -04:00
mMethodMatchInfo = NULL ;
mIsGetDefinition =
2019-08-23 11:56:54 -07:00
( resolveType = = BfResolveType_GetSymbolInfo ) | |
( resolveType = = BfResolveType_GoToDefinition ) ;
mIsAutoComplete = ( resolveType = = BfResolveType_Autocomplete ) ;
2021-12-25 20:14:23 +01:00
mDoFuzzyAutoComplete = doFuzzyAutoComplete ;
2019-08-23 11:56:54 -07:00
mGetDefinitionNode = NULL ;
mShowAttributeProperties = NULL ;
mIdentifierUsed = NULL ;
//mReplaceMethodInstance = NULL;
mReplaceLocalId = - 1 ;
mDefType = NULL ;
mDefField = NULL ;
mDefMethod = NULL ;
mDefProp = NULL ;
mDefMethodGenericParamIdx = - 1 ;
mDefTypeGenericParamIdx = - 1 ;
mCursorLineStart = - 1 ;
mCursorLineEnd = - 1 ;
}
BfAutoComplete : : ~ BfAutoComplete ( )
{
Clear ( ) ;
2025-01-02 11:42:33 -08:00
RemoveMethodMatchInfo ( ) ;
2019-08-23 11:56:54 -07:00
}
void BfAutoComplete : : SetModule ( BfModule * module )
{
2022-04-25 14:41:03 -07:00
if ( module ! = NULL )
{
mModule = module ;
mCompiler = mModule - > mCompiler ;
mSystem = mCompiler - > mSystem ;
}
else
{
mModule = NULL ;
mCompiler = NULL ;
mSystem = NULL ;
}
2019-08-23 11:56:54 -07:00
}
void BfAutoComplete : : Clear ( )
{
if ( mMethodMatchInfo ! = NULL )
{
if ( mMethodMatchInfo - > mInstanceList . size ( ) = = 0 )
{
delete mMethodMatchInfo ;
mMethodMatchInfo = NULL ;
}
else
{
// Keep mBestIdx - for when we match but then backspace
2022-07-26 13:27:03 -04:00
mMethodMatchInfo - > mPrevBestIdx = mMethodMatchInfo - > mBestIdx ;
2019-08-23 11:56:54 -07:00
mMethodMatchInfo - > mMostParamsMatched = 0 ;
mMethodMatchInfo - > mHadExactMatch = false ;
mMethodMatchInfo - > mInstanceList . Clear ( ) ;
mMethodMatchInfo - > mSrcPositions . Clear ( ) ;
}
}
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
mInsertStartIdx = - 1 ;
mInsertEndIdx = - 1 ;
mIsCapturingMethodMatchInfo = false ;
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
AutoCompleteBase : : Clear ( ) ;
}
void BfAutoComplete : : RemoveMethodMatchInfo ( )
{
mIsCapturingMethodMatchInfo = false ;
delete mMethodMatchInfo ;
mMethodMatchInfo = NULL ;
}
void BfAutoComplete : : ClearMethodMatchEntries ( )
{
mMethodMatchInfo - > mInstanceList . Clear ( ) ;
}
int BfAutoComplete : : GetCursorIdx ( BfAstNode * node )
{
if ( node = = NULL )
return - 1 ;
2022-04-16 06:27:54 -07:00
// if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
// return -1;
2019-08-23 11:56:54 -07:00
2022-04-16 06:27:54 -07:00
if ( node - > IsTemporary ( ) )
return false ;
2019-08-23 11:56:54 -07:00
auto bfParser = node - > GetSourceData ( ) - > ToParser ( ) ;
2022-04-16 06:27:54 -07:00
if ( bfParser = = NULL )
return - 1 ;
2019-08-23 11:56:54 -07:00
if ( ( bfParser - > mParserFlags & ParserFlag_Autocomplete ) = = 0 )
return - 1 ;
return bfParser - > mCursorIdx ;
}
bool BfAutoComplete : : IsAutocompleteNode ( BfAstNode * node , int lengthAdd , int startAdd )
{
2022-04-25 14:41:03 -07:00
if ( mModule = = NULL )
return false ;
2019-08-23 11:56:54 -07:00
if ( node = = NULL )
return false ;
2022-07-26 13:27:03 -04:00
2022-04-16 06:27:54 -07:00
// if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
// return false;
2019-08-23 11:56:54 -07:00
2022-04-16 06:27:54 -07:00
if ( node - > IsTemporary ( ) )
return false ;
2019-08-23 11:56:54 -07:00
auto bfParser = node - > GetSourceData ( ) - > ToParser ( ) ;
2022-04-16 06:27:54 -07:00
if ( bfParser = = NULL )
return false ;
2019-08-23 11:56:54 -07:00
if ( ( bfParser - > mParserFlags & ParserFlag_Autocomplete ) = = 0 )
return false ;
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
//if (mCompiler->mResolvePassData->mResolveType != BfResolveType_Autocomplete)
lengthAdd + + ;
int cursorIdx = bfParser - > mCursorCheckIdx ;
2022-07-26 13:27:03 -04:00
int nodeSrcStart = node - > GetSrcStart ( ) ;
if ( ( cursorIdx < nodeSrcStart + startAdd ) | | ( cursorIdx > = node - > GetSrcEnd ( ) + lengthAdd ) )
2019-08-23 11:56:54 -07:00
return false ;
return true ;
}
bool BfAutoComplete : : IsAutocompleteNode ( BfAstNode * startNode , BfAstNode * endNode , int lengthAdd , int startAdd )
{
if ( ( startNode = = NULL ) | | ( endNode = = NULL ) )
return false ;
2022-04-16 06:27:54 -07:00
// if (!startNode->IsFromParser(mCompiler->mResolvePassData->mParser))
// return false;
2019-08-23 11:56:54 -07:00
2022-04-16 06:27:54 -07:00
if ( startNode - > IsTemporary ( ) )
return false ;
2019-08-23 11:56:54 -07:00
auto bfParser = startNode - > GetSourceData ( ) - > ToParser ( ) ;
2022-04-16 06:27:54 -07:00
if ( bfParser = = NULL )
return false ;
2019-08-23 11:56:54 -07:00
if ( ( bfParser - > mParserFlags & ParserFlag_Autocomplete ) = = 0 )
return false ;
//if (mCompiler->mResolvePassData->mResolveType != BfResolveType_Autocomplete)
lengthAdd + + ;
int cursorIdx = bfParser - > mCursorCheckIdx ;
int nodeSrcStart = startNode - > GetSrcStart ( ) ;
if ( ( cursorIdx < nodeSrcStart + startAdd ) | | ( cursorIdx > = endNode - > GetSrcEnd ( ) + lengthAdd ) )
return false ;
return true ;
}
bool BfAutoComplete : : IsAutocompleteLineNode ( BfAstNode * node )
{
if ( node = = NULL )
return false ;
2022-04-16 06:27:54 -07:00
// if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
// return false;
2019-08-23 11:56:54 -07:00
2022-04-16 06:27:54 -07:00
if ( node - > IsTemporary ( ) )
return false ;
2019-08-23 11:56:54 -07:00
auto bfParser = node - > GetSourceData ( ) - > ToParser ( ) ;
2022-04-16 06:27:54 -07:00
if ( bfParser = = NULL )
return false ;
2019-08-23 11:56:54 -07:00
if ( ( bfParser - > mParserFlags & ParserFlag_Autocomplete ) = = 0 )
return false ;
int startAdd = 0 ;
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
if ( mCursorLineStart = = - 1 )
{
auto nodeSource = node - > GetSourceData ( ) ;
mCursorLineStart = bfParser - > mCursorIdx ;
while ( mCursorLineStart > 0 )
{
if ( nodeSource - > mSrc [ mCursorLineStart - 1 ] = = ' \n ' )
break ;
mCursorLineStart - - ;
}
mCursorLineEnd = bfParser - > mCursorIdx ;
while ( mCursorLineEnd < nodeSource - > mSrcLength )
{
if ( nodeSource - > mSrc [ mCursorLineEnd ] = = ' \n ' )
2022-07-26 13:27:03 -04:00
break ;
2019-08-23 11:56:54 -07:00
mCursorLineEnd + + ;
}
}
int srcStart = node - > GetSrcStart ( ) ;
return ( srcStart > = mCursorLineStart ) & & ( srcStart < = mCursorLineEnd ) ;
}
// The parser thought this was a type reference but it may not be
BfTypedValue BfAutoComplete : : LookupTypeRefOrIdentifier ( BfAstNode * node , bool * isStatic , BfEvalExprFlags evalExprFlags , BfType * expectingType )
{
SetAndRestoreValue < bool > prevIgnoreClassifying ( mModule - > mIsInsideAutoComplete , true ) ;
2020-08-12 15:07:56 -07:00
auto _FixType = [ ] ( const BfTypedValue & typedValue )
{
if ( ( typedValue . mType ! = NULL ) & & ( typedValue . mType - > IsAllocType ( ) ) )
{
BfTypedValue ret = typedValue ;
ret . mType = ret . mType - > GetUnderlyingType ( ) ;
return ret ;
}
return typedValue ;
} ;
2019-08-23 11:56:54 -07:00
if ( auto typeRef = BfNodeDynCast < BfTypeReference > ( node ) )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
if ( auto namedTypeRef = BfNodeDynCast < BfNamedTypeReference > ( typeRef ) )
{
BfExprEvaluator exprEvaluator ( mModule ) ;
auto identifierResult = exprEvaluator . LookupIdentifier ( namedTypeRef - > mNameNode ) ;
if ( identifierResult )
return identifierResult ;
2022-02-14 10:03:41 -05:00
identifierResult = exprEvaluator . GetResult ( ) ; // We need 'GetResult' to read property values
if ( identifierResult . HasType ( ) )
return _FixType ( identifierResult ) ;
2019-08-23 11:56:54 -07:00
}
else if ( auto qualifiedTypeRef = BfNodeDynCast < BfQualifiedTypeReference > ( typeRef ) )
{
auto leftValue = LookupTypeRefOrIdentifier ( qualifiedTypeRef - > mLeft , isStatic ) ;
if ( leftValue . mType )
{
if ( leftValue . mType - > IsPointer ( ) )
{
mModule - > LoadValue ( leftValue ) ;
leftValue . mType = leftValue . mType - > GetUnderlyingType ( ) ;
leftValue . mKind = BfTypedValueKind_Addr ;
}
if ( auto rightNamedTypeRef = BfNodeDynCast < BfNamedTypeReference > ( qualifiedTypeRef - > mRight ) )
{
// This keeps the classifier from colorizing properties - this causes 'flashing' when we go back over this with a resolve pass
// that wouldn't catch this
2022-04-16 06:27:54 -07:00
SetAndRestoreValue < bool > prevClassifier ( mModule - > mCompiler - > mResolvePassData - > mIsClassifying , false ) ;
2019-08-23 11:56:54 -07:00
BfExprEvaluator exprEvaluator ( mModule ) ;
auto fieldResult = exprEvaluator . LookupField ( qualifiedTypeRef - > mRight , leftValue , rightNamedTypeRef - > mNameNode - > ToString ( ) ) ;
if ( ! fieldResult ) // Was property?
fieldResult = exprEvaluator . GetResult ( ) ;
2022-02-14 10:03:41 -05:00
if ( fieldResult . HasType ( ) )
{
* isStatic = false ;
return _FixType ( fieldResult ) ;
}
2019-08-23 11:56:54 -07:00
}
}
}
2022-02-14 10:03:41 -05:00
2022-02-21 18:32:23 -08:00
BfResolveTypeRefFlags resolveTypeRefFlags = BfResolveTypeRefFlag_AllowUnboundGeneric ;
if ( mResolveType = = BfResolveType_VerifyTypeName )
resolveTypeRefFlags = ( BfResolveTypeRefFlags ) ( resolveTypeRefFlags | BfResolveTypeRefFlag_ForceUnboundGeneric ) ;
BfType * type = mModule - > ResolveTypeRef ( typeRef , BfPopulateType_Identity , resolveTypeRefFlags ) ;
2022-02-14 10:03:41 -05:00
if ( type ! = NULL )
{
* isStatic = true ;
return _FixType ( BfTypedValue ( type ) ) ;
}
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
if ( auto identifier = BfNodeDynCast < BfIdentifierNode > ( node ) )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
BfExprEvaluator exprEvaluator ( mModule ) ;
2019-10-14 14:08:29 -07:00
auto identifierResult = exprEvaluator . LookupIdentifier ( identifier , false , NULL ) ;
2019-08-23 11:56:54 -07:00
if ( ! identifierResult )
identifierResult = exprEvaluator . GetResult ( ) ;
if ( identifierResult )
2020-08-12 15:07:56 -07:00
return _FixType ( identifierResult ) ;
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
if ( auto qualifiedIdentifier = BfNodeDynCast < BfQualifiedNameNode > ( node ) )
{
bool leftIsStatic = false ;
auto leftValue = LookupTypeRefOrIdentifier ( qualifiedIdentifier - > mLeft , & leftIsStatic ) ;
if ( leftValue . mType )
{
auto findName = qualifiedIdentifier - > mRight - > ToString ( ) ;
if ( findName = = " base " )
{
return BfTypedValue ( leftValue ) ;
}
BfExprEvaluator exprEvaluator ( mModule ) ;
auto fieldResult = exprEvaluator . LookupField ( node , leftValue , findName ) ;
if ( fieldResult )
return fieldResult ;
auto result = exprEvaluator . GetResult ( ) ;
if ( result )
2020-08-12 15:07:56 -07:00
return _FixType ( result ) ;
2019-08-23 11:56:54 -07:00
}
}
auto type = mModule - > ResolveTypeRef ( identifier , NULL ) ;
if ( type ! = NULL )
{
* isStatic = true ;
2020-08-12 15:07:56 -07:00
return _FixType ( BfTypedValue ( type ) ) ;
2019-08-23 11:56:54 -07:00
}
}
else if ( auto memberRefExpr = BfNodeDynCast < BfMemberReferenceExpression > ( node ) )
2022-07-26 13:27:03 -04:00
{
2020-08-12 15:07:56 -07:00
return _FixType ( mModule - > CreateValueFromExpression ( memberRefExpr , expectingType , evalExprFlags ) ) ;
2019-08-23 11:56:54 -07:00
}
else if ( auto parenExpr = BfNodeDynCast < BfParenthesizedExpression > ( node ) )
{
2022-07-26 13:27:03 -04:00
// Don't pass BfEvalExprFlags_IgnoreNullConditional, since parenExprs end nullable chains and we actually
2019-08-23 11:56:54 -07:00
// DO want the nullable at this point
2020-08-12 15:07:56 -07:00
return _FixType ( mModule - > CreateValueFromExpression ( parenExpr ) ) ;
2019-08-23 11:56:54 -07:00
}
else if ( auto targetExpr = BfNodeDynCast < BfExpression > ( node ) )
{
2020-10-10 15:41:07 -07:00
return _FixType ( mModule - > CreateValueFromExpression ( targetExpr , expectingType , evalExprFlags ) ) ;
2019-08-23 11:56:54 -07:00
}
return BfTypedValue ( ) ;
}
void BfAutoComplete : : SetDefinitionLocation ( BfAstNode * astNode , bool force )
{
if ( mIsGetDefinition )
{
if ( ( mGetDefinitionNode = = NULL ) | | ( force ) )
2022-07-26 13:27:03 -04:00
mGetDefinitionNode = astNode ;
2019-08-23 11:56:54 -07:00
}
}
bool BfAutoComplete : : IsAttribute ( BfTypeInstance * typeInst )
{
auto checkTypeInst = typeInst ;
while ( checkTypeInst ! = NULL )
{
2021-10-28 08:05:14 -07:00
if ( checkTypeInst - > mTypeDef - > GetLatest ( ) = = mModule - > mCompiler - > mAttributeTypeDef - > GetLatest ( ) )
2019-08-23 11:56:54 -07:00
return true ;
checkTypeInst = checkTypeInst - > mBaseType ;
}
return false ;
}
2020-10-08 09:41:05 -07:00
void BfAutoComplete : : AddMethod ( BfTypeInstance * typeInstance , BfMethodDef * methodDef , BfMethodInstance * methodInstance , BfMethodDeclaration * methodDecl , const StringImpl & methodName , const StringImpl & filter )
2020-10-13 15:09:06 -07:00
{
2021-11-29 08:38:42 -08:00
int wantPrefixCount = 0 ;
const char * filterStr = filter . c_str ( ) ;
while ( filterStr [ 0 ] = = ' @ ' )
{
filterStr + + ;
wantPrefixCount + + ;
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
String replaceName ;
2021-11-29 08:38:42 -08:00
AutoCompleteEntry entry ( " method " , methodName , methodDef - > mNamePrefixCount - wantPrefixCount ) ;
2019-08-23 11:56:54 -07:00
if ( methodDecl ! = NULL )
{
if ( methodDecl - > mMixinSpecifier ! = NULL )
{
replaceName = entry . mDisplay ;
replaceName + = " ! " ;
entry . mDisplay = replaceName . c_str ( ) ;
entry . mEntryType = " mixin " ;
2022-07-26 13:27:03 -04:00
}
}
2021-01-20 12:43:55 -08:00
if ( methodDef - > mMethodType = = BfMethodType_Extension )
entry . mEntryType = " extmethod " ;
2021-11-29 08:38:42 -08:00
if ( auto entryAdded = AddEntry ( entry , filterStr ) )
2020-10-05 14:54:25 -07:00
{
2020-10-08 09:41:05 -07:00
if ( methodDecl ! = NULL )
2022-07-26 13:27:03 -04:00
{
2020-12-23 08:53:38 -08:00
if ( ( methodInstance ! = NULL ) & & ( methodInstance - > mMethodDef - > mIsLocalMethod ) & & ( methodDecl - > mReturnType ! = NULL ) & & ( GetCursorIdx ( methodDecl ) = = methodDecl - > mReturnType - > mSrcEnd ) )
2020-10-08 10:17:03 -07:00
{
// This isn't really a local method decl, it just looks like one
return ;
}
2020-10-08 09:41:05 -07:00
if ( CheckDocumentation ( entryAdded , NULL ) )
{
String str ;
if ( ( methodInstance = = NULL ) & & ( methodDef ! = NULL ) )
methodInstance = mModule - > GetRawMethodInstance ( typeInstance , methodDef ) ;
if ( methodInstance ! = NULL )
2020-10-10 06:12:29 -07:00
{
SetAndRestoreValue < BfTypeInstance * > prevTypeInstance ( mModule - > mCurTypeInstance , typeInstance ) ;
SetAndRestoreValue < BfMethodInstance * > prevCurMethodInstance ( mModule - > mCurMethodInstance , methodInstance ) ;
str = mModule - > MethodToString ( methodInstance , ( BfMethodNameFlags ) ( BfMethodNameFlag_IncludeReturnType | BfMethodNameFlag_ResolveGenericParamNames ) ) ;
}
2020-10-08 09:41:05 -07:00
2020-10-08 10:17:03 -07:00
if ( entryAdded - > mDocumentation ! = NULL )
{
str + = " \x04 " ;
str . Append ( entryAdded - > mDocumentation ) ;
}
else if ( methodDecl - > mDocumentation ! = NULL )
2020-10-08 09:41:05 -07:00
{
if ( ! str . IsEmpty ( ) )
2020-10-21 09:34:08 -07:00
str + = " \x05 " ;
2022-07-26 13:27:03 -04:00
methodDecl - > mDocumentation - > GetDocString ( str ) ;
2020-10-08 09:41:05 -07:00
}
if ( ! str . IsEmpty ( ) )
entryAdded - > mDocumentation = mAlloc . AllocString ( str ) ;
}
}
2020-10-13 15:09:06 -07:00
if ( ( mResolveType = = BfResolveType_GoToDefinition ) & & ( mGetDefinitionNode = = NULL ) & & ( methodDecl ! = NULL ) & & ( methodDecl - > mNameNode ! = NULL ) )
2020-10-05 14:54:25 -07:00
SetDefinitionLocation ( methodDecl - > mNameNode ) ;
}
2019-08-23 11:56:54 -07:00
}
void BfAutoComplete : : AddTypeDef ( BfTypeDef * typeDef , const StringImpl & filter , bool onlyAttribute )
{
2021-10-28 08:05:14 -07:00
BF_ASSERT ( typeDef - > mDefState ! = BfTypeDef : : DefState_Emitted ) ;
2019-12-24 13:13:04 -08:00
if ( typeDef - > mTypeDeclaration = = NULL )
return ;
2019-08-23 11:56:54 -07:00
StringT < 64 > name ( typeDef - > mName - > ToString ( ) ) ;
if ( name = = " @ " )
return ;
int gravePos = ( int ) name . IndexOf ( ' ` ' ) ;
2022-07-26 13:27:03 -04:00
if ( gravePos ! = - 1 )
2019-08-23 11:56:54 -07:00
name = name . Substring ( 0 , gravePos ) + " <> " ;
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
if ( onlyAttribute )
{
if ( ( mIsGetDefinition ) & & ( name = = filter + " Attribute " ) )
{
SetDefinitionLocation ( typeDef - > mTypeDeclaration - > mNameNode ) ;
return ;
}
2021-12-08 22:08:57 +01:00
int score ;
uint8 matches [ 256 ] ;
if ( ! DoesFilterMatch ( name . c_str ( ) , filter . c_str ( ) , score , matches , sizeof ( matches ) ) )
2022-07-26 13:27:03 -04:00
return ;
2019-08-23 11:56:54 -07:00
auto type = mModule - > ResolveTypeDef ( typeDef , BfPopulateType_Declaration ) ;
if ( type ! = NULL )
{
auto typeInst = type - > ToTypeInstance ( ) ;
if ( ! IsAttribute ( typeInst ) )
return ;
}
const char * attrStr = " Attribute " ;
const int attrStrLen = ( int ) strlen ( attrStr ) ;
if ( ( ( int ) name . length ( ) > attrStrLen ) & & ( ( int ) name . length ( ) - ( int ) attrStrLen > = filter . length ( ) ) & & ( strcmp ( name . c_str ( ) + ( int ) name . length ( ) - attrStrLen , attrStr ) = = 0 ) )
{
// Shorter name - remove "Attribute"
name = name . Substring ( 0 , name . length ( ) - attrStrLen ) ;
}
}
AutoCompleteEntry * entryAdded = NULL ;
if ( typeDef - > mTypeCode = = BfTypeCode_Object )
2020-10-08 09:41:05 -07:00
entryAdded = AddEntry ( AutoCompleteEntry ( " class " , name ) , filter ) ;
2019-08-23 11:56:54 -07:00
else if ( typeDef - > mTypeCode = = BfTypeCode_Interface )
2020-10-08 09:41:05 -07:00
entryAdded = AddEntry ( AutoCompleteEntry ( " interface " , name ) , filter ) ;
2019-08-23 11:56:54 -07:00
else
2020-10-08 09:41:05 -07:00
entryAdded = AddEntry ( AutoCompleteEntry ( " valuetype " , name ) , filter ) ;
2019-08-23 11:56:54 -07:00
2020-10-08 09:41:05 -07:00
if ( entryAdded ! = NULL )
2019-08-23 11:56:54 -07:00
{
2020-10-21 09:56:22 -07:00
if ( ( CheckDocumentation ( entryAdded , NULL ) ) & & ( entryAdded - > mDocumentation = = NULL ) )
2020-10-08 09:41:05 -07:00
{
2022-07-26 13:27:03 -04:00
auto type = mModule - > ResolveTypeDef ( typeDef , BfPopulateType_IdentityNoRemapAlias ) ;
2020-10-21 09:56:22 -07:00
StringT < 1024 > str ;
2021-11-16 12:28:25 -08:00
if ( type ! = NULL )
{
SetAndRestoreValue < BfTypeInstance * > prevTypeInst ( mModule - > mCurTypeInstance , type - > ToTypeInstance ( ) ) ;
SetAndRestoreValue < BfMethodInstance * > prevMethodInst ( mModule - > mCurMethodInstance , NULL ) ;
str = mModule - > TypeToString ( type , ( BfTypeNameFlags ) ( BfTypeNameFlag_ExtendedInfo | BfTypeNameFlag_ResolveGenericParamNames ) ) ;
}
2020-10-21 09:56:22 -07:00
if ( typeDef - > mTypeDeclaration - > mDocumentation ! = NULL )
2020-10-08 09:41:05 -07:00
{
if ( ! str . IsEmpty ( ) )
2020-10-21 09:34:08 -07:00
str + = " \x05 " ;
2022-07-26 13:27:03 -04:00
typeDef - > mTypeDeclaration - > mDocumentation - > GetDocString ( str ) ;
2020-10-08 09:41:05 -07:00
}
entryAdded - > mDocumentation = mAlloc . AllocString ( str ) ;
}
2019-08-23 11:56:54 -07:00
}
}
2021-11-23 14:25:07 -08:00
bool BfAutoComplete : : CheckProtection ( BfProtection protection , BfTypeDef * typeDef , bool allowProtected , bool allowPrivate )
2022-07-26 13:27:03 -04:00
{
2022-07-06 12:19:01 -07:00
if ( mResolveType = = BfResolveType_GetSymbolInfo )
{
// This is needed for nameof on private inner types
return true ;
}
2021-11-23 14:25:07 -08:00
if ( ( protection = = BfProtection_Internal ) & & ( typeDef ! = NULL ) )
{
2022-07-26 13:27:03 -04:00
return mModule - > CheckProtection ( protection , typeDef , allowProtected , allowPrivate ) ;
2021-11-23 14:25:07 -08:00
}
2019-08-23 11:56:54 -07:00
return ( mHasFriendSet ) | | ( protection = = BfProtection_Public ) | |
( ( protection = = BfProtection_Protected ) & & ( allowProtected ) ) | |
( ( protection = = BfProtection_Private ) & & ( allowPrivate ) ) ;
}
const char * BfAutoComplete : : GetTypeName ( BfType * type )
{
if ( type ! = NULL )
{
if ( type - > IsPointer ( ) )
return " pointer " ;
if ( type - > IsObjectOrInterface ( ) )
return " object " ;
}
return " value " ;
}
2022-06-24 06:45:35 -07:00
void BfAutoComplete : : AddInnerTypes ( BfTypeInstance * typeInst , const StringImpl & filter , BfTypeInstance * startType , bool allowProtected , bool allowPrivate )
2022-06-23 13:55:34 -07:00
{
2022-01-03 07:30:03 -05:00
if ( typeInst - > IsEnum ( ) )
AddEntry ( AutoCompleteEntry ( " valuetype " , " UnderlyingType " ) , filter ) ;
2022-06-24 06:45:35 -07:00
BfShow checkShow = ( typeInst = = startType ) ? BfShow_Hide : BfShow_HideIndirect ;
2019-08-23 11:56:54 -07:00
for ( auto innerType : typeInst - > mTypeDef - > mNestedTypes )
{
2022-06-24 06:45:35 -07:00
if ( innerType - > mShow > = checkShow )
continue ;
2022-06-23 13:55:34 -07:00
if ( innerType - > mOuterType - > mTypeCode = = BfTypeCode_Extension )
{
if ( typeInst - > mDefineState < BfTypeDefineState_Defined )
mModule - > PopulateType ( typeInst ) ;
if ( ( typeInst - > mGenericTypeInfo ! = NULL ) & & ( typeInst - > mGenericTypeInfo - > mGenericExtensionInfo ! = NULL ) )
{
if ( ! typeInst - > mGenericTypeInfo - > mGenericExtensionInfo - > mConstraintsPassedSet . IsSet ( innerType - > mOuterType - > mPartialIdx ) )
continue ;
}
}
2021-11-23 14:25:07 -08:00
if ( CheckProtection ( innerType - > mProtection , innerType , allowProtected , allowPrivate ) )
2019-08-23 11:56:54 -07:00
AddTypeDef ( innerType , filter ) ;
2022-06-23 13:55:34 -07:00
}
2019-08-23 11:56:54 -07:00
allowPrivate = false ;
if ( typeInst - > mBaseType ! = NULL )
2022-06-24 06:45:35 -07:00
AddInnerTypes ( typeInst - > mBaseType , filter , startType , allowProtected , allowPrivate ) ;
2019-08-23 11:56:54 -07:00
}
void BfAutoComplete : : AddCurrentTypes ( BfTypeInstance * typeInst , const StringImpl & filter , bool allowProtected , bool allowPrivate , bool onlyAttribute )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
if ( typeInst ! = mModule - > mCurTypeInstance )
2021-10-28 08:05:14 -07:00
AddTypeDef ( typeInst - > mTypeDef - > GetDefinition ( ) , filter , onlyAttribute ) ;
2019-08-23 11:56:54 -07:00
2021-10-28 08:05:14 -07:00
auto typeDef = typeInst - > mTypeDef - > GetDefinition ( ) ;
2019-08-23 11:56:54 -07:00
for ( auto nestedTypeDef : typeDef - > mNestedTypes )
{
2019-09-10 11:27:53 -07:00
if ( nestedTypeDef - > mIsPartial )
{
nestedTypeDef = mSystem - > GetCombinedPartial ( nestedTypeDef ) ;
if ( nestedTypeDef = = NULL )
continue ;
}
2021-11-23 14:25:07 -08:00
if ( CheckProtection ( nestedTypeDef - > mProtection , nestedTypeDef , allowProtected , allowPrivate ) )
2019-08-23 11:56:54 -07:00
AddTypeDef ( nestedTypeDef , filter , onlyAttribute ) ;
}
auto outerType = mModule - > GetOuterType ( typeInst ) ;
if ( outerType ! = NULL )
AddCurrentTypes ( outerType , filter , allowProtected , allowPrivate , onlyAttribute ) ;
allowPrivate = false ;
auto baseType = mModule - > GetBaseType ( typeInst ) ;
if ( baseType ! = NULL )
AddCurrentTypes ( baseType , filter , allowProtected , allowPrivate , onlyAttribute ) ;
}
2020-10-08 09:41:05 -07:00
void BfAutoComplete : : AddField ( BfTypeInstance * typeInst , BfFieldDef * fieldDef , BfFieldInstance * fieldInstance , const StringImpl & filter )
2022-07-26 13:27:03 -04:00
{
2021-11-29 08:38:42 -08:00
int wantPrefixCount = 0 ;
const char * filterStr = filter . c_str ( ) ;
while ( filterStr [ 0 ] = = ' @ ' )
{
filterStr + + ;
wantPrefixCount + + ;
2022-07-26 13:27:03 -04:00
}
2021-11-29 08:38:42 -08:00
AutoCompleteEntry entry ( GetTypeName ( fieldInstance - > mResolvedType ) , fieldDef - > mName , fieldDef - > mNamePrefixCount - wantPrefixCount ) ;
if ( auto entryAdded = AddEntry ( entry , filterStr ) )
2020-10-08 09:41:05 -07:00
{
2022-04-16 16:43:21 -07:00
auto fieldDecl = fieldDef - > GetFieldDeclaration ( ) ;
auto documentation = ( fieldDecl ! = NULL ) ? fieldDecl - > mDocumentation : NULL ;
2020-10-08 09:41:05 -07:00
if ( CheckDocumentation ( entryAdded , documentation ) )
{
mModule - > PopulateType ( typeInst ) ;
2022-07-26 13:27:03 -04:00
2024-11-08 09:16:27 -05:00
bool isTag = typeInst - > IsEnum ( ) & & typeInst - > IsOnDemand ( ) ;
String str ;
if ( ! isTag )
{
if ( ! fieldInstance - > GetFieldDef ( ) - > IsEnumCaseEntry ( ) )
{
str + = mModule - > TypeToString ( fieldInstance - > mResolvedType ) ;
str + = " " ;
}
str + = mModule - > TypeToString ( typeInst ) ;
str + = " . " ;
str + = fieldDef - > mName ;
}
2020-10-21 09:34:08 -07:00
if ( entryAdded - > mDocumentation ! = NULL )
2020-10-08 09:41:05 -07:00
{
str + = " \x04 " ;
2020-10-21 09:34:08 -07:00
str . Append ( entryAdded - > mDocumentation ) ;
}
else if ( documentation ! = NULL )
{
str + = " \x05 " ;
2020-10-08 09:41:05 -07:00
documentation - > GetDocString ( str ) ;
}
2024-11-08 09:16:27 -05:00
if ( ! str . IsEmpty ( ) )
entryAdded - > mDocumentation = mAlloc . AllocString ( str ) ;
2020-10-08 09:41:05 -07:00
}
if ( ( mIsGetDefinition ) & & ( mDefType = = NULL ) )
{
mDefType = typeInst - > mTypeDef ;
mDefField = fieldDef ;
2022-04-16 16:43:21 -07:00
if ( auto nameNode = fieldDef - > GetNameNode ( ) )
SetDefinitionLocation ( nameNode ) ;
2020-10-08 09:41:05 -07:00
}
}
}
void BfAutoComplete : : AddProp ( BfTypeInstance * typeInst , BfPropertyDef * propDef , const StringImpl & filter )
{
2021-11-29 08:38:42 -08:00
int wantPrefixCount = 0 ;
const char * filterStr = filter . c_str ( ) ;
while ( filterStr [ 0 ] = = ' @ ' )
{
filterStr + + ;
wantPrefixCount + + ;
2022-07-26 13:27:03 -04:00
}
2020-10-08 09:41:05 -07:00
BfCommentNode * documentation = NULL ;
2022-04-16 16:43:21 -07:00
auto fieldDecl = propDef - > GetFieldDeclaration ( ) ;
if ( fieldDecl ! = NULL )
documentation = fieldDecl - > mDocumentation ;
2021-11-29 08:38:42 -08:00
AutoCompleteEntry entry ( " property " , propDef - > mName , propDef - > mNamePrefixCount - wantPrefixCount ) ;
if ( auto entryAdded = AddEntry ( entry , filterStr ) )
2020-10-08 09:41:05 -07:00
{
if ( CheckDocumentation ( entryAdded , documentation ) )
{
BfType * propType = NULL ;
2020-10-08 10:17:03 -07:00
bool hasGetter = false ;
bool hasSetter = false ;
2020-10-08 09:41:05 -07:00
for ( auto methodDef : propDef - > mMethods )
{
auto methodInstance = mModule - > GetRawMethodInstance ( typeInst , methodDef ) ;
if ( methodInstance = = NULL )
continue ;
if ( methodDef - > mMethodType = = BfMethodType_PropertyGetter )
{
2020-10-08 10:17:03 -07:00
hasGetter = true ;
2022-07-26 13:27:03 -04:00
propType = methodInstance - > mReturnType ;
2020-10-08 09:41:05 -07:00
}
if ( methodDef - > mMethodType = = BfMethodType_PropertySetter )
{
2020-10-08 10:17:03 -07:00
hasSetter = true ;
2022-07-10 07:50:08 -04:00
if ( methodInstance - > GetParamCount ( ) > 0 )
propType = methodInstance - > GetParamType ( 0 ) ;
2020-10-08 09:41:05 -07:00
}
}
String str ;
if ( propType ! = NULL )
{
str + = mModule - > TypeToString ( propType ) ;
str + = " " ;
}
str + = mModule - > TypeToString ( typeInst ) ;
str + = " . " ;
str + = propDef - > mName ;
2020-10-08 10:17:03 -07:00
str + = " { " ;
if ( hasGetter )
str + = " get; " ;
if ( hasSetter )
str + = " set; " ;
str + = " } " ;
2020-10-21 09:34:08 -07:00
if ( entryAdded - > mDocumentation ! = NULL )
2020-10-08 09:41:05 -07:00
{
str + = " \x04 " ;
2020-10-21 09:34:08 -07:00
str . Append ( entryAdded - > mDocumentation ) ;
}
else if ( documentation ! = NULL )
{
str + = " \x05 " ;
2020-10-08 09:41:05 -07:00
documentation - > GetDocString ( str ) ;
}
entryAdded - > mDocumentation = mAlloc . AllocString ( str ) ;
}
2022-04-16 16:43:21 -07:00
if ( ( mIsGetDefinition ) & & ( fieldDecl ! = NULL ) )
SetDefinitionLocation ( fieldDecl - > mNameNode ) ;
2020-10-08 09:41:05 -07:00
}
}
2021-01-16 13:43:44 -08:00
void BfAutoComplete : : AddTypeMembers ( BfTypeInstance * typeInst , bool addStatic , bool addNonStatic , const StringImpl & filter , BfTypeInstance * startType , bool allowInterfaces , bool allowImplicitThis , bool checkOuterType )
2019-08-23 11:56:54 -07:00
{
bool isInterface = false ;
2022-07-26 13:27:03 -04:00
2020-09-11 10:33:16 -07:00
if ( mForceAllowNonStatic )
addNonStatic = true ;
2019-08-23 11:56:54 -07:00
auto activeTypeDef = mModule - > GetActiveTypeDef ( ) ;
2022-06-24 06:45:35 -07:00
if ( ( addStatic ) & & ( mModule - > mCurMethodInstance = = NULL ) & & ( typeInst - > IsEnum ( ) ) & & ( allowImplicitThis ) )
2019-12-24 13:13:04 -08:00
{
2022-01-03 07:30:03 -05:00
AddEntry ( AutoCompleteEntry ( " value " , " _ " ) , filter ) ;
2019-12-24 13:13:04 -08:00
}
2019-08-23 11:56:54 -07:00
# define CHECK_STATIC(staticVal) ((staticVal && addStatic) || (!staticVal && addNonStatic))
mModule - > PopulateType ( typeInst , BfPopulateType_Data ) ;
2022-06-24 06:45:35 -07:00
BfShow checkShow = ( startType = = typeInst ) ? BfShow_Hide : BfShow_HideIndirect ;
2019-08-23 11:56:54 -07:00
BfProtectionCheckFlags protectionCheckFlags = BfProtectionCheckFlag_None ;
for ( auto & fieldInst : typeInst - > mFieldInstances )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
auto fieldDef = fieldInst . GetFieldDef ( ) ;
if ( fieldDef = = NULL )
continue ;
2022-06-24 06:45:35 -07:00
if ( fieldDef - > mShow > = checkShow )
2019-08-23 11:56:54 -07:00
continue ;
2022-07-26 13:27:03 -04:00
if ( ( CHECK_STATIC ( fieldDef - > mIsStatic ) ) & &
2020-03-09 06:34:16 -07:00
( ( mIsGetDefinition ) | | ( mModule - > CheckProtection ( protectionCheckFlags , typeInst , fieldDef - > mDeclaringType - > mProject , fieldDef - > mProtection , startType ) ) ) )
2019-08-23 11:56:54 -07:00
{
if ( ( ! typeInst - > IsTypeMemberIncluded ( fieldDef - > mDeclaringType , activeTypeDef , mModule ) ) | |
( ! typeInst - > IsTypeMemberAccessible ( fieldDef - > mDeclaringType , activeTypeDef ) ) )
continue ;
2022-07-26 13:27:03 -04:00
2020-10-08 09:41:05 -07:00
AddField ( typeInst , fieldDef , & fieldInst , filter ) ;
2019-08-23 11:56:54 -07:00
}
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
for ( auto methodDef : typeInst - > mTypeDef - > mMethods )
{
if ( methodDef - > mIsOverride )
continue ;
2022-06-24 06:45:35 -07:00
if ( methodDef - > mShow > = checkShow )
2019-08-23 11:56:54 -07:00
continue ;
if ( methodDef - > mName . IsEmpty ( ) )
continue ;
if ( methodDef - > mExplicitInterface ! = NULL )
continue ;
if ( ( ! typeInst - > IsTypeMemberIncluded ( methodDef - > mDeclaringType , activeTypeDef , mModule ) ) | |
( ! typeInst - > IsTypeMemberAccessible ( methodDef - > mDeclaringType , activeTypeDef ) ) )
continue ;
bool canUseMethod ;
canUseMethod = ( methodDef - > mMethodType = = BfMethodType_Normal ) | | ( methodDef - > mMethodType = = BfMethodType_Mixin ) ;
if ( isInterface )
{
// Always allow
canUseMethod & = addNonStatic ;
}
else
{
canUseMethod & = ( CHECK_STATIC ( methodDef - > mIsStatic ) & &
2022-07-26 13:27:03 -04:00
( mModule - > CheckProtection ( protectionCheckFlags , typeInst , methodDef - > mDeclaringType - > mProject , methodDef - > mProtection , startType ) ) ) ;
2019-08-23 11:56:54 -07:00
}
if ( canUseMethod )
{
2022-07-26 13:27:03 -04:00
AddMethod ( typeInst , methodDef , NULL , methodDef - > GetMethodDeclaration ( ) , methodDef - > mName , filter ) ;
2019-08-23 11:56:54 -07:00
}
}
for ( auto propDef : typeInst - > mTypeDef - > mProperties )
{
2022-06-24 06:45:35 -07:00
if ( propDef - > mShow > = checkShow )
2019-08-23 11:56:54 -07:00
continue ;
if ( ( ! typeInst - > IsTypeMemberIncluded ( propDef - > mDeclaringType , activeTypeDef , mModule ) ) | |
( ! typeInst - > IsTypeMemberAccessible ( propDef - > mDeclaringType , activeTypeDef ) ) )
continue ;
2020-03-09 06:34:16 -07:00
if ( ( CHECK_STATIC ( propDef - > mIsStatic ) ) & & ( mModule - > CheckProtection ( protectionCheckFlags , typeInst , propDef - > mDeclaringType - > mProject , propDef - > mProtection , startType ) ) )
2019-08-23 11:56:54 -07:00
{
if ( ( ! allowInterfaces ) & & ( propDef - > HasExplicitInterface ( ) ) )
continue ;
if ( propDef - > mName = = " [] " )
continue ;
2020-10-08 09:41:05 -07:00
AddProp ( typeInst , propDef , filter ) ;
2019-08-23 11:56:54 -07:00
}
}
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
if ( allowInterfaces )
{
for ( auto iface : typeInst - > mInterfaces )
2021-01-16 13:43:44 -08:00
AddTypeMembers ( iface . mInterfaceType , addStatic , addNonStatic , filter , startType , false , allowImplicitThis , false ) ;
2019-08-23 11:56:54 -07:00
}
if ( typeInst - > mBaseType ! = NULL )
2021-01-16 13:43:44 -08:00
AddTypeMembers ( typeInst - > mBaseType , addStatic , addNonStatic , filter , startType , false , allowImplicitThis , false ) ;
2019-08-23 11:56:54 -07:00
else
{
if ( typeInst - > IsStruct ( ) )
2021-01-16 13:43:44 -08:00
AddTypeMembers ( mModule - > mContext - > mBfObjectType , addStatic , addNonStatic , filter , startType , false , allowImplicitThis , false ) ;
2019-08-23 11:56:54 -07:00
}
2022-06-29 07:18:01 -07:00
if ( typeInst - > IsInterface ( ) )
{
for ( auto interface : typeInst - > mInterfaces )
AddTypeMembers ( interface . mInterfaceType , addStatic , addNonStatic , filter , startType , false , allowImplicitThis , false ) ;
}
2021-01-16 13:43:44 -08:00
if ( ( addStatic ) & & ( allowImplicitThis ) & & ( checkOuterType ) )
2019-08-23 11:56:54 -07:00
{
auto outerType = mModule - > GetOuterType ( typeInst ) ;
if ( outerType ! = NULL )
{
2021-01-16 13:43:44 -08:00
AddTypeMembers ( outerType , true , false , filter , startType , false , allowImplicitThis , false ) ;
2019-08-23 11:56:54 -07:00
}
}
2022-07-10 07:50:08 -04:00
if ( ( typeInst - > mTypeDef - > mHasUsingFields ) & &
( ( typeInst - > mTypeInfoEx = = NULL ) | | ( typeInst - > mTypeInfoEx - > mUsingFieldData = = NULL ) ) )
mModule - > PopulateUsingFieldData ( typeInst ) ;
if ( ( typeInst - > mTypeInfoEx ! = NULL ) & & ( typeInst - > mTypeInfoEx - > mUsingFieldData ! = NULL ) )
{
for ( int pass = 0 ; pass < 2 ; pass + + )
{
auto & dict = ( pass = = 0 ) ? typeInst - > mTypeInfoEx - > mUsingFieldData - > mEntries : typeInst - > mTypeInfoEx - > mUsingFieldData - > mMethods ;
for ( auto & entryKV : dict )
{
for ( auto & entryList : entryKV . mValue . mLookups )
{
auto & endEntry = entryList . back ( ) ;
bool isStatic = endEntry . IsStatic ( ) ;
if ( ( isStatic ) & & ( ! addStatic ) )
continue ;
if ( ( ! isStatic ) & & ( ! addNonStatic ) )
continue ;
bool passesProtection = true ;
for ( int entryIdx = 0 ; entryIdx < entryList . mSize ; entryIdx + + )
{
auto & entry = entryList [ entryIdx ] ;
if ( ! mModule - > CheckProtection ( protectionCheckFlags , entry . mTypeInstance , entry . GetDeclaringType ( mModule ) - > mProject ,
( entryIdx < entryList . mSize - 1 ) ? entry . GetUsingProtection ( ) : entry . GetProtection ( ) , typeInst ) )
{
passesProtection = false ;
break ;
}
}
if ( ! passesProtection )
continue ;
switch ( endEntry . mKind )
{
case BfUsingFieldData : : MemberRef : : Kind_Field :
if ( endEntry . mTypeInstance - > mDefineState < BfTypeDefineState_Defined )
mModule - > PopulateType ( endEntry . mTypeInstance ) ;
AddField ( endEntry . mTypeInstance , endEntry . mTypeInstance - > mTypeDef - > mFields [ endEntry . mIdx ] , & endEntry . mTypeInstance - > mFieldInstances [ endEntry . mIdx ] , filter ) ;
break ;
case BfUsingFieldData : : MemberRef : : Kind_Property :
AddProp ( endEntry . mTypeInstance , endEntry . mTypeInstance - > mTypeDef - > mProperties [ endEntry . mIdx ] , filter ) ;
break ;
case BfUsingFieldData : : MemberRef : : Kind_Method :
{
auto methodDef = endEntry . mTypeInstance - > mTypeDef - > mMethods [ endEntry . mIdx ] ;
AddMethod ( endEntry . mTypeInstance , methodDef , NULL , methodDef - > GetMethodDeclaration ( ) , methodDef - > mName , filter ) ;
}
break ;
}
}
}
}
}
2019-08-23 11:56:54 -07:00
}
void BfAutoComplete : : AddSelfResultTypeMembers ( BfTypeInstance * typeInst , BfTypeInstance * selfType , const StringImpl & filter , bool allowPrivate )
{
bool isInterface = false ;
bool allowProtected = allowPrivate ;
auto activeTypeDef = mModule - > GetActiveTypeDef ( ) ;
mModule - > PopulateType ( typeInst , BfPopulateType_Data ) ;
2022-06-24 06:45:35 -07:00
BfShow checkShow = allowPrivate ? BfShow_Hide : BfShow_HideIndirect ;
2019-08-23 11:56:54 -07:00
for ( auto & fieldInst : typeInst - > mFieldInstances )
{
auto fieldDef = fieldInst . GetFieldDef ( ) ;
if ( fieldDef = = NULL )
continue ;
2022-06-24 06:45:35 -07:00
if ( fieldDef - > mShow > checkShow )
2019-08-23 11:56:54 -07:00
continue ;
2022-07-26 13:27:03 -04:00
2021-11-23 14:25:07 -08:00
if ( ( fieldDef - > mIsStatic ) & & ( CheckProtection ( fieldDef - > mProtection , fieldDef - > mDeclaringType , allowProtected , allowPrivate ) ) )
2019-08-23 11:56:54 -07:00
{
2020-01-24 10:36:22 -08:00
if ( ! mModule - > CanCast ( BfTypedValue ( mModule - > mBfIRBuilder - > GetFakeVal ( ) , fieldInst . mResolvedType ) , selfType ) )
2019-08-23 11:56:54 -07:00
continue ;
if ( ( ! typeInst - > IsTypeMemberIncluded ( fieldDef - > mDeclaringType , activeTypeDef , mModule ) ) | |
( ! typeInst - > IsTypeMemberAccessible ( fieldDef - > mDeclaringType , activeTypeDef ) ) )
continue ;
2022-07-26 13:27:03 -04:00
AddField ( typeInst , fieldDef , & fieldInst , filter ) ;
2019-08-23 11:56:54 -07:00
}
}
for ( auto methodDef : typeInst - > mTypeDef - > mMethods )
{
if ( methodDef - > mIsOverride )
continue ;
2022-06-24 06:45:35 -07:00
if ( methodDef - > mShow > checkShow )
2019-08-23 11:56:54 -07:00
continue ;
if ( methodDef - > mName . IsEmpty ( ) )
continue ;
if ( methodDef - > mExplicitInterface ! = NULL )
continue ;
if ( ( ! typeInst - > IsTypeMemberIncluded ( methodDef - > mDeclaringType , activeTypeDef , mModule ) ) | |
( ! typeInst - > IsTypeMemberAccessible ( methodDef - > mDeclaringType , activeTypeDef ) ) )
continue ;
if ( ! methodDef - > mIsStatic )
continue ;
bool canUseMethod ;
2022-07-26 13:27:03 -04:00
canUseMethod = ( methodDef - > mMethodType = = BfMethodType_Normal ) | | ( methodDef - > mMethodType = = BfMethodType_Mixin ) ;
2021-11-23 14:25:07 -08:00
canUseMethod & = CheckProtection ( methodDef - > mProtection , methodDef - > mDeclaringType , allowProtected , allowPrivate ) ;
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
if ( methodDef - > mMethodType ! = BfMethodType_Normal )
continue ;
auto methodInstance = mModule - > GetRawMethodInstanceAtIdx ( typeInst , methodDef - > mIdx ) ;
if ( methodInstance = = NULL )
continue ;
if ( methodInstance - > mReturnType - > IsUnspecializedType ( ) )
continue ;
2020-01-24 10:36:22 -08:00
if ( ! mModule - > CanCast ( BfTypedValue ( mModule - > mBfIRBuilder - > GetFakeVal ( ) , methodInstance - > mReturnType ) , selfType ) )
2019-08-23 11:56:54 -07:00
continue ;
if ( canUseMethod )
2020-10-08 09:41:05 -07:00
{
2019-08-23 11:56:54 -07:00
if ( auto methodDeclaration = methodDef - > GetMethodDeclaration ( ) )
{
2020-10-08 09:41:05 -07:00
AddMethod ( typeInst , methodDef , NULL , methodDeclaration , methodDef - > mName , filter ) ;
2019-08-23 11:56:54 -07:00
}
}
}
for ( auto propDef : typeInst - > mTypeDef - > mProperties )
{
2022-06-24 06:45:35 -07:00
if ( propDef - > mShow > checkShow )
2019-08-23 11:56:54 -07:00
continue ;
if ( ( ! typeInst - > IsTypeMemberIncluded ( propDef - > mDeclaringType , activeTypeDef , mModule ) ) | |
( ! typeInst - > IsTypeMemberAccessible ( propDef - > mDeclaringType , activeTypeDef ) ) )
continue ;
if ( ! propDef - > mIsStatic )
continue ;
BfMethodDef * getMethod = NULL ;
for ( auto methodDef : propDef - > mMethods )
{
if ( methodDef - > mMethodType = = BfMethodType_PropertyGetter )
{
getMethod = methodDef ;
break ;
}
}
if ( getMethod = = NULL )
continue ;
auto methodInstance = mModule - > GetRawMethodInstanceAtIdx ( typeInst , getMethod - > mIdx ) ;
if ( methodInstance = = NULL )
continue ;
if ( methodInstance - > mReturnType ! = selfType )
continue ;
2021-11-23 14:25:07 -08:00
if ( CheckProtection ( propDef - > mProtection , propDef - > mDeclaringType , allowProtected , allowPrivate ) )
2019-08-23 11:56:54 -07:00
{
if ( propDef - > HasExplicitInterface ( ) )
continue ;
if ( propDef - > mName = = " [] " )
continue ;
2020-10-08 09:41:05 -07:00
AddProp ( typeInst , propDef , filter ) ;
2019-08-23 11:56:54 -07:00
}
}
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
auto outerType = mModule - > GetOuterType ( typeInst ) ;
if ( outerType ! = NULL )
{
AddSelfResultTypeMembers ( outerType , selfType , filter , false ) ;
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
}
bool BfAutoComplete : : InitAutocomplete ( BfAstNode * dotNode , BfAstNode * nameNode , String & filter )
2022-07-26 13:27:03 -04:00
{
2021-09-10 14:21:25 -07:00
bool isDot = ( dotNode ! = NULL ) & & ( dotNode - > mToken = = BfToken_Dot ) ;
2019-08-23 11:56:54 -07:00
if ( IsAutocompleteNode ( nameNode ) )
{
auto bfParser = nameNode - > GetSourceData ( ) - > ToParser ( ) ;
2021-09-10 14:21:25 -07:00
if ( ( mIsGetDefinition ) | | ( ! isDot ) )
2019-08-23 11:56:54 -07:00
{
mInsertStartIdx = nameNode - > GetSrcStart ( ) ;
mInsertEndIdx = nameNode - > GetSrcEnd ( ) ;
}
else
{
mInsertStartIdx = dotNode - > GetSrcEnd ( ) ;
mInsertEndIdx = std : : min ( bfParser - > mCursorIdx + 1 , nameNode - > GetSrcEnd ( ) ) ;
}
2021-09-10 14:21:25 -07:00
filter . Append ( bfParser - > mSrc + nameNode - > GetSrcStart ( ) , mInsertEndIdx - nameNode - > GetSrcStart ( ) ) ;
2019-08-23 11:56:54 -07:00
return true ;
}
2021-09-10 14:21:25 -07:00
int lenAdd = 0 ;
if ( ! isDot )
lenAdd + + ;
if ( ( dotNode ! = NULL ) & & ( IsAutocompleteNode ( dotNode , lenAdd , 1 ) ) )
2019-08-23 11:56:54 -07:00
{
mInsertStartIdx = dotNode - > GetSrcEnd ( ) ;
mInsertEndIdx = dotNode - > GetSrcEnd ( ) ;
return true ;
}
return false ;
}
void BfAutoComplete : : AddEnumTypeMembers ( BfTypeInstance * typeInst , const StringImpl & filter , bool allowProtected , bool allowPrivate )
{
mModule - > PopulateType ( typeInst , BfPopulateType_Data ) ;
auto activeTypeDef = mModule - > GetActiveTypeDef ( ) ;
for ( auto & fieldInst : typeInst - > mFieldInstances )
{
auto fieldDef = fieldInst . GetFieldDef ( ) ;
2022-07-26 13:27:03 -04:00
if ( ( fieldDef ! = NULL ) & & ( fieldDef - > mIsConst ) & &
( ( fieldInst . mResolvedType = = typeInst ) | | ( fieldInst . mIsEnumPayloadCase ) ) & &
2021-11-23 14:25:07 -08:00
( CheckProtection ( fieldDef - > mProtection , fieldDef - > mDeclaringType , allowProtected , allowPrivate ) ) )
2019-08-23 11:56:54 -07:00
{
if ( ( ! typeInst - > IsTypeMemberIncluded ( fieldDef - > mDeclaringType , activeTypeDef , mModule ) ) | |
( ! typeInst - > IsTypeMemberAccessible ( fieldDef - > mDeclaringType , activeTypeDef ) ) )
continue ;
bool hasPayload = false ;
if ( ( fieldInst . mIsEnumPayloadCase ) & & ( fieldInst . mResolvedType - > IsTuple ( ) ) )
{
2020-06-04 15:02:46 -07:00
auto payloadType = ( BfTypeInstance * ) fieldInst . mResolvedType ;
2019-08-23 11:56:54 -07:00
if ( ! payloadType - > mFieldInstances . empty ( ) )
hasPayload = true ;
}
2020-10-08 09:41:05 -07:00
AutoCompleteEntry entry ( hasPayload ? " payloadEnum " : " value " , fieldDef - > mName ) ;
if ( auto entryAdded = AddEntry ( entry , filter ) )
2019-08-23 11:56:54 -07:00
{
2024-11-08 09:16:27 -05:00
auto fieldDecl = fieldDef - > GetFieldDeclaration ( ) ;
if ( fieldDecl = = NULL )
continue ;
if ( CheckDocumentation ( entryAdded , fieldDecl - > mDocumentation ) )
2020-10-08 09:41:05 -07:00
{
}
if ( mIsGetDefinition )
{
mDefType = typeInst - > mTypeDef ;
mDefField = fieldDef ;
2024-11-08 09:16:27 -05:00
if ( fieldDecl ! = NULL )
SetDefinitionLocation ( fieldDecl - > mNameNode ) ;
2020-10-08 09:41:05 -07:00
}
2019-08-23 11:56:54 -07:00
}
}
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
}
2020-06-03 05:22:11 -07:00
void BfAutoComplete : : AddExtensionMethods ( BfTypeInstance * targetType , BfTypeInstance * extensionContainer , const StringImpl & filter , bool allowProtected , bool allowPrivate )
{
if ( ! extensionContainer - > mTypeDef - > mHasExtensionMethods )
return ;
mModule - > PopulateType ( extensionContainer , BfPopulateType_Data ) ;
2022-06-24 06:45:35 -07:00
BfShow checkShow = allowPrivate ? BfShow_Hide : BfShow_HideIndirect ;
2020-06-03 05:22:11 -07:00
for ( auto methodDef : extensionContainer - > mTypeDef - > mMethods )
{
if ( methodDef - > mMethodType ! = BfMethodType_Extension )
2022-07-26 13:27:03 -04:00
continue ;
2022-06-24 06:45:35 -07:00
if ( methodDef - > mShow > = checkShow )
2020-06-03 05:22:11 -07:00
continue ;
if ( methodDef - > mName . IsEmpty ( ) )
continue ;
2022-07-26 13:27:03 -04:00
bool canUseMethod = true ;
2021-11-23 14:25:07 -08:00
canUseMethod & = CheckProtection ( methodDef - > mProtection , methodDef - > mDeclaringType , allowProtected , allowPrivate ) ;
2022-07-26 13:27:03 -04:00
2020-06-03 05:22:11 -07:00
auto methodInstance = mModule - > GetRawMethodInstanceAtIdx ( extensionContainer , methodDef - > mIdx ) ;
if ( methodInstance = = NULL )
continue ;
2021-12-08 22:08:57 +01:00
int score ;
uint8 matches [ 256 ] ;
2020-06-03 05:22:11 -07:00
// Do filter match first- may be cheaper than generic validation
2021-12-08 22:08:57 +01:00
if ( ! DoesFilterMatch ( methodDef - > mName . c_str ( ) , filter . c_str ( ) , score , matches , sizeof ( matches ) ) )
2020-06-03 05:22:11 -07:00
continue ;
2022-07-26 13:27:03 -04:00
auto thisType = methodInstance - > GetParamType ( 0 ) ;
2020-06-03 05:22:11 -07:00
bool paramValidated = false ;
if ( methodInstance - > GetNumGenericParams ( ) > 0 )
{
if ( ( thisType - > IsGenericParam ( ) ) & & ( methodInstance - > GetNumGenericParams ( ) = = 1 ) )
{
auto genericParamType = ( BfGenericParamType * ) thisType ;
if ( genericParamType - > mGenericParamKind = = BfGenericParamKind_Method )
{
auto & genericParams = methodInstance - > mMethodInfoEx - > mGenericParams ;
if ( ! mModule - > CheckGenericConstraints ( BfGenericParamSource ( methodInstance ) , targetType , NULL , genericParams [ genericParamType - > mGenericParamIdx ] , NULL , NULL ) )
continue ;
paramValidated = true ;
}
}
if ( ( ( thisType - > IsUnspecializedTypeVariation ( ) ) | | ( thisType - > IsGenericParam ( ) ) ) & &
( ! paramValidated ) )
{
BfTypeVector genericTypeVector ;
genericTypeVector . resize ( methodInstance - > GetNumGenericParams ( ) ) ;
BfGenericInferContext genericInferContext ;
genericInferContext . mCheckMethodGenericArguments = & genericTypeVector ;
genericInferContext . mModule = mModule ;
genericInferContext . mPrevArgValues . resize ( methodInstance - > GetNumGenericParams ( ) ) ;
if ( ! genericInferContext . InferGenericArgument ( methodInstance , targetType , thisType , BfIRValue ( ) ) )
continue ;
2021-01-20 12:43:55 -08:00
genericInferContext . InferGenericArguments ( methodInstance ) ;
2020-06-03 05:22:11 -07:00
2022-04-30 08:53:24 -07:00
thisType = mModule - > ResolveGenericType ( thisType , NULL , & genericTypeVector , mModule - > mCurTypeInstance , false ) ;
2020-06-03 05:22:11 -07:00
if ( thisType = = NULL )
continue ;
auto & genericParams = methodInstance - > mMethodInfoEx - > mGenericParams ;
bool validateError = false ;
for ( int genericIdx = 0 ; genericIdx < ( int ) genericTypeVector . size ( ) ; genericIdx + + )
{
auto genericArg = genericTypeVector [ genericIdx ] ;
if ( genericArg = = NULL )
continue ;
if ( ! mModule - > CheckGenericConstraints ( BfGenericParamSource ( methodInstance ) , genericArg , NULL , genericParams [ genericIdx ] , & genericTypeVector , NULL ) )
{
validateError = true ;
break ;
}
}
if ( validateError )
continue ;
}
}
if ( ! paramValidated )
{
if ( ! mModule - > CanCast ( BfTypedValue ( mModule - > mBfIRBuilder - > GetFakeVal ( ) , targetType ) , thisType ) )
continue ;
}
if ( canUseMethod )
{
if ( auto methodDeclaration = methodDef - > GetMethodDeclaration ( ) )
{
2020-10-08 09:41:05 -07:00
AddMethod ( extensionContainer , methodDef , NULL , methodDeclaration , methodDef - > mName , filter ) ;
2020-06-03 05:22:11 -07:00
}
}
}
}
2019-08-23 11:56:54 -07:00
2022-01-01 10:12:20 -05:00
BfProject * BfAutoComplete : : GetActiveProject ( )
{
BfProject * bfProject = NULL ;
auto activeTypeDef = mModule - > GetActiveTypeDef ( ) ;
if ( activeTypeDef ! = NULL )
bfProject = activeTypeDef - > mProject ;
2022-04-16 06:27:54 -07:00
else if ( ! mCompiler - > mResolvePassData - > mParsers . IsEmpty ( ) )
bfProject = mCompiler - > mResolvePassData - > mParsers [ 0 ] - > mProject ;
2022-01-01 10:12:20 -05:00
return bfProject ;
}
2022-04-16 06:27:54 -07:00
bool BfAutoComplete : : WantsEntries ( )
{
2022-04-25 14:41:03 -07:00
if ( mModule = = NULL )
return false ;
2022-07-26 13:27:03 -04:00
return ( mResolveType = = BfResolveType_Autocomplete ) | |
2022-04-16 16:43:21 -07:00
( mResolveType = = BfResolveType_Autocomplete_HighPri ) | |
( mResolveType = = BfResolveType_GetSymbolInfo ) | |
2022-06-01 15:21:02 -07:00
( mResolveType = = BfResolveType_GoToDefinition ) | |
( mResolveType = = BfResolveType_VerifyTypeName ) ;
2022-04-16 06:27:54 -07:00
}
2020-05-26 06:10:51 -07:00
void BfAutoComplete : : AddTopLevelNamespaces ( BfAstNode * identifierNode )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
String filter ;
if ( identifierNode ! = NULL )
{
filter = identifierNode - > ToString ( ) ;
mInsertStartIdx = identifierNode - > GetSrcStart ( ) ;
mInsertEndIdx = identifierNode - > GetSrcEnd ( ) ;
}
2022-07-26 13:27:03 -04:00
BfProject * bfProject = GetActiveProject ( ) ;
2019-08-23 11:56:54 -07:00
auto _AddProjectNamespaces = [ & ] ( BfProject * project )
{
for ( auto namespacePair : project - > mNamespaces )
{
const BfAtomComposite & namespaceComposite = namespacePair . mKey ;
if ( namespaceComposite . GetPartsCount ( ) = = 1 )
{
AddEntry ( AutoCompleteEntry ( " namespace " , namespaceComposite . ToString ( ) ) , filter ) ;
}
}
} ;
if ( bfProject ! = NULL )
{
for ( int depIdx = - 1 ; depIdx < ( int ) bfProject - > mDependencies . size ( ) ; depIdx + + )
{
BfProject * depProject = ( depIdx = = - 1 ) ? bfProject : bfProject - > mDependencies [ depIdx ] ;
_AddProjectNamespaces ( depProject ) ;
}
}
else
{
for ( auto project : mSystem - > mProjects )
_AddProjectNamespaces ( project ) ;
}
}
2020-05-26 06:10:51 -07:00
void BfAutoComplete : : AddTopLevelTypes ( BfAstNode * identifierNode , bool onlyAttribute )
2019-08-23 11:56:54 -07:00
{
String filter ;
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
if ( identifierNode ! = NULL )
{
filter = identifierNode - > ToString ( ) ;
mInsertStartIdx = identifierNode - > GetSrcStart ( ) ;
mInsertEndIdx = identifierNode - > GetSrcEnd ( ) ;
}
AddEntry ( AutoCompleteEntry ( " token " , " function " ) , filter ) ;
AddEntry ( AutoCompleteEntry ( " token " , " delegate " ) , filter ) ;
2022-06-01 12:32:03 -07:00
AddEntry ( AutoCompleteEntry ( " token " , " decltype " ) , filter ) ;
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
if ( mModule - > mCurTypeInstance ! = NULL )
{
if ( ! onlyAttribute )
{
auto activeTypeDef = mModule - > GetActiveTypeDef ( ) ;
for ( auto genericParam : activeTypeDef - > mGenericParamDefs )
AddEntry ( AutoCompleteEntry ( " generic " , genericParam - > mName ) , filter ) ;
}
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
AddCurrentTypes ( mModule - > mCurTypeInstance , filter , true , true , onlyAttribute ) ;
}
if ( mModule - > mCurMethodInstance ! = NULL )
{
if ( ! onlyAttribute )
{
for ( auto genericParam : mModule - > mCurMethodInstance - > mMethodDef - > mGenericParams )
AddEntry ( AutoCompleteEntry ( " generic " , genericParam - > mName ) , filter ) ;
}
}
if ( ! onlyAttribute )
{
2022-07-26 13:27:03 -04:00
BfTypeDef * showTypeDef = NULL ;
2019-08-23 11:56:54 -07:00
for ( auto & systemTypeDefEntry : mModule - > mSystem - > mSystemTypeDefs )
{
auto systemTypeDef = systemTypeDefEntry . mValue ;
if ( ( systemTypeDef - > mTypeCode = = BfTypeCode_IntUnknown ) | | ( systemTypeDef - > mTypeCode = = BfTypeCode_UIntUnknown ) )
continue ;
if ( ( AddEntry ( AutoCompleteEntry ( " valuetype " , systemTypeDef - > mName - > mString . mPtr ) , filter ) ) & & ( mIsGetDefinition ) )
2022-07-26 13:27:03 -04:00
showTypeDef = systemTypeDef ;
2019-08-23 11:56:54 -07:00
}
2021-01-28 05:11:02 -08:00
AddEntry ( AutoCompleteEntry ( " valuetype " , " SelfBase " ) , filter ) ;
AddEntry ( AutoCompleteEntry ( " valuetype " , " SelfOuter " ) , filter ) ;
2019-08-23 11:56:54 -07:00
if ( showTypeDef ! = NULL )
{
auto showType = mModule - > ResolveTypeDef ( showTypeDef ) ;
BfTypeInstance * showTypeInst = NULL ;
if ( showType - > IsPrimitiveType ( ) )
showTypeInst = mModule - > GetWrappedStructType ( showType ) ;
else
showTypeInst = showType - > ToTypeInstance ( ) ;
if ( showTypeInst ! = NULL )
SetDefinitionLocation ( showTypeInst - > mTypeDef - > mTypeDeclaration - > mNameNode ) ;
}
}
auto activeTypeDef = mModule - > GetActiveTypeDef ( ) ;
if ( activeTypeDef ! = NULL )
{
BfProject * curProject = activeTypeDef - > mProject ;
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
if ( mModule - > mCurTypeInstance ! = NULL )
{
for ( auto innerTypeDef : mModule - > mCurTypeInstance - > mTypeDef - > mNestedTypes )
{
if ( ! mModule - > mCurTypeInstance - > IsTypeMemberAccessible ( innerTypeDef , activeTypeDef ) )
continue ;
AddTypeDef ( innerTypeDef , filter , onlyAttribute ) ;
}
}
2022-07-26 13:27:03 -04:00
auto & namespaceSearch = activeTypeDef - > mNamespaceSearch ;
2019-08-23 11:56:54 -07:00
String prevName ;
for ( auto typeDef : mModule - > mSystem - > mTypeDefs )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
if ( typeDef - > mIsPartial )
continue ;
//TODO :Check protection
2022-07-26 13:27:03 -04:00
if ( ( curProject ! = NULL ) & & ( curProject - > ContainsReference ( typeDef - > mProject ) ) )
2019-08-23 11:56:54 -07:00
{
bool matches = false ;
if ( typeDef - > mOuterType = = NULL )
{
if ( ( ( typeDef - > mNamespace . IsEmpty ( ) ) | |
( namespaceSearch . Contains ( typeDef - > mNamespace ) ) ) )
matches = true ;
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
if ( matches )
{
AddTypeDef ( typeDef , filter , onlyAttribute ) ;
}
}
}
}
else
{
BfProject * curProject = NULL ;
2022-04-16 06:27:54 -07:00
if ( ! mModule - > mCompiler - > mResolvePassData - > mParsers . IsEmpty ( ) )
curProject = mModule - > mCompiler - > mResolvePassData - > mParsers [ 0 ] - > mProject ;
2019-08-23 11:56:54 -07:00
String prevName ;
for ( auto typeDef : mModule - > mSystem - > mTypeDefs )
{
if ( typeDef - > mIsPartial )
continue ;
//TODO :Check protection
if ( ( curProject ! = NULL ) & & ( curProject - > ContainsReference ( typeDef - > mProject ) ) )
{
bool matches = false ;
if ( typeDef - > mOuterType = = NULL )
{
if ( typeDef - > mNamespace . IsEmpty ( ) )
matches = true ;
}
if ( matches )
{
AddTypeDef ( typeDef , filter , onlyAttribute ) ;
}
}
}
}
}
2020-05-26 06:10:51 -07:00
void BfAutoComplete : : CheckIdentifier ( BfAstNode * identifierNode , bool isInExpression , bool isUsingDirective )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
if ( ( identifierNode ! = NULL ) & & ( ! IsAutocompleteNode ( identifierNode ) ) )
return ;
mIdentifierUsed = identifierNode ;
if ( ( mModule - > mParentNodeEntry ! = NULL ) & & ( mModule - > mCurMethodState ! = NULL ) )
{
if ( auto binExpr = BfNodeDynCast < BfBinaryOperatorExpression > ( mModule - > mParentNodeEntry - > mNode ) )
{
auto parentBlock = mModule - > mCurMethodState - > mCurScope - > mAstBlock ;
if ( ( identifierNode = = binExpr - > mRight ) & & ( binExpr - > mOp = = BfBinaryOp_Multiply ) & & ( parentBlock ! = NULL ) )
{
2022-07-26 13:27:03 -04:00
// If we are the last identifier in a block then we MAY be a partially-typed variable declaration
2019-08-23 11:56:54 -07:00
if ( parentBlock - > mChildArr . back ( ) = = binExpr )
{
mUncertain = true ;
}
}
}
}
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
if ( auto qualifiedNameNode = BfNodeDynCast < BfQualifiedNameNode > ( identifierNode ) )
{
CheckMemberReference ( qualifiedNameNode - > mLeft , qualifiedNameNode - > mDot , qualifiedNameNode - > mRight , false , NULL , isUsingDirective ) ;
return ;
}
AddTopLevelNamespaces ( identifierNode ) ;
if ( isUsingDirective )
return ; // Only do namespaces
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
AddTopLevelTypes ( identifierNode ) ;
String filter ;
if ( identifierNode ! = NULL )
{
filter = identifierNode - > ToString ( ) ;
mInsertStartIdx = identifierNode - > GetSrcStart ( ) ;
mInsertEndIdx = identifierNode - > GetSrcEnd ( ) ;
}
String addStr ;
if ( mShowAttributeProperties ! = NULL )
{
auto showAttrTypeDef = mShowAttributeProperties - > mTypeDef ;
for ( auto prop : showAttrTypeDef - > mProperties )
{
2020-10-08 09:41:05 -07:00
if ( auto entryAdded = AddEntry ( AutoCompleteEntry ( " property " , prop - > mName + " = " ) , filter ) )
2022-07-26 13:27:03 -04:00
{
2023-02-24 07:11:39 -05:00
auto propertyDeclaration = prop - > GetFieldDeclaration ( ) ;
if ( propertyDeclaration ! = NULL )
2020-10-08 09:41:05 -07:00
{
2023-02-24 07:11:39 -05:00
if ( CheckDocumentation ( entryAdded , propertyDeclaration - > mDocumentation ) )
{
}
if ( mIsGetDefinition )
SetDefinitionLocation ( propertyDeclaration - > mNameNode ) ;
2020-10-08 09:41:05 -07:00
}
2019-08-23 11:56:54 -07:00
}
}
for ( auto field : showAttrTypeDef - > mFields )
2022-07-26 13:27:03 -04:00
{
2020-10-08 09:41:05 -07:00
if ( auto entryAdded = AddEntry ( AutoCompleteEntry ( " field " , field - > mName + " = " ) , filter ) )
2022-07-26 13:27:03 -04:00
{
2023-02-24 07:11:39 -05:00
auto fieldDeclaration = field - > GetFieldDeclaration ( ) ;
if ( fieldDeclaration ! = NULL )
2020-10-08 09:41:05 -07:00
{
2023-02-24 07:11:39 -05:00
if ( CheckDocumentation ( entryAdded , fieldDeclaration - > mDocumentation ) )
{
}
if ( mIsGetDefinition )
SetDefinitionLocation ( fieldDeclaration - > mNameNode ) ;
2020-10-08 09:41:05 -07:00
}
2019-08-23 11:56:54 -07:00
}
}
}
2021-11-01 14:44:05 -07:00
if ( ( mModule - > mContext - > mCurTypeState ! = NULL ) & & ( mModule - > mContext - > mCurTypeState - > mType ! = NULL ) )
2019-08-23 11:56:54 -07:00
{
2021-11-01 14:44:05 -07:00
BF_ASSERT ( mModule - > mCurTypeInstance = = mModule - > mContext - > mCurTypeState - > mType ) ;
2019-08-23 11:56:54 -07:00
BfGlobalLookup globalLookup ;
globalLookup . mKind = BfGlobalLookup : : Kind_All ;
mModule - > PopulateGlobalContainersList ( globalLookup ) ;
for ( auto & globalContainer : mModule - > mContext - > mCurTypeState - > mGlobalContainers )
{
2021-01-20 12:43:55 -08:00
if ( globalContainer . mTypeInst ! = NULL )
AddTypeMembers ( globalContainer . mTypeInst , true , false , filter , globalContainer . mTypeInst , true , true , false ) ;
2019-08-23 11:56:54 -07:00
}
}
2022-07-26 13:27:03 -04:00
2020-06-02 05:46:56 -07:00
BfStaticSearch * staticSearch = mModule - > GetStaticSearch ( ) ;
if ( staticSearch ! = NULL )
2019-08-23 11:56:54 -07:00
{
2020-06-02 05:46:56 -07:00
for ( auto typeInst : staticSearch - > mStaticTypes )
2019-08-23 11:56:54 -07:00
{
2021-01-16 13:43:44 -08:00
AddTypeMembers ( typeInst , true , false , filter , typeInst , true , true , false ) ;
2022-06-24 06:45:35 -07:00
AddInnerTypes ( typeInst , filter , typeInst , false , false ) ;
2019-08-23 11:56:54 -07:00
}
}
2022-07-26 13:27:03 -04:00
2022-03-15 16:33:30 -07:00
if ( auto ceDbgState = mModule - > GetCeDbgState ( ) )
{
auto ceDebugger = mModule - > mCompiler - > mCeMachine - > mDebugger ;
auto ceContext = ceDebugger - > mCurDbgState - > mCeContext ;
auto activeFrame = ceDebugger - > mCurDbgState - > mActiveFrame ;
if ( activeFrame - > mFunction - > mDbgInfo ! = NULL )
{
int instIdx = activeFrame - > GetInstIdx ( ) ;
for ( auto & dbgVar : activeFrame - > mFunction - > mDbgInfo - > mVariables )
{
if ( ( instIdx > = dbgVar . mStartCodePos ) & & ( instIdx < dbgVar . mEndCodePos ) )
AddEntry ( AutoCompleteEntry ( GetTypeName ( dbgVar . mType ) , dbgVar . mName ) , filter ) ;
}
2022-07-26 13:27:03 -04:00
}
2022-03-15 16:33:30 -07:00
}
2019-08-23 11:56:54 -07:00
//////////////////////////////////////////////////////////////////////////
BfMethodInstance * curMethodInstance = mModule - > mCurMethodInstance ;
if ( mModule - > mCurMethodState ! = NULL )
curMethodInstance = mModule - > mCurMethodState - > GetRootMethodState ( ) - > mMethodInstance ;
if ( curMethodInstance ! = NULL )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
if ( ! curMethodInstance - > mMethodDef - > mIsStatic )
{
if ( mModule - > mCurTypeInstance - > IsObject ( ) )
AddEntry ( AutoCompleteEntry ( " object " , " this " ) , filter ) ;
else
AddEntry ( AutoCompleteEntry ( " pointer " , " this " ) , filter ) ;
2021-01-16 13:43:44 -08:00
AddTypeMembers ( mModule - > mCurTypeInstance , true , true , filter , mModule - > mCurTypeInstance , mModule - > mCurTypeInstance - > IsInterface ( ) , true , true ) ;
2019-08-23 11:56:54 -07:00
}
else
{
2021-01-16 13:43:44 -08:00
AddTypeMembers ( mModule - > mCurTypeInstance , true , false , filter , mModule - > mCurTypeInstance , mModule - > mCurTypeInstance - > IsInterface ( ) , true , true ) ;
2019-08-23 11:56:54 -07:00
}
if ( mModule - > mCurMethodState ! = NULL )
{
int varSkipCount = 0 ;
StringT < 128 > wantName = filter ;
while ( wantName . StartsWith ( " @ " ) )
{
varSkipCount + + ;
wantName . Remove ( 0 ) ;
}
if ( varSkipCount > 0 )
{
Dictionary < String , int > localCount ;
auto varMethodState = mModule - > mCurMethodState ;
while ( varMethodState ! = NULL )
{
for ( int localIdx = ( int ) varMethodState - > mLocals . size ( ) - 1 ; localIdx > = 0 ; localIdx - - )
{
auto local = varMethodState - > mLocals [ localIdx ] ;
int * findIdx = NULL ;
if ( localCount . TryAdd ( local - > mName , NULL , & findIdx ) )
{
* findIdx = 0 ;
}
else
{
( * findIdx ) + + ;
}
2021-11-29 08:38:42 -08:00
if ( varSkipCount - local - > mNamePrefixCount - * findIdx = = 0 )
2019-08-23 11:56:54 -07:00
{
2021-11-29 08:38:42 -08:00
if ( ( AddEntry ( AutoCompleteEntry ( GetTypeName ( local - > mResolvedType ) , local - > mName , varSkipCount - local - > mNamePrefixCount - * findIdx ) , wantName ) ) & & ( mIsGetDefinition ) )
2019-08-23 11:56:54 -07:00
{
}
}
}
varMethodState = varMethodState - > mPrevMethodState ;
if ( ( varMethodState = = NULL ) | |
( varMethodState - > mMixinState ! = NULL ) | |
( ( varMethodState - > mClosureState ! = NULL ) & & ( ! varMethodState - > mClosureState - > mCapturing ) ) )
break ;
}
mInsertStartIdx + = varSkipCount ;
}
else
{
auto varMethodState = mModule - > mCurMethodState ;
while ( varMethodState ! = NULL )
{
for ( auto & local : varMethodState - > mLocals )
{
if ( ( AddEntry ( AutoCompleteEntry ( GetTypeName ( local - > mResolvedType ) , local - > mName ) , wantName ) ) & & ( mIsGetDefinition ) )
{
}
}
varMethodState = varMethodState - > mPrevMethodState ;
if ( ( varMethodState = = NULL ) | |
( varMethodState - > mMixinState ! = NULL ) | |
( ( varMethodState - > mClosureState ! = NULL ) & & ( ! varMethodState - > mClosureState - > mCapturing ) ) )
break ;
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
}
}
}
else if ( mModule - > mCurTypeInstance ! = NULL )
{
bool staticOnly = true ;
if ( ( mModule - > mCurMethodState ! = NULL ) & & ( mModule - > mCurMethodState - > mTempKind = = BfMethodState : : TempKind_NonStatic ) )
staticOnly = false ;
//BF_ASSERT(mModule->mCurTypeInstance->mResolvingConstField);
2021-01-16 13:43:44 -08:00
AddTypeMembers ( mModule - > mCurTypeInstance , true , ! staticOnly , filter , mModule - > mCurTypeInstance , false , true , true ) ;
2019-08-23 11:56:54 -07:00
}
auto checkMethodState = mModule - > mCurMethodState ;
while ( checkMethodState ! = NULL )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
for ( auto localMethod : checkMethodState - > mLocalMethods )
2022-07-26 13:27:03 -04:00
{
2020-10-08 11:47:38 -07:00
if ( localMethod - > mMethodInstanceGroup ! = NULL )
AddMethod ( mModule - > mCurTypeInstance , localMethod - > mMethodDef , localMethod - > mMethodInstanceGroup - > mDefault , localMethod - > mMethodDeclaration , localMethod - > mMethodName , filter ) ;
2019-08-23 11:56:54 -07:00
}
checkMethodState = checkMethodState - > mPrevMethodState ;
}
if ( isInExpression )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
const char * tokens [ ] =
{
2022-06-27 10:55:31 -07:00
" alignof " , " append " , " as " , " asm " , " base " , " break " , " case " , " catch " , " checked " , " continue " , " const " , " default " , " defer " ,
2022-07-26 13:27:03 -04:00
" delegate " , " delete " , " do " , " else " , " false " , " finally " ,
2022-05-30 11:40:49 -07:00
" fixed " , " for " , " function " , " if " , " implicit " , " in " , " internal " , " is " , " isconst " , " new " , " mixin " , " null " ,
2022-06-06 13:03:54 -07:00
" offsetof " , " out " , " params " , " readonly " , " ref " , " rettype " , " return " ,
2020-05-08 14:33:28 -07:00
" sealed " , " sizeof " , " scope " , " static " , " strideof " , " struct " , " switch " , /*"this",*/ " try " , " true " , " typeof " , " unchecked " ,
2019-08-23 11:56:54 -07:00
" using " , " var " , " virtual " , " volatile " , " where " , " while " ,
2021-05-27 12:38:35 +02:00
" alloctype " , " comptype " , " decltype " , " nullable " ,
2022-07-26 13:27:03 -04:00
} ;
2019-08-23 11:56:54 -07:00
for ( int i = 0 ; i < sizeof ( tokens ) / sizeof ( char * ) ; i + + )
AddEntry ( AutoCompleteEntry ( " token " , tokens [ i ] ) , filter ) ;
if ( ( mModule - > mCurMethodState ! = NULL ) & & ( mModule - > mCurMethodState - > mBreakData ! = NULL ) & & ( mModule - > mCurMethodState - > mBreakData - > mIRFallthroughBlock ) )
{
AddEntry ( AutoCompleteEntry ( " token " , " fallthrough " ) , filter ) ;
}
}
else
{
const char * tokens [ ] =
{
2022-07-26 13:27:03 -04:00
" abstract " , " append " , " base " , " class " , " const " ,
2019-08-23 11:56:54 -07:00
" delegate " , " extern " , " enum " , " explicit " , " extension " , " function " ,
2021-12-17 18:05:39 +01:00
" interface " , " in " , " implicit " , " internal " , " mixin " , " namespace " , " new " ,
2019-08-23 11:56:54 -07:00
" operator " , " out " , " override " , " params " , " private " , " protected " , " public " , " readonly " , " ref " , " rettype " , " return " ,
2019-10-09 16:16:01 -07:00
" scope " , " sealed " , " static " , " struct " , " this " , " typealias " ,
2019-08-23 11:56:54 -07:00
" using " , " virtual " , " volatile " , " T " , " where "
} ;
for ( int i = 0 ; i < sizeof ( tokens ) / sizeof ( char * ) ; i + + )
AddEntry ( AutoCompleteEntry ( " token " , tokens [ i ] ) , filter ) ;
}
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
//if ((identifierNode != NULL) && ((mModule->mCurMethodInstance == NULL) || (BfNodeDynCast<BfExpression>(identifierNode->mParent) != NULL)))
/*if ((identifierNode != NULL) && ((mModule->mCurMethodInstance == NULL) || (isInExpression)))
{
AddEntry ( AutoCompleteEntry ( " token " , " #if " ) , filter ) ;
AddEntry ( AutoCompleteEntry ( " token " , " #elif " ) , filter ) ;
AddEntry ( AutoCompleteEntry ( " token " , " #endif " ) , filter ) ;
2022-07-26 13:27:03 -04:00
} */
2019-08-23 11:56:54 -07:00
//OutputDebugStrF("Autocomplete: %s\n", str.c_str());
}
String BfAutoComplete : : GetFilter ( BfAstNode * node )
{
String filter = node - > ToString ( ) ;
if ( mIsGetDefinition )
{
mInsertEndIdx = node - > GetSrcEnd ( ) ;
}
else
{
// Only use member name up to cursor
auto bfParser = node - > GetSourceData ( ) - > ToParser ( ) ;
int cursorIdx = bfParser - > mCursorIdx ;
2020-05-31 07:27:08 -07:00
filter = filter . Substring ( 0 , BF_CLAMP ( cursorIdx - node - > GetSrcStart ( ) , 0 , ( int ) filter . length ( ) ) ) ;
2022-07-26 13:27:03 -04:00
mInsertEndIdx = cursorIdx ;
2019-08-23 11:56:54 -07:00
}
2021-11-29 08:38:42 -08:00
const char * cPtr = filter . c_str ( ) ;
while ( cPtr [ 0 ] = = ' @ ' )
{
mInsertStartIdx + + ;
2022-07-26 13:27:03 -04:00
cPtr + + ;
2021-11-29 08:38:42 -08:00
}
2019-08-23 11:56:54 -07:00
return filter ;
}
bool BfAutoComplete : : CheckMemberReference ( BfAstNode * target , BfAstNode * dotToken , BfAstNode * memberName , bool onlyShowTypes , BfType * expectingType , bool isUsingDirective , bool onlyAttribute )
{
2022-04-16 06:27:54 -07:00
if ( ! WantsEntries ( ) )
return false ;
2019-08-23 11:56:54 -07:00
BfAttributedIdentifierNode * attrIdentifier = NULL ;
bool isAutocompletingName = false ;
2019-10-14 14:08:29 -07:00
if ( ( attrIdentifier = BfNodeDynCast < BfAttributedIdentifierNode > ( memberName ) ) )
2019-08-23 11:56:54 -07:00
{
memberName = attrIdentifier - > mIdentifier ;
2019-12-01 14:40:17 -08:00
if ( IsAutocompleteNode ( attrIdentifier - > mAttributes ) )
2019-08-23 11:56:54 -07:00
{
2022-07-26 13:27:03 -04:00
auto bfParser = attrIdentifier - > mAttributes - > GetSourceData ( ) - > ToParser ( ) ;
2019-08-23 11:56:54 -07:00
int cursorIdx = bfParser - > mCursorIdx ;
2019-12-01 14:40:17 -08:00
if ( cursorIdx = = attrIdentifier - > mAttributes - > GetSrcEnd ( ) )
isAutocompletingName = true ;
else
return false ;
2019-08-23 11:56:54 -07:00
}
}
if ( memberName ! = NULL )
2019-09-04 04:44:00 -07:00
isAutocompletingName = IsAutocompleteNode ( dotToken , memberName , 0 , 1 ) ;
2019-08-23 11:56:54 -07:00
if ( ( IsAutocompleteNode ( dotToken , 0 , 1 ) ) | | ( isAutocompletingName ) )
{
BfLogSys ( mModule - > mSystem , " Triggered autocomplete \n " ) ;
bool isFriend = false ;
2022-07-26 13:27:03 -04:00
mInsertStartIdx = dotToken - > GetSrcEnd ( ) ;
2019-08-23 11:56:54 -07:00
if ( attrIdentifier ! = NULL )
{
BfAttributeState attributeState ;
2021-10-30 08:10:52 -07:00
attributeState . mTarget = ( BfAttributeTargets ) ( BfAttributeTargets_MemberAccess | BfAttributeTargets_Invocation ) ;
2019-08-23 11:56:54 -07:00
attributeState . mCustomAttributes = mModule - > GetCustomAttributes ( attrIdentifier - > mAttributes , attributeState . mTarget ) ;
2020-08-16 08:33:51 -07:00
if ( ( attributeState . mCustomAttributes ! = NULL ) & & ( attributeState . mCustomAttributes - > Contains ( mModule - > mCompiler - > mFriendAttributeTypeDef ) ) )
{
isFriend = true ;
attributeState . mUsed = true ;
}
2019-08-23 11:56:54 -07:00
mInsertStartIdx = attrIdentifier - > mAttributes - > GetSrcEnd ( ) ;
}
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
if ( memberName ! = NULL )
{
//Member name MAY be incorrectly identified in cases like:
// val._
// OtherCall();
int cursorIdx = GetCursorIdx ( memberName ) ;
if ( ( cursorIdx ! = - 1 ) & & ( cursorIdx > = memberName - > GetSrcStart ( ) ) )
mInsertStartIdx = memberName - > GetSrcStart ( ) ;
}
SetAndRestoreValue < bool > prevFriendSet ( mHasFriendSet , mHasFriendSet | | isFriend ) ;
String filter ;
if ( ( memberName ! = NULL ) & & ( IsAutocompleteNode ( memberName ) ) )
{
filter = GetFilter ( memberName ) ;
}
else if ( mResolveType ! = BfResolveType_Autocomplete )
2022-07-26 13:27:03 -04:00
mInsertStartIdx = - 1 ; // Require a full span for everything but autocomplete
2019-08-23 11:56:54 -07:00
SetAndRestoreValue < bool > prevIgnoreErrors ( mModule - > mIgnoreErrors , true ) ;
bool isStatic = false ;
BfTypedValue targetValue = LookupTypeRefOrIdentifier ( target , & isStatic , ( BfEvalExprFlags ) ( BfEvalExprFlags_IgnoreNullConditional | BfEvalExprFlags_NoCast ) , expectingType ) ;
2022-06-22 08:35:25 -07:00
if ( ( targetValue ) & & ( dotToken - > mToken = = BfToken_Arrow ) )
{
SetAndRestoreValue < bool > prevIgnoreClassifying ( mModule - > mIsInsideAutoComplete , true ) ;
BfExprEvaluator exprEvaluator ( mModule ) ;
auto arrowValue = exprEvaluator . PerformUnaryOperation_TryOperator ( targetValue , NULL , BfUnaryOp_Arrow , BfNodeDynCast < BfTokenNode > ( dotToken ) , BfUnaryOpFlag_None ) ;
2022-07-26 13:27:03 -04:00
if ( arrowValue )
2022-06-22 08:35:25 -07:00
targetValue = arrowValue ;
}
2019-08-23 11:56:54 -07:00
bool hadResults = false ;
bool doAsNamespace = true ;
if ( ( targetValue . mType ) & & ( ! isUsingDirective ) )
{
doAsNamespace = false ;
if ( auto dotTokenNode = BfNodeDynCast < BfTokenNode > ( dotToken ) )
{
if ( dotTokenNode - > GetToken ( ) = = BfToken_QuestionDot )
{
2020-04-27 15:09:10 -07:00
if ( ! targetValue . mType - > IsNullable ( ) )
{
// We need this for Result<T>
SetAndRestoreValue < bool > prevIgnore ( mModule - > mBfIRBuilder - > mIgnoreWrites , true ) ;
BfExprEvaluator exprEvaluator ( mModule ) ;
2020-09-18 17:00:33 -07:00
auto opResult = exprEvaluator . PerformUnaryOperation_TryOperator ( targetValue , NULL , BfUnaryOp_NullConditional , dotTokenNode , BfUnaryOpFlag_None ) ;
2020-04-27 15:09:10 -07:00
if ( opResult )
targetValue = opResult ;
}
2019-08-23 11:56:54 -07:00
// ?. should look inside nullable types
if ( targetValue . mType - > IsNullable ( ) )
{
2020-06-05 07:01:58 -07:00
BfTypeInstance * nullableType = ( BfTypeInstance * ) targetValue . mType - > ToTypeInstance ( ) ;
2019-08-23 11:56:54 -07:00
targetValue = mModule - > MakeAddressable ( targetValue ) ;
BfIRValue valuePtr = mModule - > mBfIRBuilder - > CreateInBoundsGEP ( targetValue . mValue , 0 , 1 ) ; // mValue
2020-06-05 07:01:58 -07:00
targetValue = BfTypedValue ( valuePtr , nullableType - > mGenericTypeInfo - > mTypeGenericArguments [ 0 ] , true ) ;
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
}
}
// Statics, inner types
2022-07-26 13:27:03 -04:00
auto checkType = targetValue . mType ;
2021-01-15 14:28:21 -08:00
if ( checkType - > IsConcreteInterfaceType ( ) )
checkType = checkType - > GetUnderlyingType ( ) ;
2020-08-12 15:07:56 -07:00
2019-08-23 11:56:54 -07:00
if ( checkType - > IsGenericParam ( ) )
{
auto genericParamType = ( BfGenericParamType * ) checkType ;
2019-11-17 09:28:39 -08:00
auto genericParamInstance = mModule - > GetGenericParamInstance ( genericParamType ) ;
2022-07-26 13:27:03 -04:00
2019-11-17 09:28:39 -08:00
auto _HandleGenericParamInstance = [ & ] ( BfGenericParamInstance * genericParamInstance )
{
2020-05-27 09:46:09 -07:00
bool showStatics = ! targetValue . mValue ;
2019-11-17 09:28:39 -08:00
for ( auto interfaceConstraint : genericParamInstance - > mInterfaceConstraints )
2021-01-16 13:43:44 -08:00
AddTypeMembers ( interfaceConstraint , showStatics , ! showStatics , filter , interfaceConstraint , true , false , false ) ;
2019-11-17 09:28:39 -08:00
if ( genericParamInstance - > mTypeConstraint ! = NULL )
checkType = genericParamInstance - > mTypeConstraint ;
else
checkType = mModule - > mContext - > mBfObjectType ;
2022-01-03 07:30:03 -05:00
if ( ( genericParamInstance - > IsEnum ( ) ) )
{
if ( isStatic )
AddEntry ( AutoCompleteEntry ( " valuetype " , " UnderlyingType " ) , filter ) ;
else
{
AddEntry ( AutoCompleteEntry ( " value " , " Underlying " ) , filter ) ;
AddEntry ( AutoCompleteEntry ( " value " , " UnderlyingRef " ) , filter ) ;
}
}
2019-11-17 09:28:39 -08:00
} ;
_HandleGenericParamInstance ( genericParamInstance ) ;
// Check method generic constraints
if ( ( mModule - > mCurMethodInstance ! = NULL ) & & ( mModule - > mCurMethodInstance - > mIsUnspecialized ) & & ( mModule - > mCurMethodInstance - > mMethodInfoEx ! = NULL ) )
{
for ( int genericParamIdx = ( int ) mModule - > mCurMethodInstance - > mMethodInfoEx - > mMethodGenericArguments . size ( ) ;
genericParamIdx < mModule - > mCurMethodInstance - > mMethodInfoEx - > mGenericParams . size ( ) ; genericParamIdx + + )
{
auto genericParam = mModule - > mCurMethodInstance - > mMethodInfoEx - > mGenericParams [ genericParamIdx ] ;
if ( genericParam - > mExternType = = genericParamType )
_HandleGenericParamInstance ( genericParam ) ;
}
}
2019-08-23 11:56:54 -07:00
}
if ( checkType - > IsPointer ( ) )
2022-01-04 07:17:32 -05:00
{
auto underlyingType = checkType - > GetUnderlyingType ( ) ;
if ( ( underlyingType ! = NULL ) & & ( underlyingType - > IsValueType ( ) ) )
checkType = underlyingType ;
}
2019-08-23 11:56:54 -07:00
auto typeInst = checkType - > ToTypeInstance ( ) ;
2022-07-26 13:27:03 -04:00
if ( ( typeInst = = NULL ) & &
2019-08-23 11:56:54 -07:00
( ( checkType - > IsPrimitiveType ( ) ) | | ( checkType - > IsSizedArray ( ) ) ) )
typeInst = mModule - > GetWrappedStructType ( checkType ) ;
if ( typeInst ! = NULL )
{
if ( typeInst - > mTypeDef - > IsGlobalsContainer ( ) )
doAsNamespace = true ; // Also list the types in this namespace
bool allowPrivate = ( mModule - > mCurTypeInstance = = typeInst ) | | ( mModule - > IsInnerType ( mModule - > mCurTypeInstance , typeInst ) ) ;
bool allowProtected = allowPrivate ;
if ( isStatic )
2022-06-24 06:45:35 -07:00
AddInnerTypes ( typeInst , filter , typeInst , allowProtected , allowPrivate ) ;
2019-08-23 11:56:54 -07:00
if ( ! onlyShowTypes )
2020-06-03 05:22:11 -07:00
{
2021-01-16 13:43:44 -08:00
AddTypeMembers ( typeInst , isStatic , ! isStatic , filter , typeInst , false , false , false ) ;
2019-08-23 11:56:54 -07:00
2020-06-03 05:22:11 -07:00
if ( ! isStatic )
2022-07-26 13:27:03 -04:00
{
2020-06-03 05:22:11 -07:00
auto checkTypeInst = mModule - > mCurTypeInstance ;
while ( checkTypeInst ! = NULL )
{
2021-01-20 12:43:55 -08:00
AddExtensionMethods ( typeInst , checkTypeInst , filter , true , true ) ;
2020-06-03 05:22:11 -07:00
checkTypeInst = mModule - > GetOuterType ( checkTypeInst ) ;
}
2021-11-01 14:44:05 -07:00
if ( ( mModule - > mContext - > mCurTypeState ! = NULL ) & & ( mModule - > mContext - > mCurTypeState - > mType ! = NULL ) )
2020-06-03 05:22:11 -07:00
{
2021-11-01 14:44:05 -07:00
BF_ASSERT ( mModule - > mCurTypeInstance = = mModule - > mContext - > mCurTypeState - > mType ) ;
2020-06-03 05:22:11 -07:00
BfGlobalLookup globalLookup ;
globalLookup . mKind = BfGlobalLookup : : Kind_All ;
mModule - > PopulateGlobalContainersList ( globalLookup ) ;
2021-01-20 12:43:55 -08:00
for ( auto & globalContainer : mModule - > mContext - > mCurTypeState - > mGlobalContainers )
if ( globalContainer . mTypeInst ! = NULL )
AddExtensionMethods ( typeInst , globalContainer . mTypeInst , filter , false , false ) ;
2020-06-03 05:22:11 -07:00
}
BfStaticSearch * staticSearch = mModule - > GetStaticSearch ( ) ;
if ( staticSearch ! = NULL )
{
for ( auto staticTypeInst : staticSearch - > mStaticTypes )
AddExtensionMethods ( typeInst , staticTypeInst , filter , false , false ) ;
}
}
}
2019-08-23 11:56:54 -07:00
if ( typeInst - > IsInterface ( ) )
{
2021-01-16 13:43:44 -08:00
AddTypeMembers ( mModule - > mContext - > mBfObjectType , isStatic , ! isStatic , filter , mModule - > mContext - > mBfObjectType , true , false , false ) ;
2019-08-23 11:56:54 -07:00
}
}
hadResults = true ;
}
if ( doAsNamespace ) // Lookup namespaces
{
String targetStr = target - > ToString ( ) ;
BfAtomComposite targetComposite ;
bool isValid = mSystem - > ParseAtomComposite ( targetStr , targetComposite ) ;
2022-01-01 10:12:20 -05:00
BfProject * bfProject = GetActiveProject ( ) ;
2019-08-23 11:56:54 -07:00
auto _CheckProject = [ & ] ( BfProject * project )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
if ( ( isValid ) & & ( project - > mNamespaces . ContainsKey ( targetComposite ) ) )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
for ( auto namespacePair : project - > mNamespaces )
{
const BfAtomComposite & namespaceComposite = namespacePair . mKey ;
if ( ( namespaceComposite . StartsWith ( targetComposite ) ) & & ( namespaceComposite . GetPartsCount ( ) > targetComposite . GetPartsCount ( ) ) )
{
BfAtom * subNamespace = namespaceComposite . mParts [ targetComposite . mSize ] ;
AutoCompleteEntry entry ( " namespace " , subNamespace - > mString . mPtr ) ;
AddEntry ( entry , filter ) ;
}
}
if ( ! isUsingDirective )
2022-07-26 13:27:03 -04:00
{
2022-01-01 10:12:20 -05:00
BfProject * activeProject = GetActiveProject ( ) ;
2019-08-23 11:56:54 -07:00
for ( auto typeDef : mSystem - > mTypeDefs )
{
if ( ( typeDef - > mNamespace = = targetComposite ) & & ( typeDef - > mOuterType = = NULL ) & &
( ! typeDef - > mIsPartial ) & &
2022-01-01 10:12:20 -05:00
( ( activeProject = = NULL ) | | ( activeProject - > ContainsReference ( typeDef - > mProject ) ) ) )
2019-08-23 11:56:54 -07:00
{
2023-11-18 08:54:28 -05:00
if ( typeDef - > IsGlobalsContainer ( ) )
{
auto type = mModule - > ResolveTypeDef ( typeDef , BfPopulateType_Declaration ) ;
if ( type ! = NULL )
{
auto typeInst = type - > ToTypeInstance ( ) ;
if ( typeInst ! = NULL )
AddTypeMembers ( typeInst , true , false , filter , typeInst , false , false , false ) ;
}
}
else
AddTypeDef ( typeDef , filter , onlyAttribute ) ;
2019-08-23 11:56:54 -07:00
}
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
}
hadResults = true ;
}
} ;
if ( bfProject ! = NULL )
{
for ( int depIdx = - 1 ; depIdx < ( int ) bfProject - > mDependencies . size ( ) ; depIdx + + )
{
BfProject * depProject = ( depIdx = = - 1 ) ? bfProject : bfProject - > mDependencies [ depIdx ] ;
_CheckProject ( depProject ) ;
}
}
else
{
for ( auto project : mSystem - > mProjects )
_CheckProject ( project ) ;
}
}
return hadResults ;
}
else
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
auto identifierNode = BfNodeDynCast < BfIdentifierNode > ( target ) ;
if ( identifierNode ! = NULL )
CheckIdentifier ( identifierNode ) ;
CheckTypeRef ( BfNodeDynCast < BfTypeReference > ( target ) , true , false , onlyAttribute ) ;
}
return false ;
}
2019-12-13 14:24:00 -08:00
bool BfAutoComplete : : CheckExplicitInterface ( BfTypeInstance * interfaceType , BfAstNode * dotToken , BfAstNode * memberName )
{
bool isAutocompletingName = false ;
if ( memberName ! = NULL )
isAutocompletingName = IsAutocompleteNode ( dotToken , memberName , 0 , 1 ) ;
if ( isAutocompletingName )
{
//
}
else if ( IsAutocompleteNode ( dotToken , 0 , 1 ) )
{
mInsertStartIdx = dotToken - > GetSrcEnd ( ) ;
mInsertEndIdx = mInsertStartIdx ;
}
else
return false ;
2022-07-26 13:27:03 -04:00
2021-10-01 06:57:10 -07:00
mModule - > PopulateType ( interfaceType , BfPopulateType_DataAndMethods ) ;
2019-12-13 14:24:00 -08:00
String filter ;
if ( isAutocompletingName )
filter = GetFilter ( memberName ) ;
auto activeTypeDef = mModule - > GetActiveTypeDef ( ) ;
2022-06-24 06:45:35 -07:00
BfShow checkShow = BfShow_Hide ;
2019-12-13 14:24:00 -08:00
for ( auto methodDef : interfaceType - > mTypeDef - > mMethods )
{
if ( methodDef - > mIsOverride )
continue ;
2022-06-24 06:45:35 -07:00
if ( methodDef - > mShow > = checkShow )
2019-12-13 14:24:00 -08:00
continue ;
if ( methodDef - > mName . IsEmpty ( ) )
continue ;
if ( methodDef - > mExplicitInterface ! = NULL )
continue ;
if ( ( ! interfaceType - > IsTypeMemberIncluded ( methodDef - > mDeclaringType , activeTypeDef , mModule ) ) | |
( ! interfaceType - > IsTypeMemberAccessible ( methodDef - > mDeclaringType , activeTypeDef ) ) )
continue ;
if ( methodDef - > mIsStatic )
continue ;
bool canUseMethod ;
2022-07-26 13:27:03 -04:00
canUseMethod = ( methodDef - > mMethodType = = BfMethodType_Normal ) ;
2019-12-13 14:24:00 -08:00
if ( canUseMethod )
{
2020-10-08 09:41:05 -07:00
AddMethod ( interfaceType , methodDef , NULL , methodDef - > GetMethodDeclaration ( ) , methodDef - > mName , filter ) ;
2019-12-13 14:24:00 -08:00
}
}
return false ;
}
2019-08-23 11:56:54 -07:00
void BfAutoComplete : : CheckTypeRef ( BfTypeReference * typeRef , bool mayBeIdentifier , bool isInExpression , bool onlyAttribute )
{
if ( ( typeRef = = NULL ) | | ( typeRef - > IsTemporary ( ) ) | | ( ! IsAutocompleteNode ( typeRef ) ) )
return ;
if ( auto genericTypeRef = BfNodeDynCast < BfGenericInstanceTypeRef > ( typeRef ) )
{
CheckTypeRef ( genericTypeRef - > mElementType , mayBeIdentifier , isInExpression , onlyAttribute ) ;
for ( auto genericArg : genericTypeRef - > mGenericArguments )
2022-02-05 09:23:44 -05:00
CheckNode ( genericArg , false , isInExpression ) ;
2019-08-23 11:56:54 -07:00
return ;
}
if ( ! onlyAttribute )
{
if ( auto tupleTypeRef = BfNodeDynCast < BfTupleTypeRef > ( typeRef ) )
{
for ( auto fieldTypeRef : tupleTypeRef - > mFieldTypes )
CheckTypeRef ( fieldTypeRef , false , isInExpression , false ) ;
return ;
}
if ( auto delegateTypeRef = BfNodeDynCast < BfDelegateTypeRef > ( typeRef ) )
{
CheckTypeRef ( delegateTypeRef - > mReturnType , false , isInExpression ) ;
for ( auto param : delegateTypeRef - > mParams )
{
auto attributes = param - > mAttributes ;
while ( attributes ! = NULL )
{
if ( attributes - > mAttributeTypeRef ! = NULL )
{
CheckAttributeTypeRef ( attributes - > mAttributeTypeRef ) ;
}
attributes = attributes - > mNextAttribute ;
}
CheckTypeRef ( param - > mTypeRef , false , isInExpression ) ;
}
return ;
}
if ( auto elementedTypeRef = BfNodeDynCast < BfElementedTypeRef > ( typeRef ) )
{
// "May be identifier" where pointer types could actually end up be multiplies, etc.
CheckTypeRef ( elementedTypeRef - > mElementType , true , isInExpression ) ;
return ;
}
}
2022-02-02 09:24:02 -05:00
if ( ( mayBeIdentifier ) & & ( mResolveType ! = BfResolveType_GoToDefinition ) )
2019-08-23 11:56:54 -07:00
{
if ( auto namedTypeRef = BfNodeDynCast < BfNamedTypeReference > ( typeRef ) )
{
CheckIdentifier ( namedTypeRef - > mNameNode , isInExpression ) ;
return ;
}
2020-08-25 14:53:08 -07:00
else if ( auto varTypeRef = BfNodeDynCast < BfVarTypeReference > ( typeRef ) )
{
CheckIdentifier ( varTypeRef - > mVarToken , isInExpression ) ;
return ;
}
else if ( auto varTypeRef = BfNodeDynCast < BfLetTypeReference > ( typeRef ) )
{
CheckIdentifier ( varTypeRef - > mLetToken , isInExpression ) ;
return ;
}
2019-08-23 11:56:54 -07:00
}
if ( auto qualifiedTypeRef = BfNodeDynCast < BfQualifiedTypeReference > ( typeRef ) )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
// Only consider the left side as an identifier if there's space after the dot. Consider this:
// mVal.
// Type a = null;
// vs
// mVal.Type a = null;
2022-07-26 13:27:03 -04:00
// The first one is clearly a member reference being typed out even though it looks the same
2019-08-23 11:56:54 -07:00
// to the parser except for the spacing
if ( ( qualifiedTypeRef - > mRight = = NULL ) | | ( qualifiedTypeRef - > mDot - > GetSrcEnd ( ) < qualifiedTypeRef - > mRight - > GetSrcStart ( ) ) )
{
BfAutoParentNodeEntry autoParentNodeEntry ( mModule , qualifiedTypeRef ) ;
//CheckMemberReference(qualifiedTypeRef->mLeft, qualifiedTypeRef->mDot, NULL, !mayBeIdentifier, NULL, false, onlyAttribute);
CheckMemberReference ( qualifiedTypeRef - > mLeft , qualifiedTypeRef - > mDot , qualifiedTypeRef - > mRight , ! mayBeIdentifier , NULL , false , onlyAttribute ) ;
}
else if ( auto rightNamedTypeRef = BfNodeDynCast < BfNamedTypeReference > ( qualifiedTypeRef - > mRight ) )
{
BfAutoParentNodeEntry autoParentNodeEntry ( mModule , qualifiedTypeRef ) ;
if ( CheckMemberReference ( qualifiedTypeRef - > mLeft , qualifiedTypeRef - > mDot , rightNamedTypeRef - > mNameNode , false , NULL , false , onlyAttribute ) )
return ;
}
}
if ( auto namedTypeRef = BfNodeDynCast < BfNamedTypeReference > ( typeRef ) )
{
AddTopLevelNamespaces ( namedTypeRef - > mNameNode ) ;
AddTopLevelTypes ( namedTypeRef - > mNameNode , onlyAttribute ) ;
}
}
void BfAutoComplete : : CheckAttributeTypeRef ( BfTypeReference * typeRef )
{
if ( ! IsAutocompleteNode ( typeRef ) )
return ;
CheckTypeRef ( typeRef , false , false , true ) ;
}
void BfAutoComplete : : CheckInvocation ( BfAstNode * invocationNode , BfTokenNode * openParen , BfTokenNode * closeParen , const BfSizedArray < ASTREF ( BfTokenNode * ) > & commas )
{
if ( ! mIsAutoComplete )
return ;
bool wasCapturingMethodMatchInfo = mIsCapturingMethodMatchInfo ;
mIsCapturingMethodMatchInfo = false ;
int lenAdd = 0 ;
if ( closeParen = = NULL )
{
// Unterminated invocation expression - allow for space after last comma in param list
lenAdd = 1 ;
}
else
{
// Ignore close paren
2022-07-26 13:27:03 -04:00
lenAdd = - 1 ;
2019-08-23 11:56:54 -07:00
}
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
if ( ! IsAutocompleteNode ( invocationNode , lenAdd ) )
2022-07-26 13:27:03 -04:00
return ;
2019-08-23 11:56:54 -07:00
if ( openParen = = NULL )
{
mModule - > AssertErrorState ( ) ;
return ;
}
auto bfParser = invocationNode - > GetSourceData ( ) - > ToParser ( ) ;
if ( bfParser = = NULL )
return ;
int cursorIdx = bfParser - > mCursorIdx ;
BfAstNode * target = invocationNode ;
if ( auto invocationExpr = BfNodeDynCast < BfInvocationExpression > ( invocationNode ) )
{
target = invocationExpr - > mTarget ;
if ( auto memberTarget = BfNodeDynCast < BfMemberReferenceExpression > ( target ) )
{
if ( memberTarget - > mMemberName ! = NULL )
target = memberTarget - > mMemberName ;
}
else if ( auto qualifiedTypeRef = BfNodeDynCast < BfQualifiedTypeReference > ( target ) )
2020-02-18 08:43:29 -08:00
{
if ( qualifiedTypeRef - > mRight ! = NULL )
target = qualifiedTypeRef - > mRight ;
}
2019-08-23 11:56:54 -07:00
else if ( auto qualifiedNameNode = BfNodeDynCast < BfQualifiedNameNode > ( target ) )
2020-02-18 08:43:29 -08:00
{
if ( qualifiedNameNode - > mRight ! = NULL )
target = qualifiedNameNode - > mRight ;
}
2019-09-04 04:44:00 -07:00
if ( auto attributedMember = BfNodeDynCast < BfAttributedIdentifierNode > ( target ) )
2020-02-18 08:43:29 -08:00
if ( attributedMember - > mIdentifier ! = NULL )
target = attributedMember - > mIdentifier ;
2019-08-23 11:56:54 -07:00
}
bool doCapture = ( bfParser - > mCursorIdx > = openParen - > GetSrcStart ( ) ) ;
if ( mIsGetDefinition )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
doCapture | = ( target ! = NULL ) & & ( bfParser - > mCursorIdx > = target - > GetSrcStart ( ) ) ;
}
if ( doCapture )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
mIsCapturingMethodMatchInfo = true ;
2022-07-26 13:27:03 -04:00
2019-11-02 06:04:26 -07:00
delete mMethodMatchInfo ;
mMethodMatchInfo = new MethodMatchInfo ( ) ;
2019-08-23 11:56:54 -07:00
mMethodMatchInfo - > mInvocationSrcIdx = target - > GetSrcStart ( ) ;
mMethodMatchInfo - > mCurMethodInstance = mModule - > mCurMethodInstance ;
mMethodMatchInfo - > mCurTypeInstance = mModule - > mCurTypeInstance ;
mMethodMatchInfo - > mSrcPositions . Clear ( ) ;
mMethodMatchInfo - > mSrcPositions . push_back ( openParen - > GetSrcStart ( ) ) ;
for ( auto comma : commas )
mMethodMatchInfo - > mSrcPositions . push_back ( comma - > GetSrcStart ( ) ) ;
mMethodMatchInfo - > mSrcPositions . push_back ( invocationNode - > GetSrcEnd ( ) + lenAdd ) ;
}
}
2022-02-05 09:23:44 -05:00
void BfAutoComplete : : CheckNode ( BfAstNode * node , bool mayBeIdentifier , bool isInExpression )
2019-08-23 11:56:54 -07:00
{
if ( ! IsAutocompleteNode ( node ) )
return ;
if ( auto identifer = BfNodeDynCast < BfIdentifierNode > ( node ) )
CheckIdentifier ( identifer ) ;
if ( auto typeRef = BfNodeDynCast < BfTypeReference > ( node ) )
2022-02-05 09:23:44 -05:00
CheckTypeRef ( typeRef , mayBeIdentifier , isInExpression ) ;
2019-08-23 11:56:54 -07:00
if ( auto memberRef = BfNodeDynCast < BfMemberReferenceExpression > ( node ) )
{
if ( memberRef - > mTarget ! = NULL )
CheckMemberReference ( memberRef - > mTarget , memberRef - > mDotToken , memberRef - > mMemberName ) ;
}
}
2020-02-07 08:44:06 -08:00
bool BfAutoComplete : : GetMethodInfo ( BfMethodInstance * methodInst , StringImpl * showString , StringImpl * insertString , bool isImplementing , bool isExplicitInterface )
2020-02-05 17:07:23 -08:00
{
2020-05-27 09:46:09 -07:00
SetAndRestoreValue < BfMethodInstance * > prevMethodInstance ( mModule - > mCurMethodInstance , methodInst ) ;
2020-02-05 17:07:23 -08:00
auto methodDef = methodInst - > mMethodDef ;
bool isInterface = methodInst - > GetOwner ( ) - > IsInterface ( ) ;
2020-05-27 09:46:09 -07:00
BfTypeNameFlags nameFlags = ( BfTypeNameFlags ) ( BfTypeNameFlag_ReduceName | BfTypeNameFlag_ResolveGenericParamNames ) ;
2024-12-31 10:03:16 -08:00
if ( ( methodDef - > mMethodType = = BfMethodType_Normal ) | | ( methodDef - > mMethodType = = BfMethodType_Ctor ) )
2020-02-05 17:07:23 -08:00
{
StringT < 128 > methodPrefix ;
StringT < 128 > methodName ;
2022-07-26 13:27:03 -04:00
StringT < 256 > impString ;
2020-05-27 09:46:09 -07:00
2020-10-26 10:46:35 -07:00
bool isAbstract = ( methodDef - > mIsAbstract ) | | ( isInterface ) | | ( ! methodDef - > mIsVirtual ) ;
2020-02-05 17:07:23 -08:00
2024-12-31 10:03:16 -08:00
if ( methodDef - > mMethodType = = BfMethodType_Ctor )
{
impString + = " : base( " ;
isAbstract = false ;
}
else if ( isAbstract )
2020-02-05 17:07:23 -08:00
{
2020-02-07 08:44:06 -08:00
if ( ! methodInst - > mReturnType - > IsVoid ( ) )
impString + = " return default; " ;
}
else if ( ! isAbstract )
2022-07-26 13:27:03 -04:00
{
2020-02-07 08:44:06 -08:00
if ( ! methodInst - > mReturnType - > IsVoid ( ) )
impString = " return " ;
2020-02-05 17:07:23 -08:00
2020-02-07 08:44:06 -08:00
impString + = " base. " ;
impString + = methodDef - > mName ;
2022-07-26 13:27:03 -04:00
impString + = " ( " ;
2020-02-05 17:07:23 -08:00
}
auto methodDeclaration = methodDef - > GetMethodDeclaration ( ) ;
2024-12-31 11:46:51 -08:00
if ( methodDef - > mHasAppend )
methodPrefix + = " [AllowAppend] \r " ;
2020-02-05 17:07:23 -08:00
if ( isInterface )
2022-07-26 13:27:03 -04:00
{
2020-02-05 17:07:23 -08:00
if ( ! isExplicitInterface )
methodPrefix + = " public " ;
2022-07-26 13:27:03 -04:00
}
2020-02-05 17:07:23 -08:00
else if ( methodDeclaration - > mProtectionSpecifier ! = NULL )
methodPrefix + = methodDeclaration - > mProtectionSpecifier - > ToString ( ) + " " ;
2024-12-31 10:03:16 -08:00
if ( ( ! isInterface ) & & ( methodDef - > mMethodType ! = BfMethodType_Ctor ) )
2020-02-05 17:07:23 -08:00
methodPrefix + = " override " ;
2020-05-27 09:46:09 -07:00
if ( methodDef - > mIsStatic )
methodPrefix + = " static " ;
2024-12-31 10:03:16 -08:00
if ( methodDef - > mMethodType ! = BfMethodType_Ctor )
{
methodPrefix + = mModule - > TypeToString ( methodInst - > mReturnType , nameFlags ) ;
methodPrefix + = " " ;
}
2020-02-05 17:07:23 -08:00
if ( isExplicitInterface )
{
2020-05-27 09:46:09 -07:00
methodName + = mModule - > TypeToString ( methodInst - > GetOwner ( ) , nameFlags ) ;
2020-02-05 17:07:23 -08:00
methodName + = " . " ;
}
2024-12-31 10:03:16 -08:00
if ( methodDef - > mMethodType = = BfMethodType_Ctor )
methodName + = " this " ;
else
methodName + = methodDef - > mName ;
2020-05-27 09:46:09 -07:00
if ( methodInst - > GetNumGenericArguments ( ) > 0 )
{
methodName + = " < " ;
for ( int genericArgIdx = 0 ; genericArgIdx < ( int ) methodInst - > mMethodInfoEx - > mGenericParams . size ( ) ; genericArgIdx + + )
{
if ( genericArgIdx > 0 )
methodName + = " , " ;
auto genericParam = methodInst - > mMethodInfoEx - > mGenericParams [ genericArgIdx ] ;
methodName + = genericParam - > GetName ( ) ;
}
methodName + = " > " ;
}
2024-12-31 11:46:51 -08:00
int usedParamIdx = 0 ;
2020-02-05 17:07:23 -08:00
methodName + = " ( " ;
for ( int paramIdx = 0 ; paramIdx < ( int ) methodInst - > GetParamCount ( ) ; paramIdx + + )
2024-12-31 11:46:51 -08:00
{
if ( methodInst - > GetParamKind ( paramIdx ) = = BfParamKind_AppendIdx )
continue ;
if ( usedParamIdx > 0 )
2020-02-05 17:07:23 -08:00
{
methodName + = " , " ;
2020-02-07 08:44:06 -08:00
if ( ! isAbstract )
2020-02-05 17:07:23 -08:00
impString + = " , " ;
}
2020-12-28 05:15:47 -08:00
if ( methodInst - > GetParamKind ( paramIdx ) = = BfParamKind_Params )
methodName + = " params " ;
2024-11-21 04:58:59 -05:00
2020-05-27 09:46:09 -07:00
methodName + = mModule - > TypeToString ( methodInst - > GetParamType ( paramIdx ) , nameFlags ) ;
2020-02-05 17:07:23 -08:00
methodName + = " " ;
methodName + = methodDef - > mParams [ paramIdx ] - > mName ;
2020-02-21 06:52:25 -08:00
auto paramInitializer = methodInst - > GetParamInitializer ( paramIdx ) ;
if ( paramInitializer ! = NULL )
{
methodName + = " = " ;
paramInitializer - > ToString ( methodName ) ;
}
2020-02-07 08:44:06 -08:00
if ( ! isAbstract )
2020-12-28 05:15:47 -08:00
{
if ( methodInst - > GetParamKind ( paramIdx ) = = BfParamKind_Params )
impString + = " params " ;
2024-11-21 04:58:59 -05:00
auto paramType = methodInst - > GetParamType ( paramIdx ) ;
if ( paramType - > IsRef ( ) )
{
auto refType = ( BfRefType * ) paramType ;
if ( refType - > mRefKind = = BfRefType : : RefKind_Ref )
impString + = " ref " ;
if ( refType - > mRefKind = = BfRefType : : RefKind_Out )
impString + = " out " ;
}
2020-02-05 17:07:23 -08:00
impString + = methodDef - > mParams [ paramIdx ] - > mName ;
2020-12-28 05:15:47 -08:00
}
2024-12-31 11:46:51 -08:00
usedParamIdx + + ;
2020-02-05 17:07:23 -08:00
}
methodName + = " ) " ;
2020-05-27 09:46:09 -07:00
if ( methodInst - > GetNumGenericArguments ( ) > 0 )
2022-07-26 13:27:03 -04:00
{
2020-05-27 09:46:09 -07:00
for ( int genericArgIdx = 0 ; genericArgIdx < ( int ) methodInst - > mMethodInfoEx - > mGenericParams . size ( ) ; genericArgIdx + + )
2022-07-26 13:27:03 -04:00
{
2020-05-27 09:46:09 -07:00
auto genericParam = methodInst - > mMethodInfoEx - > mGenericParams [ genericArgIdx ] ;
2022-07-26 13:27:03 -04:00
if ( genericParam - > mTypeConstraint ! = NULL )
2020-05-27 09:46:09 -07:00
methodName + = " where " + genericParam - > GetName ( ) + " : " + mModule - > TypeToString ( genericParam - > mTypeConstraint , nameFlags ) ;
2022-07-26 13:27:03 -04:00
2020-05-27 09:46:09 -07:00
for ( auto ifaceConstraint : genericParam - > mInterfaceConstraints )
methodName + = " where " + genericParam - > GetName ( ) + " : " + mModule - > TypeToString ( ifaceConstraint , nameFlags ) ;
if ( ( genericParam - > mGenericParamFlags & BfGenericParamFlag_Class ) ! = 0 )
methodName + = " where " + genericParam - > GetName ( ) + " : class " ;
if ( ( genericParam - > mGenericParamFlags & BfGenericParamFlag_Struct ) ! = 0 )
methodName + = " where " + genericParam - > GetName ( ) + " : struct " ;
if ( ( genericParam - > mGenericParamFlags & BfGenericParamFlag_StructPtr ) ! = 0 )
methodName + = " where " + genericParam - > GetName ( ) + " : struct* " ;
if ( ( genericParam - > mGenericParamFlags & BfGenericParamFlag_New ) ! = 0 )
methodName + = " where " + genericParam - > GetName ( ) + " : new " ;
if ( ( genericParam - > mGenericParamFlags & BfGenericParamFlag_Delete ) ! = 0 )
methodName + = " where " + genericParam - > GetName ( ) + " : delete " ;
if ( ( genericParam - > mGenericParamFlags & BfGenericParamFlag_Var ) ! = 0 )
2022-07-26 13:27:03 -04:00
methodName + = " where " + genericParam - > GetName ( ) + " : var " ;
}
2020-05-27 09:46:09 -07:00
}
2024-12-31 10:03:16 -08:00
if ( methodDef - > mMethodType = = BfMethodType_Ctor )
impString + = " ) " ;
else if ( ! isAbstract )
2020-02-05 17:07:23 -08:00
impString + = " ); " ;
if ( showString ! = NULL )
2022-07-26 13:27:03 -04:00
* showString + = methodName ;
2020-02-05 17:07:23 -08:00
if ( insertString ! = NULL )
{
if ( showString = = insertString )
* insertString + = " \t " ;
2024-12-31 10:03:16 -08:00
if ( methodDef - > mMethodType = = BfMethodType_Ctor )
* insertString + = methodPrefix + methodName + impString + " \t " ;
else
* insertString + = methodPrefix + methodName + " \t " + impString ;
2020-02-05 17:07:23 -08:00
}
return true ;
}
else if ( ( methodDef - > mMethodType = = BfMethodType_PropertyGetter ) | | ( methodDef - > mMethodType = = BfMethodType_PropertySetter ) )
{
auto propDeclaration = methodDef - > GetPropertyDeclaration ( ) ;
bool hasGet = propDeclaration - > GetMethod ( " get " ) ! = NULL ;
bool hasSet = propDeclaration - > GetMethod ( " set " ) ! = NULL ;
if ( ( methodDef - > mMethodType = = BfMethodType_PropertyGetter ) | | ( ! hasGet ) )
{
StringT < 128 > propName ;
StringT < 256 > impl ;
2021-03-04 21:41:05 +01:00
if ( propDeclaration - > mNameNode ! = NULL )
propDeclaration - > mNameNode - > ToString ( propName ) ;
2022-07-26 13:27:03 -04:00
else
2021-03-04 21:41:05 +01:00
{
StringT < 128 > args ;
propName + = " this[ " ;
2021-03-24 06:31:11 -04:00
for ( int paramIdx = 0 , count = methodInst - > GetParamCount ( ) ; paramIdx < count ; + + paramIdx )
2021-03-04 21:41:05 +01:00
{
if ( paramIdx > 0 )
args + = " , " ;
args + = mModule - > TypeToString ( methodInst - > GetParamType ( paramIdx ) , nameFlags ) ;
args + = " " ;
args + = methodDef - > mParams [ paramIdx ] - > mName ;
}
propName + = args ;
propName + = " ] " ;
}
2020-02-05 17:07:23 -08:00
bool isAbstract = methodDef - > mIsAbstract ;
if ( propDeclaration - > mProtectionSpecifier ! = NULL )
impl + = propDeclaration - > mProtectionSpecifier - > ToString ( ) + " " ;
2021-03-04 21:41:05 +01:00
else if ( isInterface & & ! isExplicitInterface )
impl + = " public " ;
2020-02-05 17:07:23 -08:00
if ( ! isInterface )
impl + = " override " ;
2021-06-06 03:12:50 +02:00
else if ( methodDef - > mIsStatic )
impl + = " static " ;
2020-02-05 17:07:23 -08:00
BfType * propType = methodInst - > mReturnType ;
if ( methodDef - > mMethodType = = BfMethodType_PropertySetter )
propType = methodInst - > GetParamType ( 0 ) ;
2021-03-04 21:41:05 +01:00
2020-05-27 09:46:09 -07:00
impl + = mModule - > TypeToString ( propType , nameFlags ) ;
2020-02-05 17:07:23 -08:00
impl + = " " ;
if ( isExplicitInterface )
{
2020-05-27 09:46:09 -07:00
impl + = mModule - > TypeToString ( methodInst - > GetOwner ( ) , nameFlags ) ;
2020-02-05 17:07:23 -08:00
impl + = " . " ;
}
impl + = propName ;
impl + = " \t " ;
if ( hasGet )
{
impl + = " get \t " ;
if ( ! isAbstract )
{
if ( isInterface )
{
impl + = " return default; " ;
}
else
{
impl + = " return base. " ;
impl + = propName ;
impl + = " ; " ;
}
}
impl + = " \b " ;
}
if ( hasSet )
{
if ( hasGet )
impl + = " \r \r " ;
impl + = " set \t " ;
if ( ! isAbstract )
{
2022-07-26 13:27:03 -04:00
if ( ! isInterface )
2020-02-05 17:07:23 -08:00
{
impl + = " base. " ;
impl + = propName ;
impl + = " = value; " ;
}
}
impl + = " \b " ;
}
if ( showString ! = NULL )
* showString + = propName ;
if ( insertString ! = NULL )
{
if ( showString = = insertString )
* insertString + = " \t " ;
* insertString + = impl ;
2022-07-26 13:27:03 -04:00
}
2020-02-05 17:07:23 -08:00
return true ;
}
}
return false ;
}
2019-08-23 11:56:54 -07:00
void BfAutoComplete : : AddOverrides ( const StringImpl & filter )
{
if ( ! mIsAutoComplete )
return ;
auto activeTypeDef = mModule - > GetActiveTypeDef ( ) ;
2022-06-24 06:45:35 -07:00
BfShow checkShow = BfShow_Hide ;
2020-02-21 06:52:25 -08:00
BfTypeInstance * curType = mModule - > mCurTypeInstance ;
2019-08-23 11:56:54 -07:00
while ( curType ! = NULL )
2024-12-31 10:28:04 -08:00
{
2019-08-23 11:56:54 -07:00
for ( auto methodDef : curType - > mTypeDef - > mMethods )
{
2022-06-24 06:45:35 -07:00
if ( methodDef - > mShow > = checkShow )
2019-08-23 11:56:54 -07:00
continue ;
2020-10-25 10:40:40 -07:00
bool allowInternalOverride = false ;
2019-08-23 11:56:54 -07:00
if ( curType = = mModule - > mCurTypeInstance )
{
// The "normal" case, and only case for types without extensions
if ( methodDef - > mDeclaringType = = activeTypeDef )
continue ;
if ( ( methodDef - > mDeclaringType - > IsExtension ( ) ) & & ( methodDef - > mDeclaringType - > mProject = = activeTypeDef - > mProject ) )
continue ;
if ( ! curType - > IsTypeMemberAccessible ( methodDef - > mDeclaringType , activeTypeDef ) )
continue ;
2020-10-25 10:40:40 -07:00
if ( methodDef - > mIsExtern )
allowInternalOverride = true ;
2019-08-23 11:56:54 -07:00
}
2022-07-26 13:27:03 -04:00
2019-09-29 09:21:51 -07:00
auto & methodGroup = curType - > mMethodInstanceGroups [ methodDef - > mIdx ] ;
if ( methodGroup . mDefault = = NULL )
2019-08-23 11:56:54 -07:00
{
2019-09-29 09:21:51 -07:00
continue ;
}
auto methodInst = methodGroup . mDefault ;
2019-08-23 11:56:54 -07:00
2020-10-25 10:40:40 -07:00
if ( allowInternalOverride )
{
//
}
else if ( ( ! methodDef - > mIsVirtual ) | | ( methodDef - > mIsOverride ) )
2020-05-08 11:25:55 -07:00
continue ;
2022-07-26 13:27:03 -04:00
2020-05-08 11:25:55 -07:00
if ( ( methodDef - > mMethodType ! = BfMethodType_Normal ) & &
( methodDef - > mMethodType ! = BfMethodType_PropertyGetter ) & &
( methodDef - > mMethodType ! = BfMethodType_PropertySetter ) )
2020-02-05 17:07:23 -08:00
continue ;
2022-07-26 13:27:03 -04:00
2020-02-21 06:52:25 -08:00
if ( ( methodInst - > mVirtualTableIdx > = 0 ) & & ( methodInst - > mVirtualTableIdx < mModule - > mCurTypeInstance - > mVirtualMethodTable . size ( ) ) )
{
auto & vEntry = mModule - > mCurTypeInstance - > mVirtualMethodTable [ methodInst - > mVirtualTableIdx ] ;
if ( vEntry . mImplementingMethod . mTypeInstance = = mModule - > mCurTypeInstance )
continue ;
}
2020-02-05 17:07:23 -08:00
StringT < 512 > insertString ;
2020-02-07 08:44:06 -08:00
GetMethodInfo ( methodInst , & insertString , & insertString , true , false ) ;
2020-02-05 17:07:23 -08:00
if ( insertString . IsEmpty ( ) )
2024-12-31 10:28:04 -08:00
continue ;
AddEntry ( AutoCompleteEntry ( " override " , insertString ) , filter ) ;
2019-08-23 11:56:54 -07:00
}
if ( curType - > IsStruct ( ) )
curType = mModule - > mContext - > mBfObjectType ;
else
curType = curType - > mBaseType ;
}
}
2024-12-31 10:03:16 -08:00
void BfAutoComplete : : AddCtorPassthroughs ( )
{
if ( ! mIsAutoComplete )
return ;
auto activeTypeDef = mModule - > GetActiveTypeDef ( ) ;
BfTypeInstance * curType = mModule - > mCurTypeInstance ;
auto baseType = curType - > mBaseType ;
2024-12-31 10:28:04 -08:00
String totalInsertString ;
2024-12-31 10:03:16 -08:00
Array < BfMethodInstance * > declMethods ;
for ( auto methodDef : curType - > mTypeDef - > mMethods )
{
if ( methodDef - > mMethodType ! = BfMethodType_Ctor )
continue ;
auto & methodGroup = curType - > mMethodInstanceGroups [ methodDef - > mIdx ] ;
auto methodInst = methodGroup . mDefault ;
if ( methodInst = = NULL )
continue ;
if ( methodDef - > mMethodType ! = BfMethodType_Ctor )
continue ;
declMethods . Add ( methodInst ) ;
}
2024-12-31 10:28:04 -08:00
2024-12-31 10:03:16 -08:00
for ( auto methodDef : baseType - > mTypeDef - > mMethods )
{
if ( methodDef - > mShow ! = BfShow_Show )
continue ;
if ( methodDef - > mProtection < BfProtection_Protected )
continue ;
if ( methodDef - > mIsStatic )
continue ;
auto & methodGroup = baseType - > mMethodInstanceGroups [ methodDef - > mIdx ] ;
auto methodInst = methodGroup . mDefault ;
if ( methodInst = = NULL )
continue ;
if ( methodDef - > mMethodType ! = BfMethodType_Ctor )
continue ;
if ( methodInst - > GetParamCount ( ) = = 0 )
continue ;
bool hasDecl = false ;
for ( auto declMethod : declMethods )
{
if ( mModule - > CompareMethodSignatures ( methodInst , declMethod ) )
{
hasDecl = true ;
break ;
}
}
if ( hasDecl )
continue ;
StringT < 512 > insertString ;
GetMethodInfo ( methodInst , & insertString , & insertString , true , false ) ;
if ( insertString . IsEmpty ( ) )
continue ;
AddEntry ( AutoCompleteEntry ( " this " , insertString ) , " " ) ;
2024-12-31 10:28:04 -08:00
int tabPos = ( int ) insertString . IndexOf ( ' \t ' ) ;
if ( tabPos > = 0 )
{
if ( ! totalInsertString . IsEmpty ( ) )
totalInsertString + = " \r \r " ;
totalInsertString + = insertString . Substring ( tabPos + 1 ) ;
}
}
if ( ( ! totalInsertString . IsEmpty ( ) ) & & ( mEntriesSet . GetCount ( ) > = 2 ) )
{
totalInsertString . Replace ( " \t " , " \t \b " ) ;
totalInsertString . Insert ( 0 , " this - all \t " ) ;
auto entry = AddEntry ( AutoCompleteEntry ( " this " , totalInsertString ) , " " ) ;
2024-12-31 10:03:16 -08:00
}
}
2019-08-23 11:56:54 -07:00
void BfAutoComplete : : UpdateReplaceData ( )
{
}
void BfAutoComplete : : CheckMethod ( BfMethodDeclaration * methodDeclaration , bool isLocalMethod )
{
if ( /*(propertyDeclaration->mDefinitionBlock == NULL) &&*/ ( methodDeclaration - > mVirtualSpecifier ! = NULL ) & &
( methodDeclaration - > mVirtualSpecifier - > GetToken ( ) = = BfToken_Override ) )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
auto bfParser = methodDeclaration - > mVirtualSpecifier - > GetSourceData ( ) - > ToParser ( ) ;
if ( bfParser = = NULL )
return ;
int cursorIdx = bfParser - > mCursorIdx ;
bool isInTypeRef = IsAutocompleteNode ( methodDeclaration - > mReturnType ) ;
bool isInNameNode = IsAutocompleteNode ( methodDeclaration - > mNameNode ) ;
if ( ( ( IsAutocompleteNode ( methodDeclaration , 1 ) ) & & ( cursorIdx = = methodDeclaration - > mVirtualSpecifier - > GetSrcEnd ( ) ) ) | |
( isInTypeRef ) | | ( isInNameNode ) )
{
if ( mIsAutoComplete )
{
mInsertStartIdx = methodDeclaration - > GetSrcStart ( ) ;
mInsertEndIdx = methodDeclaration - > GetSrcEnd ( ) ;
2022-01-31 16:00:06 -05:00
if ( methodDeclaration - > mBody ! = NULL )
{
if ( methodDeclaration - > mBody - > mTriviaStart ! = - 1 )
mInsertEndIdx = methodDeclaration - > mBody - > mTriviaStart ;
else
mInsertEndIdx = methodDeclaration - > mBody - > GetSrcStart ( ) ;
}
2019-08-23 11:56:54 -07:00
}
String filter ;
if ( ( isInNameNode | | isInTypeRef ) )
{
if ( methodDeclaration - > mNameNode ! = NULL )
filter = methodDeclaration - > mNameNode - > ToString ( ) ;
else if ( methodDeclaration - > mReturnType ! = NULL )
filter = methodDeclaration - > mReturnType - > ToString ( ) ;
}
else if ( methodDeclaration - > mBody ! = NULL )
{
// We're just inside 'override' - we may be inserting a new method
mInsertEndIdx = methodDeclaration - > mVirtualSpecifier - > GetSrcEnd ( ) ;
}
AddOverrides ( filter ) ;
}
}
2024-12-31 10:03:16 -08:00
if ( auto ctorDeclaration = BfNodeDynCast < BfConstructorDeclaration > ( methodDeclaration ) )
{
if ( ( ctorDeclaration - > mThisToken ! = NULL ) & & ( ctorDeclaration - > mOpenParen = = NULL ) )
{
auto bfParser = ctorDeclaration - > mThisToken - > GetSourceData ( ) - > ToParser ( ) ;
if ( bfParser = = NULL )
return ;
int cursorIdx = bfParser - > mCursorIdx ;
if ( ( IsAutocompleteNode ( methodDeclaration , 1 ) ) & & ( cursorIdx = = ctorDeclaration - > mThisToken - > GetSrcEnd ( ) ) )
{
if ( mIsAutoComplete )
{
mInsertStartIdx = ctorDeclaration - > GetSrcStart ( ) ;
mInsertEndIdx = ctorDeclaration - > mThisToken - > GetSrcEnd ( ) ;
}
AddCtorPassthroughs ( ) ;
}
}
}
2019-08-23 11:56:54 -07:00
if ( methodDeclaration - > mReturnType ! = NULL )
CheckTypeRef ( methodDeclaration - > mReturnType , true , isLocalMethod ) ;
}
void BfAutoComplete : : CheckProperty ( BfPropertyDeclaration * propertyDeclaration )
{
if ( IsAutocompleteNode ( propertyDeclaration - > mNameNode ) )
{
mInsertStartIdx = propertyDeclaration - > mNameNode - > GetSrcStart ( ) ;
mInsertEndIdx = propertyDeclaration - > mNameNode - > GetSrcEnd ( ) ;
}
2019-12-13 14:24:00 -08:00
if ( propertyDeclaration - > mExplicitInterface ! = NULL )
{
BfTypeInstance * typeInst = NULL ;
2021-10-01 06:57:10 -07:00
auto type = mModule - > ResolveTypeRef ( propertyDeclaration - > mExplicitInterface , BfPopulateType_Identity ) ;
2019-12-13 14:24:00 -08:00
if ( type ! = NULL )
typeInst = type - > ToTypeInstance ( ) ;
2022-07-26 13:27:03 -04:00
if ( typeInst ! = NULL )
CheckExplicitInterface ( typeInst , propertyDeclaration - > mExplicitInterfaceDotToken , propertyDeclaration - > mNameNode ) ;
2019-12-13 14:24:00 -08:00
}
2019-08-23 11:56:54 -07:00
if ( ( propertyDeclaration - > mVirtualSpecifier ! = NULL ) & &
( propertyDeclaration - > mVirtualSpecifier - > GetToken ( ) = = BfToken_Override ) )
{
if ( ! mIsAutoComplete )
return ;
auto bfParser = propertyDeclaration - > mVirtualSpecifier - > GetSourceData ( ) - > ToParser ( ) ;
if ( bfParser = = NULL )
return ;
int cursorIdx = bfParser - > mCursorIdx ;
bool isInTypeRef = IsAutocompleteNode ( propertyDeclaration - > mTypeRef ) ;
bool isInNameNode = IsAutocompleteNode ( propertyDeclaration - > mNameNode ) ;
if ( ( ( IsAutocompleteNode ( propertyDeclaration , 1 ) ) & & ( cursorIdx = = propertyDeclaration - > mVirtualSpecifier - > GetSrcEnd ( ) ) ) | |
( isInTypeRef ) | | ( isInNameNode ) )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
mInsertStartIdx = propertyDeclaration - > mVirtualSpecifier - > GetSrcStart ( ) ;
String filter ;
if ( ( isInNameNode | | isInTypeRef ) )
{
BfAstNode * defNode = NULL ;
if ( isInNameNode )
defNode = propertyDeclaration - > mNameNode ;
else if ( isInTypeRef )
defNode = propertyDeclaration - > mTypeRef ;
2022-07-26 13:27:03 -04:00
filter = defNode - > ToString ( ) ;
2019-08-23 11:56:54 -07:00
mInsertEndIdx = defNode - > GetSrcEnd ( ) ;
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
else if ( propertyDeclaration - > mTypeRef ! = NULL )
{
2022-07-26 13:27:03 -04:00
// We're just inside 'override' - we may be inserting a new method
2019-08-23 11:56:54 -07:00
mInsertEndIdx = propertyDeclaration - > mVirtualSpecifier - > GetSrcEnd ( ) ;
}
else
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
mInsertEndIdx = propertyDeclaration - > mVirtualSpecifier - > GetSrcEnd ( ) ;
}
AddOverrides ( filter ) ;
2020-11-09 10:22:54 -08:00
mInsertStartIdx = propertyDeclaration - > mSrcStart ;
2019-08-23 11:56:54 -07:00
}
}
else
{
if ( propertyDeclaration - > mTypeRef ! = NULL )
CheckTypeRef ( propertyDeclaration - > mTypeRef , true ) ;
}
}
void BfAutoComplete : : CheckVarResolution ( BfAstNode * varTypeRef , BfType * resolvedType )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
if ( IsAutocompleteNode ( varTypeRef ) )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
if ( ( resolvedType = = NULL ) | | ( resolvedType - > IsVar ( ) ) | | ( resolvedType - > IsLet ( ) ) )
return ;
if ( mIsGetDefinition )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
auto typeInst = resolvedType - > ToTypeInstance ( ) ;
if ( typeInst ! = NULL )
{
if ( typeInst - > mTypeDef - > mTypeDeclaration ! = NULL )
SetDefinitionLocation ( typeInst - > mTypeDef - > mTypeDeclaration - > mNameNode ) ;
}
}
2019-12-24 13:13:04 -08:00
if ( mResolveType = = BfResolveType_GetResultString )
2019-08-23 11:56:54 -07:00
{
2019-12-24 13:13:04 -08:00
mResultString = " : " ;
2021-10-31 09:48:04 -07:00
mResultString + = mModule - > TypeToString ( resolvedType , ( BfTypeNameFlags ) ( BfTypeNameFlag_ExtendedInfo | BfTypeNameFlag_ResolveGenericParamNames ) ) ;
2019-08-23 11:56:54 -07:00
}
}
}
2024-12-31 07:48:03 -08:00
class BfAutocompleteNodeChecker : public BfStructuralVisitor
2019-12-24 13:13:04 -08:00
{
2024-12-31 07:48:03 -08:00
public :
BfAutoComplete * mAutoComplete ;
bool mSelected ;
public :
BfAutocompleteNodeChecker ( BfAutoComplete * autoComplete )
{
mAutoComplete = autoComplete ;
mSelected = false ;
}
virtual void Visit ( BfAstNode * bfAstNode ) override
{
mSelected = mAutoComplete - > IsAutocompleteNode ( bfAstNode ) ;
}
virtual void Visit ( BfBinaryOperatorExpression * binOpExpr ) override
{
mSelected = mAutoComplete - > IsAutocompleteNode ( binOpExpr - > mOpToken ) ;
}
virtual void Visit ( BfUnaryOperatorExpression * unaryOpExpr ) override
{
VisitChild ( unaryOpExpr - > mExpression ) ;
}
virtual void Visit ( BfCastExpression * castExpr ) override
{
VisitChild ( castExpr - > mExpression ) ;
}
virtual void Visit ( BfLiteralExpression * literalExpr ) override
{
mSelected = mAutoComplete - > IsAutocompleteNode ( literalExpr ) ;
}
virtual void Visit ( BfIdentifierNode * identifierNode ) override
{
mSelected = mAutoComplete - > IsAutocompleteNode ( identifierNode ) ;
}
virtual void Visit ( BfMemberReferenceExpression * memberRefExpr ) override
{
mSelected = mAutoComplete - > IsAutocompleteNode ( memberRefExpr - > mMemberName ) ;
}
} ;
void BfAutoComplete : : CheckResult ( BfAstNode * node , const BfTypedValue & typedValue )
{
2019-12-24 13:13:04 -08:00
if ( mResolveType ! = BfResolveType_GetResultString )
return ;
if ( ! IsAutocompleteNode ( node ) )
return ;
2024-12-31 07:48:03 -08:00
2019-12-24 13:13:04 -08:00
if ( ! typedValue . mValue . IsConst ( ) )
return ;
if ( typedValue . mType - > IsPointer ( ) )
return ;
if ( typedValue . mType - > IsObject ( ) )
return ;
2024-12-31 07:48:03 -08:00
BfAutocompleteNodeChecker autocompleteNodeChecker ( this ) ;
autocompleteNodeChecker . VisitChildNoRef ( node ) ;
if ( ! autocompleteNodeChecker . mSelected )
return ;
String constStr = ConstantToString ( mModule - > mBfIRBuilder , typedValue ) ;
if ( ! constStr . IsEmpty ( ) )
2019-12-24 13:13:04 -08:00
{
2024-12-31 07:48:03 -08:00
mResultString = " : " ;
mResultString + = constStr ;
AddResultTypeKind ( typedValue . mType ) ;
2019-12-24 13:13:04 -08:00
}
2024-12-31 07:48:03 -08:00
else
2019-12-24 13:13:04 -08:00
{
2024-12-31 07:48:03 -08:00
SetResultStringType ( typedValue . mType ) ;
2022-07-26 13:27:03 -04:00
}
2019-12-24 13:13:04 -08:00
}
2020-05-26 06:10:51 -07:00
void BfAutoComplete : : CheckLocalDef ( BfAstNode * identifierNode , BfLocalVariable * varDecl )
2019-08-23 11:56:54 -07:00
{
CheckLocalRef ( identifierNode , varDecl ) ;
}
2020-05-26 06:10:51 -07:00
void BfAutoComplete : : CheckLocalRef ( BfAstNode * identifierNode , BfLocalVariable * varDecl )
2019-08-23 11:56:54 -07:00
{
if ( mReplaceLocalId ! = - 1 )
return ;
if ( mResolveType = = BfResolveType_GoToDefinition )
{
if ( IsAutocompleteNode ( identifierNode ) )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
if ( varDecl - > mNameNode ! = NULL )
2020-06-14 06:39:29 -07:00
SetDefinitionLocation ( varDecl - > mNameNode , true ) ;
2020-02-21 09:26:02 -08:00
else if ( varDecl - > mIsThis )
2020-06-14 06:39:29 -07:00
SetDefinitionLocation ( mModule - > mCurTypeInstance - > mTypeDef - > GetRefNode ( ) , true ) ;
2019-08-23 11:56:54 -07:00
}
}
else if ( mResolveType = = BfResolveType_GetSymbolInfo )
{
2022-07-26 13:27:03 -04:00
if ( ( IsAutocompleteNode ( identifierNode ) ) & &
2019-08-23 11:56:54 -07:00
( ( ! varDecl - > mIsShadow ) | | ( varDecl - > mShadowedLocal ! = NULL ) ) )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
if ( ( mModule - > mCurMethodState ! = NULL ) & & ( mModule - > mCurMethodState - > mClosureState ! = NULL ) & &
( ! mModule - > mCurMethodState - > mClosureState - > mCapturing ) )
{
// For closures, only get locals during the 'capturing' stage
return ;
}
auto rootMethodInstance = mModule - > mCurMethodState - > GetRootMethodState ( ) - > mMethodInstance ;
if ( rootMethodInstance = = NULL )
return ;
2022-07-26 13:27:03 -04:00
2020-02-21 09:26:02 -08:00
if ( varDecl - > mIsThis )
return ;
2022-07-26 13:27:03 -04:00
auto resolvePassData = mModule - > mCompiler - > mResolvePassData ;
2019-08-23 11:56:54 -07:00
mDefType = mModule - > mCurTypeInstance - > mTypeDef ;
2022-07-26 13:27:03 -04:00
2020-02-21 09:26:02 -08:00
mReplaceLocalId = varDecl - > mLocalVarId ;
2019-08-23 11:56:54 -07:00
mDefMethod = rootMethodInstance - > mMethodDef ;
if ( mInsertStartIdx = = - 1 )
{
mInsertStartIdx = identifierNode - > GetSrcStart ( ) ;
mInsertEndIdx = identifierNode - > GetSrcEnd ( ) ;
2020-05-29 16:58:47 -07:00
}
2019-08-23 11:56:54 -07:00
}
2022-07-26 13:27:03 -04:00
}
2020-05-17 06:10:56 -07:00
else if ( mResolveType = = BfResolveType_GetResultString )
{
if ( IsAutocompleteNode ( identifierNode ) )
2022-07-26 13:27:03 -04:00
{
2020-05-17 06:10:56 -07:00
String constStr ;
2020-07-01 06:28:50 -07:00
if ( varDecl - > mConstValue . IsConst ( ) )
2024-12-31 07:48:03 -08:00
constStr = ConstantToString ( mModule - > mBfIRBuilder , BfTypedValue ( varDecl - > mConstValue , varDecl - > mResolvedType ) ) ;
2020-05-17 06:10:56 -07:00
if ( ! constStr . IsEmpty ( ) )
{
mResultString = constStr ;
}
else
{
2022-07-26 13:27:03 -04:00
SetResultStringType ( varDecl - > mResolvedType ) ;
2020-05-17 06:10:56 -07:00
}
}
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
}
2020-05-26 06:10:51 -07:00
void BfAutoComplete : : CheckFieldRef ( BfAstNode * identifierNode , BfFieldInstance * fieldInst )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
if ( mResolveType = = BfResolveType_GetSymbolInfo )
{
if ( mDefField ! = NULL )
return ;
if ( IsAutocompleteNode ( identifierNode ) )
{
while ( true )
{
if ( auto qualifiedName = BfNodeDynCast < BfQualifiedNameNode > ( identifierNode ) )
{
identifierNode = qualifiedName - > mRight ;
if ( ! IsAutocompleteNode ( identifierNode ) )
return ;
}
else
break ;
}
//mReplaceTypeDef = fieldInst->mOwner->mTypeDef;
//mReplaceFieldDef = fieldInst->GetFieldDef();
mDefType = fieldInst - > mOwner - > mTypeDef ;
mDefField = fieldInst - > GetFieldDef ( ) ;
mInsertStartIdx = identifierNode - > GetSrcStart ( ) ;
mInsertEndIdx = identifierNode - > GetSrcEnd ( ) ;
}
}
}
2020-05-29 16:58:47 -07:00
void BfAutoComplete : : CheckLabel ( BfIdentifierNode * identifierNode , BfAstNode * precedingNode , BfScopeData * scopeData )
2019-08-23 11:56:54 -07:00
{
String filter ;
if ( identifierNode ! = NULL )
{
2020-05-29 16:58:47 -07:00
if ( ( mModule - > mCompiler - > mResolvePassData ! = NULL ) & & ( scopeData ! = NULL ) )
2022-07-26 13:27:03 -04:00
{
2020-05-29 16:58:47 -07:00
auto rootMethodState = mModule - > mCurMethodState - > GetRootMethodState ( ) ;
mModule - > mCompiler - > mResolvePassData - > HandleLocalReference ( identifierNode , rootMethodState - > mMethodInstance - > GetOwner ( ) - > mTypeDef , rootMethodState - > mMethodInstance - > mMethodDef , scopeData - > mScopeLocalId ) ;
}
2019-08-23 11:56:54 -07:00
if ( ! IsAutocompleteNode ( identifierNode ) )
return ;
2022-07-26 13:27:03 -04:00
2020-05-29 16:58:47 -07:00
if ( scopeData ! = NULL )
{
if ( mResolveType = = BfResolveType_GoToDefinition )
{
SetDefinitionLocation ( scopeData - > mLabelNode ) ;
}
else if ( mResolveType = = BfResolveType_GetSymbolInfo )
{
auto rootMethodInstance = mModule - > mCurMethodState - > GetRootMethodState ( ) - > mMethodInstance ;
if ( rootMethodInstance = = NULL )
return ;
mDefType = mModule - > mCurTypeInstance - > mTypeDef ;
mReplaceLocalId = scopeData - > mScopeLocalId ;
mDefMethod = rootMethodInstance - > mMethodDef ;
if ( mInsertStartIdx = = - 1 )
{
mInsertStartIdx = identifierNode - > GetSrcStart ( ) ;
mInsertEndIdx = identifierNode - > GetSrcEnd ( ) ;
}
}
if ( scopeData - > mLabelNode = = identifierNode )
return ;
}
2019-08-23 11:56:54 -07:00
filter = identifierNode - > ToString ( ) ;
mInsertStartIdx = identifierNode - > GetSrcStart ( ) ;
mInsertEndIdx = identifierNode - > GetSrcEnd ( ) ;
}
else
{
if ( precedingNode = = NULL )
return ;
int expectSpacing = 1 ;
if ( auto precedingToken = BfNodeDynCast < BfTokenNode > ( precedingNode ) )
if ( precedingToken - > GetToken ( ) = = BfToken_Colon )
expectSpacing = 0 ;
if ( ! IsAutocompleteNode ( precedingNode , expectSpacing ) )
return ;
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
auto bfParser = precedingNode - > GetSourceData ( ) - > ToParser ( ) ;
if ( bfParser - > mCursorIdx ! = precedingNode - > GetSrcEnd ( ) + expectSpacing - 1 )
return ;
mInsertStartIdx = precedingNode - > GetSrcEnd ( ) + expectSpacing ;
mInsertEndIdx = mInsertStartIdx ;
}
auto checkScope = mModule - > mCurMethodState - > mCurScope ;
while ( checkScope ! = NULL )
{
if ( ! checkScope - > mLabel . empty ( ) )
AddEntry ( AutoCompleteEntry ( " label " , checkScope - > mLabel ) , filter ) ;
checkScope = checkScope - > mPrevScope ;
}
}
2020-05-31 07:12:17 -07:00
void BfAutoComplete : : CheckNamespace ( BfAstNode * node , const BfAtomComposite & namespaceName )
{
if ( mResolveType = = BfResolveType_GetSymbolInfo )
2022-07-26 13:27:03 -04:00
{
2020-05-31 07:12:17 -07:00
if ( IsAutocompleteNode ( node ) )
2022-07-26 13:27:03 -04:00
{
2020-05-31 07:12:17 -07:00
int namespaceCount = namespaceName . mSize ;
auto checkNode = node ;
2022-07-26 13:27:03 -04:00
2020-05-31 07:12:17 -07:00
while ( auto qualifiedTypeRef = BfNodeDynCast < BfQualifiedTypeReference > ( checkNode ) )
{
if ( ! IsAutocompleteNode ( qualifiedTypeRef - > mLeft ) )
break ;
namespaceCount - - ;
checkNode = qualifiedTypeRef - > mLeft ;
}
while ( auto qualifiedNameNode = BfNodeDynCast < BfQualifiedNameNode > ( checkNode ) )
{
if ( ! IsAutocompleteNode ( qualifiedNameNode - > mLeft ) )
break ;
namespaceCount - - ;
checkNode = qualifiedNameNode - > mLeft ;
}
2022-07-26 13:27:03 -04:00
while ( auto qualifiedTypeRef = BfNodeDynCast < BfQualifiedTypeReference > ( checkNode ) )
checkNode = qualifiedTypeRef - > mRight ;
2020-05-31 07:12:17 -07:00
while ( auto qualifiedNameNode = BfNodeDynCast < BfQualifiedNameNode > ( checkNode ) )
checkNode = qualifiedNameNode - > mRight ;
2022-06-25 08:32:05 -07:00
if ( checkNode ! = NULL )
{
mInsertStartIdx = checkNode - > GetSrcStart ( ) ;
mInsertEndIdx = checkNode - > GetSrcEnd ( ) ;
mDefNamespace . Set ( namespaceName . mParts , namespaceCount , NULL , 0 ) ;
2022-07-26 13:27:03 -04:00
}
2020-05-31 07:12:17 -07:00
}
2022-07-26 13:27:03 -04:00
}
2020-05-31 07:12:17 -07:00
}
2019-08-23 11:56:54 -07:00
void BfAutoComplete : : AddTypeInstanceEntry ( BfTypeInstance * typeInst )
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
String bestTypeName = mModule - > TypeToString ( typeInst , BfTypeNameFlag_ReduceName ) ;
if ( typeInst - > IsValueType ( ) )
AddEntry ( AutoCompleteEntry ( " valuetype " , bestTypeName ) ) ;
else
AddEntry ( AutoCompleteEntry ( " class " , bestTypeName ) ) ;
mDefaultSelection = bestTypeName ;
}
2020-10-08 09:41:05 -07:00
bool BfAutoComplete : : CheckDocumentation ( AutoCompleteEntry * entry , BfCommentNode * documentation )
2019-08-23 11:56:54 -07:00
{
2020-10-08 09:41:05 -07:00
if ( mDocumentationEntryName . IsEmpty ( ) )
return false ;
2022-07-26 13:27:03 -04:00
2020-10-08 09:41:05 -07:00
if ( mDocumentationEntryName ! = entry - > mDisplay )
return false ;
if ( documentation ! = NULL )
{
StringT < 128 > str ;
2022-07-26 13:27:03 -04:00
documentation - > GetDocString ( str ) ;
2020-10-08 09:41:05 -07:00
entry - > mDocumentation = mAlloc . AllocString ( str ) ;
2022-07-26 13:27:03 -04:00
}
2020-10-08 09:41:05 -07:00
return true ;
2019-08-23 11:56:54 -07:00
}
void BfAutoComplete : : CheckEmptyStart ( BfAstNode * prevNode , BfType * type )
{
// Temporarily (?) removed?
return ;
if ( IsAutocompleteNode ( prevNode , 2 ) )
{
if ( ! type - > IsEnum ( ) )
return ;
int wantCursorIdx = prevNode - > GetSrcEnd ( ) - 1 ;
String prevNodeString = prevNode - > ToString ( ) ;
if ( prevNodeString ! = " ( " )
wantCursorIdx + + ;
if ( prevNode - > GetSourceData ( ) - > ToParser ( ) - > mCursorIdx ! = wantCursorIdx )
return ;
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
AddTypeInstanceEntry ( type - > ToTypeInstance ( ) ) ;
2022-07-26 13:27:03 -04:00
CheckIdentifier ( NULL ) ;
2019-08-23 11:56:54 -07:00
mInsertStartIdx = wantCursorIdx + 1 ;
mInsertEndIdx = mInsertStartIdx ;
}
}
bool BfAutoComplete : : CheckFixit ( BfAstNode * node )
{
if ( mIgnoreFixits )
return false ;
2022-07-02 10:32:19 -07:00
if ( mModule = = NULL )
return false ;
2019-08-23 11:56:54 -07:00
if ( mCompiler - > mResolvePassData - > mResolveType ! = BfResolveType_GetFixits )
return false ;
if ( ! IsAutocompleteLineNode ( node ) )
return false ;
if ( mInsertStartIdx = = - 1 )
{
mInsertStartIdx = node - > GetSrcStart ( ) ;
mInsertEndIdx = node - > GetSrcStart ( ) ;
}
return true ;
}
2020-02-07 08:44:06 -08:00
int BfAutoComplete : : FixitGetMemberInsertPos ( BfTypeDef * typeDef )
{
BfTypeDeclaration * typeDecl = typeDef - > mTypeDeclaration ;
BfTokenNode * openNode = NULL ;
BfTokenNode * closeNode = NULL ;
if ( auto blockNode = BfNodeDynCast < BfBlock > ( typeDecl - > mDefineNode ) )
{
openNode = blockNode - > mOpenBrace ;
closeNode = blockNode - > mCloseBrace ;
}
int insertPos = - 1 ;
BfParserData * parser = typeDef - > mTypeDeclaration - > GetSourceData ( ) - > ToParserData ( ) ;
if ( ( parser ! = NULL ) & & ( closeNode ! = NULL ) )
{
int startPos = openNode - > mSrcStart + 1 ;
insertPos = closeNode - > mSrcStart ;
while ( insertPos > startPos )
{
char prevC = parser - > mSrc [ insertPos - 1 ] ;
if ( prevC = = ' \n ' )
break ;
insertPos - - ;
}
if ( insertPos > startPos )
insertPos - - ;
}
return insertPos ;
}
void BfAutoComplete : : CheckInterfaceFixit ( BfTypeInstance * typeInstance , BfAstNode * node )
2020-02-05 17:07:23 -08:00
{
if ( ! CheckFixit ( node ) )
return ;
if ( typeInstance = = NULL )
2022-07-26 13:27:03 -04:00
return ;
2020-02-05 17:07:23 -08:00
2021-07-15 07:01:02 -07:00
if ( typeInstance - > IsInterface ( ) )
return ;
2020-02-05 17:07:23 -08:00
for ( auto & ifaceTypeInst : typeInstance - > mInterfaces )
{
Array < BfMethodInstance * > missingMethods ;
auto ifaceInst = ifaceTypeInst . mInterfaceType ;
int startIdx = ifaceTypeInst . mStartInterfaceTableIdx ;
int iMethodCount = ( int ) ifaceInst - > mMethodInstanceGroups . size ( ) ;
auto declTypeDef = ifaceTypeInst . mDeclaringType ;
for ( int iMethodIdx = 0 ; iMethodIdx < iMethodCount ; iMethodIdx + + )
{
auto matchedMethodRef = & typeInstance - > mInterfaceMethodTable [ iMethodIdx + startIdx ] . mMethodRef ;
BfMethodInstance * matchedMethod = * matchedMethodRef ;
auto ifaceMethodInst = ifaceInst - > mMethodInstanceGroups [ iMethodIdx ] . mDefault ;
if ( ifaceMethodInst = = NULL )
continue ;
auto iReturnType = ifaceMethodInst - > mReturnType ;
if ( iReturnType - > IsSelf ( ) )
iReturnType = typeInstance ;
if ( ifaceMethodInst - > mMethodDef - > mIsOverride )
continue ; // Don't consider overrides here
// If we have "ProjA depends on LibBase", "ProjB depends on LibBase", then a type ClassC in LibBase implementing IFaceD,
2022-07-26 13:27:03 -04:00
// where IFaceD gets extended with MethodE in ProjA, an implementing MethodE is still required to exist on ClassC --
2020-02-05 17:07:23 -08:00
// the visibility is bidirectional. A type ClassF implementing IFaceD inside ProjB will not be required to implement
// MethodE, however
if ( ( ! ifaceInst - > IsTypeMemberAccessible ( ifaceMethodInst - > mMethodDef - > mDeclaringType , ifaceTypeInst . mDeclaringType ) ) & &
( ! ifaceInst - > IsTypeMemberAccessible ( ifaceTypeInst . mDeclaringType , ifaceMethodInst - > mMethodDef - > mDeclaringType ) ) )
continue ;
if ( ! ifaceInst - > IsTypeMemberIncluded ( ifaceMethodInst - > mMethodDef - > mDeclaringType , ifaceTypeInst . mDeclaringType ) )
continue ;
bool hadMatch = matchedMethod ! = NULL ;
bool hadPubFailure = false ;
bool hadMutFailure = false ;
if ( ! hadMatch )
missingMethods . Add ( ifaceMethodInst ) ;
}
if ( ! missingMethods . IsEmpty ( ) )
2022-07-26 13:27:03 -04:00
{
2020-02-05 17:07:23 -08:00
BfParserData * parser = declTypeDef - > mTypeDeclaration - > GetSourceData ( ) - > ToParserData ( ) ;
2020-02-07 08:44:06 -08:00
if ( parser ! = NULL )
{
int insertPos = FixitGetMemberInsertPos ( declTypeDef ) ;
2020-02-05 17:07:23 -08:00
bool wantsBreak = false ;
String insertStr = " \f " ;
for ( auto methodInst : missingMethods )
{
if ( wantsBreak )
{
insertStr + = " \r \r " ;
wantsBreak = false ;
}
2020-02-07 08:44:06 -08:00
if ( GetMethodInfo ( methodInst , NULL , & insertStr , true , false ) )
2020-02-05 17:07:23 -08:00
{
insertStr + = " \b " ;
wantsBreak = true ;
}
}
wantsBreak = false ;
String explicitInsertStr = " \f " ;
for ( auto methodInst : missingMethods )
{
if ( wantsBreak )
{
explicitInsertStr + = " \r \r " ;
wantsBreak = false ;
}
2020-02-07 08:44:06 -08:00
if ( GetMethodInfo ( methodInst , NULL , & explicitInsertStr , true , true ) )
2020-02-05 17:07:23 -08:00
{
explicitInsertStr + = " \b " ;
wantsBreak = true ;
}
}
2020-02-07 08:44:06 -08:00
if ( insertPos ! = - 1 )
{
mCompiler - > mResolvePassData - > mAutoComplete - > AddEntry ( AutoCompleteEntry ( " fixit " , StrFormat ( " Implement interface '%s' \t using|%s|%s " ,
mModule - > TypeToString ( ifaceInst ) . c_str ( ) , FixitGetLocation ( parser , insertPos ) . c_str ( ) , insertStr . c_str ( ) ) . c_str ( ) ) ) ;
mCompiler - > mResolvePassData - > mAutoComplete - > AddEntry ( AutoCompleteEntry ( " fixit " , StrFormat ( " Implement interface '%s' explicitly \t using|%s|%s " ,
mModule - > TypeToString ( ifaceInst ) . c_str ( ) , FixitGetLocation ( parser , insertPos ) . c_str ( ) , explicitInsertStr . c_str ( ) ) . c_str ( ) ) ) ;
}
}
}
}
if ( ( ! typeInstance - > IsInterface ( ) ) & & ( ! typeInstance - > IsUnspecializedTypeVariation ( ) ) & & ( ! typeInstance - > IsBoxed ( ) ) )
{
if ( ! typeInstance - > mTypeDef - > mIsAbstract )
{
Array < BfMethodInstance * > missingMethods ;
for ( int methodIdx = 0 ; methodIdx < ( int ) typeInstance - > mVirtualMethodTable . size ( ) ; methodIdx + + )
{
auto & methodRef = typeInstance - > mVirtualMethodTable [ methodIdx ] . mImplementingMethod ;
if ( methodRef . mMethodNum = = - 1 )
{
BF_ASSERT ( mCompiler - > mOptions . mHasVDataExtender ) ;
if ( methodRef . mTypeInstance = = typeInstance )
{
if ( typeInstance - > GetImplBaseType ( ) ! = NULL )
BF_ASSERT ( methodIdx = = ( int ) typeInstance - > GetImplBaseType ( ) - > mVirtualMethodTableSize ) ;
}
continue ;
}
auto methodInstance = ( BfMethodInstance * ) methodRef ;
if ( ( methodInstance ! = NULL ) & & ( methodInstance - > mMethodDef - > mIsAbstract ) )
{
if ( methodInstance - > mMethodDef - > mIsAbstract )
{
if ( ! typeInstance - > IsUnspecializedTypeVariation ( ) )
missingMethods . Add ( methodInstance ) ;
}
}
}
if ( ! missingMethods . IsEmpty ( ) )
{
auto declTypeDef = typeInstance - > mTypeDef ;
BfParserData * parser = declTypeDef - > mTypeDeclaration - > GetSourceData ( ) - > ToParserData ( ) ;
if ( parser ! = NULL )
{
int insertPos = FixitGetMemberInsertPos ( declTypeDef ) ;
bool wantsBreak = false ;
String insertStr = " \f " ;
for ( auto methodInst : missingMethods )
{
if ( wantsBreak )
{
insertStr + = " \r \r " ;
wantsBreak = false ;
}
if ( GetMethodInfo ( methodInst , NULL , & insertStr , true , false ) )
{
insertStr + = " \b " ;
wantsBreak = true ;
}
}
2020-02-05 17:07:23 -08:00
2020-02-07 08:44:06 -08:00
if ( insertPos ! = - 1 )
{
mCompiler - > mResolvePassData - > mAutoComplete - > AddEntry ( AutoCompleteEntry ( " fixit " , StrFormat ( " Implement abstract methods \t method|%s|%s " ,
FixitGetLocation ( parser , insertPos ) . c_str ( ) , insertStr . c_str ( ) ) . c_str ( ) ) ) ;
}
}
2020-02-05 17:07:23 -08:00
}
2020-02-07 08:44:06 -08:00
}
2020-02-05 17:07:23 -08:00
}
}
2019-08-23 11:56:54 -07:00
void BfAutoComplete : : FixitAddMember ( BfTypeInstance * typeInst , BfType * fieldType , const StringImpl & fieldName , bool isStatic , BfTypeInstance * referencedFrom )
{
if ( typeInst = = mModule - > mContext - > mBfObjectType )
return ;
2022-02-02 08:00:55 -05:00
auto parser = typeInst - > mTypeDef - > GetDefinition ( ) - > mSource - > ToParser ( ) ;
2019-08-23 11:56:54 -07:00
if ( parser = = NULL )
return ;
String fullName = typeInst - > mTypeDef - > mFullName . ToString ( ) ;
String fieldStr ;
if ( typeInst = = referencedFrom )
{
// Implicitly private
}
else if ( ( referencedFrom ! = NULL ) & & ( mModule - > TypeIsSubTypeOf ( referencedFrom , typeInst ) ) )
{
fieldStr + = " protected " ;
}
else
{
fieldStr + = " public " ;
}
if ( isStatic )
fieldStr + = " static " ;
if ( fieldType ! = NULL )
fieldStr + = mModule - > TypeToString ( fieldType , BfTypeNameFlag_ReduceName ) ;
else
fieldStr + = " Object " ;
fieldStr + = " " + fieldName + " ; " ;
int fileLoc = typeInst - > mTypeDef - > mTypeDeclaration - > GetSrcEnd ( ) ;
if ( auto defineBlock = BfNodeDynCast < BfBlock > ( typeInst - > mTypeDef - > mTypeDeclaration - > mDefineNode ) )
fileLoc = BfFixitFinder : : FindLineStartAfter ( defineBlock - > mOpenBrace ) ;
if ( ! typeInst - > mTypeDef - > mFields . empty ( ) )
{
auto fieldDecl = typeInst - > mTypeDef - > mFields . back ( ) - > mFieldDeclaration ;
if ( fieldDecl ! = NULL )
{
fileLoc = BfFixitFinder : : FindLineStartAfter ( fieldDecl ) ;
}
}
2020-02-08 06:13:48 -08:00
const char * memberName = " field " ;
if ( isStatic )
memberName = " static field " ;
AddEntry ( AutoCompleteEntry ( " fixit " , StrFormat ( " Create %s '%s' in '%s' \t addField|%s||%s " , memberName , fieldName . c_str ( ) , fullName . c_str ( ) ,
2020-02-07 08:44:06 -08:00
FixitGetLocation ( parser - > mParserData , fileLoc ) . c_str ( ) , fieldStr . c_str ( ) ) . c_str ( ) ) ) ;
2020-02-06 16:47:37 -08:00
}
void BfAutoComplete : : FixitAddCase ( BfTypeInstance * typeInst , const StringImpl & caseName , const BfTypeVector & fieldTypes )
{
if ( typeInst = = mModule - > mContext - > mBfObjectType )
return ;
2022-02-02 08:00:55 -05:00
auto parser = typeInst - > mTypeDef - > GetDefinition ( ) - > mSource - > ToParser ( ) ;
2020-02-06 16:47:37 -08:00
if ( parser = = NULL )
return ;
String fullName = typeInst - > mTypeDef - > mFullName . ToString ( ) ;
String fieldStr ;
int fileLoc = typeInst - > mTypeDef - > mTypeDeclaration - > GetSrcEnd ( ) ;
if ( auto defineBlock = BfNodeDynCast < BfBlock > ( typeInst - > mTypeDef - > mTypeDeclaration - > mDefineNode ) )
fileLoc = BfFixitFinder : : FindLineStartAfter ( defineBlock - > mOpenBrace ) ;
if ( ! typeInst - > mTypeDef - > mFields . empty ( ) )
{
auto fieldDecl = typeInst - > mTypeDef - > mFields . back ( ) - > mFieldDeclaration ;
if ( fieldDecl ! = NULL )
{
fileLoc = BfFixitFinder : : FindLineStartAfter ( fieldDecl ) ;
}
}
2022-07-26 13:27:03 -04:00
bool isSimpleCase = false ;
2020-02-06 16:47:37 -08:00
if ( ! typeInst - > mTypeDef - > mFields . IsEmpty ( ) )
2022-07-26 13:27:03 -04:00
{
2020-02-06 16:47:37 -08:00
if ( auto block = BfNodeDynCast < BfBlock > ( typeInst - > mTypeDef - > mTypeDeclaration - > mDefineNode ) )
{
bool endsInComma = false ;
if ( ! block - > mChildArr . IsEmpty ( ) )
2022-07-26 13:27:03 -04:00
{
auto lastNode = block - > mChildArr . back ( ) ;
2020-02-06 16:47:37 -08:00
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( lastNode ) )
{
if ( tokenNode - > mToken = = BfToken_Comma )
{
isSimpleCase = true ;
endsInComma = true ;
}
}
else if ( auto enumEntryDecl = BfNodeDynCast < BfEnumEntryDeclaration > ( lastNode ) )
{
isSimpleCase = true ;
}
}
if ( isSimpleCase )
{
if ( endsInComma )
{
fieldStr + = " | " ;
fieldStr + = caseName ;
}
else
{
auto fieldDef = typeInst - > mTypeDef - > mFields . back ( ) ;
fileLoc = fieldDef - > mFieldDeclaration - > GetSrcEnd ( ) ;
fieldStr + = " , \r " ;
fieldStr + = caseName ;
}
}
}
}
2022-07-26 13:27:03 -04:00
if ( ! isSimpleCase )
2020-02-06 16:47:37 -08:00
{
fieldStr + = " |case " ;
fieldStr + = caseName ;
if ( ! fieldTypes . IsEmpty ( ) )
{
fieldStr + = " ( " ;
2022-07-26 13:27:03 -04:00
FixitGetParamString ( fieldTypes , fieldStr ) ;
2020-02-06 16:47:37 -08:00
fieldStr + = " ) " ;
}
fieldStr + = " ; " ;
2022-07-26 13:27:03 -04:00
}
2020-02-06 16:47:37 -08:00
2022-07-26 13:27:03 -04:00
AddEntry ( AutoCompleteEntry ( " fixit " , StrFormat ( " Create case '%s' in '%s' \t addField|%s|%s " , caseName . c_str ( ) , fullName . c_str ( ) ,
2020-02-07 08:44:06 -08:00
FixitGetLocation ( parser - > mParserData , fileLoc ) . c_str ( ) , fieldStr . c_str ( ) ) . c_str ( ) ) ) ;
2020-02-06 16:47:37 -08:00
}
void BfAutoComplete : : FixitGetParamString ( const BfTypeVector & paramTypes , StringImpl & outStr )
{
std : : set < String > usedNames ;
for ( int argIdx = 0 ; argIdx < ( int ) paramTypes . size ( ) ; argIdx + + )
{
if ( argIdx > 0 )
outStr + = " , " ;
BfType * paramType = paramTypes [ argIdx ] ;
String checkName = " param " ;
if ( paramType ! = NULL )
{
bool isOut = false ;
bool isArr = false ;
BfType * checkType = paramType ;
while ( true )
{
if ( ( checkType - > IsArray ( ) ) | | ( checkType - > IsSizedArray ( ) ) )
{
isArr = true ;
checkType = checkType - > GetUnderlyingType ( ) ;
}
else if ( checkType - > IsRef ( ) )
{
BfRefType * refType = ( BfRefType * ) checkType ;
if ( refType - > mRefKind = = BfRefType : : RefKind_Out )
isOut = true ;
checkType = refType - > GetUnderlyingType ( ) ;
}
else if ( checkType - > IsTypeInstance ( ) )
{
BfTypeInstance * typeInst = ( BfTypeInstance * ) checkType ;
checkName = typeInst - > mTypeDef - > mName - > ToString ( ) ;
if ( checkName = = " String " )
checkName = " Str " ;
if ( checkName = = " Object " )
checkName = " Obj " ;
if ( isOut )
checkName = " out " + checkName ;
else if ( isupper ( checkName [ 0 ] ) )
2020-02-07 08:44:06 -08:00
{
2020-02-06 16:47:37 -08:00
checkName [ 0 ] = tolower ( checkName [ 0 ] ) ;
2020-02-07 08:44:06 -08:00
for ( int i = 1 ; i < ( int ) checkName . length ( ) ; i + + )
2022-07-26 13:27:03 -04:00
{
2020-02-07 08:44:06 -08:00
if ( ( i + 1 < ( int ) checkName . length ( ) ) & &
( islower ( checkName [ i + 1 ] ) ) )
break ;
checkName [ i ] = tolower ( checkName [ i ] ) ;
}
}
2020-02-06 16:47:37 -08:00
if ( isArr )
checkName + = " Arr " ;
break ;
}
else
break ;
}
outStr + = mModule - > TypeToString ( paramType , BfTypeNameFlag_ReduceName ) ;
}
else
{
checkName = " param " ;
outStr + = " Object " ;
}
for ( int i = 1 ; i < 10 ; i + + )
{
String lookupName = checkName ;
if ( i > 1 )
lookupName + = StrFormat ( " %d " , i ) ;
if ( usedNames . insert ( lookupName ) . second )
{
outStr + = " " + lookupName ;
break ;
}
}
}
}
2020-02-07 08:44:06 -08:00
String BfAutoComplete : : FixitGetLocation ( BfParserData * parser , int insertPos )
{
int line = 0 ;
int lineChar = 0 ;
parser - > GetLineCharAtIdx ( insertPos , line , lineChar ) ;
return StrFormat ( " %s|%d:%d " , parser - > mFileName . c_str ( ) , line , lineChar ) ;
}
2024-12-31 07:48:03 -08:00
String BfAutoComplete : : ConstantToString ( BfIRConstHolder * constHolder , BfTypedValue typedValue )
2020-05-17 06:10:56 -07:00
{
2024-12-31 07:48:03 -08:00
SetAndRestoreValue < BfTypeInstance * > prevTypeInst ( mModule - > mCurTypeInstance , typedValue . mType - > ToTypeInstance ( ) ) ;
SetAndRestoreValue < BfMethodInstance * > prevMethodInst ( mModule - > mCurMethodInstance , NULL ) ;
BF_ASSERT ( typedValue . mValue . IsConst ( ) ) ;
String result ;
result = " ( " ;
result + = mModule - > TypeToString ( typedValue . mType ) ;
result + = " ) " ;
2020-05-17 06:10:56 -07:00
char str [ 32 ] ;
2022-07-26 13:27:03 -04:00
2024-12-31 07:48:03 -08:00
int stringId = mModule - > GetStringPoolIdx ( typedValue . mValue , constHolder ) ;
2020-05-17 06:10:56 -07:00
if ( stringId ! = - 1 )
{
BfStringPoolEntry * entry ;
if ( mModule - > mContext - > mStringObjectIdMap . TryGetValue ( stringId , & entry ) )
{
2022-07-26 13:27:03 -04:00
String result = " \" " ;
2020-05-17 06:10:56 -07:00
result + = SlashString ( entry - > mString , true , true , true ) ;
result + = " \" " ;
return result ;
2022-07-26 13:27:03 -04:00
}
2020-05-17 06:10:56 -07:00
}
2022-07-26 13:27:03 -04:00
2024-12-31 07:48:03 -08:00
auto constant = constHolder - > GetConstant ( typedValue . mValue ) ;
2020-05-17 06:10:56 -07:00
switch ( constant - > mTypeCode )
{
2022-05-30 11:40:49 -07:00
case BfTypeCode_Boolean :
2024-12-31 07:48:03 -08:00
result + = StrFormat ( " %s " , constant - > mBool ? " true " : " false " ) ;
break ;
2020-05-17 06:10:56 -07:00
case BfTypeCode_UInt8 :
2024-12-31 07:48:03 -08:00
result + = StrFormat ( " %llu " , constant - > mUInt64 ) ;
break ;
2020-05-17 06:10:56 -07:00
case BfTypeCode_UInt16 :
2024-12-31 07:48:03 -08:00
result + = StrFormat ( " %llu " , constant - > mUInt64 ) ;
break ;
2020-05-17 06:10:56 -07:00
case BfTypeCode_UInt32 :
2024-12-31 07:48:03 -08:00
result + = StrFormat ( " %llu " , constant - > mUInt64 ) ;
break ;
2020-05-17 06:10:56 -07:00
case BfTypeCode_UInt64 :
2024-12-31 07:48:03 -08:00
result + = StrFormat ( " %llu " , constant - > mUInt64 ) ;
break ;
2020-05-17 06:10:56 -07:00
case BfTypeCode_Int8 :
2024-12-31 07:48:03 -08:00
result + = StrFormat ( " %lld " , constant - > mInt64 ) ;
break ;
2020-05-17 06:10:56 -07:00
case BfTypeCode_Int16 :
2024-12-31 07:48:03 -08:00
result + = StrFormat ( " %lld " , constant - > mInt64 ) ;
break ;
2020-05-17 06:10:56 -07:00
case BfTypeCode_Int32 :
2024-12-31 07:48:03 -08:00
result + = StrFormat ( " %lld " , constant - > mInt64 ) ;
break ;
2020-05-17 06:10:56 -07:00
case BfTypeCode_Int64 :
2024-12-31 07:48:03 -08:00
result + = StrFormat ( " %lld " , constant - > mInt64 ) ;
2020-05-21 06:58:26 -07:00
break ;
2024-12-31 07:48:03 -08:00
case BfTypeCode_Float :
ExactMinimalFloatToStr ( ( float ) constant - > mDouble , str ) ;
result + = " " ;
result + = str ;
result + = " f " ;
break ;
case BfTypeCode_Double :
ExactMinimalDoubleToStr ( constant - > mDouble , str ) ;
result + = " " ;
result + = str ;
break ;
default :
return " " ;
2020-05-17 06:10:56 -07:00
}
2024-12-31 07:48:03 -08:00
return result ;
2020-05-17 06:10:56 -07:00
}
2020-02-06 16:47:37 -08:00
void BfAutoComplete : : FixitAddMethod ( BfTypeInstance * typeInst , const StringImpl & methodName , BfType * returnType , const BfTypeVector & paramTypes , bool wantStatic )
{
if ( ( typeInst - > IsEnum ( ) ) & & ( returnType = = typeInst ) & & ( wantStatic ) )
{
FixitAddCase ( typeInst , methodName , paramTypes ) ;
return ;
}
if ( ( typeInst - > mTypeDef - > mSource ! = NULL ) & & ( typeInst ! = mModule - > mContext - > mBfObjectType ) )
{
2022-02-02 08:00:55 -05:00
auto parser = typeInst - > mTypeDef - > GetDefinition ( ) - > mSource - > ToParser ( ) ;
2020-02-06 16:47:37 -08:00
if ( parser ! = NULL )
{
String fullName = typeInst - > mTypeDef - > mFullName . ToString ( ) ;
String methodStr ;
2020-02-07 08:44:06 -08:00
methodStr + = " \f \a " ;
2020-02-06 16:47:37 -08:00
if ( typeInst = = mModule - > mCurTypeInstance )
{
// Implicitly private
}
else if ( mModule - > TypeIsSubTypeOf ( mModule - > mCurTypeInstance , typeInst ) )
{
methodStr + = " protected " ;
}
else
{
methodStr + = " public " ;
}
if ( wantStatic )
methodStr + = " static " ;
if ( returnType ! = NULL )
methodStr + = mModule - > TypeToString ( returnType , BfTypeNameFlag_ReduceName ) ;
else
methodStr + = " void " ;
methodStr + = " " + methodName + " ( " ;
FixitGetParamString ( paramTypes , methodStr ) ;
2020-02-07 08:44:06 -08:00
int insertPos = FixitGetMemberInsertPos ( typeInst - > mTypeDef ) ;
2020-02-06 16:47:37 -08:00
methodStr + = " ) " ;
2020-02-07 08:44:06 -08:00
methodStr + = " \t " ;
AddEntry ( AutoCompleteEntry ( " fixit " , StrFormat ( " Create method '%s' in '%s' \t addMethod|%s|%s " , methodName . c_str ( ) , fullName . c_str ( ) , FixitGetLocation ( parser - > mParserData , insertPos ) . c_str ( ) , methodStr . c_str ( ) ) . c_str ( ) ) ) ;
2020-02-06 16:47:37 -08:00
}
}
2020-02-07 08:44:06 -08:00
}
2020-03-21 13:09:42 -07:00
void BfAutoComplete : : FixitAddNamespace ( BfAstNode * refNode , const StringImpl & namespaceStr )
{
auto parserData = refNode - > GetParserData ( ) ;
BfUsingFinder usingFinder ;
2022-06-01 16:36:58 -07:00
usingFinder . mFromIdx = refNode - > mSrcStart ;
2020-03-21 13:09:42 -07:00
usingFinder . VisitMembers ( refNode - > GetSourceData ( ) - > mRootNode ) ;
2020-09-05 05:39:51 -07:00
AddEntry ( AutoCompleteEntry ( " fixit " , StrFormat ( " using %s; \t .using|%s|%d||using %s; " , namespaceStr . c_str ( ) , parserData - > mFileName . c_str ( ) ,
2020-03-21 13:09:42 -07:00
usingFinder . mLastIdx , namespaceStr . c_str ( ) ) . c_str ( ) ) ) ;
}
2020-09-11 14:01:40 -07:00
void BfAutoComplete : : FixitCheckNamespace ( BfTypeDef * activeTypeDef , BfAstNode * typeRef , BfTokenNode * nextDotToken )
2020-02-07 08:44:06 -08:00
{
if ( nextDotToken = = NULL )
return ;
auto parserData = typeRef - > GetParserData ( ) ;
BfSizedAtomComposite namespaceComposite ;
String namespaceString = typeRef - > ToString ( ) ;
bool isValid = mSystem - > ParseAtomComposite ( namespaceString , namespaceComposite ) ;
2022-07-26 13:27:03 -04:00
2020-02-07 08:44:06 -08:00
bool hasNamespace = false ;
if ( activeTypeDef ! = NULL )
hasNamespace = activeTypeDef - > mNamespaceSearch . Contains ( namespaceComposite ) ;
if ( hasNamespace )
{
AddEntry ( AutoCompleteEntry ( " fixit " , StrFormat ( " Remove unneeded '%s' \t addMethod|%s-%d| " , typeRef - > ToString ( ) . c_str ( ) ,
FixitGetLocation ( parserData , typeRef - > GetSrcStart ( ) ) . c_str ( ) , nextDotToken - > GetSrcEnd ( ) - typeRef - > GetSrcStart ( ) ) . c_str ( ) ) ) ;
}
else
2022-07-26 13:27:03 -04:00
{
2020-03-21 13:09:42 -07:00
FixitAddNamespace ( typeRef , namespaceString ) ;
2020-02-07 08:44:06 -08:00
}
}
2020-09-03 09:31:22 -07:00
2020-09-19 15:36:25 -07:00
void BfAutoComplete : : FixitAddConstructor ( BfTypeInstance * typeInstance )
{
auto baseType = typeInstance - > mBaseType ;
2022-02-02 08:00:55 -05:00
auto parser = typeInstance - > mTypeDef - > GetDefinition ( ) - > mSource - > ToParser ( ) ;
2020-09-19 15:36:25 -07:00
if ( parser ! = NULL )
{
for ( auto methodDef : baseType - > mTypeDef - > mMethods )
{
if ( methodDef - > mMethodType ! = BfMethodType_Ctor )
continue ;
if ( methodDef - > mIsStatic )
continue ;
if ( methodDef - > mProtection < = BfProtection_Private )
continue ;
auto methodInstance = mModule - > GetRawMethodInstanceAtIdx ( baseType , methodDef - > mIdx ) ;
String ctorShowName ;
2022-07-26 13:27:03 -04:00
2020-09-19 15:36:25 -07:00
int insertPos = FixitGetMemberInsertPos ( mModule - > mCurTypeInstance - > mTypeDef ) ;
String methodStr = " \f \a " ;
2020-12-28 05:15:47 -08:00
if ( methodInstance - > mMethodDef - > mHasAppend )
methodStr + = " [AllowAppend] \r " ;
2020-09-19 15:36:25 -07:00
methodStr + = " public this( " ;
2020-12-28 05:15:47 -08:00
int useParamIdx = 0 ;
2020-09-19 15:36:25 -07:00
for ( int paramIdx = 0 ; paramIdx < methodInstance - > GetParamCount ( ) ; paramIdx + + )
{
2020-12-28 05:15:47 -08:00
if ( useParamIdx > 0 )
2020-09-19 15:36:25 -07:00
methodStr + = " , " ;
2020-12-28 05:15:47 -08:00
auto paramKind = methodInstance - > GetParamKind ( paramIdx ) ;
if ( paramKind = = BfParamKind_AppendIdx )
continue ;
switch ( paramKind )
2020-09-19 15:36:25 -07:00
{
case BfParamKind_Params :
methodStr + = " params " ;
2020-09-29 08:53:36 -07:00
break ;
2022-07-26 13:27:03 -04:00
default :
2020-09-29 08:53:36 -07:00
break ;
2020-09-19 15:36:25 -07:00
}
methodStr + = mModule - > TypeToString ( methodInstance - > GetParamType ( paramIdx ) , BfTypeNameFlag_ReduceName ) ;
methodStr + = " " ;
methodStr + = methodInstance - > GetParamName ( paramIdx ) ;
2020-12-28 05:15:47 -08:00
useParamIdx + + ;
2020-09-19 15:36:25 -07:00
}
2022-07-26 13:27:03 -04:00
methodStr + = " ) : base( " ;
2020-09-19 15:36:25 -07:00
ctorShowName + = " this( " ;
2020-12-28 05:15:47 -08:00
useParamIdx = 0 ;
2020-09-19 15:36:25 -07:00
for ( int paramIdx = 0 ; paramIdx < methodInstance - > GetParamCount ( ) ; paramIdx + + )
{
2020-12-28 05:15:47 -08:00
if ( useParamIdx > 0 )
2020-09-19 15:36:25 -07:00
{
ctorShowName + = " , " ;
methodStr + = " , " ;
}
2020-12-28 05:15:47 -08:00
auto paramKind = methodInstance - > GetParamKind ( paramIdx ) ;
if ( paramKind = = BfParamKind_AppendIdx )
continue ;
switch ( paramKind )
2020-09-19 15:36:25 -07:00
{
case BfParamKind_Params :
methodStr + = " params " ;
2020-09-29 08:53:36 -07:00
break ;
default :
break ;
2020-09-19 15:36:25 -07:00
}
auto paramType = methodInstance - > GetParamType ( paramIdx ) ;
if ( paramType - > IsRef ( ) )
{
switch ( ( ( BfRefType * ) paramType ) - > mRefKind )
{
case BfRefType : : RefKind_Ref : methodStr + = " ref " ; break ;
case BfRefType : : RefKind_Out : methodStr + = " out " ; break ;
case BfRefType : : RefKind_Mut : methodStr + = " mut " ; break ;
}
}
methodStr + = methodInstance - > GetParamName ( paramIdx ) ;
ctorShowName + = methodInstance - > GetParamName ( paramIdx ) ;
2020-12-28 05:15:47 -08:00
useParamIdx + + ;
2020-09-19 15:36:25 -07:00
}
ctorShowName + = " ) " ;
methodStr + = " ) \t " ;
AddEntry ( AutoCompleteEntry ( " fixit " , StrFormat ( " Create constructor '%s' \t addMethod|%s|%s " , ctorShowName . c_str ( ) ,
FixitGetLocation ( parser - > mParserData , insertPos ) . c_str ( ) , methodStr . c_str ( ) ) . c_str ( ) ) ) ;
}
}
}
2024-12-31 07:48:03 -08:00
void BfAutoComplete : : AddResultTypeKind ( BfType * type )
2020-09-03 09:31:22 -07:00
{
if ( type - > IsObject ( ) )
mResultString + = " \n :type \t class " ;
else if ( type - > IsInterface ( ) )
mResultString + = " \n :type \t interface " ;
else if ( type - > IsPointer ( ) )
mResultString + = " \n :type \t pointer " ;
else
mResultString + = " \n :type \t valuetype " ;
}
2022-07-10 07:50:08 -04:00
2024-12-31 07:48:03 -08:00
void BfAutoComplete : : SetResultStringType ( BfType * type )
{
SetAndRestoreValue < BfTypeInstance * > prevTypeInst ( mModule - > mCurTypeInstance , type - > ToTypeInstance ( ) ) ;
SetAndRestoreValue < BfMethodInstance * > prevMethodInst ( mModule - > mCurMethodInstance , NULL ) ;
mResultString = " : " ;
mResultString + = mModule - > TypeToString ( type ) ;
AddResultTypeKind ( type ) ;
}
2022-07-10 07:50:08 -04:00
void BfAutoComplete : : FixitAddFullyQualify ( BfAstNode * refNode , const StringImpl & findName , const SizedArrayImpl < BfUsingFieldData : : MemberRef > & foundList )
{
BfProtectionCheckFlags protectionCheckFlags = BfProtectionCheckFlag_None ;
String fullName ;
for ( int entryIdx = 0 ; entryIdx < foundList . mSize - 1 ; entryIdx + + )
{
auto & entry = foundList [ entryIdx ] ;
2022-07-26 13:27:03 -04:00
if ( entryIdx > 0 )
fullName + = " . " ;
if ( ! mModule - > CheckProtection ( protectionCheckFlags , entry . mTypeInstance , entry . GetDeclaringType ( mModule ) - > mProject , entry . GetProtection ( ) , mModule - > mCurTypeInstance ) )
fullName + = " [Friend] " ;
2022-07-10 07:50:08 -04:00
fullName + = entry . GetName ( mModule ) ;
}
BfParserData * parser = refNode - > GetSourceData ( ) - > ToParserData ( ) ;
if ( parser ! = NULL )
{
AddEntry ( AutoCompleteEntry ( " fixit " , StrFormat ( " Fully qualify 'using' name as '%s.%s' \t qualify|%s|%d|%s. " ,
fullName . c_str ( ) , findName . c_str ( ) ,
parser - > mFileName . c_str ( ) , refNode - > mSrcStart ,
fullName . c_str ( ) ) . c_str ( ) ) ) ;
}
2022-07-26 13:27:03 -04:00
}