diff --git a/IDEHelper/Compiler/BfAst.cpp b/IDEHelper/Compiler/BfAst.cpp index 11c26c67..4bce720d 100644 --- a/IDEHelper/Compiler/BfAst.cpp +++ b/IDEHelper/Compiler/BfAst.cpp @@ -576,6 +576,11 @@ void BfStructuralVisitor::Visit(BfPropertyMethodDeclaration* propertyMethodDecla Visit(propertyMethodDeclaration->ToBase()); } +void BfStructuralVisitor::Visit(BfPropertyBodyExpression* propertyBodyExpression) +{ + Visit(propertyBodyExpression->ToBase()); +} + void BfStructuralVisitor::Visit(BfPropertyDeclaration* propertyDeclaration) { Visit(propertyDeclaration->ToBase()); diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index 8ce9594f..b6e7af0f 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -322,6 +322,7 @@ class BfQualifiedTypeReference; class BfUsingDirective; class BfUsingStaticDirective; class BfPropertyMethodDeclaration; +class BfPropertyBodyExpression; class BfPropertyDeclaration; class BfIndexerDeclaration; class BfPreprocesorIgnoredSectionNode; @@ -500,6 +501,7 @@ public: virtual void Visit(BfMethodDeclaration* methodDeclaration); virtual void Visit(BfOperatorDeclaration* operatorDeclaration); virtual void Visit(BfPropertyMethodDeclaration* propertyMethodDeclaration); + virtual void Visit(BfPropertyBodyExpression* propertyBodyExpression); virtual void Visit(BfPropertyDeclaration* propertyDeclaration); virtual void Visit(BfIndexerDeclaration* indexerDeclaration); virtual void Visit(BfFieldDeclaration* fieldDeclaration); @@ -2895,11 +2897,18 @@ public: BfPropertyDeclaration* mPropertyDeclaration; BfAttributeDirective* mAttributes; BfTokenNode* mProtectionSpecifier; - BfTokenNode* mMutSpecifier; + BfTokenNode* mMutSpecifier; BfIdentifierNode* mNameNode; - BfAstNode* mBody; + BfAstNode* mBody; }; BF_AST_DECL(BfPropertyMethodDeclaration, BfAstNode); +class BfPropertyBodyExpression : public BfAstNode +{ +public: + BF_AST_TYPE(BfPropertyBodyExpression, BfAstNode); + BfTokenNode* mFatTokenArrow; +}; BF_AST_DECL(BfPropertyBodyExpression, BfAstNode); + class BfPropertyDeclaration : public BfFieldDeclaration { public: @@ -2907,8 +2916,8 @@ public: BfTokenNode* mVirtualSpecifier; // either 'virtual', 'override', or 'abstract' BfTypeReference* mExplicitInterface; - BfTokenNode* mExplicitInterfaceDotToken; - BfBlock* mDefinitionBlock; + BfTokenNode* mExplicitInterfaceDotToken; + BfAstNode* mDefinitionBlock; BfSizedArray mMethods; diff --git a/IDEHelper/Compiler/BfDefBuilder.cpp b/IDEHelper/Compiler/BfDefBuilder.cpp index 1634ebb4..0672d90b 100644 --- a/IDEHelper/Compiler/BfDefBuilder.cpp +++ b/IDEHelper/Compiler/BfDefBuilder.cpp @@ -847,8 +847,10 @@ void BfDefBuilder::Visit(BfPropertyDeclaration* propertyDeclaration) } } - String methodName; - if ((methodDeclaration != NULL) && (methodDeclaration->mNameNode != NULL)) + String methodName; + if (auto propExprBody = BfNodeDynCast(propertyDeclaration->mDefinitionBlock)) + methodName = "get"; + else if ((methodDeclaration != NULL) && (methodDeclaration->mNameNode != NULL)) methodName = methodDeclaration->mNameNode->ToString(); if (methodName == "get") diff --git a/IDEHelper/Compiler/BfElementVisitor.cpp b/IDEHelper/Compiler/BfElementVisitor.cpp index 6e8539f0..c1e17bbc 100644 --- a/IDEHelper/Compiler/BfElementVisitor.cpp +++ b/IDEHelper/Compiler/BfElementVisitor.cpp @@ -1022,6 +1022,13 @@ void BfElementVisitor::Visit(BfPropertyMethodDeclaration* propertyDeclaration) VisitChild(propertyDeclaration->mBody); } +void BfElementVisitor::Visit(BfPropertyBodyExpression* propertyBodyExpression) +{ + Visit(propertyBodyExpression->ToBase()); + + VisitChild(propertyBodyExpression->mFatTokenArrow); +} + void BfElementVisitor::Visit(BfPropertyDeclaration* propertyDeclaration) { Visit(propertyDeclaration->ToBase()); @@ -1035,14 +1042,19 @@ void BfElementVisitor::Visit(BfPropertyDeclaration* propertyDeclaration) VisitChild(propertyDeclaration->mExplicitInterface); VisitChild(propertyDeclaration->mExplicitInterfaceDotToken); - if (propertyDeclaration->mDefinitionBlock != NULL) - VisitChild(propertyDeclaration->mDefinitionBlock->mOpenBrace); - - for (auto& method : propertyDeclaration->mMethods) - VisitChild(method); - - if (propertyDeclaration->mDefinitionBlock != NULL) - VisitChild(propertyDeclaration->mDefinitionBlock->mCloseBrace); + if (auto block = BfNodeDynCast(propertyDeclaration->mDefinitionBlock)) + { + VisitChild(block->mOpenBrace); + for (auto& method : propertyDeclaration->mMethods) + VisitChild(method); + VisitChild(block->mCloseBrace); + } + else + { + VisitChild(propertyDeclaration->mDefinitionBlock); + for (auto& method : propertyDeclaration->mMethods) + VisitChild(method); + } } void BfElementVisitor::Visit(BfIndexerDeclaration* indexerDeclaration) diff --git a/IDEHelper/Compiler/BfElementVisitor.h b/IDEHelper/Compiler/BfElementVisitor.h index c37bab1d..d037bb48 100644 --- a/IDEHelper/Compiler/BfElementVisitor.h +++ b/IDEHelper/Compiler/BfElementVisitor.h @@ -116,6 +116,7 @@ public: virtual void Visit(BfMethodDeclaration* methodDeclaration); virtual void Visit(BfOperatorDeclaration* operatorDeclaration); virtual void Visit(BfPropertyMethodDeclaration* propertyDeclaration); + virtual void Visit(BfPropertyBodyExpression* propertyBodyExpression); virtual void Visit(BfPropertyDeclaration* propertyDeclaration); virtual void Visit(BfIndexerDeclaration* indexerDeclaration); virtual void Visit(BfFieldDeclaration* fieldDeclaration); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index c725a90b..9f662ff9 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -16973,9 +16973,12 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) if (methodDeclaration->mFatArrowToken != NULL) isExpressionBody = true; } - else if (methodDef->GetPropertyDeclaration() != NULL) + else if (auto propertyDeclaration = methodDef->GetPropertyDeclaration()) { - // + if (auto propBodyExpr = BfNodeDynCast(propertyDeclaration->mDefinitionBlock)) + { + isExpressionBody = true; + } } else { @@ -17011,7 +17014,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) } else if (auto expressionBody = BfNodeDynCast(methodDef->mBody)) { - if (methodDef->mMethodType != BfMethodType_Normal) + if ((methodDef->mMethodType != BfMethodType_Normal) && (propertyDeclaration == NULL)) { BF_ASSERT(methodDeclaration->mFatArrowToken != NULL); Fail("Only normal methods can have expression bodies", methodDeclaration->mFatArrowToken); @@ -19960,8 +19963,13 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo else if (auto methodDeclaration = methodDef->GetMethodDeclaration()) overrideToken = methodDeclaration->mVirtualSpecifier; if (overrideToken != NULL) - { - Fail("No suitable method found to override", overrideToken, true); + { + if ((propertyDeclaration != NULL) && (propertyDeclaration->mNameNode != NULL) && + ((methodDef->mMethodType == BfMethodType_PropertyGetter) || (methodDef->mMethodType == BfMethodType_PropertySetter))) + Fail(StrFormat("No suitable method found to override for '%s.%s'", + propertyDeclaration->mNameNode->ToString().c_str(), (methodDef->mMethodType == BfMethodType_PropertyGetter) ? "get" : "set"), overrideToken, true); + else + Fail("No suitable method found to override", overrideToken, true); } return usedMethod; diff --git a/IDEHelper/Compiler/BfPrinter.cpp b/IDEHelper/Compiler/BfPrinter.cpp index 88628715..b36cca87 100644 --- a/IDEHelper/Compiler/BfPrinter.cpp +++ b/IDEHelper/Compiler/BfPrinter.cpp @@ -2070,17 +2070,25 @@ void BfPrinter::Visit(BfPropertyDeclaration* propertyDeclaration) ExpectSpace(); QueueVisitChild(propertyDeclaration->mInitializer); - bool doInlineBlock = false; - if (propertyDeclaration->mDefinitionBlock != NULL) - DoBlockOpen(propertyDeclaration->mDefinitionBlock, true, &doInlineBlock); - - for (auto method : propertyDeclaration->mMethods) + if (auto block = BfNodeDynCast(propertyDeclaration->mDefinitionBlock)) { - Visit(method); + bool doInlineBlock = false; + DoBlockOpen(block, true, &doInlineBlock); + for (auto method : propertyDeclaration->mMethods) + { + Visit(method); + } + DoBlockClose(block, true, doInlineBlock); + } + else + { + QueueVisitChild(propertyDeclaration->mDefinitionBlock); + ExpectSpace(); + for (auto method : propertyDeclaration->mMethods) + { + QueueVisitChild(method->mBody); + } } - - if (propertyDeclaration->mDefinitionBlock != NULL) - DoBlockClose(propertyDeclaration->mDefinitionBlock, true, doInlineBlock); //QueueVisitChild(propertyDeclaration->mTrailingSemicolon); diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index a96251a9..5ec7688e 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -6606,39 +6606,19 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, int depth) nextNode = mVisitorPos.Get(blockAfterIdx); auto block = BfNodeDynCast(nextNode); auto tokenNode = BfNodeDynCast(nextNode); + + bool isExprBodyProp = (tokenNode != NULL) && (tokenNode->mToken == BfToken_FatArrow); // Property. // If we don't have a token afterwards then still treat it as a property for autocomplete purposes - if (((block != NULL) || (tokenNode == NULL)) && (typeRef != NULL)) + if ((typeRef != NULL) && + ((block != NULL) || (tokenNode == NULL) || (isExprBodyProp))) { //mVisitorPos.mReadPos = blockAfterIdx; if (propertyDeclaration == NULL) { - if (block == NULL) - { - //// Actually treat it as a method - //auto methodDecl = mAlloc->Alloc(); - //ReplaceNode(typeRef, methodDecl); - //methodDecl->mDocumentation = FindDocumentation(mTypeMemberNodeStart); - //methodDecl->mReturnType = typeRef; - - //if (explicitInterface != NULL) - //{ - // MEMBER_SET(methodDecl, mExplicitInterface, explicitInterface); - // MEMBER_SET(methodDecl, mExplicitInterfaceDotToken, explicitInterfaceDot); - //} - - //// Don't set the name identifier, this could be bogus - ////mVisitorPos.mReadPos--; - // - //// WHY did we want to not set this? - //// If we don't, then typing a new method name will end up treating the name node as a typeRef - //// which can autocomplete incorrectly - //MEMBER_SET(methodDecl, mNameNode, nameIdentifier); - - //return methodDecl; - - + if ((block == NULL) && (!isExprBodyProp)) + { auto propDecl = mAlloc->Alloc(); ReplaceNode(typeRef, propDecl); propDecl->mDocumentation = FindDocumentation(mTypeMemberNodeStart); @@ -6684,6 +6664,29 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, int depth) MEMBER_SET(propertyDeclaration, mDefinitionBlock, block); ReadPropertyBlock(propertyDeclaration, block); } + else if (isExprBodyProp) + { + BfDeferredAstSizedArray methods(propertyDeclaration->mMethods, mAlloc); + + auto propertyBodyExpr = mAlloc->Alloc(); + ReplaceNode(tokenNode, propertyBodyExpr); + MEMBER_SET(propertyBodyExpr, mFatTokenArrow, tokenNode); + + auto method = mAlloc->Alloc(); + method->mPropertyDeclaration = propertyDeclaration; + method->mNameNode = propertyDeclaration->mNameNode; + + auto expr = CreateExpressionAfter(tokenNode); + if (expr != NULL) + { + MEMBER_SET(method, mBody, expr); + propertyDeclaration->SetSrcEnd(expr->GetSrcEnd()); + } + + methods.Add(method); + + MEMBER_SET(propertyDeclaration, mDefinitionBlock, propertyBodyExpr); + } return propertyDeclaration; }