Skip to content

Commit

Permalink
Remember comment next to key if any and show it in completion popup
Browse files Browse the repository at this point in the history
  • Loading branch information
klesun committed Nov 15, 2018
1 parent af9b41f commit 83be277
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 18 deletions.
10 changes: 9 additions & 1 deletion src/org/klesun/deep_assoc_completion/DeepType.java
Original file line number Diff line number Diff line change
Expand Up @@ -146,17 +146,25 @@ public static class Key
final private L<PhpType> briefTypes = L();
// where Go To Definition will lead
final public PsiElement definition;
public Set<String> comments = new LinkedHashSet<>();

private Key(KeyType keyType, PsiElement definition)
{
this.keyType = keyType;
this.definition = definition;
}

public void addType(S<Mt> getter, PhpType briefType)
public Key addType(S<Mt> getter, PhpType briefType)
{
typeGetters.add(Tls.onDemand(getter));
briefTypes.add(briefType);
return this;
}

public Key addComments(Iterable<String> comments)
{
comments.forEach(this.comments::add);
return this;
}

public void addType(S<Mt> getter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
*/
public class DeepKeysPvdr extends CompletionProvider<CompletionParameters>
{
final private static int BRIEF_TYPE_MAX_LEN = 50;
final private static int BRIEF_VALUE_MAX_LEN = 50;

private static ImageIcon icon = null;

Expand Down Expand Up @@ -70,15 +70,15 @@ private static InsertHandler<LookupElement> makeInsertHandler()
};
}

private static LookupElement makePaddedLookup(String keyName, String ideaType, String briefVal)
private static LookupElementBuilder makePaddedLookup(String keyName, String ideaType, String briefVal)
{
ideaType = !ideaType.equals("") ? ideaType : "?";

// (keyName + briefVal) length must be constant for all keys, or you'll
// get nasty broken position of type when you highlight an option
briefVal = briefVal.trim().equals("") ? "" : " = " + briefVal;
briefVal = briefVal + " ";
briefVal = Tls.substr(briefVal, 0, BRIEF_TYPE_MAX_LEN - keyName.length());
briefVal = Tls.substr(briefVal, 0, BRIEF_VALUE_MAX_LEN - keyName.length());
return LookupElementBuilder.create(keyName)
.withBoldness(!Tls.isNum(keyName))
.withInsertHandler(makeInsertHandler())
Expand All @@ -93,11 +93,11 @@ private static LookupElement makePaddedLookup(String keyName, String ideaType, S
*/
static class MutableLookup extends LookupElement
{
public LookupElement lookupData;
public LookupElementBuilder lookupData;
private boolean includeQuotes;
private InsertHandler<LookupElement> onInsert = makeInsertHandler();

public MutableLookup(LookupElement lookupData, boolean includeQuotes) {
public MutableLookup(LookupElementBuilder lookupData, boolean includeQuotes) {
this.lookupData = lookupData;
this.includeQuotes = includeQuotes;
}
Expand Down Expand Up @@ -133,10 +133,14 @@ public static It<DeepType> resolveAtPsi(PsiElement caretPsi, IExprCtx funcCtx)
.fap(srcExpr -> funcCtx.findExprType(srcExpr));
}

public static LookupElement makeFullLookup(Mt mt, String keyName)
public static LookupElementBuilder makeFullLookup(Mt mt, String keyName, Set<String> comments)
{
Mt keyMt = mt.types.fap(t -> Mt.getKeySt(t, keyName)).wap(Mt::new);
String briefValue = keyMt.getBriefValueText(BRIEF_TYPE_MAX_LEN);
String comment = Tls.implode(" ", comments);
String briefValue = keyMt.getBriefValueText(BRIEF_VALUE_MAX_LEN);
if (!comment.trim().equals("")) {
briefValue = Tls.substr(briefValue, 0, 12) + " " + comment;
}
String ideaTypeStr = keyMt.getIdeaType().filterUnknown().toStringResolved();
return makePaddedLookup(keyName, ideaTypeStr, briefValue);
}
Expand Down Expand Up @@ -167,12 +171,13 @@ protected void addCompletions(@NotNull CompletionParameters parameters, Processi

long startTime = System.nanoTime();
Mutable<Long> firstTime = new Mutable<>(-1L);
L<MutableLookup> lookups = L();
Dict<MutableLookup> nameToMutLookup = new Dict<>(new LinkedHashMap<>());
// preliminary keys without type - they may be at least 3 times faster in some cases

ExprCtx exprCtx = new ExprCtx(funcCtx, caretPsi, 0);
It<DeepType> tit = resolveAtPsi(caretPsi, exprCtx);
Set<String> keyNames = new LinkedHashSet<>();
Map<String, Set<String>> keyToComments = new HashMap<>();
System.out.println("gonna start iterating with " + search.getExpressionsResolved() + " expression already resolved");
tit.has();
System.out.println("checked if iterator has anything, took " + search.getExpressionsResolved() + " expressions");
Expand All @@ -188,22 +193,34 @@ protected void addCompletions(@NotNull CompletionParameters parameters, Processi
} else {
keyNamesToAdd.add(kt.stringValue);
}
keyNamesToAdd = keyNamesToAdd.flt(kn -> !keyNames.contains(kn)).arr();
for (String keyName: keyNamesToAdd) {
L<String> newKeyNamesToAdd = keyNamesToAdd.flt(kn -> !keyNames.contains(kn)).arr();
for (String keyName: newKeyNamesToAdd) {
if (firstTime.get() == -1) {
System.out.println("resolved " + search.getExpressionsResolved() + " expressions for first key - " + keyName);
firstTime.set(System.nanoTime() - startTime);
}
keyNames.add(keyName);
LookupElement justName = makePaddedLookup(keyName, "resolving...", "");
LookupElementBuilder justName = makePaddedLookup(keyName, "resolving...", "");
MutableLookup mutLookup = new MutableLookup(justName, includeQuotes);
int basePriority = Tls.isNum(keyName) ? 2000 : 2500;
result.addElement(PrioritizedLookupElement.withPriority(mutLookup, basePriority - keyNames.size()));
lookups.add(mutLookup);
nameToMutLookup.put(keyName, mutLookup);

String briefTypeRaw = Mt.getKeyBriefTypeSt(k.getBriefTypes()).filterUnknown().toStringResolved();
mutLookup.lookupData = makePaddedLookup(keyName, briefTypeRaw, "");
}
String comment = Tls.implode(" ", k.comments);
if (!comment.trim().equals("")) {
keyNamesToAdd.fch(name -> {
opt(nameToMutLookup.get(name)).thn(mutLookup -> {
mutLookup.lookupData = mutLookup.lookupData.withTailText(" " + Tls.substr(comment, 0, BRIEF_VALUE_MAX_LEN), true);
});
if (!keyToComments.containsKey(name)) {
keyToComments.put(name, new LinkedHashSet<>());
}
keyToComments.get(name).addAll(k.comments);
});
}
});
});
long elapsed = System.nanoTime() - startTime;
Expand All @@ -221,7 +238,7 @@ protected void addCompletions(@NotNull CompletionParameters parameters, Processi
.map(n -> n.equals("")|| n.equals("IntellijIdeaRulezzz"))
.def(false);

lookups.map(l -> l.getLookupString()).fch(el -> suggested.add(el));
nameToMutLookup.map(l -> l.getLookupString()).fch(el -> suggested.add(el));
result.runRemainingContributors(parameters, otherSourceResult -> {
// remove dupe built-in suggestions
LookupElement lookup = otherSourceResult.getLookupElement();
Expand All @@ -236,11 +253,11 @@ protected void addCompletions(@NotNull CompletionParameters parameters, Processi
// following code calculates deeper type info for
// completion options and updates them in the dialog

Dict<MutableLookup> nameToMutLookup = lookups.key(l -> l.lookupData.getLookupString());
nameToMutLookup
.fch((mutLook, keyName) -> {
search.overrideMaxExpr = som(search.getExpressionsResolved() + 25);
LookupElement lookup = makeFullLookup(mt, keyName);
Set<String> comments = opt(keyToComments.get(keyName)).def(new HashSet<>());
LookupElementBuilder lookup = makeFullLookup(mt, keyName, comments);
search.overrideMaxExpr = non();
mutLook.lookupData = lookup;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import org.klesun.lang.Opt;
import org.klesun.lang.Tls;

import java.util.HashSet;

import static org.klesun.deep_assoc_completion.completion_providers.DeepKeysPvdr.getMaxDepth;
import static org.klesun.lang.Lang.*;

Expand Down Expand Up @@ -96,7 +98,7 @@ private It<LookupElement> parseDocValue(String docValue, SearchContext search, P
opt(PsiFileFactory.getInstance(tagValue.getProject()).createFileFromText(PhpLanguage.INSTANCE, prefix + expr + ";"))
.map(file -> file.findElementAt(file.getText().indexOf("IntellijIdeaRulezzz")))
.map(psi -> DeepKeysPvdr.resolveAtPsi(psi, exprCtx).wap(Mt::new))
.fap(mt -> mt.getKeyNames().map(k -> DeepKeysPvdr.makeFullLookup(mt, k)))
.fap(mt -> mt.getKeyNames().map(k -> DeepKeysPvdr.makeFullLookup(mt, k, new HashSet<>())))
));
}

Expand Down
56 changes: 55 additions & 1 deletion src/org/klesun/deep_assoc_completion/resolvers/ArrCtorRes.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.tree.PsiCommentImpl;
import com.intellij.psi.impl.source.tree.PsiWhiteSpaceImpl;
import com.jetbrains.php.PhpIndex;
import com.jetbrains.php.lang.psi.elements.*;
import com.jetbrains.php.lang.psi.elements.impl.ArrayCreationExpressionImpl;
Expand Down Expand Up @@ -117,6 +119,57 @@ private It<Method> resolveMethodFromArray(L<PsiElement> refParts)
.fop(cls -> opt(cls.findMethodByName(met))));
}

private static int getIndent(PsiElement psi)
{
return opt(psi.getPrevSibling())
.cst(PsiWhiteSpaceImpl.class)
.fop(ws -> Tls.regex("^(.*\\n|)(\\s*?)$", ws.getText()))
.fop(ma -> ma.gat(1))
.map(space -> space.length())
.def(0);
}

private static L<String> getTopComments(ArrayHashElement hashEl)
{
L<String> comments = list();
PsiElement prev = hashEl.getPrevSibling();
int indent = getIndent(hashEl);
while (prev != null) {
boolean shouldSkip = prev instanceof PsiWhiteSpaceImpl;
if (prev instanceof PsiCommentImpl && getIndent(prev) == indent) {
comments.add(0, prev.getText());
} else if (!shouldSkip) {
break;
}
prev = prev.getPrevSibling();
}
return comments;
}

// probably it would be good to also support comments like this:
// 'someKey' => 213, // some key 1 description line 1
// // still key 1 description line 2
// 'someKey2' => 213, //bla bla about key 2
private static Opt<String> getSideComments(ArrayHashElement hashEl)
{
PsiElement next = hashEl.getNextSibling();
while (next != null) {
boolean shouldSkip = next instanceof PsiWhiteSpaceImpl || next.getText().equals(",");
if (next instanceof PsiCommentImpl) {
return som(((PsiCommentImpl)next).getText());
} else if (!shouldSkip || next.getText().contains("\n")) {
return non();
}
next = next.getNextSibling();
}
return non();
}

private static It<String> gatherSurroundingComments(ArrayHashElement hashEl)
{
return It.cnc(getTopComments(hashEl), getSideComments(hashEl));
}

public DeepType resolve(ArrayCreationExpressionImpl expr)
{
DeepType arrayType = new DeepType(expr);
Expand Down Expand Up @@ -151,7 +204,8 @@ public DeepType resolve(ArrayCreationExpressionImpl expr)
if (keyStrValues.has()) {
keyStrValues.fch(key -> arrayType
.addKey(key, ctx.getRealPsi(keyRec))
.addType(getType, Tls.getIdeaType(v)));
.addType(getType, Tls.getIdeaType(v))
.addComments(gatherSurroundingComments(keyRec)));
} else {
arrayType.addKey(KeyType.unknown(keyRec)).addType(getType);
}
Expand Down
41 changes: 41 additions & 0 deletions tests/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,47 @@ private function testExtract()
$somePrefix_gender;
}

/** @param $sale = [
* 'netPrice' => '500.89' , // price without taxes
* // or 'ticket', 'insurance', 'tablet'
* 'product' => 'car',
* // the person that gives you the money
* // maybe a man, a woman, or a programmer
* 'customer' => [
* 'lastName' => 'Pupkin',
* 'firstNme' => 'Vasya',
* ],
* ] */
private function testKeyDocs($sale)
{
// should include the comment in completion popup
$sale[''];
$hale = [
'netPrice' => '500.89', // price without taxes actually very long comment
// or 'ticket', 'insurance', 'tablet'
'product' => 'car' ,
// the person that gives you the money
// may be a man, a woman, or a programmer
'customer' => [
'lastName' => 'Pupkin',
'firstNme' => 'Vasya',
],
];
$hale[''];
$car = [
'model' => 'Mitsubishi G199', /* cars with same model are usually same */
/**
* consists of letters that describe car features
* like conditioning, wheel/door count, etc...
*/
'carCode' => 'ECAR',
'requiredLicense' => 'lightweight', // I never studied in driving school,
// but I heard there is such stuff
'sadad' => 123 // last element
];
$car[''];
}

//============================
// not implemented follow
//============================
Expand Down

0 comments on commit 83be277

Please sign in to comment.