#include "BfSourceClassifier.h" #include "BfParser.h" #include "BeefySysLib/util/BeefPerf.h" USING_NS_BF; BfSourceClassifier::BfSourceClassifier(BfParser* bfParser, CharData* charData) { mParser = bfParser; mCharData = charData; mSkipMethodInternals = false; mSkipTypeDeclarations = false; mSkipAttributes = false; mIsSideChannel = false; mPreserveFlags = false; mClassifierPassId = 0; mEnabled = true; mPrevNode = NULL; mCurMember = NULL; mCurLocalMethodDeclaration = NULL; mSkipAnonymousTypes = false; } void BfSourceClassifier::ModifyFlags(BfAstNode* node, uint8 andFlags, uint8 orFlags) { if (node != NULL) { ModifyFlags(node->GetSrcStart(), node->GetSrcEnd(), andFlags, orFlags); } } void BfSourceClassifier::ModifyFlags(int startPos, int endPos, uint8 andFlags, uint8 orFlags) { if (!mEnabled) return; endPos = std::min(endPos, mParser->mOrigSrcLength); for (int i = startPos; i < endPos; i++) { mCharData[i].mDisplayPassId = mClassifierPassId; mCharData[i].mDisplayFlags = (mCharData[i].mDisplayFlags & andFlags) | orFlags; } } void BfSourceClassifier::SetElementType(BfAstNode* node, BfSourceElementType elementType) { if (node != NULL) { SetElementType(node->GetSrcStart(), node->GetSrcEnd(), elementType); } } void BfSourceClassifier::SetElementType(BfAstNode * node, BfTypeCode typeCode) { BfSourceElementType elemType = BfSourceElementType_Type; if (typeCode == BfTypeCode_Interface) elemType = BfSourceElementType_Interface; else if (typeCode == BfTypeCode_Object) elemType = BfSourceElementType_RefType; else if (typeCode == BfTypeCode_Struct) elemType = BfSourceElementType_Struct; SetElementType(node, elemType); } void BfSourceClassifier::SetHighestElementType(int startPos, int endPos, BfSourceElementType elementType) { if (!mEnabled) return; endPos = BF_MIN(endPos, mParser->mOrigSrcLength); for (int i = startPos; i < endPos; i++) { auto& charData = mCharData[i]; charData.mDisplayPassId = mClassifierPassId; charData.mDisplayTypeId = BF_MAX(charData.mDisplayTypeId, (uint8)elementType); } } void BfSourceClassifier::SetHighestElementType(BfAstNode* node, BfSourceElementType elementType) { if (node != NULL) { SetHighestElementType(node->GetSrcStart(), node->GetSrcEnd(), elementType); } } void BfSourceClassifier::SetElementType(int startPos, int endPos, BfSourceElementType elementType) { if (!mEnabled) return; endPos = BF_MIN(endPos, mParser->mOrigSrcLength); for (int i = startPos; i < endPos; i++) { mCharData[i].mDisplayPassId = mClassifierPassId; mCharData[i].mDisplayTypeId = (uint8)elementType; } } void BfSourceClassifier::VisitMembers(BfBlock* node) { mPrevNode = NULL; for (auto& childNodeRef : *node) { BfAstNode* child = childNodeRef; child->Accept(this); mPrevNode = child; } } bool BfSourceClassifier::IsInterestedInMember(BfAstNode* node, bool forceSkip) { if ((mSkipMethodInternals || forceSkip) && (mParser->mCursorIdx != -1) && (!node->Contains(mParser->mCursorIdx, 1, 0))) return false; return true; } void BfSourceClassifier::HandleLeafNode(BfAstNode* node) { if (!mEnabled) return; int nodeStart = node->GetSrcStart(); int srcStart = nodeStart; int triviaStart = node->GetTriviaStart(); if (triviaStart != -1) { srcStart = triviaStart; if ((mIsSideChannel) && (mPrevNode != NULL)) srcStart = std::max(mPrevNode->GetSrcEnd(), srcStart); } if (nodeStart != srcStart) SetElementType(srcStart, nodeStart, BfSourceElementType_Normal); //SetElementType(srcStart, node->GetSrcEnd(), BfSourceElementType_Normal); if (!mPreserveFlags) ModifyFlags(srcStart, node->GetSrcEnd(), ~BfSourceElementFlag_CompilerFlags_Mask, 0); } void BfSourceClassifier::Visit(BfAstNode* node) { } void BfSourceClassifier::Visit(BfErrorNode* errorNode) { //Visit(errorNode->ToBase()); VisitChildNoRef(errorNode->mRefNode); } void BfSourceClassifier::Visit(BfFieldDeclaration* fieldDecl) { if (!IsInterestedInMember(fieldDecl)) return; BfElementVisitor::Visit(fieldDecl); VisitChild(fieldDecl->mConstSpecifier); VisitChild(fieldDecl->mReadOnlySpecifier); VisitChild(fieldDecl->mTypeRef); VisitChild(fieldDecl->mNameNode); SetElementType(fieldDecl->mNameNode, BfSourceElementType_Member); } void BfSourceClassifier::Visit(BfFieldDtorDeclaration* fieldDtorDecl) { Visit(fieldDtorDecl->ToBase()); BfElementVisitor::Visit(fieldDtorDecl); if (fieldDtorDecl->mTildeToken != NULL) SetElementType(fieldDtorDecl->mTildeToken, BfSourceElementType_Method); } void BfSourceClassifier::Visit(BfPreprocesorIgnoredSectionNode* preprocesorIgnoredSection) { HandleLeafNode(preprocesorIgnoredSection); Visit(preprocesorIgnoredSection->ToBase()); SetElementType(preprocesorIgnoredSection, BfSourceElementType_Comment); } void BfSourceClassifier::Visit(BfPreprocessorNode* preprocessorNode) { HandleLeafNode(preprocessorNode); if (!mPreserveFlags) ModifyFlags(preprocessorNode, ~BfSourceElementFlag_CompilerFlags_Mask, 0); SetElementType(preprocessorNode, BfSourceElementType_Normal); Visit(preprocessorNode->ToBase()); } void BfSourceClassifier::Visit(BfCommentNode* commentNode) { HandleLeafNode(commentNode); Visit(commentNode->ToBase()); SetElementType(commentNode, BfSourceElementType_Comment); } void BfSourceClassifier::Visit(BfAttributeDirective* attributeDirective) { if (mSkipAttributes) return; // Skip? { if (auto typeDeclaration = BfNodeDynCast(mCurMember)) { if (typeDeclaration->mAttributes == attributeDirective) return; } if (mCurLocalMethodDeclaration == NULL) { if (auto methodDecl = BfNodeDynCast(mCurMember)) { if (methodDecl->mAttributes == attributeDirective) return; } } if (auto propDecl = BfNodeDynCast(mCurMember)) { if (propDecl->mAttributes == attributeDirective) return; for (auto methodDeclaration : propDecl->mMethods) { if (methodDeclaration->mAttributes == attributeDirective) return; } } } BfElementVisitor::Visit(attributeDirective); VisitChild(attributeDirective->mAttrCloseToken); VisitChild(attributeDirective->mAttrOpenToken); // Either [ or , VisitChild(attributeDirective->mAttrCloseToken); if (attributeDirective->mAttributeTargetSpecifier != NULL) { if (auto attributeTargetSpecifier = BfNodeDynCast(attributeDirective->mAttributeTargetSpecifier)) { VisitChild(attributeTargetSpecifier->mTargetToken); VisitChild(attributeTargetSpecifier->mColonToken); } else { VisitChild(attributeDirective->mAttributeTargetSpecifier); } } VisitChild(attributeDirective->mAttributeTypeRef); VisitChild(attributeDirective->mCtorOpenParen); VisitChild(attributeDirective->mCtorCloseParen); for (auto& arg : attributeDirective->mArguments) VisitChild(arg); for (auto& comma : attributeDirective->mCommas) VisitChild(comma); VisitChild(attributeDirective->mNextAttribute); } void BfSourceClassifier::Visit(BfIdentifierNode* identifier) { HandleLeafNode(identifier); Visit(identifier->ToBase()); if ((identifier->Equals("this")) || (identifier->Equals("base"))) SetElementType(identifier, BfSourceElementType_Keyword); else SetElementType(identifier, BfSourceElementType_Identifier); } void BfSourceClassifier::Visit(BfQualifiedNameNode* qualifiedName) { Visit((BfAstNode*)qualifiedName); VisitChild(qualifiedName->mLeft); VisitChild(qualifiedName->mDot); VisitChild(qualifiedName->mRight); if (BfNodeIsExact(qualifiedName->mRight)) SetElementType(qualifiedName->mRight, BfSourceElementType_Member); } void BfSourceClassifier::Visit(BfThisExpression* thisExpr) { HandleLeafNode(thisExpr); Visit((BfAstNode*)thisExpr); SetElementType(thisExpr, BfSourceElementType_Keyword); } void BfSourceClassifier::Visit(BfBaseExpression* baseExpr) { HandleLeafNode(baseExpr); Visit((BfAstNode*)baseExpr); SetElementType(baseExpr, BfSourceElementType_Keyword); } void BfSourceClassifier::Visit(BfMemberReferenceExpression* memberRefExpr) { Visit((BfAstNode*)memberRefExpr); VisitChild(memberRefExpr->mTarget); VisitChild(memberRefExpr->mDotToken); VisitChild(memberRefExpr->mMemberName); SetElementType(memberRefExpr->mMemberName, BfSourceElementType_Member); } void BfSourceClassifier::Visit(BfNamedTypeReference* typeRef) { HandleLeafNode(typeRef); Visit(typeRef->ToBase()); //auto identifier = typeRef->mNameNode; if (typeRef != NULL) { BfIdentifierNode* checkName = typeRef->mNameNode; while (auto qualifiedNameNode = BfNodeDynCast(checkName)) { SetElementType(qualifiedNameNode->mRight, BfSourceElementType_Type); checkName = qualifiedNameNode->mLeft; } if (checkName != NULL) SetElementType(checkName, BfSourceElementType_Type); } } void BfSourceClassifier::Visit(BfTagTypeRef* typeRef) { Visit((BfAstNode*)typeRef); VisitChild(typeRef->mTagNode); SetElementType(typeRef->mTagNode, BfSourceElementType_Keyword); VisitChild(typeRef->mNameNode); SetElementType(typeRef->mNameNode, BfSourceElementType_Type); } void BfSourceClassifier::Visit(BfQualifiedTypeReference* qualifiedType) { Visit((BfAstNode*)qualifiedType); VisitChild(qualifiedType->mLeft); VisitChild(qualifiedType->mDot); VisitChild(qualifiedType->mRight); } void BfSourceClassifier::Visit(BfRefTypeRef* typeRef) { Visit((BfAstNode*)typeRef); VisitChild(typeRef->mRefToken); SetElementType(typeRef->mRefToken, BfSourceElementType_Type); VisitChild(typeRef->mElementType); } void BfSourceClassifier::Visit(BfArrayTypeRef* arrayType) { Visit((BfAstNode*)arrayType); VisitChild(arrayType->mElementType); VisitChild(arrayType->mOpenBracket); for (auto& param : arrayType->mParams) VisitChild(param); VisitChild(arrayType->mCloseBracket); } void BfSourceClassifier::Visit(BfPointerTypeRef* pointerType) { Visit((BfAstNode*)pointerType); VisitChild(pointerType->mElementType); VisitChild(pointerType->mStarNode); } void BfSourceClassifier::Visit(BfGenericInstanceTypeRef* genericInstTypeRef) { BfElementVisitor::Visit(genericInstTypeRef); VisitChild(genericInstTypeRef->mElementType); VisitChild(genericInstTypeRef->mOpenChevron); for (int i = 0; i < (int) genericInstTypeRef->mGenericArguments.size(); i++) { if (genericInstTypeRef->mCommas.mVals != NULL) { if ((i > 0) && (i - 1 < (int)genericInstTypeRef->mCommas.size())) VisitChild(genericInstTypeRef->mCommas[i - 1]); } VisitChild(genericInstTypeRef->mGenericArguments[i]); } VisitChild(genericInstTypeRef->mCloseChevron); } void BfSourceClassifier::Visit(BfVariableDeclaration* varDecl) { BfElementVisitor::Visit(varDecl); if (!varDecl->IsA()) SetElementType(varDecl->mNameNode, BfSourceElementType_Local); } void BfSourceClassifier::Visit(BfLambdaBindExpression* lambdaBindExpr) { BfElementVisitor::Visit(lambdaBindExpr); for (auto param : lambdaBindExpr->mParams) { SetElementType(param, BfSourceElementType_Parameter); } } void BfSourceClassifier::Visit(BfLocalMethodDeclaration* methodDecl) { if (IsInterestedInMember(methodDecl, true)) { SetAndRestoreValue prevLocalMethodDecl(mCurLocalMethodDeclaration, methodDecl); BfElementVisitor::Visit(methodDecl); } } void BfSourceClassifier::Visit(BfLiteralExpression* literalExpr) { HandleLeafNode(literalExpr); Visit(literalExpr->ToBase()); SetElementType(literalExpr, BfSourceElementType_Literal); } void BfSourceClassifier::Visit(BfStringInterpolationExpression* stringInterpolationExpression) { HandleLeafNode(stringInterpolationExpression); Visit(stringInterpolationExpression->ToBase()); SetElementType(stringInterpolationExpression, BfSourceElementType_Literal); VisitChild(stringInterpolationExpression->mAllocNode); for (auto& expr : stringInterpolationExpression->mExpressions) { SetElementType(expr, BfSourceElementType_Normal); VisitChild(expr); } } void BfSourceClassifier::Visit(BfTokenNode* tokenNode) { HandleLeafNode(tokenNode); Visit(tokenNode->ToBase()); if (BfTokenIsKeyword(tokenNode->GetToken())) SetElementType(tokenNode, BfSourceElementType_Keyword); else SetElementType(tokenNode, BfSourceElementType_Normal); } void BfSourceClassifier::Visit(BfInvocationExpression* invocationExpr) { //BfElementVisitor::Visit(invocationExpr); Visit(invocationExpr->ToBase()); //BP_ZONE("BfSourceClassifier BfInvocationExpression"); BfAstNode* target = invocationExpr->mTarget; if (target == NULL) return; VisitChild(invocationExpr->mOpenParen); VisitChild(invocationExpr->mCloseParen); VisitChild(invocationExpr->mGenericArgs); if (auto scopedTarget = BfNodeDynCast(target)) { VisitChild(target); target = scopedTarget->mTarget; VisitChild(scopedTarget->mScopeName); } BfAstNode* identifier = NULL; if (auto qualifiedName = BfNodeDynCast(target)) { VisitChild(qualifiedName->mLeft); VisitChild(qualifiedName->mDot); VisitChild(qualifiedName->mRight); identifier = qualifiedName->mRight; } else if ((identifier = BfNodeDynCast(target))) { VisitChild(target); // Leave as BfAttributedIdentifierNode if that's the case identifier = target; } else if (auto qualifiedName = BfNodeDynCast(target)) { VisitChild(qualifiedName->mLeft); VisitChild(qualifiedName->mDot); VisitChild(qualifiedName->mRight); identifier = qualifiedName->mRight; } else if (auto memberRefExpr = BfNodeDynCast(target)) { VisitChild(memberRefExpr->mTarget); VisitChild(memberRefExpr->mDotToken); VisitChild(memberRefExpr->mMemberName); identifier = memberRefExpr->mMemberName; } else { VisitChild(target); } if (identifier != NULL) { if (auto attrIdentifier = BfNodeDynCast(identifier)) { VisitChild(attrIdentifier->mAttributes); identifier = attrIdentifier->mIdentifier; } if (identifier != NULL) SetElementType(identifier, BfSourceElementType_Method); } for (auto& val : invocationExpr->mArguments) VisitChild(val); for (auto& val : invocationExpr->mCommas) VisitChild(val); } void BfSourceClassifier::Visit(BfIndexerExpression* indexerExpr) { //BfElementVisitor::Visit(indexerExpr); Visit(indexerExpr->ToBase()); VisitChild(indexerExpr->mTarget); VisitChild(indexerExpr->mOpenBracket); for (auto& val : indexerExpr->mArguments) VisitChild(val); for (auto& val : indexerExpr->mCommas) VisitChild(val); VisitChild(indexerExpr->mCloseBracket); } void BfSourceClassifier::Visit(BfConstructorDeclaration* ctorDeclaration) { if (!IsInterestedInMember(ctorDeclaration)) return; BfElementVisitor::Visit(ctorDeclaration); VisitChild(ctorDeclaration->mThisToken); auto identifier = ctorDeclaration->mThisToken; if (identifier == NULL) return; SetElementType(identifier, BfSourceElementType_Method); } void BfSourceClassifier::Visit(BfDestructorDeclaration* dtorDeclaration) { BfElementVisitor::Visit(dtorDeclaration); VisitChild(dtorDeclaration->mTildeToken); VisitChild(dtorDeclaration->mThisToken); auto identifier = dtorDeclaration->mThisToken; if (identifier == NULL) return; SetElementType(identifier, BfSourceElementType_Method); identifier = dtorDeclaration->mTildeToken; if (identifier == NULL) return; SetElementType(identifier, BfSourceElementType_Method); } void BfSourceClassifier::Visit(BfMethodDeclaration* methodDeclaration) { if (!IsInterestedInMember(methodDeclaration)) return; //BP_ZONE("BfSourceClassifier BfMethodDeclaration"); SetAndRestoreValue prevMember(mCurMember, methodDeclaration); BfElementVisitor::Visit(methodDeclaration); SetElementType(methodDeclaration->mNameNode, BfSourceElementType_Method); for (auto paramDecl : methodDeclaration->mParams) { if (paramDecl != NULL) SetElementType(paramDecl->mNameNode, BfSourceElementType_Parameter); } if (methodDeclaration->mGenericParams != NULL) { for (auto& genericParam : methodDeclaration->mGenericParams->mGenericParams) { BfIdentifierNode* typeRef = genericParam; SetElementType(typeRef, BfSourceElementType_GenericParam); } } if (methodDeclaration->mGenericConstraintsDeclaration != NULL) { for (auto constraintNode : methodDeclaration->mGenericConstraintsDeclaration->mGenericConstraints) { if (auto genericConstraint = BfNodeDynCast(constraintNode)) { BfTypeReference* typeRef = genericConstraint->mTypeRef; if (typeRef != NULL) { if (auto namedTypeRef = BfNodeDynCast(typeRef)) SetElementType(typeRef, BfSourceElementType_GenericParam); else VisitChild(typeRef); } } } } } void BfSourceClassifier::Visit(BfPropertyMethodDeclaration* propertyMethodDeclaration) { if ((propertyMethodDeclaration->mBody != NULL) && (!IsInterestedInMember(propertyMethodDeclaration->mBody))) return; BfElementVisitor::Visit(propertyMethodDeclaration); } void BfSourceClassifier::Visit(BfPropertyDeclaration* propertyDeclaration) { SetAndRestoreValue prevMember(mCurMember, propertyDeclaration); BfElementVisitor::Visit(propertyDeclaration); SetElementType(propertyDeclaration->mNameNode, BfSourceElementType_Member); if (auto expr = BfNodeDynCast(propertyDeclaration->mDefinitionBlock)) return; for (auto methodDeclaration : propertyDeclaration->mMethods) { if ((methodDeclaration != NULL) && (methodDeclaration->mNameNode != NULL)) SetElementType(methodDeclaration->mNameNode, BfSourceElementType_Method); } } void BfSourceClassifier::Visit(BfTypeDeclaration* typeDeclaration) { if ((mSkipAnonymousTypes) && (typeDeclaration->IsAnonymous())) return; if (typeDeclaration->mIgnoreDeclaration) return; SetAndRestoreValue prevMember(mCurMember, typeDeclaration); if ((mSkipTypeDeclarations) && (!typeDeclaration->IsAnonymous())) { if (auto defineBlock = BfNodeDynCast(typeDeclaration->mDefineNode)) { // Clear out any potential "fail after" errors on the closing brace- // Can happen when we don't close out a namespace, for example if (defineBlock->mCloseBrace != NULL) VisitChild(defineBlock->mCloseBrace); } return; } Handle(typeDeclaration); } void BfSourceClassifier::Handle(BfTypeDeclaration* typeDeclaration) { if (mParser->mCursorIdx != -1) { // This is to fix a case where we are typing out a type name, so an "actualTypeDef" will not be found during autocomplete // and therefore we will not process the attributes. Removing this will cause classify flashing while typing SetAndRestoreValue prevSkipAttributes(mSkipAttributes, true); BfElementVisitor::Visit(typeDeclaration); } else BfElementVisitor::Visit(typeDeclaration); llvm::SmallVector mBaseClasses; llvm::SmallVector mBaseClassCommas; if (typeDeclaration->mGenericParams != NULL) { for (auto& genericParam : typeDeclaration->mGenericParams->mGenericParams) { BfIdentifierNode* typeRef = genericParam; SetElementType(typeRef, BfSourceElementType_GenericParam); } } if (typeDeclaration->mGenericConstraintsDeclaration != NULL) { for (auto constraintNode : typeDeclaration->mGenericConstraintsDeclaration->mGenericConstraints) { auto genericConstraint = BfNodeDynCast(constraintNode); BfTypeReference* typeRef = genericConstraint->mTypeRef; if (typeRef != NULL) { if (auto namedTypeRef = BfNodeDynCast(typeRef)) SetElementType(namedTypeRef, BfSourceElementType_GenericParam); } } } auto typeRef = typeDeclaration->mNameNode; if (typeRef != NULL) SetElementType(typeRef, BfSourceElementType_Type); } void BfSourceClassifier::MarkSkipped(int startPos, int endPos) { for (int i = startPos; i < endPos; i++) { mCharData[i].mDisplayPassId = BfSourceDisplayId_SkipResult; } } void BfSourceClassifier::MarkSkipped(BfAstNode* node) { MarkSkipped(node->GetSrcStart(), node->GetSrcEnd()); } void BfSourceClassifier::DeferNodes(BfBlock* block) { for (auto child : *block) mDeferredNodes.Add(child); } void BfSourceClassifier::FlushDeferredNodes() { for (auto node : mDeferredNodes) VisitChild(node); mDeferredNodes.Clear(); } void BfSourceClassifier::Visit(BfTypeAliasDeclaration* typeDeclaration) { if (typeDeclaration->mIgnoreDeclaration) return; BfElementVisitor::Visit(typeDeclaration); } void BfSourceClassifier::Visit(BfUsingDirective* usingDirective) { BfElementVisitor::Visit(usingDirective); auto checkIdentifier = usingDirective->mNamespace; if (checkIdentifier != NULL) { while (auto qualifiedNameNode = BfNodeDynCast(checkIdentifier)) { SetElementType(qualifiedNameNode->mRight, BfSourceElementType_Namespace); checkIdentifier = qualifiedNameNode->mLeft; } if (checkIdentifier != NULL) SetElementType(checkIdentifier, BfSourceElementType_Namespace); } } void BfSourceClassifier::Visit(BfUsingModDirective* usingDirective) { BfElementVisitor::Visit(usingDirective); } void BfSourceClassifier::Visit(BfNamespaceDeclaration* namespaceDeclaration) { BfElementVisitor::Visit(namespaceDeclaration); auto checkIdentifier = namespaceDeclaration->mNameNode; if (checkIdentifier != NULL) { while (auto qualifiedNameNode = BfNodeDynCast(checkIdentifier)) { SetElementType(qualifiedNameNode->mRight, BfSourceElementType_Namespace); checkIdentifier = qualifiedNameNode->mLeft; } if (checkIdentifier != NULL) SetElementType(checkIdentifier, BfSourceElementType_Namespace); } } bool BfSourceClassifier::WantsSkipParentMethod(BfAstNode* node) { if (!mSkipMethodInternals) return false; #ifdef BF_AST_HAS_PARENT_MEMBER if (node->mParent->IsA()) { BF_ASSERT(node->mParent == mCurMember); } if (auto propDecl = BfNodeDynCast(node->mParent)) { BF_ASSERT(node->mParent == mCurMember); } #endif if (auto methodDecl = BfNodeDynCast(mCurMember)) { if (methodDecl->mBody == node) return true; } if (auto propDecl = BfNodeDynCast(mCurMember)) { for (auto methodDeclaration : propDecl->mMethods) { if (node == methodDeclaration->mBody) return true; } } return false; } void BfSourceClassifier::Visit(BfGenericConstraintsDeclaration* genericConstraints) { /*if (WantsSkipParentMethod(genericConstraints)) return;*/ BfElementVisitor::Visit(genericConstraints); } void BfSourceClassifier::Visit(BfBlock* block) { if (WantsSkipParentMethod(block)) return; if (block->mOpenBrace != NULL) Visit(block->mOpenBrace); if (block->mCloseBrace != NULL) Visit(block->mCloseBrace); VisitMembers(block); } void BfSourceClassifier::Visit(BfRootNode* rootNode) { // Clear off the flags at the end ModifyFlags(mParser->mRootNode->GetSrcEnd(), mParser->mOrigSrcLength, 0, 0); VisitMembers(rootNode); } void BfSourceClassifier::Visit(BfInlineAsmStatement* asmStmt) { if (asmStmt->mOpenBrace != NULL) Visit(asmStmt->mOpenBrace); if (asmStmt->mCloseBrace != NULL) Visit(asmStmt->mCloseBrace); //VisitMembers(asmStmt); } void BfSourceClassifier::Visit(BfInlineAsmInstruction* asmInst) { //VisitMembers(asmInst); }