11 #include "GDCore/Events/Parsers/ExpressionParser2.h"
12 #include "GDCore/Events/Parsers/ExpressionParser2Node.h"
13 #include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
14 #include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
15 #include "GDCore/Events/Parsers/GrammarTerminals.h"
16 #include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
17 #include "GDCore/Extensions/Metadata/InstructionMetadata.h"
18 #include "GDCore/Extensions/Metadata/ValueTypeMetadata.h"
19 #include "GDCore/IDE/Events/ExpressionNodeLocationFinder.h"
20 #include "GDCore/IDE/Events/ExpressionTypeFinder.h"
21 #include "GDCore/IDE/Events/ExpressionVariableOwnerFinder.h"
22 #include "GDCore/IDE/Events/ExpressionVariablePathFinder.h"
23 #include "GDCore/Project/ProjectScopedContainers.h"
24 #include "GDCore/Project/Variable.h"
28 class ObjectsContainer;
30 class ParameterMetadata;
31 class ExpressionMetadata;
32 class ObjectConfiguration;
64 size_t replacementStartPosition_,
65 size_t replacementEndPosition_,
68 BehaviorWithPrefix, replacementStartPosition_, replacementEndPosition_);
69 description.SetPrefix(prefix_);
70 description.SetObjectName(objectName_);
81 size_t replacementStartPosition_,
82 size_t replacementEndPosition_,
83 const bool isLastParameter_,
86 TextWithPrefix, replacementStartPosition_, replacementEndPosition_);
87 description.SetObjectName(objectName_);
88 description.SetType(type_);
89 description.SetPrefix(prefix_);
90 description.SetIsLastParameter(isLastParameter_);
91 description.SetParameterMetadata(parameterMetadata_);
102 size_t replacementStartPosition_,
103 size_t replacementEndPosition_,
107 replacementStartPosition_,
108 replacementEndPosition_);
109 description.SetObjectName(objectName_);
110 description.SetBehaviorName(behaviorName_);
111 description.SetType(type_);
112 description.SetPrefix(prefix_);
118 return completionKind == other.completionKind && type == other.type &&
119 variableType == other.variableType && prefix == other.prefix &&
120 objectName == other.objectName && completion == other.completion &&
121 behaviorName == other.behaviorName;
145 variableType = variableType_;
153 return variableScope;
157 SetVariableScope(gd::VariablesContainer::SourceType variableScope_) {
158 variableScope = variableScope_;
179 completion = completion_;
191 objectName = objectName_;
206 behaviorName = behaviorName_;
231 return replacementStartPosition;
243 isLastParameter = isLastParameter_;
258 parameterMetadata = ¶meterMetadata_;
266 return parameterMetadata != &badParameterMetadata;
274 return *parameterMetadata;
283 objectConfiguration = objectConfiguration_;
284 if (!objectConfiguration) objectConfiguration = &badObjectConfiguration;
292 return objectConfiguration != &badObjectConfiguration;
300 return *objectConfiguration;
305 (GetType() ||
"no type") +
", " +
307 (GetPrefix() ||
"no prefix") +
", " +
308 (GetCompletion() ||
"no completion") +
", " +
309 (GetObjectName() ||
"no object name") +
", " +
310 (GetBehaviorName() ||
"no behavior name") +
", " +
311 (IsExact() ?
"exact" :
"non-exact") +
", " +
312 (IsLastParameter() ?
"last parameter" :
"not last parameter") +
314 (HasParameterMetadata() ?
"with parameter metadata"
315 :
"no parameter metadata") +
317 (HasObjectConfiguration() ?
"with object configuration"
318 :
"no object configuration") +
326 size_t replacementStartPosition_,
327 size_t replacementEndPosition_)
328 : completionKind(completionKind_),
331 replacementStartPosition(replacementStartPosition_),
332 replacementEndPosition(replacementEndPosition_),
334 isLastParameter(false),
335 parameterMetadata(&badParameterMetadata),
336 objectConfiguration(&badObjectConfiguration) {}
339 CompletionKind completionKind;
341 gd::VariablesContainer::SourceType variableScope = gd::VariablesContainer::Unknown;
345 size_t replacementStartPosition = 0;
346 size_t replacementEndPosition = 0;
349 bool isExact =
false;
350 bool isLastParameter =
false;
362 std::ostream& os, ExpressionCompletionDescription
const& value);
376 static std::vector<ExpressionCompletionDescription>
382 size_t searchedPosition) {
387 if (nodeAtLocation ==
nullptr) {
388 std::vector<ExpressionCompletionDescription> emptyCompletions;
389 return emptyCompletions;
395 projectScopedContainers,
398 maybeParentNodeAtLocation);
399 nodeAtLocation->Visit(autocompletionProvider);
406 const std::vector<ExpressionCompletionDescription>&
414 void OnVisitSubExpressionNode(SubExpressionNode& node)
override {
415 auto type = gd::ExpressionTypeFinder::GetType(
416 platform, projectScopedContainers, rootType, node);
418 AddCompletionsForAllIdentifiersMatchingSearch(
"", type);
419 completions.push_back(
421 type,
"", searchedPosition + 1, searchedPosition + 1));
423 void OnVisitOperatorNode(OperatorNode& node)
override {
426 void OnVisitUnaryOperatorNode(UnaryOperatorNode& node)
override {
428 platform, projectScopedContainers, rootType, node);
430 AddCompletionsForAllIdentifiersMatchingSearch(
"", type);
431 completions.push_back(
433 type,
"", searchedPosition + 1, searchedPosition + 1));
435 void OnVisitNumberNode(NumberNode& node)
override {
439 void OnVisitTextNode(TextNode& node)
override {
442 FunctionCallNode* functionCall =
443 dynamic_cast<FunctionCallNode*
>(maybeParentNodeAtLocation);
444 if (functionCall !=
nullptr) {
445 int parameterIndex = -1;
446 for (
int i = 0; i < functionCall->parameters.size(); i++) {
447 if (functionCall->parameters.at(i).get() == &node) {
452 if (parameterIndex < 0) {
456 size_t visibleParameterIndex = 0;
457 size_t metadataParameterIndex =
459 functionCall->objectName, functionCall->behaviorName);
460 const auto& objectsContainersList =
461 projectScopedContainers.GetObjectsContainersList();
463 MetadataProvider::GetFunctionCallMetadata(
464 platform, objectsContainersList, *functionCall);
467 while (metadataParameterIndex <
469 if (!metadata.GetParameters()
472 if (visibleParameterIndex == parameterIndex) {
474 &metadata.GetParameters().
GetParameter(metadataParameterIndex);
476 visibleParameterIndex++;
478 metadataParameterIndex++;
480 const int visibleParameterCount = visibleParameterIndex;
481 if (parameterMetadata ==
nullptr) {
488 if (type ==
"string") {
493 bool isLastParameter = parameterIndex == visibleParameterCount - 1;
498 node.location.GetStartPosition(),
499 node.location.GetEndPosition(),
501 functionCall->objectName));
504 void OnVisitVariableNode(VariableNode& node)
override {
505 const auto& objectsContainersList =
506 projectScopedContainers.GetObjectsContainersList();
508 platform, projectScopedContainers, rootType, node);
512 bool eagerlyCompleteIfExactMatch = node.child ==
nullptr;
515 if (type ==
"globalvar" || type ==
"scenevar") {
516 const auto* variablesContainer =
518 ? projectScopedContainers.GetVariablesContainersList()
519 .GetTopMostVariablesContainer()
520 : projectScopedContainers.GetVariablesContainersList()
521 .GetBottomMostVariablesContainer();
522 if (variablesContainer) {
523 AddCompletionsForVariablesMatchingSearch(
524 *variablesContainer,
"", node.name, node.nameLocation,
525 eagerlyCompleteIfExactMatch);
527 }
else if (type ==
"objectvar") {
529 platform, objectsContainersList, rootObjectName, node);
531 AddCompletionsForObjectOrGroupVariablesMatchingSearch(
532 objectsContainersList, objectName,
"", node.name, node.nameLocation,
533 eagerlyCompleteIfExactMatch);
536 AddCompletionsForObjectsAndVariablesMatchingSearch(
537 node.name, type, node.nameLocation, eagerlyCompleteIfExactMatch);
540 void OnVisitVariableAccessorNode(VariableAccessorNode& node)
override {
541 VariableAndItsParent variableAndItsParent =
542 gd::ExpressionVariablePathFinder::GetLastParentOfNode(
543 platform, projectScopedContainers, node);
546 platform, projectScopedContainers, rootType, node);
547 const auto type = typeAndExtraInfo.type;
548 const auto extraInfo = typeAndExtraInfo.extraInfo;
554 node.child ==
nullptr ? node.name :
"";
555 AddCompletionsForChildrenVariablesOf(variableAndItsParent, extraInfo,
557 eagerlyCompleteForVariableName);
559 void OnVisitVariableBracketAccessorNode(
560 VariableBracketAccessorNode& node)
override {}
561 void OnVisitIdentifierNode(IdentifierNode& node)
override {
562 const auto& objectsContainersList =
563 projectScopedContainers.GetObjectsContainersList();
566 platform, projectScopedContainers, rootType, node);
567 const auto type = typeAndExtraInfo.type;
568 const auto extraInfo = typeAndExtraInfo.extraInfo;
572 AddCompletionsForObjectMatchingSearch(
573 node.identifierName, type, node.location);
575 if (type ==
"globalvar" || type ==
"scenevar") {
576 const auto* variablesContainer =
578 ? projectScopedContainers.GetVariablesContainersList()
579 .GetTopMostVariablesContainer()
580 : projectScopedContainers.GetVariablesContainersList()
581 .GetBottomMostVariablesContainer();
582 if (variablesContainer) {
583 if (IsCaretOn(node.identifierNameDotLocation) ||
584 IsCaretOn(node.childIdentifierNameLocation)) {
586 if (variablesContainer->Has(node.identifierName)) {
587 AddCompletionsForChildrenVariablesOf(
588 variablesContainer->Get(node.identifierName), extraInfo,
589 node.childIdentifierNameLocation, node.childIdentifierName);
596 bool eagerlyCompleteIfPossible =
597 !node.identifierNameDotLocation.IsValid();
598 AddCompletionsForVariablesMatchingSearch(
599 *variablesContainer, extraInfo, node.identifierName,
600 node.identifierNameLocation, eagerlyCompleteIfPossible);
603 }
else if (type ==
"objectvar") {
605 platform, objectsContainersList, rootObjectName, node);
607 if (IsCaretOn(node.identifierNameDotLocation) ||
608 IsCaretOn(node.childIdentifierNameLocation)) {
610 const auto* variablesContainer =
611 objectsContainersList.GetObjectOrGroupVariablesContainer(
613 if (variablesContainer &&
614 variablesContainer->Has(node.identifierName)) {
615 AddCompletionsForChildrenVariablesOf(
616 variablesContainer->Get(node.identifierName), extraInfo,
617 node.childIdentifierNameLocation, node.childIdentifierName);
624 bool eagerlyCompleteIfPossible =
625 !node.identifierNameDotLocation.IsValid();
626 AddCompletionsForObjectOrGroupVariablesMatchingSearch(
627 objectsContainersList, objectName, extraInfo, node.identifierName,
628 node.identifierNameLocation, eagerlyCompleteIfPossible);
633 if (IsCaretOn(node.identifierNameLocation)) {
636 bool eagerlyCompleteIfPossible =
637 !node.identifierNameDotLocation.IsValid();
638 AddCompletionsForAllIdentifiersMatchingSearch(
642 node.identifierNameLocation,
643 eagerlyCompleteIfPossible);
644 if (!node.identifierNameDotLocation.IsValid() &&
646 completions.push_back(
648 type, node.identifierName,
649 node.identifierNameLocation.GetStartPosition(),
650 node.identifierNameLocation.GetEndPosition()));
652 }
else if (IsCaretOn(node.identifierNameDotLocation) ||
653 IsCaretOn(node.childIdentifierNameLocation)) {
657 projectScopedContainers.MatchIdentifierWithName<
void>(
661 const gd::String& objectName = node.identifierName;
662 AddCompletionsForObjectOrGroupVariablesMatchingSearch(
663 objectsContainersList, objectName, extraInfo,
664 node.childIdentifierName, node.childIdentifierNameLocation,
667 completions.push_back(
669 node.childIdentifierName,
670 node.childIdentifierNameLocation.GetStartPosition(),
671 node.childIdentifierNameLocation.GetEndPosition(),
673 completions.push_back(
676 node.childIdentifierName,
677 node.childIdentifierNameLocation.GetStartPosition(),
678 node.childIdentifierNameLocation.GetEndPosition(),
683 VariableAndItsParent variableAndItsParent =
684 gd::ExpressionVariablePathFinder::GetLastParentOfNode(
685 platform, projectScopedContainers, node);
687 AddCompletionsForChildrenVariablesOf(
688 variableAndItsParent,
690 node.childIdentifierNameLocation,
691 node.childIdentifierName);
707 void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node)
override {
709 platform, projectScopedContainers, rootType, node);
710 if (!node.behaviorFunctionName.empty() ||
711 node.behaviorNameNamespaceSeparatorLocation.IsValid()) {
714 if (IsCaretOn(node.objectNameLocation)) {
715 AddCompletionsForObjectMatchingSearch(
716 node.objectName, type, node.objectNameLocation);
717 }
else if (IsCaretOn(node.objectNameDotLocation) ||
718 IsCaretOn(node.objectFunctionOrBehaviorNameLocation)) {
719 completions.push_back(
721 node.objectFunctionOrBehaviorName,
722 node.objectFunctionOrBehaviorNameLocation.GetStartPosition(),
723 node.objectFunctionOrBehaviorNameLocation.GetEndPosition(),
725 }
else if (IsCaretOn(node.behaviorNameNamespaceSeparatorLocation) ||
726 IsCaretOn(node.behaviorFunctionNameLocation)) {
727 completions.push_back(
730 node.behaviorFunctionName,
731 node.behaviorFunctionNameLocation.GetStartPosition(),
732 node.behaviorFunctionNameLocation.GetEndPosition(),
734 node.objectFunctionOrBehaviorName));
738 if (IsCaretOn(node.objectNameLocation)) {
739 AddCompletionsForObjectMatchingSearch(
740 node.objectName, type, node.objectNameLocation);
741 }
else if (IsCaretOn(node.objectNameDotLocation) ||
742 IsCaretOn(node.objectFunctionOrBehaviorNameLocation)) {
743 completions.push_back(
745 node.objectFunctionOrBehaviorName,
746 node.objectFunctionOrBehaviorNameLocation.GetStartPosition(),
747 node.objectFunctionOrBehaviorNameLocation.GetEndPosition(),
749 completions.push_back(
752 node.objectFunctionOrBehaviorName,
753 node.objectFunctionOrBehaviorNameLocation.GetStartPosition(),
754 node.objectFunctionOrBehaviorNameLocation.GetEndPosition(),
759 void OnVisitFunctionCallNode(FunctionCallNode& node)
override {
761 platform, projectScopedContainers, rootType, node);
762 bool isCaretOnParenthesis = IsCaretOn(node.openingParenthesisLocation) ||
763 IsCaretOn(node.closingParenthesisLocation);
765 if (!node.behaviorName.empty()) {
767 if (IsCaretOn(node.objectNameLocation)) {
768 AddCompletionsForObjectMatchingSearch(
769 node.objectName, type, node.objectNameLocation);
770 }
else if (IsCaretOn(node.objectNameDotLocation) ||
771 IsCaretOn(node.behaviorNameLocation)) {
772 completions.push_back(
775 node.behaviorNameLocation.GetStartPosition(),
776 node.behaviorNameLocation.GetEndPosition(),
779 completions.push_back(
783 node.functionNameLocation.GetStartPosition(),
784 node.functionNameLocation.GetEndPosition(),
789 }
else if (!node.objectName.empty()) {
791 if (IsCaretOn(node.objectNameLocation)) {
792 AddCompletionsForObjectMatchingSearch(
793 node.objectName, type, node.objectNameLocation);
800 if (!isCaretOnParenthesis) {
801 completions.push_back(
804 node.objectNameLocation.GetStartPosition(),
805 node.objectNameLocation.GetEndPosition(),
809 completions.push_back(
813 node.functionNameLocation.GetStartPosition(),
814 node.functionNameLocation.GetEndPosition(),
820 completions.push_back(
824 node.functionNameLocation.GetStartPosition(),
825 node.functionNameLocation.GetEndPosition())
829 void OnVisitEmptyNode(EmptyNode& node)
override {
831 platform, projectScopedContainers, rootType, node);
833 AddCompletionsForAllIdentifiersMatchingSearch(
834 node.text, type,
"", node.location);
835 completions.push_back(
839 node.location.GetStartPosition(),
840 node.location.GetEndPosition()));
844 bool IsCaretOn(
const ExpressionParserLocation& location,
845 bool inclusive =
false) {
846 if (!location.IsValid())
return false;
848 return (location.GetStartPosition() <= searchedPosition &&
849 ((!inclusive && searchedPosition < location.GetEndPosition()) ||
850 (inclusive && searchedPosition <= location.GetEndPosition())));
857 bool IsIdentifierSafe(
const gd::String& name) {
858 if (name.
empty())
return false;
860 for (
auto character : name) {
869 void AddCompletionsForChildrenVariablesOf(
870 VariableAndItsParent variableAndItsParent,
872 const ExpressionParserLocation& location,
873 gd::String eagerlyCompleteForVariableName =
"") {
874 if (variableAndItsParent.parentVariable) {
875 AddCompletionsForChildrenVariablesOf(*variableAndItsParent.parentVariable,
876 variableTypeConstraint, location,
877 eagerlyCompleteForVariableName);
878 }
else if (variableAndItsParent.parentVariablesContainer) {
879 AddCompletionsForVariablesMatchingSearch(
880 *variableAndItsParent.parentVariablesContainer,
881 variableTypeConstraint,
"", location);
885 void AddCompletionsForChildrenVariablesOf(
888 const ExpressionParserLocation& location,
889 gd::String eagerlyCompleteForVariableName =
"") {
890 if (variable.
GetType() == gd::Variable::Structure) {
892 if (!IsIdentifierSafe(name))
continue;
894 const auto& childVariable = variable.
GetChild(name);
897 (childVariable.GetType() == gd::Variable::Type::Structure ||
898 childVariable.GetType() == gd::Variable::Type::Array);
901 if (variableTypeConstraint !=
"collection" || isCollection) {
902 ExpressionCompletionDescription description(
903 ExpressionCompletionDescription::Variable,
904 location.GetStartPosition(),
905 location.GetEndPosition());
906 description.SetCompletion(name);
907 description.SetVariableType(childVariable.GetType());
908 completions.push_back(description);
911 if (name == eagerlyCompleteForVariableName) {
912 AddEagerCompletionForVariableChildren(
915 gd::VariablesContainer::SourceType::Unknown,
916 variableTypeConstraint, location);
925 void AddEagerCompletionForVariableChildren(
928 const gd::VariablesContainer::SourceType variableScope,
930 const ExpressionParserLocation& location) {
931 if (variable.
GetType() == gd::Variable::Structure) {
935 IsIdentifierSafe(name)
937 : (variableName +
"[" +
938 gd::ExpressionParser2NodePrinter::PrintStringLiteral(name) +
941 const auto& childVariable = variable.
GetChild(name);
944 (childVariable.GetType() == gd::Variable::Type::Structure ||
945 childVariable.GetType() == gd::Variable::Type::Array);
948 if (variableTypeConstraint !=
"collection" || isCollection) {
949 ExpressionCompletionDescription description(
950 ExpressionCompletionDescription::Variable,
951 location.GetStartPosition(),
952 location.GetEndPosition());
953 description.SetCompletion(completion);
954 description.SetVariableType(childVariable.GetType());
955 description.SetVariableScope(variableScope);
956 completions.push_back(description);
960 if (variable.
GetType() == gd::Variable::Structure ||
961 variable.
GetType() == gd::Variable::Array) {
962 ExpressionCompletionDescription description(
963 ExpressionCompletionDescription::Variable,
964 location.GetStartPosition(), location.GetEndPosition());
965 description.SetCompletion(variableName +
"[]");
966 description.SetVariableType(variable.
GetType());
967 description.SetVariableScope(variableScope);
968 completions.push_back(description);
972 void AddCompletionsForVariablesMatchingSearch(
976 const ExpressionParserLocation& location,
977 bool eagerlyCompleteIfExactMatch =
false) {
981 ExpressionCompletionDescription description(
982 ExpressionCompletionDescription::Variable,
983 location.GetStartPosition(),
984 location.GetEndPosition());
985 description.SetCompletion(variableName);
986 description.SetVariableType(variable.
GetType());
987 description.SetVariableScope(variablesContainer.GetSourceType());
988 completions.push_back(description);
990 if (eagerlyCompleteIfExactMatch && variableName == search) {
991 AddEagerCompletionForVariableChildren(
992 variable, variableName, variablesContainer.GetSourceType(),
993 variableTypeConstraint, location);
998 void AddCompletionsForObjectOrGroupVariablesMatchingSearch(
1003 const ExpressionParserLocation& location,
1004 bool eagerlyCompleteIfExactMatch) {
1006 objectOrGroupName, search,
1009 (variable.
GetType() == gd::Variable::Type::Structure ||
1010 variable.
GetType() == gd::Variable::Type::Array);
1013 if (variableTypeConstraint !=
"collection" || isCollection) {
1014 ExpressionCompletionDescription description(
1015 ExpressionCompletionDescription::Variable,
1016 location.GetStartPosition(), location.GetEndPosition());
1017 description.SetCompletion(variableName);
1018 description.SetVariableType(variable.
GetType());
1019 description.SetVariableScope(gd::VariablesContainer::Object);
1020 completions.push_back(description);
1022 if (eagerlyCompleteIfExactMatch && variableName == search) {
1023 AddEagerCompletionForVariableChildren(
1024 variable, variableName, gd::VariablesContainer::Object,
1025 variableTypeConstraint, location);
1030 void AddCompletionsForObjectMatchingSearch(
1033 const ExpressionParserLocation& location) {
1034 projectScopedContainers.GetObjectsContainersList()
1035 .ForEachNameMatchingSearch(
1039 ExpressionCompletionDescription description(
1040 ExpressionCompletionDescription::Object,
1041 location.GetStartPosition(),
1042 location.GetEndPosition());
1043 description.SetObjectConfiguration(objectConfiguration);
1044 description.SetCompletion(name);
1045 description.SetType(type);
1046 completions.push_back(description);
1050 void AddCompletionsForObjectsAndVariablesMatchingSearch(
1053 const ExpressionParserLocation& location,
1054 bool eagerlyCompleteIfExactMatch) {
1055 projectScopedContainers.ForEachIdentifierMatchingSearch(
1058 const ObjectConfiguration* objectConfiguration) {
1059 ExpressionCompletionDescription description(
1060 ExpressionCompletionDescription::Object,
1061 location.GetStartPosition(),
1062 location.GetEndPosition());
1063 description.SetObjectConfiguration(objectConfiguration);
1064 description.SetCompletion(objectName);
1065 description.SetType(type);
1066 completions.push_back(description);
1069 ExpressionCompletionDescription description(
1070 ExpressionCompletionDescription::Variable,
1071 location.GetStartPosition(),
1072 location.GetEndPosition());
1073 description.SetCompletion(variableName);
1074 description.SetVariableType(variable.
GetType());
1075 auto variableScope =
1076 projectScopedContainers.GetVariablesContainersList()
1077 .GetVariablesContainerFromVariableOrPropertyOrParameterName(
1080 description.SetVariableScope(variableScope);
1081 completions.push_back(description);
1083 if (eagerlyCompleteIfExactMatch && variableName == search) {
1084 AddEagerCompletionForVariableChildren(
1085 variable, variableName, variableScope,
"", location);
1096 void AddCompletionsForAllIdentifiersMatchingSearch(
const gd::String& search,
1098 AddCompletionsForAllIdentifiersMatchingSearch(
1100 ExpressionParserLocation(searchedPosition + 1, searchedPosition + 1));
1103 void AddCompletionsForAllIdentifiersMatchingSearch(
1107 const ExpressionParserLocation& location,
1108 bool eagerlyCompleteIfExactMatch =
false) {
1109 projectScopedContainers.ForEachIdentifierMatchingSearch(
1112 const ObjectConfiguration *objectConfiguration) {
1116 ExpressionCompletionDescription description(
1117 ExpressionCompletionDescription::Object,
1118 location.GetStartPosition(),
1119 location.GetEndPosition());
1120 description.SetObjectConfiguration(objectConfiguration);
1121 description.SetCompletion(objectName);
1122 description.SetType(type);
1123 completions.push_back(description);
1127 (variable.
GetType() == gd::Variable::Type::Structure ||
1128 variable.
GetType() == gd::Variable::Type::Array);
1131 if (extraInfo ==
"collection" && !isCollection) {
1134 ExpressionCompletionDescription description(
1135 ExpressionCompletionDescription::Variable,
1136 location.GetStartPosition(),
1137 location.GetEndPosition());
1138 description.SetCompletion(variableName);
1139 description.SetVariableType(variable.
GetType());
1140 auto variableScope =
1141 projectScopedContainers.GetVariablesContainersList()
1142 .GetVariablesContainerFromVariableOrPropertyOrParameterName(
1145 description.SetVariableScope(variableScope);
1146 completions.push_back(description);
1148 if (eagerlyCompleteIfExactMatch && variableName == search) {
1149 AddEagerCompletionForVariableChildren(
1150 variable, variableName, variableScope, extraInfo, location);
1154 if (extraInfo ==
"collection") {
1158 property.GetType());
1161 ExpressionCompletionDescription description(
1162 ExpressionCompletionDescription::Property,
1163 location.GetStartPosition(), location.GetEndPosition());
1164 description.SetCompletion(property.GetName());
1165 description.SetType(property.GetType());
1166 completions.push_back(description);
1170 if (extraInfo ==
"collection") {
1173 if (parameter.GetValueTypeMetadata().IsNumber() ||
1174 parameter.GetValueTypeMetadata().IsString()) {
1175 ExpressionCompletionDescription description(
1176 ExpressionCompletionDescription::Parameter,
1177 location.GetStartPosition(), location.GetEndPosition());
1178 description.SetCompletion(parameter.GetName());
1179 description.SetType(parameter.GetType());
1180 completions.push_back(description);
1185 ExpressionCompletionFinder(
1189 size_t searchedPosition_,
1191 : searchedPosition(searchedPosition_),
1192 maybeParentNodeAtLocation(maybeParentNodeAtLocation_),
1193 platform(platform_),
1194 projectScopedContainers(projectScopedContainers_),
1195 rootType(rootType_),
1200 std::vector<ExpressionCompletionDescription> completions;
1201 size_t searchedPosition;
Returns the list of completion descriptions for an expression node.
Definition: ExpressionCompletionFinder.h:370
const std::vector< ExpressionCompletionDescription > & GetCompletionDescriptions()
Return the completions found for the visited node.
Definition: ExpressionCompletionFinder.h:407
static std::vector< ExpressionCompletionDescription > GetCompletionDescriptionsFor(const gd::Platform &platform, const gd::ProjectScopedContainers &projectScopedContainers, const gd::String &rootType, gd::ExpressionNode &node, size_t searchedPosition)
Given the expression, find the node at the specified location and returns completions for it.
Definition: ExpressionCompletionFinder.h:377
Find the deepest node at the specified location in an expression.
Definition: ExpressionNodeLocationFinder.h:30
ExpressionNode * GetParentNode()
Return the parent of deepest node found at the search position, if any.
Definition: ExpressionNodeLocationFinder.h:74
ExpressionNode * GetNode()
Return the deepest node found at the search position, if any.
Definition: ExpressionNodeLocationFinder.h:68
static size_t WrittenParametersFirstIndex(const gd::String &objectName, const gd::String &behaviorName)
Definition: ExpressionParser2.h:80
The interface for any worker class ("visitor" pattern) that want to interact with the nodes of a pars...
Definition: ExpressionParser2NodeWorker.h:36
static const gd::TypeAndExtraInfo GetTypeAndExtraInfo(const gd::Platform &platform, const gd::ProjectScopedContainers &projectScopedContainers, const gd::String &rootType, gd::ExpressionNode &node)
Helper function to find the type of the expression or sub-expression that a given node represents.
Definition: ExpressionTypeFinder.h:70
static const gd::String GetType(const gd::Platform &platform, const gd::ProjectScopedContainers &projectScopedContainers, const gd::String &rootType, gd::ExpressionNode &node)
Helper function to find the type of the expression or sub-expression that a given node represents.
Definition: ExpressionTypeFinder.h:56
const gd::String & GetObjectName()
Get all the errors.
Definition: ExpressionVariableOwnerFinder.h:75
Used to describe a property shown in a property grid.
Definition: NamedPropertyDescriptor.h:21
Base class used to represent an object configuration. For example, this can be the animations in a sp...
Definition: ObjectConfiguration.h:38
Represent an object of a platform.
Definition: Object.h:39
A list of objects containers, useful for accessing objects in a scoped way, along with methods to acc...
Definition: ObjectsContainersList.h:29
void ForEachObjectOrGroupVariableMatchingSearch(const gd::String &objectOrGroupName, const gd::String &search, std::function< void(const gd::String &variableName, const gd::Variable &variable)> fn) const
Call the callback for each variable of the object (or group) matching the search passed in parameter.
Definition: ObjectsContainersList.cpp:274
Holds references to variables, objects, properties and other containers.
Definition: ProjectScopedContainers.h:36
String represents an UTF8 encoded string.
Definition: String.h:33
static String From(T value)
Method to create a gd::String from a number (float, double, int, ...)
Definition: String.h:221
void push_back(value_type character)
Add a character (from its codepoint) at the end of the String.
Definition: String.cpp:223
bool empty() const
Returns true if the string is empty.
Definition: String.h:157
Defines a variable which can be used by an object, a layout or a project.
Definition: Variable.h:29
Type
Definition: Variable.h:32
Variable & GetChild(const gd::String &name)
Return the child with the specified name.
Definition: Variable.cpp:149
Type GetType() const
Get the type of the variable.
Definition: Variable.h:64
std::vector< gd::String > GetAllChildrenNames() const
Get the names of all children.
Definition: Variable.cpp:383
Class defining a container for gd::Variable.
Definition: VariablesContainer.h:29
void ForEachVariableMatchingSearch(const gd::String &search, std::function< void(const gd::String &name, const gd::Variable &variable)> fn) const
Call the callback for each variable with a name matching the specified search.
Definition: VariablesContainer.cpp:177
bool IsAllowedInIdentifier(gd::String::value_type character)
Definition: GrammarTerminals.h:110
Definition: CommonTools.h:24
std::ostream & operator<<(std::ostream &os, ExpressionCompletionDescription const &value)
Turn an ExpressionCompletionDescription to a string.
Definition: ExpressionCompletionFinder.cpp:19
Describe completions to be shown to the user.
Definition: ExpressionCompletionFinder.h:40
const gd::String & GetCompletion() const
Return the completion that must be inserted.
Definition: ExpressionCompletionFinder.h:175
const gd::String & GetPrefix() const
Return the prefix that must be completed.
Definition: ExpressionCompletionFinder.h:165
bool operator==(const ExpressionCompletionDescription &other) const
Definition: ExpressionCompletionFinder.h:117
ExpressionCompletionDescription()
Definition: ExpressionCompletionFinder.h:323
bool IsExact() const
Check if the completion description is exact, i.e: it's not used to complete anything....
Definition: ExpressionCompletionFinder.h:225
const gd::String & GetObjectName() const
Return the object name, if completing an object expression or a behavior.
Definition: ExpressionCompletionFinder.h:187
ExpressionCompletionDescription & SetObjectConfiguration(const gd::ObjectConfiguration *objectConfiguration_)
Set the object configuration, in the case the completion is about an object.
Definition: ExpressionCompletionFinder.h:281
ExpressionCompletionDescription & SetParameterMetadata(const gd::ParameterMetadata ¶meterMetadata_)
Set the parameter metadata, in the case the completion is about a parameter of a function call.
Definition: ExpressionCompletionFinder.h:256
gd::VariablesContainer::SourceType GetVariableScope() const
Return the scope of the variable, for a variable completion.
Definition: ExpressionCompletionFinder.h:152
static ExpressionCompletionDescription ForBehaviorWithPrefix(const gd::String &prefix_, size_t replacementStartPosition_, size_t replacementEndPosition_, const gd::String &objectName_)
Create a completion for a behavior with the given prefix, for the specified object.
Definition: ExpressionCompletionFinder.h:62
bool HasParameterMetadata() const
Check if the completion is about a parameter of a function call.
Definition: ExpressionCompletionFinder.h:265
ExpressionCompletionDescription & SetIsLastParameter(bool isLastParameter_)
Set if the expression is the last child of a function call.
Definition: ExpressionCompletionFinder.h:242
const gd::ObjectConfiguration & GetObjectConfiguration() const
Return the parameter metadata, if the completion is about a object. Returns an empty configuration ot...
Definition: ExpressionCompletionFinder.h:299
CompletionKind
Definition: ExpressionCompletionFinder.h:48
size_t GetReplacementStartPosition() const
Return the first character index of the autocompleted part.
Definition: ExpressionCompletionFinder.h:230
const gd::String & GetBehaviorName() const
Return the behavior name, if completing an object behavior expression.
Definition: ExpressionCompletionFinder.h:202
gd::Variable::Type GetVariableType() const
Return the type of the variable, for a variable completion.
Definition: ExpressionCompletionFinder.h:141
size_t GetReplacementEndPosition() const
Return the first character index after the autocompleted part.
Definition: ExpressionCompletionFinder.h:237
static ExpressionCompletionDescription ForTextWithPrefix(const gd::String &type_, const gd::ParameterMetadata ¶meterMetadata_, const gd::String &prefix_, size_t replacementStartPosition_, size_t replacementEndPosition_, const bool isLastParameter_, const gd::String &objectName_="")
Create a completion for a text with the given prefix.
Definition: ExpressionCompletionFinder.h:77
CompletionKind GetCompletionKind() const
Return the kind of the completion.
Definition: ExpressionCompletionFinder.h:125
const gd::String & GetType() const
Return the type of the completion (same type as types supported in expressions). For properties,...
Definition: ExpressionCompletionFinder.h:131
ExpressionCompletionDescription & SetIsExact(bool isExact_)
Set if the completion description is exact, i.e: it's not used to complete anything....
Definition: ExpressionCompletionFinder.h:215
bool HasObjectConfiguration() const
Check if the completion is about an object.
Definition: ExpressionCompletionFinder.h:291
static ExpressionCompletionDescription ForExpressionWithPrefix(const gd::String &type_, const gd::String &prefix_, size_t replacementStartPosition_, size_t replacementEndPosition_, const gd::String &objectName_="", const gd::String &behaviorName_="")
Create a completion for an expression (free, object or behavior expression) with the given prefix.
Definition: ExpressionCompletionFinder.h:99
const gd::ParameterMetadata & GetParameterMetadata() const
Return the parameter metadata, if the completion is about a parameter of a function call....
Definition: ExpressionCompletionFinder.h:273
bool IsLastParameter() const
Check if the expression is the last child of a function call.
Definition: ExpressionCompletionFinder.h:250
The base node, from which all nodes in the tree of an expression inherits from.
Definition: ExpressionParser2Node.h:101