package com.google.jstestdriver.idea.assertFramework.jasmine; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.jstestdriver.idea.assertFramework.JstdRunElement; import com.google.jstestdriver.idea.util.JsPsiUtils; import com.intellij.lang.javascript.psi.JSCallExpression; import com.intellij.lang.javascript.psi.JSFunctionExpression; import com.intellij.openapi.util.TextRange; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Map; public class JasmineSuiteStructure implements JasmineSuiteChild { private final String myName; private final JSCallExpression myEnclosingCallExpression; private final JSFunctionExpression mySpecDefinitions; private final List<JasmineSuiteStructure> mySuiteChildren = Lists.newArrayList(); private final List<JasmineSpecStructure> mySpecChildren = Lists.newArrayList(); private final Map<String, JasmineSuiteChild> myChildByNameMap = Maps.newLinkedHashMap(); public JasmineSuiteStructure(@NotNull String name, @NotNull JSCallExpression enclosingCallExpression, @NotNull JSFunctionExpression specDefinitions) { myName = name; myEnclosingCallExpression = enclosingCallExpression; mySpecDefinitions = specDefinitions; } @NotNull public String getName() { return myName; } @NotNull public JSCallExpression getEnclosingCallExpression() { return myEnclosingCallExpression; } @NotNull public JSFunctionExpression getSpecDefinitions() { return mySpecDefinitions; } public void addChild(@NotNull JasmineSuiteChild child) { if (child instanceof JasmineSuiteStructure) { JasmineSuiteStructure suiteStructure = (JasmineSuiteStructure) child; myChildByNameMap.put(suiteStructure.getName(), suiteStructure); mySuiteChildren.add(suiteStructure); } else if (child instanceof JasmineSpecStructure) { JasmineSpecStructure specStructure = (JasmineSpecStructure) child; myChildByNameMap.put(specStructure.getName(), specStructure); mySpecChildren.add(specStructure); } } @Nullable public JasmineSuiteStructure getInnerSuiteByName(String suiteName) { JasmineSuiteChild child = myChildByNameMap.get(suiteName); if (child instanceof JasmineSuiteStructure) { return (JasmineSuiteStructure) child; } return null; } @Nullable public JasmineSpecStructure getInnerSpecByName(String specName) { JasmineSuiteChild child = myChildByNameMap.get(specName); if (child instanceof JasmineSpecStructure) { return (JasmineSpecStructure) child; } return null; } public int getSuiteChildrenCount() { return mySuiteChildren.size(); } public int getSpecChildrenCount() { return mySpecChildren.size(); } @Nullable public JasmineSpecStructure findSpecContainingOffset(int offset) { for (JasmineSpecStructure specChild : mySpecChildren) { TextRange specTextRange = specChild.getEnclosingCallExpression().getTextRange(); if (JsPsiUtils.containsOffsetStrictly(specTextRange, offset)) { return specChild; } } for (JasmineSuiteStructure suiteChild : mySuiteChildren) { JasmineSpecStructure specStructure = suiteChild.findSpecContainingOffset(offset); if (specStructure != null) { return specStructure; } } return null; } @Nullable public JasmineSuiteStructure findLowestSuiteStructureContainingOffset(int offset) { for (JasmineSuiteStructure suiteStructure : mySuiteChildren) { JasmineSuiteStructure inner = suiteStructure.findLowestSuiteStructureContainingOffset(offset); if (inner != null) { return null; } } TextRange suiteTextRange = myEnclosingCallExpression.getTextRange(); if (JsPsiUtils.containsOffsetStrictly(suiteTextRange, offset)) { return this; } return null; } @Nullable JstdRunElement findJstdRunElement(@NotNull TextRange textRange) { for (JasmineSpecStructure specChild : mySpecChildren) { TextRange callTextRange = specChild.getEnclosingCallExpression().getTextRange(); if (callTextRange.contains(textRange)) { return JstdRunElement.newTestMethodRunElement(myName, specChild.getName()); } } for (JasmineSuiteStructure suiteChild : mySuiteChildren) { JstdRunElement jstdRunElement = suiteChild.findJstdRunElement(textRange); if (jstdRunElement != null) { return jstdRunElement; } } if (myEnclosingCallExpression.getTextRange().contains(textRange)) { return JstdRunElement.newTestCaseRunElement(myName); } return null; } }