package com.google.jstestdriver.idea.assertFramework.library; import com.google.jstestdriver.idea.assertFramework.jstd.jsSrc.JstdDefaultAssertionFrameworkSrcMarker; import com.intellij.lang.javascript.library.JSLibraryManager; import com.intellij.lang.javascript.library.JSLibraryMappings; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.impl.libraries.LibraryEx; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.webcore.libraries.ScriptingLibraryModel; import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; /** * @author Sergey Simonchik */ public class JstdLibraryUtil { public static final String LIBRARY_NAME = "JsTestDriver Assertion Framework"; private static final AtomicBoolean INITIALIZED = new AtomicBoolean(false); private static volatile Boolean JSTD_LIBRARY_EXISTS; private static void init(@NotNull Project project) { if (INITIALIZED.compareAndSet(false, true)) { doInit(project); } } private static void doInit(@NotNull final Project project) { ApplicationManager.getApplication().runReadAction(() -> { JSLibraryManager libraryManager = JSLibraryManager.getInstance(project); LibraryTable libraryTable = libraryManager.getLibraryTable(ScriptingLibraryModel.LibraryLevel.GLOBAL); libraryTable.addListener(new MyLibraryChangeWatcher()); }); } private static void libraryChanged() { JSTD_LIBRARY_EXISTS = null; } public static boolean isFileInJstdLibScope(@NotNull Project project, @NotNull VirtualFile file) { init(project); boolean result = false; boolean libExists = doesCorrectJstdLibExist(project); if (libExists) { result = isCorrectMapping(project, file); } return result; } private static boolean doesCorrectJstdLibExist(@NotNull final Project project) { Boolean correctJstdLibExists = JSTD_LIBRARY_EXISTS; if (correctJstdLibExists == null) { correctJstdLibExists = ReadAction.compute(() -> { VirtualFile libVirtualFile = VfsUtil.findFileByURL( JstdDefaultAssertionFrameworkSrcMarker.class.getResource("TestCase.js") ); if (libVirtualFile == null) { return false; } JSLibraryManager libraryManager = JSLibraryManager.getInstance(project); for (ScriptingLibraryModel libraryModel : libraryManager.getAllLibraries()) { if (libraryModel == null) { continue; } String libraryName = libraryModel.getName(); if (libraryName != null && libraryName.startsWith(LIBRARY_NAME)) { Library library = libraryModel.getOriginalLibrary(); if (library instanceof LibraryEx) { LibraryEx libraryEx = (LibraryEx)library; if (libraryEx.isDisposed()) { continue; } } if (libraryModel.containsFile(libVirtualFile)) { return true; } } } return false; }); JSTD_LIBRARY_EXISTS = correctJstdLibExists; } return correctJstdLibExists; } private static boolean isCorrectMapping(@NotNull Project project, @NotNull VirtualFile file) { JSLibraryMappings jsLibraryMappings = JSLibraryMappings.getInstance(project); // TODO search for all JsTD libraries List<VirtualFile> usageScope = jsLibraryMappings.getMappingsByLibraryName(LIBRARY_NAME); String filePath = file.getPath(); for (VirtualFile root : usageScope) { if (root == null) { return true; } if (filePath.startsWith(root.getPath())) { return true; } } return false; } private static class MyLibraryChangeWatcher implements LibraryTable.Listener { @Override public void afterLibraryAdded(@NotNull Library newLibrary) { libraryChanged(); } @Override public void afterLibraryRenamed(@NotNull Library library) { libraryChanged(); } @Override public void afterLibraryRemoved(@NotNull Library library) { libraryChanged(); } } }