@Override
 public boolean isEmpty() {
   for (JstdTestCaseStructure testCaseStructure : myTestCaseStructures) {
     if (testCaseStructure.getTestCount() > 0) {
       return false;
     }
   }
   return true;
 }
 @Nullable
 public JstdTestCaseStructure findEnclosingTestCaseByOffset(int documentOffset) {
   for (JstdTestCaseStructure testCaseStructure : myTestCaseStructures) {
     TextRange testCaseCallExpressionTextRange =
         testCaseStructure.getEnclosingCallExpression().getTextRange();
     if (JsPsiUtils.containsOffsetStrictly(testCaseCallExpressionTextRange, documentOffset)) {
       return testCaseStructure;
     }
   }
   return null;
 }
 @Override
 @Nullable
 public JstdRunElement findJstdRunElement(@NotNull TextRange textRange) {
   for (JstdTestCaseStructure testCaseStructure : myTestCaseStructures) {
     JstdRunElement jstdRunElement = testCaseStructure.findJstdRunElement(textRange);
     if (jstdRunElement != null) {
       return jstdRunElement;
     }
   }
   return null;
 }
 @NotNull
 @Override
 public List<String> getTopLevelElements() {
   if (myTestCaseStructures.isEmpty()) {
     return Collections.emptyList();
   }
   List<String> out = new ArrayList<String>(myTestCaseStructures.size());
   for (JstdTestCaseStructure structure : myTestCaseStructures) {
     out.add(structure.getName());
   }
   return out;
 }
 @NotNull
 @Override
 public List<String> getChildrenOf(@NotNull String topLevelElementName) {
   JstdTestCaseStructure testCaseStructure = myTestCaseStructureByNameMap.get(topLevelElementName);
   if (testCaseStructure == null) {
     return Collections.emptyList();
   }
   List<String> out = new ArrayList<String>(testCaseStructure.getTestCount());
   for (JstdTestStructure testStructure : testCaseStructure.getTestStructures()) {
     out.add(testStructure.getName());
   }
   return out;
 }
 @Override
 public PsiElement findPsiElement(@NotNull String testCaseName, @Nullable String testMethodName) {
   JstdTestCaseStructure testCaseStructure = myTestCaseStructureByNameMap.get(testCaseName);
   if (testCaseStructure == null) {
     return null;
   }
   if (testMethodName == null) {
     return testCaseStructure.getEnclosingCallExpression();
   }
   JstdTestStructure testStructure = testCaseStructure.getTestStructureByName(testMethodName);
   if (testStructure != null) {
     return testStructure.getTestMethodNameDeclaration();
   }
   return null;
 }
 private static void fillTestCaseStructureByObjectLiteral(
     @NotNull JstdTestCaseStructure testCaseStructure,
     @NotNull JSObjectLiteralExpression testsObjectLiteral) {
   JSProperty[] properties = JsPsiUtils.getProperties(testsObjectLiteral);
   for (JSProperty property : properties) {
     JstdTestStructure testStructure = JstdTestStructure.newPropertyBasedTestStructure(property);
     if (testStructure != null) {
       testCaseStructure.addTestStructure(testStructure);
     }
   }
 }
 private static void addPrototypeTest(
     @NotNull JstdTestCaseStructure testCaseStructure,
     @Nullable JSExpression rightAssignmentOperand,
     @NotNull JSDefinitionExpression wholeLeftDefExpr) {
   JSReferenceExpression wholeLeftRefExpr =
       ObjectUtils.tryCast(wholeLeftDefExpr.getExpression(), JSReferenceExpression.class);
   LeafPsiElement testMethodLeafPsiElement = null;
   if (wholeLeftRefExpr != null) {
     testMethodLeafPsiElement =
         ObjectUtils.tryCast(wholeLeftRefExpr.getReferenceNameElement(), LeafPsiElement.class);
   }
   if (testMethodLeafPsiElement != null
       && testMethodLeafPsiElement.getElementType() == JSTokenTypes.IDENTIFIER) {
     JSFunctionExpression jsFunctionExpression =
         JsPsiUtils.extractFunctionExpression(rightAssignmentOperand);
     JstdTestStructure jstdTestStructure =
         JstdTestStructure.newPrototypeBasedTestStructure(
             wholeLeftDefExpr, testMethodLeafPsiElement, jsFunctionExpression);
     if (jstdTestStructure != null) {
       testCaseStructure.addTestStructure(jstdTestStructure);
     }
   }
 }
 void postProcess() {
   myNameByPsiElementMap = Collections.emptyMap();
   myPrototypeBasedTestElements = Collections.emptyMap();
   if (myTestCaseStructures.isEmpty()) {
     return;
   }
   int totalCount = 0;
   int prototypeBasedTestCount = 0;
   for (JstdTestCaseStructure testCaseStructure : myTestCaseStructures) {
     totalCount += testCaseStructure.getTestCount() + 1;
     for (JstdTestStructure testStructure : testCaseStructure.getTestStructures()) {
       if (testStructure.getWholeLeftDefExpr() != null) {
         prototypeBasedTestCount++;
       }
     }
   }
   myNameByPsiElementMap = new IdentityHashMap<PsiElement, String>(totalCount);
   if (prototypeBasedTestCount > 0) {
     myPrototypeBasedTestElements = new IdentityHashMap<PsiElement, Void>(prototypeBasedTestCount);
   }
   for (JstdTestCaseStructure testCaseStructure : myTestCaseStructures) {
     JSExpression testCaseMethodExpr =
         testCaseStructure.getEnclosingCallExpression().getMethodExpression();
     if (testCaseMethodExpr != null) {
       myNameByPsiElementMap.put(testCaseMethodExpr, testCaseStructure.getName());
     }
     for (JstdTestStructure testStructure : testCaseStructure.getTestStructures()) {
       PsiElement anchor = testStructure.getTestMethodNameDeclaration();
       myNameByPsiElementMap.put(anchor, testStructure.getName());
       JSDefinitionExpression wholeLeftDefExpr = testStructure.getWholeLeftDefExpr();
       if (wholeLeftDefExpr != null) {
         myPrototypeBasedTestElements.put(wholeLeftDefExpr, null);
       }
     }
   }
 }
 public void addTestCaseStructure(JstdTestCaseStructure testCaseStructure) {
   myTestCaseStructures.add(testCaseStructure);
   myTestCaseStructureByNameMap.put(testCaseStructure.getName(), testCaseStructure);
 }