Skip to content

Commit

Permalink
Provide completion when typing accessed key from a function in @param
Browse files Browse the repository at this point in the history
…tag
  • Loading branch information
klesun committed May 23, 2018
1 parent 4a45eb4 commit bfa6a63
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 29 deletions.
7 changes: 3 additions & 4 deletions resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<idea-plugin>
<id>lv.midiana.misc.phpstorm-plugins.deep-keys</id>
<name>deep-assoc-completion</name>
<version>2018.05.22.001</version>
<version>2018.05.24.001</version>
<vendor email="safronevev@gmail.com" url="http://midiana.lv/entry/phpstorm-deep-keys">Klesun</vendor>

<description><![CDATA[
Expand Down Expand Up @@ -29,9 +29,8 @@ This plugin greatly extends phpstorm's associative array completion and typing<b

<change-notes><![CDATA[
<ul>
<li>Allow specifying keys in @return php doc</li>
<li>Provide string completion in array_intersect()</li>
<li>Provide completion in the _needle_ arg in in_array, not just _haystack_</li>
<li>Provide completion when typing accessed key from a function in @param tag</li>
<li>Small fixes</li>
</ul>
]]>
</change-notes>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,33 @@ public void handleInsert(InsertionContext ctx)
}
}

public static MultiType resolveAtPsi(PsiElement caretPsi, SearchContext search)
{
FuncCtx funcCtx = new FuncCtx(search);
return opt(caretPsi.getParent())
.map(litRaw -> litRaw.getParent())
.fop(toCast(ArrayIndex.class))
.map(index -> index.getParent())
.fop(toCast(ArrayAccessExpression.class))
.map(expr -> expr.getValue())
.fop(toCast(PhpExpression.class))
.map(srcExpr -> funcCtx.findExprType(srcExpr))
.def(MultiType.INVALID_PSI);
}

public static LookupElement makeFullLookup(MultiType mt, String keyName)
{
MultiType keyMt = mt.getKey(keyName);
String briefValue = keyMt.getBriefValueText(BRIEF_TYPE_MAX_LEN);
String ideaTypeStr = keyMt.getIdeaType().filterUnknown().toStringResolved();
return makePaddedLookup(keyName, ideaTypeStr, briefValue);
}

@Override
protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext processingContext, @NotNull CompletionResultSet result)
{
int depth = getMaxDepth(parameters.isAutoPopup());
SearchContext search = new SearchContext().setDepth(depth);
FuncCtx funcCtx = new FuncCtx(search);

Set<String> suggested = new HashSet<>();
PsiElement caretPsi = parameters.getPosition(); // usually leaf element
Opt<PsiElement> firstParent = opt(caretPsi.getParent());
Expand All @@ -114,15 +134,7 @@ protected void addCompletions(@NotNull CompletionParameters parameters, Processi
.uni(l -> false, () -> true); // else just inside []

long startTime = System.nanoTime();
MultiType mt = firstParent
.map(litRaw -> litRaw.getParent())
.fop(toCast(ArrayIndex.class))
.map(index -> index.getParent())
.fop(toCast(ArrayAccessExpression.class))
.map(expr -> expr.getValue())
.fop(toCast(PhpExpression.class))
.map(srcExpr -> funcCtx.findExprType(srcExpr))
.def(MultiType.INVALID_PSI);
MultiType mt = resolveAtPsi(caretPsi, search);

L<String> keyNames = mt.getKeyNames();
L<MutableLookup> lookups = L();
Expand Down Expand Up @@ -173,12 +185,7 @@ protected void addCompletions(@NotNull CompletionParameters parameters, Processi
// completion options and updates them in the dialog

Dict<LookupElement> nameToNewLookup = keyNames.key(keyName -> keyName)
.map(keyName -> mt.getKey(keyName))
.map((keyMt, keyName) -> {
String briefValue = keyMt.getBriefValueText(BRIEF_TYPE_MAX_LEN);
String ideaTypeStr = keyMt.getIdeaType().filterUnknown().toStringResolved();
return makePaddedLookup(keyName, ideaTypeStr, briefValue);
});
.map(keyName -> makeFullLookup(mt, keyName));

lookups.fch(l -> nameToNewLookup.gat(l.getKeyName()).thn(newL -> l.lookupData = newL));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@
import com.intellij.codeInsight.completion.impl.CamelHumpMatcher;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFileFactory;
import com.intellij.util.ProcessingContext;
import com.jetbrains.php.PhpIndex;
import com.jetbrains.php.lang.PhpLanguage;
import com.jetbrains.php.lang.psi.elements.*;
import org.jetbrains.annotations.NotNull;
import org.klesun.deep_assoc_completion.helpers.SearchContext;
import org.klesun.lang.Opt;
import org.klesun.lang.Tls;

import java.util.*;

import static org.klesun.deep_assoc_completion.completion_providers.DeepKeysPvdr.getMaxDepth;
import static org.klesun.lang.Lang.L;
import static org.klesun.lang.Lang.list;
import static org.klesun.lang.Lang.opt;
Expand All @@ -29,9 +33,8 @@ private static String makeMethOrderValue(Method meth)
return result;
}

private Opt<List<String>> extractTypedFqnPart(String docValue, Project project)
private Opt<List<String>> extractTypedFqnPart(String docValue, PhpIndex idx)
{
PhpIndex idx = PhpIndex.getInstance(project);
return Opt.fst(list(opt(null)
, Tls.regex(" *= *([A-Z][A-Za-z0-9_]+)::([a-zA-Z0-9_]*?)(IntellijIdeaRulezzz.*)?", docValue)
// have to complete method
Expand Down Expand Up @@ -61,11 +64,32 @@ private Opt<List<String>> extractTypedFqnPart(String docValue, Project project)
@Override
protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext processingContext, @NotNull CompletionResultSet result)
{
int depth = getMaxDepth(parameters.isAutoPopup());
SearchContext search = new SearchContext().setDepth(depth);

opt(parameters.getPosition().getParent())
.thn(literal -> extractTypedFqnPart(literal.getText(), literal.getProject())
.thn(options -> L(options)
.map((lookup) -> LookupElementBuilder.create(lookup))
.fch(result::addElement))
.els(() -> result.addLookupAdvertisement("No FQN-s found with such partial name - " + literal.getText())));
.thn(literal -> {
String docValue = literal.getText();
Project project = literal.getProject();
PhpIndex idx = PhpIndex.getInstance(project);
// method name completion
extractTypedFqnPart(docValue, idx)
.thn(options -> L(options)
.map((lookup) -> LookupElementBuilder.create(lookup))
.fch(result::addElement))
.els(() -> result.addLookupAdvertisement("No FQN-s found with such partial name - " + literal.getText()));

// assoc array completion
String prefix = "<?php\n$arg = ";
Tls.regex("^\\s*=\\s*(.+)$", docValue)
.fop(match -> match.gat(0))
.map(expr -> prefix + expr + ";")
.map(expr -> PsiFileFactory.getInstance(project).createFileFromText(PhpLanguage.INSTANCE, expr))
.map(file -> file.findElementAt(file.getText().indexOf("IntellijIdeaRulezzz")))
.map(psi -> DeepKeysPvdr.resolveAtPsi(psi, search))
.fap(mt -> mt.getKeyNames().map(k -> DeepKeysPvdr.makeFullLookup(mt, k)))
.fch(result::addElement)
;
});
}
}
5 changes: 4 additions & 1 deletion tests/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,10 @@ private static function testLaravelModelCtorParams()
]);
}

private static function testInArray()
/**
* @param $asd = PersonStorage::addPerson()['']
*/
private static function testInArray($asd)
{
$i = rand(0, 3);
$types = ['AIR', 'CAR', 'HOTEL', 'RAIL'];
Expand Down

0 comments on commit bfa6a63

Please sign in to comment.