Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.yaml.YAMLTokenTypes;
import org.jetbrains.yaml.psi.YAMLCompoundValue;
import org.jetbrains.yaml.psi.YAMLKeyValue;
import org.jetbrains.yaml.psi.YAMLMapping;
import org.jetbrains.yaml.psi.YAMLScalar;

import java.util.*;
Expand Down Expand Up @@ -265,6 +267,9 @@ public void addCompletions(@NotNull CompletionParameters parameters,
// _defaults:
// bind:
// $<caret>: ''
// service:
// arguments:
// $<caret>: ''
extend(
CompletionType.BASIC,
YamlElementPatternHelper.getNamedDefaultBindPattern(),
Expand Down Expand Up @@ -408,16 +413,66 @@ protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull
* _defaults:
* bind:
* $projectDir: '%kernel.project_dir%'
* foobar:
* arguments:
* $projectDir: '%kernel.project_dir%'
*/
private static class NamedArgumentCompletionProvider extends CompletionProvider<CompletionParameters> {
@Override
protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
HashSet<String> uniqueParameters = new HashSet<>();

PsiElement position = parameters.getPosition();
boolean hasEmptyNextElement = position.getNextSibling() == null;

ServiceContainerUtil.visitNamedArguments(position.getContainingFile(), pair -> {
YAMLMapping serviceDefintion = null;

Collection<Pair<Parameter, Integer>> arguments = new ArrayList<>();

// depending on code complete state we already have a key or not
// then decide if we are inside a "service" or "default bind" scope
if (position.getNode().getElementType() == YAMLTokenTypes.SCALAR_KEY) {
// "$name" key exists
YAMLKeyValue parentOfType = PsiTreeUtil.getParentOfType(position, YAMLKeyValue.class);
YAMLKeyValue parentOfType2 = PsiTreeUtil.getParentOfType(parentOfType, YAMLKeyValue.class);
if (parentOfType2 == null) {
return;
}

String keyText2 = parentOfType2.getKeyText();
if (!"bind".equals(keyText2)) {
serviceDefintion = parentOfType2.getParentMapping();
}
} else {
// "$" its just a text element
YAMLKeyValue parentOfType = PsiTreeUtil.getParentOfType(position, YAMLKeyValue.class);
if (parentOfType == null) {
return;
}

if (!"bind".equals(parentOfType.getKeyText())) {
serviceDefintion = parentOfType.getParentMapping();
}
}

ContainerCollectionResolver.LazyServiceCollector lazyServiceCollector = new ContainerCollectionResolver.LazyServiceCollector(position.getProject());

// visit full file for arguments or current service scope
if (serviceDefintion == null) {
ServiceContainerUtil.visitNamedArguments(position.getContainingFile(), arguments::add);
} else {
@Nullable PhpClass yamlNamedArgumentPhpClass = ServiceContainerUtil.getServicePhpClassFromServiceMapping(serviceDefintion, lazyServiceCollector);
if (yamlNamedArgumentPhpClass != null) {
Method constructor = yamlNamedArgumentPhpClass.getConstructor();
if (constructor != null) {
Parameter @NotNull [] constructorParameters = constructor.getParameters();
for (int i = 0; i < constructorParameters.length; i++) {
arguments.add(Pair.create(constructorParameters[i], i));
}
}
}
}

Set<String> uniqueParameters = new HashSet<>();
for (Pair<Parameter, Integer> pair : arguments) {
Parameter parameter = pair.getFirst();
String parameterName = parameter.getName();
if (uniqueParameters.contains(parameterName)) {
Expand Down Expand Up @@ -445,7 +500,7 @@ protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull

if (!parameter.getType().getTypes().stream().allMatch(PhpType::isPrimitiveType)) {
// $foobar: '@service'
result.addAllElements(getServiceSuggestion(position, pair, parameterName, new ContainerCollectionResolver.LazyServiceCollector(position.getProject())));
result.addAllElements(getServiceSuggestion(position, pair, parameterName, lazyServiceCollector));
} else {
String parameterNormalized = parameterName.toLowerCase(Locale.ROOT).replaceAll("[^a-z0-9]", "");
if (parameterNormalized.length() > 5) {
Expand All @@ -457,9 +512,14 @@ protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull
}
}
}
});
}
}

/**
* Matched service name on instance
*
* $foobar: '@service'
*/
@NotNull
private Collection<LookupElement> getServiceSuggestion(@NotNull PsiElement position, @NotNull Pair<Parameter, Integer> pair, @NotNull String parameterName, @NotNull ContainerCollectionResolver.LazyServiceCollector lazyServiceCollector) {
Parameter parameter = pair.getFirst();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -804,7 +804,7 @@ public static ElementPattern<PsiElement> getPhpConstPattern() {
* arguments:
* $<caret>
*/
static ElementPattern<PsiElement> getNamedDefaultBindPattern() {
public static ElementPattern<PsiElement> getNamedDefaultBindPattern() {
// "__defaults" key
PsiElementPattern.Capture<YAMLMapping> defaultsKey = PlatformPatterns.psiElement(YAMLMapping.class).withParent(PlatformPatterns.psiElement(YAMLKeyValue.class).with(new PatternCondition<YAMLKeyValue>("KeyText") {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,17 @@ public static String getServiceClassFromServiceMapping(@NotNull YAMLMapping yaml
return null;
}

@Nullable
public static PhpClass getServicePhpClassFromServiceMapping(@NotNull YAMLMapping yamlMapping, @NotNull ContainerCollectionResolver.LazyServiceCollector lazyServiceCollector) {
String serviceId = getServiceClassFromServiceMapping(yamlMapping);
if (StringUtils.isNotBlank(serviceId)) {
return ServiceUtil.getResolvedClassDefinition(yamlMapping.getProject(), serviceId, lazyServiceCollector);
}

return null;
}


/**
* <services>
* <service class="Foo\\Bar\\Car">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,16 @@ public void testNamedArgumentCompletionForServiceArguments() {
"$myDateTime: '@foo'"
);

assertCompletionNotContains(YAMLFileType.YML, "" +
"services:\n" +
" Foo\\Bus: ~\n" +
"\n" +
" Foo\\Car:\n" +
" arguments:\n" +
" $<caret>\n",
"$myBus"
);

assertCompletionContains(YAMLFileType.YML, "" +
"services:\n" +
" Foo\\Car:\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,9 @@ function __construct(\string $projectDir, \string $foobarEnv, \MyDateTime $myDat
{
}
}

class Bus
{
function __construct($myBus) { }
}
}