From e16e4613b691f8cf8c458aa65125cb06eff0dab1 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Tue, 26 May 2020 06:10:51 -0700 Subject: [PATCH] Better handling of autocomplete with tokens --- IDEHelper/Compiler/BfAst.cpp | 5 ++ IDEHelper/Compiler/BfAst.h | 19 ++++---- IDEHelper/Compiler/BfAutoComplete.cpp | 14 +++--- IDEHelper/Compiler/BfAutoComplete.h | 16 +++--- IDEHelper/Compiler/BfElementVisitor.cpp | 5 ++ IDEHelper/Compiler/BfElementVisitor.h | 2 +- IDEHelper/Compiler/BfExprEvaluator.cpp | 14 +++++- IDEHelper/Compiler/BfExprEvaluator.h | 1 + IDEHelper/Compiler/BfPrinter.cpp | 8 ++- IDEHelper/Compiler/BfReducer.cpp | 65 ++++++++++++------------- IDEHelper/Compiler/BfReducer.h | 1 + IDEHelper/Compiler/BfSource.cpp | 8 ++- IDEHelper/Compiler/BfSource.h | 1 + IDEHelper/Compiler/BfStmtEvaluator.cpp | 14 +++++- 14 files changed, 108 insertions(+), 65 deletions(-) diff --git a/IDEHelper/Compiler/BfAst.cpp b/IDEHelper/Compiler/BfAst.cpp index 36e4af9a..81195c61 100644 --- a/IDEHelper/Compiler/BfAst.cpp +++ b/IDEHelper/Compiler/BfAst.cpp @@ -51,6 +51,11 @@ void BfStructuralVisitor::Visit(BfLabeledBlock* labeledBlock) Visit(labeledBlock->ToBase()); } +void BfStructuralVisitor::Visit(BfErrorNode* bfErrorNode) +{ + Visit(bfErrorNode->ToBase()); +} + void BfStructuralVisitor::Visit(BfScopeNode* scopeNode) { Visit(scopeNode->ToBase()); diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index 31f0860f..59ece5bc 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -399,7 +399,7 @@ public: BfStructuralVisitor(); virtual void Visit(BfAstNode* bfAstNode) {} - virtual void Visit(BfErrorNode* bfErrorNode) {} + virtual void Visit(BfErrorNode* bfErrorNode); virtual void Visit(BfScopeNode* scopeNode); virtual void Visit(BfNewNode* newNode); virtual void Visit(BfLabeledBlock* labeledBlock); @@ -1461,15 +1461,6 @@ T* BfNodeDynCastExact(BfAstNode* node) BfIdentifierNode* BfIdentifierCast(BfAstNode* node); BfAstNode* BfNodeToNonTemporary(BfAstNode* node); -class BfErrorNode : public BfAstNode -{ -public: - BF_AST_TYPE(BfErrorNode, BfAstNode); - - BfAstNode* mRefNode; -}; BF_AST_DECL(BfErrorNode, BfAstNode); - - class BfStatement : public BfAstNode { public: @@ -1496,6 +1487,14 @@ public: bool VerifyIsStatement(BfPassInstance* passInstance, bool ignoreError = false); }; BF_AST_DECL(BfExpression, BfAstNode); +class BfErrorNode : public BfExpression +{ +public: + BF_AST_TYPE(BfErrorNode, BfExpression); + + BfAstNode* mRefNode; +}; BF_AST_DECL(BfErrorNode, BfExpression); + class BfExpressionStatement : public BfStatement { public: diff --git a/IDEHelper/Compiler/BfAutoComplete.cpp b/IDEHelper/Compiler/BfAutoComplete.cpp index 2303f58e..fef1e946 100644 --- a/IDEHelper/Compiler/BfAutoComplete.cpp +++ b/IDEHelper/Compiler/BfAutoComplete.cpp @@ -921,7 +921,7 @@ void BfAutoComplete::AddEnumTypeMembers(BfTypeInstance* typeInst, const StringIm // return IsInExpression(node->mParent); // } -void BfAutoComplete::AddTopLevelNamespaces(BfIdentifierNode* identifierNode) +void BfAutoComplete::AddTopLevelNamespaces(BfAstNode* identifierNode) { String filter; if (identifierNode != NULL) @@ -964,7 +964,7 @@ void BfAutoComplete::AddTopLevelNamespaces(BfIdentifierNode* identifierNode) } } -void BfAutoComplete::AddTopLevelTypes(BfIdentifierNode* identifierNode, bool onlyAttribute) +void BfAutoComplete::AddTopLevelTypes(BfAstNode* identifierNode, bool onlyAttribute) { String filter; @@ -1144,7 +1144,7 @@ void BfAutoComplete::AddTopLevelTypes(BfIdentifierNode* identifierNode, bool onl } } -void BfAutoComplete::CheckIdentifier(BfIdentifierNode* identifierNode, bool isInExpression, bool isUsingDirective) +void BfAutoComplete::CheckIdentifier(BfAstNode* identifierNode, bool isInExpression, bool isUsingDirective) { if ((identifierNode != NULL) && (!IsAutocompleteNode(identifierNode))) return; @@ -2335,12 +2335,12 @@ void BfAutoComplete::CheckResult(BfAstNode* node, const BfTypedValue& typedValue } } -void BfAutoComplete::CheckLocalDef(BfIdentifierNode* identifierNode, BfLocalVariable* varDecl) +void BfAutoComplete::CheckLocalDef(BfAstNode* identifierNode, BfLocalVariable* varDecl) { CheckLocalRef(identifierNode, varDecl); } -void BfAutoComplete::CheckLocalRef(BfIdentifierNode* identifierNode, BfLocalVariable* varDecl) +void BfAutoComplete::CheckLocalRef(BfAstNode* identifierNode, BfLocalVariable* varDecl) { if (mReplaceLocalId != -1) return; @@ -2406,7 +2406,7 @@ void BfAutoComplete::CheckLocalRef(BfIdentifierNode* identifierNode, BfLocalVari } } -void BfAutoComplete::CheckFieldRef(BfIdentifierNode* identifierNode, BfFieldInstance* fieldInst) +void BfAutoComplete::CheckFieldRef(BfAstNode* identifierNode, BfFieldInstance* fieldInst) { if (mResolveType == BfResolveType_GetSymbolInfo) { @@ -2438,7 +2438,7 @@ void BfAutoComplete::CheckFieldRef(BfIdentifierNode* identifierNode, BfFieldInst } } -void BfAutoComplete::CheckLabel(BfIdentifierNode* identifierNode, BfAstNode* precedingNode) +void BfAutoComplete::CheckLabel(BfAstNode* identifierNode, BfAstNode* precedingNode) { String filter; if (identifierNode != NULL) diff --git a/IDEHelper/Compiler/BfAutoComplete.h b/IDEHelper/Compiler/BfAutoComplete.h index ec2134e9..c67ac7eb 100644 --- a/IDEHelper/Compiler/BfAutoComplete.h +++ b/IDEHelper/Compiler/BfAutoComplete.h @@ -175,7 +175,7 @@ public: BfAstNode* mGetDefinitionNode; BfResolveType mResolveType; BfTypeInstance* mShowAttributeProperties; - BfIdentifierNode* mIdentifierUsed; + BfAstNode* mIdentifierUsed; bool mIgnoreFixits; bool mHasFriendSet; bool mUncertain; // May be an unknown identifier, do not aggressively autocomplete @@ -212,8 +212,8 @@ public: void AddSelfResultTypeMembers(BfTypeInstance* typeInst, BfTypeInstance* selfType, const StringImpl& filter, bool allowPrivate); bool InitAutocomplete(BfAstNode* dotNode, BfAstNode* nameNode, String& filter); void AddEnumTypeMembers(BfTypeInstance* typeInst, const StringImpl& filter, bool allowProtected, bool allowPrivate); - void AddTopLevelNamespaces(BfIdentifierNode* identifierNode); - void AddTopLevelTypes(BfIdentifierNode* identifierNode, bool onlyAttribute = false); + void AddTopLevelNamespaces(BfAstNode* identifierNode); + void AddTopLevelTypes(BfAstNode* identifierNode, bool onlyAttribute = false); void AddOverrides(const StringImpl& filter); void UpdateReplaceData(); void AddTypeInstanceEntry(BfTypeInstance* typeInst); @@ -233,7 +233,7 @@ public: void RemoveMethodMatchInfo(); void ClearMethodMatchEntries(); - void CheckIdentifier(BfIdentifierNode* identifierNode, bool isInExpression = false, bool isUsingDirective = false); + void CheckIdentifier(BfAstNode* identifierNode, bool isInExpression = false, bool isUsingDirective = false); bool CheckMemberReference(BfAstNode* target, BfAstNode* dotToken, BfAstNode* memberName, bool onlyShowTypes = false, BfType* expectingType = NULL, bool isUsingDirective = false, bool onlyAttribute = false); bool CheckExplicitInterface(BfTypeInstance* interfaceType, BfAstNode* dotToken, BfAstNode* memberName); void CheckTypeRef(BfTypeReference* typeRef, bool mayBeIdentifier, bool isInExpression = false, bool onlyAttribute = false); @@ -244,10 +244,10 @@ public: void CheckProperty(BfPropertyDeclaration* propertyDeclaration); void CheckVarResolution(BfAstNode* varTypeRef, BfType* resolvedTypeRef); void CheckResult(BfAstNode* node, const BfTypedValue& typedValue); - void CheckLocalDef(BfIdentifierNode* identifierNode, BfLocalVariable* varDecl); - void CheckLocalRef(BfIdentifierNode* identifierNode, BfLocalVariable* varDecl); - void CheckFieldRef(BfIdentifierNode* identifierNode, BfFieldInstance* fieldInst); - void CheckLabel(BfIdentifierNode* identifierNode, BfAstNode* precedingNode = NULL); + 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 CheckEmptyStart(BfAstNode* prevNode, BfType* type); bool CheckFixit(BfAstNode* node); void CheckInterfaceFixit(BfTypeInstance* typeInstance, BfAstNode* node); diff --git a/IDEHelper/Compiler/BfElementVisitor.cpp b/IDEHelper/Compiler/BfElementVisitor.cpp index a73ba9a8..af97f643 100644 --- a/IDEHelper/Compiler/BfElementVisitor.cpp +++ b/IDEHelper/Compiler/BfElementVisitor.cpp @@ -125,6 +125,11 @@ void BfElementVisitor::Visit(BfLabelableStatement* labelableStmt) } } +void BfElementVisitor::Visit(BfErrorNode* bfErrorNode) +{ + Visit(bfErrorNode->mRefNode); +} + void BfElementVisitor::Visit(BfScopeNode* scopeNode) { Visit(scopeNode->ToBase()); diff --git a/IDEHelper/Compiler/BfElementVisitor.h b/IDEHelper/Compiler/BfElementVisitor.h index da9a042c..4d4a3dcf 100644 --- a/IDEHelper/Compiler/BfElementVisitor.h +++ b/IDEHelper/Compiler/BfElementVisitor.h @@ -10,7 +10,7 @@ public: BfElementVisitor(); virtual void Visit(BfAstNode* bfAstNode) {} - virtual void Visit(BfErrorNode* bfErrorNode) {} + virtual void Visit(BfErrorNode* bfErrorNode); virtual void Visit(BfScopeNode* scopeNode); virtual void Visit(BfNewNode* newNode); virtual void Visit(BfLabeledBlock* labeledBlock); diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 2ebb7c8d..df47e44a 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -2290,6 +2290,15 @@ void BfExprEvaluator::Evaluate(BfAstNode* astNode, bool propogateNullConditional } } +void BfExprEvaluator::Visit(BfErrorNode* errorNode) +{ + mModule->Fail("Invalid token", errorNode); + + auto autoComplete = GetAutoComplete(); + if (autoComplete != NULL) + autoComplete->CheckIdentifier(errorNode->mRefNode, true); +} + void BfExprEvaluator::Visit(BfTypeReference* typeRef) { mResult.mType = ResolveTypeRef(typeRef, BfPopulateType_Declaration); @@ -3583,7 +3592,10 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar bool isStaticCtor = (mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_Ctor) && (mModule->mCurMethodInstance->mMethodDef->mIsStatic); if ((field->mIsReadOnly) && (!isStaticCtor)) - retVal = mModule->LoadValue(retVal, NULL, mIsVolatileReference); + { + if (retVal.IsAddr()) + retVal.mKind = BfTypedValueKind_ReadOnlyAddr; + } else mIsHeapReference = true; return retVal; diff --git a/IDEHelper/Compiler/BfExprEvaluator.h b/IDEHelper/Compiler/BfExprEvaluator.h index 400e96fc..9fc75485 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.h +++ b/IDEHelper/Compiler/BfExprEvaluator.h @@ -405,6 +405,7 @@ public: ////////////////////////////////////////////////////////////////////////// + virtual void Visit(BfErrorNode* errorNode) override; virtual void Visit(BfTypeReference* typeRef) override; virtual void Visit(BfAttributedExpression* attribExpr) override; virtual void Visit(BfBlock* blockExpr) override; diff --git a/IDEHelper/Compiler/BfPrinter.cpp b/IDEHelper/Compiler/BfPrinter.cpp index 798b52c9..f5263492 100644 --- a/IDEHelper/Compiler/BfPrinter.cpp +++ b/IDEHelper/Compiler/BfPrinter.cpp @@ -2787,9 +2787,15 @@ void BfPrinter::Visit(BfRootNode* rootNode) child->Accept(this); } + // Flush whitespace at the end of the document BfParserData* bfParser = rootNode->GetSourceData()->ToParserData(); if (bfParser != NULL) - Write(rootNode, rootNode->GetSrcEnd(), bfParser->mSrcLength - rootNode->GetSrcEnd()); + { + BfAstNode endNode; + BfAstNode::Zero(&endNode); + endNode.Init(rootNode->GetSrcEnd(), rootNode->GetSrcEnd(), bfParser->mSrcLength - rootNode->GetSrcEnd()); + Visit(&endNode); + } if (mCharMapping != NULL) { diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index 1e0b0f17..9b62c1ef 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -1402,16 +1402,8 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat AssertCurrentNode(node); - /*if (auto block = BfNodeDynCast(node)) - { - HandleBlock(block, true); - return block; - }*/ - auto rhsCreateExprFlags = (CreateExprFlags)(createExprFlags & CreateExprFlags_BreakOnRChevron); - node = ReplaceTokenStarter(node); - auto exprLeft = BfNodeDynCast(node); AssertCurrentNode(node); @@ -2431,6 +2423,8 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat { if (nextTokenNode->GetToken() == BfToken_Dot) { + TryIdentifierConvert(checkIdx + 2); + auto nextNextCheckNode = mVisitorPos.Get(checkIdx + 2); if (auto identifierNode = BfNodeDynCast(nextNextCheckNode)) @@ -4265,8 +4259,6 @@ BfAstNode* BfReducer::CreateStatement(BfAstNode* node, CreateStmtFlags createStm { AssertCurrentNode(node); - node = ReplaceTokenStarter(node); - if ((createStmtFlags & CreateStmtFlags_AllowUnterminatedExpression) != 0) { if (IsTerminatingExpression(node)) @@ -5033,11 +5025,6 @@ BfTypeReference* BfReducer::CreateTypeRef(BfAstNode* firstNode, CreateTypeRefFla } return CreateRefTypeRef(typeRef, tokenNode); } - else if ((token == BfToken_In) || (token == BfToken_As)) - { - // This is mostly to allow a partially typed 'int' to be parsed as 'in' to make autocomplete nicer - return CreateTypeRef(ReplaceTokenStarter(firstNode), createTypeRefFlags); - } } return DoCreateTypeRef(firstNode, createTypeRefFlags); } @@ -5108,7 +5095,19 @@ BfIdentifierNode* BfReducer::CompactQualifiedName(BfAstNode* leftNode) auto nextNextToken = mVisitorPos.Get(mVisitorPos.mReadPos + 2); auto rightIdentifier = BfNodeDynCast(nextNextToken); if (rightIdentifier == NULL) - return leftIdentifier; + { + if (auto rightToken = BfNodeDynCast(nextNextToken)) + { + if (BfTokenIsKeyword(rightToken->mToken)) + { + rightIdentifier = mAlloc->Alloc(); + ReplaceNode(rightToken, rightIdentifier); + } + } + + if (rightIdentifier == NULL) + return leftIdentifier; + } // If the previous dotted span failed (IE: had chevrons) then don't insert qualified names in the middle of it auto prevNodeToken = BfNodeDynCast(prevNode); @@ -5131,6 +5130,20 @@ BfIdentifierNode* BfReducer::CompactQualifiedName(BfAstNode* leftNode) return leftIdentifier; } +void BfReducer::TryIdentifierConvert(int readPos) +{ + auto node = mVisitorPos.Get(readPos); + if (auto tokenNode = BfNodeDynCast(node)) + { + if (BfTokenIsKeyword(tokenNode->mToken)) + { + auto identifierNode = mAlloc->Alloc(); + ReplaceNode(tokenNode, identifierNode); + mVisitorPos.Set(readPos, identifierNode); + } + } +} + void BfReducer::CreateQualifiedNames(BfAstNode* node) { auto block = BfNodeDynCast(node); @@ -6266,8 +6279,6 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, int depth) AssertCurrentNode(node); - node = ReplaceTokenStarter(node); - BfTokenNode* refToken = NULL; if (auto tokenNode = BfNodeDynCast(node)) @@ -7583,7 +7594,7 @@ BfAstNode* BfReducer::HandleTopLevel(BfBlock* node) isDone = !mVisitorPos.MoveNext(); if (newNode != NULL) - mVisitorPos.Write(newNode); + mVisitorPos.Write(newNode); } mVisitorPos.Trim(); return node; @@ -9296,21 +9307,7 @@ void BfReducer::HandleBlock(BfBlock* block, bool allowEndingExpression) auto statement = CreateStatement(node, flags); if (statement == NULL) - { - auto nextNode = mVisitorPos.GetNext(); - isDone = !mVisitorPos.MoveNext(); -#ifdef BF_AST_HAS_PARENT_MEMBER - BF_ASSERT(node->mParent != NULL); -#endif - - node->RemoveSelf(); - BF_ASSERT(node->GetSourceData() == mSource->mSourceData); - mSource->AddErrorNode(node); - - if (nextNode == NULL) - break; - continue; - } + statement = mSource->CreateErrorNode(node); isDone = !mVisitorPos.MoveNext(); mVisitorPos.Write(statement); diff --git a/IDEHelper/Compiler/BfReducer.h b/IDEHelper/Compiler/BfReducer.h index 5fad8b32..1feb96b7 100644 --- a/IDEHelper/Compiler/BfReducer.h +++ b/IDEHelper/Compiler/BfReducer.h @@ -185,6 +185,7 @@ public: BfAstNode* ReadTypeMember(BfTokenNode* node, int depth = 0); BfAstNode* ReadTypeMember(BfAstNode* node, int depth = 0); BfIdentifierNode* CompactQualifiedName(BfAstNode* leftNode); + void TryIdentifierConvert(int readPos); void CreateQualifiedNames(BfAstNode* node); BfFieldDtorDeclaration* CreateFieldDtorDeclaration(BfAstNode* srcNode); BfFieldDeclaration* CreateFieldDeclaration(BfTokenNode* tokenNode, BfTypeReference* typeRef, BfIdentifierNode* nameIdentifier, BfFieldDeclaration* prevFieldDeclaration); diff --git a/IDEHelper/Compiler/BfSource.cpp b/IDEHelper/Compiler/BfSource.cpp index dc2e4788..03ec1cf4 100644 --- a/IDEHelper/Compiler/BfSource.cpp +++ b/IDEHelper/Compiler/BfSource.cpp @@ -58,7 +58,7 @@ bool BfSource::WantsStats() return ((int)parser->mFileName.IndexOf("main2.cs") != -1); } -void BfSource::AddErrorNode(BfAstNode* astNode) +BfErrorNode* BfSource::CreateErrorNode(BfAstNode* astNode) { BfErrorNode* errorNode = BfNodeDynCast(astNode); if (errorNode == NULL) @@ -67,8 +67,12 @@ void BfSource::AddErrorNode(BfAstNode* astNode) errorNode->Init(astNode->GetSrcStart(), astNode->GetSrcStart(), astNode->GetSrcEnd()); errorNode->mRefNode = astNode; } + return errorNode; +} - mPendingErrorNodes.push_back(errorNode); +void BfSource::AddErrorNode(BfAstNode* astNode) +{ + mPendingErrorNodes.push_back(CreateErrorNode(astNode)); } int BfSource::AllocChars(int charCount) diff --git a/IDEHelper/Compiler/BfSource.h b/IDEHelper/Compiler/BfSource.h index 6e79e24d..7c67206d 100644 --- a/IDEHelper/Compiler/BfSource.h +++ b/IDEHelper/Compiler/BfSource.h @@ -102,6 +102,7 @@ public: virtual BfParser* ToParser() { return NULL; } + BfErrorNode* BfSource::CreateErrorNode(BfAstNode* astNode); void AddErrorNode(BfAstNode* astNode); int AllocChars(int charCount); void FinishSideNodes(); diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index eaad4ac0..9341ead2 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -3517,11 +3517,15 @@ void BfModule::Visit(BfUncheckedStatement* uncheckedStmt) void BfModule::DoIfStatement(BfIfStatement* ifStmt, bool includeTrueStmt, bool includeFalseStmt) { + auto autoComplete = mCompiler->GetAutoComplete(); + if (autoComplete != NULL) + autoComplete->CheckIdentifier(ifStmt->mIfToken, true); + if (ifStmt->mCondition == NULL) { AssertErrorState(); return; - } + } //TODO: Only conditionally create the scopeData here if we create a variable inside the condition statement @@ -3764,6 +3768,10 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt) { UpdateSrcPos(deleteStmt); + auto autoComplete = mCompiler->GetAutoComplete(); + if (autoComplete != NULL) + autoComplete->CheckIdentifier(deleteStmt->mDeleteToken, true); + bool isAppendDelete = false; BfTypedValue customAllocator; if (deleteStmt->mAllocExpr != NULL) @@ -5463,6 +5471,10 @@ void BfModule::Visit(BfWhileStatement* whileStmt) void BfModule::Visit(BfForStatement* forStmt) { + auto autoComplete = mCompiler->GetAutoComplete(); + if (autoComplete != NULL) + autoComplete->CheckIdentifier(forStmt->mForToken, true); + UpdateSrcPos(forStmt); auto startBB = mBfIRBuilder->CreateBlock("for.start", true);