@NotNull @Override public Runnable processFile(@NotNull PsiFile file) { if (!(file instanceof GoFile)) { return EmptyRunnable.getInstance(); } MultiMap<String, GoImportSpec> importMap = ((GoFile) file).getImportMap(); Set<PsiElement> importEntriesToDelete = ContainerUtil.newLinkedHashSet(); Set<PsiElement> importIdentifiersToDelete = findRedundantImportIdentifiers(importMap); importEntriesToDelete.addAll(findDuplicatedEntries(importMap)); importEntriesToDelete.addAll(filterUnusedImports(file, importMap).values()); if (importEntriesToDelete.isEmpty() && importIdentifiersToDelete.isEmpty()) { return EmptyRunnable.getInstance(); } return new CollectingInfoRunnable() { @Nullable @Override public String getUserNotificationInfo() { int entriesToDelete = importEntriesToDelete.size(); int identifiersToDelete = importIdentifiersToDelete.size(); String result = ""; if (entriesToDelete > 0) { result = "Removed " + entriesToDelete + " import" + (entriesToDelete > 1 ? "s" : ""); } if (identifiersToDelete > 0) { result += result.isEmpty() ? "Removed " : " and "; result += identifiersToDelete + " alias" + (identifiersToDelete > 1 ? "es" : ""); } return StringUtil.nullize(result); } @Override public void run() { if (!importEntriesToDelete.isEmpty() || !importIdentifiersToDelete.isEmpty()) { PsiDocumentManager manager = PsiDocumentManager.getInstance(file.getProject()); Document document = manager.getDocument(file); if (document != null) { manager.commitDocument(document); } } for (PsiElement importEntry : importEntriesToDelete) { if (importEntry != null && importEntry.isValid()) { deleteImportSpec(getImportSpec(importEntry)); } } for (PsiElement identifier : importIdentifiersToDelete) { if (identifier != null && identifier.isValid()) { identifier.delete(); } } } }; }
public final void runBare() throws Throwable { final Throwable[] throwables = new Throwable[1]; SwingUtilities.invokeAndWait( new Runnable() { public void run() { try { ourTestThread = Thread.currentThread(); startRunAndTear(); } catch (Throwable throwable) { throwables[0] = throwable; } finally { ourTestThread = null; try { cleanupApplicationCaches(); } catch (Throwable e) { e.printStackTrace(); } } } }); if (throwables[0] != null) { throw throwables[0]; } // just to make sure all deffered Runnable's to finish SwingUtilities.invokeAndWait(EmptyRunnable.getInstance()); if (IdeaLogger.ourErrorsOccurred != null) { throw IdeaLogger.ourErrorsOccurred; } }
@NotNull @Override public ListPopup createConfirmation( String title, final String yesText, String noText, final Runnable onYes, int defaultOptionIndex) { return createConfirmation( title, yesText, noText, onYes, EmptyRunnable.getInstance(), defaultOptionIndex); }
public void testDelayedTasksReusePooledThreadIfExecuteAtDifferentTimes() throws InterruptedException, ExecutionException { final AppScheduledExecutorService service = new AppScheduledExecutorService(getName()); final List<LogInfo> log = Collections.synchronizedList(new ArrayList<>()); // pre-start one thread Future<?> future = service.submit(EmptyRunnable.getInstance()); future.get(); service.setBackendPoolCorePoolSize(1); assertEquals(1, service.getBackendPoolExecutorSize()); int delay = 500; ScheduledFuture<?> f1 = service.schedule((Runnable) () -> log.add(new LogInfo(1)), delay, TimeUnit.MILLISECONDS); ScheduledFuture<?> f2 = service.schedule( (Runnable) () -> log.add(new LogInfo(2)), delay + 100, TimeUnit.MILLISECONDS); ScheduledFuture<?> f3 = service.schedule( (Runnable) () -> log.add(new LogInfo(3)), delay + 200, TimeUnit.MILLISECONDS); assertEquals(1, service.getBackendPoolExecutorSize()); assertFalse(f1.isDone()); assertFalse(f2.isDone()); assertFalse(f3.isDone()); TimeoutUtil.sleep(delay + 200 + 300); assertTrue(f1.isDone()); assertTrue(f2.isDone()); assertTrue(f3.isDone()); assertEquals(1, service.getBackendPoolExecutorSize()); assertEquals(3, log.size()); Set<Thread> usedThreads = new HashSet<>( Arrays.asList( log.get(0).currentThread, log.get(1).currentThread, log.get(2).currentThread)); if (usedThreads.size() != 1) { System.err.println(ThreadDumper.dumpThreadsToString()); } assertEquals(usedThreads.toString(), 1, usedThreads.size()); // must be executed in same thread service.shutdownAppScheduledExecutorService(); assertTrue(service.awaitTermination(10, TimeUnit.SECONDS)); }
private static void waitForAllLaters() throws InterruptedException, InvocationTargetException { for (int i = 0; i < 3; i++) { SwingUtilities.invokeAndWait(EmptyRunnable.getInstance()); } }
public final void updateUI() { updateUI(EmptyRunnable.getInstance()); }
public class RefResolveServiceImpl extends RefResolveService implements Runnable, Disposable { private static final Logger LOG = Logger.getInstance(RefResolveServiceImpl.class); private final AtomicInteger fileCount = new AtomicInteger(); private final AtomicLong bytesSize = new AtomicLong(); private final AtomicLong refCount = new AtomicLong(); private final PersistentIntList storage; private final Deque<VirtualFile> filesToResolve = new ArrayDeque<VirtualFile>(); // guarded by filesToResolve private final ConcurrentBitSet fileIsInQueue = new ConcurrentBitSet(); private final ConcurrentBitSet fileIsResolved; private final ApplicationEx myApplication; private volatile boolean myDisposed; private volatile boolean upToDate; private final AtomicInteger enableVetoes = new AtomicInteger(); // number of disable() calls. To enable the service, there should be at // least corresponding number of enable() calls. private final FileWriter log; private final ProjectFileIndex myProjectFileIndex; public RefResolveServiceImpl( final Project project, final MessageBus messageBus, final PsiManager psiManager, StartupManager startupManager, ApplicationEx application, ProjectFileIndex projectFileIndex) throws IOException { super(project); ((FutureTask) resolveProcess).run(); myApplication = application; myProjectFileIndex = projectFileIndex; if (ENABLED) { log = new FileWriter(new File(getStorageDirectory(), "log.txt")); File dataFile = new File(getStorageDirectory(), "data"); fileIsResolved = ConcurrentBitSet.readFrom(new File(getStorageDirectory(), "bitSet")); log("Read resolved file bitset: " + fileIsResolved); int maxId = FSRecords.getMaxId(); PersistentIntList list = new PersistentIntList(dataFile, dataFile.exists() ? 0 : maxId); if (list.getSize() == maxId) { storage = list; } else { // just to be safe, re-resolve all if VFS files count changes since last restart list.dispose(); storage = new PersistentIntList(dataFile, maxId); log( "VFS maxId changed: was " + list.getSize() + "; now: " + maxId + "; re-resolving everything"); fileIsResolved.clear(); } Disposer.register(this, storage); if (!application.isUnitTestMode()) { startupManager.runWhenProjectIsInitialized( () -> { initListeners(messageBus, psiManager); startThread(); }); } Disposer.register( this, new Disposable() { @Override public void dispose() { try { save(); log.close(); } catch (IOException e) { LOG.error(e); } } }); } else { log = null; fileIsResolved = null; storage = null; } } @NotNull private static List<VirtualFile> toVf(@NotNull int[] ids) { List<VirtualFile> res = new ArrayList<VirtualFile>(); for (int id : ids) { VirtualFile file = PersistentFS.getInstance().findFileById(id); if (file != null) { res.add(file); } } return res; } @NotNull private static String toVfString(@NotNull int[] backIds) { List<VirtualFile> list = toVf(backIds); return toVfString(list); } @NotNull private static String toVfString(@NotNull Collection<VirtualFile> list) { List<VirtualFile> sub = new ArrayList<VirtualFile>(list).subList(0, Math.min(list.size(), 100)); return list.size() + " files: " + StringUtil.join(sub, file -> file.getName(), ", ") + (list.size() == sub.size() ? "" : "..."); } private void initListeners(@NotNull MessageBus messageBus, @NotNull PsiManager psiManager) { messageBus .connect() .subscribe( VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() { @Override public void after(@NotNull List<? extends VFileEvent> events) { fileCount.set(0); List<VirtualFile> files = ContainerUtil.mapNotNull( events, new Function<VFileEvent, VirtualFile>() { @Override public VirtualFile fun(VFileEvent event) { return event.getFile(); } }); queue(files, "VFS events " + events.size()); } }); psiManager.addPsiTreeChangeListener( new PsiTreeChangeAdapter() { @Override public void childrenChanged(@NotNull PsiTreeChangeEvent event) { PsiFile file = event.getFile(); VirtualFile virtualFile = PsiUtilCore.getVirtualFile(file); if (virtualFile != null) { queue(Collections.singletonList(virtualFile), event); } } @Override public void propertyChanged(@NotNull PsiTreeChangeEvent event) { childrenChanged(event); } }); messageBus .connect() .subscribe( DumbService.DUMB_MODE, new DumbService.DumbModeListener() { @Override public void enteredDumbMode() { disable(); } @Override public void exitDumbMode() { enable(); } }); messageBus .connect() .subscribe( PowerSaveMode.TOPIC, new PowerSaveMode.Listener() { @Override public void powerSaveStateChanged() { if (PowerSaveMode.isEnabled()) { enable(); } else { disable(); } } }); myApplication.addApplicationListener( new ApplicationAdapter() { @Override public void beforeWriteActionStart(@NotNull Object action) { disable(); } @Override public void writeActionFinished(@NotNull Object action) { enable(); } @Override public void applicationExiting() { disable(); } }, this); VirtualFileManager.getInstance() .addVirtualFileManagerListener( new VirtualFileManagerListener() { @Override public void beforeRefreshStart(boolean asynchronous) { disable(); } @Override public void afterRefreshFinish(boolean asynchronous) { enable(); } }, this); HeavyProcessLatch.INSTANCE.addListener( new HeavyProcessLatch.HeavyProcessListener() { @Override public void processStarted() {} @Override public void processFinished() { wakeUp(); } }, this); } // return true if file was added to queue private boolean queueIfNeeded(VirtualFile virtualFile, @NotNull Project project) { return toResolve(virtualFile, project) && queueUpdate(virtualFile); } private boolean toResolve(VirtualFile virtualFile, @NotNull Project project) { if (virtualFile != null && virtualFile.isValid() && project.isInitialized() && myProjectFileIndex.isInSourceContent(virtualFile) && isSupportedFileType(virtualFile)) { return true; } // else mark it as resolved so we will not have to check it again if (virtualFile instanceof VirtualFileWithId) { int id = getAbsId(virtualFile); fileIsResolved.set(id); } return false; } public static boolean isSupportedFileType(@NotNull VirtualFile virtualFile) { if (virtualFile.isDirectory()) return true; if (virtualFile.getFileType() == StdFileTypes.JAVA) return true; if (virtualFile.getFileType() == StdFileTypes.XML && !ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile)) return true; if ("groovy".equals(virtualFile.getExtension())) return true; return false; } @NotNull private File getStorageDirectory() { String dirName = myProject.getName() + "." + Integer.toHexString(myProject.getPresentableUrl().hashCode()); File dir = new File(PathManager.getSystemPath(), "refs/" + dirName); FileUtil.createDirectory(dir); return dir; } private void log(String m) { // System.out.println(m); logf(m); } private void logf(String m) { if (LOG.isDebugEnabled()) { try { log.write( DateFormat.getDateTimeInstance().format(new Date()) + " " + m + /*" ; gap="+storage.gap+*/ "\n"); } catch (IOException e) { LOG.error(e); } } } private void flushLog() { try { log.flush(); } catch (IOException e) { LOG.error(e); } } // return true if file was added to queue private boolean queueUpdate(@NotNull VirtualFile file) { synchronized (filesToResolve) { if (!(file instanceof VirtualFileWithId)) return false; int fileId = getAbsId(file); countAndMarkUnresolved(file, new LinkedHashSet<VirtualFile>(), true); boolean alreadyAdded = fileIsInQueue.set(fileId); if (!alreadyAdded) { filesToResolve.add(file); } upToDate = false; wakeUpUnderLock(); return !alreadyAdded; } } private void wakeUp() { synchronized (filesToResolve) { wakeUpUnderLock(); } } private void wakeUpUnderLock() { filesToResolve.notifyAll(); } private void waitForQueue() throws InterruptedException { synchronized (filesToResolve) { filesToResolve.wait(1000); } } private void startThread() { new Thread(this, "Ref resolve service").start(); upToDate = true; queueUnresolvedFilesSinceLastRestart(); } private void queueUnresolvedFilesSinceLastRestart() { PersistentFS fs = PersistentFS.getInstance(); int maxId = FSRecords.getMaxId(); TIntArrayList list = new TIntArrayList(); for (int id = fileIsResolved.nextClearBit(1); id >= 0 && id < maxId; id = fileIsResolved.nextClearBit(id + 1)) { int nextSetBit = fileIsResolved.nextSetBit(id); int endOfRun = Math.min(maxId, nextSetBit == -1 ? maxId : nextSetBit); do { VirtualFile virtualFile = fs.findFileById(id); if (queueIfNeeded(virtualFile, myProject)) { list.add(id); } else { fileIsResolved.set(id); } } while (++id < endOfRun); } log("Initially added to resolve " + toVfString(list.toNativeArray())); } @Override public void dispose() { myDisposed = true; } private void save() throws IOException { log("Saving resolved file bitset: " + fileIsResolved); fileIsResolved.writeTo(new File(getStorageDirectory(), "bitSet")); log("list.size = " + storage.getSize()); } private volatile Future<?> resolveProcess = new FutureTask<Object>(EmptyRunnable.getInstance(), null); // write from EDT only @Override public void run() { while (!myDisposed) { boolean isEmpty; synchronized (filesToResolve) { isEmpty = filesToResolve.isEmpty(); } if (enableVetoes.get() > 0 || isEmpty || !resolveProcess.isDone() || HeavyProcessLatch.INSTANCE.isRunning() || PsiDocumentManager.getInstance(myProject).hasUncommitedDocuments()) { try { waitForQueue(); } catch (InterruptedException e) { break; } continue; } final Set<VirtualFile> files = pollFilesToResolve(); if (files.isEmpty()) continue; upToDate = false; myApplication.invokeLater( () -> { if (!resolveProcess.isDone()) return; log("Started to resolve " + files.size() + " files"); Task.Backgroundable backgroundable = new Task.Backgroundable(myProject, "Resolving files...", false) { @Override public void run(@NotNull final ProgressIndicator indicator) { if (!myApplication.isDisposed()) { processBatch(indicator, files); } } }; ProgressIndicator indicator; if (files.size() > 1) { // show progress indicator = new BackgroundableProcessIndicator(backgroundable); } else { indicator = new MyProgress(); } resolveProcess = ((ProgressManagerImpl) ProgressManager.getInstance()) .runProcessWithProgressAsynchronously(backgroundable, indicator, null); }, myProject.getDisposed()); flushLog(); } } private volatile int resolvedInPreviousBatch; private void processBatch( @NotNull final ProgressIndicator indicator, @NotNull Set<VirtualFile> files) { assert !myApplication.isDispatchThread(); final int resolvedInPreviousBatch = this.resolvedInPreviousBatch; final int totalSize = files.size() + resolvedInPreviousBatch; final ConcurrentIntObjectMap<int[]> fileToForwardIds = ContainerUtil.createConcurrentIntObjectMap(); final Set<VirtualFile> toProcess = Collections.synchronizedSet(files); indicator.setIndeterminate(false); ProgressIndicatorUtils.forceWriteActionPriority(indicator, (Disposable) indicator); long start = System.currentTimeMillis(); Processor<VirtualFile> processor = file -> { double fraction = 1 - toProcess.size() * 1.0 / totalSize; indicator.setFraction(fraction); try { if (!file.isDirectory() && toResolve(file, myProject)) { int fileId = getAbsId(file); int i = totalSize - toProcess.size(); indicator.setText(i + "/" + totalSize + ": Resolving " + file.getPresentableUrl()); int[] forwardIds = processFile(file, fileId, indicator); if (forwardIds == null) { // queueUpdate(file); return false; } fileToForwardIds.put(fileId, forwardIds); } toProcess.remove(file); return true; } catch (RuntimeException e) { indicator.checkCanceled(); } return true; }; boolean success = true; try { success = processFilesConcurrently(files, indicator, processor); } finally { this.resolvedInPreviousBatch = toProcess.isEmpty() ? 0 : totalSize - toProcess.size(); queue(toProcess, "re-added after fail. success=" + success); storeIds(fileToForwardIds); long end = System.currentTimeMillis(); log( "Resolved batch of " + (totalSize - toProcess.size()) + " from " + totalSize + " files in " + ((end - start) / 1000) + "sec. (Gap: " + storage.gap + ")"); synchronized (filesToResolve) { upToDate = filesToResolve.isEmpty(); log("upToDate = " + upToDate); if (upToDate) { for (Listener listener : myListeners) { listener.allFilesResolved(); } } } } } private boolean processFilesConcurrently( @NotNull Set<VirtualFile> files, @NotNull final ProgressIndicator indicator, @NotNull final Processor<VirtualFile> processor) { final List<VirtualFile> fileList = new ArrayList<VirtualFile>(files); // fine but grabs all CPUs // return JobLauncher.getInstance().invokeConcurrentlyUnderProgress(fileList, indicator, false, // false, processor); int parallelism = CacheUpdateRunner.indexingThreadCount(); final Callable<Boolean> processFileFromSet = () -> { final boolean[] result = {true}; ProgressManager.getInstance() .executeProcessUnderProgress( () -> { while (true) { ProgressManager.checkCanceled(); VirtualFile file; synchronized (fileList) { file = fileList.isEmpty() ? null : fileList.remove(fileList.size() - 1); } if (file == null) { break; } if (!processor.process(file)) { result[0] = false; break; } } }, indicator); return result[0]; }; List<Future<Boolean>> futures = ContainerUtil.map( Collections.nCopies(parallelism, ""), s -> myApplication.executeOnPooledThread(processFileFromSet)); List<Boolean> results = ContainerUtil.map( futures, future -> { try { return future.get(); } catch (Exception e) { LOG.error(e); } return false; }); return !ContainerUtil.exists( results, result -> { return result != null && !result; // null means PCE }); } @NotNull private Set<VirtualFile> pollFilesToResolve() { Set<VirtualFile> set; synchronized (filesToResolve) { int queuedSize = filesToResolve.size(); set = new LinkedHashSet<VirtualFile>(queuedSize); // someone might have cleared this bit to mark file as processed for (VirtualFile file : filesToResolve) { if (fileIsInQueue.clear(getAbsId(file))) { set.add(file); } } filesToResolve.clear(); } return countAndMarkUnresolved(set, false); } private static int getAbsId(@NotNull VirtualFile file) { return Math.abs(((VirtualFileWithId) file).getId()); } @NotNull private Set<VirtualFile> countAndMarkUnresolved( @NotNull Collection<VirtualFile> files, boolean inDbOnly) { Set<VirtualFile> result = new LinkedHashSet<VirtualFile>(); for (VirtualFile file : files) { countAndMarkUnresolved(file, result, inDbOnly); } return result; } private void countAndMarkUnresolved( @NotNull VirtualFile file, @NotNull final Set<VirtualFile> result, final boolean inDbOnly) { if (file.isDirectory()) { VfsUtilCore.visitChildrenRecursively( file, new VirtualFileVisitor() { @Override public boolean visitFile(@NotNull VirtualFile file) { return doCountAndMarkUnresolved(file, result); } @Nullable @Override public Iterable<VirtualFile> getChildrenIterable(@NotNull VirtualFile file) { return inDbOnly ? ((NewVirtualFile) file).iterInDbChildren() : null; } }); } else { doCountAndMarkUnresolved(file, result); } } // return true if continue to process sub-directories of the {@code file}, false if the file is // already processed private boolean doCountAndMarkUnresolved( @NotNull VirtualFile file, @NotNull Set<VirtualFile> result) { if (file.isDirectory()) { fileIsResolved.set(getAbsId(file)); return result.add(file); } if (toResolve(file, myProject)) { result.add(file); fileIsResolved.clear(getAbsId(file)); } return true; } private void enable() { // decrement but only if it's positive int vetoes; do { vetoes = enableVetoes.get(); if (vetoes == 0) break; } while (!enableVetoes.compareAndSet(vetoes, vetoes - 1)); wakeUp(); } private void disable() { enableVetoes.incrementAndGet(); wakeUp(); } // returns list of resolved files if updated successfully, or null if write action or dumb mode // started private int[] processFile( @NotNull final VirtualFile file, int fileId, @NotNull final ProgressIndicator indicator) { final TIntHashSet forward; try { forward = calcForwardRefs(file, indicator); } catch (IndexNotReadyException e) { return null; } catch (ApplicationUtil.CannotRunReadActionException e) { return null; } catch (ProcessCanceledException e) { throw e; } catch (Exception e) { log(ExceptionUtil.getThrowableText(e)); flushLog(); return null; } int[] forwardIds = forward.toArray(); fileIsResolved.set(fileId); logf( " ---- " + file.getPresentableUrl() + " processed. forwardIds: " + toVfString(forwardIds)); for (Listener listener : myListeners) { listener.fileResolved(file); } return forwardIds; } private void storeIds(@NotNull ConcurrentIntObjectMap<int[]> fileToForwardIds) { int forwardSize = 0; int backwardSize = 0; final TIntObjectHashMap<TIntArrayList> fileToBackwardIds = new TIntObjectHashMap<TIntArrayList>(fileToForwardIds.size()); for (ConcurrentIntObjectMap.IntEntry<int[]> entry : fileToForwardIds.entries()) { int fileId = entry.getKey(); int[] forwardIds = entry.getValue(); forwardSize += forwardIds.length; for (int forwardId : forwardIds) { TIntArrayList backIds = fileToBackwardIds.get(forwardId); if (backIds == null) { backIds = new TIntArrayList(); fileToBackwardIds.put(forwardId, backIds); } backIds.add(fileId); backwardSize++; } } log("backwardSize = " + backwardSize); log("forwardSize = " + forwardSize); log("fileToForwardIds.size() = " + fileToForwardIds.size()); log("fileToBackwardIds.size() = " + fileToBackwardIds.size()); assert forwardSize == backwardSize; // wrap in read action so that sudden quit (in write action) would not interrupt us myApplication.runReadAction( () -> { if (!myApplication.isDisposed()) { fileToBackwardIds.forEachEntry( new TIntObjectProcedure<TIntArrayList>() { @Override public boolean execute(int fileId, TIntArrayList backIds) { storage.addAll(fileId, backIds.toNativeArray()); return true; } }); } }); } @NotNull private TIntHashSet calcForwardRefs( @NotNull final VirtualFile virtualFile, @NotNull final ProgressIndicator indicator) throws IndexNotReadyException, ApplicationUtil.CannotRunReadActionException { final TIntHashSet forward = new TIntHashSet(); final PsiFile psiFile = ApplicationUtil.tryRunReadAction( () -> { if (myProject.isDisposed()) throw new ProcessCanceledException(); if (fileCount.incrementAndGet() % 100 == 0) { PsiManager.getInstance(myProject).dropResolveCaches(); try { storage.flush(); log.flush(); } catch (IOException e) { LOG.error(e); } } return PsiManager.getInstance(myProject).findFile(virtualFile); }); final int fileId = getAbsId(virtualFile); if (psiFile != null) { bytesSize.addAndGet(virtualFile.getLength()); final Set<PsiElement> resolved = new THashSet<PsiElement>(); ApplicationUtil.tryRunReadAction( new Runnable() { @Override public void run() { indicator.checkCanceled(); if (psiFile instanceof PsiJavaFile) { psiFile.accept( new JavaRecursiveElementWalkingVisitor() { @Override public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { indicator.checkCanceled(); resolveReference(reference, resolved); super.visitReferenceElement(reference); } }); } else { psiFile.accept( new PsiRecursiveElementWalkingVisitor() { @Override public void visitElement(PsiElement element) { for (PsiReference reference : element.getReferences()) { indicator.checkCanceled(); resolveReference(reference, resolved); } super.visitElement(element); } }); } indicator.checkCanceled(); for (PsiElement element : resolved) { PsiFile file = element.getContainingFile(); addIdAndSuperClasses(file, forward); } } }); } forward.remove(fileId); return forward; } private void resolveReference( @NotNull PsiReference reference, @NotNull Set<PsiElement> resolved) { PsiElement element = reference.resolve(); if (element != null) { resolved.add(element); } refCount.incrementAndGet(); } private static void addIdAndSuperClasses(PsiFile file, @NotNull TIntHashSet forward) { if (file instanceof PsiJavaFile && file.getName().equals("Object.class") && ((PsiJavaFile) file).getPackageName().equals("java.lang")) { return; } VirtualFile virtualFile = PsiUtilCore.getVirtualFile(file); if (virtualFile instanceof VirtualFileWithId && forward.add(getAbsId(virtualFile)) && file instanceof PsiClassOwner) { for (PsiClass aClass : ((PsiClassOwner) file).getClasses()) { for (PsiClass superClass : aClass.getSupers()) { addIdAndSuperClasses(superClass.getContainingFile(), forward); } } } } @Override @Nullable public int[] getBackwardIds(@NotNull VirtualFileWithId file) { if (!isUpToDate()) return null; int fileId = getAbsId((VirtualFile) file); return storage.get(fileId); } private String prevLog = ""; private static final Set<JavaSourceRootType> SOURCE_ROOTS = ContainerUtil.newTroveSet(JavaSourceRootType.SOURCE, JavaSourceRootType.TEST_SOURCE); @NotNull @Override public GlobalSearchScope restrictByBackwardIds( @NotNull final VirtualFile virtualFile, @NotNull GlobalSearchScope scope) { final int[] backIds = RefResolveService.getInstance(myProject).getBackwardIds((VirtualFileWithId) virtualFile); if (backIds == null) { return scope; } String files = toVfString(backIds); String log = "Restricting scope of " + virtualFile.getName() + " to " + files; if (!log.equals(prevLog)) { log(log); flushLog(); prevLog = log; } GlobalSearchScope restrictedByBackwardIds = new GlobalSearchScope() { @Override public boolean contains(@NotNull VirtualFile file) { if (!(file instanceof VirtualFileWithId) || file.equals(virtualFile) || ArrayUtil.indexOf(backIds, getAbsId(file)) != -1) return true; return false & !myProjectFileIndex.isUnderSourceRootOfType( file, SOURCE_ROOTS); // filter out source file which we know for sure does not // reference the element } @Override public int compare(@NotNull VirtualFile file1, @NotNull VirtualFile file2) { return 0; } @Override public boolean isSearchInModuleContent(@NotNull Module aModule) { return true; } @Override public boolean isSearchInLibraries() { return false; } }; return scope.intersectWith(restrictedByBackwardIds); } @Override public boolean queue(@NotNull Collection<VirtualFile> files, @NotNull Object reason) { if (files.isEmpty()) { return false; } boolean queued = false; List<VirtualFile> added = new ArrayList<VirtualFile>(files.size()); for (VirtualFile file : files) { boolean wasAdded = queueIfNeeded(file, myProject); if (wasAdded) { added.add(file); } queued |= wasAdded; } if (queued) { log("Queued to resolve (from " + reason + "): " + toVfString(added)); flushLog(); } return queued; } @Override public boolean isUpToDate() { return ENABLED && !myDisposed && upToDate; } @Override public int getQueueSize() { synchronized (filesToResolve) { return filesToResolve.size(); } } private final List<Listener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList(); @Override public void addListener(@NotNull Disposable parent, @NotNull final Listener listener) { myListeners.add(listener); Disposer.register( parent, new Disposable() { @Override public void dispose() { myListeners.remove(listener); } }); } private static class MyProgress extends ProgressIndicatorBase implements Disposable { @Override public void dispose() {} } }
@NotNull @Override public Runnable processFile(final PsiFile file) { VirtualFile vFile = file.getVirtualFile(); if (vFile instanceof VirtualFileWindow) vFile = ((VirtualFileWindow) vFile).getDelegate(); final Project project = file.getProject(); if (vFile == null || !ProjectRootManager.getInstance(project).getFileIndex().isInSourceContent(vFile)) { return EmptyRunnable.INSTANCE; } final List<Pair<String, Boolean>> names = new ArrayList<Pair<String, Boolean>>(); final Set<String> demandedForNested = new HashSet<>(); collectNamesToImport(names, demandedForNested, (XmlFile) file); Collections.sort(names, (o1, o2) -> StringUtil.compare(o1.first, o2.first, true)); final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(project); final List<Pair<String, Boolean>> sortedNames = ImportHelper.sortItemsAccordingToSettings(names, settings); final HashSet<String> onDemand = new HashSet<String>(); ImportHelper.collectOnDemandImports(sortedNames, onDemand, settings); onDemand.addAll(demandedForNested); final Set<String> imported = new HashSet<String>(); final List<String> imports = new ArrayList<String>(); for (Pair<String, Boolean> pair : sortedNames) { final String qName = pair.first; final String packageName = StringUtil.getPackageName(qName); if (imported.contains(packageName) || imported.contains(qName)) { continue; } if (onDemand.contains(packageName)) { imported.add(packageName); imports.add("<?import " + packageName + ".*?>"); } else { imported.add(qName); imports.add("<?import " + qName + "?>"); } } final PsiFileFactory factory = PsiFileFactory.getInstance(file.getProject()); final XmlFile dummyFile = (XmlFile) factory.createFileFromText( "_Dummy_.fxml", StdFileTypes.XML, StringUtil.join(imports, "\n")); final XmlDocument document = dummyFile.getDocument(); final XmlProlog newImportList = document != null ? document.getProlog() : null; if (newImportList == null) return EmptyRunnable.getInstance(); return () -> { final XmlDocument xmlDocument = ((XmlFile) file).getDocument(); final XmlProlog prolog = xmlDocument != null ? xmlDocument.getProlog() : null; if (prolog != null) { final Collection<XmlProcessingInstruction> instructions = PsiTreeUtil.findChildrenOfType(prolog, XmlProcessingInstruction.class); for (final XmlProcessingInstruction instruction : instructions) { final ASTNode node = instruction.getNode(); final ASTNode nameNode = node.findChildByType(XmlTokenType.XML_NAME); if (nameNode != null && nameNode.getText().equals("import")) { instruction.delete(); } } prolog.add(newImportList); } else { document.addBefore(newImportList, document.getRootTag()); } }; }
public void testDelayedWorks() throws InterruptedException { final AppScheduledExecutorService service = new AppScheduledExecutorService(getName()); final List<LogInfo> log = Collections.synchronizedList(new ArrayList<>()); assertFalse(service.isShutdown()); assertFalse(service.isTerminated()); service.invokeAll( Collections.nCopies( service.getBackendPoolCorePoolSize() + 1, Executors.callable(EmptyRunnable.getInstance()))); // pre-start all threads int delay = 1000; long start = System.currentTimeMillis(); ScheduledFuture<?> f1 = service.schedule( () -> { log.add(new LogInfo(1)); TimeoutUtil.sleep(10); }, delay, TimeUnit.MILLISECONDS); assertFalse(service.isShutdown()); assertFalse(service.isTerminated()); ScheduledFuture<?> f2 = service.schedule( () -> { log.add(new LogInfo(2)); TimeoutUtil.sleep(10); }, delay, TimeUnit.MILLISECONDS); assertFalse(service.isShutdown()); assertFalse(service.isTerminated()); ScheduledFuture<?> f3 = service.schedule( () -> { log.add(new LogInfo(3)); TimeoutUtil.sleep(10); }, delay, TimeUnit.MILLISECONDS); assertFalse(service.isShutdown()); assertFalse(service.isTerminated()); Future<?> f4 = service.submit((Runnable) () -> log.add(new LogInfo(4))); assertFalse(service.isShutdown()); assertFalse(service.isTerminated()); assertFalse(f1.isDone()); assertFalse(f2.isDone()); assertFalse(f3.isDone()); TimeoutUtil.sleep(delay / 2); long elapsed = System.currentTimeMillis() - start; // can be > delay/2 on overloaded agent assertEquals(String.valueOf(f1.isDone()), elapsed > delay, f1.isDone()); assertEquals(String.valueOf(f2.isDone()), elapsed > delay, f2.isDone()); assertEquals(String.valueOf(f3.isDone()), elapsed > delay, f3.isDone()); assertTrue(f4.isDone()); TimeoutUtil.sleep(delay / 2 + 500); assertTrue(f1.isDone()); assertTrue(f2.isDone()); assertTrue(f3.isDone()); assertTrue(f4.isDone()); assertEquals(4, log.size()); assertEquals(4, log.get(0).runnable); List<Thread> threads = Arrays.asList(log.get(1).currentThread, log.get(2).currentThread, log.get(3).currentThread); assertEquals( threads.toString(), 3, new HashSet<>(threads).size()); // must be executed in parallel service.shutdownAppScheduledExecutorService(); assertTrue(service.awaitTermination(10, TimeUnit.SECONDS)); }
public NewLanguageSettings(String projectPath) { super(new GridLayoutManager(5, 1, new Insets(0, 5, 5, 5), -1, -1)); myProjectPath = projectPath; this.add(new JLabel("Language name:"), Util.getGridConstraints(0)); myLanguageName = new JTextField(); myLanguageName.setName("Name"); myLanguageName .getDocument() .addDocumentListener( new DocumentAdapter() { protected void textChanged(DocumentEvent p0) { if ((myProjectPath == null || myProjectPath.length() == 0)) { return; } String path = myProjectPath + File.separator + "languages" + File.separator; final String langName = getLanguageName(); if (!(langName.equals(getLanguageLocation()))) { path += langName; } if (!(myLangLocationChangedByUser)) { setLanguageLocation(path); } fireChanged(); } }); this.add(myLanguageName, Util.getGridConstraints(1)); myLanguageLocation = new JTextField(); myLanguageLocation.setName("Path"); myLanguageLocation .getDocument() .addDocumentListener( new DocumentAdapter() { protected void textChanged(DocumentEvent p0) { if (myLangLocationDocListenerEnabled) { myLangLocationChangedByUser = true; } } }); final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor(); InsertPathAction.addTo(myLanguageLocation, descriptor); BrowseFilesListener listener = new BrowseFilesListener( myLanguageLocation, "Choose Language Location Folder", "", descriptor); FieldPanel fieldPanel = new FieldPanel( myLanguageLocation, "Language location:", null, listener, EmptyRunnable.getInstance()); FileChooserFactory.getInstance() .installFileCompletion(fieldPanel.getTextField(), descriptor, false, null); this.add(fieldPanel, Util.getGridConstraints(2)); myRuntimeSolution = new JCheckBox("Create Runtime Solution"); this.add(myRuntimeSolution, Util.getGridConstraints(3)); mySandboxSolution = new JCheckBox("Create Sandbox Solution"); this.add(mySandboxSolution, Util.getGridConstraints(4)); this.setPreferredSize(new Dimension(400, 100)); reset(); }