@Override public Map<LookupElement, StringBuilder> getRelevanceStrings() { final LinkedHashMap<LookupElement, StringBuilder> map = new LinkedHashMap<LookupElement, StringBuilder>(); for (LookupElement item : myItems) { map.put(item, new StringBuilder()); } final MultiMap<CompletionSorterImpl, LookupElement> inputBySorter = groupItemsBySorter(new ArrayList<LookupElement>(map.keySet())); if (inputBySorter.size() > 1) { for (LookupElement element : map.keySet()) { map.get(element).append(obtainSorter(element)).append(": "); } } for (CompletionSorterImpl sorter : inputBySorter.keySet()) { final LinkedHashMap<LookupElement, StringBuilder> subMap = new LinkedHashMap<LookupElement, StringBuilder>(); for (LookupElement element : inputBySorter.get(sorter)) { subMap.put(element, map.get(element)); } Classifier<LookupElement> classifier = myClassifiers.get(sorter); if (classifier != null) { classifier.describeItems(subMap, createContext(false)); } } return map; }
void submitPasses( @NotNull Map<FileEditor, HighlightingPass[]> passesMap, @NotNull DaemonProgressIndicator updateProgress) { if (isDisposed()) return; // null keys are ok MultiMap<Document, FileEditor> documentToEditors = MultiMap.createSet(); MultiMap<FileEditor, TextEditorHighlightingPass> documentBoundPasses = MultiMap.createSmart(); MultiMap<FileEditor, EditorBoundHighlightingPass> editorBoundPasses = MultiMap.createSmart(); List<Pair<FileEditor, TextEditorHighlightingPass>> passesWithNoDocuments = new ArrayList<>(); Set<VirtualFile> vFiles = new HashSet<>(); for (Map.Entry<FileEditor, HighlightingPass[]> entry : passesMap.entrySet()) { FileEditor fileEditor = entry.getKey(); HighlightingPass[] passes = entry.getValue(); Document document; if (fileEditor instanceof TextEditor) { Editor editor = ((TextEditor) fileEditor).getEditor(); LOG.assertTrue(!(editor instanceof EditorWindow)); document = editor.getDocument(); } else { VirtualFile virtualFile = ((FileEditorManagerEx) FileEditorManager.getInstance(myProject)).getFile(fileEditor); document = virtualFile == null ? null : FileDocumentManager.getInstance().getDocument(virtualFile); } if (document != null) { vFiles.add(FileDocumentManager.getInstance().getFile(document)); } int prevId = 0; for (final HighlightingPass pass : passes) { if (pass instanceof EditorBoundHighlightingPass) { EditorBoundHighlightingPass editorPass = (EditorBoundHighlightingPass) pass; editorPass.setId( nextPassId.incrementAndGet()); // have to make ids unique for this document editorBoundPasses.putValue(fileEditor, editorPass); } else { TextEditorHighlightingPass textEditorHighlightingPass = convertToTextHighlightingPass(pass, document, nextPassId, prevId); document = textEditorHighlightingPass.getDocument(); documentBoundPasses.putValue(fileEditor, textEditorHighlightingPass); if (document == null) { passesWithNoDocuments.add(Pair.create(fileEditor, textEditorHighlightingPass)); } else { documentToEditors.putValue(document, fileEditor); } prevId = textEditorHighlightingPass.getId(); } } } List<ScheduledPass> freePasses = new ArrayList<>(documentToEditors.size() * 5); List<ScheduledPass> dependentPasses = new ArrayList<>(documentToEditors.size() * 10); // (fileEditor, passId) -> created pass Map<Pair<FileEditor, Integer>, ScheduledPass> toBeSubmitted = new THashMap<>(passesMap.size()); final AtomicInteger threadsToStartCountdown = new AtomicInteger(0); for (Map.Entry<Document, Collection<FileEditor>> entry : documentToEditors.entrySet()) { Collection<FileEditor> fileEditors = entry.getValue(); Document document = entry.getKey(); FileEditor preferredFileEditor = getPreferredFileEditor(document, fileEditors); List<TextEditorHighlightingPass> passes = (List<TextEditorHighlightingPass>) documentBoundPasses.get(preferredFileEditor); if (passes.isEmpty()) { continue; } sortById(passes); for (TextEditorHighlightingPass currentPass : passes) { createScheduledPass( preferredFileEditor, currentPass, toBeSubmitted, passes, freePasses, dependentPasses, updateProgress, threadsToStartCountdown); } } for (Map.Entry<FileEditor, Collection<EditorBoundHighlightingPass>> entry : editorBoundPasses.entrySet()) { FileEditor fileEditor = entry.getKey(); Collection<EditorBoundHighlightingPass> createdEditorBoundPasses = entry.getValue(); List<TextEditorHighlightingPass> createdDocumentBoundPasses = (List<TextEditorHighlightingPass>) documentBoundPasses.get(fileEditor); List<TextEditorHighlightingPass> allCreatedPasses = new ArrayList<>(createdDocumentBoundPasses); allCreatedPasses.addAll(createdEditorBoundPasses); for (EditorBoundHighlightingPass pass : createdEditorBoundPasses) { createScheduledPass( fileEditor, pass, toBeSubmitted, allCreatedPasses, freePasses, dependentPasses, updateProgress, threadsToStartCountdown); } } for (Pair<FileEditor, TextEditorHighlightingPass> pair : passesWithNoDocuments) { FileEditor fileEditor = pair.first; TextEditorHighlightingPass pass = pair.second; createScheduledPass( fileEditor, pass, toBeSubmitted, ContainerUtil.emptyList(), freePasses, dependentPasses, updateProgress, threadsToStartCountdown); } if (CHECK_CONSISTENCY && !ApplicationInfoImpl.isInPerformanceTest()) { assertConsistency(freePasses, toBeSubmitted, threadsToStartCountdown); } log( updateProgress, null, vFiles + " ----- starting " + threadsToStartCountdown.get(), freePasses); for (ScheduledPass dependentPass : dependentPasses) { mySubmittedPasses.put(dependentPass, Job.NULL_JOB); } for (ScheduledPass freePass : freePasses) { submit(freePass); } }
@Override protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException { final GrField field; if (element.getParent() instanceof GrField) { field = (GrField) element.getParent(); } else { final PsiReference ref = element.getReference(); LOG.assertTrue(ref != null); PsiElement resolved = ref.resolve(); if (resolved instanceof GrAccessorMethod) { resolved = ((GrAccessorMethod) resolved).getProperty(); } LOG.assertTrue(resolved instanceof GrField); field = (GrField) resolved; } final HashSet<PsiReference> usages = new HashSet<PsiReference>(); usages.addAll(ReferencesSearch.search(field).findAll()); final GrAccessorMethod[] getters = field.getGetters(); for (GrAccessorMethod getter : getters) { usages.addAll(MethodReferencesSearch.search(getter).findAll()); } final GrAccessorMethod setter = field.getSetter(); if (setter != null) { usages.addAll(MethodReferencesSearch.search(setter).findAll()); } final String fieldName = field.getName(); LOG.assertTrue(fieldName != null); final Collection<PsiElement> fieldUsages = new HashSet<PsiElement>(); MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>(); for (PsiReference usage : usages) { final PsiElement psiElement = usage.getElement(); if (PsiUtil.isMethodUsage(psiElement)) continue; if (!GroovyFileType.GROOVY_LANGUAGE.equals(psiElement.getLanguage())) { conflicts.putValue( psiElement, GroovyIntentionsBundle.message("closure.is.accessed.outside.of.groovy", fieldName)); } else { if (psiElement instanceof GrReferenceExpression) { fieldUsages.add(psiElement); if (PsiUtil.isAccessedForWriting((GrExpression) psiElement)) { conflicts.putValue( psiElement, GroovyIntentionsBundle.message("write.access.to.closure.variable", fieldName)); } } else if (psiElement instanceof GrArgumentLabel) { conflicts.putValue( psiElement, GroovyIntentionsBundle.message("field.is.used.in.argument.label", fieldName)); } } } final PsiClass containingClass = field.getContainingClass(); final GrExpression initializer = field.getInitializerGroovy(); LOG.assertTrue(initializer != null); final PsiType type = initializer.getType(); LOG.assertTrue(type instanceof GrClosureType); final GrSignature signature = ((GrClosureType) type).getSignature(); final List<MethodSignature> signatures = GrClosureSignatureUtil.generateAllMethodSignaturesBySignature(fieldName, signature); for (MethodSignature s : signatures) { final PsiMethod method = MethodSignatureUtil.findMethodBySignature(containingClass, s, true); if (method != null) { conflicts.putValue( method, GroovyIntentionsBundle.message( "method.with.signature.already.exists", GroovyPresentationUtil.getSignaturePresentation(s))); } } if (conflicts.size() > 0) { final ConflictsDialog conflictsDialog = new ConflictsDialog( project, conflicts, new Runnable() { @Override public void run() { execute(field, fieldUsages); } }); conflictsDialog.show(); if (conflictsDialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) return; } execute(field, fieldUsages); }