From c9da45715b4fdd67739b9b8cd0f72a826b97a33c Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Fri, 29 May 2020 16:58:47 -0700 Subject: [PATCH] Added ability to rename labels and goto definition on labels --- IDEHelper/Compiler/BfAutoComplete.cpp | 38 ++++++++++++++++++-- IDEHelper/Compiler/BfAutoComplete.h | 4 +-- IDEHelper/Compiler/BfExprEvaluator.cpp | 7 ++++ IDEHelper/Compiler/BfModule.cpp | 8 +++++ IDEHelper/Compiler/BfModule.h | 8 +++-- IDEHelper/Compiler/BfStmtEvaluator.cpp | 50 ++++++++++++++------------ 6 files changed, 86 insertions(+), 29 deletions(-) diff --git a/IDEHelper/Compiler/BfAutoComplete.cpp b/IDEHelper/Compiler/BfAutoComplete.cpp index 36271675..2cb0fa17 100644 --- a/IDEHelper/Compiler/BfAutoComplete.cpp +++ b/IDEHelper/Compiler/BfAutoComplete.cpp @@ -2434,7 +2434,7 @@ void BfAutoComplete::CheckLocalRef(BfAstNode* identifierNode, BfLocalVariable* v { mInsertStartIdx = identifierNode->GetSrcStart(); mInsertEndIdx = identifierNode->GetSrcEnd(); - } + } } } else if (mResolveType == BfResolveType_GetResultString) @@ -2489,13 +2489,47 @@ void BfAutoComplete::CheckFieldRef(BfAstNode* identifierNode, BfFieldInstance* f } } -void BfAutoComplete::CheckLabel(BfAstNode* identifierNode, BfAstNode* precedingNode) +void BfAutoComplete::CheckLabel(BfIdentifierNode* identifierNode, BfAstNode* precedingNode, BfScopeData* scopeData) { String filter; if (identifierNode != NULL) { + if ((mModule->mCompiler->mResolvePassData != NULL) && (scopeData != NULL)) + { + auto rootMethodState = mModule->mCurMethodState->GetRootMethodState(); + mModule->mCompiler->mResolvePassData->HandleLocalReference(identifierNode, rootMethodState->mMethodInstance->GetOwner()->mTypeDef, rootMethodState->mMethodInstance->mMethodDef, scopeData->mScopeLocalId); + } + if (!IsAutocompleteNode(identifierNode)) return; + + 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; + } + filter = identifierNode->ToString(); mInsertStartIdx = identifierNode->GetSrcStart(); mInsertEndIdx = identifierNode->GetSrcEnd(); diff --git a/IDEHelper/Compiler/BfAutoComplete.h b/IDEHelper/Compiler/BfAutoComplete.h index c67ac7eb..0a56eed7 100644 --- a/IDEHelper/Compiler/BfAutoComplete.h +++ b/IDEHelper/Compiler/BfAutoComplete.h @@ -246,8 +246,8 @@ public: void CheckResult(BfAstNode* node, const BfTypedValue& typedValue); void CheckLocalDef(BfAstNode* identifierNode, BfLocalVariable* varDecl); void CheckLocalRef(BfAstNode* identifierNode, BfLocalVariable* varDecl); - void CheckFieldRef(BfAstNode* identifierNode, BfFieldInstance* fieldInst); - void CheckLabel(BfAstNode* identifierNode, BfAstNode* precedingNode = NULL); + void CheckFieldRef(BfAstNode* identifierNode, BfFieldInstance* fieldInst); + void CheckLabel(BfIdentifierNode* identifierNode, BfAstNode* precedingNode, BfScopeData* scopeData); void CheckEmptyStart(BfAstNode* prevNode, BfType* type); bool CheckFixit(BfAstNode* node); void CheckInterfaceFixit(BfTypeInstance* typeInstance, BfAstNode* node); diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index f2cbd8b4..620d9008 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -12964,7 +12964,14 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo { auto targetScope = mModule->FindScope(scopedInvocationTarget->mScopeName, curMethodState->mMixinState); if (targetScope != NULL) + { mixinState->mTargetScope = targetScope; + if (autoComplete != NULL) + { + if (auto identifer = BfNodeDynCast(scopedInvocationTarget->mScopeName)) + autoComplete->CheckLabel(identifer, NULL, targetScope); + } + } } mModule->mBfIRBuilder->SaveDebugLocation(); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 1e176104..b483c880 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -1654,8 +1654,16 @@ void BfModule::NewScopeState(bool createLexicalBlock, bool flushValueScope) { auto curScope = mCurMethodState->mCurScope; if (curScope->mLabelNode != NULL) + { curScope->mLabelNode->ToString(curScope->mLabel); + auto rootMethodState = mCurMethodState->GetRootMethodState(); + curScope->mScopeLocalId = rootMethodState->mCurLocalVarId++; + auto autoComplete = mCompiler->GetAutoComplete(); + if (autoComplete != NULL) + autoComplete->CheckLabel(curScope->mLabelNode, NULL, curScope); + } + if (!mCurMethodState->mCurScope->mLabel.IsEmpty()) { auto checkScope = mCurMethodState->mCurScope->mPrevScope; diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 919ce324..50e1611a 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -303,10 +303,11 @@ public: BfIRMDNode mDIScope; BfIRMDNode mDIInlinedAt; String mLabel; - BfAstNode* mLabelNode; + BfIdentifierNode* mLabelNode; int mLocalVarStart; int mScopeDepth; - int mMixinDepth; + int mMixinDepth; + int mScopeLocalId; bool mIsScopeHead; // For first scope data or for inlined start bool mIsLoop; bool mIsConditional; // Rarely set - usually we rely on OuterIsConditional or InnerIsConditional @@ -352,6 +353,7 @@ public: mAllowVariableDeclarations = true; mMixinDepth = 0; mScopeDepth = 0; + mScopeLocalId = -1; } ~BfScopeData() @@ -937,7 +939,7 @@ public: bool mAllowUinitReads; bool mCancelledDeferredCall; bool mNoObjectAccessChecks; - int mCurLocalVarId; + int mCurLocalVarId; // Can also refer to a label int mCurAccessId; // For checking to see if a block reads from or writes to a local public: diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 9341ead2..11544a43 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -4950,13 +4950,7 @@ void BfModule::Visit(BfYieldStatement* yieldStmt) void BfModule::Visit(BfBreakStatement* breakStmt) { bool inMixinDecl = (mCurMethodInstance != NULL) && (mCurMethodInstance->IsMixin()); - - if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL)) - { - if (auto identifer = BfNodeDynCast(breakStmt->mLabel)) - mCompiler->mResolvePassData->mAutoComplete->CheckLabel(identifer, breakStmt->mBreakNode); - } - + UpdateSrcPos(breakStmt); mBfIRBuilder->CreateEnsureInstructionAt(); @@ -4975,6 +4969,15 @@ void BfModule::Visit(BfBreakStatement* breakStmt) } } + if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL)) + { + BfScopeData* scope = NULL; + if (breakData != NULL) + scope = breakData->mScope; + if (auto identifer = BfNodeDynCast(breakStmt->mLabel)) + mCompiler->mResolvePassData->mAutoComplete->CheckLabel(identifer, breakStmt->mBreakNode, scope); + } + if ((breakData == NULL) || (!breakData->mIRBreakBlock)) { if (inMixinDecl) @@ -5038,13 +5041,7 @@ void BfModule::Visit(BfBreakStatement* breakStmt) void BfModule::Visit(BfContinueStatement* continueStmt) { bool inMixinDecl = (mCurMethodInstance != NULL) && (mCurMethodInstance->IsMixin()); - - if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL)) - { - if (auto identifer = BfNodeDynCast(continueStmt->mLabel)) - mCompiler->mResolvePassData->mAutoComplete->CheckLabel(identifer, continueStmt->mContinueNode); - } - + UpdateSrcPos(continueStmt); mBfIRBuilder->CreateEnsureInstructionAt(); @@ -5069,6 +5066,15 @@ void BfModule::Visit(BfContinueStatement* continueStmt) } } + if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL)) + { + BfScopeData* scope = NULL; + if (breakData != NULL) + scope = breakData->mScope; + if (auto identifer = BfNodeDynCast(continueStmt->mLabel)) + mCompiler->mResolvePassData->mAutoComplete->CheckLabel(identifer, continueStmt->mContinueNode, scope); + } + if ((breakData == NULL) || (!breakData->mIRContinueBlock)) { if (inMixinDecl) @@ -6489,14 +6495,7 @@ void BfModule::Visit(BfDeferStatement* deferStmt) UpdateSrcPos(deferStmt); EmitEnsureInstructionAt(); - - if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL)) - { - auto targetIdentifier = BfNodeDynCast(deferStmt->mScopeName); - if ((deferStmt->mScopeName == NULL) || (targetIdentifier != NULL)) - mCompiler->mResolvePassData->mAutoComplete->CheckLabel(targetIdentifier, deferStmt->mColonToken); - } - + BfScopeData* scope = NULL; if (deferStmt->mScopeToken != NULL) @@ -6511,6 +6510,13 @@ void BfModule::Visit(BfDeferStatement* deferStmt) else scope = mCurMethodState->mCurScope; + if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL)) + { + auto targetIdentifier = BfNodeDynCast(deferStmt->mScopeName); + if ((deferStmt->mScopeName == NULL) || (targetIdentifier != NULL)) + mCompiler->mResolvePassData->mAutoComplete->CheckLabel(targetIdentifier, deferStmt->mColonToken, scope); + } + if ((scope == mCurMethodState->mCurScope) && (scope->mCloseNode == NULL)) { Warn(0, "This defer will immediately execute. Consider specifying a wider scope target such as 'defer::'", deferStmt->mDeferToken);