qmlls: auto completion for inside do while statements

Save the source location of the do and while keywords, as well as the
parenthesis to be able to provide correct completion between the
parenthesis and between the do and while keyword.

Task-number: QTBUG-117445
Change-Id: I1474b5cb61589027451122228dc383fb2a4bb5aa
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Semih Yavuz <semih.yavuz@qt.io>
This commit is contained in:
Sami Shalayel 2023-11-03 17:04:19 +01:00
parent 7df34d498d
commit 9776460553
6 changed files with 48 additions and 1 deletions

View File

@ -2090,6 +2090,7 @@ void QQmlDomAstCreator::endVisit(AST::WhileStatement *exp)
return;
auto current = makeGenericScriptElement(exp, DomType::ScriptWhileStatement);
current->addLocation(FileLocationRegion::WhileKeywordRegion, exp->whileToken);
current->addLocation(FileLocationRegion::LeftParenthesisRegion, exp->lparenToken);
current->addLocation(FileLocationRegion::RightParenthesisRegion, exp->rparenToken);
@ -2122,6 +2123,10 @@ void QQmlDomAstCreator::endVisit(AST::DoWhileStatement *exp)
return;
auto current = makeGenericScriptElement(exp, DomType::ScriptDoWhileStatement);
current->addLocation(FileLocationRegion::DoKeywordRegion, exp->doToken);
current->addLocation(FileLocationRegion::WhileKeywordRegion, exp->whileToken);
current->addLocation(FileLocationRegion::LeftParenthesisRegion, exp->lparenToken);
current->addLocation(FileLocationRegion::RightParenthesisRegion, exp->rparenToken);
if (exp->expression) {
Q_SCRIPTELEMENT_EXIT_IF(scriptNodeStack.isEmpty());

View File

@ -341,6 +341,7 @@ MainRegion denotes the entire FileLocation region.
*/
enum FileLocationRegion : int {
AsTokenRegion,
DoKeywordRegion,
ColonTokenRegion,
CommaTokenRegion,
ComponentKeywordRegion,
@ -377,6 +378,7 @@ enum FileLocationRegion : int {
SecondSemicolonRegion,
SignalKeywordRegion,
TypeIdentifierRegion,
WhileKeywordRegion,
};
Q_ENUM_NS(FileLocationRegion);

View File

@ -207,6 +207,12 @@ OutWriter &OutWriter::writeRegion(FileLocationRegion region)
case ElseKeywordRegion:
codeForRegion = u"else"_s;
break;
case DoKeywordRegion:
codeForRegion = u"do"_s;
break;
case WhileKeywordRegion:
codeForRegion = u"while"_s;
break;
// not keywords:
case ImportUriRegion:

View File

@ -2739,6 +2739,24 @@ static QList<CompletionItem> insideWhileStatement(const DomItem &currentItem,
return {};
}
static QList<CompletionItem> insideDoWhileStatement(const DomItem &currentItem,
const CompletionContextStrings &ctx)
{
const auto regions = FileLocations::treeOf(currentItem)->info().regions;
const QQmlJS::SourceLocation doKeyword = regions[DoKeywordRegion];
const QQmlJS::SourceLocation whileKeyword = regions[WhileKeywordRegion];
const QQmlJS::SourceLocation leftParenthesis = regions[LeftParenthesisRegion];
const QQmlJS::SourceLocation rightParenthesis = regions[RightParenthesisRegion];
if (betweenLocations(doKeyword, ctx, whileKeyword)) {
return QQmlLSUtils::suggestJSStatementCompletion(currentItem);
}
if (betweenLocations(leftParenthesis, ctx, rightParenthesis)) {
return QQmlLSUtils::scriptIdentifierCompletion(currentItem, ctx);
}
return {};
}
QList<CompletionItem> QQmlLSUtils::completions(const DomItem &currentItem,
const CompletionContextStrings &ctx)
{
@ -2808,6 +2826,8 @@ QList<CompletionItem> QQmlLSUtils::completions(const DomItem &currentItem,
return insideReturnStatement(currentParent, ctx);
case DomType::ScriptWhileStatement:
return insideWhileStatement(currentParent, ctx);
case DomType::ScriptDoWhileStatement:
return insideDoWhileStatement(currentParent, ctx);
// TODO: Implement those statements.
// In the meanwhile, suppress completions to avoid weird behaviors.
@ -2824,7 +2844,6 @@ QList<CompletionItem> QQmlLSUtils::completions(const DomItem &currentItem,
case DomType::ScriptCaseClauses:
case DomType::ScriptCaseClause:
case DomType::ScriptDefaultClause:
case DomType::ScriptDoWhileStatement:
case DomType::ScriptForEachStatement:
return {};

View File

@ -127,4 +127,7 @@ Zzz {
function helloWhileStatement(hello) {
while (hello) --hello
}
function helloDoWhileStatement(hello) {
do --hello; while (hello);
}
}

View File

@ -2428,6 +2428,18 @@ void tst_qmlls_utils::completions_data()
<< ExpectedCompletions{ { u"hello"_s, CompletionItemKind::Variable },
{ letStatementCompletion, CompletionItemKind::Snippet } }
<< QStringList{ propertyCompletion } << None;
QTest::newRow("doWhileCondition")
<< file << 131 << 30
<< ExpectedCompletions{ { u"hello"_s, CompletionItemKind::Variable }, }
<< QStringList{ propertyCompletion, letStatementCompletion }
<< None;
QTest::newRow("whileConsequence")
<< file << 131 << 12
<< ExpectedCompletions{ { u"hello"_s, CompletionItemKind::Variable },
{ letStatementCompletion, CompletionItemKind::Snippet } }
<< QStringList{ propertyCompletion } << None;
}
void tst_qmlls_utils::completions()