package com.google.jstestdriver.idea.assertFramework.jasmine;
import com.google.jstestdriver.idea.assertFramework.AbstractTestFileStructureBuilder;
import com.google.jstestdriver.idea.util.CastUtils;
import com.google.jstestdriver.idea.util.JsPsiUtils;
import com.google.jstestdriver.idea.util.ObjectUtils;
import com.intellij.lang.javascript.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class JasmineFileStructureBuilder extends AbstractTestFileStructureBuilder {
private static JasmineFileStructureBuilder ourInstance = new JasmineFileStructureBuilder();
@NotNull
@Override
public JasmineFileStructure buildTestFileStructure(@NotNull JSFile jsFile) {
return new Builder(jsFile).build();
}
public static JasmineFileStructureBuilder getInstance() {
return ourInstance;
}
private static class Builder {
private final JasmineFileStructure myFileStructure;
public Builder(JSFile jsFile) {
myFileStructure = new JasmineFileStructure(jsFile);
}
public JasmineFileStructure build() {
List<JSElement> elements = JsPsiUtils.listJsElementsInExecutionOrder(myFileStructure.getJsFile());
for (JSElement element : elements) {
JSCallExpression jsCallExpression = JsPsiUtils.asCallExpressionStatement(element);
if (jsCallExpression != null) {
handleCallExpr(null, jsCallExpression);
}
}
return myFileStructure;
}
private void handleCallExpr(@Nullable JasmineSuiteStructure parentSuiteStructure, @NotNull JSCallExpression callExpression) {
JSReferenceExpression methodExpression = CastUtils.tryCast(callExpression.getMethodExpression(), JSReferenceExpression.class);
JSArgumentList argumentList = callExpression.getArgumentList();
if (methodExpression != null && argumentList != null) {
String methodName = methodExpression.getReferencedName();
JSExpression[] arguments = ObjectUtils.notNull(argumentList.getArguments(), JSExpression.EMPTY_ARRAY);
if ("describe".equals(methodName) && arguments.length == 2) {
String name = JsPsiUtils.extractStringValue(arguments[0]);
JSFunctionExpression specDefinitions = JsPsiUtils.extractFunctionExpression(arguments[1]);
if (name != null && specDefinitions != null) {
JasmineSuiteStructure suiteStructure = new JasmineSuiteStructure(name, callExpression, specDefinitions);
if (parentSuiteStructure != null) {
parentSuiteStructure.addChild(suiteStructure);
} else {
myFileStructure.addDescribeStructure(suiteStructure);
}
handleDescribeSpecDefinitions(suiteStructure, specDefinitions);
}
}
if ("it".equals(methodName) && arguments.length == 2) {
String name = JsPsiUtils.extractStringValue(arguments[0]);
JSFunctionExpression body = JsPsiUtils.extractFunctionExpression(arguments[1]);
if (name != null && body != null) {
JasmineSpecStructure specStructure = new JasmineSpecStructure(name, callExpression, body);
if (parentSuiteStructure != null) {
parentSuiteStructure.addChild(specStructure);
}
}
}
}
}
private void handleDescribeSpecDefinitions(@NotNull JasmineSuiteStructure suiteStructure,
@NotNull JSFunctionExpression specDefinitions) {
JSSourceElement[] sourceElements = ObjectUtils.notNull(specDefinitions.getBody(), JSSourceElement.EMPTY_ARRAY);
for (JSSourceElement sourceElement : sourceElements) {
JSBlockStatement jsBlockStatement = CastUtils.tryCast(sourceElement, JSBlockStatement.class);
if (jsBlockStatement != null) {
JSStatement[] statements = ObjectUtils.notNull(jsBlockStatement.getStatements(), JSStatement.EMPTY);
for (JSStatement statement : statements) {
JSCallExpression jsCallExpression = JsPsiUtils.asCallExpressionStatement(statement);
if (jsCallExpression != null) {
handleCallExpr(suiteStructure, jsCallExpression);
}
}
}
}
}
}
}