#include "CodeService/AstUtil.h" bool ast_util::IsSingleStringOrTableArg(std::shared_ptr callArgList) { if (!callArgList) { return false; } for (auto child : callArgList->GetChildren()) { switch (child->GetType()) { case LuaAstNodeType::StringLiteralExpression: case LuaAstNodeType::TableExpression: { return true; } case LuaAstNodeType::ExpressionList: { auto expressionList = child; if (expressionList->GetChildren().empty() || expressionList->FindFirstOf(LuaAstNodeType::GeneralOperator)) { return false; } auto expression = expressionList->GetChildren().front(); if (expression->FindFirstOf(LuaAstNodeType::StringLiteralExpression) || expression->FindFirstOf(LuaAstNodeType::TableExpression)) { return true; } break; } default: { break; } } } return false; } bool ast_util::IsSingleStringArg(std::shared_ptr callArgList) { if (!callArgList) { return false; } for (auto child : callArgList->GetChildren()) { switch (child->GetType()) { case LuaAstNodeType::StringLiteralExpression: { return true; } case LuaAstNodeType::ExpressionList: { auto expressionList = child; if (expressionList->GetChildren().empty() || expressionList->FindFirstOf(LuaAstNodeType::GeneralOperator)) { return false; } auto expression = expressionList->GetChildren().front(); if (expression->FindFirstOf(LuaAstNodeType::StringLiteralExpression)) { return true; } break; } default: { break; } } } return false; } bool ast_util::IsSingleStringArgUnambiguous(std::shared_ptr callArgList) { bool isSingleStringArg = IsSingleStringArg(callArgList); if (!isSingleStringArg) { return false; } auto callExpression = callArgList->GetParent(); if (!callExpression) { return false; } if (callExpression->GetType() != LuaAstNodeType::CallExpression) { return false; } auto indexExpression = callExpression->GetParent(); if (indexExpression && indexExpression->GetType() == LuaAstNodeType::IndexExpression) { if (!indexExpression->GetChildren().empty() && callExpression == indexExpression->GetChildren().front()) { return false; } } return true; } bool ast_util::IsSingleTableArg(std::shared_ptr callArgList) { if (!callArgList) { return false; } for (auto child : callArgList->GetChildren()) { switch (child->GetType()) { case LuaAstNodeType::TableExpression: { return true; } case LuaAstNodeType::ExpressionList: { auto expressionList = child; if (expressionList->GetChildren().empty() || expressionList->FindFirstOf(LuaAstNodeType::GeneralOperator)) { return false; } auto expression = expressionList->GetChildren().front(); if (expression->FindFirstOf(LuaAstNodeType::TableExpression)) { return true; } break; } default: { break; } } } return false; } bool ast_util::WillCallArgHaveParentheses(std::shared_ptr callArgList, CallArgParentheses callArgParentheses) { if (ast_util::IsSingleStringOrTableArg(callArgList)) { switch (callArgParentheses) { case CallArgParentheses::Remove: { return false; } case CallArgParentheses::RemoveStringOnly: { if (IsSingleStringArg(callArgList)) { return false; } break; } case CallArgParentheses::RemoveTableOnly: { if (IsSingleTableArg(callArgList)) { return false; } break; } case CallArgParentheses::UnambiguousRemoveStringOnly: { if (IsSingleStringArgUnambiguous(callArgList)) { return false; } break; } default: { break; } } auto leftParentheses = callArgList->FindFirstOf(LuaAstNodeType::GeneralOperator); if (leftParentheses && leftParentheses->GetText() == "(") { return true; } else { return false; } } return true; } std::shared_ptr ast_util::FindLeftIndexExpression(std::shared_ptr expression) { if (expression->GetChildren().empty()) { return nullptr; } std::shared_ptr leftIndex = nullptr; auto subExpression = expression->GetChildren().front(); while (subExpression) { switch (subExpression->GetType()) { case LuaAstNodeType::CallExpression: { if (subExpression->GetChildren().empty()) { subExpression = nullptr; } else { subExpression = subExpression->GetChildren().front(); } break; } case LuaAstNodeType::IndexExpression: { leftIndex = subExpression; if (subExpression->GetChildren().empty()) { subExpression = nullptr; } else { subExpression = subExpression->GetChildren().front(); } break; } case LuaAstNodeType::PrimaryExpression: { subExpression = nullptr; break; } default: { return nullptr; } } } return leftIndex; } bool ast_util::WillIndexExpressionFormatError(std::shared_ptr expression) { auto text = expression->GetText(); if(text.empty()) { return false; } if(text.front() == '[') { return text.length() > 2 && (text[1] == '[' || text[1] == '='); } if(text.back() == ']') { return text.length() > 2 && (text[text.length() - 2] == ']' || text[text.length() - 2] == '='); } return false; }