package com.google.jstestdriver.idea.assertFramework.jstd.codeInsight; import com.google.jstestdriver.idea.assertFramework.codeInsight.AbstractJsGenerateAction; import com.google.jstestdriver.idea.assertFramework.codeInsight.GenerateActionContext; import com.google.jstestdriver.idea.assertFramework.codeInsight.JsGeneratorUtils; import com.google.jstestdriver.idea.assertFramework.jstd.JstdTestCaseStructure; import com.google.jstestdriver.idea.assertFramework.jstd.JstdTestFileStructure; import com.google.jstestdriver.idea.assertFramework.jstd.JstdTestFileStructureBuilder; import com.google.jstestdriver.idea.util.JsPsiUtils; import com.intellij.lang.javascript.psi.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public abstract class AbstractJstdCreateStaticMethodAction extends AbstractJsGenerateAction { @NotNull @Override public abstract String getHumanReadableDescription(); @NotNull public abstract String getMethodName(); @Override public boolean isEnabled(@NotNull GenerateActionContext context) { JstdTestFileStructureBuilder builder = JstdTestFileStructureBuilder.getInstance(); JstdTestFileStructure fileStructure = builder.buildTestFileStructure(context.getJsFile()); Runnable generator = buildGenerator(context, fileStructure); return generator != null; } @Nullable private Runnable buildGenerator(GenerateActionContext context, @NotNull JstdTestFileStructure fileStructure) { if (fileStructure.getTestCaseCount() == 0) { return null; } int caretOffset = context.getDocumentCaretOffset(); JstdTestCaseStructure testCaseStructure = fileStructure.findEnclosingTestCaseByOffset(caretOffset); if (testCaseStructure != null) { JSObjectLiteralExpression testsObjectLiteral = testCaseStructure.getTestsObjectsLiteral(); if (testsObjectLiteral != null) { if (!findMethod(testsObjectLiteral)) { return new StaticMethodGenerator(testsObjectLiteral, context); } } else { JSCallExpression callExpression = testCaseStructure.getEnclosingCallExpression(); JSArgumentList argumentList = callExpression.getArgumentList(); JSExpression[] arguments = JsPsiUtils.getArguments(argumentList); if (arguments.length == 1 && arguments[0] != null) { return new StaticMethodGeneratorOnNewlyCreatedObjectLiteral(argumentList, context); } } } else { for (JstdTestCaseStructure testCase : fileStructure.getTestCaseStructures()) { JSObjectLiteralExpression testsObjectLiteral = testCase.getTestsObjectsLiteral(); if (testsObjectLiteral != null && JsPsiUtils.containsOffsetStrictly(testsObjectLiteral.getTextRange(), caretOffset)) { if (!findMethod(testsObjectLiteral)) { return new StaticMethodGenerator(testsObjectLiteral, context); } } } } return null; } private boolean findMethod(@NotNull JSObjectLiteralExpression objectLiteralExpression) { JSProperty[] properties = JsPsiUtils.getProperties(objectLiteralExpression); String methodName = getMethodName(); for (JSProperty property : properties) { String propertyName = JsPsiUtils.getPropertyName(property); if (methodName.equals(propertyName)) { return true; } } return false; } @Override public void actionPerformed(@NotNull GenerateActionContext context) { JstdTestFileStructureBuilder builder = JstdTestFileStructureBuilder.getInstance(); JstdTestFileStructure fileStructure = builder.buildTestFileStructure(context.getJsFile()); Runnable generator = buildGenerator(context, fileStructure); if (generator != null) { generator.run(); } } private class StaticMethodGenerator implements Runnable { private final JSObjectLiteralExpression myTestsObjectLiteral; private final GenerateActionContext myContext; public StaticMethodGenerator( @NotNull JSObjectLiteralExpression testsObjectLiteral, @NotNull GenerateActionContext context) { myTestsObjectLiteral = testsObjectLiteral; myContext = context; } @Override public void run() { JsGeneratorUtils.generateProperty(myTestsObjectLiteral, myContext, getMethodName() + ": function() {|}"); } } private class StaticMethodGeneratorOnNewlyCreatedObjectLiteral implements Runnable { private final JSArgumentList myArgumentList; private final GenerateActionContext myContext; public StaticMethodGeneratorOnNewlyCreatedObjectLiteral(JSArgumentList argumentList, GenerateActionContext context) { myArgumentList = argumentList; myContext = context; } @Override public void run() { JsGeneratorUtils .generateObjectLiteralWithPropertyAsArgument(myContext, "{\n" + getMethodName() + ": function() {|}\n}", myArgumentList, 1); } } }