Skip to content

Commit

Permalink
Provide filter field completion in CMS Framework Model::get()
Browse files Browse the repository at this point in the history
  • Loading branch information
klesun-itn committed Nov 5, 2018
1 parent dff03d6 commit 4bb771d
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 38 deletions.
6 changes: 3 additions & 3 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.10.31.001</version>
<version>2018.11.05.001</version>
<vendor email="safronevev@gmail.com" url="http://midiana.lv/entry/phpstorm-deep-keys">Klesun</vendor>

<description><![CDATA[
Expand Down Expand Up @@ -37,8 +37,8 @@ This plugin greatly extends phpstorm's typing with associative array support<br/

<change-notes><![CDATA[
<ul>
<li>#53 Use type info from func arg default value</li>
<li>Support closure use vars</li>
<li>Provide filter field completion in CMS Framework Model::get()</li>
<li>Infer type from `public $field` deep-format doc comment</li>
</ul>
]]>
</change-notes>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,15 @@ private It<DeepType> findKeysUsedInPdoExec(Function meth, ParameterList argList,
.map(varName -> T2(varName, pdostt.definition))));
}

private It<DeepType> findKeysUsedInModelGet(Function func, ParameterList argList, PhpExpression arrCtor)
{
return Tls.cast(Method.class, func)
.flt(m -> L(argList.getParameters()).indexOf(arrCtor) == 0)
.fap(meth -> opt(argList.getParent())
.cst(MethodReference.class)
.fap(methCall -> (new MethCallRes(fakeCtx)).getModelRowType(methCall, meth)));
}

public It<DeepType> findKeysUsedOnExpr(PhpExpression arrCtor)
{
return opt(arrCtor.getParent())
Expand All @@ -215,6 +224,7 @@ public It<DeepType> findKeysUsedOnExpr(PhpExpression arrCtor)
.fap(n -> resolveReplaceKeys(argList, order).types),
findKeysUsedInArrayMap(meth, argList, arrCtor),
findKeysUsedInPdoExec(meth, argList, arrCtor),
findKeysUsedInModelGet(meth, argList, arrCtor),
opt(argList.getParent())
.fop(toCast(NewExpressionImpl.class))
.fap(newEx -> findClsMagicCtorUsedKeys(newEx, order).types)
Expand Down
71 changes: 39 additions & 32 deletions src/org/klesun/deep_assoc_completion/resolvers/MethCallRes.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,10 @@
import com.jetbrains.php.PhpIndex;
import com.jetbrains.php.lang.documentation.phpdoc.psi.tags.PhpDocReturnTag;
import com.jetbrains.php.lang.psi.elements.*;
import com.jetbrains.php.lang.psi.elements.impl.ClassReferenceImpl;
import com.jetbrains.php.lang.psi.elements.impl.MethodReferenceImpl;
import com.jetbrains.php.lang.psi.resolve.types.PhpType;
import org.klesun.deep_assoc_completion.DeepType;
import org.klesun.deep_assoc_completion.helpers.FuncCtx;
import org.klesun.deep_assoc_completion.helpers.IExprCtx;
import org.klesun.deep_assoc_completion.helpers.IFuncCtx;
import org.klesun.deep_assoc_completion.helpers.Mt;
import org.klesun.deep_assoc_completion.resolvers.var_res.DocParamRes;
import org.klesun.lang.*;
Expand Down Expand Up @@ -112,34 +109,17 @@ public String next() {
});
}

private It<DeepType> findBuiltInRetType(Method meth, IExprCtx argCtx, MethodReference methCall)
public It<DeepType> getModelRowType(MethodReference methCall, Method meth)
{
It<DeepType> types = It(list());
// treating any class named "Model" as a base ORM class for Doctrine/Eloquent/CustomStuff completion
String clsNme = opt(meth.getContainingClass()).map(cls -> cls.getName()).def("");
if (clsNme.equals("PDO") && meth.getName().equals("query") ||
clsNme.equals("PDO") && meth.getName().equals("prepare")
) {
DeepType type = new DeepType(methCall);
argCtx.func().getArg(0)
.fap(mt -> mt.types)
.fch(strType -> {
DeepType fetchType = parseSqlSelect(strType, meth.getProject());
type.pdoFetchTypes.add(fetchType);
getBindVars(strType).fch(type.pdoBindVars::add);
});
types = It(list(type));
} else if (clsNme.equals("PDOStatement") && meth.getName().equals("fetch")) {
It<DeepType> pdoTypes = opt(methCall.getClassReference())
.fop(toCast(PhpExpression.class))
.fap(obj -> ctx.findExprType(obj))
.fap(t -> t.pdoFetchTypes);
types = It(pdoTypes);
} else if (clsNme.equals("Model") && meth.getName().equals("get")) {
// treating any class named "Model" as a base ORM class for Doctrine/Eloquent/CustomStuff completion
MemoizingIterable<PhpType> callsClsType = new MiscRes(ctx).resolveClassReferenceFromMember(methCall).mem();
return Tls.ifi(
clsNme.equals("Model") && meth.getName().equals("get"),
() -> new MiscRes(ctx).resolveClassReferenceFromMember(methCall)
).fap(ideaType -> {
Mutable<Boolean> isAssoc = new Mutable<>(false);
It<T2<String, PsiElement>> fieldNames = callsClsType
.fap(ideaType -> ArrCtorRes.resolveIdeaTypeCls(ideaType, methCall.getProject()))
It<T2<String, PsiElement>> fieldNames =
ArrCtorRes.resolveIdeaTypeCls(ideaType, methCall.getProject())
.fap(callCls -> It.cnc(som(callCls), It(callCls.getSupers())).end(sup -> sup.getName().equals("Model")).unq())
.fap(callCls -> callCls.getFields())
// could also add here "getFields" functions, not just "fields" property
Expand All @@ -157,13 +137,40 @@ private It<DeepType> findBuiltInRetType(Method meth, IExprCtx argCtx, MethodRefe
return keyTypes.fap(t -> opt(t.stringValue).map(str -> T2(str, t.definition)));
})
.unq(t2 -> t2.a);
It<DeepType> rowTypes = It.cnc(
callsClsType.map(ideaType -> new DeepType(methCall, ideaType)),
return It.cnc(
som(new DeepType(methCall, ideaType)),
som(KeyUsageResolver.makeAssoc(methCall, fieldNames))
);
DeepType rowArrType = Mt.getInArraySt(rowTypes, methCall);
types = It(som(rowArrType));
});
}

private It<DeepType> findBuiltInRetType(Method meth, IExprCtx argCtx, MethodReference methCall)
{
It<DeepType> types = It(list());
String clsNme = opt(meth.getContainingClass()).map(cls -> cls.getName()).def("");
if (clsNme.equals("PDO") && meth.getName().equals("query") ||
clsNme.equals("PDO") && meth.getName().equals("prepare")
) {
DeepType type = new DeepType(methCall);
argCtx.func().getArg(0)
.fap(mt -> mt.types)
.fch(strType -> {
DeepType fetchType = parseSqlSelect(strType, meth.getProject());
type.pdoFetchTypes.add(fetchType);
getBindVars(strType).fch(type.pdoBindVars::add);
});
types = It(list(type));
} else if (clsNme.equals("PDOStatement") && meth.getName().equals("fetch")) {
It<DeepType> pdoTypes = opt(methCall.getClassReference())
.fop(toCast(PhpExpression.class))
.fap(obj -> ctx.findExprType(obj))
.fap(t -> t.pdoFetchTypes);
types = It(pdoTypes);
}
It<DeepType> modelRowTypes = getModelRowType(methCall, meth);
It<DeepType> modelRowArrTypes = !modelRowTypes.has() ? It.non() :
It(som(Mt.getInArraySt(modelRowTypes, methCall)));
types = It.cnc(types, modelRowArrTypes);
return types;
}

Expand Down
6 changes: 3 additions & 3 deletions src/org/klesun/lang/Tls.java
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,12 @@ public static <T> T ife(boolean cond, S<T> then, S<T> els)
}
}

public static <T> Iterable<T> ifi(boolean cond, S<Iterable<T>> then)
public static <T> It<T> ifi(boolean cond, S<Iterable<T>> then)
{
if (cond) {
return then.get();
return It(then.get());
} else {
return list();
return It(list());
}
}
}

0 comments on commit 4bb771d

Please sign in to comment.