From 1b40be5b1dfe64cc86035528c355f1d20434ec28 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 19 Jan 2015 13:22:57 +0100 Subject: [PATCH 01/47] revert my previous temp fix 0c90cc01992c2c3a19391c5199a9f85eeae7dac2 --- .../editorActions/CompletionAutoPopupHandler.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java index 0c618e515248..8010e76335bb 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java @@ -32,8 +32,6 @@ import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiPlainText; -import com.intellij.psi.PsiPlainTextFile; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import org.jetbrains.annotations.NotNull; @@ -67,9 +65,7 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { return Result.STOP; } - if ((Character.isLetter(charTyped) || charTyped == '_') && - !(file instanceof PsiPlainTextFile) // todo [maxim, peter] why we start autopopup when editing text files ? it cancels find preview - ) { + if (Character.isLetter(charTyped) || charTyped == '_') { AutoPopupController.getInstance(project).scheduleAutoPopup(editor); return Result.STOP; } From 4d457b8f270273bd09655040c3c890f75aeb1403 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 19 Jan 2015 14:07:05 +0100 Subject: [PATCH 02/47] [performance optimization] avoid calling VirtualFile.getPath() for files that doesn't have "scratches" as parent file name --- .../com/intellij/ide/scratch/ScratchFileServiceImpl.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileServiceImpl.java b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileServiceImpl.java index 5352b24cb5ec..e2e264a8e86c 100644 --- a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileServiceImpl.java @@ -36,7 +36,9 @@ import com.intellij.openapi.fileTypes.*; import com.intellij.openapi.fileTypes.ex.FileTypeIdentifiableByVirtualFile; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Iconable; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -305,8 +307,13 @@ public abstract class ScratchFileServiceImpl extends ScratchFileService { } private static boolean isFileInRootImpl(@NotNull VirtualFile file, RootId scratches) { + // files are created under scratches.getId() directory, quickly check parent name to avoid calling getPath() + VirtualFile parent = file.getParent(); + if (parent == null) return false; + if (!Comparing.equal(parent.getNameSequence(), scratches.getId(), SystemInfo.isFileSystemCaseSensitive)) return false; + String rootPath = ScratchFileService.getInstance().getRootPath(scratches); - return file.getPath().startsWith(rootPath); + return FileUtil.startsWith(file.getPath(), rootPath); } private static class MyFileType extends LanguageFileType implements FileTypeIdentifiableByVirtualFile, InternalFileType { From 89335d7a78bfd18297acdee3ccbbc50d383ac84f Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 19 Jan 2015 16:51:04 +0100 Subject: [PATCH 03/47] smartly restart find in file on write action --- .../com/intellij/find/impl/FindDialog.java | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java index 6db6bfe0e4db..25f1e631ca9e 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java @@ -61,6 +61,7 @@ import com.intellij.ui.table.JBTable; import com.intellij.usageView.UsageInfo; import com.intellij.usages.*; import com.intellij.usages.impl.UsagePreviewPanel; +import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; import com.intellij.util.Processor; @@ -128,6 +129,7 @@ public class FindDialog extends DialogWrapper { private JBTable myResultsPreviewTable; private UsagePreviewPanel myUsagePreviewPanel; private TabbedPane myContent; + private Alarm mySearchRescheduleOnCancellationsAlarm; private volatile ProgressIndicatorBase myResultsPreviewSearchProgress; public FindDialog(@NotNull Project project, @NotNull FindModel model, @NotNull Consumer myOkHandler){ @@ -176,6 +178,7 @@ public class FindDialog extends DialogWrapper { @Override protected void dispose() { finishPreviousPreviewSearch(); + if (mySearchRescheduleOnCancellationsAlarm != null) Disposer.dispose(mySearchRescheduleOnCancellationsAlarm); if (myUsagePreviewPanel != null) Disposer.dispose(myUsagePreviewPanel); for(Map.Entry e: myComboBoxListeners.entrySet()) { e.getKey().removeDocumentListener(e.getValue()); @@ -324,6 +327,7 @@ public class FindDialog extends DialogWrapper { if (state == ModalityState.NON_MODAL) return; // skip initial changes finishPreviousPreviewSearch(); + mySearchRescheduleOnCancellationsAlarm.cancelAllRequests(); final DefaultTableModel model = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { @@ -337,7 +341,6 @@ public class FindDialog extends DialogWrapper { applyTo(modelClone, false); ValidationInfo result = getValidationInfo(modelClone); - if (result != null) return; // todo final PsiDirectory psiDirectory = FindInProjectUtil.getPsiDirectory(modelClone, myProject); @@ -345,6 +348,12 @@ public class FindDialog extends DialogWrapper { myResultsPreviewSearchProgress = progressIndicatorWhenSearchStarted; myResultsPreviewTable.setModel(model); + + if (result != null) { + myResultsPreviewTable.getEmptyText().setText(UIBundle.message("message.nothingToShow")); + return; + } + myResultsPreviewTable.getColumnModel().getColumn(0).setCellRenderer(new UsageTableCellRenderer()); myResultsPreviewTable.getEmptyText().setText("Searching..."); @@ -375,7 +384,7 @@ public class FindDialog extends DialogWrapper { return resultsCount.incrementAndGet() < ShowUsagesAction.USAGES_PAGE_SIZE; } }, processPresentation); - if (resultsCount.get() == 0) { + if (resultsCount.get() == 0 && !progressIndicatorWhenSearchStarted.isCanceled()) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { @@ -389,8 +398,14 @@ public class FindDialog extends DialogWrapper { @Override public void onCanceled(@NotNull ProgressIndicator indicator) { - if (progressIndicatorWhenSearchStarted == myResultsPreviewSearchProgress && resultsCount.get() == 0) { - myResultsPreviewTable.getEmptyText().setText("Cancelled"); + if (isShowing() && progressIndicatorWhenSearchStarted == myResultsPreviewSearchProgress) { + mySearchRescheduleOnCancellationsAlarm.cancelAllRequests(); + mySearchRescheduleOnCancellationsAlarm.addRequest(new Runnable() { + @Override + public void run() { + findSettingsChanged(); + } + }, 100); } } }); @@ -513,6 +528,7 @@ public class FindDialog extends DialogWrapper { } } }); + mySearchRescheduleOnCancellationsAlarm = new Alarm(); previewSplitter.setFirstComponent(new JBScrollPane(myResultsPreviewTable)); previewSplitter.setSecondComponent(myUsagePreviewPanel.createComponent()); myPreviewSplitter = previewSplitter; From f7b4d9724dc2ad1b6c1335a43085be33f04c0bcc Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 19 Jan 2015 16:53:13 +0100 Subject: [PATCH 04/47] introduced getVirtualFilesWithWord: same as getFilesWithWord but without PsiFile --- .../com/intellij/psi/impl/cache/CacheManager.java | 4 ++++ .../psi/impl/cache/impl/IndexCacheManagerImpl.java | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/cache/CacheManager.java b/platform/indexing-impl/src/com/intellij/psi/impl/cache/CacheManager.java index e403f60c8777..fb4a272361dc 100644 --- a/platform/indexing-impl/src/com/intellij/psi/impl/cache/CacheManager.java +++ b/platform/indexing-impl/src/com/intellij/psi/impl/cache/CacheManager.java @@ -18,6 +18,7 @@ package com.intellij.psi.impl.cache; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.UsageSearchContext; @@ -38,6 +39,9 @@ public interface CacheManager { @NotNull PsiFile[] getFilesWithWord(@NotNull String word, short occurenceMask, @NotNull GlobalSearchScope scope, final boolean caseSensitively); + @NotNull + VirtualFile[] getVirtualFilesWithWord(@NotNull String word, short occurenceMask, @NotNull GlobalSearchScope scope, final boolean caseSensitively); + boolean processFilesWithWord(@NotNull Processor processor, @NotNull String word, @MagicConstant(flagsFromClass = UsageSearchContext.class) short occurenceMask, diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/IndexCacheManagerImpl.java b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/IndexCacheManagerImpl.java index 1a44cf491b54..d2027575121a 100644 --- a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/IndexCacheManagerImpl.java +++ b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/IndexCacheManagerImpl.java @@ -65,6 +65,18 @@ public class IndexCacheManagerImpl implements CacheManager{ return processor.getResults().isEmpty() ? PsiFile.EMPTY_ARRAY : processor.toArray(PsiFile.EMPTY_ARRAY); } + @Override + @NotNull + public VirtualFile[] getVirtualFilesWithWord(@NotNull final String word, final short occurenceMask, @NotNull final GlobalSearchScope scope, final boolean caseSensitively) { + if (myProject.isDefault()) { + return VirtualFile.EMPTY_ARRAY; + } + + final List vFiles = new ArrayList(5); + collectVirtualFilesWithWord(new CommonProcessors.CollectProcessor(vFiles), word, occurenceMask, scope, caseSensitively); + return vFiles.isEmpty() ? VirtualFile.EMPTY_ARRAY : vFiles.toArray(new VirtualFile[vFiles.size()]); + } + // IMPORTANT!!! // Since implementation of virtualFileProcessor.process() may call indices directly or indirectly, // we cannot call it inside FileBasedIndex.processValues() method except in collecting form From 880dd54504d3818b4fbd7b0c9cafc0a537cd68c0 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 19 Jan 2015 20:03:31 +0100 Subject: [PATCH 05/47] [performance optimization] use VirtualFile.getNameSequence() instead of VirtualFile.getName() --- .../openapi/vfs/newvfs/persistent/PersistentFSImpl.java | 2 +- .../src/com/intellij/openapi/vcs/changes/IgnoredFileBean.java | 3 ++- .../jetbrains/python/psi/stubs/PySetuptoolsNamespaceIndex.java | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java index b1c3d90a8aed..bf91a747b948 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java @@ -1323,7 +1323,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone @NotNull @Override public CharSequence getNameSequence() { - return myParentLocalFile.getName(); + return myParentLocalFile.getNameSequence(); } @Override diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/IgnoredFileBean.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/IgnoredFileBean.java index 1091f908b600..2245b5eae90b 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/IgnoredFileBean.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/IgnoredFileBean.java @@ -25,6 +25,7 @@ package com.intellij.openapi.vcs.changes; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; @@ -119,7 +120,7 @@ public class IgnoredFileBean { } else { // quick check for 'file' == exact match pattern - if (IgnoreSettingsType.FILE.equals(myType) && !myFilenameIfFile.equals(file.getName())) return false; + if (IgnoreSettingsType.FILE.equals(myType) && !StringUtil.equals(myFilenameIfFile, file.getNameSequence())) return false; VirtualFile selector = resolve(); if (Comparing.equal(selector, NullVirtualFile.INSTANCE)) return false; diff --git a/python/src/com/jetbrains/python/psi/stubs/PySetuptoolsNamespaceIndex.java b/python/src/com/jetbrains/python/psi/stubs/PySetuptoolsNamespaceIndex.java index 2988922415d2..a0bf1cceb943 100644 --- a/python/src/com/jetbrains/python/psi/stubs/PySetuptoolsNamespaceIndex.java +++ b/python/src/com/jetbrains/python/psi/stubs/PySetuptoolsNamespaceIndex.java @@ -16,6 +16,7 @@ package com.jetbrains.python.psi.stubs; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.indexing.*; @@ -58,7 +59,7 @@ public class PySetuptoolsNamespaceIndex extends ScalarIndexExtension { private FileBasedIndex.InputFilter myInputFilter = new FileBasedIndex.InputFilter() { @Override public boolean acceptInput(@NotNull VirtualFile file) { - return file.getName().endsWith(NAMESPACE_FILE_SUFFIX); + return StringUtil.endsWith(file.getNameSequence(), NAMESPACE_FILE_SUFFIX); } }; From 25b7390eb9578674178a3a8e35e6472cb398c0a0 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 19 Jan 2015 20:40:57 +0100 Subject: [PATCH 06/47] revert 2bd96de1a3d0c6486397dd10c2bb98ad3326205c to avoid performance problem calculating getFileType() for large number of files --- .../src/com/intellij/openapi/roots/FileIndexFacade.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java b/platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java index 96dde81c6a80..8f0dce494eac 100644 --- a/platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java +++ b/platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java @@ -61,7 +61,7 @@ public abstract class FileIndexFacade { public abstract boolean isValidAncestor(@NotNull VirtualFile baseDir, @NotNull VirtualFile child); public boolean shouldBeFound(GlobalSearchScope scope, VirtualFile virtualFile) { - return (scope.isSearchOutsideRootModel() || isInContent(virtualFile) || isInLibrarySource(virtualFile)) && !virtualFile.getFileType().isBinary(); + return scope.isSearchOutsideRootModel() || isInContent(virtualFile) || isInLibrarySource(virtualFile); } @NotNull public abstract ModificationTracker getRootModificationTracker(); From fddbfa9f9e4b1926f71853a4c6a9e2e8fedd3dbf Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 19 Jan 2015 20:54:09 +0100 Subject: [PATCH 07/47] add statistics for IDE help --- .../src/com/intellij/help/impl/HelpManagerImpl.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java b/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java index 340fbb9ae186..8d8fa2d6797b 100644 --- a/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import com.intellij.ide.IdeBundle; import com.intellij.ide.plugins.HelpSetPath; import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.ide.plugins.PluginManager; +import com.intellij.internal.statistic.UsageTrigger; import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.application.ex.ApplicationInfoEx; import com.intellij.openapi.diagnostic.Logger; @@ -49,6 +50,8 @@ public class HelpManagerImpl extends HelpManager { private Object myFXHelpBrowser = null; public void invokeHelp(@Nullable String id) { + UsageTrigger.trigger("ide.help." + id); + if (myHelpSet == null) { myHelpSet = createHelpSet(); } From 2933385ff14c26aa7a4d06870734827584959a0f Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 19 Jan 2015 20:57:24 +0100 Subject: [PATCH 08/47] [performance optimization] use getVirtualFilesWithWord to work with virtual file objects instead of psifile --- .../intellij/find/impl/FindInProjectTask.java | 67 +++++++++---------- .../usages/FindUsagesProcessPresentation.java | 10 +-- .../usages/impl/SearchForUsagesRunnable.java | 10 ++- 3 files changed, 42 insertions(+), 45 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java index 7d3577851221..93e88a25e0fa 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java @@ -82,7 +82,7 @@ class FindInProjectTask { private final Condition myFileMask; private final ProgressIndicator myProgress; @Nullable private final Module myModule; - private final Set myLargeFiles = ContainerUtil.newTroveSet(); + private final Set myLargeFiles = ContainerUtil.newTroveSet(); private boolean myWarningShown; FindInProjectTask(@NotNull final FindModel findModel, @@ -122,9 +122,9 @@ class FindInProjectTask { try { myProgress.setIndeterminate(true); myProgress.setText("Scanning indexed files..."); - final Set filesForFastWordSearch = ApplicationManager.getApplication().runReadAction(new Computable>() { + final Set filesForFastWordSearch = ApplicationManager.getApplication().runReadAction(new Computable>() { @Override - public Set compute() { + public Set compute() { return getFilesForFastWordSearch(); } }); @@ -138,7 +138,7 @@ class FindInProjectTask { myProgress.setIndeterminate(true); myProgress.setText("Scanning non-indexed files..."); boolean skipIndexed = canRelyOnIndices(); - final Collection otherFiles = collectFilesInScope(filesForFastWordSearch, skipIndexed); + final Collection otherFiles = collectFilesInScope(filesForFastWordSearch, skipIndexed); myProgress.setIndeterminate(false); if (LOG.isDebugEnabled()) { @@ -167,13 +167,13 @@ class FindInProjectTask { } } - private static void logStats(Collection otherFiles, long start) { + private static void logStats(Collection otherFiles, long start) { long time = System.currentTimeMillis() - start; final Multiset stats = HashMultiset.create(); - for (PsiFile file : otherFiles) { + for (VirtualFile file : otherFiles) { //noinspection StringToUpperCaseOrToLowerCaseWithoutLocale - stats.add(StringUtil.notNullize(file.getViewProvider().getVirtualFile().getExtension()).toLowerCase()); + stats.add(StringUtil.notNullize(file.getExtension()).toLowerCase()); } List extensions = ContainerUtil.newArrayList(stats.elementSet()); @@ -194,17 +194,16 @@ class FindInProjectTask { LOG.info(message); } - private void searchInFiles(@NotNull Collection psiFiles, + private void searchInFiles(@NotNull Collection virtualFiles, @NotNull FindUsagesProcessPresentation processPresentation, @NotNull final Processor consumer) { int i = 0; long totalFilesSize = 0; int count = 0; - for (final PsiFile psiFile : psiFiles) { - final VirtualFile virtualFile = psiFile.getVirtualFile(); + for (final VirtualFile virtualFile : virtualFiles) { final int index = i++; - if (virtualFile == null) continue; + if (!virtualFile.isValid()) continue; long fileLength = UsageViewManagerImpl.getFileLength(virtualFile); if (fileLength == -1) continue; // Binary or invalid @@ -213,17 +212,26 @@ class FindInProjectTask { if (skipProjectFile && !Registry.is("find.search.in.project.files")) continue; if (fileLength > SINGLE_FILE_SIZE_LIMIT) { - myLargeFiles.add(psiFile); + myLargeFiles.add(virtualFile); continue; } myProgress.checkCanceled(); - myProgress.setFraction((double)index / psiFiles.size()); + myProgress.setFraction((double)index / virtualFiles.size()); String text = FindBundle.message("find.searching.for.string.in.file.progress", myFindModel.getStringToFind(), virtualFile.getPresentableUrl()); myProgress.setText(text); myProgress.setText2(FindBundle.message("find.searching.for.string.in.file.occurrences.progress", count)); + PsiFile psiFile = findFile(virtualFile); + if (psiFile == null) continue; + + if (!(psiFile instanceof PsiBinaryFile)) { + PsiFile sourceFile = (PsiFile)psiFile.getNavigationElement(); + if (sourceFile != null) psiFile = sourceFile; + if (psiFile.getFileType().isBinary()) continue; + } + int countInFile = FindInProjectUtil.processUsagesInFile(psiFile, myFindModel, new Processor() { @Override public boolean process(UsageInfo info) { @@ -258,7 +266,7 @@ class FindInProjectTask { } @NotNull - private Collection collectFilesInScope(@NotNull final Set alreadySearched, final boolean skipIndexed) { + private Collection collectFilesInScope(@NotNull final Set alreadySearched, final boolean skipIndexed) { SearchScope customScope = myFindModel.getCustomScope(); final GlobalSearchScope globalCustomScope = toGlobal(customScope); @@ -266,7 +274,7 @@ class FindInProjectTask { final boolean hasTrigrams = hasTrigrams(myFindModel.getStringToFind()); class EnumContentIterator implements ContentIterator { - final Set myFiles = new LinkedHashSet(); + final Set myFiles = new LinkedHashSet(); @Override public boolean processFile(@NotNull final VirtualFile virtualFile) { @@ -285,14 +293,7 @@ class FindInProjectTask { return; } - PsiFile psiFile = myPsiManager.findFile(virtualFile); - if (psiFile != null && !(psiFile instanceof PsiBinaryFile) && !alreadySearched.contains(psiFile)) { - PsiFile sourceFile = (PsiFile)psiFile.getNavigationElement(); - if (sourceFile != null) psiFile = sourceFile; - if (!psiFile.getFileType().isBinary()) { - myFiles.add(psiFile); - } - } + if (!alreadySearched.contains(virtualFile)) myFiles.add(virtualFile); } private final FileBasedIndexImpl fileBasedIndex = (FileBasedIndexImpl)FileBasedIndex.getInstance(); @@ -309,7 +310,7 @@ class FindInProjectTask { } @NotNull - private Collection getFiles() { + private Collection getFiles() { return myFiles; } } @@ -425,7 +426,7 @@ class FindInProjectTask { @NotNull - private Set getFilesForFastWordSearch() { + private Set getFilesForFastWordSearch() { String stringToFind = myFindModel.getStringToFind(); if (stringToFind.isEmpty() || DumbService.getInstance(myProject).isDumb()) { return Collections.emptySet(); @@ -443,7 +444,7 @@ class FindInProjectTask { scope = ProjectScope.getContentScope(myProject); } - final Set resultFiles = new LinkedHashSet(); + final Set resultFiles = new LinkedHashSet(); if (TrigramIndex.ENABLED) { final Set keys = ContainerUtil.newTroveSet(); @@ -468,10 +469,7 @@ class FindInProjectTask { for (VirtualFile hit : hits) { if (myFileMask.value(hit)) { - PsiFile file = findFile(hit); - if (file != null) { - resultFiles.add(file); - } + resultFiles.add(hit); } } @@ -484,7 +482,7 @@ class FindInProjectTask { @Override public boolean process(VirtualFile file) { if (myFileMask.value(file)) { - ContainerUtil.addIfNotNull(resultFiles, findFile(file)); + ContainerUtil.addIfNotNull(resultFiles, file); } return true; } @@ -492,9 +490,10 @@ class FindInProjectTask { // in case our word splitting is incorrect CacheManager cacheManager = CacheManager.SERVICE.getInstance(myProject); - PsiFile[] filesWithWord = cacheManager.getFilesWithWord(stringToFind, UsageSearchContext.ANY, scope, myFindModel.isCaseSensitive()); - for (PsiFile file : filesWithWord) { - if (myFileMask.value(file.getVirtualFile())) { + VirtualFile[] filesWithWord = cacheManager.getVirtualFilesWithWord(stringToFind, UsageSearchContext.ANY, scope, + myFindModel.isCaseSensitive()); + for (VirtualFile file : filesWithWord) { + if (myFileMask.value(file)) { resultFiles.add(file); } } diff --git a/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java b/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java index c303c7fd0496..98b9f2389e30 100644 --- a/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java +++ b/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java @@ -17,7 +17,7 @@ package com.intellij.usages; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.util.Factory; -import com.intellij.psi.PsiFile; +import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -40,7 +40,7 @@ public class FindUsagesProcessPresentation { private boolean myShowPanelIfOnlyOneUsage; private boolean myShowNotFoundMessage; private Factory myProgressIndicatorFactory; - private Collection myLargeFiles; + private Collection myLargeFiles; private boolean myShowFindOptionsPrompt = true; private Runnable mySearchWithProjectFiles; private boolean myCanceled; @@ -92,13 +92,13 @@ public class FindUsagesProcessPresentation { mySearchWithProjectFiles = searchWithProjectFiles; } - public void setLargeFilesWereNotScanned(@NotNull Collection largeFiles) { + public void setLargeFilesWereNotScanned(@NotNull Collection largeFiles) { myLargeFiles = largeFiles; } @NotNull - public Collection getLargeFiles() { - return myLargeFiles == null ? Collections.emptyList() : myLargeFiles; + public Collection getLargeFiles() { + return myLargeFiles == null ? Collections.emptyList() : myLargeFiles; } public boolean isShowFindOptionsPrompt() { diff --git a/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java b/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java index 449c462d7668..90cbcd7c784b 100644 --- a/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java +++ b/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java @@ -43,7 +43,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.ToolWindowId; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.ui.HyperlinkAdapter; @@ -129,7 +128,7 @@ class SearchForUsagesRunnable implements Runnable { @NotNull final List lines) { com.intellij.usageView.UsageViewManager.getInstance(project); // in case tool window not registered - final Collection largeFiles = processPresentation.getLargeFiles(); + final Collection largeFiles = processPresentation.getLargeFiles(); List resultLines = new ArrayList(lines); HyperlinkListener resultListener = listener; if (!largeFiles.isEmpty()) { @@ -181,18 +180,17 @@ class SearchForUsagesRunnable implements Runnable { } @NotNull - private static String detailedLargeFilesMessage(@NotNull Collection largeFiles) { + private static String detailedLargeFilesMessage(@NotNull Collection largeFiles) { String message = ""; if (largeFiles.size() == 1) { - final VirtualFile vFile = largeFiles.iterator().next().getVirtualFile(); + final VirtualFile vFile = largeFiles.iterator().next(); message += "File " + presentableFileInfo(vFile) + " is "; } else { message += "Files
"; int counter = 0; - for (PsiFile file : largeFiles) { - final VirtualFile vFile = file.getVirtualFile(); + for (VirtualFile vFile : largeFiles) { message += presentableFileInfo(vFile) + "
"; if (counter++ > 10) break; } From 1d7f537142df41cdd02613e973c39824567e2baa Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Mon, 19 Jan 2015 21:16:54 +0100 Subject: [PATCH 09/47] CPP-2056 Enormous increase of 'Pass system environment' field: proper fix --- .../src/com/intellij/ui/CommonActionsPanel.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java b/platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java index 3aacbf00edf5..9e31235b469d 100644 --- a/platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java +++ b/platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java @@ -25,6 +25,7 @@ import com.intellij.util.IconUtil; import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.ui.MacUIUtil; import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -38,6 +39,7 @@ import java.util.*; */ public class CommonActionsPanel extends JPanel { private final boolean myDecorateButtons; + private final ActionToolbarPosition myPosition; public enum Buttons { ADD, REMOVE, EDIT, UP, DOWN; @@ -102,6 +104,7 @@ public class CommonActionsPanel extends JPanel { String addName, String removeName, String moveUpName, String moveDownName, String editName, Icon addIcon, Buttons... buttons) { super(new BorderLayout()); + myPosition = position; final Listener listener = factory.createListener(this); AnActionButton[] actions = new AnActionButton[buttons.length + (additionalActions == null ? 0 : additionalActions.length)]; for (int i = 0; i < buttons.length; i++) { @@ -224,6 +227,11 @@ public class CommonActionsPanel extends JPanel { } } + @NotNull + public ActionToolbarPosition getPosition() { + return myPosition; + } + static class MyActionButton extends AnActionButton implements DumbAware { private final Buttons myButton; private final Listener myListener; From c2f6dc17589b05eb50c519d83687d5d24977ba5f Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Tue, 20 Jan 2015 00:10:46 +0100 Subject: [PATCH 10/47] (with special flag) fileloader data is persisted in classpath.index file and reused if available (make will clean the index files upon nontrivial change, see d261422680c7868d5d556c7eee653fcd5f4fdcc2). This change allows faster debugged Idea / tests (with -Djava.system.class.loader=UrlClassLoader) start up especially for Windows --- .../intellij/util/lang/ClasspathCache.java | 7 + .../com/intellij/util/lang/FileLoader.java | 172 ++++++++++++++++-- 2 files changed, 159 insertions(+), 20 deletions(-) diff --git a/platform/util/src/com/intellij/util/lang/ClasspathCache.java b/platform/util/src/com/intellij/util/lang/ClasspathCache.java index 7d43900cf6ee..bfe39ed936ce 100644 --- a/platform/util/src/com/intellij/util/lang/ClasspathCache.java +++ b/platform/util/src/com/intellij/util/lang/ClasspathCache.java @@ -65,6 +65,13 @@ public class ClasspathCache { public void addNameEntry(String name) { myNames.add(transformName(name)); } + + List getResourcePaths() { + return myResourcePaths; + } + List getNames() { + return myNames; + } } private final ReadWriteLock myLock = new ReentrantReadWriteLock(); diff --git a/platform/util/src/com/intellij/util/lang/FileLoader.java b/platform/util/src/com/intellij/util/lang/FileLoader.java index f072acd480f4..b49c70b9a347 100644 --- a/platform/util/src/com/intellij/util/lang/FileLoader.java +++ b/platform/util/src/com/intellij/util/lang/FileLoader.java @@ -23,6 +23,9 @@ import sun.misc.Resource; import java.io.*; import java.net.URL; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; class FileLoader extends Loader { private final File myRootDir; @@ -62,7 +65,11 @@ class FileLoader extends Loader { } private String getRelativeResourcePath(final File file) { - String relativePath = file.getAbsolutePath().substring(myRootDirAbsolutePath.length()); + return getRelativeResourcePath(file.getAbsolutePath()); + } + + private String getRelativeResourcePath(final String absFilePath) { + String relativePath = absFilePath.substring(myRootDirAbsolutePath.length()); relativePath = relativePath.replace(File.separatorChar, '/'); if (relativePath.startsWith("/")) relativePath = relativePath.substring(1); return relativePath; @@ -110,31 +117,156 @@ class FileLoader extends Loader { return null; } + private static final AtomicInteger totalLoaders = new AtomicInteger(); + private static final AtomicLong totalScanning = new AtomicLong(); + private static final AtomicLong totalSaving = new AtomicLong(); + private static final AtomicLong totalReading = new AtomicLong(); + private static final boolean INDEX_PERSISTENCE_DISABLED = Boolean.parseBoolean(System.getProperty("idea.classpath.index.disabled", "true")); + private static final Boolean doLogging = false; + + private ClasspathCache.LoaderData tryReadFromIndex() { + if (INDEX_PERSISTENCE_DISABLED) return null; + long started = System.nanoTime(); + ClasspathCache.LoaderData loaderData = new ClasspathCache.LoaderData(); + File index = getIndexFileFile(); + + BufferedReader reader = null; + try { + reader = new BufferedReader(new FileReader(index)); + readList(reader, loaderData.getResourcePaths()); + readList(reader, loaderData.getNames()); + + return loaderData; + } catch (Exception ex) { + if (!(ex instanceof FileNotFoundException)) index.delete(); + } + finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException ignore) {} + } + totalReading.addAndGet(System.nanoTime() - started); + } + + return null; + } + + private static void readList(BufferedReader reader, List paths) throws IOException { + String line = reader.readLine(); + int numberOfElements = Integer.parseInt(line); + for(int i = 0; i < numberOfElements; ++i) paths.add(reader.readLine()); + } + + private void trySaveToIndex(ClasspathCache.LoaderData data) { + if (INDEX_PERSISTENCE_DISABLED) return; + long started = System.nanoTime(); + File index = getIndexFileFile(); + BufferedWriter writer = null; + + try { + writer = new BufferedWriter(new FileWriter(index)); + writeList(writer, data.getResourcePaths()); + writeList(writer, data.getNames()); + } catch (IOException ex) { + index.delete(); + } + finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException ignore) {} + } + totalSaving.addAndGet(System.nanoTime() - started); + } + } + + private static void writeList(BufferedWriter writer, List paths) throws IOException { + writer.append(Integer.toString(paths.size())).append('\n'); + for(String s: paths) writer.append(s).append('\n'); + } + + @NotNull + private File getIndexFileFile() { + return new File(myRootDir, "classpath.index"); + } + @NotNull @Override public ClasspathCache.LoaderData buildData() throws IOException { - ClasspathCache.LoaderData loaderData = new ClasspathCache.LoaderData(); - File index = new File(myRootDir, "classpath.index"); - if (index.exists()) { - BufferedReader reader = new BufferedReader(new FileReader(index)); - try { - do { - String line = reader.readLine(); - if (line == null) break; - loaderData.addResourceEntry(line); - loaderData.addNameEntry(line); - } - while (true); - } - finally { - reader.close(); + ClasspathCache.LoaderData fromIndex = tryReadFromIndex(); + final ClasspathCache.LoaderData loaderData = fromIndex != null ? fromIndex : new ClasspathCache.LoaderData(); + + final int nsMsFactor = 1000000; + int currentLoaders = totalLoaders.incrementAndGet(); + long currentScanning; + if (fromIndex == null) { + long started = System.nanoTime(); +/* // todo code below uses java 7 api, uncomment once we are done with Java 6 + if (SystemInfo.isJavaVersionAtLeast("1.7") && !SystemProperties.getBooleanProperty("idea.no.nio.class.scanning", false) && false) { + final Path start = Paths.get(myRootDir.getPath()); + Files.walkFileTree(start, new FileVisitor() { + final Stack containsClasses = new Stack(); + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + containsClasses.push(Boolean.FALSE); + if (dir != start) loaderData.addNameEntry(dir.getFileName().toString()); + loaderData.addResourceEntry(getRelativeResourcePath(dir.toAbsolutePath().toString())); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + String fileName = file.getFileName().toString(); + final boolean isClass = fileName.endsWith(UrlClassLoader.CLASS_EXTENSION); + if (isClass) { + Boolean dirContainClasses = containsClasses.peek(); + if (dirContainClasses == Boolean.FALSE) { + loaderData.addResourceEntry(getRelativeResourcePath(file.toAbsolutePath().toString())); + containsClasses.set(containsClasses.size() - 1, Boolean.TRUE); + } + loaderData.addNameEntry(fileName); + } + else { + loaderData.addNameEntry(fileName); + loaderData.addResourceEntry(getRelativeResourcePath(file.toAbsolutePath().toString())); + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { + throw exc; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + containsClasses.pop(); + return FileVisitResult.CONTINUE; + } + }); + } else { */ + buildPackageCache(myRootDir, loaderData); + /* } */ + final long doneNanos = System.nanoTime() - started; + currentScanning = totalScanning.addAndGet(doneNanos); + if (doLogging) { + System.out.println("Scanned: " + myRootDirAbsolutePath + " for " + (doneNanos / nsMsFactor) + "ms"); } + trySaveToIndex(loaderData); + } else { + currentScanning = totalScanning.get(); } - else { - loaderData.addResourceEntry("foo.class"); - loaderData.addResourceEntry("bar.properties"); - buildPackageCache(myRootDir, loaderData); + + loaderData.addResourceEntry("foo.class"); + loaderData.addResourceEntry("bar.properties"); + + if (doLogging) { + System.out.println("Scanning: " + (currentScanning / nsMsFactor) + "ms, saving: " + (totalSaving.get() / nsMsFactor) + + "ms, loading:" + (totalReading.get() / nsMsFactor) + "ms for " + currentLoaders + " loaders"); } + return loaderData; } From b92369b5052c62082702e9f2d960b026c0c43d05 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Tue, 20 Jan 2015 10:28:32 +0300 Subject: [PATCH 11/47] Extracted JSP imports panel from Java Code Style Settings imports tab into JSP one --- .../options/CodeStyleImportForm.form | 8 --- .../options/CodeStyleImportsPanel.java | 59 +------------------ 2 files changed, 2 insertions(+), 65 deletions(-) diff --git a/java/java-impl/src/com/intellij/application/options/CodeStyleImportForm.form b/java/java-impl/src/com/intellij/application/options/CodeStyleImportForm.form index 370492c2c7de..7009dba79298 100644 --- a/java/java-impl/src/com/intellij/application/options/CodeStyleImportForm.form +++ b/java/java-impl/src/com/intellij/application/options/CodeStyleImportForm.form @@ -29,14 +29,6 @@ - - - - - - - - diff --git a/java/java-impl/src/com/intellij/application/options/CodeStyleImportsPanel.java b/java/java-impl/src/com/intellij/application/options/CodeStyleImportsPanel.java index 47e7b3ad5942..8a47633f2b93 100644 --- a/java/java-impl/src/com/intellij/application/options/CodeStyleImportsPanel.java +++ b/java/java-impl/src/com/intellij/application/options/CodeStyleImportsPanel.java @@ -39,11 +39,8 @@ public class CodeStyleImportsPanel extends JPanel { private JBTable myPackageTable; private final CodeStyleSettings mySettings; - private JRadioButton myJspImportCommaSeparated; - private JRadioButton myJspOneImportPerDirective; private JPanel myGeneralPanel; - private JPanel myJSPPanel; private JPanel myPackagesPanel; private JPanel myImportsLayoutPanel; private JPanel myWholePanel; @@ -56,7 +53,6 @@ public class CodeStyleImportsPanel extends JPanel { add(myWholePanel, BorderLayout.CENTER); myGeneralPanel.add(createGeneralOptionsPanel(), BorderLayout.CENTER); - myJSPPanel.add(createJspImportLayoutPanel(), BorderLayout.CENTER); createImportPanel(); createPackagePanel(); } @@ -77,47 +73,6 @@ public class CodeStyleImportsPanel extends JPanel { myPackagesPanel.add(PackagePanel.createPackagesPanel(myPackageTable, myPackageList), BorderLayout.CENTER); } - private JPanel createJspImportLayoutPanel() { - ButtonGroup buttonGroup = new ButtonGroup(); - myJspImportCommaSeparated = new JRadioButton(ApplicationBundle.message("radio.prefer.comma.separated.import.list")); - myJspOneImportPerDirective = new JRadioButton(ApplicationBundle.message("radio.prefer.one.import.statement.per.page.directive")); - buttonGroup.add(myJspImportCommaSeparated); - buttonGroup.add(myJspOneImportPerDirective); - JPanel btnPanel = new JPanel(new BorderLayout()); - btnPanel.add(myJspImportCommaSeparated, BorderLayout.NORTH); - btnPanel.add(myJspOneImportPerDirective, BorderLayout.CENTER); - - //noinspection HardCodedStringLiteral - final MultiLineLabel commaSeparatedLabel = new MultiLineLabel("<% page import=\"com.company.Boo, \n" + - " com.company.Far\"%>"); - //noinspection HardCodedStringLiteral - final MultiLineLabel oneImportPerDirectiveLabel = new MultiLineLabel("<% page import=\"com.company.Boo\"%>\n" + - "<% page import=\"com.company.Far\"%>"); - final JPanel labelPanel = new JPanel(new BorderLayout()); - labelPanel.setBorder( - BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(20, 10, 0, 0), IdeBorderFactory.createTitledBorder( - ApplicationBundle.message("title.preview"), false))); - - JPanel resultPanel = new JPanel(new BorderLayout()); - resultPanel.add(btnPanel, BorderLayout.NORTH); - resultPanel.add(labelPanel, BorderLayout.CENTER); - resultPanel.setBorder(IdeBorderFactory.createTitledBorder(ApplicationBundle.message("title.jsp.imports.layout"), true)); - - - ActionListener actionListener = new ActionListener() { - public void actionPerformed(ActionEvent e) { - boolean isComma = myJspImportCommaSeparated.isSelected(); - labelPanel.removeAll(); - labelPanel.add(isComma ? commaSeparatedLabel : oneImportPerDirectiveLabel, BorderLayout.NORTH); - labelPanel.repaint(); - labelPanel.revalidate(); - } - }; - myJspImportCommaSeparated.addActionListener(actionListener); - myJspOneImportPerDirective.addActionListener(actionListener); - return resultPanel; - } - private JPanel createGeneralOptionsPanel() { OptionGroup group = new OptionGroup(ApplicationBundle.message("title.general")); myCbUseSingleClassImports = new JCheckBox(ApplicationBundle.message("checkbox.use.single.class.import")); @@ -139,13 +94,13 @@ public class CodeStyleImportsPanel extends JPanel { new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 3, 0, 0), 0, 0)); panel.add(myClassCountField, - new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, + new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 1, 0, 0), 0, 0)); panel.add(new JLabel(ApplicationBundle.message("editbox.names.count.to.use.static.import.with.star")), new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 3, 0, 0), 0, 0)); panel.add(myNamesCountField, - new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, + new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 1, 0, 0), 0, 0)); group.add(panel); @@ -185,13 +140,6 @@ public class CodeStyleImportsPanel extends JPanel { if (myPackageTable.getRowCount() > 0) { myPackageTable.getSelectionModel().setSelectionInterval(0, 0); } - - if (settings.JSP_PREFER_COMMA_SEPARATED_IMPORT_LIST) { - myJspImportCommaSeparated.doClick(); - } - else { - myJspOneImportPerDirective.doClick(); - } } public void reset() { @@ -225,8 +173,6 @@ public class CodeStyleImportsPanel extends JPanel { myPackageList.removeEmptyPackages(); settings.PACKAGES_TO_USE_IMPORT_ON_DEMAND.copyFrom(myPackageList); - settings.JSP_PREFER_COMMA_SEPARATED_IMPORT_LIST = myJspImportCommaSeparated.isSelected(); - myFqnInJavadocOption.apply(settings); } @@ -250,7 +196,6 @@ public class CodeStyleImportsPanel extends JPanel { isModified |= isModified(myImportLayoutPanel.getImportLayoutList(), settings.IMPORT_LAYOUT_TABLE); isModified |= isModified(myPackageList, settings.PACKAGES_TO_USE_IMPORT_ON_DEMAND); - isModified |= settings.JSP_PREFER_COMMA_SEPARATED_IMPORT_LIST != myJspImportCommaSeparated.isSelected(); return isModified; } From 5d94f4fdb974e34760f12af2a6daaa1e950e0e6d Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Tue, 20 Jan 2015 12:14:51 +0300 Subject: [PATCH 12/47] Fully Qualify Names in Javadoc option now is represented by combo, instead of three radios --- ...QualifiedNamesInJavadocOptionProvider.java | 114 ++++++++++-------- .../src/messages/ApplicationBundle.properties | 2 +- 2 files changed, 67 insertions(+), 49 deletions(-) diff --git a/java/java-impl/src/com/intellij/application/options/FullyQualifiedNamesInJavadocOptionProvider.java b/java/java-impl/src/com/intellij/application/options/FullyQualifiedNamesInJavadocOptionProvider.java index 3bd00bfb3110..fd66d06561a8 100644 --- a/java/java-impl/src/com/intellij/application/options/FullyQualifiedNamesInJavadocOptionProvider.java +++ b/java/java-impl/src/com/intellij/application/options/FullyQualifiedNamesInJavadocOptionProvider.java @@ -16,64 +16,49 @@ package com.intellij.application.options; import com.intellij.openapi.application.ApplicationBundle; +import com.intellij.openapi.ui.ComboBox; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.JavaCodeStyleSettings; +import com.intellij.ui.ListCellRendererWrapper; import org.jetbrains.annotations.NotNull; import javax.swing.*; +import java.awt.*; + import static com.intellij.psi.codeStyle.JavaCodeStyleSettings.FULLY_QUALIFY_NAMES_ALWAYS; import static com.intellij.psi.codeStyle.JavaCodeStyleSettings.FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED; import static com.intellij.psi.codeStyle.JavaCodeStyleSettings.SHORTEN_NAMES_ALWAYS_AND_ADD_IMPORT; public class FullyQualifiedNamesInJavadocOptionProvider { - - private JRadioButton myFullyQualifyNamesAlways; - private JRadioButton myShortenNamesAlways; - private JRadioButton myFullyQualifyIfNotImported; - + private JPanel myPanel; + private ComboBox myComboBox; public FullyQualifiedNamesInJavadocOptionProvider(@NotNull CodeStyleSettings settings) { composePanel(); reset(settings); } - + public void reset(@NotNull CodeStyleSettings settings) { JavaCodeStyleSettings javaSettings = settings.getCustomSettings(JavaCodeStyleSettings.class); - int classNamesInJavadoc = javaSettings.CLASS_NAMES_IN_JAVADOC; - - if (classNamesInJavadoc == FULLY_QUALIFY_NAMES_ALWAYS) { - myFullyQualifyNamesAlways.setSelected(true); - } - else if (classNamesInJavadoc == SHORTEN_NAMES_ALWAYS_AND_ADD_IMPORT) { - myShortenNamesAlways.setSelected(true); - } - else { - myFullyQualifyIfNotImported.setSelected(true); - } + QualifyJavadocOptions option = QualifyJavadocOptions.fromIntValue(javaSettings.CLASS_NAMES_IN_JAVADOC); + myComboBox.setSelectedItem(option); } public void apply(@NotNull CodeStyleSettings settings) { JavaCodeStyleSettings javaSettings = settings.getCustomSettings(JavaCodeStyleSettings.class); - javaSettings.CLASS_NAMES_IN_JAVADOC = getIntValueFromSelectedRadioButton(); + javaSettings.CLASS_NAMES_IN_JAVADOC = getSelectedIntOptionValue(); } public boolean isModified(CodeStyleSettings settings) { JavaCodeStyleSettings javaSettings = settings.getCustomSettings(JavaCodeStyleSettings.class); - return javaSettings.CLASS_NAMES_IN_JAVADOC != getIntValueFromSelectedRadioButton(); + return javaSettings.CLASS_NAMES_IN_JAVADOC != getSelectedIntOptionValue(); } - private int getIntValueFromSelectedRadioButton() { - if (myFullyQualifyNamesAlways.isSelected()) { - return FULLY_QUALIFY_NAMES_ALWAYS; - } - else if (myShortenNamesAlways.isSelected()) { - return SHORTEN_NAMES_ALWAYS_AND_ADD_IMPORT; - } - else { - return FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED; - } + private int getSelectedIntOptionValue() { + QualifyJavadocOptions item = (QualifyJavadocOptions)myComboBox.getSelectedItem(); + return item.getIntOptionValue(); } @NotNull @@ -82,30 +67,63 @@ public class FullyQualifiedNamesInJavadocOptionProvider { } private void composePanel() { - myPanel = new JPanel(); - BoxLayout boxLayout = new BoxLayout(myPanel, BoxLayout.Y_AXIS); - myPanel.setLayout(boxLayout); + myPanel = new JPanel(new GridBagLayout()); + + myComboBox = new ComboBox(); + for (QualifyJavadocOptions options : QualifyJavadocOptions.values()) { + myComboBox.addItem(options); + } + myComboBox.setRenderer(new ListCellRendererWrapper() { + @Override + public void customize(final JList list, final Object value, final int index, final boolean selected, final boolean hasFocus) { + if (value instanceof QualifyJavadocOptions) { + setText(((QualifyJavadocOptions)value).getPresentableText()); + } + } + }); JLabel title = new JLabel(ApplicationBundle.message("radio.use.fully.qualified.class.names.in.javadoc")); - title.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0)); - - myFullyQualifyNamesAlways = new JRadioButton(ApplicationBundle.message("radio.use.fully.qualified.class.names.in.javadoc.always")); - myFullyQualifyNamesAlways.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 0)); + myPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); - myShortenNamesAlways = new JRadioButton(ApplicationBundle.message("radio.use.fully.qualified.class.names.in.javadoc.never")); - myShortenNamesAlways.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 0)); + GridBagConstraints left = new GridBagConstraints(); + left.anchor = GridBagConstraints.WEST; - myFullyQualifyIfNotImported = new JRadioButton(ApplicationBundle.message("radio.use.fully.qualified.class.names.in.javadoc.if.not.imported")); - myFullyQualifyIfNotImported.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 0)); + GridBagConstraints right = new GridBagConstraints(); + right.anchor = GridBagConstraints.WEST; + right.weightx = 1.0; + right.insets = new Insets(0, 5, 0, 0); - ButtonGroup group = new ButtonGroup(); - group.add(myFullyQualifyNamesAlways); - group.add(myShortenNamesAlways); - group.add(myFullyQualifyIfNotImported); + myPanel.add(title, left); + myPanel.add(myComboBox, right); + } +} - myPanel.add(title); - myPanel.add(myFullyQualifyNamesAlways); - myPanel.add(myFullyQualifyIfNotImported); - myPanel.add(myShortenNamesAlways); +enum QualifyJavadocOptions { + + FQ_ALWAYS(FULLY_QUALIFY_NAMES_ALWAYS, ApplicationBundle.message("radio.use.fully.qualified.class.names.in.javadoc.always")), + SHORTEN_ALWAYS(SHORTEN_NAMES_ALWAYS_AND_ADD_IMPORT, ApplicationBundle.message("radio.use.fully.qualified.class.names.in.javadoc.never")), + FQ_WHEN_NOT_IMPORTED(FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED, ApplicationBundle.message("radio.use.fully.qualified.class.names.in.javadoc.if.not.imported")); + + private final String myText; + private final int myOption; + + public String getPresentableText() { + return myText; + } + + public int getIntOptionValue() { + return myOption; + } + + public static QualifyJavadocOptions fromIntValue(int value) { + for (QualifyJavadocOptions option : values()) { + if (option.myOption == value) return option; + } + return FQ_WHEN_NOT_IMPORTED; + } + + QualifyJavadocOptions(int option, String text) { + myOption = option; + myText = text; } } \ No newline at end of file diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index 2212fb98e3f6..adc5d40cd4f6 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -116,7 +116,7 @@ checkbox.use.fully.qualified.class.names.in.javadoc=Use fully qualified class na radio.use.fully.qualified.class.names.in.javadoc=Use fully qualified class names in JavaDoc: radio.use.fully.qualified.class.names.in.javadoc.always=Always radio.use.fully.qualified.class.names.in.javadoc.if.not.imported=If not already imported -radio.use.fully.qualified.class.names.in.javadoc.never=Never: use short name and add import +radio.use.fully.qualified.class.names.in.javadoc.never=Never, use short name and add import editbox.class.count.to.use.import.with.star=Class count to use import with '*': editbox.names.count.to.use.static.import.with.star=Names count to use static import with '*': title.packages.to.use.import.with=Packages to Use Import with '*' From 0bec748d2fb6cd709858226d42e4a59cb2c23cd4 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 20 Jan 2015 12:59:51 +0300 Subject: [PATCH 13/47] EA-63783 - NPE: XDebugSessionImpl.updateExecutionPosition --- .../src/com/intellij/xdebugger/impl/XDebugSessionImpl.java | 4 ++-- .../src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java index e69aea064c9d..395fde044bd7 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -564,7 +564,7 @@ public class XDebugSessionImpl implements XDebugSession { @Override public void updateExecutionPosition() { boolean isTopFrame = isTopFrameSelected(); - myDebuggerManager.updateExecutionPoint(myCurrentStackFrame.getSourcePosition(), !isTopFrame, getPositionIconRenderer(isTopFrame)); + myDebuggerManager.updateExecutionPoint(getCurrentPosition(), !isTopFrame, getPositionIconRenderer(isTopFrame)); } public boolean isTopFrameSelected() { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java index 6865672332e4..c7665fa18b96 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -278,7 +278,7 @@ public class XDebuggerManagerImpl extends XDebuggerManager } } - public void updateExecutionPoint(XSourcePosition position, boolean useSelection, @Nullable GutterIconRenderer gutterIconRenderer) { + public void updateExecutionPoint(@Nullable XSourcePosition position, boolean useSelection, @Nullable GutterIconRenderer gutterIconRenderer) { if (position != null) { myExecutionPointHighlighter.show(position, useSelection, gutterIconRenderer); } From 64894391eaa7153900375eefe40d791e32bc0553 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 19 Jan 2015 20:44:34 +0100 Subject: [PATCH 14/47] switch context when get to anonymous class so access to the inherited members should not be raised as a conflict --- .../util/RefactoringConflictsUtil.java | 23 ++++++++++++++----- .../after/a/A.java | 9 ++++++++ .../after/b/B.java | 14 +++++++++++ .../before/a/A.java | 17 ++++++++++++++ .../before/b/B.java | 3 +++ .../refactoring/PullUpMultifileTest.java | 4 ++++ 6 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/after/a/A.java create mode 100644 java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/after/b/B.java create mode 100644 java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/before/a/A.java create mode 100644 java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/before/b/B.java diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java index aece13de0764..bc0148ff44f4 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java @@ -134,11 +134,22 @@ public class RefactoringConflictsUtil { } } + public static void checkUsedElements(PsiMember member, + PsiElement scope, + @NotNull Set membersToMove, + @Nullable Set abstractMethods, + @Nullable PsiClass targetClass, + @NotNull PsiElement context, + MultiMap conflicts) { + checkUsedElements(member, scope, membersToMove, abstractMethods, targetClass, null, context, conflicts); + } + public static void checkUsedElements(PsiMember member, PsiElement scope, @NotNull Set membersToMove, @Nullable Set abstractMethods, @Nullable PsiClass targetClass, + PsiClass accessClass, @NotNull PsiElement context, MultiMap conflicts) { final Set moving = new HashSet(membersToMove); @@ -150,10 +161,10 @@ public class RefactoringConflictsUtil { PsiElement refElement = refExpr.resolve(); if (refElement instanceof PsiMember) { PsiExpression qualifier = refExpr.getQualifierExpression(); - PsiClass accessClass = (PsiClass)(qualifier != null ? PsiUtil.getAccessObjectClass(qualifier).getElement() : null); + PsiClass qualifierAccessClass = (PsiClass)(qualifier != null ? PsiUtil.getAccessObjectClass(qualifier).getElement() : accessClass); if (!RefactoringHierarchyUtil.willBeInTargetClass(refElement, moving, targetClass, false) && - (accessClass == null || !RefactoringHierarchyUtil.willBeInTargetClass(accessClass, moving, targetClass, false))) { - checkAccessibility((PsiMember)refElement, context, accessClass, member, conflicts); + (qualifierAccessClass == null || !RefactoringHierarchyUtil.willBeInTargetClass(qualifierAccessClass, moving, targetClass, false))) { + checkAccessibility((PsiMember)refElement, context, qualifierAccessClass, member, conflicts); } } } @@ -169,7 +180,7 @@ public class RefactoringConflictsUtil { final PsiMethod refElement = newExpression.resolveConstructor(); if (refElement != null) { if (!RefactoringHierarchyUtil.willBeInTargetClass(refElement, moving, targetClass, false)) { - checkAccessibility(refElement, context, null, member, conflicts); + checkAccessibility(refElement, context, accessClass, member, conflicts); } } } @@ -179,14 +190,14 @@ public class RefactoringConflictsUtil { PsiElement refElement = refExpr.resolve(); if (refElement instanceof PsiMember) { if (!RefactoringHierarchyUtil.willBeInTargetClass(refElement, moving, targetClass, false)) { - checkAccessibility((PsiMember)refElement, context, null, member, conflicts); + checkAccessibility((PsiMember)refElement, context, accessClass, member, conflicts); } } } for (PsiElement child : scope.getChildren()) { if (child instanceof PsiWhiteSpace || child instanceof PsiComment) continue; - checkUsedElements(member, child, membersToMove, abstractMethods, targetClass, context, conflicts); + checkUsedElements(member, child, membersToMove, abstractMethods, targetClass, child instanceof PsiClass ? (PsiClass)child : accessClass, context, conflicts); } } diff --git a/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/after/a/A.java b/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/after/a/A.java new file mode 100644 index 000000000000..34dee12da94d --- /dev/null +++ b/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/after/a/A.java @@ -0,0 +1,9 @@ +package a; +import b.B; +public class A extends B { + + protected static void bar(){} + public static class I { + protected void foo(){} + } +} diff --git a/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/after/b/B.java b/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/after/b/B.java new file mode 100644 index 000000000000..bf1f35b90535 --- /dev/null +++ b/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/after/b/B.java @@ -0,0 +1,14 @@ +package b; + +import a.A; + +public class B { + void method2Move() { + new A.I() { + { + foo(); + A.bar(); + } + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/before/a/A.java b/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/before/a/A.java new file mode 100644 index 000000000000..efa03290b9da --- /dev/null +++ b/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/before/a/A.java @@ -0,0 +1,17 @@ +package a; +import b.B; +public class A extends B { + void method2Move() { + new I() { + { + foo(); + bar(); + } + } + } + + protected static void bar(){} + public static class I { + protected void foo(){} + } +} diff --git a/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/before/b/B.java b/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/before/b/B.java new file mode 100644 index 000000000000..64950f347e93 --- /dev/null +++ b/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/before/b/B.java @@ -0,0 +1,3 @@ +package b; +public class B { +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/PullUpMultifileTest.java b/java/java-tests/testSrc/com/intellij/refactoring/PullUpMultifileTest.java index a1df6dba3b81..195f91ad62a5 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/PullUpMultifileTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/PullUpMultifileTest.java @@ -100,6 +100,10 @@ public class PullUpMultifileTest extends MultiFileTestCase { "Method method2Move() uses method A.foo(), which is not moved to the superclass"); } + public void testAccessibleViaInheritanceInsideAnonymousClass() throws Exception { + doTest("Method method2Move() uses method A.bar(), which is not accessible from the superclass"); + } + public void testReuseSuperMethod() throws Exception { doTest(); } From ede7cd1364bbce4c19941d4637c75ac36e16385c Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 16 Jan 2015 15:05:25 +0300 Subject: [PATCH 15/47] cleanup: bitutil --- .../reference/RefFieldImpl.java | 11 ++-- .../reference/RefJavaElementImpl.java | 9 +-- .../reference/RefMethodImpl.java | 8 +-- .../daemon/impl/HighlightInfo.java | 56 +++++++++--------- .../reference/RefEntityImpl.java | 16 ++--- .../openapi/editor/impl/IntervalTreeImpl.java | 6 +- .../openapi/editor/impl/RangeMarkerTree.java | 6 +- .../openapi/editor/impl/RedBlackTree.java | 28 ++++----- .../com/intellij/formatting/WhiteSpace.java | 57 ++++++++---------- .../openapi/wm/impl/ProjectWindowAction.java | 6 +- .../openapi/wm/impl/ToolWindowHeader.java | 5 +- .../src/com/intellij/usages/impl/Node.java | 59 +++++++++---------- .../util/src/com/intellij/util/BitUtil.java | 12 +++- .../com/intellij/util/io/IntToIntBtree.java | 7 ++- .../evaluate/XDebuggerEvaluationDialog.java | 4 +- .../breadcrumbs/BreadcrumbsXmlWrapper.java | 5 +- 16 files changed, 147 insertions(+), 148 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java index b7751409f6e4..d2de19b5aac5 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ package com.intellij.codeInspection.reference; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.Key; import com.intellij.psi.*; import com.intellij.psi.util.ClassUtil; import com.intellij.psi.util.PsiFormatUtil; @@ -33,7 +32,7 @@ import org.jetbrains.annotations.Nullable; public class RefFieldImpl extends RefJavaElementImpl implements RefField { private static final int USED_FOR_READING_MASK = 0x10000; private static final int USED_FOR_WRITING_MASK = 0x20000; - private static final int ASSIGNED_ONLY_IN_INITIALIZER = 0x40000; + private static final int ASSIGNED_ONLY_IN_INITIALIZER_MASK = 0x40000; RefFieldImpl(@NotNull RefClass ownerClass, PsiField field, RefManager manager) { super(field, manager); @@ -94,13 +93,13 @@ public class RefFieldImpl extends RefJavaElementImpl implements RefField { } private void setUsedForWriting(boolean usedForWriting) { - setFlag(false, ASSIGNED_ONLY_IN_INITIALIZER); + setFlag(false, ASSIGNED_ONLY_IN_INITIALIZER_MASK); setFlag(usedForWriting, USED_FOR_WRITING_MASK); } @Override public boolean isOnlyAssignedInInitializer() { - return checkFlag(ASSIGNED_ONLY_IN_INITIALIZER); + return checkFlag(ASSIGNED_ONLY_IN_INITIALIZER_MASK); } @Override @@ -130,7 +129,7 @@ public class RefFieldImpl extends RefJavaElementImpl implements RefField { if (psiField.getInitializer() != null || psiField instanceof PsiEnumConstant) { if (!checkFlag(USED_FOR_WRITING_MASK)) { - setFlag(true, ASSIGNED_ONLY_IN_INITIALIZER); + setFlag(true, ASSIGNED_ONLY_IN_INITIALIZER_MASK); setFlag(true, USED_FOR_WRITING_MASK); } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaElementImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaElementImpl.java index 7607c033bb70..12f42b7b3f23 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaElementImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaElementImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,10 +41,11 @@ public abstract class RefJavaElementImpl extends RefElementImpl implements RefJa private static final int ACCESS_PROTECTED = 0x01; private static final int ACCESS_PACKAGE = 0x02; private static final int ACCESS_PUBLIC = 0x03; + private static final int IS_STATIC_MASK = 0x04; private static final int IS_FINAL_MASK = 0x08; private static final int IS_USES_DEPRECATION_MASK = 0x200; - private static final int IS_SYNTHETIC_JSP_ELEMENT = 0x400; + private static final int IS_SYNTHETIC_JSP_ELEMENT_MASK = 0x400; protected RefJavaElementImpl(String name, @NotNull RefJavaElement owner) { super(name, owner); @@ -148,11 +149,11 @@ public abstract class RefJavaElementImpl extends RefElementImpl implements RefJa @Override public boolean isSyntheticJSP() { - return checkFlag(IS_SYNTHETIC_JSP_ELEMENT); + return checkFlag(IS_SYNTHETIC_JSP_ELEMENT_MASK); } public void setSyntheticJSP(boolean b) { - setFlag(b, IS_SYNTHETIC_JSP_ELEMENT); + setFlag(b, IS_SYNTHETIC_JSP_ELEMENT_MASK); } @Override diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java index 941de66f8519..6845c42fd95f 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,7 +46,7 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod { private static final int IS_RETURN_VALUE_USED_MASK = 0x400000; private static final int IS_TEST_METHOD_MASK = 0x4000000; - private static final int IS_CALLED_ON_SUBCLASS = 0x8000000; + private static final int IS_CALLED_ON_SUBCLASS_MASK = 0x8000000; private static final String RETURN_VALUE_UNDEFINED = "#"; @@ -701,11 +701,11 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod { @Override public boolean isCalledOnSubClass() { - return checkFlag(IS_CALLED_ON_SUBCLASS); + return checkFlag(IS_CALLED_ON_SUBCLASS_MASK); } public void setCalledOnSubClass(boolean isCalledOnSubClass){ - setFlag(isCalledOnSubClass, IS_CALLED_ON_SUBCLASS); + setFlag(isCalledOnSubClass, IS_CALLED_ON_SUBCLASS_MASK); } } diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java index f3f087a880ff..49ca573251e1 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,6 +41,7 @@ import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.ArrayUtilRt; +import com.intellij.util.BitUtil; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.xml.util.XmlStringUtil; @@ -90,12 +91,12 @@ public class HighlightInfo implements Segment { private final ProblemGroup myProblemGroup; private volatile byte myFlags; // bit packed flags below: - private static final int BIJECTIVE_FLAG = 0; - private static final int HAS_HINT_FLAG = 1; - private static final int FROM_INJECTION_FLAG = 2; - private static final int AFTER_END_OF_LINE_FLAG = 3; - private static final int FILE_LEVEL_ANNOTATION_FLAG = 4; - private static final int NEEDS_UPDATE_ON_TYPING_FLAG = 5; + private static final byte BIJECTIVE_MASK = 1; + private static final byte HAS_HINT_MASK = 2; + private static final byte FROM_INJECTION_MASK = 4; + private static final byte AFTER_END_OF_LINE_MASK = 8; + private static final byte FILE_LEVEL_ANNOTATION_MASK = 16; + private static final byte NEEDS_UPDATE_ON_TYPING_MASK = 32; PsiElement psiElement; @NotNull @@ -104,7 +105,7 @@ public class HighlightInfo implements Segment { } void setFromInjection(boolean fromInjection) { - setFlag(FROM_INJECTION_FLAG, fromInjection); + setFlag(FROM_INJECTION_MASK, fromInjection); } public String getToolTip() { @@ -132,31 +133,28 @@ public class HighlightInfo implements Segment { return description; } - @MagicConstant(intValues = {BIJECTIVE_FLAG, HAS_HINT_FLAG, FROM_INJECTION_FLAG, AFTER_END_OF_LINE_FLAG, FILE_LEVEL_ANNOTATION_FLAG, NEEDS_UPDATE_ON_TYPING_FLAG}) - @interface FlagConstant {} + @MagicConstant(intValues = {BIJECTIVE_MASK, HAS_HINT_MASK, FROM_INJECTION_MASK, AFTER_END_OF_LINE_MASK, FILE_LEVEL_ANNOTATION_MASK, + NEEDS_UPDATE_ON_TYPING_MASK}) + private @interface FlagConstant {} - private boolean isFlagSet(@FlagConstant int flag) { - assert flag < 8; - int state = myFlags >> flag; - return (state & 1) != 0; + private boolean isFlagSet(@FlagConstant byte mask) { + return BitUtil.isSet(myFlags, mask); } - private void setFlag(@FlagConstant int flag, boolean value) { - assert flag < 8; - int state = value ? 1 : 0; - myFlags = (byte)(myFlags & ~(1 << flag) | state << flag); + private void setFlag(@FlagConstant byte mask, boolean value) { + myFlags = BitUtil.set(myFlags, mask, value); } boolean isFileLevelAnnotation() { - return isFlagSet(FILE_LEVEL_ANNOTATION_FLAG); + return isFlagSet(FILE_LEVEL_ANNOTATION_MASK); } boolean isBijective() { - return isFlagSet(BIJECTIVE_FLAG); + return isFlagSet(BIJECTIVE_MASK); } void setBijective(boolean bijective) { - setFlag(BIJECTIVE_FLAG, bijective); + setFlag(BIJECTIVE_MASK, bijective); } @NotNull @@ -165,7 +163,7 @@ public class HighlightInfo implements Segment { } public boolean isAfterEndOfLine() { - return isFlagSet(AFTER_END_OF_LINE_FLAG); + return isFlagSet(AFTER_END_OF_LINE_MASK); } @Nullable @@ -253,7 +251,7 @@ public class HighlightInfo implements Segment { private static final HighlightInfoFilter[] FILTERS = HighlightInfoFilter.EXTENSION_POINT_NAME.getExtensions(); public boolean needUpdateOnTyping() { - return isFlagSet(NEEDS_UPDATE_ON_TYPING_FLAG); + return isFlagSet(NEEDS_UPDATE_ON_TYPING_MASK); } HighlightInfo(@Nullable TextAttributes forcedTextAttributes, @@ -284,9 +282,9 @@ public class HighlightInfo implements Segment { // optimisation: do not retain extra memory if can recompute toolTip = encodeTooltip(escapedToolTip, escapedDescription); this.severity = severity; - setFlag(AFTER_END_OF_LINE_FLAG, afterEndOfLine); - setFlag(NEEDS_UPDATE_ON_TYPING_FLAG, calcNeedUpdateOnTyping(needsUpdateOnTyping, type)); - setFlag(FILE_LEVEL_ANNOTATION_FLAG, isFileLevelAnnotation); + setFlag(AFTER_END_OF_LINE_MASK, afterEndOfLine); + setFlag(NEEDS_UPDATE_ON_TYPING_MASK, calcNeedUpdateOnTyping(needsUpdateOnTyping, type)); + setFlag(FILE_LEVEL_ANNOTATION_MASK, isFileLevelAnnotation); this.navigationShift = navigationShift; myProblemGroup = problemGroup; this.gutterIconRenderer = gutterIconRenderer; @@ -701,11 +699,11 @@ public class HighlightInfo implements Segment { public boolean hasHint() { - return isFlagSet(HAS_HINT_FLAG); + return isFlagSet(HAS_HINT_MASK); } void setHint(final boolean hasHint) { - setFlag(HAS_HINT_FLAG, hasHint); + setFlag(HAS_HINT_MASK, hasHint); } public int getActualStartOffset() { @@ -879,7 +877,7 @@ public class HighlightInfo implements Segment { } boolean isFromInjection() { - return isFlagSet(FROM_INJECTION_FLAG); + return isFlagSet(FROM_INJECTION_MASK); } @NotNull diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefEntityImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefEntityImpl.java index 6b0bb66018fc..5ad5b1d33cf2 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefEntityImpl.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefEntityImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ package com.intellij.codeInspection.reference; import com.intellij.codeInspection.InspectionsBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.Key; +import com.intellij.util.BitUtil; import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,7 +42,7 @@ public abstract class RefEntityImpl implements RefEntity { protected List myChildren; private final String myName; private Map myUserMap; - protected int myFlags = 0; + protected int myFlags; protected final RefManagerImpl myManager; protected RefEntityImpl(String name, @NotNull RefManager manager) { @@ -138,16 +139,11 @@ public abstract class RefEntityImpl implements RefEntity { } public boolean checkFlag(int mask) { - return (myFlags & mask) != 0; + return BitUtil.isSet(myFlags, mask); } - public void setFlag(boolean b, int mask) { - if (b) { - myFlags |= mask; - } - else { - myFlags &= ~mask; - } + public void setFlag(final boolean value, final int mask) { + myFlags = BitUtil.set(myFlags, mask, value); } @Override diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java index b07f0b373c29..ed1c71dd095f 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,7 +51,7 @@ abstract class IntervalTreeImpl extends RedBlackTree< static class IntervalNode extends RedBlackTree.Node implements MutableInterval { private volatile int myStart; private volatile int myEnd; - private static final int ATTACHED_TO_TREE_FLAG = COLOR_FLAG+1; // true if the node is inserted to the tree + private static final byte ATTACHED_TO_TREE_FLAG = COLOR_MASK <<1; // true if the node is inserted to the tree protected final List> intervals; int maxEnd; // max of all intervalEnd()s among all children. protected int delta; // delta of startOffset. getStartOffset() = myStartOffset + Sum of deltas up to root @@ -268,7 +268,7 @@ abstract class IntervalTreeImpl extends RedBlackTree< return myEnd = end; } - static final int VALID_FLAG = ATTACHED_TO_TREE_FLAG + 1; + static final byte VALID_FLAG = ATTACHED_TO_TREE_FLAG << 1; @Override public boolean isValid() { return isFlagSet(VALID_FLAG); diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java index 5ce1e2c2167b..5df198263512 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -152,8 +152,8 @@ public class RangeMarkerTree extends IntervalTreeImpl extends IntervalTreeImpl.IntervalNode { - private static final int EXPAND_TO_LEFT_FLAG = VALID_FLAG+1; - private static final int EXPAND_TO_RIGHT_FLAG = EXPAND_TO_LEFT_FLAG+1; + private static final byte EXPAND_TO_LEFT_FLAG = VALID_FLAG<<1; + private static final byte EXPAND_TO_RIGHT_FLAG = EXPAND_TO_LEFT_FLAG<<1; public RMNode(@NotNull RangeMarkerTree rangeMarkerTree, @NotNull T key, diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/RedBlackTree.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/RedBlackTree.java index 6ff5fb91bd17..41197feb5e74 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/RedBlackTree.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/RedBlackTree.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package com.intellij.openapi.editor.impl; +import com.intellij.util.BitUtil; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -299,17 +300,14 @@ public abstract class RedBlackTree { protected Node parent = null; private volatile byte myFlags; - protected static final int COLOR_FLAG = 0; + protected static final byte COLOR_MASK = 1; - protected boolean isFlagSet(int flag) { - int state = myFlags >> flag; - return (state & 1) != 0; + protected boolean isFlagSet(byte mask) { + return BitUtil.isSet(myFlags, mask); } - protected void setFlag(int flag, boolean value) { - assert flag < 8; - int state = value ? 1 : 0; - myFlags = (byte)(myFlags & ~(1 << flag) | state << flag); + protected void setFlag(byte mask, boolean value) { + myFlags = BitUtil.set(myFlags, mask, value); } @@ -325,7 +323,7 @@ public abstract class RedBlackTree { return this == parent.getLeft() ? parent.getRight() : parent.getLeft(); } - public Node uncle() { + private Node uncle() { assert getParent() != null; // Root node has no uncle assert getParent().getParent() != null; // Children of root have no uncle return getParent().sibling(); @@ -360,16 +358,16 @@ public abstract class RedBlackTree { public abstract boolean hasAliveKey(boolean purgeDead); public boolean isBlack() { - return isFlagSet(COLOR_FLAG); + return isFlagSet(COLOR_MASK); } - public void setBlack() { - setFlag(COLOR_FLAG, true); + private void setBlack() { + setFlag(COLOR_MASK, true); } public void setRed() { - setFlag(COLOR_FLAG, false); + setFlag(COLOR_MASK, false); } public void setColor(boolean isBlack) { - setFlag(COLOR_FLAG, isBlack); + setFlag(COLOR_MASK, isBlack); } } diff --git a/platform/lang-impl/src/com/intellij/formatting/WhiteSpace.java b/platform/lang-impl/src/com/intellij/formatting/WhiteSpace.java index 1df92e2803bb..63692a899925 100644 --- a/platform/lang-impl/src/com/intellij/formatting/WhiteSpace.java +++ b/platform/lang-impl/src/com/intellij/formatting/WhiteSpace.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.formatter.FormattingDocumentModelImpl; +import com.intellij.util.BitUtil; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NotNull; @@ -61,13 +62,14 @@ class WhiteSpace { private boolean myForceSkipTabulationsUsage; private boolean myIsBeforeCodeBlockEnd; - private static final byte FIRST = 1; - private static final byte SAFE = 0x2; - private static final byte KEEP_FIRST_COLUMN = 0x4; - private static final byte LINE_FEEDS_ARE_READ_ONLY = 0x8; - private static final byte READ_ONLY = 0x10; - private static final byte CONTAINS_LF_INITIALLY = 0x20; - private static final byte CONTAINS_SPACES_INITIALLY = 0x40; + private static final byte FIRST_MASK = 1; + private static final byte SAFE_MASK = 0x2; + private static final byte KEEP_FIRST_COLUMN_MASK = 0x4; + private static final byte LINE_FEEDS_ARE_READ_ONLY_MASK = 0x8; + private static final byte READ_ONLY_MASK = 0x10; + private static final byte CONTAINS_LF_INITIALLY_MASK = 0x20; + private static final byte CONTAINS_SPACES_INITIALLY_MASK = 0x40; + private static final int LF_COUNT_SHIFT = 7; private static final int MAX_LF_COUNT = 1 << 24; @@ -139,12 +141,10 @@ class WhiteSpace { myInitialLastLinesSpaces = indent.whiteSpaces; myInitialLastLinesTabs = indent.tabs; - if (getLineFeeds() > 0) myFlags |= CONTAINS_LF_INITIALLY; - else myFlags &= ~CONTAINS_LF_INITIALLY; + setFlag(CONTAINS_LF_INITIALLY_MASK, getLineFeeds() > 0); final int totalSpaces = getTotalSpaces(); - if (totalSpaces > 0) myFlags |= CONTAINS_SPACES_INITIALLY; - else myFlags &=~ CONTAINS_SPACES_INITIALLY; + setFlag(CONTAINS_SPACES_INITIALLY_MASK, totalSpaces > 0); } /** @@ -295,7 +295,7 @@ class WhiteSpace { performModification(new Runnable() { @Override public void run() { - if (!isKeepFirstColumn() || (myFlags & CONTAINS_SPACES_INITIALLY) != 0) { + if (!isKeepFirstColumn() || getFlag(CONTAINS_SPACES_INITIALLY_MASK)) { mySpaces = spaces; myIndentSpaces = indent; } @@ -508,20 +508,15 @@ class WhiteSpace { } public void setIsSafe(final boolean value) { - setFlag(SAFE, value); + setFlag(SAFE_MASK, value); } private void setFlag(final int mask, final boolean value) { - if (value) { - myFlags |= mask; - } - else { - myFlags &= ~mask; - } + myFlags = BitUtil.set(myFlags, mask, value); } private boolean getFlag(final int mask) { - return (myFlags & mask) != 0; + return BitUtil.isSet(myFlags, mask); } private boolean isFirst() { @@ -537,7 +532,7 @@ class WhiteSpace { */ public boolean containsLineFeedsInitially() { if (myInitial == null) return false; - return (myFlags & CONTAINS_LF_INITIALLY) != 0; + return getFlag(CONTAINS_LF_INITIALLY_MASK); } /** @@ -588,7 +583,7 @@ class WhiteSpace { } public void setKeepFirstColumn(final boolean b) { - setFlag(KEEP_FIRST_COLUMN, b); + setFlag(KEEP_FIRST_COLUMN_MASK, b); } public void setLineFeedsAreReadOnly() { @@ -600,35 +595,35 @@ class WhiteSpace { } public boolean isIsFirstWhiteSpace() { - return getFlag(FIRST); + return getFlag(FIRST_MASK); } public boolean isIsSafe() { - return getFlag(SAFE); + return getFlag(SAFE_MASK); } public boolean isKeepFirstColumn() { - return getFlag(KEEP_FIRST_COLUMN); + return getFlag(KEEP_FIRST_COLUMN_MASK); } public boolean isLineFeedsAreReadOnly() { - return getFlag(LINE_FEEDS_ARE_READ_ONLY); + return getFlag(LINE_FEEDS_ARE_READ_ONLY_MASK); } public void setLineFeedsAreReadOnly(final boolean lineFeedsAreReadOnly) { - setFlag(LINE_FEEDS_ARE_READ_ONLY, lineFeedsAreReadOnly); + setFlag(LINE_FEEDS_ARE_READ_ONLY_MASK, lineFeedsAreReadOnly); } public boolean isIsReadOnly() { - return getFlag(READ_ONLY); + return getFlag(READ_ONLY_MASK); } public void setIsReadOnly(final boolean isReadOnly) { - setFlag(READ_ONLY, isReadOnly); + setFlag(READ_ONLY_MASK, isReadOnly); } public void setIsFirstWhiteSpace(final boolean isFirstWhiteSpace) { - setFlag(FIRST, isFirstWhiteSpace); + setFlag(FIRST_MASK, isFirstWhiteSpace); } public StringBuilder generateWhiteSpace(final CommonCodeStyleSettings.IndentOptions indentOptions, diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectWindowAction.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectWindowAction.java index 3383236b02e6..15045cedc05c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectWindowAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectWindowAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,12 +17,12 @@ package com.intellij.openapi.wm.impl; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.actionSystem.ToggleAction; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.wm.WindowManager; +import com.intellij.util.BitUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -121,7 +121,7 @@ public class ProjectWindowAction extends ToggleAction implements DumbAware { } final JFrame projectFrame = WindowManager.getInstance().getFrame(project); final int frameState = projectFrame.getExtendedState(); - if ((frameState & Frame.ICONIFIED) == Frame.ICONIFIED) { + if (BitUtil.isSet(frameState, Frame.ICONIFIED)) { // restore the frame if it is minimized projectFrame.setExtendedState(frameState ^ Frame.ICONIFIED); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java index e3ebfe83a4b3..8f113e5fe3fb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,7 @@ import com.intellij.ui.PopupHandler; import com.intellij.ui.UIBundle; import com.intellij.ui.components.panels.Wrapper; import com.intellij.ui.tabs.TabsUtil; +import com.intellij.util.BitUtil; import com.intellij.util.Producer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.EmptyIcon; @@ -520,7 +521,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS public void actionPerformed(final ActionEvent e) { AnAction action = - myAlternativeAction != null && (e.getModifiers() & InputEvent.ALT_MASK) == InputEvent.ALT_MASK ? myAlternativeAction : myAction; + myAlternativeAction != null && BitUtil.isSet(e.getModifiers(), InputEvent.ALT_MASK) ? myAlternativeAction : myAction; final DataContext dataContext = DataManager.getInstance().getDataContext(this); final ActionManagerEx actionManager = ActionManagerEx.getInstanceEx(); InputEvent inputEvent = e.getSource() instanceof InputEvent ? (InputEvent) e.getSource() : null; diff --git a/platform/usageView/src/com/intellij/usages/impl/Node.java b/platform/usageView/src/com/intellij/usages/impl/Node.java index 92155f851fd6..1be53e8e8b47 100644 --- a/platform/usageView/src/com/intellij/usages/impl/Node.java +++ b/platform/usageView/src/com/intellij/usages/impl/Node.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package com.intellij.usages.impl; import com.intellij.openapi.util.Comparing; import com.intellij.usages.UsageView; +import com.intellij.util.BitUtil; import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NotNull; @@ -31,23 +32,21 @@ public abstract class Node extends DefaultMutableTreeNode { private String myCachedText; private byte myCachedFlags; // bit packed flags below: - private static final int INVALID_FLAG = 0; - private static final int READ_ONLY_FLAG = 1; - private static final int READ_ONLY_COMPUTED_FLAG = 2; - private static final int EXCLUDED_FLAG = 3; - private static final int UPDATED_FLAG = 4; + private static final byte INVALID_MASK = 1; + private static final byte READ_ONLY_MASK = 2; + private static final byte READ_ONLY_COMPUTED_MASK = 4; + private static final byte EXCLUDED_MASK = 8; + private static final byte UPDATED_MASK = 16; - @MagicConstant(intValues = {INVALID_FLAG, READ_ONLY_FLAG, READ_ONLY_COMPUTED_FLAG, EXCLUDED_FLAG, UPDATED_FLAG}) - @interface FlagConstant {} + @MagicConstant(intValues = {INVALID_MASK, READ_ONLY_MASK, READ_ONLY_COMPUTED_MASK, EXCLUDED_MASK, UPDATED_MASK}) + private @interface FlagConstant {} - private boolean isFlagSet(@FlagConstant int flag) { - int state = myCachedFlags >> flag; - return (state & 1) != 0; + private boolean isFlagSet(@FlagConstant byte mask) { + return BitUtil.isSet(myCachedFlags, mask); } - private void setFlag(@FlagConstant int flag, boolean value) { - int state = value ? 1 : 0; - myCachedFlags = (byte)(myCachedFlags & ~(1 << flag) | state << flag); + private void setFlag(@FlagConstant byte mask, boolean value) { + myCachedFlags = BitUtil.set(myCachedFlags, mask, value); } protected Node(@NotNull DefaultTreeModel model) { @@ -72,25 +71,25 @@ public abstract class Node extends DefaultMutableTreeNode { protected abstract String getText(@NotNull UsageView view); public final boolean isValid() { - return !isFlagSet(INVALID_FLAG); + return !isFlagSet(INVALID_MASK); } public final boolean isReadOnly() { boolean result; - boolean computed = isFlagSet(READ_ONLY_COMPUTED_FLAG); + boolean computed = isFlagSet(READ_ONLY_COMPUTED_MASK); if (computed) { - result = isFlagSet(READ_ONLY_FLAG); + result = isFlagSet(READ_ONLY_MASK); } else { result = isDataReadOnly(); - setFlag(READ_ONLY_COMPUTED_FLAG, true); - setFlag(READ_ONLY_FLAG, result); + setFlag(READ_ONLY_COMPUTED_MASK, true); + setFlag(READ_ONLY_MASK, result); } return result; } public final boolean isExcluded() { - return isFlagSet(EXCLUDED_FLAG); + return isFlagSet(EXCLUDED_MASK); } public final void update(@NotNull UsageView view) { @@ -100,26 +99,26 @@ public abstract class Node extends DefaultMutableTreeNode { String text = getText(view); boolean cachedValid = isValid(); - boolean cachedReadOnly = isFlagSet(READ_ONLY_FLAG); - boolean cachedExcluded = isFlagSet(EXCLUDED_FLAG); + boolean cachedReadOnly = isFlagSet(READ_ONLY_MASK); + boolean cachedExcluded = isFlagSet(EXCLUDED_MASK); if (isDataValid != cachedValid || isReadOnly != cachedReadOnly || isExcluded != cachedExcluded || !Comparing.equal(myCachedText, text)) { - setFlag(INVALID_FLAG, !isDataValid); - setFlag(READ_ONLY_FLAG, isReadOnly); - setFlag(EXCLUDED_FLAG, isExcluded); + setFlag(INVALID_MASK, !isDataValid); + setFlag(READ_ONLY_MASK, isReadOnly); + setFlag(EXCLUDED_MASK, isExcluded); myCachedText = text; updateNotify(); myTreeModel.nodeChanged(this); } - setFlag(UPDATED_FLAG, true); + setFlag(UPDATED_MASK, true); } - public void markNeedUpdate() { - setFlag(UPDATED_FLAG, false); + void markNeedUpdate() { + setFlag(UPDATED_MASK, false); } - public boolean needsUpdate() { - return !isFlagSet(UPDATED_FLAG); + boolean needsUpdate() { + return !isFlagSet(UPDATED_MASK); } /** diff --git a/platform/util/src/com/intellij/util/BitUtil.java b/platform/util/src/com/intellij/util/BitUtil.java index 6afab4aafa30..788695a29951 100644 --- a/platform/util/src/com/intellij/util/BitUtil.java +++ b/platform/util/src/com/intellij/util/BitUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,15 +20,22 @@ package com.intellij.util; */ public class BitUtil { public static boolean isSet(final byte value, final byte mask) { + assertOneBitMask(mask); return (value & mask) == mask; } public static boolean isSet(final int value, final int mask) { + assertOneBitMask(mask); return (value & mask) == mask; } public static boolean isSet(long flags, long mask) { + assertOneBitMask(mask); return (flags & mask) == mask; } + private static void assertOneBitMask(long mask) { + assert (mask & (mask - 1)) == 0 : "Mask must have only one bit set, but got: " + Long.toBinaryString(mask); + } + public static boolean notSet(final int value, final int mask) { return (value & mask) != mask; } @@ -37,6 +44,7 @@ public class BitUtil { * @return {@code value} with the bit corresponding to the {@code mask} set (if setBit is true) or cleared (if setBit is false) */ public static byte set(byte value, byte mask, boolean setBit) { + assertOneBitMask(mask); return (byte)(setBit ? value | mask : value & ~mask); } @@ -44,12 +52,14 @@ public class BitUtil { * @return {@code value} with the bit corresponding to the {@code mask} set (if setBit is true) or cleared (if setBit is false) */ public static int set(int value, int mask, boolean setBit) { + assertOneBitMask(mask); return setBit ? value | mask : value & ~mask; } /** * @return {@code value} with the bit corresponding to the {@code mask} set (if setBit is true) or cleared (if setBit is false) */ public static long set(long value, long mask, boolean setBit) { + assertOneBitMask(mask); return setBit ? value | mask : value & ~mask; } } diff --git a/platform/util/src/com/intellij/util/io/IntToIntBtree.java b/platform/util/src/com/intellij/util/io/IntToIntBtree.java index 475f3cb67a94..5b2e7cb751d9 100644 --- a/platform/util/src/com/intellij/util/io/IntToIntBtree.java +++ b/platform/util/src/com/intellij/util/io/IntToIntBtree.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.intellij.util.io; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.BitUtil; import gnu.trove.TIntIntHashMap; import org.jetbrains.annotations.NotNull; @@ -488,8 +489,8 @@ public class IntToIntBtree { protected void doInitFlags(int flags) { super.doInitFlags(flags); flags = (flags >> FLAGS_SHIFT) & 0xFF; - isHashedLeaf = (flags & HASHED_LEAF_MASK) == HASHED_LEAF_MASK; - isIndexLeaf = (flags & INDEX_LEAF_MASK) == INDEX_LEAF_MASK; + isHashedLeaf = BitUtil.isSet(flags, HASHED_LEAF_MASK); + isIndexLeaf = BitUtil.isSet(flags, INDEX_LEAF_MASK); } void setIndexLeaf(boolean value) { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java index ce7e5721d059..24ef2910875f 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -166,7 +166,7 @@ public class XDebuggerEvaluationDialog extends DialogWrapper { @Override public void actionPerformed(ActionEvent e) { super.actionPerformed(e); - if (BitUtil.isSet(e.getModifiers(), InputEvent.SHIFT_MASK | InputEvent.CTRL_MASK)) { + if (BitUtil.isSet(e.getModifiers(), InputEvent.SHIFT_MASK) || BitUtil.isSet(e.getModifiers(), InputEvent.CTRL_MASK)) { addToWatches(); } } diff --git a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java index 0ae4b53b8694..e827a0fcc773 100644 --- a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java +++ b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,6 +46,7 @@ import com.intellij.openapi.vcs.FileStatusListener; import com.intellij.openapi.vcs.FileStatusManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.util.BitUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.UiNotifyConnector; @@ -381,7 +382,7 @@ public class BreadcrumbsXmlWrapper implements BreadcrumbsItemListener Date: Fri, 16 Jan 2015 18:14:17 +0300 Subject: [PATCH 16/47] cleanup --- .../codeInsight/daemon/impl/DaemonListeners.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java index b56c0f74ea27..82df1c71f40b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -85,7 +85,6 @@ import org.jetbrains.annotations.Nullable; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -436,7 +435,7 @@ public class DaemonListeners implements Disposable { if (activeVcs == null) return Result.NOT_SURE; FilePath path = VcsUtil.getFilePath(virtualFile); - boolean vcsIsThinking = !myVcsDirtyScopeManager.whatFilesDirty(Arrays.asList(path)).isEmpty(); + boolean vcsIsThinking = !myVcsDirtyScopeManager.whatFilesDirty(Collections.singletonList(path)).isEmpty(); if (vcsIsThinking) return Result.NOT_SURE; // do not modify file which is in the process of updating FileStatus status = myFileStatusManager.getStatus(virtualFile); @@ -573,7 +572,7 @@ public class DaemonListeners implements Disposable { if (myTogglePopupHintsPanel != null) myTogglePopupHintsPanel.updateStatus(); } - private class MyAnActionListener implements AnActionListener { + private class MyAnActionListener extends AnActionListener.Adapter { private final AnAction escapeAction = myActionManager.getAction(IdeActions.ACTION_EDITOR_ESCAPE); @Override @@ -581,10 +580,6 @@ public class DaemonListeners implements Disposable { myEscPressed = action == escapeAction; } - @Override - public void afterActionPerformed(final AnAction action, final DataContext dataContext, AnActionEvent event) { - } - @Override public void beforeEditorTyping(char c, DataContext dataContext) { Editor editor = CommonDataKeys.EDITOR.getData(dataContext); From 8d88d4f246a40d0025a9cb4227d7da80899bcfb2 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 19 Jan 2015 13:55:41 +0300 Subject: [PATCH 17/47] test dependency --- platform/util/util.iml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/util/util.iml b/platform/util/util.iml index c015e73f13b3..684449e02d43 100644 --- a/platform/util/util.iml +++ b/platform/util/util.iml @@ -24,6 +24,7 @@ + @@ -177,5 +178,4 @@ - - + \ No newline at end of file From 1d64a6e867d5e71449b66fa9ced10309eefac1d4 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 19 Jan 2015 13:57:31 +0300 Subject: [PATCH 18/47] moved to testFramework --- .../{util => testFramework}/src/com/intellij/util/GCUtil.java | 3 +++ 1 file changed, 3 insertions(+) rename platform/{util => testFramework}/src/com/intellij/util/GCUtil.java (96%) diff --git a/platform/util/src/com/intellij/util/GCUtil.java b/platform/testFramework/src/com/intellij/util/GCUtil.java similarity index 96% rename from platform/util/src/com/intellij/util/GCUtil.java rename to platform/testFramework/src/com/intellij/util/GCUtil.java index b1a4da43afa3..6c1762a7f2f2 100644 --- a/platform/util/src/com/intellij/util/GCUtil.java +++ b/platform/testFramework/src/com/intellij/util/GCUtil.java @@ -16,6 +16,7 @@ package com.intellij.util; import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.TestOnly; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; @@ -27,6 +28,7 @@ public class GCUtil { * Try to force VM to collect all the garbage along with soft- and weak-references. * Method doesn't guarantee to succeed, and should not be used in the production code. */ + @TestOnly public static void tryForceGC() { tryGcSoftlyReachableObjects(); WeakReference weakReference = new WeakReference(new Object()); @@ -40,6 +42,7 @@ public class GCUtil { * Try to force VM to collect soft references if possible. * Method doesn't guarantee to succeed, and should not be used in the production code. */ + @TestOnly public static void tryGcSoftlyReachableObjects() { ReferenceQueue q = new ReferenceQueue(); SoftReference ref = new SoftReference(new Object(), q); From dd469ff7dc823aed40aacfc3a3d2a2b25807c5c3 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Jan 2015 13:03:24 +0300 Subject: [PATCH 19/47] cleanup --- .../impl/smartPointers/AnchorElementInfo.java | 8 ++--- .../impl/smartPointers/SelfElementInfo.java | 17 ++++------ .../SmartPsiElementPointerImpl.java | 8 +++-- .../impl/source/text/BlockSupportImpl.java | 6 ++-- .../psi/impl/source/text/DiffLog.java | 32 +++++++++---------- .../moveUpDown/XmlMoverTest.java | 4 ++- 6 files changed, 37 insertions(+), 38 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java b/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java index c3319d2d2ce7..aae94191f942 100644 --- a/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java +++ b/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,13 +34,13 @@ import org.jetbrains.annotations.Nullable; * User: cdr */ class AnchorElementInfo extends SelfElementInfo { - private int stubId = -1; + private int stubId; private IStubElementType myStubElementType; AnchorElementInfo(@NotNull PsiElement anchor, @NotNull PsiFile containingFile) { - super(containingFile.getProject(), ProperTextRange.create(anchor.getTextRange()), anchor.getClass(), containingFile, - LanguageUtil.getRootLanguage(anchor)); + super(containingFile.getProject(), ProperTextRange.create(anchor.getTextRange()), anchor.getClass(), containingFile, LanguageUtil.getRootLanguage(anchor)); assert !(anchor instanceof PsiFile) : "FileElementInfo must be used for file: "+anchor; + stubId = -1; } // will restore by stub index until file tree get loaded AnchorElementInfo(@NotNull PsiElement anchor, diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java index d141a79f5703..ceb856e077e6 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java +++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package com.intellij.psi.impl.smartPointers; import com.intellij.lang.Language; -import com.intellij.lang.LanguageUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.RangeMarker; @@ -47,15 +46,11 @@ public class SelfElementInfo implements SmartPointerElementInfo { private volatile RangeMarker myRangeMarker; //maintains hard reference during modification protected final Language myLanguage; - protected SelfElementInfo(@NotNull Project project, @NotNull PsiElement anchor) { - this(project, ProperTextRange.create(anchor.getTextRange()), anchor.getClass(), anchor.getContainingFile(), - LanguageUtil.getRootLanguage(anchor)); - } - public SelfElementInfo(@NotNull Project project, - @NotNull ProperTextRange range, - @NotNull Class anchorClass, - @NotNull PsiFile containingFile, - @NotNull Language language) { + SelfElementInfo(@NotNull Project project, + @NotNull ProperTextRange range, + @NotNull Class anchorClass, + @NotNull PsiFile containingFile, + @NotNull Language language) { myLanguage = language; myVirtualFile = PsiUtilCore.getVirtualFile(containingFile); myType = anchorClass; diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java index d7b70398cf74..326d6b050250 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -126,7 +126,9 @@ class SmartPsiElementPointerImpl implements SmartPointerEx } @NotNull - static SmartPointerElementInfo createElementInfo(@NotNull Project project, @NotNull E element, PsiFile containingFile) { + private static SmartPointerElementInfo createElementInfo(@NotNull Project project, + @NotNull E element, + PsiFile containingFile) { if (element instanceof PsiDirectory) { return new DirElementInfo((PsiDirectory)element); } @@ -185,7 +187,7 @@ class SmartPsiElementPointerImpl implements SmartPointerEx return myElementInfo; } - protected static boolean pointsToTheSameElementAs(@NotNull SmartPsiElementPointer pointer1, @NotNull SmartPsiElementPointer pointer2) { + static boolean pointsToTheSameElementAs(@NotNull SmartPsiElementPointer pointer1, @NotNull SmartPsiElementPointer pointer2) { if (pointer1 == pointer2) return true; if (pointer1 instanceof SmartPsiElementPointerImpl && pointer2 instanceof SmartPsiElementPointerImpl) { SmartPsiElementPointerImpl impl1 = (SmartPsiElementPointerImpl)pointer1; diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/text/BlockSupportImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/text/BlockSupportImpl.java index 0ef1af849fd1..81369fcd59af 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/text/BlockSupportImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/text/BlockSupportImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -239,8 +239,8 @@ public class BlockSupportImpl extends BlockSupport { } @NotNull - private static DiffLog replaceElementWithEvents(final CompositeElement oldRoot, - final CompositeElement newRoot) { + private static DiffLog replaceElementWithEvents(@NotNull CompositeElement oldRoot, + @NotNull CompositeElement newRoot) { DiffLog diffLog = new DiffLog(); diffLog.appendReplaceElementWithEvents(oldRoot, newRoot); return diffLog; diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java b/platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java index 386fb2dea0e9..32edb4d4e0e7 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -70,11 +70,11 @@ public class DiffLog implements DiffTreeChangeBuilder { } } - public void appendReplaceElementWithEvents(CompositeElement oldRoot, CompositeElement newRoot) { + void appendReplaceElementWithEvents(@NotNull CompositeElement oldRoot, @NotNull CompositeElement newRoot) { myEntries.add(new ReplaceElementWithEvents(oldRoot, newRoot)); } - public void appendReplaceFileElement(FileElement oldNode, FileElement newNode) { + void appendReplaceFileElement(@NotNull FileElement oldNode, @NotNull FileElement newNode) { myEntries.add(new ReplaceFileElement(oldNode, newNode)); } @@ -92,7 +92,7 @@ public class DiffLog implements DiffTreeChangeBuilder { private final ASTNode myOldChild; private final ASTNode myNewChild; - public ReplaceEntry(@NotNull ASTNode oldNode, @NotNull ASTNode newNode) { + private ReplaceEntry(@NotNull ASTNode oldNode, @NotNull ASTNode newNode) { myOldChild = oldNode; myNewChild = newNode; ASTNode parent = oldNode.getTreeParent(); @@ -133,10 +133,10 @@ public class DiffLog implements DiffTreeChangeBuilder { } private static class DeleteEntry extends LogEntry { - private final ASTNode myOldParent; - private final ASTNode myOldNode; + @NotNull private final ASTNode myOldParent; + @NotNull private final ASTNode myOldNode; - public DeleteEntry(ASTNode oldParent, ASTNode oldNode) { + private DeleteEntry(@NotNull ASTNode oldParent, @NotNull ASTNode oldNode) { myOldParent = oldParent; myOldNode = oldNode; } @@ -167,11 +167,11 @@ public class DiffLog implements DiffTreeChangeBuilder { } private static class InsertEntry extends LogEntry { - private final ASTNode myOldParent; - private final ASTNode myNewNode; + @NotNull private final ASTNode myOldParent; + @NotNull private final ASTNode myNewNode; private final int myPos; - public InsertEntry(@NotNull ASTNode oldParent, @NotNull ASTNode newNode, int pos) { + private InsertEntry(@NotNull ASTNode oldParent, @NotNull ASTNode newNode, int pos) { assert oldParent instanceof CompositeElement : oldParent; myOldParent = oldParent; myNewNode = newNode; @@ -226,10 +226,10 @@ public class DiffLog implements DiffTreeChangeBuilder { } private static class ReplaceFileElement extends LogEntry { - private final FileElement myOldNode; - private final FileElement myNewNode; + @NotNull private final FileElement myOldNode; + @NotNull private final FileElement myNewNode; - public ReplaceFileElement(FileElement oldNode, FileElement newNode) { + private ReplaceFileElement(@NotNull FileElement oldNode, @NotNull FileElement newNode) { myOldNode = oldNode; myNewNode = newNode; } @@ -250,10 +250,10 @@ public class DiffLog implements DiffTreeChangeBuilder { } private static class ReplaceElementWithEvents extends LogEntry { - private final CompositeElement myOldRoot; - private final CompositeElement myNewRoot; + @NotNull private final CompositeElement myOldRoot; + @NotNull private final CompositeElement myNewRoot; - public ReplaceElementWithEvents(CompositeElement oldRoot, CompositeElement newRoot) { + private ReplaceElementWithEvents(@NotNull CompositeElement oldRoot, @NotNull CompositeElement newRoot) { myOldRoot = oldRoot; myNewRoot = newRoot; } diff --git a/xml/tests/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMoverTest.java b/xml/tests/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMoverTest.java index 308163ba8815..69a939721c1b 100644 --- a/xml/tests/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMoverTest.java +++ b/xml/tests/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMoverTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import com.intellij.openapi.editor.actionSystem.EditorActionHandler; import com.intellij.testFramework.LightPlatformCodeInsightTestCase; import com.intellij.testFramework.PlatformTestUtil; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import java.io.File; @@ -85,6 +86,7 @@ public class XmlMoverTest extends LightPlatformCodeInsightTestCase { return "/mover"; } + @NotNull @Override protected String getTestDataPath() { return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/xml/tests/testData"; From bc619a322bb368492de4875bd770eca93d3b87fd Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Tue, 20 Jan 2015 13:22:18 +0300 Subject: [PATCH 20/47] IDEA-131313 Restore last opened tab in Preferences | Editor | Code Style | --- .../options/TabbedLanguageCodeStylePanel.java | 26 +++++++++++++++ .../options/codeStyle/CodeStyleMainPanel.java | 32 ++++++++++++++++++- .../codeStyle/NewCodeStyleSettingsPanel.java | 11 ++++++- 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/TabbedLanguageCodeStylePanel.java b/platform/lang-impl/src/com/intellij/application/options/TabbedLanguageCodeStylePanel.java index 630fc8a5a3ac..81f2c875d574 100644 --- a/platform/lang-impl/src/com/intellij/application/options/TabbedLanguageCodeStylePanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/TabbedLanguageCodeStylePanel.java @@ -43,6 +43,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -62,6 +64,7 @@ public abstract class TabbedLanguageCodeStylePanel extends CodeStyleAbstractPane private TabbedPaneWrapper myTabbedPane; private final PredefinedCodeStyle[] myPredefinedCodeStyles; private JPopupMenu myCopyFromMenu; + private @Nullable TabChangeListener myListener; protected TabbedLanguageCodeStylePanel(@Nullable Language language, CodeStyleSettings currentSettings, CodeStyleSettings settings) { super(language, currentSettings, settings); @@ -123,6 +126,17 @@ public abstract class TabbedLanguageCodeStylePanel extends CodeStyleAbstractPane myPanel = new JPanel(); myPanel.setLayout(new BorderLayout()); myTabbedPane = new TabbedPaneWrapper(this); + myTabbedPane.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (myListener != null) { + String title = myTabbedPane.getSelectedTitle(); + if (title != null) { + myListener.tabChanged(TabbedLanguageCodeStylePanel.this, title); + } + } + } + }); myTabs = new ArrayList(); myPanel.add(myTabbedPane.getComponent()); initTabs(getSettings()); @@ -662,4 +676,16 @@ public abstract class TabbedLanguageCodeStylePanel extends CodeStyleAbstractPane } } + + public interface TabChangeListener { + void tabChanged(@NotNull TabbedLanguageCodeStylePanel source, @NotNull String tabTitle); + } + + public void setListener(@Nullable TabChangeListener listener) { + myListener = listener; + } + + public void changeTab(@NotNull String tabTitle) { + myTabbedPane.setSelectedTitle(tabTitle); + } } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleMainPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleMainPanel.java index db86ddaeebff..ef7a514be380 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleMainPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleMainPanel.java @@ -18,6 +18,8 @@ package com.intellij.application.options.codeStyle; import com.intellij.application.options.CodeStyleAbstractPanel; import com.intellij.application.options.TabbedLanguageCodeStylePanel; +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.lang.Language; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.options.ConfigurationException; @@ -27,6 +29,7 @@ import com.intellij.psi.codeStyle.CodeStyleSchemes; import com.intellij.ui.components.labels.SwingActionLink; import com.intellij.util.Alarm; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -37,7 +40,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; -public class CodeStyleMainPanel extends JPanel { +public class CodeStyleMainPanel extends JPanel implements TabbedLanguageCodeStylePanel.TabChangeListener { private final CardLayout myLayout = new CardLayout(); private final JPanel mySettingsPanel = new JPanel(myLayout); @@ -61,12 +64,16 @@ public class CodeStyleMainPanel extends JPanel { @NonNls private static final String WAIT_CARD = "CodeStyleSchemesConfigurable.$$$.Wait.placeholder.$$$"; + private final PropertiesComponent myProperties; + + private final static String SELECTED_TAB = "settings.code.style.selected.tab"; public CodeStyleMainPanel(CodeStyleSchemesModel model, CodeStyleSettingsPanelFactory factory) { super(new BorderLayout()); myModel = model; myFactory = factory; mySchemesPanel = new CodeStyleSchemesPanel(model); + myProperties = PropertiesComponent.getInstance(); model.addListener(new CodeStyleSettingsListener(){ @Override @@ -214,6 +221,15 @@ public class CodeStyleMainPanel extends JPanel { NewCodeStyleSettingsPanel panel = myFactory.createPanel(scheme); panel.reset(); panel.setModel(myModel); + CodeStyleAbstractPanel settingsPanel = panel.getSelectedPanel(); + if (settingsPanel instanceof TabbedLanguageCodeStylePanel) { + TabbedLanguageCodeStylePanel tabbedPanel = (TabbedLanguageCodeStylePanel)settingsPanel; + tabbedPanel.setListener(this); + String currentTab = myProperties.getValue(getSelectedTabPropertyName(tabbedPanel)); + if (currentTab != null) { + tabbedPanel.changeTab(currentTab); + } + } mySettingsPanels.put(name, panel); mySettingsPanel.add(scheme.getName(), panel); } @@ -244,4 +260,18 @@ public class CodeStyleMainPanel extends JPanel { final NewCodeStyleSettingsPanel panel = ensurePanel(defaultScheme); return panel.processListOptions(); } + + @Override + public void tabChanged(@NotNull TabbedLanguageCodeStylePanel source, @NotNull String tabTitle) { + myProperties.setValue(getSelectedTabPropertyName(source), tabTitle); + for (NewCodeStyleSettingsPanel panel : getPanels()) { + panel.tabChanged(source, tabTitle); + } + } + + @NotNull + private static String getSelectedTabPropertyName(@NotNull TabbedLanguageCodeStylePanel panel) { + Language language = panel.getDefaultLanguage(); + return SELECTED_TAB + (language != null ? "." + language.getID() : ""); + } } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/NewCodeStyleSettingsPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/NewCodeStyleSettingsPanel.java index 4ee9e0ecc9ad..3677845f5300 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/NewCodeStyleSettingsPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/NewCodeStyleSettingsPanel.java @@ -19,6 +19,7 @@ package com.intellij.application.options.codeStyle; import com.intellij.application.options.CodeStyleAbstractConfigurable; import com.intellij.application.options.CodeStyleAbstractPanel; import com.intellij.application.options.OptionsContainingConfigurable; +import com.intellij.application.options.TabbedLanguageCodeStylePanel; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; @@ -33,7 +34,7 @@ import java.util.Set; /** * @author max */ -public class NewCodeStyleSettingsPanel extends JPanel { +public class NewCodeStyleSettingsPanel extends JPanel implements TabbedLanguageCodeStylePanel.TabChangeListener { private static final Logger LOG = Logger.getInstance("#com.intellij.application.options.codeStyle.NewCodeStyleSettingsPanel"); private final Configurable myTab; @@ -106,4 +107,12 @@ public class NewCodeStyleSettingsPanel extends JPanel { } return null; } + + @Override + public void tabChanged(@NotNull TabbedLanguageCodeStylePanel source, @NotNull String tabTitle) { + CodeStyleAbstractPanel panel = getSelectedPanel(); + if (panel instanceof TabbedLanguageCodeStylePanel && panel != source) { + ((TabbedLanguageCodeStylePanel)panel).changeTab(tabTitle); + } + } } From 5cb55dc809e985be70abdbd00c7e1d49071a6037 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Mon, 19 Jan 2015 20:34:25 +0300 Subject: [PATCH 21/47] more friendly find-methods --- .../extapi/psi/ASTDelegatePsiElement.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/platform/core-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java b/platform/core-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java index 9dd2fc252479..c5112ac45705 100644 --- a/platform/core-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java +++ b/platform/core-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java @@ -176,18 +176,17 @@ public abstract class ASTDelegatePsiElement extends PsiElementBase { } @Nullable - protected PsiElement findChildByType(IElementType type) { + protected T findChildByType(IElementType type) { ASTNode node = getNode().findChildByType(type); - return node == null ? null : node.getPsi(); + return node == null ? null : (T)node.getPsi(); } - @Nullable - protected PsiElement findLastChildByType(IElementType type) { + protected T findLastChildByType(IElementType type) { PsiElement child = getLastChild(); while (child != null) { final ASTNode node = child.getNode(); - if (node != null && node.getElementType() == type) return child; + if (node != null && node.getElementType() == type) return (T)child; child = child.getPrevSibling(); } return null; @@ -196,14 +195,14 @@ public abstract class ASTDelegatePsiElement extends PsiElementBase { @NotNull - protected PsiElement findNotNullChildByType(IElementType type) { - return notNullChild(findChildByType(type)); + protected T findNotNullChildByType(IElementType type) { + return notNullChild(this.findChildByType(type)); } @Nullable - protected PsiElement findChildByType(TokenSet type) { + protected T findChildByType(TokenSet type) { ASTNode node = getNode().findChildByType(type); - return node == null ? null : node.getPsi(); + return node == null ? null : (T)node.getPsi(); } @NotNull From 377794baf6d0d4a140ee6846afed901ed482fbbb Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Tue, 20 Jan 2015 14:16:40 +0300 Subject: [PATCH 22/47] When testing module reformat - pass module directory into DataContext instead of random file. Fixes failing test (ReformatCodeActionTest.testOptimizeAndReformatInModule) --- .../actions/AbstractLayoutCodeProcessorTest.java | 11 +++++------ .../codeInsight/actions/ReformatCodeActionTest.java | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java index fbd85a3b62a5..366fd626baaf 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java @@ -139,10 +139,10 @@ public abstract class AbstractLayoutCodeProcessorTest extends PsiTestCase { protected void performReformatActionOnSelectedFile(PsiFile file) { final AnAction action = getReformatCodeAction(); - action.actionPerformed(createEventFor(action, ContainerUtil.newArrayList(file), getProject(), new AdditionalEventInfo().setPsiElement(file))); + action.actionPerformed(createEventFor(action, ContainerUtil.newArrayList(file.getVirtualFile()), getProject(), new AdditionalEventInfo().setPsiElement(file))); } - protected void performReformatActionOnModule(Module module, List files) { + protected void performReformatActionOnModule(Module module, List files) { final AnAction action = getReformatCodeAction(); action.actionPerformed(createEventFor(action, files, getProject(), new AdditionalEventInfo().setModule(module))); } @@ -156,7 +156,7 @@ public abstract class AbstractLayoutCodeProcessorTest extends PsiTestCase { final AnAction action = getReformatCodeAction(); Document document = PsiDocumentManager.getInstance(getProject()).getDocument(file); Editor editor = EditorFactory.getInstance().createEditor(document); - action.actionPerformed(createEventFor(action, ContainerUtil.newArrayList(file), getProject(), new AdditionalEventInfo().setEditor(editor))); + action.actionPerformed(createEventFor(action, ContainerUtil.newArrayList(file.getVirtualFile()), getProject(), new AdditionalEventInfo().setEditor(editor))); EditorFactory.getInstance().releaseEditor(editor); } @@ -199,13 +199,12 @@ public abstract class AbstractLayoutCodeProcessorTest extends PsiTestCase { }, "", action.getTemplatePresentation(), ActionManager.getInstance(), 0); } - protected AnActionEvent createEventFor(AnAction action, List files, final Project project, @NotNull final AdditionalEventInfo eventInfo) { - final VirtualFile[] vFilesArray = getVirtualFileArrayFrom(files); + protected AnActionEvent createEventFor(AnAction action, final List files, final Project project, @NotNull final AdditionalEventInfo eventInfo) { return new AnActionEvent(null, new DataContext() { @Nullable @Override public Object getData(@NonNls String dataId) { - if (CommonDataKeys.VIRTUAL_FILE_ARRAY.is(dataId)) return vFilesArray; + if (CommonDataKeys.VIRTUAL_FILE_ARRAY.is(dataId)) return files.toArray(new VirtualFile[files.size()]); if (CommonDataKeys.PROJECT.is(dataId)) return project; if (CommonDataKeys.EDITOR.is(dataId)) return eventInfo.getEditor(); if (LangDataKeys.MODULE_CONTEXT.is(dataId)) return eventInfo.getModule(); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java index f2cd858132db..b0e4024ff076 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java @@ -105,7 +105,7 @@ public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest { List files = createTestFiles(srcDir, classNames); injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true)); - performReformatActionOnModule(module, files.subList(0, 1)); + performReformatActionOnModule(module, ContainerUtil.newArrayList(srcDir)); checkFormationAndImportsOptimizationFor(files); } From b5d00409eef0514304c87b93fc7b15766187ad9b Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 20 Jan 2015 14:33:30 +0300 Subject: [PATCH 23/47] ContainerUtil.map2Array: variance of generic parameter corrected --- .../src/com/intellij/extapi/psi/ASTDelegatePsiElement.java | 6 +++--- .../src/com/intellij/util/containers/ContainerUtil.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/platform/core-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java b/platform/core-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java index c5112ac45705..c7651631d212 100644 --- a/platform/core-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java +++ b/platform/core-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java @@ -262,10 +262,10 @@ public abstract class ASTDelegatePsiElement extends PsiElementBase { } protected T[] findChildrenByType(TokenSet elementType, Class arrayClass) { - return (T[])ContainerUtil.map2Array(getNode().getChildren(elementType), arrayClass, new Function() { + return ContainerUtil.map2Array(getNode().getChildren(elementType), arrayClass, new Function() { @Override - public PsiElement fun(final ASTNode s) { - return s.getPsi(); + public T fun(final ASTNode s) { + return (T)s.getPsi(); } }); } diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index 38074a2af9a1..d0577e173dba 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -896,13 +896,13 @@ public class ContainerUtil extends ContainerUtilRt { @NotNull @Contract(pure=true) - public static V[] map2Array(@NotNull T[] array, @NotNull Class aClass, @NotNull Function mapper) { + public static V[] map2Array(@NotNull T[] array, @NotNull Class aClass, @NotNull Function mapper) { return map2Array(Arrays.asList(array), aClass, mapper); } @NotNull @Contract(pure=true) - public static V[] map2Array(@NotNull Collection collection, @NotNull Class aClass, @NotNull Function mapper) { + public static V[] map2Array(@NotNull Collection collection, @NotNull Class aClass, @NotNull Function mapper) { final List list = map2List(collection, mapper); @SuppressWarnings("unchecked") V[] array = (V[])Array.newInstance(aClass, list.size()); return list.toArray(array); From 558ce95696dfffb20f962221983e020caad7ff01 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Jan 2015 12:48:51 +0100 Subject: [PATCH 24/47] javadoc for MoveFileHandler --- .../MoveFileHandler.java | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/MoveFileHandler.java b/platform/lang-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/MoveFileHandler.java index a73dc4fd89e4..ec4c5fc3bfd6 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/MoveFileHandler.java +++ b/platform/lang-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/MoveFileHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,18 +30,58 @@ import java.util.List; import java.util.Map; /** + * Allows plugins to handle the Move refactoring for a file in a custom way. + * * @author Maxim.Mossienko - * Date: Sep 18, 2008 - * Time: 3:40:48 PM */ public abstract class MoveFileHandler { private static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.moveFileHandler"); + /** + * Checks whether a file can be handled by this move handler. + * + * @param element the file being moved. + * @return true if this handler can handle this file, false otherwise. + */ public abstract boolean canProcessElement(PsiFile element); + + /** + * Performs any necessary modifications of the file contents before the move. + * + * @param file the file being moved. + * @param moveDestination the directory to which the file is being moved. + * @param oldToNewMap the map of elements which can be referenced from other files directly (not through a file reference) + * to their counterparts after the move. The handler needs to add elements to this map according to the + * file modifications that it has performed. + */ public abstract void prepareMovedFile(PsiFile file, PsiDirectory moveDestination, Map oldToNewMap); + + /** + * Finds the list of references to the file being moved that will need to be updated during the move refactoring. + * + * @param psiFile the file being moved. + * @param newParent the directory to which the file is being moved. + * @param searchInComments if true, search for references in comments has been requested. + * @param searchInNonJavaFiles if true, search for references in non-code files (such as .xml) has been requested. + * @return the list of usages that need to be updated, or null if nothing needs to be updated. + */ @Nullable public abstract List findUsages(PsiFile psiFile, PsiDirectory newParent, boolean searchInComments, boolean searchInNonJavaFiles); + + /** + * After a file has been moved, updates the references to the file so that they point to the new location of the file. + * + * @param usageInfos the list of references, as returned from {@link #findUsages} + * @param oldToNewMap the map of all moved elements, filled by {@link #prepareMovedFile} + */ public abstract void retargetUsages(List usageInfos, Map oldToNewMap) ; + + /** + * Updates the contents of the file after it has been moved (e.g. updates the package statement to correspond to the + * new location of a Java class). + * + * @param file the moved file. + */ public abstract void updateMovedFile(PsiFile file) throws IncorrectOperationException; @NotNull From 1e3dd0be4878c478c02760322ef9659b05b2a699 Mon Sep 17 00:00:00 2001 From: Konstantin Ulitin Date: Tue, 20 Jan 2015 14:59:54 +0300 Subject: [PATCH 25/47] IDEA-131672 Find usages of Java package / class / method / field / constructor should skip JavaScript code unless source latter has Nashorn language dialect --- .../psi/impl/search/PsiSearchHelperImpl.java | 6 ++++++ .../intellij/psi/search/UseScopeOptimizer.java | 16 ++++++++++++++++ .../src/META-INF/LangExtensionPoints.xml | 1 + 3 files changed, 23 insertions(+) create mode 100644 platform/indexing-impl/src/com/intellij/psi/search/UseScopeOptimizer.java diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java b/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java index 5081ea2ce148..8e9b6bf78be2 100644 --- a/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java +++ b/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java @@ -82,6 +82,12 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { scope = scope.union(additionalScope); } } + for (UseScopeOptimizer optimizer : UseScopeOptimizer.EP_NAME.getExtensions()) { + final GlobalSearchScope scopeToExclude = optimizer.getScopeToExclude(element); + if (scopeToExclude != null) { + scope = scope.intersectWith(GlobalSearchScope.notScope(scopeToExclude)); + } + } return scope; } diff --git a/platform/indexing-impl/src/com/intellij/psi/search/UseScopeOptimizer.java b/platform/indexing-impl/src/com/intellij/psi/search/UseScopeOptimizer.java new file mode 100644 index 000000000000..58849a3f6fca --- /dev/null +++ b/platform/indexing-impl/src/com/intellij/psi/search/UseScopeOptimizer.java @@ -0,0 +1,16 @@ +package com.intellij.psi.search; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Konstantin.Ulitin + */ +public abstract class UseScopeOptimizer { + public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.useScopeOptimizer"); + + @Nullable + public abstract GlobalSearchScope getScopeToExclude(@NotNull PsiElement element); +} diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index d5375dca95bd..42cfe0195523 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -246,6 +246,7 @@ + From 94ef8e039dc9af22f9f1a0e10258cc46fdcc3b99 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 19 Jan 2015 16:48:55 +0300 Subject: [PATCH 26/47] [vcs] fix ChangesComparator once again --- .../vcs/changes/ui/ChangesComparator.java | 57 ++++++++++++------- .../vcs/changes/ui/ChangesComparatorTest.java | 41 +++++++++---- 2 files changed, 69 insertions(+), 29 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesComparator.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesComparator.java index a3e998b0bbc2..f28e279d5893 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesComparator.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesComparator.java @@ -15,8 +15,8 @@ */ package com.intellij.openapi.vcs.changes.ui; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtilRt; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ChangesUtil; @@ -46,25 +46,44 @@ public class ChangesComparator implements Comparator { if (myTreeCompare) { final String path1 = FileUtilRt.toSystemIndependentName(filePath1.getPath()); final String path2 = FileUtilRt.toSystemIndependentName(filePath2.getPath()); - if (path1.compareToIgnoreCase(path2) == 0) { - return 0; - } - final int lastSlash1 = path1.lastIndexOf('/'); - final String parentPath1 = lastSlash1 >= 0 && !filePath1.isDirectory() ? path1.substring(0, lastSlash1) : path1; - final int lastSlash2 = path2.lastIndexOf('/'); - final String parentPath2 = lastSlash2 >= 0 && !filePath2.isDirectory() ? path2.substring(0, lastSlash2) : path2; - // subdirs precede files - if (FileUtil.isAncestor(parentPath2, parentPath1, true)) { - return -1; - } - else if (FileUtil.isAncestor(parentPath1, parentPath2, true)) { - return 1; - } - int parentPathComparison = parentPath1.compareToIgnoreCase(parentPath2); - if (parentPathComparison != 0) { - return parentPathComparison; + + int index1 = 0; + int index2 = 0; + + int start = 0; + + while (index1 < path1.length() && index2 < path2.length()) { + char c1 = path1.charAt(index1); + char c2 = path2.charAt(index2); + + if (StringUtil.compare(c1, c2, true) != 0) break; + + if (c1 == '/') start = index1; + + index1++; + index2++; } + + if (index1 == path1.length() && index2 == path2.length()) return 0; + if (index1 == path1.length()) return -1; + if (index2 == path2.length()) return 1; + + int end1 = path1.indexOf('/', start + 1); + int end2 = path2.indexOf('/', start + 1); + + String name1 = end1 == -1 ? path1.substring(start) : path1.substring(start, end1); + String name2 = end2 == -1 ? path2.substring(start) : path2.substring(start, end2); + + boolean isDirectory1 = end1 != -1 || filePath1.isDirectory(); + boolean isDirectory2 = end2 != -1 || filePath2.isDirectory(); + + if (isDirectory1 && !isDirectory2) return -1; + if (!isDirectory1 && isDirectory2) return 1; + + return name1.compareToIgnoreCase(name2); + } + else { + return filePath1.getName().compareToIgnoreCase(filePath2.getName()); } - return filePath1.getName().compareToIgnoreCase(filePath2.getName()); } } diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ui/ChangesComparatorTest.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ui/ChangesComparatorTest.java index 4f5932b5f409..5708cf43a746 100644 --- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ui/ChangesComparatorTest.java +++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ui/ChangesComparatorTest.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.vcs.changes.ui; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FilePathImpl; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ContentRevision; @@ -66,25 +67,45 @@ public class ChangesComparatorTest { assertEquals(0, compare("", "")); } + @Test + public void testSamePrefixFolder() throws Exception { + assertEquals(-1, compare("~/project/aaa/", "~/project/aaa-qwe/")); + assertEquals(-1, compare("~/project/aaa/A.java", "~/project/aaa-qwe/A.java")); + assertEquals(1, compare("~/project/zzz-qwe.java", "~/project/zzz/")); + } + + @Test + public void testRootDirectory() throws Exception { + assertEquals(0, compare("A.java", "A.java")); + assertEquals(0, compare("/aaa/", "/aaa/")); + assertEquals(-1, compare("/aaa/", "/aaa-qwe/")); + assertEquals(-1, compare("/aaa/", "/ZZ.java")); + } + + @Test + public void testAssociativeBug() throws Exception { + assertEquals(1, compare("/folder/aaa-qwerty/", "/folder/aaa/")); + assertEquals(1, compare("/folder/aaa/.gitignore", "/folder/aaa/")); + assertEquals(-1, compare("/folder/aaa/.gitignore", "/folder/aaa-qwerty/")); + assertEquals(1, compare("/folder/aaa-qwerty/qwerty", "/folder/aaa/qwerty/")); + } + private static int compare(String path1, String path2) throws Exception { - return compare(change(path1), change(path2)); + int compare1 = compare(change(path1), change(path2)); + int compare2 = compare(change(path2), change(path1)); + assert compare1 == -compare2; + return compare1; } private static int compare(Change c1, Change c2) { int result = ChangesComparator.getInstance(false).compare(c1, c2); - if (result > 0) { - return 1; - } - if (result < 0) { - return -1; - } - return 0; + return Integer.signum(result); } @NotNull private static Change change(@NotNull String path) throws Exception { - ContentRevision before = new MockContentRevision(new FilePathImpl(new File(path), false), VcsRevisionNumber.NULL); - ContentRevision after = new MockContentRevision(new FilePathImpl(new File(path), false), VcsRevisionNumber.NULL); + ContentRevision before = new MockContentRevision(new FilePathImpl(new File(path), StringUtil.endsWithChar(path, '/')), VcsRevisionNumber.NULL); + ContentRevision after = new MockContentRevision(new FilePathImpl(new File(path), StringUtil.endsWithChar(path, '/')), VcsRevisionNumber.NULL); return new Change(before, after); } From 4000b08193434eda43b218d311078953cccad7ef Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Tue, 20 Jan 2015 13:34:50 +0100 Subject: [PATCH 27/47] IDEA-96013 Quick javadoc invoked differently from decomiled class stub and other places --- .../com/intellij/lang/java/JavaDocumentationProvider.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java index cf5eea20c05d..97b4cab5aae1 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java @@ -42,6 +42,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileSystem; import com.intellij.psi.*; import com.intellij.psi.impl.beanProperties.BeanPropertyElement; +import com.intellij.psi.impl.compiled.ClsElementImpl; import com.intellij.psi.impl.source.javadoc.PsiDocParamRef; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.javadoc.PsiDocComment; @@ -479,6 +480,13 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext @Override public String generateDoc(PsiElement element, PsiElement originalElement) { + PsiCompiledElement originalCompiledElement = element.getUserData(ClsElementImpl.COMPILED_ELEMENT); + if (originalCompiledElement != null) { + // take compiled element instead decompiled one for finding proper documentation (IDEA-96013) + // it will not be needed iff TargetElementUtilBase stops preferring decompiled source + // via ((PsiCompiledFile) file).getDecompiledPsiFile() + element = originalCompiledElement; + } if (element instanceof PsiExpressionList) { element = element.getParent(); // for new Class() or methodCall() proceed from method call or new expression originalElement = null; From e33853c6d6fddfaf9847de6dd1edcfde06149997 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 20 Jan 2015 12:21:03 +0100 Subject: [PATCH 28/47] StringUtil.unescapeChar API --- .../src/com/intellij/openapi/util/text/StringUtil.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index efb174a77b73..d493deb0e493 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -2036,6 +2036,14 @@ public class StringUtil extends StringUtilRt { return buf.toString(); } + @NotNull + @Contract(pure = true) + public static String unescapeChar(@NotNull final String str, char unescapeChar) { + final StringBuilder buf = new StringBuilder(str.length()); + unescapeChar(buf, str, unescapeChar); + return buf.toString(); + } + private static void unescapeChar(@NotNull StringBuilder buf, @NotNull String str, char unescapeChar) { final int length = str.length(); final int last = length - 1; From 4eab91ea46864dbd005db537f8b81472fbd791b5 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 19 Jan 2015 16:10:04 +0300 Subject: [PATCH 29/47] javadoc --- .../src/com/intellij/dvcs/branch/DvcsSyncSettings.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsSyncSettings.java b/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsSyncSettings.java index 7d33bc79e9b5..cd31b24f1419 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsSyncSettings.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsSyncSettings.java @@ -15,8 +15,12 @@ */ package com.intellij.dvcs.branch; +import com.intellij.dvcs.repo.RepositoryManager; import org.jetbrains.annotations.NotNull; +/** + * @see RepositoryManager#isSyncEnabled() + */ public interface DvcsSyncSettings { enum Value { From 80092d6c64179c3f39b533f21fac84eb11a2376b Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 20 Jan 2015 15:48:59 +0300 Subject: [PATCH 30/47] IDEA-135034 Unable to create branch with opening JIRA task --- .../intellij/dvcs/branch/DvcsTaskHandler.java | 143 +++++++++--------- .../intellij/openapi/vcs/VcsTaskHandler.java | 38 +++-- .../git4idea/src/git4idea/GitTaskHandler.java | 17 ++- .../src/org/zmlx/hg4idea/HgTaskHandler.java | 11 +- .../src/com/intellij/tasks/BranchInfo.java | 26 ++-- .../tasks/actions/OpenTaskDialog.java | 4 +- .../intellij/tasks/impl/TaskManagerImpl.java | 20 ++- .../tasks/vcs/GitTaskBranchesTest.java | 2 +- .../intellij/tasks/vcs/TaskBranchesTest.java | 27 +++- 9 files changed, 174 insertions(+), 114 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsTaskHandler.java b/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsTaskHandler.java index 0d128e319954..7b2dd244b846 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsTaskHandler.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsTaskHandler.java @@ -27,14 +27,15 @@ import com.intellij.openapi.vcs.VcsTaskHandler; import com.intellij.util.Function; import com.intellij.util.NullableFunction; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.FactoryMap; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.Map; public abstract class DvcsTaskHandler extends VcsTaskHandler { @@ -49,8 +50,8 @@ public abstract class DvcsTaskHandler extends VcsTaskHandl } @Override - public boolean isEnabled(@Nullable Project project) { - return project != null && !project.isDisposed() && !myRepositoryManager.getRepositories().isEmpty(); + public boolean isEnabled() { + return !myRepositoryManager.getRepositories().isEmpty(); } @Override @@ -62,17 +63,17 @@ public abstract class DvcsTaskHandler extends VcsTaskHandl return hasBranch(repository, taskName); } }); - MultiMap map = new MultiMap(); + List map = new ArrayList(); if (!problems.isEmpty()) { if (ApplicationManager.getApplication().isUnitTestMode() || Messages.showDialog(myProject, "The following repositories already have specified " + myBranchType + "" + taskName + ":
" + StringUtil.join(problems, "
") + ".
" + - "Do you want to checkout existing " + myBranchType + "?", myBranchType + " Already Exists", + "Do you want to checkout existing " + myBranchType + "?", StringUtil.capitalize(myBranchType) + " Already Exists", new String[]{Messages.YES_BUTTON, Messages.NO_BUTTON}, 0, Messages.getWarningIcon(), new DialogWrapper.PropertyDoNotAskOption("git.checkout.existing.branch")) == 0) { checkout(taskName, problems, null); - fillMap(taskName, problems, map); + map.addAll(problems); } } repositories.removeAll(problems); @@ -80,89 +81,88 @@ public abstract class DvcsTaskHandler extends VcsTaskHandl checkoutAsNewBranch(taskName, repositories); } - fillMap(taskName, repositories, map); - return new TaskInfo(map); - } - - private static void fillMap(String taskName, List repositories, MultiMap map) { - for (R repository : repositories) { - map.putValue(taskName, repository.getPresentableUrl()); - } + map.addAll(repositories); + return new TaskInfo(taskName, ContainerUtil.map(map, new Function() { + @Override + public String fun(R r) { + return r.getPresentableUrl(); + } + })); } @Override public void switchToTask(@NotNull TaskInfo taskInfo, @Nullable Runnable invokeAfter) { - for (final String branchName : taskInfo.branches.keySet()) { - List repositories = getRepositories(taskInfo.branches.get(branchName)); - List notFound = ContainerUtil.filter(repositories, new Condition() { - @Override - public boolean value(R repository) { - return !hasBranch(repository, branchName); - } - }); - if (!notFound.isEmpty()) { - checkoutAsNewBranch(branchName, notFound); - } - repositories.removeAll(notFound); - if (!repositories.isEmpty()) { - checkout(branchName, repositories, invokeAfter); + final String branchName = taskInfo.getName(); + List repositories = getRepositories(taskInfo.getRepositories()); + List notFound = ContainerUtil.filter(repositories, new Condition() { + @Override + public boolean value(R repository) { + return !hasBranch(repository, branchName); } + }); + if (!notFound.isEmpty()) { + checkoutAsNewBranch(branchName, notFound); + } + repositories.removeAll(notFound); + if (!repositories.isEmpty()) { + checkout(branchName, repositories, invokeAfter); } } @Override public void closeTask(@NotNull final TaskInfo taskInfo, @NotNull TaskInfo original) { - Set branches = original.branches.keySet(); - final AtomicInteger counter = new AtomicInteger(branches.size()); - for (final String originalBranch : branches) { - checkout(originalBranch, getRepositories(original.branches.get(originalBranch)), new Runnable() { - @Override - public void run() { - if (counter.decrementAndGet() == 0) { - merge(taskInfo); - } - } - }); - } - } - - private void merge(@NotNull TaskInfo taskInfo) { - for (String featureBranch : taskInfo.branches.keySet()) { - mergeAndClose(featureBranch, getRepositories(taskInfo.branches.get(featureBranch))); - } + checkout(original.getName(), getRepositories(original.getRepositories()), new Runnable() { + @Override + public void run() { + mergeAndClose(taskInfo.getName(), getRepositories(taskInfo.getRepositories())); + } + }); } @Override - @NotNull - public TaskInfo getActiveTask() { - List repositories = myRepositoryManager.getRepositories(); - - MultiMap branches = new MultiMap(); - for (R repository : repositories) { - String branchName = repository.getCurrentBranchName(); - if (branchName != null) { - branches.putValue(branchName, repository.getPresentableUrl()); - } - } - return new TaskInfo(branches); + public boolean isSyncEnabled() { + return myRepositoryManager.isSyncEnabled(); } @Override public TaskInfo[] getCurrentTasks() { List repositories = myRepositoryManager.getRepositories(); - final List names = ContainerUtil.map(repositories, new Function() { + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") + FactoryMap tasks = new FactoryMap() { + @Nullable @Override - public String fun(R repository) { - return repository.getPresentableUrl(); + protected TaskInfo create(String key) { + return new TaskInfo(key, new ArrayList()); } - }); - Collection branches = getCommonBranchNames(repositories); - return ContainerUtil.map2Array(branches, TaskInfo.class, new Function() { + }; + for (R repository : repositories) { + String branch = getActiveBranch(repository); + if (branch != null) { + tasks.get(branch).getRepositories().add(repository.getPresentableUrl()); + } + } + if (tasks.size() == 0) return new TaskInfo[0]; + if (isSyncEnabled()) { + return new TaskInfo[] { tasks.values().iterator().next() }; + } + else { + return tasks.values().toArray(new TaskInfo[tasks.values().size()]); + } + } + + @Override + public TaskInfo[] getAllExistingTasks() { + List repositories = myRepositoryManager.getRepositories(); + MultiMap tasks = new MultiMap(); + for (R repository : repositories) { + for (String branch : getAllBranches(repository)) { + tasks.putValue(branch, repository.getPresentableUrl()); + } + } + return ContainerUtil.map2Array(tasks.entrySet(), TaskInfo.class, new Function>, TaskInfo>() { @Override - public TaskInfo fun(String branchName) { - MultiMap map = new MultiMap(); - map.put(branchName, names); - return new TaskInfo(map); + public TaskInfo fun(Map.Entry> entry) { + return new TaskInfo(entry.getKey(), entry.getValue()); } }); } @@ -189,8 +189,11 @@ public abstract class DvcsTaskHandler extends VcsTaskHandl protected abstract void checkoutAsNewBranch(@NotNull String name, @NotNull List repositories); + @Nullable + protected abstract String getActiveBranch(R repository); + @NotNull - protected abstract Collection getCommonBranchNames(@NotNull List repositories); + protected abstract Iterable getAllBranches(@NotNull R repository); protected abstract void mergeAndClose(@NotNull String branch, @NotNull List repositories); diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsTaskHandler.java b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsTaskHandler.java index 22c554b05e1d..0ee5f2ed09c3 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsTaskHandler.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsTaskHandler.java @@ -19,9 +19,9 @@ import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; +import java.util.Collection; import java.util.List; /** @@ -35,41 +35,55 @@ public abstract class VcsTaskHandler { List handlers = ContainerUtil.filter(extensions, new Condition() { @Override public boolean value(VcsTaskHandler handler) { - return handler.isEnabled(project); + return handler.isEnabled(); } }); return handlers.toArray(new VcsTaskHandler[handlers.size()]); } public static class TaskInfo { - // branch name/repository names - public final MultiMap branches; - public TaskInfo(MultiMap branches) { - this.branches = branches; + private final String myBranch; + private final Collection myRepositories; + + public TaskInfo(String branch, Collection repositories) { + myBranch = branch; + myRepositories = repositories; } public String getName() { - return branches.isEmpty() ? null : branches.keySet().iterator().next(); + return myBranch; + } + + public Collection getRepositories() { + return myRepositories; } @Override - public boolean equals(Object obj) { - return branches.equals(((TaskInfo)obj).branches); + public String toString() { + return getName(); } } private static final ExtensionPointName EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.vcs.taskHandler"); - public abstract boolean isEnabled(Project project); + public abstract boolean isEnabled(); public abstract TaskInfo startNewTask(@NotNull String taskName); public abstract void switchToTask(TaskInfo taskInfo, Runnable invokeAfter); - public abstract void closeTask(TaskInfo taskInfo, TaskInfo original); + public abstract void closeTask(@NotNull TaskInfo taskInfo, @NotNull TaskInfo original); - public abstract TaskInfo getActiveTask(); + public abstract boolean isSyncEnabled(); + /** + * @return currently active (checked out) tasks (branches) + */ public abstract TaskInfo[] getCurrentTasks(); + + /** + * @return all existing tasks (branches) + */ + public abstract TaskInfo[] getAllExistingTasks(); } diff --git a/plugins/git4idea/src/git4idea/GitTaskHandler.java b/plugins/git4idea/src/git4idea/GitTaskHandler.java index 3a685ae15b94..b6cf56abce0a 100644 --- a/plugins/git4idea/src/git4idea/GitTaskHandler.java +++ b/plugins/git4idea/src/git4idea/GitTaskHandler.java @@ -17,7 +17,8 @@ package git4idea; import com.intellij.dvcs.branch.DvcsTaskHandler; import com.intellij.openapi.project.Project; -import git4idea.branch.GitBranchUtil; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import git4idea.branch.GitBrancher; import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryManager; @@ -50,6 +51,11 @@ public class GitTaskHandler extends DvcsTaskHandler { myBrancher.checkoutNewBranch(name, repositories); } + @Override + protected String getActiveBranch(GitRepository repository) { + return repository.getCurrentBranchName(); + } + @Override protected void mergeAndClose(@NotNull String branch, @NotNull List repositories) { myBrancher.merge(branch, GitBrancher.DeleteOnMergeOption.DELETE, repositories); @@ -62,7 +68,12 @@ public class GitTaskHandler extends DvcsTaskHandler { @NotNull @Override - protected Collection getCommonBranchNames(@NotNull List repositories) { - return GitBranchUtil.getCommonBranches(repositories, true); + protected Collection getAllBranches(@NotNull GitRepository repository) { + return ContainerUtil.map(repository.getBranches().getLocalBranches(), new Function() { + @Override + public String fun(GitLocalBranch branch) { + return branch.getName(); + } + }); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgTaskHandler.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgTaskHandler.java index 1c9bc0e95de8..ed2b05899324 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgTaskHandler.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgTaskHandler.java @@ -36,7 +36,6 @@ import org.zmlx.hg4idea.repo.HgRepositoryManager; import org.zmlx.hg4idea.util.HgErrorUtil; import org.zmlx.hg4idea.util.HgUtil; -import java.util.Collection; import java.util.List; public class HgTaskHandler extends DvcsTaskHandler { @@ -58,11 +57,17 @@ public class HgTaskHandler extends DvcsTaskHandler { HgBookmarkCommand.createBookmark(repositories, name, true); } + @Override + protected String getActiveBranch(HgRepository repository) { + String bookmark = repository.getCurrentBookmark(); + return bookmark == null ? repository.getCurrentBranch() : bookmark; + } + @NotNull @Override - protected Collection getCommonBranchNames(@NotNull List repositories) { + protected Iterable getAllBranches(@NotNull HgRepository repository) { //be careful with equality names of branches/bookmarks =( - return ContainerUtil.concat(HgBranchUtil.getCommonBookmarks(repositories), HgBranchUtil.getCommonBranches(repositories)); + return ContainerUtil.concat(HgUtil.getNamesWithoutHashes(repository.getBookmarks()), repository.getOpenedBranches()); } @Override diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/BranchInfo.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/BranchInfo.java index 4626ab11f9d1..1abcbb802c23 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/BranchInfo.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/BranchInfo.java @@ -16,13 +16,12 @@ package com.intellij.tasks; import com.intellij.openapi.vcs.VcsTaskHandler; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xmlb.annotations.Attribute; import com.intellij.util.xmlb.annotations.Tag; -import java.util.ArrayList; -import java.util.Collection; import java.util.List; -import java.util.Map; /** * @author Dmitry Avdeev @@ -40,18 +39,17 @@ public class BranchInfo { @Attribute("original") public boolean original; - public static List fromTaskInfo(VcsTaskHandler.TaskInfo taskInfo, boolean original) { - ArrayList list = new ArrayList(); - for (Map.Entry> entry : taskInfo.branches.entrySet()) { - for (String repository : entry.getValue()) { - BranchInfo branchInfo = new BranchInfo(); - branchInfo.name = entry.getKey(); - branchInfo.repository = repository; - branchInfo.original = original; - list.add(branchInfo); + public static List fromTaskInfo(final VcsTaskHandler.TaskInfo taskInfo, final boolean original) { + return ContainerUtil.map(taskInfo.getRepositories(), new Function() { + @Override + public BranchInfo fun(String s) { + BranchInfo info = new BranchInfo(); + info.name = taskInfo.getName(); + info.repository = s; + info.original = original; + return info; } - } - return list; + }); } @Override diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java index d9ced072e5cd..66c3f80540c5 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java @@ -132,7 +132,7 @@ public class OpenTaskDialog extends DialogWrapper { }); } if (info == null) { - info = handler.getActiveTask(); + info = tasks[0]; } myBranchFrom.setSelectedItem(info); myBranchFrom.addActionListener(new ActionListener() { @@ -213,7 +213,7 @@ public class OpenTaskDialog extends DialogWrapper { taskManager.createBranch(localTask, activeTask, myBranchName.getText()); } }; - if (item != null && !item.equals(myVcsTaskHandler.getActiveTask())) { + if (item != null) { myVcsTaskHandler.switchToTask(item, createBranch); } else { diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java index 11c09894b852..3529dc1229e9 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java @@ -413,7 +413,7 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe ArrayList infos = new ArrayList(); VcsTaskHandler[] handlers = VcsTaskHandler.getAllHandlers(myProject); for (VcsTaskHandler handler : handlers) { - VcsTaskHandler.TaskInfo[] tasks = handler.getCurrentTasks(); + VcsTaskHandler.TaskInfo[] tasks = handler.getAllExistingTasks(); for (VcsTaskHandler.TaskInfo info : tasks) { infos.addAll(ContainerUtil.filter(BranchInfo.fromTaskInfo(info, false), new Condition() { @Override @@ -434,22 +434,24 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe } private static VcsTaskHandler.TaskInfo fromBranches(List branches) { + if (branches.isEmpty()) return new VcsTaskHandler.TaskInfo(null, Collections.emptyList()); MultiMap map = new MultiMap(); for (BranchInfo branch : branches) { map.putValue(branch.name, branch.repository); } - return new VcsTaskHandler.TaskInfo(map); + Map.Entry> next = map.entrySet().iterator().next(); + return new VcsTaskHandler.TaskInfo(next.getKey(), next.getValue()); } public void createBranch(LocalTask task, LocalTask previousActive, String name) { VcsTaskHandler[] handlers = VcsTaskHandler.getAllHandlers(myProject); for (VcsTaskHandler handler : handlers) { - VcsTaskHandler.TaskInfo info = handler.getActiveTask(); + VcsTaskHandler.TaskInfo[] info = handler.getCurrentTasks(); if (previousActive != null && previousActive.getBranches(false).isEmpty()) { addBranches(previousActive, info, false); } addBranches(task, info, true); - addBranches(task, handler.startNewTask(name), false); + addBranches(task, new VcsTaskHandler.TaskInfo[] { handler.startNewTask(name) }, false); } } @@ -463,10 +465,12 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe } } - private static void addBranches(LocalTask task, VcsTaskHandler.TaskInfo info, boolean original) { - List branchInfos = BranchInfo.fromTaskInfo(info, original); - for (BranchInfo branchInfo : branchInfos) { - task.addBranch(branchInfo); + private static void addBranches(LocalTask task, VcsTaskHandler.TaskInfo[] info, boolean original) { + for (VcsTaskHandler.TaskInfo taskInfo : info) { + List branchInfos = BranchInfo.fromTaskInfo(taskInfo, original); + for (BranchInfo branchInfo : branchInfos) { + task.addBranch(branchInfo); + } } } diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/GitTaskBranchesTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/GitTaskBranchesTest.java index 3a5f52f78fff..223466efd615 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/GitTaskBranchesTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/GitTaskBranchesTest.java @@ -58,7 +58,7 @@ public class GitTaskBranchesTest extends TaskBranchesTest { @Override protected int getNumberOfBranches(@NotNull Repository repository) { - return repository instanceof GitRepository ? ((GitRepository)repository).getBranches().getLocalBranches().size() : 0; + return ((GitRepository)repository).getBranches().getLocalBranches().size(); } @Override diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskBranchesTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskBranchesTest.java index 95d93a5a3dcb..38475d68f943 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskBranchesTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskBranchesTest.java @@ -37,6 +37,7 @@ import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; +import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -62,9 +63,15 @@ public abstract class TaskBranchesTest extends PlatformTestCase { assertEquals(1, handlers.length); VcsTaskHandler handler = handlers[0]; - VcsTaskHandler.TaskInfo defaultInfo = handler.getActiveTask(); + VcsTaskHandler.TaskInfo defaultInfo = handler.getAllExistingTasks()[0]; + assertEquals(defaultBranchName, defaultInfo.getName()); + assertEquals(2, defaultInfo.getRepositories().size()); + final String first = "first"; VcsTaskHandler.TaskInfo firstInfo = handler.startNewTask(first); + assertEquals(first, firstInfo.getName()); + assertEquals(2, firstInfo.getRepositories().size()); + assertEquals(2, getNumberOfBranches(repository)); assertEquals(first, repository.getCurrentBranchName()); @@ -199,6 +206,24 @@ public abstract class TaskBranchesTest extends PlatformTestCase { assertEquals(2, getNumberOfBranches(repository)); } + public void _testCurrentTasks() throws Exception { + initRepositories("foo", "bar"); + VcsTaskHandler handler = VcsTaskHandler.getAllHandlers(getProject())[0]; + VcsTaskHandler.TaskInfo[] tasks = handler.getAllExistingTasks(); + assertEquals(1, tasks.length); + VcsTaskHandler.TaskInfo defaultTask = tasks[0]; + assertEquals(1, handler.getCurrentTasks().length); + + VcsTaskHandler.TaskInfo task = handler.startNewTask("new"); + assertEquals(2, handler.getAllExistingTasks().length); + assertEquals(1, handler.getCurrentTasks().length); + + handler.closeTask(task, defaultTask); + VcsTaskHandler.TaskInfo[] existingTasks = handler.getAllExistingTasks(); + assertEquals(Arrays.asList(existingTasks).toString(), 1, existingTasks.length); + assertEquals(1, handler.getCurrentTasks().length); + } + private List initRepositories(String... names) { return ContainerUtil.map(names, new Function() { @Override From 7cec7ec696552b9368b44411b6c80b3fa5457218 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 20 Jan 2015 16:12:59 +0300 Subject: [PATCH 31/47] IDEA-135382 Provide unified capitalization --- .../src/com/intellij/tasks/generic/GenericRepositoryEditor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.java index c677744fe958..0d1c68c49ac1 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.java @@ -106,7 +106,7 @@ public class GenericRepositoryEditor extends BaseRe installListener(myTasksListURLText); installListener(mySingleTaskURLText); installListener(myDownloadTasksInSeparateRequests); - myTabbedPane.addTab("Server configuration", myPanel); + myTabbedPane.addTab("Server Configuration", myPanel); // Put appropriate configuration components on the card panel ResponseHandler xmlHandler = myRepository.getResponseHandler(ResponseType.XML); From bca58728adbb75587b2a8cecaec15dc878b39c8f Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Jan 2015 14:29:47 +0300 Subject: [PATCH 32/47] assertion when creating list with extremely small size --- .../intellij/psi/refResolve/PersistentIntList.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/refResolve/PersistentIntList.java b/java/java-impl/src/com/intellij/psi/refResolve/PersistentIntList.java index 03d0ee883d47..d3fc1e65486c 100644 --- a/java/java-impl/src/com/intellij/psi/refResolve/PersistentIntList.java +++ b/java/java-impl/src/com/intellij/psi/refResolve/PersistentIntList.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,17 +44,17 @@ class PersistentIntList implements Disposable { public PersistentIntList(@NotNull File dataFile, int initialSize) throws IOException { data = new RandomAccessFile(dataFile, "rw").getChannel(); int pointersBase; - int initialCapacity = initialSize + 256; - if (initialSize != 0) { + int initialCapacity = Math.min((initialSize+1)*2, initialSize + 256); + if (initialSize == 0) { + pointersBase = readInt(data, 0); + } + else { writeInt(data, 0, 4); // base of the pointers array writeInt(data, 4, initialSize); writeInt(data, 8, initialCapacity); fillWithZeros(data, 4 + 8, initialCapacity *4); pointersBase = 4; } - else { - pointersBase = readInt(data, 0); - } pointers = new IntArray(data, pointersBase); if (initialSize != 0) { assert pointers.size == initialSize; From b188597eedcc095488fc37924077223077f11eff Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Jan 2015 16:24:27 +0300 Subject: [PATCH 33/47] javadoc --- .../daemon/LineMarkerProvider.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerProvider.java b/platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerProvider.java index 6165561ae1f1..e0c90ef34eeb 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerProvider.java +++ b/platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +28,26 @@ import java.util.List; */ public interface LineMarkerProvider { @Nullable + /** + * Get line markers for this PsiElement. + * + * NOTE for implementers: + * Please return line marker info for exact element you were asked for. + * For example, do not return class marker info if getLineMarkerInfo() was called for a method. + * Please return relevant line marker info for as small element as possible. + * For example, do not return method marker for PsiMethod. Instead, return it for the PsiIdentifier which is a name of this method. + * + * More technical details: + * Inspection (specifically, LineMarkersPass) for performance reasons queries all LineMarkerProviders in two passes: + * - first pass for all elements in visible area + * - second pass for all the rest elements + * If providers return nothing for either area, its line markers are cleared. + * So if, for example a method, is half-visible (e.g. its name is visible but a part of its body isn't) and + * some poorly written LineMarkerProvider returns info for the PsiMethod instead of PsiIdentifier then following happens: + * - the first pass removes line marker info because whole PsiMethod is not visible. + * - the second pass tries to add line marker info back because LineMarkerProvider is called for the PsiMethod at last. + * As a result, line marker icon blinks annoyingly. + */ LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element); void collectSlowLineMarkers(@NotNull List elements, @NotNull Collection result); From faac404fdc6653c489750ab33c74db61bf4f98a8 Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Tue, 20 Jan 2015 16:31:59 +0300 Subject: [PATCH 34/47] ActionPlace.JS_BUILD_TOOL_POPUP added --- .../src/com/intellij/openapi/actionSystem/ActionPlaces.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java index 7c0006c9a3e7..d899d533f052 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java @@ -81,7 +81,7 @@ public abstract class ActionPlaces { public static final String ANT_MESSAGES_TOOLBAR = "AntMessagesToolbar"; public static final String ANT_EXPLORER_POPUP = "AntExplorerPopup"; public static final String ANT_EXPLORER_TOOLBAR = "AntExplorerToolbar"; - public static final String GULP_VIEW_POPUP = "JavaScriptGulpPopup"; + public static final String JS_BUILD_TOOL_POPUP = "JavaScriptBuildTool"; //todo: probably these context should be splitted into several contexts public static final String CODE_INSPECTION = "CodeInspection"; @@ -143,7 +143,7 @@ public abstract class ActionPlaces { FILEVIEW_POPUP, CHECKOUT_POPUP, LVCS_DIRECTORY_HISTORY_POPUP, GUI_DESIGNER_EDITOR_POPUP, GUI_DESIGNER_COMPONENT_TREE_POPUP, GUI_DESIGNER_PROPERTY_INSPECTOR_POPUP, CREATE_EJB_POPUP, CHANGES_VIEW_POPUP, REMOTE_HOST_VIEW_POPUP, REMOTE_HOST_DIALOG_POPUP, TFS_TREE_POPUP, - ACTION_PLACE_VCS_QUICK_LIST_POPUP_ACTION, PHING_EXPLORER_POPUP, NAVIGATION_BAR_POPUP, GULP_VIEW_POPUP + ACTION_PLACE_VCS_QUICK_LIST_POPUP_ACTION, PHING_EXPLORER_POPUP, NAVIGATION_BAR_POPUP, JS_BUILD_TOOL_POPUP }; public static boolean isPopupPlace(@NotNull String place) { From e84e27c43200936aa555072c54d39bc5db6bc56c Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Tue, 20 Jan 2015 16:39:36 +0300 Subject: [PATCH 35/47] vcs: scroll to line for annotate-from-annotate --- .../util/src/com/intellij/util/diff/Diff.java | 19 ++++++++----- .../openapi/vcs/AbstractVcsHelper.java | 2 ++ .../actions/AnnotateRevisionActionBase.java | 28 +++++++++++++++++-- .../vcs/impl/AbstractVcsHelperImpl.java | 6 +++- .../tests/git4idea/test/MockVcsHelper.java | 5 ++++ .../zmlx/hg4idea/test/HgMockVcsHelper.java | 4 +++ 6 files changed, 53 insertions(+), 11 deletions(-) diff --git a/platform/util/src/com/intellij/util/diff/Diff.java b/platform/util/src/com/intellij/util/diff/Diff.java index d41175fb3a98..db71cb5ccdcd 100644 --- a/platform/util/src/com/intellij/util/diff/Diff.java +++ b/platform/util/src/com/intellij/util/diff/Diff.java @@ -119,11 +119,13 @@ public class Diff { * @return translated line if the processing is ok; negative value otherwise */ public static int translateLine(@NotNull CharSequence before, @NotNull CharSequence after, int line) throws FilesTooBigForDiffException { + return translateLine(before, after, line, false); + } + + public static int translateLine(@NotNull CharSequence before, @NotNull CharSequence after, int line, boolean approximate) + throws FilesTooBigForDiffException { Change change = buildChanges(before, after); - if (change == null) { - return -1; - } - return translateLine(change, line); + return translateLine(change, line, approximate); } /** @@ -133,17 +135,20 @@ public class Diff { * @param line target line before change * @return translated line if the processing is ok; negative value otherwise */ - public static int translateLine(@NotNull Change change, int line) { + public static int translateLine(@Nullable Change change, int line) { + return translateLine(change, line, false); + } + + public static int translateLine(@Nullable Change change, int line, boolean approximate) { int result = line; Change currentChange = change; - while (currentChange != null) { if (line < currentChange.line0) break; if (line >= currentChange.line0 + currentChange.deleted) { result += currentChange.inserted - currentChange.deleted; } else { - return -1; + if (approximate) return currentChange.line1; } currentChange = currentChange.link; diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcsHelper.java b/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcsHelper.java index 0d76538eb978..1d2cadb6a532 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcsHelper.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcsHelper.java @@ -71,6 +71,8 @@ public abstract class AbstractVcsHelper { public abstract void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs); + public abstract void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs, int line); + public abstract void showDifferences(final VcsFileRevision cvsVersionOn, final VcsFileRevision cvsVersionOn1, final File file); public abstract void showChangesListBrowser(CommittedChangeList changelist, @Nls String title); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionActionBase.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionActionBase.java index 84331cdafdf5..15ed9ee1481c 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionActionBase.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionActionBase.java @@ -2,6 +2,8 @@ package com.intellij.openapi.vcs.actions; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; @@ -15,6 +17,8 @@ import com.intellij.openapi.vcs.impl.BackgroundableActionEnabledHandler; import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl; import com.intellij.openapi.vcs.impl.VcsBackgroundableActions; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.diff.Diff; +import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -60,7 +64,7 @@ public abstract class AnnotateRevisionActionBase extends AnAction { } @Override - public void actionPerformed(@NotNull AnActionEvent e) { + public void actionPerformed(@NotNull final AnActionEvent e) { final VcsFileRevision fileRevision = getFileRevision(e); final VirtualFile file = getFile(e); final AbstractVcs vcs = getVcs(e); @@ -68,10 +72,15 @@ public abstract class AnnotateRevisionActionBase extends AnAction { assert file != null; assert fileRevision != null; + final Editor editor = e.getData(CommonDataKeys.EDITOR); + final CharSequence oldContent = editor == null ? null : editor.getDocument().getImmutableCharSequence(); + final int oldLine = editor == null ? 0 : editor.getCaretModel().getLogicalPosition().line; + final AnnotationProvider annotationProvider = vcs.getCachingAnnotationProvider(); assert annotationProvider != null; final Ref fileAnnotationRef = new Ref(); + final Ref newLineRef = new Ref(); final Ref exceptionRef = new Ref(); final ProjectLevelVcsManagerImpl plVcsManager = (ProjectLevelVcsManagerImpl)ProjectLevelVcsManager.getInstance(vcs.getProject()); @@ -82,7 +91,20 @@ public abstract class AnnotateRevisionActionBase extends AnAction { BackgroundFromStartOption.getInstance()) { public void run(@NotNull ProgressIndicator indicator) { try { - fileAnnotationRef.set(annotationProvider.annotate(file, fileRevision)); + FileAnnotation fileAnnotation = annotationProvider.annotate(file, fileRevision); + + int newLine = oldLine; + if (oldContent != null) { + String content = fileAnnotation.getAnnotatedContent(); + try { + newLine = Diff.translateLine(oldContent, content, oldLine); + } + catch (FilesTooBigForDiffException ignore) { + } + } + + fileAnnotationRef.set(fileAnnotation); + newLineRef.set(newLine); } catch (VcsException e) { exceptionRef.set(e); @@ -103,7 +125,7 @@ public abstract class AnnotateRevisionActionBase extends AnAction { } if (fileAnnotationRef.isNull()) return; - AbstractVcsHelper.getInstance(myProject).showAnnotation(fileAnnotationRef.get(), file, vcs); + AbstractVcsHelper.getInstance(myProject).showAnnotation(fileAnnotationRef.get(), file, vcs, newLineRef.get()); } }); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/AbstractVcsHelperImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/AbstractVcsHelperImpl.java index 4dfbc258a191..c616c0d4eaf4 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/AbstractVcsHelperImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/AbstractVcsHelperImpl.java @@ -375,7 +375,11 @@ public class AbstractVcsHelperImpl extends AbstractVcsHelper { } public void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs) { - OpenFileDescriptor openFileDescriptor = new OpenFileDescriptor(myProject, file); + showAnnotation(annotation, file, vcs, 0); + } + + public void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs, int line) { + OpenFileDescriptor openFileDescriptor = new OpenFileDescriptor(myProject, file, line, 0); Editor editor = FileEditorManager.getInstance(myProject).openTextEditor(openFileDescriptor, true); if (editor == null) { Messages.showMessageDialog(VcsBundle.message("message.text.cannot.open.editor", file.getPresentableUrl()), diff --git a/plugins/git4idea/tests/git4idea/test/MockVcsHelper.java b/plugins/git4idea/tests/git4idea/test/MockVcsHelper.java index 45f1e3965bea..c65a0f0ddaa8 100644 --- a/plugins/git4idea/tests/git4idea/test/MockVcsHelper.java +++ b/plugins/git4idea/tests/git4idea/test/MockVcsHelper.java @@ -67,6 +67,11 @@ public class MockVcsHelper extends AbstractVcsHelper { throw new UnsupportedOperationException(); } + @Override + public void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs, int line) { + throw new UnsupportedOperationException(); + } + @Override public void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs) { throw new UnsupportedOperationException(); diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMockVcsHelper.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMockVcsHelper.java index 6e2414f53125..cad97728affa 100644 --- a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMockVcsHelper.java +++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMockVcsHelper.java @@ -68,6 +68,10 @@ public class HgMockVcsHelper extends AbstractVcsHelper { return null; } + @Override + public void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs, int line) { + } + @Override public void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs) { } From 785bf291ccfd595280f749a3999625ca4ac59a75 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 20 Jan 2015 14:58:15 +0100 Subject: [PATCH 36/47] remove Shift+Alt+9 from XWin keymap --- platform/platform-resources/src/idea/Keymap_XWin.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/platform-resources/src/idea/Keymap_XWin.xml b/platform/platform-resources/src/idea/Keymap_XWin.xml index a07c052b514a..7daa90cfee8c 100644 --- a/platform/platform-resources/src/idea/Keymap_XWin.xml +++ b/platform/platform-resources/src/idea/Keymap_XWin.xml @@ -7,6 +7,9 @@ + + + From bb40bb36144288a004bae2b46715ce52d22673c9 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Tue, 20 Jan 2015 17:29:23 +0300 Subject: [PATCH 37/47] IDEA-135419 Git: Force Push: html tags from the confirmation dialog fixed --- .../intellij/dvcs/push/PushController.java | 84 +++++++++++-------- 1 file changed, 47 insertions(+), 37 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java index c35f94c047b6..76d0e5bfd061 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java @@ -36,6 +36,7 @@ import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.xml.util.XmlStringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -548,46 +549,15 @@ public class PushController implements Disposable { final PushSupport activePushSupport = selectedModel.getSupport(); final PushTarget commonTarget = getCommonTarget(selectedNodes); if (commonTarget != null && activePushSupport.isSilentForcePushAllowed(commonTarget)) return true; - return Messages.showOkCancelDialog(myProject, DvcsBundle.message("push.force.confirmation.text", - commonTarget != null - ? " to " + - commonTarget.getPresentation() + "" - : ""), + return Messages.showOkCancelDialog(myProject, XmlStringUtil.wrapInHtml(DvcsBundle.message("push.force.confirmation.text", + commonTarget != null + ? " to " + + commonTarget.getPresentation() + "" + : "")), "Force Push", "&Force Push", CommonBundle.getCancelButtonText(), Messages.getWarningIcon(), - commonTarget != null - ? new DialogWrapper.DoNotAskOption() { - - @Override - public boolean isToBeShown() { - return true; - } - - @Override - public void setToBeShown(boolean toBeShown, int exitCode) { - if (!toBeShown && exitCode == OK) { - activePushSupport.saveSilentForcePushTarget(commonTarget); - } - } - - @Override - public boolean canBeHidden() { - return true; - } - - @Override - public boolean shouldSaveOptionsOnCancel() { - return false; - } - - @NotNull - @Override - public String getDoNotShowMessage() { - return "Don't warn about this target"; - } - } - : null) == OK; + commonTarget != null ? new MyDoNotAskOptionForPush(activePushSupport, commonTarget) : null) == OK; } @Nullable @@ -689,4 +659,44 @@ public class PushController implements Disposable { return myCheckBoxModel; } } + + private static class MyDoNotAskOptionForPush implements DialogWrapper.DoNotAskOption { + + @NotNull private final PushSupport myActivePushSupport; + @NotNull private final PushTarget myCommonTarget; + + public MyDoNotAskOptionForPush(@NotNull PushSupport support, + @NotNull PushTarget target) { + myActivePushSupport = support; + myCommonTarget = target; + } + + @Override + public boolean isToBeShown() { + return true; + } + + @Override + public void setToBeShown(boolean toBeShown, int exitCode) { + if (!toBeShown && exitCode == OK) { + myActivePushSupport.saveSilentForcePushTarget(myCommonTarget); + } + } + + @Override + public boolean canBeHidden() { + return true; + } + + @Override + public boolean shouldSaveOptionsOnCancel() { + return false; + } + + @NotNull + @Override + public String getDoNotShowMessage() { + return "Don't warn about this target"; + } + } } From d715be6152717c52b3455baa3e43b37fa86ef2ad Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Tue, 20 Jan 2015 17:35:20 +0300 Subject: [PATCH 38/47] maven: JB maven proxy server for internal use was changed, see page history at https://confluence.jetbrains.com/display/JBINT/Maven+proxy+server --- .../test/java/org/jetbrains/idea/maven/MavenTestCase.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java index 8b33581b0eb6..40e52ea00d5a 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java @@ -323,12 +323,14 @@ public abstract class MavenTestCase extends UsefulTestCase { private static String createSettingsXmlContent(String content) { String mirror = System.getProperty("idea.maven.test.mirror", - "http://maven.labs.intellij.net:8081/nexus/content/groups/public/"); + // use JB maven proxy server for internal use by default, see details at + // https://confluence.jetbrains.com/display/JBINT/Maven+proxy+server + "http://maven.labs.intellij.net/remote-repos/"); return "" + content + "" + " " + - " Nexus" + + " jb-central-proxy" + " " + mirror + "" + " *" + " " + From db3a08b145387e040a8f192483b91301386dc6fe Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 20 Jan 2015 12:07:19 +0100 Subject: [PATCH 39/47] escape copyright keyword to use in regexp (IDEA-135402) --- .../maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java b/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java index f40b3245891d..acc201e6ff81 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java @@ -120,7 +120,7 @@ public abstract class UpdatePsiFileCopyright extends AbstractUpdateCopyright { final LinkedHashSet found = new LinkedHashSet(); Document doc = null; if (!StringUtil.isEmpty(keyword)) { - Pattern pattern = Pattern.compile(keyword, Pattern.CASE_INSENSITIVE); + Pattern pattern = Pattern.compile(StringUtil.escapeToRegexp(keyword), Pattern.CASE_INSENSITIVE); doc = FileDocumentManager.getInstance().getDocument(getFile().getVirtualFile()); for (int i = 0; i < comments.size(); i++) { PsiComment comment = comments.get(i); From 5b62d34d11fc688bedbe85eb8f7f83ed22c7b17f Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 20 Jan 2015 12:40:25 +0100 Subject: [PATCH 40/47] switch context when get to anonymous class so access to the inherited members should not be raised as a conflict; super expression --- .../com/intellij/refactoring/util/RefactoringConflictsUtil.java | 2 +- .../accessibleViaInheritanceInsideAnonymousClass/after/b/B.java | 1 + .../before/a/A.java | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java index bc0148ff44f4..19a6be869c43 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java @@ -161,7 +161,7 @@ public class RefactoringConflictsUtil { PsiElement refElement = refExpr.resolve(); if (refElement instanceof PsiMember) { PsiExpression qualifier = refExpr.getQualifierExpression(); - PsiClass qualifierAccessClass = (PsiClass)(qualifier != null ? PsiUtil.getAccessObjectClass(qualifier).getElement() : accessClass); + PsiClass qualifierAccessClass = (PsiClass)(qualifier != null && !(qualifier instanceof PsiSuperExpression) ? PsiUtil.getAccessObjectClass(qualifier).getElement() : accessClass); if (!RefactoringHierarchyUtil.willBeInTargetClass(refElement, moving, targetClass, false) && (qualifierAccessClass == null || !RefactoringHierarchyUtil.willBeInTargetClass(qualifierAccessClass, moving, targetClass, false))) { checkAccessibility((PsiMember)refElement, context, qualifierAccessClass, member, conflicts); diff --git a/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/after/b/B.java b/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/after/b/B.java index bf1f35b90535..eed100e87513 100644 --- a/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/after/b/B.java +++ b/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/after/b/B.java @@ -6,6 +6,7 @@ public class B { void method2Move() { new A.I() { { + super.foo(); foo(); A.bar(); } diff --git a/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/before/a/A.java b/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/before/a/A.java index efa03290b9da..4e75f05ef8ec 100644 --- a/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/before/a/A.java +++ b/java/java-tests/testData/refactoring/pullUp/accessibleViaInheritanceInsideAnonymousClass/before/a/A.java @@ -4,6 +4,7 @@ public class A extends B { void method2Move() { new I() { { + super.foo(); foo(); bar(); } From e66bca36cc4770122581d040069feab89666b248 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 20 Jan 2015 15:39:38 +0100 Subject: [PATCH 41/47] ensure java.system.class.loader is set to UrlClassLoader for idea project --- plugins/devkit/src/run/JUnitDevKitPatcher.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/devkit/src/run/JUnitDevKitPatcher.java b/plugins/devkit/src/run/JUnitDevKitPatcher.java index cc274f031133..aa4b741e310f 100644 --- a/plugins/devkit/src/run/JUnitDevKitPatcher.java +++ b/plugins/devkit/src/run/JUnitDevKitPatcher.java @@ -21,12 +21,14 @@ import com.intellij.execution.configurations.ParametersList; import com.intellij.openapi.module.Module; import com.intellij.openapi.projectRoots.JavaSdkType; import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.util.lang.UrlClassLoader; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.devkit.module.PluginModuleType; import org.jetbrains.idea.devkit.projectRoots.IdeaJdk; import org.jetbrains.idea.devkit.projectRoots.Sandbox; import org.jetbrains.idea.devkit.util.DescriptorUtil; +import org.jetbrains.idea.devkit.util.PsiUtil; import java.io.File; import java.io.IOException; @@ -36,8 +38,13 @@ import java.io.IOException; * Date: Mar 4, 2005 */ public class JUnitDevKitPatcher extends JUnitPatcher{ + public static final String JAVA_SYSTEM_CLASS_LOADER_PROPERTY = "-Djava.system.class.loader"; public void patchJavaParameters(@Nullable Module module, JavaParameters javaParameters) { + if (module != null && PsiUtil.isIdeaProject(module.getProject()) && + !javaParameters.getVMParametersList().hasParameter(JAVA_SYSTEM_CLASS_LOADER_PROPERTY)) { + javaParameters.getVMParametersList().add(JAVA_SYSTEM_CLASS_LOADER_PROPERTY + "=" + UrlClassLoader.class.getName()); + } Sdk jdk = javaParameters.getJdk(); jdk = IdeaJdk.findIdeaJdk(jdk); if (jdk == null) return; From 853be218500194c60eb027408506ad0893fbfaab Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Jan 2015 15:57:53 +0100 Subject: [PATCH 42/47] restore public access for class used in Kotlin --- .../intellij/util/containers/ConcurrentSoftValueHashMap.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentSoftValueHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentSoftValueHashMap.java index b02753f0bcc2..a63cff46167b 100644 --- a/platform/util/src/com/intellij/util/containers/ConcurrentSoftValueHashMap.java +++ b/platform/util/src/com/intellij/util/containers/ConcurrentSoftValueHashMap.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ import java.util.Map; * Null values are NOT allowed * @deprecated Use {@link ContainerUtil#createConcurrentSoftValueMap()} instead */ -final class ConcurrentSoftValueHashMap extends ConcurrentRefValueHashMap { +public final class ConcurrentSoftValueHashMap extends ConcurrentRefValueHashMap { public ConcurrentSoftValueHashMap(@NotNull Map map) { super(map); } From 37d8a7343b68646d7e948fd2eeee846e833f95cb Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 20 Jan 2015 16:07:03 +0100 Subject: [PATCH 43/47] remove cyclic test dependency (prevent me from compilation with language level 8) --- .../com/intellij/util/containers/ConcurrentMapsTest.java | 0 .../testSrc/com/intellij/util/containers/WeakListTest.java | 0 platform/util/util.iml | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) rename platform/{util => platform-tests}/testSrc/com/intellij/util/containers/ConcurrentMapsTest.java (100%) rename platform/{util => platform-tests}/testSrc/com/intellij/util/containers/WeakListTest.java (100%) diff --git a/platform/util/testSrc/com/intellij/util/containers/ConcurrentMapsTest.java b/platform/platform-tests/testSrc/com/intellij/util/containers/ConcurrentMapsTest.java similarity index 100% rename from platform/util/testSrc/com/intellij/util/containers/ConcurrentMapsTest.java rename to platform/platform-tests/testSrc/com/intellij/util/containers/ConcurrentMapsTest.java diff --git a/platform/util/testSrc/com/intellij/util/containers/WeakListTest.java b/platform/platform-tests/testSrc/com/intellij/util/containers/WeakListTest.java similarity index 100% rename from platform/util/testSrc/com/intellij/util/containers/WeakListTest.java rename to platform/platform-tests/testSrc/com/intellij/util/containers/WeakListTest.java diff --git a/platform/util/util.iml b/platform/util/util.iml index 684449e02d43..c015e73f13b3 100644 --- a/platform/util/util.iml +++ b/platform/util/util.iml @@ -24,7 +24,6 @@ - @@ -178,4 +177,5 @@ - \ No newline at end of file + + From cc12765efbb8568f11f90f1a079d76ebed364fc4 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Tue, 20 Jan 2015 18:10:38 +0300 Subject: [PATCH 44/47] vcs: fix typo --- platform/util/src/com/intellij/util/diff/Diff.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/util/diff/Diff.java b/platform/util/src/com/intellij/util/diff/Diff.java index db71cb5ccdcd..2e38bec801ad 100644 --- a/platform/util/src/com/intellij/util/diff/Diff.java +++ b/platform/util/src/com/intellij/util/diff/Diff.java @@ -148,7 +148,7 @@ public class Diff { if (line >= currentChange.line0 + currentChange.deleted) { result += currentChange.inserted - currentChange.deleted; } else { - if (approximate) return currentChange.line1; + return approximate ? currentChange.line1 : -1; } currentChange = currentChange.link; From d1a9d2810a84d21636b160eb1f61d263649ecfe6 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Tue, 20 Jan 2015 18:23:07 +0300 Subject: [PATCH 45/47] vcs: use approximate diff in annotate-from-annotate scroll editor to 'good enough' position --- .../openapi/vcs/actions/AnnotateRevisionActionBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionActionBase.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionActionBase.java index 15ed9ee1481c..32df4bbb77ad 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionActionBase.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionActionBase.java @@ -97,7 +97,7 @@ public abstract class AnnotateRevisionActionBase extends AnAction { if (oldContent != null) { String content = fileAnnotation.getAnnotatedContent(); try { - newLine = Diff.translateLine(oldContent, content, oldLine); + newLine = Diff.translateLine(oldContent, content, oldLine, true); } catch (FilesTooBigForDiffException ignore) { } From 5019dfccec900b0d870997f899b27ce979e0052f Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 20 Jan 2015 18:39:21 +0300 Subject: [PATCH 46/47] decompiler: fixed inner class constructor signature decompilation --- .../java/decompiler/main/ClassWriter.java | 20 +++-- .../java/decompiler/SingleClassesTest.java | 1 + .../pkg/TestInnerSignature$Inner.class | Bin 0 -> 610 bytes .../pkg/TestInnerSignature$InnerStatic.class | Bin 0 -> 637 bytes .../classes/pkg/TestInnerSignature.class | Bin 0 -> 683 bytes .../testData/results/TestInnerSignature.dec | 70 ++++++++++++++++++ .../testData/src/pkg/TestInnerSignature.java | 51 +++++++++++++ 7 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestInnerSignature$Inner.class create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestInnerSignature$InnerStatic.class create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestInnerSignature.class create mode 100644 plugins/java-decompiler/engine/testData/results/TestInnerSignature.dec create mode 100644 plugins/java-decompiler/engine/testData/src/pkg/TestInnerSignature.java diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java index a996eb8b554c..cc7f2dde2c23 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -639,7 +639,16 @@ public class ClassWriter { descriptor = GenericMain.parseMethodSignature(attr.getSignature()); if (descriptor != null) { int actualParams = md.params.length; - if (isEnum && init) actualParams -= 2; + List sigFields = methodWrapper.signatureFields; + if (sigFields != null) { + actualParams = 0; + for (VarVersionPair field : methodWrapper.signatureFields) { + if (field == null) { + actualParams++; + } + } + } + else if (isEnum && init) actualParams -= 2; if (actualParams != descriptor.params.size()) { String message = "Inconsistent generic signature in method " + mt.getName() + " " + mt.getDescriptor(); DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN); @@ -685,10 +694,11 @@ public class ClassWriter { boolean firstParameter = true; int index = isEnum && init ? 3 : thisVar ? 1 : 0; - int start = isEnum && init && descriptor == null ? 2 : 0; - int params = descriptor == null ? md.params.length : descriptor.params.size(); + boolean hasDescriptor = descriptor != null; + int start = isEnum && init && !hasDescriptor ? 2 : 0; + int params = hasDescriptor ? descriptor.params.size() : md.params.length; for (int i = start; i < params; i++) { - if (signFields == null || signFields.get(i) == null) { + if (hasDescriptor || (signFields == null || signFields.get(i) == null)) { if (!firstParameter) { buffer.append(", "); } diff --git a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java index 62fef0a8a7fa..a65ab26441f1 100644 --- a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -58,4 +58,5 @@ public class SingleClassesTest extends SingleClassesTestBase { @Test public void testAnonymousClass() { doTest("pkg/TestAnonymousClass"); } @Test public void testThrowException() { doTest("pkg/TestThrowException"); } @Test public void testInnerLocal() { doTest("pkg/TestInnerLocal"); } + @Test public void testInnerSignature() { doTest("pkg/TestInnerSignature"); } } diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestInnerSignature$Inner.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestInnerSignature$Inner.class new file mode 100644 index 0000000000000000000000000000000000000000..d335f61d6f41d82b1c10e3899465101d5982de53 GIT binary patch literal 610 zcma)(%TB^j5QhH)g<7mq5xIHgmSDZ$!kxxMNK8yn7ZCR?HdulsX^ZdWqA_vd1NczJ z|1^Y!xNy;#f2K2YzH{d5`{NV9Ihq>MC}*IeBGtAuJJRf`*jG^#5SBo$H@04__Qdi= z?FW1848scnt?!OJE1da`Kyq-+jIgEZNHvtIOO+0v-Jo$MknatgAiVWF$6qwc|Cg@k zhF1c2t-lJE5B^W)@KHeNPM=7Y?YW+FKYOtqe_+`YX7mrlBZg&z+GnW++3r6tEAUSmw8MVvJZiOnn*LiSDe@CkXV*ESfijwNf&wQMS(QMElwg(%#U2hIegM~Cd#V5c literal 0 HcmV?d00001 diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestInnerSignature$InnerStatic.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestInnerSignature$InnerStatic.class new file mode 100644 index 0000000000000000000000000000000000000000..2bd775bc27a377081b540e9fd09e821d9a4dd787 GIT binary patch literal 637 zcma)3%TB^j5IvVyp;SOX@rhzwU=`5BjY>$MiHQkO6Nvj38&ZNLX^a2mf|$7Q1N}yBLmHM_H+_%>t*Gs~54xya@Bl^eU_4*v2kWU%yU?H2?qr literal 0 HcmV?d00001 diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestInnerSignature.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestInnerSignature.class new file mode 100644 index 0000000000000000000000000000000000000000..e2f948978059ff410185daba9e079b7247c94fee GIT binary patch literal 683 zcma)3T}uK{5Iy79rmksfrhQumY9GGzQi-5K5J&}z@2f4cVk_v{|LQ@49{K_OsOVfR zq1K>>ojd33+&Od4ynnpD0XWA|2mx#d;m3{&yDIEy*w>KNa3BcZ*tR)pI)-C)1^Nut z2gZ18jx`(#{4+)%h9KVP8&5`QVA#FVU8iq$ohw1GY4vQwnT$+KSrsiY- { + A a; + B b; + C c; + + public TestInnerSignature(A var1, B var2, C var3) { + this.a = var1;// 23 + this.b = var2;// 24 + this.c = var3;// 25 + } + + public static class InnerStatic { + A a; + B b; + C c; + + public InnerStatic(A var1, B var2, C var3) { + this.a = var1;// 46 + this.b = var2;// 47 + this.c = var3;// 48 + } + } + + public class Inner { + A a; + B b; + C c; + + public Inner(A var1, B var2, C var3) { + this.a = var2;// 34 + this.b = var3;// 35 + this.c = var4;// 36 + } + } +} + +class 'TestInnerSignature' { + method ' (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V' { + 6 6 + b 7 + 10 8 + } +} + +class 'TestInnerSignature$InnerStatic' { + method ' (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V' { + 6 17 + b 18 + 10 19 + } +} + +class 'TestInnerSignature$Inner' { + method ' (LTestInnerSignature;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V' { + b 29 + 10 30 + 16 31 + } +} + +Lines mapping: +23 <-> 7 +24 <-> 8 +25 <-> 9 +34 <-> 30 +35 <-> 31 +36 <-> 32 +46 <-> 18 +47 <-> 19 +48 <-> 20 diff --git a/plugins/java-decompiler/engine/testData/src/pkg/TestInnerSignature.java b/plugins/java-decompiler/engine/testData/src/pkg/TestInnerSignature.java new file mode 100644 index 000000000000..d69f0b3521e4 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/pkg/TestInnerSignature.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +public class TestInnerSignature { + A a; + B b; + C c; + + public TestInnerSignature(A a,B b,C c) { + this.a = a; + this.b = b; + this.c = c; + } + + public class Inner { + A a; + B b; + C c; + + public Inner(A a, B b, C c) { + this.a = a; + this.b = b; + this.c = c; + } + } + + public static class InnerStatic { + A a; + B b; + C c; + + public InnerStatic(A a, B b, C c) { + this.a = a; + this.b = b; + this.c = c; + } + } +} \ No newline at end of file From 55a82ef2c1a1c4c8662bc37f9bc028c1a277aa8f Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Tue, 20 Jan 2015 19:11:52 +0300 Subject: [PATCH 47/47] IDEA-128681 Windows theme: mnemonics are not shown in dialogs --- platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java index 2bbca4d274fc..affb8e4968b3 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java @@ -974,7 +974,7 @@ public class IdeEventQueue extends EventQueue { !SystemInfo.isWindows || !Registry.is("actionSystem.win.suppressAlt") || !(UISettings.getInstance().HIDE_TOOL_STRIPES || UISettings.getInstance().PRESENTATION_MODE)) { - return true; + return false; } if (ke.getID() == KeyEvent.KEY_PRESSED) {