Skip to content

Added primitive argument type checking #44

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 16, 2017
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
2 changes: 2 additions & 0 deletions config/checkstyle/checkstyle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@
<module name="InterfaceIsType"/>
<module name="VisibilityModifier">
<property name="protectedAllowed" value="true"/>
<property name="allowPublicFinalFields" value="true"/>
<property name="allowPublicImmutableFields" value="true"/>
</module>

<!-- Miscellaneous other checks. -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,90 +14,90 @@
public final class CypherBuiltInFunctions {

private static final List<CypherBuiltInFunctionElement> FUNCTIONS_PREDICATE = Lists.newArrayList(
element("all", "(variable IN list WHERE predicate)", BOOLEAN.single()),
element("any", "(variable IN list WHERE predicate)", BOOLEAN.single()),
element("none", "(variable in list WHERE predicate)", BOOLEAN.single()),
element("single", "(variable in list WHERE predicate)", BOOLEAN.single()),
element("exists", "(pattern)", BOOLEAN.single()),
element("exists", "(property)", BOOLEAN.single())
element("all", "(variable IN list WHERE predicate :: ANY)", BOOLEAN.single()),
element("any", "(variable IN list WHERE predicate :: ANY)", BOOLEAN.single()),
element("none", "(variable in list WHERE predicate :: ANY)", BOOLEAN.single()),
element("single", "(variable in list WHERE predicate :: ANY)", BOOLEAN.single()),
element("exists", "(pattern :: ANY)", BOOLEAN.single()),
element("exists", "(property :: ANY)", BOOLEAN.single())
);
private static final List<CypherBuiltInFunctionElement> FUNCTIONS_SHORTEST_PATH = Lists.newArrayList(
element("shortestPath", "(pattern)", PATH.single()),
element("allShortestPaths", "(pattern)", PATH.array())
element("shortestPath", "(pattern :: PATH)", PATH.single()),
element("allShortestPaths", "(pattern :: PATH)", PATH.array())
);
private static final List<CypherBuiltInFunctionElement> FUNCTIONS_SCALAR = Lists.newArrayList(
element("size", "(list)", INTEGER.single()),
element("size", "(pattern)", INTEGER.single()),
element("length", "(path)", INTEGER.single()),
element("length", "(string)", INTEGER.single()),
element("type", "(relationship)", STRING.single()),
element("id", "(node)", INTEGER.single()),
element("id", "(relationship)", INTEGER.single()),
element("coalesce", "(expression...)", ANY.single()),
element("head", "(expression)", ANY.single()),
element("last", "(expression)", ANY.single()),
element("size", "(list :: LIST OF ANY)", INTEGER.single()),
element("size", "(pattern :: ANY)", INTEGER.single()),
element("length", "(path :: ANY)", INTEGER.single()),
element("length", "(string :: STRING)", INTEGER.single()),
element("type", "(relationship :: RELATIONSHIP)", STRING.single()),
element("id", "(node :: NODE)", INTEGER.single()),
element("id", "(relationship :: RELATIONSHIP)", INTEGER.single()),
element("coalesce", "(expression... :: ANY)", ANY.single()),
element("head", "(expression :: LIST OF ANY)", ANY.single()),
element("last", "(expression :: LIST OF ANY)", ANY.single()),
element("timestamp", "()", INTEGER.single()),
element("startNode", "(relationship)", NODE.single()),
element("endNode", "(relationship", NODE.single()),
element("properties", "(node)", MAP.single()),
element("properties", "(relationship)", MAP.single()),
element("toInt", "(expression)", INTEGER.single()),
element("toFloat", "(expression)", FLOAT.single())
element("startNode", "(relationship :: RELATIONSHIP)", NODE.single()),
element("endNode", "(relationship :: RELATIONSHIP)", NODE.single()),
element("properties", "(node :: NODE)", MAP.single()),
element("properties", "(relationship :: RELATIONSHIP)", MAP.single()),
element("toInt", "(expression :: STRING)", INTEGER.single()),
element("toFloat", "(expression :: STRING)", FLOAT.single())
);
private static final List<CypherBuiltInFunctionElement> FUNCTIONS_LIST = Lists.newArrayList(
element("nodes", "(path)", NODE.array()),
element("relationships", "(path)", RELATIONSHIP.array()),
element("labels", "(node)", STRING.array()),
element("keys", "(node)", STRING.array()),
element("keys", "(relationship)", STRING.array()),
element("extract", "(variable IN list | expression)", ANY.array()),
element("filter", "(variable IN list WHERE predicate)", ANY.array()),
element("tail", "(expression)", ANY.array()),
element("range", "(start, end, step = 1)", INTEGER.array()),
element("reduce", "(accumulator = initial, variable IN list | expression)", ANY.single())
element("nodes", "(path :: PATH)", NODE.array()),
element("relationships", "(path :: PATH)", RELATIONSHIP.array()),
element("labels", "(node :: NODE)", STRING.array()),
element("keys", "(node :: NODE)", STRING.array()),
element("keys", "(relationship :: RELATIONSHIP)", STRING.array()),
element("extract", "(variable IN list | expression :: ANY)", ANY.array()),
element("filter", "(variable IN list WHERE predicate :: ANY)", ANY.array()),
element("tail", "(expression :: LIST OF ANY)", ANY.array()),
element("range", "(start :: INTEGER, end :: INTEGER, step = 1 :: INTEGER)", INTEGER.array()),
element("reduce", "(accumulator = initial :: ANY, variable IN list | expression :: ANY)", ANY.single())
);
private static final List<CypherBuiltInFunctionElement> FUNCTIONS_MATH_NUMERIC = Lists.newArrayList(
element("abs", "(expression)", INTEGER.single()),
element("ceil", "(expression)", INTEGER.single()),
element("floor", "(expression)", INTEGER.single()),
element("round", "(expression)", INTEGER.single()),
element("sign", "(expression)", INTEGER.single()),
element("abs", "(expression :: NUMBER)", INTEGER.single()),
element("ceil", "(expression :: NUMBER)", INTEGER.single()),
element("floor", "(expression :: NUMBER)", INTEGER.single()),
element("round", "(expression :: NUMBER)", INTEGER.single()),
element("sign", "(expression :: NUMBER)", INTEGER.single()),
element("rand", "()", FLOAT.single())
);
private static final List<CypherBuiltInFunctionElement> FUNCTIONS_MATH_LOGARITHMIC = Lists.newArrayList(
element("log", "(expression)", FLOAT.single()),
element("log10", "(expression)", FLOAT.single()),
element("exp", "(expression)", FLOAT.single()),
element("log", "(expression :: NUMBER)", FLOAT.single()),
element("log10", "(expression :: NUMBER)", FLOAT.single()),
element("exp", "(expression :: NUMBER)", FLOAT.single()),
element("e", "()", FLOAT.single()),
element("sqrt", "(expression)", FLOAT.single())
element("sqrt", "(expression :: NUMBER)", FLOAT.single())
);
private static final List<CypherBuiltInFunctionElement> FUNCTIONS_MATH_TRIGONOMETRIC = Lists.newArrayList(
element("sin", "(expression)", FLOAT.single()),
element("cos", "(expression)", FLOAT.single()),
element("tan", "(expression)", FLOAT.single()),
element("cot", "(expression)", FLOAT.single()),
element("asin", "(expression)", FLOAT.single()),
element("acos", "(expression)", FLOAT.single()),
element("atan", "(expression)", FLOAT.single()),
element("atan2", "(expression, expression)", FLOAT.single()),
element("sin", "(expression :: NUMBER)", FLOAT.single()),
element("cos", "(expression :: NUMBER)", FLOAT.single()),
element("tan", "(expression :: NUMBER)", FLOAT.single()),
element("cot", "(expression :: NUMBER)", FLOAT.single()),
element("asin", "(expression :: NUMBER)", FLOAT.single()),
element("acos", "(expression :: NUMBER)", FLOAT.single()),
element("atan", "(expression :: NUMBER)", FLOAT.single()),
element("atan2", "(expression :: NUMBER, expression :: NUMBER)", FLOAT.single()),
element("pi", "()", FLOAT.single()),
element("degrees", "(expression)", FLOAT.single()),
element("radians", "(expression)", FLOAT.single()),
element("haversin", "(expression)", FLOAT.single())
element("degrees", "(expression :: NUMBER)", FLOAT.single()),
element("radians", "(expression :: NUMBER)", FLOAT.single()),
element("haversin", "(expression :: NUMBER)", FLOAT.single())
);
private static final List<CypherBuiltInFunctionElement> FUNCTIONS_STRING = Lists.newArrayList(
element("replace", "(original, search, replace)", STRING.single()),
element("substring", "(original, start, length = length(original))", STRING.single()),
element("left", "(original, length)", STRING.single()),
element("right", "(original, length)", STRING.single()),
element("ltrim", "(original)", STRING.single()),
element("rtrim", "(original)", STRING.single()),
element("trim", "(original)", STRING.single()),
element("lower", "(original)", STRING.single()),
element("upper", "(original)", STRING.single()),
element("split", "(original, splitPattern)", STRING.array()),
element("reverse", "(original)", STRING.single()),
element("toString", "(expression)", STRING.single())
element("replace", "(original :: STRING, search :: STRING, replace :: STRING)", STRING.single()),
element("substring", "(original :: STRING, start :: INTEGER, length = length(original) :: INTEGER)", STRING.single()),
element("left", "(original :: STRING, length :: INTEGER)", STRING.single()),
element("right", "(original :: STRING, length :: INTEGER)", STRING.single()),
element("ltrim", "(original :: STRING)", STRING.single()),
element("rtrim", "(original :: STRING)", STRING.single()),
element("trim", "(original :: STRING)", STRING.single()),
element("lower", "(original :: STRING)", STRING.single()),
element("upper", "(original :: STRING)", STRING.single()),
element("split", "(original :: STRING, splitPattern :: STRING)", STRING.array()),
element("reverse", "(original :: STRING)", STRING.single()),
element("toString", "(expression :: STRING)", STRING.single())
);

public static final List<CypherBuiltInFunctionElement> FUNCTIONS = new ArrayList<CypherBuiltInFunctionElement>() {{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,36 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Range;

import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.stream.Stream;

import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toList;

public final class InvokableInformation {

public static class Argument {
public final String name;
public final String type;
public final boolean optional;
public final boolean varArgs;

Argument(String definition) {
String[] s = definition.trim().split("::");
name = s[0].split("=")[0].split("\\.\\.\\.")[0].trim();
type = s.length > 1 ? s[1].trim() : "ANY";
optional = s[0].contains("=");
varArgs = s[0].contains("...");
}
}

private final String name;
private final String signature;
private final String returnType;
private final boolean hasParameters;
private final List<Argument> arguments;
private final Range<Integer> arity;

public InvokableInformation(String fullSignature, String name) {
Expand All @@ -28,6 +49,8 @@ public InvokableInformation(String fullSignature, String name) {

this.name = name;
this.hasParameters = !this.signature.startsWith("()");

this.arguments = parseArguments();
this.arity = calculateArity();
}

Expand All @@ -36,6 +59,8 @@ public InvokableInformation(String name, String signature, String returnType) {
this.signature = signature;
this.returnType = returnType;
this.hasParameters = !Objects.equals(signature, "()");

this.arguments = parseArguments();
this.arity = calculateArity();
}

Expand All @@ -55,25 +80,37 @@ public boolean hasParameters() {
return hasParameters;
}

public List<Argument> getArguments() {
return arguments;
}

public Range<Integer> getArity() {
return arity;
}

private Range<Integer> calculateArity() {
private List<Argument> parseArguments() {
if (!hasParameters) {
return emptyList();
}

return Stream.of(signature.substring(1, signature.length() - 1).split(","))
.map(Argument::new)
.collect(toList());
}

private Range<Integer> calculateArity() {
if (arguments.isEmpty()) {
return new Range<>(0, 0);
}

int from = 0;
int to = 0;
String[] args = signature.substring(1, signature.length() - 1).split(",");
for (String arg : args) {
String p = arg.trim();
if (p.endsWith("...")) {
for (Argument arg : arguments) {
if (arg.varArgs) {
from++;
to = Integer.MAX_VALUE;
break;
} else if (p.contains("=")) {
} else if (arg.optional) {
to++;
} else {
from++;
Expand All @@ -83,4 +120,5 @@ private Range<Integer> calculateArity() {

return new Range<>(from, to);
}

}
Loading