package com.google.jstestdriver.idea.assertFramework.qunit; import com.google.common.collect.Maps; import com.google.jstestdriver.idea.assertFramework.Annotation; import com.google.jstestdriver.idea.assertFramework.CompoundId; import com.intellij.lang.javascript.psi.JSFile; import com.intellij.openapi.util.TextRange; import java.util.Collection; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; class MarkedQUnitStructureBuilder { private static final Pattern MODULE_PATTERN = Pattern.compile("/\\*module (.+?)\\*/"); private static final Pattern MODULE_END_PATTERN = Pattern.compile("/\\*moduleEnd (.+?)\\*/"); private static final Pattern TEST_PATTERN = Pattern.compile("/\\*test (.+?)\\*/"); private static final Pattern TEST_END_PATTERN = Pattern.compile("/\\*testEnd (.+?)\\*/"); private MarkedQUnitStructureBuilder() { } public static MarkedQUnitFileStructure buildMarkedQUnitFileStructureByFileText(String fileText, JSFile jsFile) { MarkedQUnitFileStructure markedQUnitFileStructure = new MarkedQUnitFileStructure(); markedQUnitFileStructure.addMarkedModuleStructure(MarkedQUnitModuleStructure.newDefaultModule()); handleBeginOfMarkedModule(markedQUnitFileStructure, fileText); handleEndOfMarkedModule(markedQUnitFileStructure, fileText, jsFile); validateMarkedModules(markedQUnitFileStructure.getModules()); Collection<MarkedQUnitTestMethodStructure> markedQUnitTestStructures = buildMarkedQUnitTestStructures(fileText, jsFile); assignTestsToModules(markedQUnitFileStructure, markedQUnitTestStructures); return markedQUnitFileStructure; } private static void assignTestsToModules(MarkedQUnitFileStructure markedQUnitFileStructure, Collection<MarkedQUnitTestMethodStructure> markedQUnitTestStructures) { for (MarkedQUnitTestMethodStructure markedQUnitTestStructure : markedQUnitTestStructures) { MarkedQUnitModuleStructure markedQUnitModuleStructure = markedQUnitFileStructure.findById(markedQUnitTestStructure.getModuleId()); markedQUnitModuleStructure.addTestStructure(markedQUnitTestStructure); } } private static void handleBeginOfMarkedModule(MarkedQUnitFileStructure markedQUnitFileStructure, String fileText) { Matcher moduleMatcher = MODULE_PATTERN.matcher(fileText); while (moduleMatcher.find()) { Annotation annotation = Annotation.fromMatcher(moduleMatcher); int id = annotation.getPositiveIntId(); MarkedQUnitModuleStructure markedQUnitModuleStructure = markedQUnitFileStructure.findById(id); if (markedQUnitModuleStructure != null) { throw new RuntimeException("Duplicated module with id " + id + " found"); } markedQUnitModuleStructure = MarkedQUnitModuleStructure.newRegularModule(annotation); markedQUnitFileStructure.addMarkedModuleStructure(markedQUnitModuleStructure); } } private static void handleEndOfMarkedModule(MarkedQUnitFileStructure markedQUnitFileStructure, String fileText, JSFile jsFile) { Matcher moduleEndMatcher = MODULE_END_PATTERN.matcher(fileText); while (moduleEndMatcher.find()) { Annotation endAnnotation = Annotation.fromMatcher(moduleEndMatcher); int moduleId = endAnnotation.getPositiveIntId(); MarkedQUnitModuleStructure markedQUnitModuleStructure = markedQUnitFileStructure.findById(moduleId); if (markedQUnitModuleStructure == null) { throw new RuntimeException("'" + moduleEndMatcher.group() + "' references undefined module"); } markedQUnitModuleStructure.endAnnotationEncountered(TextRange.create(moduleEndMatcher.start(), moduleEndMatcher.end()), jsFile); } } private static void validateMarkedModules(Collection<MarkedQUnitModuleStructure> markedQUnitModuleStructures) { for (MarkedQUnitModuleStructure markedQUnitModuleStructure : markedQUnitModuleStructures) { markedQUnitModuleStructure.validate(); } } private static Collection<MarkedQUnitTestMethodStructure> buildMarkedQUnitTestStructures(String fileText, JSFile jsFile) { Map<CompoundId, MarkedQUnitTestMethodStructure> markedTestStructureMap = Maps.newHashMap(); handleBeginOfMarkedQUnitTest(markedTestStructureMap, fileText); handleEndOfMarkedQUnitTest(markedTestStructureMap, fileText, jsFile); Collection<MarkedQUnitTestMethodStructure> markedQUnitTestStructures = markedTestStructureMap.values(); for (MarkedQUnitTestMethodStructure markedQUnitTestStructure : markedQUnitTestStructures) { markedQUnitTestStructure.validateBuiltStructure(); } return markedQUnitTestStructures; } private static void handleBeginOfMarkedQUnitTest(Map<CompoundId, MarkedQUnitTestMethodStructure> markedQUniTestStructureMap, String fileText) { Matcher testMatcher = TEST_PATTERN.matcher(fileText); while (testMatcher.find()) { Annotation annotation = Annotation.fromMatcher(testMatcher); CompoundId testId = annotation.getCompoundId(); MarkedQUnitTestMethodStructure markedQUnitTestStructure = markedQUniTestStructureMap.get(testId); if (markedQUnitTestStructure != null) { throw new RuntimeException("Test with id " + testId + " is duplicated"); } markedQUnitTestStructure = new MarkedQUnitTestMethodStructure(annotation); markedQUniTestStructureMap.put(testId, markedQUnitTestStructure); } } private static void handleEndOfMarkedQUnitTest(Map<CompoundId, MarkedQUnitTestMethodStructure> markedQUnitTestStructureMap, String fileText, JSFile jsFile) { Matcher testEndMatcher = TEST_END_PATTERN.matcher(fileText); while (testEndMatcher.find()) { Annotation annotation = Annotation.fromMatcher(testEndMatcher); CompoundId testId = annotation.getCompoundId(); MarkedQUnitTestMethodStructure markedQUnitTestStructure = markedQUnitTestStructureMap.get(testId); if (markedQUnitTestStructure == null) { throw new RuntimeException("Test with id " + testId + " is not found"); } markedQUnitTestStructure.endEncountered(annotation.getTextRange(), jsFile); } } }