From 08f5c0cf2c88df03c5fce172ce96cefb929eec1f Mon Sep 17 00:00:00 2001 From: irengrig Date: Tue, 24 Jul 2012 13:35:33 +0400 Subject: [PATCH 01/51] Svn: when activating Svn, it's better to schedule working copy cleanup not synchronously --- .../src/org/jetbrains/idea/svn/SvnVcs.java | 2425 +++++++++-------- 1 file changed, 1216 insertions(+), 1209 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java index 82a8d8e201b2..ad9ec3a3a169 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java @@ -1,1209 +1,1216 @@ -/* - * Copyright 2000-2011 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. - */ - - -package org.jetbrains.idea.svn; - -import com.intellij.ide.FrameStateListener; -import com.intellij.ide.FrameStateManager; -import com.intellij.idea.RareLogger; -import com.intellij.notification.*; -import com.intellij.notification.impl.NotificationsConfigurationImpl; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.options.Configurable; -import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.project.DumbAwareRunnable; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.startup.StartupManager; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.Trinity; -import com.intellij.openapi.vcs.*; -import com.intellij.openapi.vcs.annotate.AnnotationProvider; -import com.intellij.openapi.vcs.changes.*; -import com.intellij.openapi.vcs.checkin.CheckinEnvironment; -import com.intellij.openapi.vcs.diff.DiffProvider; -import com.intellij.openapi.vcs.history.VcsHistoryProvider; -import com.intellij.openapi.vcs.history.VcsRevisionNumber; -import com.intellij.openapi.vcs.merge.MergeProvider; -import com.intellij.openapi.vcs.rollback.RollbackEnvironment; -import com.intellij.openapi.vcs.update.UpdateEnvironment; -import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; -import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileManager; -import com.intellij.util.Processor; -import com.intellij.util.ThreeState; -import com.intellij.util.containers.Convertor; -import com.intellij.util.containers.SoftHashMap; -import com.intellij.util.messages.MessageBus; -import com.intellij.util.messages.MessageBusConnection; -import com.intellij.util.messages.Topic; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.actions.ShowPropertiesDiffWithLocalAction; -import org.jetbrains.idea.svn.actions.SvnMergeProvider; -import org.jetbrains.idea.svn.annotate.SvnAnnotationProvider; -import org.jetbrains.idea.svn.checkin.SvnCheckinEnvironment; -import org.jetbrains.idea.svn.commandLine.SvnExecutableChecker; -import org.jetbrains.idea.svn.dialogs.SvnBranchPointsCalculator; -import org.jetbrains.idea.svn.dialogs.WCInfo; -import org.jetbrains.idea.svn.history.LoadedRevisionsCache; -import org.jetbrains.idea.svn.history.SvnChangeList; -import org.jetbrains.idea.svn.history.SvnCommittedChangesProvider; -import org.jetbrains.idea.svn.history.SvnHistoryProvider; -import org.jetbrains.idea.svn.rollback.SvnRollbackEnvironment; -import org.jetbrains.idea.svn.update.SvnIntegrateEnvironment; -import org.jetbrains.idea.svn.update.SvnUpdateEnvironment; -import org.tmatesoft.sqljet.core.SqlJetErrorCode; -import org.tmatesoft.sqljet.core.SqlJetException; -import org.tmatesoft.svn.core.*; -import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; -import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory; -import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory; -import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl; -import org.tmatesoft.svn.core.internal.util.jna.SVNJNAUtil; -import org.tmatesoft.svn.core.internal.wc.SVNAdminUtil; -import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminArea14; -import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaFactory; -import org.tmatesoft.svn.core.internal.wc.admin.SVNWCAccess; -import org.tmatesoft.svn.core.io.SVNRepository; -import org.tmatesoft.svn.core.io.SVNRepositoryFactory; -import org.tmatesoft.svn.core.wc.*; -import org.tmatesoft.svn.util.SVNDebugLog; -import org.tmatesoft.svn.util.SVNDebugLogAdapter; -import org.tmatesoft.svn.util.SVNLogType; - -import java.io.File; -import java.io.UnsupportedEncodingException; -import java.util.*; -import java.util.logging.Level; - -@SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"}) -public class SvnVcs extends AbstractVcs { - private static final String KEEP_CONNECTIONS_KEY = "svn.keep.connections"; - private static final Logger REFRESH_LOG = Logger.getInstance("#svn_refresh"); - - private static final int ourLogUsualInterval = 20 * 1000; - private static final int ourLogRareInterval = 30 * 1000; - - private static final Set ourLogRarely = new HashSet( - Arrays.asList(new SVNErrorCode[]{SVNErrorCode.WC_UNSUPPORTED_FORMAT, SVNErrorCode.WC_CORRUPT, SVNErrorCode.WC_CORRUPT_TEXT_BASE, - SVNErrorCode.WC_NOT_FILE, SVNErrorCode.WC_NOT_DIRECTORY, SVNErrorCode.WC_PATH_NOT_FOUND})); - - private static final Logger LOG = wrapLogger(Logger.getInstance("org.jetbrains.idea.svn.SvnVcs")); - @NonNls public static final String VCS_NAME = "svn"; - private static final VcsKey ourKey = createKey(VCS_NAME); - public static final Topic WC_CONVERTED = new Topic("WC_CONVERTED", Runnable.class); - private final Map>>> myPropertyCache = - new SoftHashMap>>>(); - - private DefaultSVNRepositoryPool myPool; - private final SvnConfiguration myConfiguration; - private final SvnEntriesFileListener myEntriesFileListener; - - private CheckinEnvironment myCheckinEnvironment; - private RollbackEnvironment myRollbackEnvironment; - private UpdateEnvironment mySvnUpdateEnvironment; - private UpdateEnvironment mySvnIntegrateEnvironment; - private VcsHistoryProvider mySvnHistoryProvider; - private AnnotationProvider myAnnotationProvider; - private DiffProvider mySvnDiffProvider; - private final VcsShowConfirmationOption myAddConfirmation; - private final VcsShowConfirmationOption myDeleteConfirmation; - private EditFileProvider myEditFilesProvider; - private SvnCommittedChangesProvider myCommittedChangesProvider; - private final VcsShowSettingOption myCheckoutOptions; - - private ChangeProvider myChangeProvider; - private MergeProvider myMergeProvider; - private final WorkingCopiesContent myWorkingCopiesContent; - - @NonNls public static final String LOG_PARAMETER_NAME = "javasvn.log"; - public static final String pathToEntries = SvnUtil.SVN_ADMIN_DIR_NAME + File.separatorChar + SvnUtil.ENTRIES_FILE_NAME; - public static final String pathToDirProps = SvnUtil.SVN_ADMIN_DIR_NAME + File.separatorChar + SvnUtil.DIR_PROPS_FILE_NAME; - private final SvnChangelistListener myChangeListListener; - - private SvnCopiesRefreshManager myCopiesRefreshManager; - private SvnFileUrlMappingImpl myMapping; - private final MyFrameStateListener myFrameStateListener; - - public static final Topic ROOTS_RELOADED = new Topic("ROOTS_RELOADED", Runnable.class); - private VcsListener myVcsListener; - - private SvnBranchPointsCalculator mySvnBranchPointsCalculator; - - private final RootsToWorkingCopies myRootsToWorkingCopies; - private final SvnAuthenticationNotifier myAuthNotifier; - private static RareLogger.LogFilter[] ourLogFilters; - private final SvnLoadedBrachesStorage myLoadedBranchesStorage; - - public static final String SVNKIT_HTTP_SSL_PROTOCOLS = "svnkit.http.sslProtocols"; - private final SvnExecutableChecker myChecker; - - public static final Processor ourBusyExceptionProcessor = new Processor() { - @Override - public boolean process(Exception e) { - if (e instanceof SVNException) { - final SVNErrorCode errorCode = ((SVNException)e).getErrorMessage().getErrorCode(); - if (SVNErrorCode.WC_LOCKED.equals(errorCode)) { - return true; - } else if (SVNErrorCode.SQLITE_ERROR.equals(errorCode)) { - Throwable cause = ((SVNException)e).getErrorMessage().getCause(); - if (cause instanceof SqlJetException) { - return SqlJetErrorCode.BUSY.equals(((SqlJetException)cause).getErrorCode()); - } - } - } - return false; - } - }; - - public void checkCommandLineVersion() { - myChecker.checkExecutableAndNotifyIfNeeded(); - } - - static { - SVNJNAUtil.setJNAEnabled(true); - SvnHttpAuthMethodsDefaultChecker.check(); - - //noinspection UseOfArchaicSystemPropertyAccessors - final JavaSVNDebugLogger logger = new JavaSVNDebugLogger(Boolean.getBoolean(LOG_PARAMETER_NAME), LOG); - SVNDebugLog.setDefaultLog(logger); - SVNAdminAreaFactory.setSelector(new SvnFormatSelector()); - - DAVRepositoryFactory.setup(); - SVNRepositoryFactoryImpl.setup(); - FSRepositoryFactory.setup(); - - // non-optimized writing is fast enough on Linux/MacOS, and somewhat more reliable - if (SystemInfo.isWindows) { - SVNAdminArea14.setOptimizedWritingEnabled(true); - } - - if (!SVNJNAUtil.isJNAPresent()) { - LOG.warn("JNA is not found by svnkit library"); - } - initLogFilters(); - - // Alexander Kitaev says it is default value (SSLv3) - since 8254 - if (!SystemInfo.JAVA_RUNTIME_VERSION.startsWith("1.7") && System.getProperty(SVNKIT_HTTP_SSL_PROTOCOLS) == null) { - System.setProperty(SVNKIT_HTTP_SSL_PROTOCOLS, "SSLv3"); - } - } - - public SvnVcs(final Project project, MessageBus bus, SvnConfiguration svnConfiguration, final SvnLoadedBrachesStorage storage) { - super(project, VCS_NAME); - myLoadedBranchesStorage = storage; - LOG.debug("ct"); - myRootsToWorkingCopies = new RootsToWorkingCopies(myProject); - myConfiguration = svnConfiguration; - myAuthNotifier = new SvnAuthenticationNotifier(this); - - dumpFileStatus(FileStatus.ADDED); - dumpFileStatus(FileStatus.DELETED); - dumpFileStatus(FileStatus.MERGE); - dumpFileStatus(FileStatus.MODIFIED); - dumpFileStatus(FileStatus.NOT_CHANGED); - dumpFileStatus(FileStatus.UNKNOWN); - - dumpFileStatus(SvnFileStatus.REPLACED); - dumpFileStatus(SvnFileStatus.EXTERNAL); - dumpFileStatus(SvnFileStatus.OBSTRUCTED); - - final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project); - myAddConfirmation = vcsManager.getStandardConfirmation(VcsConfiguration.StandardConfirmation.ADD, this); - myDeleteConfirmation = vcsManager.getStandardConfirmation(VcsConfiguration.StandardConfirmation.REMOVE, this); - myCheckoutOptions = vcsManager.getStandardOption(VcsConfiguration.StandardOption.CHECKOUT, this); - - if (myProject.isDefault()) { - myChangeListListener = null; - myEntriesFileListener = null; - } - else { - myEntriesFileListener = new SvnEntriesFileListener(project); - upgradeIfNeeded(bus); - - myChangeListListener = new SvnChangelistListener(myProject, this); - - myVcsListener = new VcsListener() { - @Override - public void directoryMappingChanged() { - invokeRefreshSvnRoots(true); - } - }; - } - - myFrameStateListener = project.isDefault() ? null : new MyFrameStateListener(ChangeListManager.getInstance(project), - VcsDirtyScopeManager.getInstance(project)); - myWorkingCopiesContent = new WorkingCopiesContent(this); - - // remove used some time before old notification group ids - correctNotificationIds(); - myChecker = new SvnExecutableChecker(myProject); - } - - private void correctNotificationIds() { - boolean notEmpty = NotificationsConfigurationImpl.getNotificationsConfigurationImpl().isRegistered("SVN_NO_JNA") || - NotificationsConfigurationImpl.getNotificationsConfigurationImpl().isRegistered("SVN_NO_CRYPT32") || - NotificationsConfigurationImpl.getNotificationsConfigurationImpl().isRegistered("SubversionId"); - if (notEmpty) { - NotificationsConfigurationImpl.remove("SVN_NO_JNA", "SVN_NO_CRYPT32", "SubversionId"); - NotificationsConfiguration.getNotificationsConfiguration().register(getDisplayName(), NotificationDisplayType.BALLOON); - } - } - - public void postStartup() { - if (myProject.isDefault()) return; - myCopiesRefreshManager = new SvnCopiesRefreshManager(myProject, (SvnFileUrlMappingImpl) getSvnFileUrlMapping()); - if (! myConfiguration.isCleanupRun()) { - if (cleanup17copies()) { - myConfiguration.setCleanupRun(true); - } - } - - invokeRefreshSvnRoots(true); - myWorkingCopiesContent.activate(); - } - - private boolean cleanup17copies() { - final boolean[] result = new boolean[1]; - result[0] = true; - final Runnable runnable = new Runnable() { - public void run() { - myCopiesRefreshManager.getCopiesRefresh().synchRequest(); - final List infos = getAllWcInfos(); - for (WCInfo info : infos) { - if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(info.getFormat())) { - try { - createWCClient().doCleanup(new File(info.getPath())); - } - catch (SVNException e) { - LOG.info(e); - result[0] = false; } - } - } - } - }; - - if (ApplicationManager.getApplication().isDispatchThread()) { - ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable, - "Cleanup working copies", true, myProject); - } else { - runnable.run(); - } - return result[0]; - } - - public void invokeRefreshSvnRoots(final boolean asynchronous) { - REFRESH_LOG.debug("refresh: ", new Throwable()); - if (myCopiesRefreshManager != null) { - if (asynchronous) { - myCopiesRefreshManager.getCopiesRefresh().asynchRequest(); - } - else { - if (ApplicationManager.getApplication().isDispatchThread()) { - ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { - @Override - public void run() { - myCopiesRefreshManager.getCopiesRefresh().synchRequest(); - } - }, SvnBundle.message("refreshing.working.copies.roots.progress.text"), true, myProject); - } - else { - myCopiesRefreshManager.getCopiesRefresh().synchRequest(); - } - } - } - } - - @Override - public boolean checkImmediateParentsBeforeCommit() { - return true; - } - - private void upgradeIfNeeded(final MessageBus bus) { - final MessageBusConnection connection = bus.connect(); - connection.subscribe(ChangeListManagerImpl.LISTS_LOADED, new LocalChangeListsLoadedListener() { - @Override - public void processLoadedLists(final List lists) { - if (lists.isEmpty()) return; - SvnConfiguration.SvnSupportOptions supportOptions = null; - try { - ChangeListManager.getInstance(myProject).setReadOnly(SvnChangeProvider.ourDefaultListName, true); - supportOptions = myConfiguration.getSupportOptions(myProject); - - if (!supportOptions.changeListsSynchronized()) { - processChangeLists(lists); - } - } - catch (ProcessCanceledException e) { - // - } - finally { - if (supportOptions != null) { - supportOptions.upgrade(); - } - } - - connection.disconnect(); - } - }); - } - - public void processChangeLists(final List lists) { - final ProjectLevelVcsManager plVcsManager = ProjectLevelVcsManager.getInstanceChecked(myProject); - plVcsManager.startBackgroundVcsOperation(); - try { - final SVNChangelistClient client = createChangelistClient(); - for (LocalChangeList list : lists) { - if (!list.isDefault()) { - final Collection changes = list.getChanges(); - for (Change change : changes) { - correctListForRevision(plVcsManager, change.getBeforeRevision(), client, list.getName()); - correctListForRevision(plVcsManager, change.getAfterRevision(), client, list.getName()); - } - } - } - } - finally { - final Application appManager = ApplicationManager.getApplication(); - if (appManager.isDispatchThread()) { - appManager.executeOnPooledThread(new Runnable() { - @Override - public void run() { - plVcsManager.stopBackgroundVcsOperation(); - } - }); - } - else { - plVcsManager.stopBackgroundVcsOperation(); - } - } - } - - private static void correctListForRevision(final ProjectLevelVcsManager plVcsManager, final ContentRevision revision, - final SVNChangelistClient client, final String name) { - if (revision != null) { - final FilePath path = revision.getFile(); - final AbstractVcs vcs = plVcsManager.getVcsFor(path); - if (vcs != null && VCS_NAME.equals(vcs.getName())) { - try { - client.doAddToChangelist(new File[]{path.getIOFile()}, SVNDepth.EMPTY, name, null); - } - catch (SVNException e) { - // left in default list - } - } - } - } - - @Override - public void activate() { - createPool(); - final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject); - if (!myProject.isDefault()) { - ChangeListManager.getInstance(myProject).addChangeListListener(myChangeListListener); - vcsManager.addVcsListener(myVcsListener); - } - - SvnApplicationSettings.getInstance().svnActivated(); - if (myEntriesFileListener != null) { - VirtualFileManager.getInstance().addVirtualFileListener(myEntriesFileListener); - } - // this will initialize its inner listener for committed changes upload - LoadedRevisionsCache.getInstance(myProject); - FrameStateManager.getInstance().addListener(myFrameStateListener); - - myAuthNotifier.init(); - mySvnBranchPointsCalculator = new SvnBranchPointsCalculator(myProject); - mySvnBranchPointsCalculator.activate(); - - if (SystemInfo.isWindows) { - if (!SVNJNAUtil.isJNAPresent()) { - Notifications.Bus.notify(new Notification(getDisplayName(), "Subversion plugin: no JNA", - "A problem with JNA initialization for svnkit library. Encryption is not available.", - NotificationType.WARNING), - NotificationDisplayType.BALLOON, myProject); - } - else if (!SVNJNAUtil.isWinCryptEnabled()) { - Notifications.Bus.notify(new Notification(getDisplayName(), "Subversion plugin: no encryption", - "A problem with encryption module (Crypt32.dll) initialization for svnkit library. Encryption is not available.", - NotificationType.WARNING), NotificationDisplayType.BALLOON, myProject); - } - } - - final SvnConfiguration.UseAcceleration accelerationType = SvnConfiguration.getInstance(myProject).myUseAcceleration; - if (SvnConfiguration.UseAcceleration.javaHL.equals(accelerationType)) { - CheckJavaHL.runtimeCheck(myProject); - } - else if (SvnConfiguration.UseAcceleration.commandLine.equals(accelerationType) && - !ApplicationManager.getApplication().isHeadlessEnvironment()) { - myChecker.checkExecutableAndNotifyIfNeeded(); - } - - // do one time after project loaded - StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new DumbAwareRunnable() { - @Override - public void run() { - postStartup(); - - // for IDEA, it takes 2 minutes - and anyway this can be done in background, no sense... - // once it could be mistaken about copies for 2 minutes on start... - - /*if (! myMapping.getAllWcInfos().isEmpty()) { - invokeRefreshSvnRoots(); - return; - } - ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { - public void run() { - myCopiesRefreshManager.getCopiesRefresh().ensureInit(); - } - }, SvnBundle.message("refreshing.working.copies.roots.progress.text"), true, myProject);*/ - } - }); - - vcsManager.addVcsListener(myRootsToWorkingCopies); - - myLoadedBranchesStorage.activate(); - } - - private static void initLogFilters() { - if (ourLogFilters != null) return; - ourLogFilters = new RareLogger.LogFilter[]{new RareLogger.LogFilter() { - @Override - public Object getKey(@NotNull org.apache.log4j.Level level, - @NonNls String message, - @Nullable Throwable t, - @NonNls String... details) { - SVNException svnExc = null; - if (t instanceof SVNException) { - svnExc = (SVNException)t; - } - else if (t instanceof VcsException && t.getCause() instanceof SVNException) { - svnExc = (SVNException)t.getCause(); - } - if (svnExc != null) { - // only filter a few cases - if (ourLogRarely.contains(svnExc.getErrorMessage().getErrorCode())) { - return svnExc.getErrorMessage().getErrorCode(); - } - } - return null; - } - - @Override - @NotNull - public Integer getAllowedLoggingInterval(org.apache.log4j.Level level, String message, Throwable t, String[] details) { - SVNException svnExc = null; - if (t instanceof SVNException) { - svnExc = (SVNException)t; - } - else if (t instanceof VcsException && t.getCause() instanceof SVNException) { - svnExc = (SVNException)t.getCause(); - } - if (svnExc != null) { - if (ourLogRarely.contains(svnExc.getErrorMessage().getErrorCode())) { - return ourLogRareInterval; - } - else { - return ourLogUsualInterval; - } - } - return 0; - } - }}; - } - - public static Logger wrapLogger(final Logger logger) { - initLogFilters(); - return RareLogger.wrap(logger, Boolean.getBoolean("svn.logger.fairsynch"), ourLogFilters); - } - - public RootsToWorkingCopies getRootsToWorkingCopies() { - return myRootsToWorkingCopies; - } - - public SvnAuthenticationNotifier getAuthNotifier() { - return myAuthNotifier; - } - - @Override - public void deactivate() { - FrameStateManager.getInstance().removeListener(myFrameStateListener); - - final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject); - if (myVcsListener != null) { - vcsManager.removeVcsListener(myVcsListener); - } - - if (myEntriesFileListener != null) { - VirtualFileManager.getInstance().removeVirtualFileListener(myEntriesFileListener); - } - SvnApplicationSettings.getInstance().svnDeactivated(); - if (myCommittedChangesProvider != null) { - myCommittedChangesProvider.deactivate(); - } - if (myChangeListListener != null && !myProject.isDefault()) { - ChangeListManager.getInstance(myProject).removeChangeListListener(myChangeListListener); - } - vcsManager.removeVcsListener(myRootsToWorkingCopies); - myRootsToWorkingCopies.clear(); - - myAuthNotifier.stop(); - myAuthNotifier.clear(); - - mySvnBranchPointsCalculator.deactivate(); - mySvnBranchPointsCalculator = null; - myWorkingCopiesContent.deactivate(); - myLoadedBranchesStorage.deactivate(); - myPool.dispose(); - myPool = null; - } - - public VcsShowConfirmationOption getAddConfirmation() { - return myAddConfirmation; - } - - public VcsShowConfirmationOption getDeleteConfirmation() { - return myDeleteConfirmation; - } - - public VcsShowSettingOption getCheckoutOptions() { - return myCheckoutOptions; - } - - @Override - public EditFileProvider getEditFileProvider() { - if (myEditFilesProvider == null) { - myEditFilesProvider = new SvnEditFileProvider(this); - } - return myEditFilesProvider; - } - - @Override - @NotNull - public ChangeProvider getChangeProvider() { - if (myChangeProvider == null) { - myChangeProvider = new SvnChangeProvider(this); - } - return myChangeProvider; - } - - public SVNRepository createRepository(String url) throws SVNException { - SVNRepository repos = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(url)); - repos.setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); - repos.setTunnelProvider(myConfiguration.getOptions(myProject)); - return repos; - } - - public SVNRepository createRepository(SVNURL url) throws SVNException { - SVNRepository repos = SVNRepositoryFactory.create(url); - repos.setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); - repos.setTunnelProvider(myConfiguration.getOptions(myProject)); - return repos; - } - - private void createPool() { - if (myPool != null) return; - boolean keep = !ApplicationManager.getApplication().isUnitTestMode() && Boolean.getBoolean(KEEP_CONNECTIONS_KEY); - myPool = - new DefaultSVNRepositoryPool(myConfiguration.getAuthenticationManager(this), myConfiguration.getOptions(myProject), 60 * 1000, keep); - } - - @NotNull - private ISVNRepositoryPool getPool() { - if (myPool == null) { - createPool(); - } - return myPool; - } - - public SVNUpdateClient createUpdateClient() { - final SVNUpdateClient client = new SVNUpdateClient(getPool(), myConfiguration.getOptions(myProject)); - client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); - return client; - } - - public SVNStatusClient createStatusClient() { - SVNStatusClient client = new SVNStatusClient(getPool(), myConfiguration.getOptions(myProject)); - client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); - client.setIgnoreExternals(false); - return client; - } - - public SVNWCClient createWCClient() { - final SVNWCClient client = new SVNWCClient(getPool(), myConfiguration.getOptions(myProject)); - client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); - return client; - } - - public SVNCopyClient createCopyClient() { - final SVNCopyClient client = new SVNCopyClient(getPool(), myConfiguration.getOptions(myProject)); - client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); - return client; - } - - public SVNMoveClient createMoveClient() { - final SVNMoveClient client = new SVNMoveClient(getPool(), myConfiguration.getOptions(myProject)); - client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); - return client; - } - - public SVNLogClient createLogClient() { - final SVNLogClient client = new SVNLogClient(getPool(), myConfiguration.getOptions(myProject)); - client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); - return client; - } - - public SVNCommitClient createCommitClient() { - final SVNCommitClient client = new SVNCommitClient(getPool(), myConfiguration.getOptions(myProject)); - client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); - return client; - } - - public SVNDiffClient createDiffClient() { - final SVNDiffClient client = new SVNDiffClient(getPool(), myConfiguration.getOptions(myProject)); - client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); - return client; - } - - public SVNChangelistClient createChangelistClient() { - final SVNChangelistClient client = new SVNChangelistClient(getPool(), myConfiguration.getOptions(myProject)); - client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); - return client; - } - - public SVNWCAccess createWCAccess() { - final SVNWCAccess access = SVNWCAccess.newInstance(null); - access.setOptions(myConfiguration.getOptions(myProject)); - return access; - } - - public ISVNOptions getSvnOptions() { - return myConfiguration.getOptions(myProject); - } - - public ISVNAuthenticationManager getSvnAuthenticationManager() { - return myConfiguration.getAuthenticationManager(this); - } - - void dumpFileStatus(FileStatus fs) { - if (LOG.isDebugEnabled()) { - LOG.debug("FileStatus:" + fs.getText() + " " + fs.getColor() + " " + " " + fs.getClass().getName()); - } - } - - @Override - public UpdateEnvironment getIntegrateEnvironment() { - if (mySvnIntegrateEnvironment == null) { - mySvnIntegrateEnvironment = new SvnIntegrateEnvironment(this); - } - return mySvnIntegrateEnvironment; - } - - @Override - public UpdateEnvironment createUpdateEnvironment() { - if (mySvnUpdateEnvironment == null) { - mySvnUpdateEnvironment = new SvnUpdateEnvironment(this); - } - return mySvnUpdateEnvironment; - } - - @Override - public String getDisplayName() { - LOG.debug("getDisplayName"); - return "Subversion"; - } - - @Override - public Configurable getConfigurable() { - LOG.debug("createConfigurable"); - return new SvnConfigurable(myProject); - } - - - public SvnConfiguration getSvnConfiguration() { - return myConfiguration; - } - - public static SvnVcs getInstance(Project project) { - return (SvnVcs)ProjectLevelVcsManager.getInstance(project).findVcsByName(VCS_NAME); - } - - @Override - @NotNull - public CheckinEnvironment createCheckinEnvironment() { - if (myCheckinEnvironment == null) { - myCheckinEnvironment = new SvnCheckinEnvironment(this); - } - return myCheckinEnvironment; - } - - @Override - @NotNull - public RollbackEnvironment createRollbackEnvironment() { - if (myRollbackEnvironment == null) { - myRollbackEnvironment = new SvnRollbackEnvironment(this); - } - return myRollbackEnvironment; - } - - @Override - public VcsHistoryProvider getVcsHistoryProvider() { - // no heavy state, but it would be useful to have place to keep state in -> do not reuse instance - return new SvnHistoryProvider(this); - } - - @Override - public VcsHistoryProvider getVcsBlockHistoryProvider() { - return getVcsHistoryProvider(); - } - - @Override - public AnnotationProvider getAnnotationProvider() { - if (myAnnotationProvider == null) { - myAnnotationProvider = new SvnAnnotationProvider(this); - } - return myAnnotationProvider; - } - - public void addEntriesListener(final SvnEntriesListener listener) { - if (myEntriesFileListener != null) { - myEntriesFileListener.addListener(listener); - } - } - - public void removeEntriesListener(final SvnEntriesListener listener) { - if (myEntriesFileListener != null) { - myEntriesFileListener.removeListener(listener); - } - } - - @Override - public DiffProvider getDiffProvider() { - if (mySvnDiffProvider == null) { - mySvnDiffProvider = new SvnDiffProvider(this); - } - return mySvnDiffProvider; - } - - private static Trinity getTimestampForPropertiesChange(final File ioFile, final boolean isDir) { - final File dir = isDir ? ioFile : ioFile.getParentFile(); - final String relPath = SVNAdminUtil.getPropPath(ioFile.getName(), isDir ? SVNNodeKind.DIR : SVNNodeKind.FILE, false); - final String relPathBase = SVNAdminUtil.getPropBasePath(ioFile.getName(), isDir ? SVNNodeKind.DIR : SVNNodeKind.FILE, false); - final String relPathRevert = SVNAdminUtil.getPropRevertPath(ioFile.getName(), isDir ? SVNNodeKind.DIR : SVNNodeKind.FILE, false); - return new Trinity(new File(dir, relPath).lastModified(), new File(dir, relPathBase).lastModified(), - new File(dir, relPathRevert).lastModified()); - } - - private static boolean trinitiesEqual(final Trinity t1, final Trinity t2) { - if (t2.first == 0 && t2.second == 0 && t2.third == 0) return false; - return t1.equals(t2); - } - - @Nullable - public SVNPropertyValue getPropertyWithCaching(final VirtualFile file, final String propName) throws SVNException { - Map>> cachedMap = myPropertyCache.get(keyForVf(file)); - final Pair> cachedValue = cachedMap == null ? null : cachedMap.get(propName); - - final File ioFile = new File(file.getPath()); - final Trinity tsTrinity = getTimestampForPropertiesChange(ioFile, file.isDirectory()); - - if (cachedValue != null) { - // zero means that a file was not found - if (trinitiesEqual(cachedValue.getSecond(), tsTrinity)) { - return cachedValue.getFirst(); - } - } - - final SVNPropertyData value = createWCClient().doGetProperty(ioFile, propName, SVNRevision.WORKING, SVNRevision.WORKING); - final SVNPropertyValue propValue = value == null ? null : value.getValue(); - - if (cachedMap == null) { - cachedMap = new HashMap>>(); - myPropertyCache.put(keyForVf(file), cachedMap); - } - - cachedMap.put(propName, new Pair>(propValue, tsTrinity)); - - return propValue; - } - - @Override - public boolean fileExistsInVcs(FilePath path) { - File file = path.getIOFile(); - try { - SVNStatus status = createStatusClient().doStatus(file, false); - if (status != null) { - if (svnStatusIs(status, SVNStatusType.STATUS_ADDED)) { - return status.isCopied(); - } - return !(svnStatusIsUnversioned(status) || - svnStatusIs(status, SVNStatusType.STATUS_IGNORED) || - svnStatusIs(status, SVNStatusType.STATUS_OBSTRUCTED)); - } - } - catch (SVNException e) { - // - } - return false; - } - - public static boolean svnStatusIsUnversioned(final SVNStatus status) { - return svnStatusIs(status, SVNStatusType.STATUS_UNVERSIONED); - } - - public static boolean svnStatusIs(final SVNStatus status, @NotNull final SVNStatusType value) { - return value.equals(status.getNodeStatus()) || value.equals(status.getContentsStatus()); - } - - @Override - public boolean fileIsUnderVcs(FilePath path) { - final ChangeListManager clManager = ChangeListManager.getInstance(myProject); - final VirtualFile file = path.getVirtualFile(); - if (file == null) { - return false; - } - return !SvnStatusUtil.isIgnoredInAnySense(clManager, file) && !clManager.isUnversioned(file); - } - - private static File getEntriesFile(File file) { - return file.isDirectory() ? new File(file, pathToEntries) : new File(file.getParentFile(), pathToEntries); - } - - private static File getDirPropsFile(File file) { - return new File(file, pathToDirProps); - } - - @Nullable - public SVNInfo getInfo(final VirtualFile file) { - final File ioFile = new File(file.getPath()); - return getInfo(ioFile); - } - - public SVNInfo getInfo(File ioFile) { - try { - SVNWCClient wcClient = createWCClient(); - SVNInfo info = wcClient.doInfo(ioFile, SVNRevision.UNDEFINED); - if (info == null || info.getRepositoryRootURL() == null) { - info = wcClient.doInfo(ioFile, SVNRevision.HEAD); - } - return info; - } - catch (SVNException e) { - return null; - } - } - - public static class SVNStatusHolder { - - private final SVNStatus myValue; - private final long myEntriesTimestamp; - private final long myFileTimestamp; - private final boolean myIsLocked; - - public SVNStatusHolder(long entriesStamp, long fileStamp, SVNStatus value) { - myValue = value; - myEntriesTimestamp = entriesStamp; - myFileTimestamp = fileStamp; - myIsLocked = value != null && value.isLocked(); - } - - public long getEntriesTimestamp() { - return myEntriesTimestamp; - } - - public long getFileTimestamp() { - return myFileTimestamp; - } - - public boolean isLocked() { - return myIsLocked; - } - - public SVNStatus getStatus() { - return myValue; - } - } - - public static class SVNInfoHolder { - - private final SVNInfo myValue; - private final long myEntriesTimestamp; - private final long myFileTimestamp; - - public SVNInfoHolder(long entriesStamp, long fileStamp, SVNInfo value) { - myValue = value; - myEntriesTimestamp = entriesStamp; - myFileTimestamp = fileStamp; - } - - public long getEntriesTimestamp() { - return myEntriesTimestamp; - } - - public long getFileTimestamp() { - return myFileTimestamp; - } - - public SVNInfo getInfo() { - return myValue; - } - } - - private static class JavaSVNDebugLogger extends SVNDebugLogAdapter { - private final boolean myLoggingEnabled; - private final Logger myLog; - @NonNls public static final String TRACE_LOG_PARAMETER_NAME = "javasvn.log.trace"; - - public JavaSVNDebugLogger(boolean loggingEnabled, Logger log) { - myLoggingEnabled = loggingEnabled; - myLog = log; - } - - @Override - public void log(final SVNLogType logType, final Throwable th, final Level logLevel) { - if (myLoggingEnabled) { - myLog.info(th); - } - } - - @Override - public void log(final SVNLogType logType, final String message, final Level logLevel) { - if (myLoggingEnabled) { - myLog.info(message); - } - } - - @Override - public void log(final SVNLogType logType, final String message, final byte[] data) { - if (myLoggingEnabled) { - if (data != null) { - try { - myLog.info(message + "\n" + new String(data, "UTF-8")); - } - catch (UnsupportedEncodingException e) { - myLog.info(message + "\n" + new String(data)); - } - } - else { - myLog.info(message); - } - } - } - } - - @Override - public FileStatus[] getProvidedStatuses() { - return new FileStatus[]{SvnFileStatus.EXTERNAL, - SvnFileStatus.OBSTRUCTED, - SvnFileStatus.REPLACED}; - } - - - @Override - @NotNull - public CommittedChangesProvider getCommittedChangesProvider() { - if (myCommittedChangesProvider == null) { - myCommittedChangesProvider = new SvnCommittedChangesProvider(myProject); - } - return myCommittedChangesProvider; - } - - @Nullable - @Override - public VcsRevisionNumber parseRevisionNumber(final String revisionNumberString) { - final SVNRevision revision = SVNRevision.parse(revisionNumberString); - if (revision.equals(SVNRevision.UNDEFINED)) { - return null; - } - return new SvnRevisionNumber(revision); - } - - @Override - public String getRevisionPattern() { - return ourIntegerPattern; - } - - @Override - public boolean isVersionedDirectory(final VirtualFile dir) { - return SvnUtil.seemsLikeVersionedDir(dir); - } - - @NotNull - public SvnFileUrlMapping getSvnFileUrlMapping() { - if (myMapping == null) { - myMapping = SvnFileUrlMappingImpl.getInstance(myProject); - } - return myMapping; - } - - /** - * Returns real working copies roots - if there is -> Subversion setting, - * and there is one working copy, will return one root - */ - public List getAllWcInfos() { - final SvnFileUrlMapping urlMapping = getSvnFileUrlMapping(); - - final List infoList = urlMapping.getAllWcInfos(); - final List infos = new ArrayList(); - for (RootUrlInfo info : infoList) { - final File file = info.getIoFile(); - infos.add(new WCInfo(file.getAbsolutePath(), info.getAbsoluteUrlAsUrl(), - info.getFormat(), info.getRepositoryUrl(), SvnUtil.isWorkingCopyRoot(file), info.getType(), - SvnUtil.getDepth(this, file))); - } - return infos; - } - - @Override - public RootsConvertor getCustomConvertor() { - if (myProject.isDefault()) return null; - return getSvnFileUrlMapping(); - } - - @Override - public MergeProvider getMergeProvider() { - if (myMergeProvider == null) { - myMergeProvider = new SvnMergeProvider(myProject); - } - return myMergeProvider; - } - - @Override - public List getAdditionalActionsForLocalChange() { - return Arrays.asList(new ShowPropertiesDiffWithLocalAction()); - } - - private static String keyForVf(final VirtualFile vf) { - return vf.getUrl(); - } - - @Override - public boolean allowsNestedRoots() { - return SvnConfiguration.getInstance(myProject).DETECT_NESTED_COPIES; - } - - @Override - public List filterUniqueRoots(final List in, final Convertor convertor) { - if (in.size() <= 1) return in; - - final List> infos = new ArrayList>(in.size()); - final SvnFileUrlMappingImpl mapping = (SvnFileUrlMappingImpl)getSvnFileUrlMapping(); - final List notMatched = new LinkedList(); - for (S s : in) { - final VirtualFile vf = convertor.convert(s); - if (vf == null) continue; - - final File ioFile = new File(vf.getPath()); - SVNURL url = mapping.getUrlForFile(ioFile); - if (url == null) { - url = SvnUtil.getUrl(ioFile); - if (url == null) { - notMatched.add(s); - continue; - } - } - infos.add(new MyPair(vf, url.toString(), s)); - } - final List> filtered = new ArrayList>(infos.size()); - ForNestedRootChecker.filterOutSuperfluousChildren(this, infos, filtered); - - final List converted = ObjectsConvertor.convert(filtered, new Convertor, S>() { - @Override - public S convert(final MyPair o) { - return o.getSrc(); - } - }); - if (!notMatched.isEmpty()) { - // potential bug is here: order is not kept. but seems it only occurs for cases where result is sorted after filtering so ok - converted.addAll(notMatched); - } - return converted; - } - - private static class MyPair implements RootUrlPair { - private final VirtualFile myFile; - private final String myUrl; - private final T mySrc; - - private MyPair(VirtualFile file, String url, T src) { - myFile = file; - myUrl = url; - mySrc = src; - } - - public T getSrc() { - return mySrc; - } - - @Override - public VirtualFile getVirtualFile() { - return myFile; - } - - @Override - public String getUrl() { - return myUrl; - } - } - - private static class MyFrameStateListener implements FrameStateListener { - private final ChangeListManager myClManager; - private final VcsDirtyScopeManager myDirtyScopeManager; - - private MyFrameStateListener(ChangeListManager clManager, VcsDirtyScopeManager dirtyScopeManager) { - myClManager = clManager; - myDirtyScopeManager = dirtyScopeManager; - } - - @Override - public void onFrameDeactivated() { - } - - @Override - public void onFrameActivated() { - final List folders = ((ChangeListManagerImpl)myClManager).getLockedFolders(); - if (!folders.isEmpty()) { - myDirtyScopeManager.filesDirty(null, folders); - } - } - } - - public static VcsKey getKey() { - return ourKey; - } - - @Override - public boolean isVcsBackgroundOperationsAllowed(VirtualFile root) { - return ThreeState.YES.equals(myAuthNotifier.isAuthenticatedFor(root)); - } - - public SvnBranchPointsCalculator getSvnBranchPointsCalculator() { - return mySvnBranchPointsCalculator; - } - - @Override - public boolean areDirectoriesVersionedItems() { - return true; - } -} +/* + * Copyright 2000-2011 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. + */ + + +package org.jetbrains.idea.svn; + +import com.intellij.ide.FrameStateListener; +import com.intellij.ide.FrameStateManager; +import com.intellij.idea.RareLogger; +import com.intellij.notification.*; +import com.intellij.notification.impl.NotificationsConfigurationImpl; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.project.DumbAwareRunnable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.startup.StartupManager; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.Trinity; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.annotate.AnnotationProvider; +import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vcs.checkin.CheckinEnvironment; +import com.intellij.openapi.vcs.diff.DiffProvider; +import com.intellij.openapi.vcs.history.VcsHistoryProvider; +import com.intellij.openapi.vcs.history.VcsRevisionNumber; +import com.intellij.openapi.vcs.merge.MergeProvider; +import com.intellij.openapi.vcs.rollback.RollbackEnvironment; +import com.intellij.openapi.vcs.update.UpdateEnvironment; +import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; +import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.util.Processor; +import com.intellij.util.ThreeState; +import com.intellij.util.containers.Convertor; +import com.intellij.util.containers.SoftHashMap; +import com.intellij.util.messages.MessageBus; +import com.intellij.util.messages.MessageBusConnection; +import com.intellij.util.messages.Topic; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.actions.ShowPropertiesDiffWithLocalAction; +import org.jetbrains.idea.svn.actions.SvnMergeProvider; +import org.jetbrains.idea.svn.annotate.SvnAnnotationProvider; +import org.jetbrains.idea.svn.checkin.SvnCheckinEnvironment; +import org.jetbrains.idea.svn.commandLine.SvnExecutableChecker; +import org.jetbrains.idea.svn.dialogs.SvnBranchPointsCalculator; +import org.jetbrains.idea.svn.dialogs.WCInfo; +import org.jetbrains.idea.svn.history.LoadedRevisionsCache; +import org.jetbrains.idea.svn.history.SvnChangeList; +import org.jetbrains.idea.svn.history.SvnCommittedChangesProvider; +import org.jetbrains.idea.svn.history.SvnHistoryProvider; +import org.jetbrains.idea.svn.rollback.SvnRollbackEnvironment; +import org.jetbrains.idea.svn.update.SvnIntegrateEnvironment; +import org.jetbrains.idea.svn.update.SvnUpdateEnvironment; +import org.tmatesoft.sqljet.core.SqlJetErrorCode; +import org.tmatesoft.sqljet.core.SqlJetException; +import org.tmatesoft.svn.core.*; +import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; +import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory; +import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory; +import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl; +import org.tmatesoft.svn.core.internal.util.jna.SVNJNAUtil; +import org.tmatesoft.svn.core.internal.wc.SVNAdminUtil; +import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminArea14; +import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaFactory; +import org.tmatesoft.svn.core.internal.wc.admin.SVNWCAccess; +import org.tmatesoft.svn.core.io.SVNRepository; +import org.tmatesoft.svn.core.io.SVNRepositoryFactory; +import org.tmatesoft.svn.core.wc.*; +import org.tmatesoft.svn.util.SVNDebugLog; +import org.tmatesoft.svn.util.SVNDebugLogAdapter; +import org.tmatesoft.svn.util.SVNLogType; + +import javax.swing.*; +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.util.*; +import java.util.logging.Level; + +@SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"}) +public class SvnVcs extends AbstractVcs { + private static final String KEEP_CONNECTIONS_KEY = "svn.keep.connections"; + private static final Logger REFRESH_LOG = Logger.getInstance("#svn_refresh"); + + private static final int ourLogUsualInterval = 20 * 1000; + private static final int ourLogRareInterval = 30 * 1000; + + private static final Set ourLogRarely = new HashSet( + Arrays.asList(new SVNErrorCode[]{SVNErrorCode.WC_UNSUPPORTED_FORMAT, SVNErrorCode.WC_CORRUPT, SVNErrorCode.WC_CORRUPT_TEXT_BASE, + SVNErrorCode.WC_NOT_FILE, SVNErrorCode.WC_NOT_DIRECTORY, SVNErrorCode.WC_PATH_NOT_FOUND})); + + private static final Logger LOG = wrapLogger(Logger.getInstance("org.jetbrains.idea.svn.SvnVcs")); + @NonNls public static final String VCS_NAME = "svn"; + private static final VcsKey ourKey = createKey(VCS_NAME); + public static final Topic WC_CONVERTED = new Topic("WC_CONVERTED", Runnable.class); + private final Map>>> myPropertyCache = + new SoftHashMap>>>(); + + private DefaultSVNRepositoryPool myPool; + private final SvnConfiguration myConfiguration; + private final SvnEntriesFileListener myEntriesFileListener; + + private CheckinEnvironment myCheckinEnvironment; + private RollbackEnvironment myRollbackEnvironment; + private UpdateEnvironment mySvnUpdateEnvironment; + private UpdateEnvironment mySvnIntegrateEnvironment; + private VcsHistoryProvider mySvnHistoryProvider; + private AnnotationProvider myAnnotationProvider; + private DiffProvider mySvnDiffProvider; + private final VcsShowConfirmationOption myAddConfirmation; + private final VcsShowConfirmationOption myDeleteConfirmation; + private EditFileProvider myEditFilesProvider; + private SvnCommittedChangesProvider myCommittedChangesProvider; + private final VcsShowSettingOption myCheckoutOptions; + + private ChangeProvider myChangeProvider; + private MergeProvider myMergeProvider; + private final WorkingCopiesContent myWorkingCopiesContent; + + @NonNls public static final String LOG_PARAMETER_NAME = "javasvn.log"; + public static final String pathToEntries = SvnUtil.SVN_ADMIN_DIR_NAME + File.separatorChar + SvnUtil.ENTRIES_FILE_NAME; + public static final String pathToDirProps = SvnUtil.SVN_ADMIN_DIR_NAME + File.separatorChar + SvnUtil.DIR_PROPS_FILE_NAME; + private final SvnChangelistListener myChangeListListener; + + private SvnCopiesRefreshManager myCopiesRefreshManager; + private SvnFileUrlMappingImpl myMapping; + private final MyFrameStateListener myFrameStateListener; + + public static final Topic ROOTS_RELOADED = new Topic("ROOTS_RELOADED", Runnable.class); + private VcsListener myVcsListener; + + private SvnBranchPointsCalculator mySvnBranchPointsCalculator; + + private final RootsToWorkingCopies myRootsToWorkingCopies; + private final SvnAuthenticationNotifier myAuthNotifier; + private static RareLogger.LogFilter[] ourLogFilters; + private final SvnLoadedBrachesStorage myLoadedBranchesStorage; + + public static final String SVNKIT_HTTP_SSL_PROTOCOLS = "svnkit.http.sslProtocols"; + private final SvnExecutableChecker myChecker; + + public static final Processor ourBusyExceptionProcessor = new Processor() { + @Override + public boolean process(Exception e) { + if (e instanceof SVNException) { + final SVNErrorCode errorCode = ((SVNException)e).getErrorMessage().getErrorCode(); + if (SVNErrorCode.WC_LOCKED.equals(errorCode)) { + return true; + } else if (SVNErrorCode.SQLITE_ERROR.equals(errorCode)) { + Throwable cause = ((SVNException)e).getErrorMessage().getCause(); + if (cause instanceof SqlJetException) { + return SqlJetErrorCode.BUSY.equals(((SqlJetException)cause).getErrorCode()); + } + } + } + return false; + } + }; + + public void checkCommandLineVersion() { + myChecker.checkExecutableAndNotifyIfNeeded(); + } + + static { + SVNJNAUtil.setJNAEnabled(true); + SvnHttpAuthMethodsDefaultChecker.check(); + + //noinspection UseOfArchaicSystemPropertyAccessors + final JavaSVNDebugLogger logger = new JavaSVNDebugLogger(Boolean.getBoolean(LOG_PARAMETER_NAME), LOG); + SVNDebugLog.setDefaultLog(logger); + SVNAdminAreaFactory.setSelector(new SvnFormatSelector()); + + DAVRepositoryFactory.setup(); + SVNRepositoryFactoryImpl.setup(); + FSRepositoryFactory.setup(); + + // non-optimized writing is fast enough on Linux/MacOS, and somewhat more reliable + if (SystemInfo.isWindows) { + SVNAdminArea14.setOptimizedWritingEnabled(true); + } + + if (!SVNJNAUtil.isJNAPresent()) { + LOG.warn("JNA is not found by svnkit library"); + } + initLogFilters(); + + // Alexander Kitaev says it is default value (SSLv3) - since 8254 + if (!SystemInfo.JAVA_RUNTIME_VERSION.startsWith("1.7") && System.getProperty(SVNKIT_HTTP_SSL_PROTOCOLS) == null) { + System.setProperty(SVNKIT_HTTP_SSL_PROTOCOLS, "SSLv3"); + } + } + + public SvnVcs(final Project project, MessageBus bus, SvnConfiguration svnConfiguration, final SvnLoadedBrachesStorage storage) { + super(project, VCS_NAME); + myLoadedBranchesStorage = storage; + LOG.debug("ct"); + myRootsToWorkingCopies = new RootsToWorkingCopies(myProject); + myConfiguration = svnConfiguration; + myAuthNotifier = new SvnAuthenticationNotifier(this); + + dumpFileStatus(FileStatus.ADDED); + dumpFileStatus(FileStatus.DELETED); + dumpFileStatus(FileStatus.MERGE); + dumpFileStatus(FileStatus.MODIFIED); + dumpFileStatus(FileStatus.NOT_CHANGED); + dumpFileStatus(FileStatus.UNKNOWN); + + dumpFileStatus(SvnFileStatus.REPLACED); + dumpFileStatus(SvnFileStatus.EXTERNAL); + dumpFileStatus(SvnFileStatus.OBSTRUCTED); + + final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project); + myAddConfirmation = vcsManager.getStandardConfirmation(VcsConfiguration.StandardConfirmation.ADD, this); + myDeleteConfirmation = vcsManager.getStandardConfirmation(VcsConfiguration.StandardConfirmation.REMOVE, this); + myCheckoutOptions = vcsManager.getStandardOption(VcsConfiguration.StandardOption.CHECKOUT, this); + + if (myProject.isDefault()) { + myChangeListListener = null; + myEntriesFileListener = null; + } + else { + myEntriesFileListener = new SvnEntriesFileListener(project); + upgradeIfNeeded(bus); + + myChangeListListener = new SvnChangelistListener(myProject, this); + + myVcsListener = new VcsListener() { + @Override + public void directoryMappingChanged() { + invokeRefreshSvnRoots(true); + } + }; + } + + myFrameStateListener = project.isDefault() ? null : new MyFrameStateListener(ChangeListManager.getInstance(project), + VcsDirtyScopeManager.getInstance(project)); + myWorkingCopiesContent = new WorkingCopiesContent(this); + + // remove used some time before old notification group ids + correctNotificationIds(); + myChecker = new SvnExecutableChecker(myProject); + } + + private void correctNotificationIds() { + boolean notEmpty = NotificationsConfigurationImpl.getNotificationsConfigurationImpl().isRegistered("SVN_NO_JNA") || + NotificationsConfigurationImpl.getNotificationsConfigurationImpl().isRegistered("SVN_NO_CRYPT32") || + NotificationsConfigurationImpl.getNotificationsConfigurationImpl().isRegistered("SubversionId"); + if (notEmpty) { + NotificationsConfigurationImpl.remove("SVN_NO_JNA", "SVN_NO_CRYPT32", "SubversionId"); + NotificationsConfiguration.getNotificationsConfiguration().register(getDisplayName(), NotificationDisplayType.BALLOON); + } + } + + public void postStartup() { + if (myProject.isDefault()) return; + myCopiesRefreshManager = new SvnCopiesRefreshManager(myProject, (SvnFileUrlMappingImpl) getSvnFileUrlMapping()); + if (! myConfiguration.isCleanupRun()) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (cleanup17copies()) { + myConfiguration.setCleanupRun(true); + } + } + }); + } else { + invokeRefreshSvnRoots(true); + } + + myWorkingCopiesContent.activate(); + } + + private boolean cleanup17copies() { + final boolean[] result = new boolean[1]; + result[0] = true; + final Runnable runnable = new Runnable() { + public void run() { + myCopiesRefreshManager.getCopiesRefresh().synchRequest(); + final List infos = getAllWcInfos(); + for (WCInfo info : infos) { + if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(info.getFormat())) { + try { + createWCClient().doCleanup(new File(info.getPath())); + } + catch (SVNException e) { + LOG.info(e); + result[0] = false; } + } + } + } + }; + + if (ApplicationManager.getApplication().isDispatchThread()) { + ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable, + "Cleanup working copies", true, myProject); + } else { + runnable.run(); + } + return result[0]; + } + + public void invokeRefreshSvnRoots(final boolean asynchronous) { + REFRESH_LOG.debug("refresh: ", new Throwable()); + if (myCopiesRefreshManager != null) { + if (asynchronous) { + myCopiesRefreshManager.getCopiesRefresh().asynchRequest(); + } + else { + if (ApplicationManager.getApplication().isDispatchThread()) { + ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { + @Override + public void run() { + myCopiesRefreshManager.getCopiesRefresh().synchRequest(); + } + }, SvnBundle.message("refreshing.working.copies.roots.progress.text"), true, myProject); + } + else { + myCopiesRefreshManager.getCopiesRefresh().synchRequest(); + } + } + } + } + + @Override + public boolean checkImmediateParentsBeforeCommit() { + return true; + } + + private void upgradeIfNeeded(final MessageBus bus) { + final MessageBusConnection connection = bus.connect(); + connection.subscribe(ChangeListManagerImpl.LISTS_LOADED, new LocalChangeListsLoadedListener() { + @Override + public void processLoadedLists(final List lists) { + if (lists.isEmpty()) return; + SvnConfiguration.SvnSupportOptions supportOptions = null; + try { + ChangeListManager.getInstance(myProject).setReadOnly(SvnChangeProvider.ourDefaultListName, true); + supportOptions = myConfiguration.getSupportOptions(myProject); + + if (!supportOptions.changeListsSynchronized()) { + processChangeLists(lists); + } + } + catch (ProcessCanceledException e) { + // + } + finally { + if (supportOptions != null) { + supportOptions.upgrade(); + } + } + + connection.disconnect(); + } + }); + } + + public void processChangeLists(final List lists) { + final ProjectLevelVcsManager plVcsManager = ProjectLevelVcsManager.getInstanceChecked(myProject); + plVcsManager.startBackgroundVcsOperation(); + try { + final SVNChangelistClient client = createChangelistClient(); + for (LocalChangeList list : lists) { + if (!list.isDefault()) { + final Collection changes = list.getChanges(); + for (Change change : changes) { + correctListForRevision(plVcsManager, change.getBeforeRevision(), client, list.getName()); + correctListForRevision(plVcsManager, change.getAfterRevision(), client, list.getName()); + } + } + } + } + finally { + final Application appManager = ApplicationManager.getApplication(); + if (appManager.isDispatchThread()) { + appManager.executeOnPooledThread(new Runnable() { + @Override + public void run() { + plVcsManager.stopBackgroundVcsOperation(); + } + }); + } + else { + plVcsManager.stopBackgroundVcsOperation(); + } + } + } + + private static void correctListForRevision(final ProjectLevelVcsManager plVcsManager, final ContentRevision revision, + final SVNChangelistClient client, final String name) { + if (revision != null) { + final FilePath path = revision.getFile(); + final AbstractVcs vcs = plVcsManager.getVcsFor(path); + if (vcs != null && VCS_NAME.equals(vcs.getName())) { + try { + client.doAddToChangelist(new File[]{path.getIOFile()}, SVNDepth.EMPTY, name, null); + } + catch (SVNException e) { + // left in default list + } + } + } + } + + @Override + public void activate() { + createPool(); + final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject); + if (!myProject.isDefault()) { + ChangeListManager.getInstance(myProject).addChangeListListener(myChangeListListener); + vcsManager.addVcsListener(myVcsListener); + } + + SvnApplicationSettings.getInstance().svnActivated(); + if (myEntriesFileListener != null) { + VirtualFileManager.getInstance().addVirtualFileListener(myEntriesFileListener); + } + // this will initialize its inner listener for committed changes upload + LoadedRevisionsCache.getInstance(myProject); + FrameStateManager.getInstance().addListener(myFrameStateListener); + + myAuthNotifier.init(); + mySvnBranchPointsCalculator = new SvnBranchPointsCalculator(myProject); + mySvnBranchPointsCalculator.activate(); + + if (SystemInfo.isWindows) { + if (!SVNJNAUtil.isJNAPresent()) { + Notifications.Bus.notify(new Notification(getDisplayName(), "Subversion plugin: no JNA", + "A problem with JNA initialization for svnkit library. Encryption is not available.", + NotificationType.WARNING), + NotificationDisplayType.BALLOON, myProject); + } + else if (!SVNJNAUtil.isWinCryptEnabled()) { + Notifications.Bus.notify(new Notification(getDisplayName(), "Subversion plugin: no encryption", + "A problem with encryption module (Crypt32.dll) initialization for svnkit library. Encryption is not available.", + NotificationType.WARNING), NotificationDisplayType.BALLOON, myProject); + } + } + + final SvnConfiguration.UseAcceleration accelerationType = SvnConfiguration.getInstance(myProject).myUseAcceleration; + if (SvnConfiguration.UseAcceleration.javaHL.equals(accelerationType)) { + CheckJavaHL.runtimeCheck(myProject); + } + else if (SvnConfiguration.UseAcceleration.commandLine.equals(accelerationType) && + !ApplicationManager.getApplication().isHeadlessEnvironment()) { + myChecker.checkExecutableAndNotifyIfNeeded(); + } + + // do one time after project loaded + StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new DumbAwareRunnable() { + @Override + public void run() { + postStartup(); + + // for IDEA, it takes 2 minutes - and anyway this can be done in background, no sense... + // once it could be mistaken about copies for 2 minutes on start... + + /*if (! myMapping.getAllWcInfos().isEmpty()) { + invokeRefreshSvnRoots(); + return; + } + ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { + public void run() { + myCopiesRefreshManager.getCopiesRefresh().ensureInit(); + } + }, SvnBundle.message("refreshing.working.copies.roots.progress.text"), true, myProject);*/ + } + }); + + vcsManager.addVcsListener(myRootsToWorkingCopies); + + myLoadedBranchesStorage.activate(); + } + + private static void initLogFilters() { + if (ourLogFilters != null) return; + ourLogFilters = new RareLogger.LogFilter[]{new RareLogger.LogFilter() { + @Override + public Object getKey(@NotNull org.apache.log4j.Level level, + @NonNls String message, + @Nullable Throwable t, + @NonNls String... details) { + SVNException svnExc = null; + if (t instanceof SVNException) { + svnExc = (SVNException)t; + } + else if (t instanceof VcsException && t.getCause() instanceof SVNException) { + svnExc = (SVNException)t.getCause(); + } + if (svnExc != null) { + // only filter a few cases + if (ourLogRarely.contains(svnExc.getErrorMessage().getErrorCode())) { + return svnExc.getErrorMessage().getErrorCode(); + } + } + return null; + } + + @Override + @NotNull + public Integer getAllowedLoggingInterval(org.apache.log4j.Level level, String message, Throwable t, String[] details) { + SVNException svnExc = null; + if (t instanceof SVNException) { + svnExc = (SVNException)t; + } + else if (t instanceof VcsException && t.getCause() instanceof SVNException) { + svnExc = (SVNException)t.getCause(); + } + if (svnExc != null) { + if (ourLogRarely.contains(svnExc.getErrorMessage().getErrorCode())) { + return ourLogRareInterval; + } + else { + return ourLogUsualInterval; + } + } + return 0; + } + }}; + } + + public static Logger wrapLogger(final Logger logger) { + initLogFilters(); + return RareLogger.wrap(logger, Boolean.getBoolean("svn.logger.fairsynch"), ourLogFilters); + } + + public RootsToWorkingCopies getRootsToWorkingCopies() { + return myRootsToWorkingCopies; + } + + public SvnAuthenticationNotifier getAuthNotifier() { + return myAuthNotifier; + } + + @Override + public void deactivate() { + FrameStateManager.getInstance().removeListener(myFrameStateListener); + + final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject); + if (myVcsListener != null) { + vcsManager.removeVcsListener(myVcsListener); + } + + if (myEntriesFileListener != null) { + VirtualFileManager.getInstance().removeVirtualFileListener(myEntriesFileListener); + } + SvnApplicationSettings.getInstance().svnDeactivated(); + if (myCommittedChangesProvider != null) { + myCommittedChangesProvider.deactivate(); + } + if (myChangeListListener != null && !myProject.isDefault()) { + ChangeListManager.getInstance(myProject).removeChangeListListener(myChangeListListener); + } + vcsManager.removeVcsListener(myRootsToWorkingCopies); + myRootsToWorkingCopies.clear(); + + myAuthNotifier.stop(); + myAuthNotifier.clear(); + + mySvnBranchPointsCalculator.deactivate(); + mySvnBranchPointsCalculator = null; + myWorkingCopiesContent.deactivate(); + myLoadedBranchesStorage.deactivate(); + myPool.dispose(); + myPool = null; + } + + public VcsShowConfirmationOption getAddConfirmation() { + return myAddConfirmation; + } + + public VcsShowConfirmationOption getDeleteConfirmation() { + return myDeleteConfirmation; + } + + public VcsShowSettingOption getCheckoutOptions() { + return myCheckoutOptions; + } + + @Override + public EditFileProvider getEditFileProvider() { + if (myEditFilesProvider == null) { + myEditFilesProvider = new SvnEditFileProvider(this); + } + return myEditFilesProvider; + } + + @Override + @NotNull + public ChangeProvider getChangeProvider() { + if (myChangeProvider == null) { + myChangeProvider = new SvnChangeProvider(this); + } + return myChangeProvider; + } + + public SVNRepository createRepository(String url) throws SVNException { + SVNRepository repos = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(url)); + repos.setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); + repos.setTunnelProvider(myConfiguration.getOptions(myProject)); + return repos; + } + + public SVNRepository createRepository(SVNURL url) throws SVNException { + SVNRepository repos = SVNRepositoryFactory.create(url); + repos.setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); + repos.setTunnelProvider(myConfiguration.getOptions(myProject)); + return repos; + } + + private void createPool() { + if (myPool != null) return; + boolean keep = !ApplicationManager.getApplication().isUnitTestMode() && Boolean.getBoolean(KEEP_CONNECTIONS_KEY); + myPool = + new DefaultSVNRepositoryPool(myConfiguration.getAuthenticationManager(this), myConfiguration.getOptions(myProject), 60 * 1000, keep); + } + + @NotNull + private ISVNRepositoryPool getPool() { + if (myPool == null) { + createPool(); + } + return myPool; + } + + public SVNUpdateClient createUpdateClient() { + final SVNUpdateClient client = new SVNUpdateClient(getPool(), myConfiguration.getOptions(myProject)); + client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); + return client; + } + + public SVNStatusClient createStatusClient() { + SVNStatusClient client = new SVNStatusClient(getPool(), myConfiguration.getOptions(myProject)); + client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); + client.setIgnoreExternals(false); + return client; + } + + public SVNWCClient createWCClient() { + final SVNWCClient client = new SVNWCClient(getPool(), myConfiguration.getOptions(myProject)); + client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); + return client; + } + + public SVNCopyClient createCopyClient() { + final SVNCopyClient client = new SVNCopyClient(getPool(), myConfiguration.getOptions(myProject)); + client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); + return client; + } + + public SVNMoveClient createMoveClient() { + final SVNMoveClient client = new SVNMoveClient(getPool(), myConfiguration.getOptions(myProject)); + client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); + return client; + } + + public SVNLogClient createLogClient() { + final SVNLogClient client = new SVNLogClient(getPool(), myConfiguration.getOptions(myProject)); + client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); + return client; + } + + public SVNCommitClient createCommitClient() { + final SVNCommitClient client = new SVNCommitClient(getPool(), myConfiguration.getOptions(myProject)); + client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); + return client; + } + + public SVNDiffClient createDiffClient() { + final SVNDiffClient client = new SVNDiffClient(getPool(), myConfiguration.getOptions(myProject)); + client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); + return client; + } + + public SVNChangelistClient createChangelistClient() { + final SVNChangelistClient client = new SVNChangelistClient(getPool(), myConfiguration.getOptions(myProject)); + client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this)); + return client; + } + + public SVNWCAccess createWCAccess() { + final SVNWCAccess access = SVNWCAccess.newInstance(null); + access.setOptions(myConfiguration.getOptions(myProject)); + return access; + } + + public ISVNOptions getSvnOptions() { + return myConfiguration.getOptions(myProject); + } + + public ISVNAuthenticationManager getSvnAuthenticationManager() { + return myConfiguration.getAuthenticationManager(this); + } + + void dumpFileStatus(FileStatus fs) { + if (LOG.isDebugEnabled()) { + LOG.debug("FileStatus:" + fs.getText() + " " + fs.getColor() + " " + " " + fs.getClass().getName()); + } + } + + @Override + public UpdateEnvironment getIntegrateEnvironment() { + if (mySvnIntegrateEnvironment == null) { + mySvnIntegrateEnvironment = new SvnIntegrateEnvironment(this); + } + return mySvnIntegrateEnvironment; + } + + @Override + public UpdateEnvironment createUpdateEnvironment() { + if (mySvnUpdateEnvironment == null) { + mySvnUpdateEnvironment = new SvnUpdateEnvironment(this); + } + return mySvnUpdateEnvironment; + } + + @Override + public String getDisplayName() { + LOG.debug("getDisplayName"); + return "Subversion"; + } + + @Override + public Configurable getConfigurable() { + LOG.debug("createConfigurable"); + return new SvnConfigurable(myProject); + } + + + public SvnConfiguration getSvnConfiguration() { + return myConfiguration; + } + + public static SvnVcs getInstance(Project project) { + return (SvnVcs)ProjectLevelVcsManager.getInstance(project).findVcsByName(VCS_NAME); + } + + @Override + @NotNull + public CheckinEnvironment createCheckinEnvironment() { + if (myCheckinEnvironment == null) { + myCheckinEnvironment = new SvnCheckinEnvironment(this); + } + return myCheckinEnvironment; + } + + @Override + @NotNull + public RollbackEnvironment createRollbackEnvironment() { + if (myRollbackEnvironment == null) { + myRollbackEnvironment = new SvnRollbackEnvironment(this); + } + return myRollbackEnvironment; + } + + @Override + public VcsHistoryProvider getVcsHistoryProvider() { + // no heavy state, but it would be useful to have place to keep state in -> do not reuse instance + return new SvnHistoryProvider(this); + } + + @Override + public VcsHistoryProvider getVcsBlockHistoryProvider() { + return getVcsHistoryProvider(); + } + + @Override + public AnnotationProvider getAnnotationProvider() { + if (myAnnotationProvider == null) { + myAnnotationProvider = new SvnAnnotationProvider(this); + } + return myAnnotationProvider; + } + + public void addEntriesListener(final SvnEntriesListener listener) { + if (myEntriesFileListener != null) { + myEntriesFileListener.addListener(listener); + } + } + + public void removeEntriesListener(final SvnEntriesListener listener) { + if (myEntriesFileListener != null) { + myEntriesFileListener.removeListener(listener); + } + } + + @Override + public DiffProvider getDiffProvider() { + if (mySvnDiffProvider == null) { + mySvnDiffProvider = new SvnDiffProvider(this); + } + return mySvnDiffProvider; + } + + private static Trinity getTimestampForPropertiesChange(final File ioFile, final boolean isDir) { + final File dir = isDir ? ioFile : ioFile.getParentFile(); + final String relPath = SVNAdminUtil.getPropPath(ioFile.getName(), isDir ? SVNNodeKind.DIR : SVNNodeKind.FILE, false); + final String relPathBase = SVNAdminUtil.getPropBasePath(ioFile.getName(), isDir ? SVNNodeKind.DIR : SVNNodeKind.FILE, false); + final String relPathRevert = SVNAdminUtil.getPropRevertPath(ioFile.getName(), isDir ? SVNNodeKind.DIR : SVNNodeKind.FILE, false); + return new Trinity(new File(dir, relPath).lastModified(), new File(dir, relPathBase).lastModified(), + new File(dir, relPathRevert).lastModified()); + } + + private static boolean trinitiesEqual(final Trinity t1, final Trinity t2) { + if (t2.first == 0 && t2.second == 0 && t2.third == 0) return false; + return t1.equals(t2); + } + + @Nullable + public SVNPropertyValue getPropertyWithCaching(final VirtualFile file, final String propName) throws SVNException { + Map>> cachedMap = myPropertyCache.get(keyForVf(file)); + final Pair> cachedValue = cachedMap == null ? null : cachedMap.get(propName); + + final File ioFile = new File(file.getPath()); + final Trinity tsTrinity = getTimestampForPropertiesChange(ioFile, file.isDirectory()); + + if (cachedValue != null) { + // zero means that a file was not found + if (trinitiesEqual(cachedValue.getSecond(), tsTrinity)) { + return cachedValue.getFirst(); + } + } + + final SVNPropertyData value = createWCClient().doGetProperty(ioFile, propName, SVNRevision.WORKING, SVNRevision.WORKING); + final SVNPropertyValue propValue = value == null ? null : value.getValue(); + + if (cachedMap == null) { + cachedMap = new HashMap>>(); + myPropertyCache.put(keyForVf(file), cachedMap); + } + + cachedMap.put(propName, new Pair>(propValue, tsTrinity)); + + return propValue; + } + + @Override + public boolean fileExistsInVcs(FilePath path) { + File file = path.getIOFile(); + try { + SVNStatus status = createStatusClient().doStatus(file, false); + if (status != null) { + if (svnStatusIs(status, SVNStatusType.STATUS_ADDED)) { + return status.isCopied(); + } + return !(svnStatusIsUnversioned(status) || + svnStatusIs(status, SVNStatusType.STATUS_IGNORED) || + svnStatusIs(status, SVNStatusType.STATUS_OBSTRUCTED)); + } + } + catch (SVNException e) { + // + } + return false; + } + + public static boolean svnStatusIsUnversioned(final SVNStatus status) { + return svnStatusIs(status, SVNStatusType.STATUS_UNVERSIONED); + } + + public static boolean svnStatusIs(final SVNStatus status, @NotNull final SVNStatusType value) { + return value.equals(status.getNodeStatus()) || value.equals(status.getContentsStatus()); + } + + @Override + public boolean fileIsUnderVcs(FilePath path) { + final ChangeListManager clManager = ChangeListManager.getInstance(myProject); + final VirtualFile file = path.getVirtualFile(); + if (file == null) { + return false; + } + return !SvnStatusUtil.isIgnoredInAnySense(clManager, file) && !clManager.isUnversioned(file); + } + + private static File getEntriesFile(File file) { + return file.isDirectory() ? new File(file, pathToEntries) : new File(file.getParentFile(), pathToEntries); + } + + private static File getDirPropsFile(File file) { + return new File(file, pathToDirProps); + } + + @Nullable + public SVNInfo getInfo(final VirtualFile file) { + final File ioFile = new File(file.getPath()); + return getInfo(ioFile); + } + + public SVNInfo getInfo(File ioFile) { + try { + SVNWCClient wcClient = createWCClient(); + SVNInfo info = wcClient.doInfo(ioFile, SVNRevision.UNDEFINED); + if (info == null || info.getRepositoryRootURL() == null) { + info = wcClient.doInfo(ioFile, SVNRevision.HEAD); + } + return info; + } + catch (SVNException e) { + return null; + } + } + + public static class SVNStatusHolder { + + private final SVNStatus myValue; + private final long myEntriesTimestamp; + private final long myFileTimestamp; + private final boolean myIsLocked; + + public SVNStatusHolder(long entriesStamp, long fileStamp, SVNStatus value) { + myValue = value; + myEntriesTimestamp = entriesStamp; + myFileTimestamp = fileStamp; + myIsLocked = value != null && value.isLocked(); + } + + public long getEntriesTimestamp() { + return myEntriesTimestamp; + } + + public long getFileTimestamp() { + return myFileTimestamp; + } + + public boolean isLocked() { + return myIsLocked; + } + + public SVNStatus getStatus() { + return myValue; + } + } + + public static class SVNInfoHolder { + + private final SVNInfo myValue; + private final long myEntriesTimestamp; + private final long myFileTimestamp; + + public SVNInfoHolder(long entriesStamp, long fileStamp, SVNInfo value) { + myValue = value; + myEntriesTimestamp = entriesStamp; + myFileTimestamp = fileStamp; + } + + public long getEntriesTimestamp() { + return myEntriesTimestamp; + } + + public long getFileTimestamp() { + return myFileTimestamp; + } + + public SVNInfo getInfo() { + return myValue; + } + } + + private static class JavaSVNDebugLogger extends SVNDebugLogAdapter { + private final boolean myLoggingEnabled; + private final Logger myLog; + @NonNls public static final String TRACE_LOG_PARAMETER_NAME = "javasvn.log.trace"; + + public JavaSVNDebugLogger(boolean loggingEnabled, Logger log) { + myLoggingEnabled = loggingEnabled; + myLog = log; + } + + @Override + public void log(final SVNLogType logType, final Throwable th, final Level logLevel) { + if (myLoggingEnabled) { + myLog.info(th); + } + } + + @Override + public void log(final SVNLogType logType, final String message, final Level logLevel) { + if (myLoggingEnabled) { + myLog.info(message); + } + } + + @Override + public void log(final SVNLogType logType, final String message, final byte[] data) { + if (myLoggingEnabled) { + if (data != null) { + try { + myLog.info(message + "\n" + new String(data, "UTF-8")); + } + catch (UnsupportedEncodingException e) { + myLog.info(message + "\n" + new String(data)); + } + } + else { + myLog.info(message); + } + } + } + } + + @Override + public FileStatus[] getProvidedStatuses() { + return new FileStatus[]{SvnFileStatus.EXTERNAL, + SvnFileStatus.OBSTRUCTED, + SvnFileStatus.REPLACED}; + } + + + @Override + @NotNull + public CommittedChangesProvider getCommittedChangesProvider() { + if (myCommittedChangesProvider == null) { + myCommittedChangesProvider = new SvnCommittedChangesProvider(myProject); + } + return myCommittedChangesProvider; + } + + @Nullable + @Override + public VcsRevisionNumber parseRevisionNumber(final String revisionNumberString) { + final SVNRevision revision = SVNRevision.parse(revisionNumberString); + if (revision.equals(SVNRevision.UNDEFINED)) { + return null; + } + return new SvnRevisionNumber(revision); + } + + @Override + public String getRevisionPattern() { + return ourIntegerPattern; + } + + @Override + public boolean isVersionedDirectory(final VirtualFile dir) { + return SvnUtil.seemsLikeVersionedDir(dir); + } + + @NotNull + public SvnFileUrlMapping getSvnFileUrlMapping() { + if (myMapping == null) { + myMapping = SvnFileUrlMappingImpl.getInstance(myProject); + } + return myMapping; + } + + /** + * Returns real working copies roots - if there is -> Subversion setting, + * and there is one working copy, will return one root + */ + public List getAllWcInfos() { + final SvnFileUrlMapping urlMapping = getSvnFileUrlMapping(); + + final List infoList = urlMapping.getAllWcInfos(); + final List infos = new ArrayList(); + for (RootUrlInfo info : infoList) { + final File file = info.getIoFile(); + infos.add(new WCInfo(file.getAbsolutePath(), info.getAbsoluteUrlAsUrl(), + info.getFormat(), info.getRepositoryUrl(), SvnUtil.isWorkingCopyRoot(file), info.getType(), + SvnUtil.getDepth(this, file))); + } + return infos; + } + + @Override + public RootsConvertor getCustomConvertor() { + if (myProject.isDefault()) return null; + return getSvnFileUrlMapping(); + } + + @Override + public MergeProvider getMergeProvider() { + if (myMergeProvider == null) { + myMergeProvider = new SvnMergeProvider(myProject); + } + return myMergeProvider; + } + + @Override + public List getAdditionalActionsForLocalChange() { + return Arrays.asList(new ShowPropertiesDiffWithLocalAction()); + } + + private static String keyForVf(final VirtualFile vf) { + return vf.getUrl(); + } + + @Override + public boolean allowsNestedRoots() { + return SvnConfiguration.getInstance(myProject).DETECT_NESTED_COPIES; + } + + @Override + public List filterUniqueRoots(final List in, final Convertor convertor) { + if (in.size() <= 1) return in; + + final List> infos = new ArrayList>(in.size()); + final SvnFileUrlMappingImpl mapping = (SvnFileUrlMappingImpl)getSvnFileUrlMapping(); + final List notMatched = new LinkedList(); + for (S s : in) { + final VirtualFile vf = convertor.convert(s); + if (vf == null) continue; + + final File ioFile = new File(vf.getPath()); + SVNURL url = mapping.getUrlForFile(ioFile); + if (url == null) { + url = SvnUtil.getUrl(ioFile); + if (url == null) { + notMatched.add(s); + continue; + } + } + infos.add(new MyPair(vf, url.toString(), s)); + } + final List> filtered = new ArrayList>(infos.size()); + ForNestedRootChecker.filterOutSuperfluousChildren(this, infos, filtered); + + final List converted = ObjectsConvertor.convert(filtered, new Convertor, S>() { + @Override + public S convert(final MyPair o) { + return o.getSrc(); + } + }); + if (!notMatched.isEmpty()) { + // potential bug is here: order is not kept. but seems it only occurs for cases where result is sorted after filtering so ok + converted.addAll(notMatched); + } + return converted; + } + + private static class MyPair implements RootUrlPair { + private final VirtualFile myFile; + private final String myUrl; + private final T mySrc; + + private MyPair(VirtualFile file, String url, T src) { + myFile = file; + myUrl = url; + mySrc = src; + } + + public T getSrc() { + return mySrc; + } + + @Override + public VirtualFile getVirtualFile() { + return myFile; + } + + @Override + public String getUrl() { + return myUrl; + } + } + + private static class MyFrameStateListener implements FrameStateListener { + private final ChangeListManager myClManager; + private final VcsDirtyScopeManager myDirtyScopeManager; + + private MyFrameStateListener(ChangeListManager clManager, VcsDirtyScopeManager dirtyScopeManager) { + myClManager = clManager; + myDirtyScopeManager = dirtyScopeManager; + } + + @Override + public void onFrameDeactivated() { + } + + @Override + public void onFrameActivated() { + final List folders = ((ChangeListManagerImpl)myClManager).getLockedFolders(); + if (!folders.isEmpty()) { + myDirtyScopeManager.filesDirty(null, folders); + } + } + } + + public static VcsKey getKey() { + return ourKey; + } + + @Override + public boolean isVcsBackgroundOperationsAllowed(VirtualFile root) { + return ThreeState.YES.equals(myAuthNotifier.isAuthenticatedFor(root)); + } + + public SvnBranchPointsCalculator getSvnBranchPointsCalculator() { + return mySvnBranchPointsCalculator; + } + + @Override + public boolean areDirectoriesVersionedItems() { + return true; + } +} From 6880a08a7cbc2d9aec2393d6003e5ec080a81424 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 24 Jul 2012 11:58:04 +0200 Subject: [PATCH 02/51] analyze cyclic dependencies: dialog tweaks (IDEA-88935;IDEA-88936) --- .../actions/CyclicDependenciesAction.java | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/java/java-impl/src/com/intellij/cyclicDependencies/actions/CyclicDependenciesAction.java b/java/java-impl/src/com/intellij/cyclicDependencies/actions/CyclicDependenciesAction.java index cd222246348c..77c39c581c2f 100644 --- a/java/java-impl/src/com/intellij/cyclicDependencies/actions/CyclicDependenciesAction.java +++ b/java/java-impl/src/com/intellij/cyclicDependencies/actions/CyclicDependenciesAction.java @@ -21,7 +21,8 @@ import com.intellij.analysis.JavaAnalysisScope; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.psi.*; @@ -49,7 +50,8 @@ public class CyclicDependenciesAction extends AnAction{ public void update(AnActionEvent event) { Presentation presentation = event.getPresentation(); presentation.setEnabled( - getInspectionScope(event.getDataContext()) != null || event.getData(LangDataKeys.PSI_FILE) != null); + getInspectionScope(event.getDataContext()) != null || + event.getData(PlatformDataKeys.PROJECT) != null); } public void actionPerformed(AnActionEvent e) { @@ -57,15 +59,11 @@ public class CyclicDependenciesAction extends AnAction{ final Project project = PlatformDataKeys.PROJECT.getData(dataContext); final Module module = LangDataKeys.MODULE.getData(dataContext); if (project != null) { - PsiFile psiFile = LangDataKeys.PSI_FILE.getData(dataContext); - if (psiFile != null && !(psiFile instanceof PsiJavaFile)) { - return; - } AnalysisScope scope = getInspectionScope(dataContext); if (scope == null || scope.getScopeType() != AnalysisScope.MODULES){ ProjectModuleOrPackageDialog dlg = null; if (module != null) { - dlg = new ProjectModuleOrPackageDialog(ModuleUtil.getModuleNameInReadAction(module), scope); + dlg = new ProjectModuleOrPackageDialog(ModuleManager.getInstance(project).getModules().length == 1 ? null : ModuleUtilCore.getModuleNameInReadAction(module), scope); dlg.show(); if (!dlg.isOK()) return; } @@ -104,12 +102,12 @@ public class CyclicDependenciesAction extends AnAction{ //Possible scopes: package, project, module. Project projectContext = PlatformDataKeys.PROJECT_CONTEXT.getData(dataContext); if (projectContext != null) { - return new AnalysisScope(projectContext); + return null; } Module moduleContext = LangDataKeys.MODULE_CONTEXT.getData(dataContext); if (moduleContext != null) { - return new AnalysisScope(moduleContext); + return null; } Module [] modulesArray = LangDataKeys.MODULE_CONTEXT_ARRAY.getData(dataContext); @@ -128,12 +126,9 @@ public class CyclicDependenciesAction extends AnAction{ PsiDirectory[] dirs = pack.getDirectories(GlobalSearchScope.projectScope(pack.getProject())); if (dirs.length == 0) return null; return new JavaAnalysisScope(pack, LangDataKeys.MODULE.getData(dataContext)); - } else if (psiTarget != null){ - return null; } - - return getProjectScope(dataContext); + return null; } @Nullable @@ -173,7 +168,6 @@ public class CyclicDependenciesAction extends AnAction{ init(); setTitle(AnalysisScopeBundle.message("cyclic.dependencies.scope.dialog.title", myTitle)); setHorizontalStretch(1.75f); - myModuleButton.setSelected(true); } public boolean isIncludeTestSources() { @@ -190,11 +184,19 @@ public class CyclicDependenciesAction extends AnAction{ myModuleButton.setText(AnalysisScopeBundle.message("cyclic.dependencies.scope.dialog.module.button", myAnalysisVerb, myModuleName)); group.add(myModuleButton); } + myModuleButton.setVisible(myModuleName != null); mySelectedScopeButton.setVisible(mySelectedScope != null); if (mySelectedScope != null) { mySelectedScopeButton.setText(mySelectedScope.getShortenName()); group.add(mySelectedScopeButton); } + if (mySelectedScope != null) { + mySelectedScopeButton.setSelected(true); + } else if (myModuleName != null) { + myModuleButton.setSelected(true); + } else { + myProjectButton.setSelected(true); + } return myWholePanel; } From 1c1e1522b3ec0b576c4b7098a73eda24e498c020 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 24 Jul 2012 14:02:06 +0400 Subject: [PATCH 03/51] EA-37337 - assert: FileManagerImpl.findFile --- .../org/jetbrains/idea/maven/navigator/MavenNavigationUtil.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenNavigationUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenNavigationUtil.java index c78438e07754..0d665347ae29 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenNavigationUtil.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenNavigationUtil.java @@ -72,6 +72,8 @@ public class MavenNavigationUtil { public static Navigatable createNavigatableForDependency(final Project project, final VirtualFile file, final MavenArtifact artifact) { return new NavigatableAdapter() { public void navigate(boolean requestFocus) { + if (!file.isValid()) return; + final PsiFile pom = PsiManager.getInstance(project).findFile(file); if (pom instanceof XmlFile) { final XmlTag id = findDependency((XmlFile)pom, artifact.getArtifactId()); From 05c56bd35f33498077535b960a45bb1ea53fc4c0 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 24 Jul 2012 14:09:00 +0400 Subject: [PATCH 04/51] Add additional diagnostic --- .../idea/maven/importing/MavenModuleNameMapper.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java index c125e65db08e..c9736b2926d0 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java @@ -102,7 +102,10 @@ public class MavenModuleNameMapper { mavenProjectToModuleName.put(each.project, each.getResultName()); } - assert new HashSet(mavenProjectToModuleName.values()).size() == mavenProjectToModuleName.size(); + assert new HashSet(mavenProjectToModuleName.values()).size() == mavenProjectToModuleName.size() : mavenProjectToModuleName + .values() + + "\n||\n" + + mavenProjectToModuleName; } public static class NameItem implements Comparable { From 97ef06692d7fd6193b380b74eec5026f40dd3fe8 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 24 Jul 2012 14:15:57 +0400 Subject: [PATCH 05/51] Add additional diagnostic --- .../idea/maven/importing/MavenModuleNameMapper.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java index c9736b2926d0..877fd771e545 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java @@ -102,10 +102,7 @@ public class MavenModuleNameMapper { mavenProjectToModuleName.put(each.project, each.getResultName()); } - assert new HashSet(mavenProjectToModuleName.values()).size() == mavenProjectToModuleName.size() : mavenProjectToModuleName - .values() + - "\n||\n" + - mavenProjectToModuleName; + assert new HashSet(mavenProjectToModuleName.values()).size() == mavenProjectToModuleName.size() : mavenProjectToModuleName; } public static class NameItem implements Comparable { From 8927880846cdc84dc61453b42b771420c1a9e034 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 24 Jul 2012 11:53:16 +0200 Subject: [PATCH 06/51] Cleanup --- .../vfs/impl/jar/JarFileSystemImpl.java | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java index 1ab273622a04..743dbcb93d69 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java @@ -20,7 +20,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.ApplicationComponent; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileAttributes; import com.intellij.openapi.util.io.FileUtil; @@ -43,23 +42,18 @@ import java.io.OutputStream; import java.util.*; public class JarFileSystemImpl extends JarFileSystem implements ApplicationComponent { + @NonNls private static final String IDEA_JARS_NOCOPY = "idea.jars.nocopy"; + + private static final class JarFileSystemImplLock { } + private static final Object LOCK = new JarFileSystemImplLock(); + private final Set myNoCopyJarPaths = SystemInfo.isFileSystemCaseSensitive ? new ConcurrentHashSet() : new ConcurrentHashSet(CaseInsensitiveStringHashingStrategy.INSTANCE); - - private final static Logger LOG = Logger.getInstance(JarFileSystemImpl.class); - - @NonNls private static final String IDEA_JARS_NOCOPY = "idea.jars.nocopy"; - private File myNoCopyJarDir; - private final Map myHandlers = new HashMap(); + private File myNoCopyJarDir; private String[] jarPathsCache; // jarPathsCache = myHandlers.keySet() - private static final class JarFileSystemImplLock { - } - - private static final Object LOCK = new JarFileSystemImplLock(); - public JarFileSystemImpl(MessageBus bus) { bus.connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() { @Override @@ -107,7 +101,7 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo } } - VirtualFile[] roots = VfsUtil.toVirtualFileArray(rootsToRefresh); + VirtualFile[] roots = VfsUtilCore.toVirtualFileArray(rootsToRefresh); RefreshQueue.getInstance().refresh(false, true, null, roots); } }; @@ -301,8 +295,8 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo } @Override - public void setTimeStamp(@NotNull final VirtualFile file, final long modstamp) throws IOException { - getHandler(file).setTimeStamp(file, modstamp); + public void setTimeStamp(@NotNull final VirtualFile file, final long modStamp) throws IOException { + getHandler(file).setTimeStamp(file, modStamp); } @Override From d901cd9d5da4c82d8d25ba28a1ecab6cbc91604d Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 24 Jul 2012 12:20:44 +0200 Subject: [PATCH 07/51] Lost changes --- native/IdeaWin32/readme.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/native/IdeaWin32/readme.txt b/native/IdeaWin32/readme.txt index e69de29bb2d1..d3a99b387d3c 100644 --- a/native/IdeaWin32/readme.txt +++ b/native/IdeaWin32/readme.txt @@ -0,0 +1,9 @@ +Prerequisites: +- Visual Studio C++ 2010 Express +- Windows SDK 7.1 (native: Windows Headers, x86 Libraries, x64 Libraries, Tools, Visual C++ Compilers) +- JDK 1.6+ + +To build: +- open Property Manager, expand any configuration, open IdeaWin32 property page, and edit JAVA_HOME user macro + to point to a valid JDK installation +- build Release/Win32 and Release/x64 configurations From 8e87fb2551919197849a1d8de4ded1695115df51 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 24 Jul 2012 12:11:28 +0200 Subject: [PATCH 08/51] IDEA-89175 Completing an annotation on an @interface class should always suggest meta-annotations --- .../completion/JavaNoVariantsDelegator.java | 16 +- .../PreferApplicableAnnotations.java | 14 +- .../NormalCompletionOrderingTest.groovy | 11 +- .../completion/GroovyNoVariantsDelegator.java | 364 +++++++++--------- .../completion/GroovyCompletionTest.groovy | 16 +- 5 files changed, 220 insertions(+), 201 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java index 78a87644b8ed..af6dc31c8482 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java @@ -30,6 +30,9 @@ import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; +import static com.intellij.patterns.PsiJavaPatterns.psiClass; +import static com.intellij.patterns.PsiJavaPatterns.psiElement; + /** * @author peter */ @@ -37,17 +40,24 @@ public class JavaNoVariantsDelegator extends CompletionContributor { @Override public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) { - final boolean empty = containsOnlyPackages(result.runRemainingContributors(parameters, true)); + final boolean empty = containsOnlyPackages(result.runRemainingContributors(parameters, true)) || + suggestMetaAnnotations(parameters); if (!empty && parameters.getInvocationCount() == 0) { result.restartCompletionWhenNothingMatches(); } if (empty) { - delegate(parameters, result); + delegate(parameters, JavaCompletionSorting.addJavaSorting(parameters, result)); } } + private static boolean suggestMetaAnnotations(CompletionParameters parameters) { + PsiElement position = parameters.getPosition(); + return psiElement().withParents(PsiJavaCodeReferenceElement.class, PsiAnnotation.class, PsiModifierList.class, PsiClass.class).accepts( position) && + psiElement().withSuperParent(4, psiClass().isAnnotationType()).accepts(position); + } + public static boolean containsOnlyPackages(LinkedHashSet results) { for (CompletionResult result : results) { if (!(CompletionUtil.getTargetElement(result.getLookupElement()) instanceof PsiPackage)) { @@ -152,7 +162,7 @@ public class JavaNoVariantsDelegator extends CompletionContributor { final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result); JavaClassNameCompletionContributor.addAllClasses(parameters, - true, JavaCompletionSorting.addJavaSorting(parameters, result).getPrefixMatcher(), new Consumer() { + true, result.getPrefixMatcher(), new Consumer() { @Override public void consume(LookupElement element) { JavaPsiClassReferenceElement classElement = element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY); diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/PreferApplicableAnnotations.java b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferApplicableAnnotations.java index 75ba46a656f5..fe6080708ee9 100644 --- a/java/java-tests/testData/codeInsight/completion/normalSorting/PreferApplicableAnnotations.java +++ b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferApplicableAnnotations.java @@ -1,12 +1,2 @@ -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; - -@Z -@interface Foo { -} - -@Target({ElementType.ANNOTATION_TYPE}) -@interface ZMetaAnno {} - -@Target({ElementType.LOCAL_VARIABLE}) -@interface ZLocalAnno {} \ No newline at end of file +@T +@interface Foo { } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy index aa532f06acb5..df1588a69eab 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy @@ -343,7 +343,16 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase { } public void testPreferApplicableAnnotations() throws Throwable { - checkPreferredItems 0, 'ZMetaAnno', 'ZLocalAnno' + myFixture.addClass ''' +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +@Target({ElementType.ANNOTATION_TYPE}) +@interface TMetaAnno {} + +@Target({ElementType.LOCAL_VARIABLE}) +@interface TLocalAnno {}''' + checkPreferredItems 0, 'TMetaAnno', 'Target', 'TreeSelectionMode', 'TLocalAnno' } public void testJComponentAddNewWithStats() throws Throwable { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java index ed5c200dac8c..0c485f1bfa63 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java @@ -1,176 +1,188 @@ -/* - * Copyright 2000-2011 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. - */ -package org.jetbrains.plugins.groovy.lang.completion; - -import com.intellij.codeInsight.completion.*; -import com.intellij.codeInsight.completion.impl.CamelHumpMatcher; -import com.intellij.codeInsight.lookup.AutoCompletionPolicy; -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.psi.*; -import com.intellij.psi.search.PsiShortNamesCache; -import com.intellij.util.Consumer; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; - -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Set; - -/** - * @author peter - */ -public class GroovyNoVariantsDelegator extends CompletionContributor { - - @Override - public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) { - final boolean empty = JavaNoVariantsDelegator.containsOnlyPackages(result.runRemainingContributors(parameters, true)); - - if (!empty && parameters.getInvocationCount() == 0) { - result.restartCompletionWhenNothingMatches(); - } - - if (empty) { - delegate(parameters, result); - } - } - - private static void delegate(CompletionParameters parameters, CompletionResultSet result) { - if (parameters.getCompletionType() == CompletionType.BASIC) { - if (parameters.getInvocationCount() <= 1 && - JavaCompletionContributor.mayStartClassName(result) && - GroovyCompletionContributor.isClassNamePossible(parameters.getPosition()) && - !MapArgumentCompletionProvider.isMapKeyCompletion(parameters)) { - suggestNonImportedClasses(parameters, result); - } - - suggestChainedCalls(parameters, result); - } - } - - private static void suggestNonImportedClasses(CompletionParameters parameters, CompletionResultSet result) { - final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result); - - GroovyCompletionContributor.addAllClasses(parameters, new Consumer() { - @Override - public void consume(LookupElement element) { - JavaPsiClassReferenceElement classElement = - element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY); - if (classElement != null) { - classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE); - } - merger.consume(classElement); - } - }, new InheritorsHolder(parameters.getPosition(), result), result.getPrefixMatcher()); - - merger.finishedClassProcessing(); - } - - private static void suggestChainedCalls(CompletionParameters parameters, CompletionResultSet result) { - PsiElement position = parameters.getPosition(); - PsiElement parent = position.getParent(); - if (!(parent instanceof GrReferenceElement)) { - return; - } - PsiElement qualifier = ((GrReferenceElement)parent).getQualifier(); - if (!(qualifier instanceof GrReferenceElement) || - ((GrReferenceElement)qualifier).getQualifier() != null) { - return; - } - PsiElement target = ((GrReferenceElement)qualifier).resolve(); - if (target != null && !(target instanceof PsiPackage)) { - return; - } - - String fullPrefix = position.getContainingFile().getText().substring(parent.getTextRange().getStartOffset(), parameters.getOffset()); - final CompletionResultSet qualifiedCollector = result.withPrefixMatcher(fullPrefix); - InheritorsHolder inheritors = new InheritorsHolder(position, result); - for (final LookupElement base : suggestQualifierItems(parameters, (GrReferenceElement)qualifier, inheritors)) { - final PsiType type = JavaCompletionUtil.getLookupElementType(base); - if (type != null && !PsiType.VOID.equals(type)) { - GrReferenceElement ref = createMockReference(position, type, base); - PsiElement refName = ref.getReferenceNameElement(); - assert refName != null; - CompletionParameters newParams = parameters.withPosition(refName, refName.getTextRange().getStartOffset()); - GroovyCompletionContributor.completeReference(newParams, ref, inheritors, result.getPrefixMatcher(), new Consumer() { - @Override - public void consume(LookupElement element) { - qualifiedCollector.addElement(new JavaChainLookupElement(base, element) { - @Override - protected boolean shouldParenthesizeQualifier(PsiFile file, int startOffset, int endOffset) { - return false; - } - }); - } - }); - } - } - } - - private static GrReferenceElement createMockReference(final PsiElement place, @NotNull PsiType qualifierType, LookupElement qualifierItem) { - GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(place.getProject()); - if (qualifierItem.getObject() instanceof PsiClass) { - return factory - .createReferenceExpressionFromText(((PsiClass)qualifierItem.getObject()).getQualifiedName() + ".xxx", place); - } - - return factory.createReferenceExpressionFromText("xxx.xxx", - JavaCompletionUtil - .createContextWithXxxVariable(place, qualifierType)); - } - - - private static Set suggestQualifierItems(CompletionParameters _parameters, - GrReferenceElement qualifier, - InheritorsHolder inheritors) { - CompletionParameters parameters = - _parameters.withPosition(qualifier.getReferenceNameElement(), qualifier.getTextRange().getEndOffset()); - String referenceName = qualifier.getReferenceName(); - if (referenceName == null) { - return Collections.emptySet(); - } - - final PrefixMatcher qMatcher = new CamelHumpMatcher(referenceName); - final Set variants = new LinkedHashSet(); - GroovyCompletionContributor.completeReference(parameters, qualifier, inheritors, qMatcher, new Consumer() { - @Override - public void consume(LookupElement element) { - if (qMatcher.prefixMatches(element)) { - variants.add(element); - } - } - }); - - for (PsiClass aClass : PsiShortNamesCache.getInstance(qualifier.getProject()).getClassesByName(referenceName, qualifier.getResolveScope())) { - variants.add(GroovyCompletionUtil.createClassLookupItem(aClass)); - } - - - if (variants.isEmpty()) { - GroovyCompletionContributor.addAllClasses(parameters, new Consumer() { - @Override - public void consume(LookupElement element) { - if (qMatcher.prefixMatches(element)) { - variants.add(element); - } - } - }, inheritors, qMatcher); - } - return variants; - } - - -} +/* + * Copyright 2000-2011 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. + */ +package org.jetbrains.plugins.groovy.lang.completion; + +import com.intellij.codeInsight.completion.*; +import com.intellij.codeInsight.completion.impl.CamelHumpMatcher; +import com.intellij.codeInsight.lookup.AutoCompletionPolicy; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.psi.*; +import com.intellij.psi.search.PsiShortNamesCache; +import com.intellij.util.Consumer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnnotationTypeDefinition; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; + +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; + +import static com.intellij.patterns.PsiJavaPatterns.psiElement; + +/** + * @author peter + */ +public class GroovyNoVariantsDelegator extends CompletionContributor { + + private static boolean suggestMetaAnnotations(CompletionParameters parameters) { + PsiElement position = parameters.getPosition(); + return psiElement().withParents(GrCodeReferenceElement.class, GrAnnotation.class, GrModifierList.class, GrAnnotationTypeDefinition.class).accepts(position); + } + + @Override + public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) { + final boolean empty = JavaNoVariantsDelegator.containsOnlyPackages(result.runRemainingContributors(parameters, true)) || + suggestMetaAnnotations(parameters); + + if (!empty && parameters.getInvocationCount() == 0) { + result.restartCompletionWhenNothingMatches(); + } + + if (empty) { + delegate(parameters, result); + } + } + + private static void delegate(CompletionParameters parameters, CompletionResultSet result) { + if (parameters.getCompletionType() == CompletionType.BASIC) { + if (parameters.getInvocationCount() <= 1 && + JavaCompletionContributor.mayStartClassName(result) && + GroovyCompletionContributor.isClassNamePossible(parameters.getPosition()) && + !MapArgumentCompletionProvider.isMapKeyCompletion(parameters)) { + suggestNonImportedClasses(parameters, result); + } + + suggestChainedCalls(parameters, result); + } + } + + private static void suggestNonImportedClasses(CompletionParameters parameters, CompletionResultSet result) { + final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result); + + GroovyCompletionContributor.addAllClasses(parameters, new Consumer() { + @Override + public void consume(LookupElement element) { + JavaPsiClassReferenceElement classElement = + element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY); + if (classElement != null) { + classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE); + } + merger.consume(classElement); + } + }, new InheritorsHolder(parameters.getPosition(), result), result.getPrefixMatcher()); + + merger.finishedClassProcessing(); + } + + private static void suggestChainedCalls(CompletionParameters parameters, CompletionResultSet result) { + PsiElement position = parameters.getPosition(); + PsiElement parent = position.getParent(); + if (!(parent instanceof GrReferenceElement)) { + return; + } + PsiElement qualifier = ((GrReferenceElement)parent).getQualifier(); + if (!(qualifier instanceof GrReferenceElement) || + ((GrReferenceElement)qualifier).getQualifier() != null) { + return; + } + PsiElement target = ((GrReferenceElement)qualifier).resolve(); + if (target != null && !(target instanceof PsiPackage)) { + return; + } + + String fullPrefix = position.getContainingFile().getText().substring(parent.getTextRange().getStartOffset(), parameters.getOffset()); + final CompletionResultSet qualifiedCollector = result.withPrefixMatcher(fullPrefix); + InheritorsHolder inheritors = new InheritorsHolder(position, result); + for (final LookupElement base : suggestQualifierItems(parameters, (GrReferenceElement)qualifier, inheritors)) { + final PsiType type = JavaCompletionUtil.getLookupElementType(base); + if (type != null && !PsiType.VOID.equals(type)) { + GrReferenceElement ref = createMockReference(position, type, base); + PsiElement refName = ref.getReferenceNameElement(); + assert refName != null; + CompletionParameters newParams = parameters.withPosition(refName, refName.getTextRange().getStartOffset()); + GroovyCompletionContributor.completeReference(newParams, ref, inheritors, result.getPrefixMatcher(), new Consumer() { + @Override + public void consume(LookupElement element) { + qualifiedCollector.addElement(new JavaChainLookupElement(base, element) { + @Override + protected boolean shouldParenthesizeQualifier(PsiFile file, int startOffset, int endOffset) { + return false; + } + }); + } + }); + } + } + } + + private static GrReferenceElement createMockReference(final PsiElement place, @NotNull PsiType qualifierType, LookupElement qualifierItem) { + GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(place.getProject()); + if (qualifierItem.getObject() instanceof PsiClass) { + return factory + .createReferenceExpressionFromText(((PsiClass)qualifierItem.getObject()).getQualifiedName() + ".xxx", place); + } + + return factory.createReferenceExpressionFromText("xxx.xxx", + JavaCompletionUtil + .createContextWithXxxVariable(place, qualifierType)); + } + + + private static Set suggestQualifierItems(CompletionParameters _parameters, + GrReferenceElement qualifier, + InheritorsHolder inheritors) { + CompletionParameters parameters = + _parameters.withPosition(qualifier.getReferenceNameElement(), qualifier.getTextRange().getEndOffset()); + String referenceName = qualifier.getReferenceName(); + if (referenceName == null) { + return Collections.emptySet(); + } + + final PrefixMatcher qMatcher = new CamelHumpMatcher(referenceName); + final Set variants = new LinkedHashSet(); + GroovyCompletionContributor.completeReference(parameters, qualifier, inheritors, qMatcher, new Consumer() { + @Override + public void consume(LookupElement element) { + if (qMatcher.prefixMatches(element)) { + variants.add(element); + } + } + }); + + for (PsiClass aClass : PsiShortNamesCache.getInstance(qualifier.getProject()).getClassesByName(referenceName, qualifier.getResolveScope())) { + variants.add(GroovyCompletionUtil.createClassLookupItem(aClass)); + } + + + if (variants.isEmpty()) { + GroovyCompletionContributor.addAllClasses(parameters, new Consumer() { + @Override + public void consume(LookupElement element) { + if (qMatcher.prefixMatches(element)) { + variants.add(element); + } + } + }, inheritors, qMatcher); + } + return variants; + } + + +} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy index 4b2c458e6d94..1effb9ba323f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -1399,21 +1399,19 @@ def bar(){}''') } public void testPreferApplicableAnnotations() { - configure(''' + myFixture.addClass ''' import java.lang.annotation.ElementType; import java.lang.annotation.Target; -@Z -@interface Foo { -} +@Target({ElementType.ANNOTATION_TYPE}) +@interface TMetaAnno {} -@Target(ElementType.ANNOTATION_TYPE) -@interface ZMetaAnno {} +@Target({ElementType.LOCAL_VARIABLE}) +@interface TLocalAnno {}''' -@Target(ElementType.LOCAL_VARIABLE) -@interface ZLocalAnno {}''') + configure('@T @interface Foo {}') myFixture.completeBasic() - myFixture.assertPreferredCompletionItems 0, 'ZMetaAnno', 'ZLocalAnno' + myFixture.assertPreferredCompletionItems 0, 'TMetaAnno', 'Target', 'TreeSelectionMode', 'TLocalAnno' } } \ No newline at end of file From 8b19d329d20a7535c803624ff52f439b7b4187b1 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 24 Jul 2012 14:33:08 +0400 Subject: [PATCH 09/51] EA-36585 - ISE: ComponentManagerImpl.getPicoContainer --- .../idea/maven/project/MavenProjectsManager.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java index 4cea7a342eb8..c566f537d32c 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java @@ -18,6 +18,7 @@ package org.jetbrains.idea.maven.project; import com.intellij.ide.startup.StartupManagerEx; import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.components.*; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.module.Module; @@ -334,10 +335,21 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent if (shouldScheduleProject(projectWithChanges)) { scheduleForNextImport(projectWithChanges); + MavenImportingSettings importingSettings; + + AccessToken token = ReadAction.start(); + try { + if (myProject.isDisposed()) return; + importingSettings = getImportingSettings(); + } + finally { + token.finish(); + } + scheduleArtifactsDownloading(Collections.singleton(projectWithChanges.first), null, - getImportingSettings().isDownloadSourcesAutomatically(), - getImportingSettings().isDownloadDocsAutomatically(), + importingSettings.isDownloadSourcesAutomatically(), + importingSettings.isDownloadDocsAutomatically(), null); } From 5a3327e431e4a4d2e07d65ff4aa9ff55c5c816fe Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 24 Jul 2012 14:41:31 +0400 Subject: [PATCH 10/51] EA-36393 - NPE: EncodingProjectManager.getInstance --- .../maven/importing/MavenModuleImporter.java | 492 +++++++++--------- 1 file changed, 246 insertions(+), 246 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java index 5eee5a640775..a319b64bac20 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java @@ -1,246 +1,246 @@ -/* - * Copyright 2000-2009 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. - */ -package org.jetbrains.idea.maven.importing; - -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleType; -import com.intellij.openapi.roots.*; -import com.intellij.openapi.roots.libraries.Library; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.JarFileSystem; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.encoding.EncodingManager; -import com.intellij.pom.java.LanguageLevel; -import org.jdom.Element; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.model.MavenArtifact; -import org.jetbrains.idea.maven.model.MavenConstants; -import org.jetbrains.idea.maven.project.*; -import org.jetbrains.idea.maven.utils.MavenUtil; - -import java.nio.charset.Charset; -import java.nio.charset.IllegalCharsetNameException; -import java.nio.charset.UnsupportedCharsetException; -import java.util.List; -import java.util.Map; - -public class MavenModuleImporter { - private final Module myModule; - private final MavenProjectsTree myMavenTree; - private final MavenProject myMavenProject; - - @Nullable - private final MavenProjectChanges myMavenProjectChanges; - private final Map myMavenProjectToModuleName; - private final MavenImportingSettings mySettings; - private final MavenModifiableModelsProvider myModifiableModelsProvider; - private MavenRootModelAdapter myRootModelAdapter; - - public MavenModuleImporter(Module module, - MavenProjectsTree mavenTree, - MavenProject mavenProject, - @Nullable MavenProjectChanges changes, - Map mavenProjectToModuleName, - MavenImportingSettings settings, - MavenModifiableModelsProvider modifiableModelsProvider) { - myModule = module; - myMavenTree = mavenTree; - myMavenProject = mavenProject; - myMavenProjectChanges = changes; - myMavenProjectToModuleName = mavenProjectToModuleName; - mySettings = settings; - myModifiableModelsProvider = modifiableModelsProvider; - } - - public ModifiableRootModel getRootModel() { - return myRootModelAdapter.getRootModel(); - } - - public void config(boolean isNewlyCreatedModule) { - myRootModelAdapter = new MavenRootModelAdapter(myMavenProject, myModule, myModifiableModelsProvider); - myRootModelAdapter.init(isNewlyCreatedModule); - - configFolders(); - configDependencies(); - configLanguageLevel(); - configEncoding(); - } - - public void preConfigFacets() { - final ModuleType moduleType = ModuleType.get(myModule); - - for (final MavenImporter importer : getSuitableImporters()) { - final MavenProjectChanges changes; - if (myMavenProjectChanges == null) { - if (importer.processChangedModulesOnly()) continue; - changes = MavenProjectChanges.NONE; - } - else { - changes = myMavenProjectChanges; - } - - if (importer.getModuleType() == moduleType) { - // facets use FacetConfiguration and like that do not have modifiable models, - // therefore we have to take write lock - MavenUtil.invokeAndWaitWriteAction(myModule.getProject(), new Runnable() { - public void run() { - importer.preProcess(myModule, myMavenProject, changes, myModifiableModelsProvider); - } - }); - } - } - } - - public void configFacets(final List postTasks) { - final ModuleType moduleType = ModuleType.get(myModule); - - for (final MavenImporter importer : getSuitableImporters()) { - final MavenProjectChanges changes; - if (myMavenProjectChanges == null) { - if (importer.processChangedModulesOnly()) continue; - changes = MavenProjectChanges.NONE; - } - else { - changes = myMavenProjectChanges; - } - - if (importer.getModuleType() == moduleType) { - // facets use FacetConfiguration and like that do not have modifiable models, - // therefore we have to take write lock - MavenUtil.invokeAndWaitWriteAction(myModule.getProject(), new Runnable() { - public void run() { - importer.process(myModifiableModelsProvider, - myModule, - myRootModelAdapter, - myMavenTree, - myMavenProject, - changes, - myMavenProjectToModuleName, - postTasks); - } - }); - } - } - } - - private List getSuitableImporters() { - return myMavenProject.getSuitableImporters(); - } - - private void configFolders() { - new MavenFoldersImporter(myMavenProject, mySettings, myRootModelAdapter).config(); - } - - private void configDependencies() { - for (MavenArtifact artifact : myMavenProject.getDependencies()) { - if (!myMavenProject.isSupportedDependency(artifact, SupportedRequestType.FOR_IMPORT)) continue; - - DependencyScope scope = selectScope(artifact.getScope()); - MavenProject depProject = myMavenTree.findProject(artifact.getMavenId()); - - if (depProject != null) { - if (depProject == myMavenProject) continue; - myRootModelAdapter.addModuleDependency(myMavenProjectToModuleName.get(depProject), scope); - - Element buildHelperCfg = depProject.getPluginGoalConfiguration("org.codehaus.mojo", "build-helper-maven-plugin", "attach-artifact"); - if (buildHelperCfg != null) { - addAttachArtifactDependency(buildHelperCfg, scope, depProject, artifact); - } - } - else { - myRootModelAdapter.addLibraryDependency(artifact, scope, myModifiableModelsProvider, myMavenProject); - } - } - } - - private void addAttachArtifactDependency(@NotNull Element buildHelperCfg, - @NotNull DependencyScope scope, - @NotNull MavenProject mavenProject, - @NotNull MavenArtifact artifact) { - Library.ModifiableModel libraryModel = null; - - for (Element artifactsElement : (List)buildHelperCfg.getChildren("artifacts")) { - for (Element artifactElement : (List)artifactsElement.getChildren("artifact")) { - String typeString = artifactElement.getChildTextTrim("type"); - if (typeString != null && !typeString.equals("jar")) continue; - - OrderRootType rootType = OrderRootType.CLASSES; - - String classifier = artifactElement.getChildTextTrim("classifier"); - if ("sources".equals(classifier)) { - rootType = OrderRootType.SOURCES; - } - else if ("javadoc".equals(classifier)) { - rootType = JavadocOrderRootType.getInstance(); - } - - String filePath = artifactElement.getChildTextTrim("file"); - if (StringUtil.isEmpty(filePath)) continue; - - VirtualFile file = VfsUtil.findRelativeFile(filePath, mavenProject.getDirectoryFile()); - if (file == null) continue; - - file = JarFileSystem.getInstance().getJarRootForLocalFile(file); - if (file == null) continue; - - if (libraryModel == null) { - String libraryName = artifact.getLibraryName(); - assert libraryName.startsWith(MavenArtifact.MAVEN_LIB_PREFIX); - libraryName = MavenArtifact.MAVEN_LIB_PREFIX + "ATTACHED-JAR: " + libraryName.substring(MavenArtifact.MAVEN_LIB_PREFIX.length()); - - Library library = myModifiableModelsProvider.getLibraryByName(libraryName); - if (library == null) { - library = myModifiableModelsProvider.createLibrary(libraryName); - } - libraryModel = myModifiableModelsProvider.getLibraryModel(library); - - LibraryOrderEntry entry = myRootModelAdapter.getRootModel().addLibraryEntry(library); - entry.setScope(scope); - } - - libraryModel.addRoot(file, rootType); - } - } - } - - @NotNull - private static DependencyScope selectScope(String mavenScope) { - if (MavenConstants.SCOPE_RUNTIME.equals(mavenScope)) return DependencyScope.RUNTIME; - if (MavenConstants.SCOPE_TEST.equals(mavenScope)) return DependencyScope.TEST; - if (MavenConstants.SCOPE_PROVIDEED.equals(mavenScope)) return DependencyScope.PROVIDED; - return DependencyScope.COMPILE; - } - - private void configEncoding() { - if (Boolean.parseBoolean(System.getProperty("maven.disable.encode.import"))) return; - - String encoding = myMavenProject.getEncoding(); - if (encoding != null) { - try { - EncodingManager.getInstance().setEncoding(myMavenProject.getDirectoryFile(), Charset.forName(encoding)); - } - catch (UnsupportedCharsetException ignored) {/**/} - catch (IllegalCharsetNameException ignored) {/**/} - } - } - - private void configLanguageLevel() { - final LanguageLevel level = LanguageLevel.parse(myMavenProject.getSourceLevel()); - myRootModelAdapter.setLanguageLevel(level); - } -} +/* + * Copyright 2000-2009 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. + */ +package org.jetbrains.idea.maven.importing; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleType; +import com.intellij.openapi.roots.*; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.JarFileSystem; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.encoding.EncodingProjectManager; +import com.intellij.pom.java.LanguageLevel; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.maven.model.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenConstants; +import org.jetbrains.idea.maven.project.*; +import org.jetbrains.idea.maven.utils.MavenUtil; + +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; +import java.util.List; +import java.util.Map; + +public class MavenModuleImporter { + private final Module myModule; + private final MavenProjectsTree myMavenTree; + private final MavenProject myMavenProject; + + @Nullable + private final MavenProjectChanges myMavenProjectChanges; + private final Map myMavenProjectToModuleName; + private final MavenImportingSettings mySettings; + private final MavenModifiableModelsProvider myModifiableModelsProvider; + private MavenRootModelAdapter myRootModelAdapter; + + public MavenModuleImporter(Module module, + MavenProjectsTree mavenTree, + MavenProject mavenProject, + @Nullable MavenProjectChanges changes, + Map mavenProjectToModuleName, + MavenImportingSettings settings, + MavenModifiableModelsProvider modifiableModelsProvider) { + myModule = module; + myMavenTree = mavenTree; + myMavenProject = mavenProject; + myMavenProjectChanges = changes; + myMavenProjectToModuleName = mavenProjectToModuleName; + mySettings = settings; + myModifiableModelsProvider = modifiableModelsProvider; + } + + public ModifiableRootModel getRootModel() { + return myRootModelAdapter.getRootModel(); + } + + public void config(boolean isNewlyCreatedModule) { + myRootModelAdapter = new MavenRootModelAdapter(myMavenProject, myModule, myModifiableModelsProvider); + myRootModelAdapter.init(isNewlyCreatedModule); + + configFolders(); + configDependencies(); + configLanguageLevel(); + configEncoding(); + } + + public void preConfigFacets() { + final ModuleType moduleType = ModuleType.get(myModule); + + for (final MavenImporter importer : getSuitableImporters()) { + final MavenProjectChanges changes; + if (myMavenProjectChanges == null) { + if (importer.processChangedModulesOnly()) continue; + changes = MavenProjectChanges.NONE; + } + else { + changes = myMavenProjectChanges; + } + + if (importer.getModuleType() == moduleType) { + // facets use FacetConfiguration and like that do not have modifiable models, + // therefore we have to take write lock + MavenUtil.invokeAndWaitWriteAction(myModule.getProject(), new Runnable() { + public void run() { + importer.preProcess(myModule, myMavenProject, changes, myModifiableModelsProvider); + } + }); + } + } + } + + public void configFacets(final List postTasks) { + final ModuleType moduleType = ModuleType.get(myModule); + + for (final MavenImporter importer : getSuitableImporters()) { + final MavenProjectChanges changes; + if (myMavenProjectChanges == null) { + if (importer.processChangedModulesOnly()) continue; + changes = MavenProjectChanges.NONE; + } + else { + changes = myMavenProjectChanges; + } + + if (importer.getModuleType() == moduleType) { + // facets use FacetConfiguration and like that do not have modifiable models, + // therefore we have to take write lock + MavenUtil.invokeAndWaitWriteAction(myModule.getProject(), new Runnable() { + public void run() { + importer.process(myModifiableModelsProvider, + myModule, + myRootModelAdapter, + myMavenTree, + myMavenProject, + changes, + myMavenProjectToModuleName, + postTasks); + } + }); + } + } + } + + private List getSuitableImporters() { + return myMavenProject.getSuitableImporters(); + } + + private void configFolders() { + new MavenFoldersImporter(myMavenProject, mySettings, myRootModelAdapter).config(); + } + + private void configDependencies() { + for (MavenArtifact artifact : myMavenProject.getDependencies()) { + if (!myMavenProject.isSupportedDependency(artifact, SupportedRequestType.FOR_IMPORT)) continue; + + DependencyScope scope = selectScope(artifact.getScope()); + MavenProject depProject = myMavenTree.findProject(artifact.getMavenId()); + + if (depProject != null) { + if (depProject == myMavenProject) continue; + myRootModelAdapter.addModuleDependency(myMavenProjectToModuleName.get(depProject), scope); + + Element buildHelperCfg = depProject.getPluginGoalConfiguration("org.codehaus.mojo", "build-helper-maven-plugin", "attach-artifact"); + if (buildHelperCfg != null) { + addAttachArtifactDependency(buildHelperCfg, scope, depProject, artifact); + } + } + else { + myRootModelAdapter.addLibraryDependency(artifact, scope, myModifiableModelsProvider, myMavenProject); + } + } + } + + private void addAttachArtifactDependency(@NotNull Element buildHelperCfg, + @NotNull DependencyScope scope, + @NotNull MavenProject mavenProject, + @NotNull MavenArtifact artifact) { + Library.ModifiableModel libraryModel = null; + + for (Element artifactsElement : (List)buildHelperCfg.getChildren("artifacts")) { + for (Element artifactElement : (List)artifactsElement.getChildren("artifact")) { + String typeString = artifactElement.getChildTextTrim("type"); + if (typeString != null && !typeString.equals("jar")) continue; + + OrderRootType rootType = OrderRootType.CLASSES; + + String classifier = artifactElement.getChildTextTrim("classifier"); + if ("sources".equals(classifier)) { + rootType = OrderRootType.SOURCES; + } + else if ("javadoc".equals(classifier)) { + rootType = JavadocOrderRootType.getInstance(); + } + + String filePath = artifactElement.getChildTextTrim("file"); + if (StringUtil.isEmpty(filePath)) continue; + + VirtualFile file = VfsUtil.findRelativeFile(filePath, mavenProject.getDirectoryFile()); + if (file == null) continue; + + file = JarFileSystem.getInstance().getJarRootForLocalFile(file); + if (file == null) continue; + + if (libraryModel == null) { + String libraryName = artifact.getLibraryName(); + assert libraryName.startsWith(MavenArtifact.MAVEN_LIB_PREFIX); + libraryName = MavenArtifact.MAVEN_LIB_PREFIX + "ATTACHED-JAR: " + libraryName.substring(MavenArtifact.MAVEN_LIB_PREFIX.length()); + + Library library = myModifiableModelsProvider.getLibraryByName(libraryName); + if (library == null) { + library = myModifiableModelsProvider.createLibrary(libraryName); + } + libraryModel = myModifiableModelsProvider.getLibraryModel(library); + + LibraryOrderEntry entry = myRootModelAdapter.getRootModel().addLibraryEntry(library); + entry.setScope(scope); + } + + libraryModel.addRoot(file, rootType); + } + } + } + + @NotNull + private static DependencyScope selectScope(String mavenScope) { + if (MavenConstants.SCOPE_RUNTIME.equals(mavenScope)) return DependencyScope.RUNTIME; + if (MavenConstants.SCOPE_TEST.equals(mavenScope)) return DependencyScope.TEST; + if (MavenConstants.SCOPE_PROVIDEED.equals(mavenScope)) return DependencyScope.PROVIDED; + return DependencyScope.COMPILE; + } + + private void configEncoding() { + if (Boolean.parseBoolean(System.getProperty("maven.disable.encode.import"))) return; + + String encoding = myMavenProject.getEncoding(); + if (encoding != null) { + try { + EncodingProjectManager.getInstance(myModule.getProject()).setEncoding(myMavenProject.getDirectoryFile(), Charset.forName(encoding)); + } + catch (UnsupportedCharsetException ignored) {/**/} + catch (IllegalCharsetNameException ignored) {/**/} + } + } + + private void configLanguageLevel() { + final LanguageLevel level = LanguageLevel.parse(myMavenProject.getSourceLevel()); + myRootModelAdapter.setLanguageLevel(level); + } +} From a17fbd9b81e92d1a4e77c8aa6a8a82be4c504763 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 24 Jul 2012 14:56:37 +0400 Subject: [PATCH 11/51] IDEA-66333 Quick documentation lookup on mouse hover Corrected links appliance in case of partial head match --- .../navigation/DocPreviewUtil.java | 4 ++++ .../navigation/DocPreviewUtilTest.groovy | 20 ++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/DocPreviewUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/DocPreviewUtil.java index 70c485b6b1cf..63d95d730fca 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/DocPreviewUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/DocPreviewUtil.java @@ -191,6 +191,10 @@ public class DocPreviewUtil { // We don't want to perform the replacement then. continue; } + if (end - i > 1 && i > 0 && !ALLOWED_LINK_SEPARATORS.contains(text.charAt(i - 1))) { + // Similar situation but targets head match: from = 'TextRange', text = 'getTextRange()'. + continue; + } text.replace(i, end, replaceTo); int diff = replaceTo.length() - replaceFrom.length(); for (int j = 0; j < readOnlyChanges.size(); j++) { diff --git a/platform/lang-impl/testSources/com/intellij/codeInsight/navigation/DocPreviewUtilTest.groovy b/platform/lang-impl/testSources/com/intellij/codeInsight/navigation/DocPreviewUtilTest.groovy index 31b235dcd1ca..22df21db934c 100644 --- a/platform/lang-impl/testSources/com/intellij/codeInsight/navigation/DocPreviewUtilTest.groovy +++ b/platform/lang-impl/testSources/com/intellij/codeInsight/navigation/DocPreviewUtilTest.groovy @@ -147,7 +147,7 @@ Qname''' } @Test - void substrings() { + void tailSubstrings() { def header = '''\ PsiResolveHelperImpl public static com.intellij.openapi.util.Pair<com.intellij.psi.PsiType, com.intellij.psi.ConstraintType> getSubstitutionForTypeParameterConstraint (com.intellij.psi.PsiTypeParameter typeParam, com.intellij.psi.PsiType param, com.intellij.psi.PsiType arg, boolean isContraVariantPosition, com.intellij.pom.java.LanguageLevel languageLevel)''' @@ -164,4 +164,22 @@ public static com.intellij.openapi.util.Pair<com.intellij.psi.PsiType, com.in assertEquals(expected, DocPreviewUtil.buildPreview(header, null, fullText)) } + + @Test + void headSubstrings() { + def header = '''\ +ASTNode +com.intellij.openapi.util.TextRange getTextRange ()''' + + def fullText = '''\ + com.intellij.lang.ASTNode
TextRange getTextRange()
+ Returns the text range (a combination of starting offset in the document and length) for this node. + +
Returns:
the text range.
''' + + def expected = '''\ +ASTNode
TextRange getTextRange ()''' + + assertEquals(expected, DocPreviewUtil.buildPreview(header, null, fullText)) + } } From 776321540ff68c0dcdaff267dcc4eeaab14e0933 Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 24 Jul 2012 15:07:36 +0400 Subject: [PATCH 12/51] EA-37638 - IAE: ArtifactType.findById --- .../jps/model/serialization/artifact/ArtifactState.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactState.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactState.java index 2d7c02a5f385..0ebdbfbb84db 100644 --- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactState.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactState.java @@ -33,7 +33,7 @@ public class ArtifactState { @NonNls public static final String NAME_ATTRIBUTE = "name"; private String myName; private String myOutputPath; - private String myArtifactType; + private String myArtifactType = "plain"; private boolean myBuildOnMake; private Element myRootElement; private List myPropertiesList = new ArrayList(); From 69772a119e4d14e3b5e4cbad89974237e89813c9 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 24 Jul 2012 14:28:07 +0400 Subject: [PATCH 13/51] IDEA-89177 refresh generated apk file --- .../org/jetbrains/android/exportSignedPackage/ApkStep.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/android/src/org/jetbrains/android/exportSignedPackage/ApkStep.java b/plugins/android/src/org/jetbrains/android/exportSignedPackage/ApkStep.java index 4e674dee5306..904c0d7cfc87 100644 --- a/plugins/android/src/org/jetbrains/android/exportSignedPackage/ApkStep.java +++ b/plugins/android/src/org/jetbrains/android/exportSignedPackage/ApkStep.java @@ -252,11 +252,16 @@ class ApkStep extends ExportSignedPackageWizardStep { public void run() { String title = AndroidBundle.message("android.export.package.wizard.title"); final Project project = myWizard.getProject(); + final File apkFile = new File(apkPath); + + final VirtualFile vApkFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(apkFile); + if (vApkFile != null) { + vApkFile.refresh(true, false); + } if (!runZipAlign) { Messages.showWarningDialog(project, AndroidBundle.message("cannot.find.zip.align"), title); } - final File apkFile = new File(apkPath); if (ShowFilePathAction.isSupported()) { if (Messages.showOkCancelDialog(project, AndroidBundle.message("android.export.package.success.message", apkFile.getName()), From e49515e1bdb06175fa3dc3191987278edcd192dc Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 24 Jul 2012 15:00:32 +0400 Subject: [PATCH 14/51] IDEA-89125 provide dimension keys for number of dialogs --- .../android/actions/AndroidProcessChooserDialog.java | 5 +++++ .../android/actions/CreateResourceDirectoryDialog.java | 5 +++++ .../jetbrains/android/actions/CreateResourceFileDialog.java | 5 +++++ .../jetbrains/android/actions/CreateXmlResourceDialog.java | 5 +++++ .../src/org/jetbrains/android/run/DeviceChooserDialog.java | 5 +++++ .../jetbrains/android/run/ExtendedDeviceChooserDialog.java | 5 +++++ .../jetbrains/android/uipreview/EditConfigurationDialog.java | 5 +++++ .../android/uipreview/LayoutDeviceConfigurationsDialog.java | 5 +++++ 8 files changed, 40 insertions(+) diff --git a/plugins/android/src/org/jetbrains/android/actions/AndroidProcessChooserDialog.java b/plugins/android/src/org/jetbrains/android/actions/AndroidProcessChooserDialog.java index e41808994894..4176b09cee43 100644 --- a/plugins/android/src/org/jetbrains/android/actions/AndroidProcessChooserDialog.java +++ b/plugins/android/src/org/jetbrains/android/actions/AndroidProcessChooserDialog.java @@ -417,6 +417,11 @@ public class AndroidProcessChooserDialog extends DialogWrapper { closeOldSessionAndRun(debugPort); } + @Override + protected String getDimensionServiceKey() { + return "AndroidProcessChooserDialog"; + } + private void closeOldSessionAndRun(final String debugPort) { final String configurationName = getRunConfigurationName(debugPort); final Collection descriptors = diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateResourceDirectoryDialog.java b/plugins/android/src/org/jetbrains/android/actions/CreateResourceDirectoryDialog.java index d3111600b9a6..d88fc300b483 100644 --- a/plugins/android/src/org/jetbrains/android/actions/CreateResourceDirectoryDialog.java +++ b/plugins/android/src/org/jetbrains/android/actions/CreateResourceDirectoryDialog.java @@ -107,6 +107,11 @@ public abstract class CreateResourceDirectoryDialog extends DialogWrapper { } } + @Override + protected String getDimensionServiceKey() { + return "AndroidCreateResourceDirectoryDialog"; + } + @Override public JComponent getPreferredFocusedComponent() { return myResourceTypeComboBox; diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileDialog.java b/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileDialog.java index a4bd770f4830..50137e580186 100644 --- a/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileDialog.java +++ b/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileDialog.java @@ -265,6 +265,11 @@ public class CreateResourceFileDialog extends DialogWrapper { } } + @Override + protected String getDimensionServiceKey() { + return "AndroidCreateResourceFileDialog"; + } + @NotNull public Module getSelectedModule() { return (Module)myModuleCombo.getSelectedItem(); diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java b/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java index 972e765f78bd..baef99fe9126 100644 --- a/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java +++ b/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java @@ -435,6 +435,11 @@ public class CreateXmlResourceDialog extends DialogWrapper { } } + @Override + protected String getDimensionServiceKey() { + return "AndroidCreateXmlResourceDialog"; + } + @NotNull public String getResourceName() { return myNameField.getText().trim(); diff --git a/plugins/android/src/org/jetbrains/android/run/DeviceChooserDialog.java b/plugins/android/src/org/jetbrains/android/run/DeviceChooserDialog.java index 1d1fd69085ff..6e865b0a2e55 100644 --- a/plugins/android/src/org/jetbrains/android/run/DeviceChooserDialog.java +++ b/plugins/android/src/org/jetbrains/android/run/DeviceChooserDialog.java @@ -61,6 +61,11 @@ public class DeviceChooserDialog extends DialogWrapper { super.doOKAction(); } + @Override + protected String getDimensionServiceKey() { + return "AndroidDeviceChooserDialog"; + } + protected JComponent createCenterPanel() { return myDeviceChooser.getPanel(); } diff --git a/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.java b/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.java index 5cd03042bc56..ccb449ac3aa4 100644 --- a/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.java +++ b/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.java @@ -165,6 +165,11 @@ public class ExtendedDeviceChooserDialog extends DialogWrapper { super.doOKAction(); } + @Override + protected String getDimensionServiceKey() { + return "AndroidExtendedDeviceChooserDialog"; + } + protected JComponent createCenterPanel() { return myPanel; } diff --git a/plugins/android/src/org/jetbrains/android/uipreview/EditConfigurationDialog.java b/plugins/android/src/org/jetbrains/android/uipreview/EditConfigurationDialog.java index f16ffc153a0f..e64eb678ead1 100644 --- a/plugins/android/src/org/jetbrains/android/uipreview/EditConfigurationDialog.java +++ b/plugins/android/src/org/jetbrains/android/uipreview/EditConfigurationDialog.java @@ -109,6 +109,11 @@ public class EditConfigurationDialog extends DialogWrapper { myDeviceConfiguratorPanel.applyEditors(); } + @Override + protected String getDimensionServiceKey() { + return "AndroidEditLayoutDeviceConfigurationDialog"; + } + @Override public JComponent getPreferredFocusedComponent() { if (myEditDeviceForm.getNameField().getText().length() == 0) { diff --git a/plugins/android/src/org/jetbrains/android/uipreview/LayoutDeviceConfigurationsDialog.java b/plugins/android/src/org/jetbrains/android/uipreview/LayoutDeviceConfigurationsDialog.java index 55f07edac269..b45b32afa16d 100644 --- a/plugins/android/src/org/jetbrains/android/uipreview/LayoutDeviceConfigurationsDialog.java +++ b/plugins/android/src/org/jetbrains/android/uipreview/LayoutDeviceConfigurationsDialog.java @@ -603,4 +603,9 @@ public class LayoutDeviceConfigurationsDialog extends DialogWrapper { protected JComponent createCenterPanel() { return myContentPanel; } + + @Override + protected String getDimensionServiceKey() { + return "AndroidLayoutDeviceConfigurationsDialog"; + } } From 1df902aa65299ee0ef805cf6e03830a1fc93af5a Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 24 Jul 2012 15:00:58 +0400 Subject: [PATCH 15/51] remove unused files --- .../GenerateSignedApkDialog.java | 71 ----- .../GreateSignedApkDialog.form | 187 ------------ .../newProject/CreateLibraryDialog.form | 40 --- .../newProject/CreateLibraryDialog.java | 60 ---- .../org/jetbrains/android/run/AvdChooser.form | 74 ----- .../org/jetbrains/android/run/AvdChooser.java | 286 ------------------ 6 files changed, 718 deletions(-) delete mode 100644 plugins/android/src/org/jetbrains/android/exportSignedPackage/GenerateSignedApkDialog.java delete mode 100644 plugins/android/src/org/jetbrains/android/exportSignedPackage/GreateSignedApkDialog.form delete mode 100644 plugins/android/src/org/jetbrains/android/newProject/CreateLibraryDialog.form delete mode 100644 plugins/android/src/org/jetbrains/android/newProject/CreateLibraryDialog.java delete mode 100644 plugins/android/src/org/jetbrains/android/run/AvdChooser.form delete mode 100644 plugins/android/src/org/jetbrains/android/run/AvdChooser.java diff --git a/plugins/android/src/org/jetbrains/android/exportSignedPackage/GenerateSignedApkDialog.java b/plugins/android/src/org/jetbrains/android/exportSignedPackage/GenerateSignedApkDialog.java deleted file mode 100644 index affdca089c0a..000000000000 --- a/plugins/android/src/org/jetbrains/android/exportSignedPackage/GenerateSignedApkDialog.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.jetbrains.android.exportSignedPackage; - -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.ui.TextFieldWithBrowseButton; -import com.intellij.ui.CollectionComboBoxModel; -import com.intellij.ui.components.JBCheckBox; -import org.jetbrains.android.facet.AndroidFacet; -import org.jetbrains.android.util.ModuleListCellRendererWrapper; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Eugene.Kudelevsky - */ -public class GenerateSignedApkDialog extends DialogWrapper { - private JCheckBox myProGuardCheckBox; - private JComboBox myModuleComboBox; - private JPanel myPanel; - private JPasswordField myKeyStorePasswordField; - private JPasswordField myKeyPasswordField; - private TextFieldWithBrowseButton.NoPathCompletion myKeyAliasField; - private JTextField myKeyStorePathField; - private JPanel myKeyStoreButtonsPanel; - private JButton myCreateKeyStoreButton; - private JButton myLoadKeyStoreButton; - private JBCheckBox myRememberPasswordsCheckBox; - private TextFieldWithBrowseButton myProGuardConfigFilePathField; - private JCheckBox myIncludeSystemProGuardFileCheckBox; - private TextFieldWithBrowseButton.NoPathCompletion myApkPathField; - - protected GenerateSignedApkDialog(@NotNull Project project, @Nullable Module defaultModule) { - super(project); - setTitle("Generate Signed APK"); - - final List androidAppModules = new ArrayList(); - for (Module module : ModuleManager.getInstance(project).getModules()) { - final AndroidFacet facet = AndroidFacet.getInstance(module); - if (facet != null && !facet.getConfiguration().LIBRARY_PROJECT) { - androidAppModules.add(module); - } - } - myModuleComboBox.setModel( - new CollectionComboBoxModel(androidAppModules, androidAppModules.contains(defaultModule) ? defaultModule : androidAppModules.get(0))); - myModuleComboBox.setRenderer(new ModuleListCellRendererWrapper(myModuleComboBox.getRenderer())); - - myModuleComboBox.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - //To change body of implemented methods use File | Settings | File Templates. - } - }); - - init(); - } - - @Override - protected JComponent createCenterPanel() { - return myPanel; - } - - -} diff --git a/plugins/android/src/org/jetbrains/android/exportSignedPackage/GreateSignedApkDialog.form b/plugins/android/src/org/jetbrains/android/exportSignedPackage/GreateSignedApkDialog.form deleted file mode 100644 index e8609309e905..000000000000 --- a/plugins/android/src/org/jetbrains/android/exportSignedPackage/GreateSignedApkDialog.form +++ /dev/null @@ -1,187 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/plugins/android/src/org/jetbrains/android/newProject/CreateLibraryDialog.form b/plugins/android/src/org/jetbrains/android/newProject/CreateLibraryDialog.form deleted file mode 100644 index 0d202e3c0803..000000000000 --- a/plugins/android/src/org/jetbrains/android/newProject/CreateLibraryDialog.form +++ /dev/null @@ -1,40 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/plugins/android/src/org/jetbrains/android/newProject/CreateLibraryDialog.java b/plugins/android/src/org/jetbrains/android/newProject/CreateLibraryDialog.java deleted file mode 100644 index 0515e13eecdd..000000000000 --- a/plugins/android/src/org/jetbrains/android/newProject/CreateLibraryDialog.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2000-2010 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. - */ - -package org.jetbrains.android.newProject; - -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.android.util.AndroidBundle; - -import javax.swing.*; -import java.awt.event.KeyEvent; - -/** - * Created by IntelliJ IDEA. - * User: Eugene.Kudelevsky - * Date: Aug 13, 2009 - * Time: 4:21:39 PM - * To change this template use File | Settings | File Templates. - */ -public class CreateLibraryDialog extends DialogWrapper { - private JPanel myPanel; - private JRadioButton myProjectLibButton; - private JRadioButton myGlobalLibButton; - - public CreateLibraryDialog(@NotNull Project project, @NotNull String libraryName) { - super(project, true); - setModal(true); - setTitle(AndroidBundle.message("create.library.dialog.title")); - myProjectLibButton.setSelected(true); - myProjectLibButton.setMnemonic(KeyEvent.VK_P); - myGlobalLibButton.setMnemonic(KeyEvent.VK_G); - - myProjectLibButton.setText(AndroidBundle.message("create.project.library", libraryName)); - myGlobalLibButton.setText(AndroidBundle.message("create.global.library", libraryName)); - init(); - } - - @Override - protected JComponent createCenterPanel() { - return myPanel; - } - - public boolean isGlobalSelected() { - return myGlobalLibButton.isSelected(); - } -} diff --git a/plugins/android/src/org/jetbrains/android/run/AvdChooser.form b/plugins/android/src/org/jetbrains/android/run/AvdChooser.form deleted file mode 100644 index c8cd07618b12..000000000000 --- a/plugins/android/src/org/jetbrains/android/run/AvdChooser.form +++ /dev/null @@ -1,74 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/plugins/android/src/org/jetbrains/android/run/AvdChooser.java b/plugins/android/src/org/jetbrains/android/run/AvdChooser.java deleted file mode 100644 index 2353cb8ad2ab..000000000000 --- a/plugins/android/src/org/jetbrains/android/run/AvdChooser.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright 2000-2010 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. - */ - -package org.jetbrains.android.run; - -import com.android.ddmlib.AndroidDebugBridge; -import com.android.ddmlib.IDevice; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.SdkConstants; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.internal.avd.AvdManager; -import com.intellij.CommonBundle; -import com.intellij.execution.ExecutionException; -import com.intellij.execution.configurations.GeneralCommandLine; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.ui.Messages; -import com.intellij.ui.DoubleClickListener; -import org.jetbrains.android.facet.AndroidFacet; -import org.jetbrains.android.sdk.AndroidSdkData; -import org.jetbrains.android.sdk.AndroidSdkUtils; -import org.jetbrains.android.util.*; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import javax.swing.table.AbstractTableModel; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseEvent; -import java.io.File; - -/** - * Created by IntelliJ IDEA. - * User: Eugene.Kudelevsky - * Date: May 9, 2009 - * Time: 5:33:45 PM - * To change this template use File | Settings | File Templates. - */ -public class AvdChooser extends DialogWrapper { - private JTable myAvdTable; - private JPanel myPanel; - private JButton myRefreshButton; - private JButton myCreateButton; - private JButton myRemoveButton; - private JButton myStartAvdManagerButton; - private final AvdManager myAvdManager; - private final AndroidFacet myFacet; - private final boolean myCompatibleAvd; - private final boolean myMustSelect; - - private static final String[] COLUMN_TITLES = new String[]{"Name", "Target", "Platform", "API Level", "Valid", "Compatible"}; - - @Nullable - private static String getAndroidToolPath(@NotNull AndroidFacet facet) { - AndroidSdkData sdkData = facet.getConfiguration().getAndroidSdk(); - if (sdkData == null) return null; - String androidCmd = SdkConstants.androidCmdName(); - return sdkData.getLocation() + File.separator + AndroidCommonUtils.toolPath(androidCmd); - } - - public AvdChooser(@NotNull final Project project, - @NotNull final AndroidFacet facet, - @NotNull AvdManager avdManager, - boolean mustSelect, - boolean compatibleAvd) { - super(project, true); - myMustSelect = mustSelect; - setTitle(AndroidBundle.message("avd.dialog.title")); - init(); - myAvdManager = avdManager; - myFacet = facet; - myAvdTable.setModel(new MyAvdTableModel(myFacet.getAllAvds())); - myAvdTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - myCompatibleAvd = compatibleAvd; - myRefreshButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - updateTable(); - } - }); - myCreateButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - createAvd(project, facet); - } - }); - myRemoveButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - removeSelectedAvd(); - } - }); - myAvdTable.setDefaultRenderer(Boolean.class, new BooleanCellRenderer()); - new DoubleClickListener() { - @Override - protected boolean onDoubleClick(MouseEvent e) { - if (isOKActionEnabled()) { - doOKAction(); - return true; - } - return false; - } - }.installOn(myAvdTable); - - final String androidToolPath = getAndroidToolPath(facet); - myStartAvdManagerButton.setEnabled(new File(androidToolPath).exists()); - myStartAvdManagerButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - GeneralCommandLine commandLine = new GeneralCommandLine(); - commandLine.setExePath(androidToolPath); - try { - AndroidUtils.executeCommand(commandLine, new StringBuildingOutputProcessor(), WaitingStrategies.DoNotWait.getInstance()); - } - catch (ExecutionException e1) { - final String message = e1.getMessage() != null ? e1.getMessage() : "Cannot launch AVD manager"; - Messages.showErrorDialog(myPanel, message, CommonBundle.getErrorTitle()); - } - } - }); - updateTable(); - ListSelectionModel selectionModel = myAvdTable.getSelectionModel(); - if (mustSelect) { - if (myAvdTable.getModel().getRowCount() > 0) { - selectionModel.setSelectionInterval(0, 0); - } - } - selectionModel.addListSelectionListener(new ListSelectionListener() { - public void valueChanged(ListSelectionEvent e) { - updateOkAction(); - } - }); - updateOkAction(); - myAvdTable.requestFocus(); - } - - private void updateOkAction() { - AvdInfo avd = getSelectedAvd(); - getOKAction().setEnabled(avd != null ? avd.getStatus() == AvdInfo.AvdStatus.OK : myMustSelect); - } - - @Override - public JComponent getPreferredFocusedComponent() { - return myAvdTable; - } - - private void createAvd(Project project, AndroidFacet facet) { - CreateAvdDialog dialog = new CreateAvdDialog(project, facet, myAvdManager, false, false); - dialog.show(); - if (dialog.getExitCode() == OK_EXIT_CODE) { - updateTable(); - } - } - - private boolean isAvdBusy(@NotNull AvdInfo avd) { - final AndroidDebugBridge bridge = myFacet.getDebugBridge(); - if (bridge == null) return false; - IDevice[] devices = bridge.getDevices(); - for (IDevice device : devices) { - String avdName = device.getAvdName(); - if (avdName != null && avdName.equals(avd.getName())) { - return true; - } - } - return false; - } - - private void removeSelectedAvd() { - AvdInfo selectedAvd = getSelectedAvd(); - if (selectedAvd != null) { - if (isAvdBusy(selectedAvd)) { - Messages.showErrorDialog(myPanel, AndroidBundle.message("cant.remove.avd.error")); - } - else { - myAvdManager.deleteAvd(selectedAvd, AndroidSdkUtils.getSdkLog(myPanel)); - updateTable(); - } - } - } - - private void updateTable() { - int selected = myAvdTable.getSelectedRow(); - myAvdTable.setModel(new MyAvdTableModel(myFacet.getAllAvds())); - myAvdTable.getSelectionModel().setSelectionInterval(selected, selected); - } - - protected JComponent createCenterPanel() { - return myPanel; - } - - @Nullable - public AvdInfo getSelectedAvd() { - MyAvdTableModel model = (MyAvdTableModel)myAvdTable.getModel(); - int selectedRow = myAvdTable.getSelectedRow(); - return selectedRow >= 0 && selectedRow < model.myInfos.length ? model.myInfos[selectedRow] : null; - } - - public void setSelectedAvd(@NotNull String avdName) { - MyAvdTableModel model = (MyAvdTableModel)myAvdTable.getModel(); - for (int i = 0; i < model.myInfos.length; i++) { - AvdInfo info = model.myInfos[i]; - if (info.getName().equals(avdName)) { - myAvdTable.getSelectionModel().setSelectionInterval(i, i); - } - } - } - - private class MyAvdTableModel extends AbstractTableModel { - private final AvdInfo[] myInfos; - - public MyAvdTableModel(AvdInfo[] infos) { - myInfos = infos; - } - - @Override - public String getColumnName(int column) { - return COLUMN_TITLES[column]; - } - - public int getRowCount() { - return myInfos.length; - } - - public int getColumnCount() { - return COLUMN_TITLES.length; - } - - @Nullable - public Object getValueAt(int rowIndex, int columnIndex) { - AvdInfo info = myInfos[rowIndex]; - IAndroidTarget target = info.getTarget(); - final String unknown = ""; - switch (columnIndex) { - case 0: - return info.getName(); - case 1: - return target != null ? target.getName() : unknown; - case 2: - return target != null ? target.getVersionName() : unknown; - case 3: - return target != null ? target.getVersion().getApiString() : unknown; - case 4: - return info.getStatus() == AvdInfo.AvdStatus.OK; - case 5: - return myFacet.isCompatibleAvd(info); - } - return null; - } - - @Override - public Class getColumnClass(int columnIndex) { - if (columnIndex == 4 || columnIndex == 5) { - return Boolean.class; - } - return String.class; - } - } - - @Override - protected String getHelpId() { - return "reference.android.selectAVD"; - } - - @Override - protected void doOKAction() { - AvdInfo selectedAvd = getSelectedAvd(); - if (myCompatibleAvd && selectedAvd != null && !myFacet.isCompatibleAvd(selectedAvd)) { - Messages.showErrorDialog(myPanel, AndroidBundle.message("select.compatible.avd.error")); - return; - } - super.doOKAction(); - } - -} From 001eba63042e5b49a249b60c813b02f25977068a Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 24 Jul 2012 15:04:55 +0400 Subject: [PATCH 16/51] fix dialog scaling --- .../android/run/ExtendedDeviceChooserDialog.form | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.form b/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.form index cb43b8aa8164..e95748900be1 100644 --- a/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.form +++ b/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.form @@ -1,6 +1,6 @@
- + @@ -17,11 +17,6 @@ - - - - - @@ -53,7 +48,7 @@ - + From 5eb1b1604282de0cc4d7f7ec3a54922aecde4a1a Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 24 Jul 2012 15:30:26 +0400 Subject: [PATCH 17/51] fix: update ok action on combo box selection change --- .../org/jetbrains/android/run/ExtendedDeviceChooserDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.java b/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.java index ccb449ac3aa4..6dbce36086f1 100644 --- a/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.java +++ b/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.java @@ -95,7 +95,7 @@ public class ExtendedDeviceChooserDialog extends DialogWrapper { }; myLaunchEmulatorRadioButton.addActionListener(listener); myChooserRunningDeviceRadioButton.addActionListener(listener); - myAvdCombo.addActionListener(listener); + myAvdCombo.getComboBox().addActionListener(listener); init(); From e9ee0ef6c8ac457aad9ce1c38386f3b1044b9e03 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 24 Jul 2012 13:42:32 +0200 Subject: [PATCH 18/51] Ignore broken symlinks on reading file attributes --- bin/win/IdeaWin32.dll | Bin 35840 -> 35840 bytes bin/win/IdeaWin64.dll | Bin 41472 -> 40960 bytes native/IdeaWin32/IdeaWin32.cpp | 59 +++++++++--------- .../util/io/FileAttributesReadingTest.java | 14 ++++- 4 files changed, 44 insertions(+), 29 deletions(-) diff --git a/bin/win/IdeaWin32.dll b/bin/win/IdeaWin32.dll index 7556f14f241129c568079969b9b526272dc99ad3..3cd28fe38ce9f8e5647b48ac14bafb0c774ae849 100644 GIT binary patch delta 2621 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 delta 8894 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 zoP)nW+M&+_eg#AllocObject(fileInfoClass); - if (o == NULL) { - return NULL; - } + DWORD attributes = lpData->dwFileAttributes; + LONGLONG timestamp = pairToInt64(lpData->ftLastWriteTime.dwLowDateTime, lpData->ftLastWriteTime.dwHighDateTime); + LONGLONG length = pairToInt64(lpData->nFileSizeLow, lpData->nFileSizeHigh); - jstring fileName = env->NewString((jchar*)lpData->cFileName, (jsize)wcslen(lpData->cFileName)); - if (fileName == NULL) { - return NULL; - } - env->SetObjectField(o, nameID, fileName); - - bool read = false; - if (IS_SET(lpData->dwFileAttributes, FILE_ATTRIBUTE_REPARSE_POINT)) { + if (IS_SET(attributes, FILE_ATTRIBUTE_REPARSE_POINT)) { if (IS_SET(lpData->dwReserved0, IO_REPARSE_TAG_SYMLINK)) { size_t nameLen = env->GetStringLength(path) + wcslen(lpData->cFileName) + 2; wchar_t *lpName = (wchar_t *)malloc(nameLen * sizeof(wchar_t)); @@ -82,32 +74,43 @@ static jobject CreateFileInfo(JNIEnv *env, jstring path, bool append, LPWIN32_FI // read symlink target attributes HANDLE th = CreateFile(lpName, 0, FILE_SHARE_ATTRIBUTES, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (th != INVALID_HANDLE_VALUE) { - BY_HANDLE_FILE_INFORMATION targetData; - if (GetFileInformationByHandle(th, &targetData)) { - targetData.dwFileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT; - env->SetIntField(o, attributesID, targetData.dwFileAttributes); - env->SetLongField(o, timestampID, pairToInt64(targetData.ftLastWriteTime.dwLowDateTime, targetData.ftLastWriteTime.dwHighDateTime)); - env->SetLongField(o, lengthID, pairToInt64(targetData.nFileSizeLow, targetData.nFileSizeHigh)); - read = true; - } - CloseHandle(th); + free(lpName); + if (th == INVALID_HANDLE_VALUE) { + return NULL; // invalid link } - free(lpName); + BY_HANDLE_FILE_INFORMATION targetData; + BOOL result = GetFileInformationByHandle(th, &targetData); + CloseHandle(th); + if (result == 0) { + return NULL; // invalid link + } + + attributes = targetData.dwFileAttributes | FILE_ATTRIBUTE_REPARSE_POINT; + timestamp = pairToInt64(targetData.ftLastWriteTime.dwLowDateTime, targetData.ftLastWriteTime.dwHighDateTime); + length = pairToInt64(targetData.nFileSizeLow, targetData.nFileSizeHigh); } } else { - lpData->dwFileAttributes &= (~ FILE_ATTRIBUTE_REPARSE_POINT); // keep reparse flag only for symlinks + attributes &= (~ FILE_ATTRIBUTE_REPARSE_POINT); // keep reparse flag only for symlinks } } - if (!read) { - env->SetIntField(o, attributesID, lpData->dwFileAttributes); - env->SetLongField(o, timestampID, pairToInt64(lpData->ftLastWriteTime.dwLowDateTime, lpData->ftLastWriteTime.dwHighDateTime)); - env->SetLongField(o, lengthID, pairToInt64(lpData->nFileSizeLow, lpData->nFileSizeHigh)); + jobject o = env->AllocObject(fileInfoClass); + if (o == NULL) { + return NULL; } + jstring fileName = env->NewString((jchar*)lpData->cFileName, (jsize)wcslen(lpData->cFileName)); + if (fileName == NULL) { + return NULL; + } + env->SetObjectField(o, nameID, fileName); + + env->SetIntField(o, attributesID, attributes); + env->SetLongField(o, timestampID, timestamp); + env->SetLongField(o, lengthID, length); + return o; } diff --git a/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java b/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java index b713b2d38fab..1f0e65e23b6f 100644 --- a/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java +++ b/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java @@ -137,9 +137,21 @@ public class FileAttributesReadingTest { assertEquals(file.getPath(), target); } + @Test + public void missingLink() throws Exception { + final File file = FileUtil.createTempFile(myTempDirectory, "test.", ".txt", false); + final File link = IoTestUtil.createTempLink(file.getPath(), new File(myTempDirectory, "link").getPath()); + + final FileAttributes attributes = FileSystemUtil.getAttributes(link); + assertNull(attributes); + + final String target = FileSystemUtil.resolveSymLink(link); + assertNull(target); + } + @NotNull private static FileAttributes getAttributes(@NotNull final File file) { - final FileAttributes attributes = FileSystemUtil.getAttributes(file.getPath()); + final FileAttributes attributes = FileSystemUtil.getAttributes(file); assertNotNull(attributes); System.out.println(attributes); return attributes; From f05916c5f2e4b0fa40453eb6cf6263c3e102ae74 Mon Sep 17 00:00:00 2001 From: Mikhail Senkov Date: Tue, 24 Jul 2012 14:10:39 +0400 Subject: [PATCH 19/51] OC-4427 --- .../com/intellij/lang/ForeignLeafType.java | 2 +- .../intellij/lang/impl/PsiBuilderImpl.java | 14 ++++++------- .../source/tree/ForeignLeafPsiElement.java | 20 +++++++++++++++++-- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/platform/core-impl/src/com/intellij/lang/ForeignLeafType.java b/platform/core-impl/src/com/intellij/lang/ForeignLeafType.java index bc114917769d..f6e8f3065333 100644 --- a/platform/core-impl/src/com/intellij/lang/ForeignLeafType.java +++ b/platform/core-impl/src/com/intellij/lang/ForeignLeafType.java @@ -32,6 +32,6 @@ public class ForeignLeafType extends TokenWrapper implements ILeafElementType { @Override @NotNull public ASTNode createLeafNode(CharSequence leafText) { - return new ForeignLeafPsiElement(getDelegate(), getValue()); + return new ForeignLeafPsiElement(this, getValue()); } } diff --git a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java index 15ce63211bce..9d6e1ef3f87a 100644 --- a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java +++ b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java @@ -1367,15 +1367,13 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder, AS return ourAnyLanguageWhitespaceTokens.contains(n2.getTokenType()) || n2 instanceof Token && ((Token)n2).myBuilder.myWhitespaces.contains(n2.getTokenType()); } + IElementType n1t; + if (n1 instanceof ForeignLeafPsiElement) + n1t = ((ForeignLeafPsiElement)n1).getForeignType(); + else + n1t = n1.getElementType(); - return dereferenceToken(n1.getElementType()) == dereferenceToken(n2.getTokenType()); - } - - public static IElementType dereferenceToken(IElementType probablyWrapper) { - if (probablyWrapper instanceof TokenWrapper) { - return dereferenceToken(((TokenWrapper)probablyWrapper).getDelegate()); - } - return probablyWrapper; + return Comparing.equal(n1t, n2.getTokenType()); } @Override diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/ForeignLeafPsiElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/ForeignLeafPsiElement.java index 3e893cc10276..71e25c4cb1f0 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/ForeignLeafPsiElement.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/ForeignLeafPsiElement.java @@ -19,13 +19,25 @@ */ package com.intellij.psi.impl.source.tree; +import com.intellij.lang.ForeignLeafType; +import com.intellij.lang.TokenWrapper; import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; public class ForeignLeafPsiElement extends LeafPsiElement { - public ForeignLeafPsiElement(IElementType type, CharSequence text) { - super(type, text); + private ForeignLeafType myForeignType; + + public ForeignLeafPsiElement(ForeignLeafType type, CharSequence text) { + super(dereferenceElementType(type.getDelegate()), text); + myForeignType = type; + } + + private static IElementType dereferenceElementType(IElementType type) { + while ( type instanceof TokenWrapper) + type = (( TokenWrapper ) type ).getDelegate(); + + return type; } @Override @@ -63,6 +75,10 @@ public class ForeignLeafPsiElement extends LeafPsiElement { return 0; } + public ForeignLeafType getForeignType() { + return myForeignType; + } + @Override public String toString() { return "ForeignLeaf(" + getElementType() + ": " + getText() + ")"; From 6551a3645986b277ff302af561be61e21e093472 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 24 Jul 2012 16:19:10 +0400 Subject: [PATCH 20/51] IDEA-89212 Quick doc: Don't show markup elements at the 'on mouse hover' hint --- .../javadoc/JavaDocInfoGenerator.java | 8 ++++---- .../lang/java/JavaDocumentationProvider.java | 17 ++++++++--------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java index 4b2720bf39e0..0071b02a937a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -1496,7 +1496,7 @@ public class JavaDocInfoGenerator { @SuppressWarnings({"HardCodedStringLiteral"}) public static int generateType(StringBuilder buffer, PsiType type, PsiElement context, boolean generateLink) { if (type instanceof PsiPrimitiveType) { - String text = type.getCanonicalText(); + String text = StringUtil.escapeXml(type.getCanonicalText()); buffer.append(text); return text.length(); } @@ -1539,7 +1539,7 @@ public class JavaDocInfoGenerator { PsiSubstitutor psiSubst = result.getSubstitutor(); if (psiClass == null) { - String text = "" + type.getCanonicalText() + ""; + String text = "" + StringUtil.escapeXml(type.getCanonicalText()) + ""; buffer.append(text); return text.length(); } @@ -1547,7 +1547,7 @@ public class JavaDocInfoGenerator { String qName = psiClass.getQualifiedName(); if (qName == null || psiClass instanceof PsiTypeParameter) { - String text = type.getCanonicalText(); + String text = StringUtil.escapeXml(type.getCanonicalText()); buffer.append(text); return text.length(); } @@ -1596,7 +1596,7 @@ public class JavaDocInfoGenerator { if (type instanceof PsiDisjunctionType) { if (!generateLink) { - final String text = type.getCanonicalText(); + final String text = StringUtil.escapeXml(type.getCanonicalText()); buffer.append(text); return text.length(); } 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 9579238128ab..33f850c252a1 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -72,26 +72,25 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext @Override public String getQuickNavigateInfo(PsiElement element, PsiElement originalElement) { - String navigateInfo = null; if (element instanceof PsiClass) { - navigateInfo = generateClassInfo((PsiClass)element); + return generateClassInfo((PsiClass)element); } else if (element instanceof PsiMethod) { - navigateInfo = generateMethodInfo((PsiMethod)element, calcSubstitutor(originalElement)); + return generateMethodInfo((PsiMethod)element, calcSubstitutor(originalElement)); } else if (element instanceof PsiField) { - navigateInfo = generateFieldInfo((PsiField)element, calcSubstitutor(originalElement)); + return generateFieldInfo((PsiField)element, calcSubstitutor(originalElement)); } else if (element instanceof PsiVariable) { - navigateInfo = generateVariableInfo((PsiVariable)element); + return generateVariableInfo((PsiVariable)element); } else if (element instanceof PsiPackage) { - navigateInfo = generatePackageInfo((PsiPackage)element); + return generatePackageInfo((PsiPackage)element); } else if (element instanceof BeanPropertyElement) { - navigateInfo = generateMethodInfo(((BeanPropertyElement) element).getMethod(), PsiSubstitutor.EMPTY); + return generateMethodInfo(((BeanPropertyElement) element).getMethod(), PsiSubstitutor.EMPTY); } - return StringUtil.escapeXml(StringUtil.unescapeXml(navigateInfo)); + return null; } private static PsiSubstitutor calcSubstitutor(PsiElement originalElement) { From f0e7c4d88b6719e641031fe8c02768af8a11f22f Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 24 Jul 2012 17:11:23 +0400 Subject: [PATCH 21/51] IDEA-27620 XML Catalog support --- .../daemon/impl/DaemonCodeAnalyzerImpl.java | 2 +- .../resources/standardSchemas/catalog.xsd | 196 ++++++++++++++ .../javaee/ExternalResourceManagerEx.java | 2 +- .../javaee/ExternalResourceManagerImpl.java | 6 +- .../javaee/InternalResourceProvider.java | 2 + .../javaee/XMLCatalogConfigurable.java | 6 + .../intellij/xml/XMLCatalogManagerTest.java | 26 ++ xml/tests/testData/catalog/catalog.xml | 2 + .../catalog/cs-xacml-schema-policy-01.xsd | 250 ++++++++++++++++++ xml/tests/testData/catalog/policy.xml | 18 ++ 10 files changed, 507 insertions(+), 3 deletions(-) create mode 100644 xml/impl/resources/standardSchemas/catalog.xsd create mode 100644 xml/tests/testData/catalog/catalog/cs-xacml-schema-policy-01.xsd create mode 100644 xml/tests/testData/catalog/policy.xml diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java index b8e74f01806a..69844cdef078 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java @@ -198,7 +198,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx assert !myDisposed; Application application = ApplicationManager.getApplication(); application.assertIsDispatchThread(); - assert !application.isWriteAccessAllowed(); + assert !application.isWriteAccessAllowed() : "Write access is required"; // pump first so that queued event do not interfere UIUtil.dispatchAllInvocationEvents(); diff --git a/xml/impl/resources/standardSchemas/catalog.xsd b/xml/impl/resources/standardSchemas/catalog.xsd new file mode 100644 index 000000000000..5b932b47f213 --- /dev/null +++ b/xml/impl/resources/standardSchemas/catalog.xsd @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/impl/src/com/intellij/javaee/ExternalResourceManagerEx.java b/xml/impl/src/com/intellij/javaee/ExternalResourceManagerEx.java index d327ac4beb7c..00e93a44d273 100644 --- a/xml/impl/src/com/intellij/javaee/ExternalResourceManagerEx.java +++ b/xml/impl/src/com/intellij/javaee/ExternalResourceManagerEx.java @@ -60,7 +60,7 @@ public abstract class ExternalResourceManagerEx extends ExternalResourceManager public abstract void setDefaultHtmlDoctype(@NotNull String defaultHtmlDoctype, @NotNull Project project); public abstract String getCatalogPropertiesFile(); - public abstract void setCatalogPropertiesFile(String filePath); + public abstract void setCatalogPropertiesFile(@Nullable String filePath); public abstract long getModificationCount(@NotNull Project project); } diff --git a/xml/impl/src/com/intellij/javaee/ExternalResourceManagerImpl.java b/xml/impl/src/com/intellij/javaee/ExternalResourceManagerImpl.java index e3fe4ba5cf8f..ed3aa301d460 100644 --- a/xml/impl/src/com/intellij/javaee/ExternalResourceManagerImpl.java +++ b/xml/impl/src/com/intellij/javaee/ExternalResourceManagerImpl.java @@ -145,7 +145,10 @@ public class ExternalResourceManagerImpl extends ExternalResourceManagerEx imple if (result == null) { result = getStdResource(url, version); } -// getCatalogManager().getCatalog().resolveURI() + XMLCatalogManager manager = getCatalogManager(); + if (manager != null) { + result = manager.resolve(url); + } if (result == null) { result = url; } @@ -446,6 +449,7 @@ public class ExternalResourceManagerImpl extends ExternalResourceManagerEx imple public void setCatalogPropertiesFile(String filePath) { myCatalogManager = null; myCatalogPropertiesFile = filePath; + myModificationCount++; } @Nullable diff --git a/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java b/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java index 8706f9f0b8a2..d9755ad98847 100644 --- a/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java +++ b/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java @@ -46,6 +46,8 @@ public class InternalResourceProvider implements StandardResourceProvider{ impl.addInternalResource("http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd","xhtml1-frameset.dtd"); impl.addInternalResource("http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd","xhtml11/xhtml11.dtd"); + impl.addInternalResource("urn:oasis:names:tc:entity:xmlns:xml:catalog", "catalog.xsd"); + // Plugins DTDs // stathik impl.addInternalResource("http://plugins.intellij.net/plugin.dtd", "plugin.dtd"); impl.addInternalResource("http://plugins.intellij.net/plugin-repository.dtd", "plugin-repository.dtd"); diff --git a/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.java b/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.java index 099fec7f15e2..739d0d3880df 100644 --- a/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.java +++ b/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.java @@ -20,6 +20,7 @@ import com.intellij.openapi.options.BaseConfigurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.openapi.util.Comparing; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -70,6 +71,11 @@ public class XMLCatalogConfigurable extends BaseConfigurable implements Searchab myPropertyFile.setText(ExternalResourceManagerEx.getInstanceEx().getCatalogPropertiesFile()); } + @Override + public boolean isModified() { + return !Comparing.equal(ExternalResourceManagerEx.getInstanceEx().getCatalogPropertiesFile(), myPropertyFile.getText()); + } + @Override public void disposeUIResources() { diff --git a/xml/tests/src/com/intellij/xml/XMLCatalogManagerTest.java b/xml/tests/src/com/intellij/xml/XMLCatalogManagerTest.java index 630642fb3620..2905c3081b0c 100644 --- a/xml/tests/src/com/intellij/xml/XMLCatalogManagerTest.java +++ b/xml/tests/src/com/intellij/xml/XMLCatalogManagerTest.java @@ -15,6 +15,8 @@ */ package com.intellij.xml; +import com.intellij.codeInsight.daemon.impl.HighlightInfo; +import com.intellij.javaee.ExternalResourceManagerEx; import com.intellij.javaee.XMLCatalogManager; import com.intellij.testFramework.IdeaTestCase; import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; @@ -23,6 +25,7 @@ import org.apache.xml.resolver.CatalogManager; import java.io.File; import java.io.IOException; import java.net.URI; +import java.util.List; import java.util.Vector; /** @@ -54,10 +57,33 @@ public class XMLCatalogManagerTest extends LightPlatformCodeInsightFixtureTestCa assertTrue(resolve, resolve.endsWith("/catalog/xhtml1-strict.dtd")); } + public void testHighlighting() { + myFixture.configureByFile("policy.xml"); + List infos = myFixture.doHighlighting(); + assertEquals("urn:oasis:names:tc:xacml:1.0:policy", infos.get(0).text); + } + + public void testFixedHighlighting() throws Exception { + myFixture.configureByFile("policy.xml"); + try { + ExternalResourceManagerEx.getInstanceEx().setCatalogPropertiesFile(getTestDataPath() + "catalog.properties"); + List infos = myFixture.doHighlighting(); + assertEquals(infos.toString(), 0, infos.size()); + } + finally { + ExternalResourceManagerEx.getInstanceEx().setCatalogPropertiesFile(null); + } + } + private XMLCatalogManager getManager() throws IOException { return new XMLCatalogManager(getTestDataPath() + "catalog.properties"); } + @Override + protected boolean isWriteActionRequired() { + return false; + } + @Override protected String getBasePath() { return "/xml/tests/testData/catalog/"; diff --git a/xml/tests/testData/catalog/catalog.xml b/xml/tests/testData/catalog/catalog.xml index 2618424db905..1e97c2c0decd 100644 --- a/xml/tests/testData/catalog/catalog.xml +++ b/xml/tests/testData/catalog/catalog.xml @@ -6,4 +6,6 @@ uri="xhtml1-strict.dtd"/> + \ No newline at end of file diff --git a/xml/tests/testData/catalog/catalog/cs-xacml-schema-policy-01.xsd b/xml/tests/testData/catalog/catalog/cs-xacml-schema-policy-01.xsd new file mode 100644 index 000000000000..3ce43dabb218 --- /dev/null +++ b/xml/tests/testData/catalog/catalog/cs-xacml-schema-policy-01.xsd @@ -0,0 +1,250 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/tests/testData/catalog/policy.xml b/xml/tests/testData/catalog/policy.xml new file mode 100644 index 000000000000..9ea5785ce8f0 --- /dev/null +++ b/xml/tests/testData/catalog/policy.xml @@ -0,0 +1,18 @@ + + xxx + + + + + + + + + + + + + \ No newline at end of file From 858a95e9bd4105d073ca6d9a37a9ab6f6b8b7875 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 24 Jul 2012 14:06:06 +0200 Subject: [PATCH 22/51] inplace introduce: do not select the typed name on template restart (IDEA-69477) --- .../replaceAllWithClassRefType_after.java | 8 +++---- .../beforeAssignmentReplaceAll_after.java | 2 +- .../replaceAllMethodCalls_after.java | 4 ++-- .../inplace/AbstractInplaceIntroducer.java | 21 ++++++++++++++++++- .../rename/inplace/InplaceRefactoring.java | 4 +++- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/java/java-tests/testData/refactoring/inplaceIntroduceConstant/replaceAllWithClassRefType_after.java b/java/java-tests/testData/refactoring/inplaceIntroduceConstant/replaceAllWithClassRefType_after.java index 9dc08ab38e06..4ffba021a591 100644 --- a/java/java-tests/testData/refactoring/inplaceIntroduceConstant/replaceAllWithClassRefType_after.java +++ b/java/java-tests/testData/refactoring/inplaceIntroduceConstant/replaceAllWithClassRefType_after.java @@ -1,12 +1,12 @@ public class Derr { - public static final Long ONE = new Long(1); + public static final Long LONGONE = new Long(1); public static void main(String[] args) { long value; - value = ONE; - value = ONE; - value = ONE; + value = LONGONE; + value = LONGONE; + value = LONGONE; } } \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/inplaceIntroduceField/beforeAssignmentReplaceAll_after.java b/java/java-tests/testData/refactoring/inplaceIntroduceField/beforeAssignmentReplaceAll_after.java index 79053152e42b..3e61dd57c8de 100644 --- a/java/java-tests/testData/refactoring/inplaceIntroduceField/beforeAssignmentReplaceAll_after.java +++ b/java/java-tests/testData/refactoring/inplaceIntroduceField/beforeAssignmentReplaceAll_after.java @@ -3,7 +3,7 @@ class Test { private final String string; Test() { - string = ""; + string = ""; myTimer = string; } } \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/inplaceIntroduceParameter/replaceAllMethodCalls_after.java b/java/java-tests/testData/refactoring/inplaceIntroduceParameter/replaceAllMethodCalls_after.java index 04616eb6e31f..6853ca829b2f 100644 --- a/java/java-tests/testData/refactoring/inplaceIntroduceParameter/replaceAllMethodCalls_after.java +++ b/java/java-tests/testData/refactoring/inplaceIntroduceParameter/replaceAllMethodCalls_after.java @@ -1,6 +1,6 @@ public class Aaa { - public String method(String string) { - return string + string + string; + public String method(String stringstring) { + return stringstring + stringstring + stringstring; } public String getString() { diff --git a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/AbstractInplaceIntroducer.java b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/AbstractInplaceIntroducer.java index 625568fb8c20..e33cae73d485 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/AbstractInplaceIntroducer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/AbstractInplaceIntroducer.java @@ -297,6 +297,12 @@ public abstract class AbstractInplaceIntroducer Date: Tue, 24 Jul 2012 14:15:48 +0200 Subject: [PATCH 23/51] EA-37664 - NPE: InlineUtil.getTailCallType --- .../refactoring/inline/InlineMethodProcessor.java | 10 ++++++---- .../src/com/intellij/refactoring/util/InlineUtil.java | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java index 06204c6338ea..5ab60d23295d 100644 --- a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java @@ -196,10 +196,12 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor { if (value != null && !(value instanceof PsiCallExpression)) { for (UsageInfo info : usagesIn) { PsiReference reference = info.getReference(); - InlineUtil.TailCallType type = InlineUtil.getTailCallType(reference); - if (type == InlineUtil.TailCallType.Simple) { - conflicts.putValue(statement, "Inlined result won't be a valid statement"); - break; + if (reference != null) { + InlineUtil.TailCallType type = InlineUtil.getTailCallType(reference); + if (type == InlineUtil.TailCallType.Simple) { + conflicts.putValue(statement, "Inlined result won't be a valid statement"); + break; + } } } } diff --git a/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java b/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java index db679f4a7bac..05466f3485c2 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java @@ -30,6 +30,7 @@ import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import java.util.*; @@ -276,7 +277,7 @@ public class InlineUtil { return result && nonTailCallUsages.isEmpty(); } - public static TailCallType getTailCallType(final PsiReference psiReference) { + public static TailCallType getTailCallType(@NotNull final PsiReference psiReference) { PsiElement element = psiReference.getElement(); PsiExpression methodCall = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class); if (methodCall == null) return TailCallType.None; From 11213429facad4ecf95f0b46f3d1949a8e22ebd3 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 24 Jul 2012 14:25:31 +0200 Subject: [PATCH 24/51] EA-37640 - IAE: ModuleManager.getInstance --- .../idea/eclipse/importWizard/EclipseImportBuilder.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java index ba3d2df79d46..20fb50f51178 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java @@ -411,11 +411,15 @@ public class EclipseImportBuilder extends ProjectImportBuilder implement } public Parameters getParameters() { + return getParameters(getCurrentProject()); + } + + public Parameters getParameters(final Project project) { if (parameters == null) { parameters = new Parameters(); parameters.existingModuleNames = new HashSet(); - if (isUpdate()) { - for (Module module : ModuleManager.getInstance(getCurrentProject()).getModules()) { + if (isUpdate() && project != null) { + for (Module module : ModuleManager.getInstance(project).getModules()) { parameters.existingModuleNames.add(module.getName()); } } From f704f090469a3623a8cc154de11e310dca161edb Mon Sep 17 00:00:00 2001 From: Vassiliy Kudryashov Date: Tue, 24 Jul 2012 18:01:22 +0400 Subject: [PATCH 25/51] IDEA-89161 "Make before run" reappear after restart --- .../execution/impl/RunManagerImpl.java | 2185 ++++++++--------- 1 file changed, 1091 insertions(+), 1094 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java index 59913365f30e..fec7906323ba 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java @@ -1,1094 +1,1091 @@ -/* - * Copyright 2000-2009 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. - */ - -package com.intellij.execution.impl; - -import com.intellij.execution.*; -import com.intellij.execution.configurations.*; -import com.intellij.ide.util.PropertiesComponent; -import com.intellij.openapi.components.ProjectComponent; -import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.*; -import com.intellij.ui.IconDeferrer; -import com.intellij.util.EventDispatcher; -import com.intellij.util.Function; -import com.intellij.util.NullableFunction; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.WeakHashMap; -import org.jdom.Element; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; - - -public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, ProjectComponent { - private final Project myProject; - - private final Map myTypesByName = new LinkedHashMap(); - - private final Map myTemplateConfigurationsMap = - new HashMap(); - private final Map myConfigurations = - new LinkedHashMap(); // template configurations are not included here - private final Map mySharedConfigurations = new TreeMap(); - private final Map> myConfigurationToBeforeTasksMap = new WeakHashMap>(); - - // When readExternal not all configuration may be loaded, so we need to remember the selected configuration - // so that when it is eventually loaded, we can mark is as a selected. - @Nullable private String myLoadedSelectedConfigurationUniqueName = null; - @Nullable private Integer mySelectedConfigurationId = null; - - private Map myIdToIcon = new com.intellij.util.containers.HashMap(); - - @NonNls - protected static final String CONFIGURATION = "configuration"; - protected static final String RECENT = "recent_temporary"; - private ConfigurationType[] myTypes; - private final RunManagerConfig myConfig; - @NonNls - protected static final String NAME_ATTR = "name"; - @NonNls - protected static final String SELECTED_ATTR = "selected"; - @NonNls private static final String METHOD = "method"; - @NonNls private static final String OPTION = "option"; - - private List myUnknownElements = null; - private JDOMExternalizableStringList myOrder = new JDOMExternalizableStringList(); - private final ArrayList myRecentlyUsedTemporaries = new ArrayList(); - private boolean myOrdered = true; - - private final EventDispatcher myDispatcher = EventDispatcher.create(RunManagerListener.class); - - public RunManagerImpl(final Project project, - PropertiesComponent propertiesComponent) { - myConfig = new RunManagerConfig(propertiesComponent, this); - myProject = project; - - initConfigurationTypes(); - } - - // separate method needed for tests - public final void initializeConfigurationTypes(@NotNull final ConfigurationType[] factories) { - Arrays.sort(factories, new Comparator() { - @Override - public int compare(final ConfigurationType o1, final ConfigurationType o2) { - return o1.getDisplayName().compareTo(o2.getDisplayName()); - } - }); - - final ArrayList types = new ArrayList(Arrays.asList(factories)); - types.add(UnknownConfigurationType.INSTANCE); - myTypes = types.toArray(new ConfigurationType[types.size()]); - - for (final ConfigurationType type : factories) { - myTypesByName.put(type.getId(), type); - } - - final UnknownConfigurationType broken = UnknownConfigurationType.INSTANCE; - myTypesByName.put(broken.getId(), broken); - } - - private void initConfigurationTypes() { - final ConfigurationType[] configurationTypes = Extensions.getExtensions(ConfigurationType.CONFIGURATION_TYPE_EP); - initializeConfigurationTypes(configurationTypes); - } - - @Override - public void disposeComponent() { - } - - @Override - public void initComponent() { - } - - @Override - public void projectOpened() { - } - - @Override - @NotNull - public RunnerAndConfigurationSettings createConfiguration(final String name, final ConfigurationFactory factory) { - return createConfiguration(doCreateConfiguration(name, factory, true), factory); - } - - protected RunConfiguration doCreateConfiguration(String name, ConfigurationFactory factory, final boolean fromTemplate) { - if (fromTemplate) { - return factory.createConfiguration(name, getConfigurationTemplate(factory).getConfiguration()); - } - else { - final RunConfiguration configuration = factory.createTemplateConfiguration(myProject, this); - configuration.setName(name); - return configuration; - } - } - - @Override - @NotNull - public RunnerAndConfigurationSettings createConfiguration(final RunConfiguration runConfiguration, - final ConfigurationFactory factory) { - RunnerAndConfigurationSettings template = getConfigurationTemplate(factory); - myConfigurationToBeforeTasksMap.put(runConfiguration, getBeforeRunTasks(template.getConfiguration())); - shareConfiguration(runConfiguration, isConfigurationShared(template)); - RunnerAndConfigurationSettingsImpl settings = new RunnerAndConfigurationSettingsImpl(this, runConfiguration, false); - settings.importRunnerAndConfigurationSettings((RunnerAndConfigurationSettingsImpl)template); - return settings; - } - - @Override - public void projectClosed() { - myTemplateConfigurationsMap.clear(); - } - - @Override - public RunManagerConfig getConfig() { - return myConfig; - } - - @Override - @NotNull - public ConfigurationType[] getConfigurationFactories() { - return myTypes.clone(); - } - - public ConfigurationType[] getConfigurationFactories(final boolean includeUnknown) { - final ConfigurationType[] configurationTypes = myTypes.clone(); - if (!includeUnknown) { - final List types = new ArrayList(); - for (ConfigurationType configurationType : configurationTypes) { - if (!(configurationType instanceof UnknownConfigurationType)) { - types.add(configurationType); - } - } - - return types.toArray(new ConfigurationType[types.size()]); - } - - return configurationTypes; - } - - /** - * Template configuration is not included - */ - @Override - @NotNull - public RunConfiguration[] getConfigurations(@NotNull final ConfigurationType type) { - - final List array = new ArrayList(); - for (RunnerAndConfigurationSettings myConfiguration : getSortedConfigurations()) { - final RunConfiguration configuration = myConfiguration.getConfiguration(); - final ConfigurationType configurationType = configuration.getType(); - if (type.getId().equals(configurationType.getId())) { - array.add(configuration); - } - } - return array.toArray(new RunConfiguration[array.size()]); - } - - @Override - @NotNull - public RunConfiguration[] getAllConfigurations() { - RunConfiguration[] result = new RunConfiguration[myConfigurations.size()]; - int i = 0; - for (Iterator iterator = getSortedConfigurations().iterator(); iterator.hasNext(); i++) { - RunnerAndConfigurationSettings settings = iterator.next(); - result[i] = settings.getConfiguration(); - } - - return result; - } - - @Nullable - public RunnerAndConfigurationSettings getSettings(@Nullable RunConfiguration configuration) { - if (configuration == null) return null; - for (RunnerAndConfigurationSettings settings : getSortedConfigurations()) { - if (settings.getConfiguration() == configuration) return settings; - } - return null; - } - - /** - * Template configuration is not included - */ - @Override - @NotNull - public RunnerAndConfigurationSettings[] getConfigurationSettings(@NotNull final ConfigurationType type) { - - final LinkedHashSet set = new LinkedHashSet(); - for (RunnerAndConfigurationSettings configuration : getSortedConfigurations()) { - final ConfigurationType configurationType = configuration.getType(); - if (configurationType != null && type.getId().equals(configurationType.getId())) { - set.add(configuration); - } - } - return set.toArray(new RunnerAndConfigurationSettings[set.size()]); - } - - public RunnerAndConfigurationSettings getConfigurationTemplate(final ConfigurationFactory factory) { - RunnerAndConfigurationSettings template = myTemplateConfigurationsMap.get(factory.getType().getId() + "." + factory.getName()); - if (template == null) { - template = new RunnerAndConfigurationSettingsImpl(this, factory.createTemplateConfiguration(myProject, this), true); - if (template.getConfiguration() instanceof UnknownRunConfiguration) { - ((UnknownRunConfiguration)template.getConfiguration()).setDoNotStore(true); - } - myTemplateConfigurationsMap.put(factory.getType().getId() + "." + factory.getName(), template); - } - return template; - } - - @Override - public void addConfiguration(RunnerAndConfigurationSettings settings, - boolean shared, - List tasks, boolean addEnabledTemplateTasksIfAbsent) { - final RunConfiguration configuration = settings.getConfiguration(); - - Integer existingId = findConfigurationIdByUniqueName(getUniqueName(configuration)); - Integer newId = configuration.getUniqueID(); - RunnerAndConfigurationSettings existingSettings = null; - - if (existingId != null) { - existingSettings = myConfigurations.remove(existingId); - mySharedConfigurations.remove(existingId); - } - - if (mySelectedConfigurationId != null && mySelectedConfigurationId.equals(existingId)) { - setSelectedConfigurationId(newId); - } - myConfigurations.put(newId, settings); - if (existingId == null) { - refreshUsagesList(configuration); - } - checkRecentsLimit(); - - mySharedConfigurations.put(newId, shared); - setBeforeRunTasks(configuration, tasks, addEnabledTemplateTasksIfAbsent); - - if (existingSettings == settings) { - myDispatcher.getMulticaster().runConfigurationChanged(settings); - } - else { - myDispatcher.getMulticaster().runConfigurationAdded(settings); - } - } - - @Override - public void refreshUsagesList(RunProfile profile) { - if (profile instanceof RunConfiguration && isTemporary((RunConfiguration)profile)) { - myRecentlyUsedTemporaries.remove((RunConfiguration)profile); - myRecentlyUsedTemporaries.add(0, (RunConfiguration)profile); - while(myRecentlyUsedTemporaries.size() > getConfig().getRecentsLimit()) { - myRecentlyUsedTemporaries.remove(myRecentlyUsedTemporaries.size() - 1); - } - } - } - - void checkRecentsLimit() { - List removed = new ArrayList(); - while (getTempConfigurations().length > getConfig().getRecentsLimit()) { - for (Iterator> it = myConfigurations.entrySet().iterator(); it.hasNext(); ) { - Map.Entry entry = it.next(); - if (entry.getValue().isTemporary() && !myRecentlyUsedTemporaries.contains(entry.getValue().getConfiguration())) { - removed.add(entry.getValue()); - it.remove(); - break; - } - } - } - fireRunConfigurationsRemoved(removed); - } - - public void setOrdered(boolean ordered) { - myOrdered = ordered; - } - - public void saveOrder() { - myOrder.clear(); - for (RunnerAndConfigurationSettings each : myConfigurations.values()) { - if (each.getType() instanceof UnknownConfigurationType) continue; - myOrder.add(getUniqueName(each.getConfiguration())); - } - } - - static String getUniqueName(@NotNull RunConfiguration config) { - return config.getType().getDisplayName() + "." + config.getName() + - (config instanceof UnknownRunConfiguration ? config.getUniqueID() : ""); - } - - @Override - public void removeConfiguration(@Nullable RunnerAndConfigurationSettings settings) { - if (settings == null) return; - - for (Iterator it = getSortedConfigurations().iterator(); it.hasNext(); ) { - final RunnerAndConfigurationSettings configuration = it.next(); - if (configuration.equals(settings)) { - if (mySelectedConfigurationId != null && mySelectedConfigurationId == settings.getConfiguration().getUniqueID()) { - setSelectedConfiguration(null); - } - - it.remove(); - invalidateConfigurationIcon(configuration); - myDispatcher.getMulticaster().runConfigurationRemoved(configuration); - break; - } - } - } - - @Override - @Nullable - public RunnerAndConfigurationSettings getSelectedConfiguration() { - if (mySelectedConfigurationId == null && myLoadedSelectedConfigurationUniqueName != null) { - setSelectedConfigurationId(findConfigurationIdByUniqueName(myLoadedSelectedConfigurationUniqueName)); - } - return mySelectedConfigurationId == null ? null : myConfigurations.get(mySelectedConfigurationId); - } - - @Override - public void setSelectedConfiguration(@Nullable RunnerAndConfigurationSettings settings) { - setSelectedConfigurationId(settings == null ? null : settings.getConfiguration().getUniqueID()); - if (settings != null) { - invalidateConfigurationIcon(settings); - } - fireRunConfigurationSelected(); - } - - private void setSelectedConfigurationId(@Nullable Integer id) { - mySelectedConfigurationId = id; - if (mySelectedConfigurationId != null) myLoadedSelectedConfigurationUniqueName = null; - } - - @Override - public Collection getSortedConfigurations() { - if (!myOrdered) { //compatibility - List> order - = new ArrayList>(myConfigurations.size()); - for (RunnerAndConfigurationSettings each : myConfigurations.values()) { - order.add(Pair.create(getUniqueName(each.getConfiguration()), each)); - } - myConfigurations.clear(); - - if (myOrder.isEmpty()) { - // IDEA-63663 Sort run configurations alphabetically if clean checkout - Collections.sort(order, new Comparator>() { - @Override - public int compare(Pair o1, Pair o2) { - boolean temporary1 = o1.getSecond().isTemporary(); - boolean temporary2 = o2.getSecond().isTemporary(); - if (temporary1 == temporary2) { - return o1.first.compareTo(o2.first); - } else { - return temporary1 ? 1 : -1; - } - } - }); - } - else { - Collections.sort(order, new Comparator>() { - @Override - public int compare(Pair o1, Pair o2) { - boolean temporary1 = o1.getSecond().isTemporary(); - boolean temporary2 = o2.getSecond().isTemporary(); - if (temporary1 == temporary2) { - return myOrder.indexOf(o1.first) - myOrder.indexOf(o2.first); - } else { - return temporary1 ? 1 : -1; - } - } - }); - } - - for (Pair each : order) { - RunnerAndConfigurationSettings setting = each.second; - myConfigurations.put(setting.getConfiguration().getUniqueID(), setting); - } - - myOrdered = true; - } - return myConfigurations.values(); - } - - public static boolean canRunConfiguration(@NotNull final RunnerAndConfigurationSettings configuration, - @NotNull final Executor executor) { - try { - configuration.checkSettings(executor); - } - catch (RuntimeConfigurationError er) { - return false; - } - catch (RuntimeConfigurationException e) { - return true; - } - return true; - } - - @Override - public void writeExternal(@NotNull final Element parentNode) throws WriteExternalException { - writeContext(parentNode); - for (final RunnerAndConfigurationSettings runnerAndConfigurationSettings : myTemplateConfigurationsMap.values()) { - if (runnerAndConfigurationSettings.getConfiguration() instanceof UnknownRunConfiguration) { - if (((UnknownRunConfiguration)runnerAndConfigurationSettings.getConfiguration()).isDoNotStore()) { - continue; - } - } - - addConfigurationElement(parentNode, runnerAndConfigurationSettings); - } - - final Collection configurations = getStableConfigurations(); - for (RunnerAndConfigurationSettings configuration : configurations) { - if (!isConfigurationShared(configuration)) { - addConfigurationElement(parentNode, configuration); - } - } - - final JDOMExternalizableStringList order = new JDOMExternalizableStringList(); - //temp && stable configurations, !unknown - for (RunnerAndConfigurationSettings each : myConfigurations.values()) { - if (each.getType() instanceof UnknownConfigurationType) continue; - order.add(getUniqueName(each.getConfiguration())); - } - - order.writeExternal(parentNode); - - final JDOMExternalizableStringList recentList = new JDOMExternalizableStringList(); - for (RunConfiguration each : myRecentlyUsedTemporaries) { - if (each.getType() instanceof UnknownConfigurationType) continue; - recentList.add(getUniqueName(each)); - } - if (!recentList.isEmpty()) { - final Element recent = new Element(RECENT); - parentNode.addContent(recent); - recentList.writeExternal(recent); - } - - if (myUnknownElements != null) { - for (Element unloadedElement : myUnknownElements) { - parentNode.addContent((Element)unloadedElement.clone()); - } - } - } - - public void writeContext(Element parentNode) throws WriteExternalException { - for (RunnerAndConfigurationSettings configurationSettings : myConfigurations.values()) { - if (configurationSettings.isTemporary()) { - addConfigurationElement(parentNode, configurationSettings, CONFIGURATION); - } - } - RunnerAndConfigurationSettings selected = getSelectedConfiguration(); - if (selected != null) { - parentNode.setAttribute(SELECTED_ATTR, getUniqueName(selected.getConfiguration())); - } - } - - void addConfigurationElement(final Element parentNode, RunnerAndConfigurationSettings template) throws WriteExternalException { - addConfigurationElement(parentNode, template, CONFIGURATION); - } - - private void addConfigurationElement(final Element parentNode, RunnerAndConfigurationSettings settings, String elementType) - throws WriteExternalException { - final Element configurationElement = new Element(elementType); - parentNode.addContent(configurationElement); - ((RunnerAndConfigurationSettingsImpl)settings).writeExternal(configurationElement); - - if (!(settings.getConfiguration() instanceof UnknownRunConfiguration)) { - final List tasks = new CopyOnWriteArrayList(getBeforeRunTasks(settings.getConfiguration())); - final Element methodsElement = new Element(METHOD); - Map, BeforeRunTask> templateTasks = null; - if (!settings.isTemplate()) { - List beforeRunTasks = getBeforeRunTasks(getConfigurationTemplate(settings.getFactory()).getConfiguration()); - templateTasks = new HashMap, BeforeRunTask>(); - for (BeforeRunTask templateTask : beforeRunTasks) { - templateTasks.put(templateTask.getProviderId(), templateTask); - if (templateTask.isEnabled()) { - boolean found = false; - for (BeforeRunTask realTask : tasks) { - if (realTask.getProviderId() == templateTask.getProviderId()) { - found = true; - break; - } - } - if (!found) { - BeforeRunTask clone = templateTask.clone(); - clone.setEnabled(false); - tasks.add(0, clone); - } - } - } - } - for (int i = 0, size = tasks.size(); i < size; i++) { - BeforeRunTask task = tasks.get(i); - if (templateTasks != null) { - int j = 0; - BeforeRunTask templateTask = null; - for (Map.Entry, BeforeRunTask> entry : templateTasks.entrySet()) { - if (entry.getKey() == task.getProviderId()) { - templateTask = entry.getValue(); - break; - } - j++; - } - if (task.equals(templateTask) && i == j) { - continue; // not neccesary saving if the task is the same as template and on the same place - } - } - final Element child = new Element(OPTION); - child.setAttribute(NAME_ATTR, task.getProviderId().toString()); - task.writeExternal(child); - methodsElement.addContent(child); - } - configurationElement.addContent(methodsElement); - } - } - - - @Override - public void readExternal(final Element parentNode) throws InvalidDataException { - clear(); - - final Comparator comparator = new Comparator() { - @Override - public int compare(Element a, Element b) { - final boolean aDefault = Boolean.valueOf(a.getAttributeValue("default", "false")); - final boolean bDefault = Boolean.valueOf(b.getAttributeValue("default", "false")); - return aDefault == bDefault ? 0 : aDefault ? -1 : 1; - } - }; - - final List children = parentNode.getChildren(); - final List sortedElements = new ArrayList(); - for (final Object aChildren : children) { - final Element element = (Element)aChildren; - if (Comparing.strEqual(element.getName(), CONFIGURATION)) { - sortedElements.add(element); - } - } - - Collections.sort(sortedElements, comparator); // ensure templates are loaded first! - - for (final Element element : sortedElements) { - if (loadConfiguration(element, false) == null) { - if (myUnknownElements == null) myUnknownElements = new ArrayList(2); - myUnknownElements.add(element); - } - } - - myOrder.readExternal(parentNode); - myRecentlyUsedTemporaries.clear(); - Element recentNode = parentNode.getChild(RECENT); - if (recentNode != null) { - JDOMExternalizableStringList list = new JDOMExternalizableStringList(); - list.readExternal(recentNode); - for (String name : list) { - Integer id = findConfigurationIdByUniqueName(name); - if (id != null) { - myRecentlyUsedTemporaries.add(myConfigurations.get(id).getConfiguration()); - } - } - } - myOrdered = false; - - myLoadedSelectedConfigurationUniqueName = parentNode.getAttributeValue(SELECTED_ATTR); - setSelectedConfigurationId(findConfigurationIdByUniqueName(myLoadedSelectedConfigurationUniqueName)); - - fireBeforeRunTasksUpdated(); - fireRunConfigurationSelected(); - } - - public void readContext(Element parentNode) throws InvalidDataException { - myLoadedSelectedConfigurationUniqueName = parentNode.getAttributeValue(SELECTED_ATTR); - - for (Object aChildren : parentNode.getChildren()) { - Element element = (Element)aChildren; - RunnerAndConfigurationSettings config = loadConfiguration(element, false); - if (myLoadedSelectedConfigurationUniqueName == null - && config != null - && Boolean.valueOf(element.getAttributeValue(SELECTED_ATTR)).booleanValue()) { - myLoadedSelectedConfigurationUniqueName = getUniqueName(config.getConfiguration()); - } - } - - setSelectedConfigurationId(findConfigurationIdByUniqueName(myLoadedSelectedConfigurationUniqueName)); - - fireRunConfigurationSelected(); - } - - @Nullable - private Integer findConfigurationIdByUniqueName(@Nullable String selectedUniqueName) { - if (selectedUniqueName != null) { - for (RunnerAndConfigurationSettings each : myConfigurations.values()) { - if (selectedUniqueName.equals(getUniqueName(each.getConfiguration()))) { - return each.getConfiguration().getUniqueID(); - } - } - } - return null; - } - - // used by MPS, don't delete - public void clearAll() { - clear(); - myTypesByName.clear(); - initializeConfigurationTypes(new ConfigurationType[0]); - } - - private void clear() { - final List configurations = new ArrayList(myConfigurations.values()); - myConfigurations.clear(); - myUnknownElements = null; - myConfigurationToBeforeTasksMap.clear(); - mySharedConfigurations.clear(); - myTemplateConfigurationsMap.clear(); - mySelectedConfigurationId = null; - myLoadedSelectedConfigurationUniqueName = null; - myIdToIcon.clear(); - myRecentlyUsedTemporaries.clear(); - fireRunConfigurationsRemoved(configurations); - } - - @Nullable - public RunnerAndConfigurationSettings loadConfiguration(final Element element, boolean isShared) throws InvalidDataException { - RunnerAndConfigurationSettingsImpl settings = new RunnerAndConfigurationSettingsImpl(this); - settings.readExternal(element); - ConfigurationFactory factory = settings.getFactory(); - if (factory == null) { - return null; - } - - final Element methodsElement = element.getChild(METHOD); - final List tasks = readStepsBeforeRun(methodsElement, settings); - if (settings.isTemplate()) { - myTemplateConfigurationsMap.put(factory.getType().getId() + "." + factory.getName(), settings); - setBeforeRunTasks(settings.getConfiguration(), tasks, true); - } - else { - addConfiguration(settings, isShared, tasks, true); - if (Boolean.valueOf(element.getAttributeValue(SELECTED_ATTR)).booleanValue()) { //to support old style - setSelectedConfiguration(settings); - } - } - return settings; - } - - @NotNull - private List readStepsBeforeRun(final Element child, RunnerAndConfigurationSettings settings) { - final List result = new ArrayList(); - if (child != null) { - for (Object o : child.getChildren(OPTION)) { - final Element methodElement = (Element)o; - final String providerName = methodElement.getAttributeValue(NAME_ATTR); - final Key id = getProviderKey(providerName); - final BeforeRunTaskProvider provider = getProvider(id); - final BeforeRunTask beforeRunTask = provider.createTask(settings.getConfiguration()); - if (beforeRunTask != null) { - beforeRunTask.readExternal(methodElement); - result.add(beforeRunTask); - } - } - } - return result; - } - - - @Nullable - public ConfigurationType getConfigurationType(final String typeName) { - return myTypesByName.get(typeName); - } - - @Nullable - public ConfigurationFactory getFactory(final String typeName, String factoryName) { - final ConfigurationType type = myTypesByName.get(typeName); - if (factoryName == null) { - factoryName = type != null ? type.getConfigurationFactories()[0].getName() : null; - } - return findFactoryOfTypeNameByName(typeName, factoryName); - } - - - @Nullable - private ConfigurationFactory findFactoryOfTypeNameByName(final String typeName, final String factoryName) { - ConfigurationType type = myTypesByName.get(typeName); - if (type == null) { - type = myTypesByName.get(UnknownConfigurationType.NAME); - } - - return findFactoryOfTypeByName(type, factoryName); - } - - @Nullable - private static ConfigurationFactory findFactoryOfTypeByName(final ConfigurationType type, final String factoryName) { - if (factoryName == null) return null; - - if (type instanceof UnknownConfigurationType) { - return type.getConfigurationFactories()[0]; - } - - final ConfigurationFactory[] factories = type.getConfigurationFactories(); - for (final ConfigurationFactory factory : factories) { - if (factoryName.equals(factory.getName())) return factory; - } - - return null; - } - - @Override - @NotNull - public String getComponentName() { - return "RunManager"; - } - - @Override - public void setTemporaryConfiguration(@Nullable final RunnerAndConfigurationSettings tempConfiguration) { - if (tempConfiguration == null) return; - - tempConfiguration.setTemporary(true); - invalidateConfigurationIcon(tempConfiguration); - - addConfiguration(tempConfiguration, isConfigurationShared(tempConfiguration), - getBeforeRunTasks(tempConfiguration.getConfiguration()), false); - setActiveConfiguration(tempConfiguration); - } - - public static boolean isEditBeforeRun(@NotNull final RunnerAndConfigurationSettings configuration) { - return configuration.isEditBeforeRun(); - } - - Collection getStableConfigurations() { - final Map result = - new LinkedHashMap(myConfigurations); - for (Iterator> it = result.entrySet().iterator(); it.hasNext(); ) { - Map.Entry entry = it.next(); - if (entry.getValue().isTemporary()) { - it.remove(); - } - } - return result.values(); - } - - @Override - public boolean isTemporary(@NotNull final RunConfiguration configuration) { - return Arrays.asList(getTempConfigurations()).contains(configuration); - } - - @Override - public boolean isTemporary(@NotNull RunnerAndConfigurationSettings settings) { - return settings.isTemporary(); - } - - @Override - @NotNull - public RunConfiguration[] getTempConfigurations() { - List configurations = - ContainerUtil.mapNotNull(myConfigurations.values(), new NullableFunction() { - @Override - public RunConfiguration fun(RunnerAndConfigurationSettings settings) { - return settings.isTemporary() ? settings.getConfiguration() : null; - } - }); - return configurations.toArray(new RunConfiguration[configurations.size()]); - } - - @Override - public void makeStable(@NotNull RunConfiguration configuration) { - RunnerAndConfigurationSettings settings = getSettings(configuration); - if (settings != null) { - invalidateConfigurationIcon(settings); - settings.setTemporary(false); - myRecentlyUsedTemporaries.remove(configuration); - if (!myOrder.isEmpty()) { - setOrdered(false); - } - fireRunConfigurationChanged(settings); - } - } - - @Override - @NotNull - public RunnerAndConfigurationSettings createRunConfiguration(String name, ConfigurationFactory type) { - return createConfiguration(name, type); - } - - @Override - public boolean isConfigurationShared(final RunnerAndConfigurationSettings settings) { - Boolean shared = mySharedConfigurations.get(settings.getConfiguration().getUniqueID()); - if (shared == null) { - final RunnerAndConfigurationSettings template = getConfigurationTemplate(settings.getFactory()); - shared = mySharedConfigurations.get(template.getConfiguration().getUniqueID()); - } - return shared != null && shared.booleanValue(); - } - - @Override - @NotNull - public List getBeforeRunTasks(Key taskProviderID) { - final List tasks = new ArrayList(); - final List checkedTemplates = new ArrayList(); - List settingsList = new ArrayList(myConfigurations.values()); - for (RunnerAndConfigurationSettings settings : settingsList) { - final List runTasks = getBeforeRunTasks(settings.getConfiguration()); - for (BeforeRunTask task : runTasks) { - if (task != null && task.isEnabled() && task.getProviderId() == taskProviderID) { - tasks.add((T)task); - } - else { - final RunnerAndConfigurationSettings template = getConfigurationTemplate(settings.getFactory()); - if (!checkedTemplates.contains(template)) { - checkedTemplates.add(template); - final List templateTasks = getBeforeRunTasks(template.getConfiguration()); - for (BeforeRunTask templateTask : templateTasks) { - if (templateTask != null && templateTask.isEnabled() && templateTask.getProviderId() == taskProviderID) { - tasks.add((T)templateTask); - } - } - } - } - } - } - return tasks; - } - - @Override - public void invalidateConfigurationIcon(@NotNull final RunnerAndConfigurationSettings settings) { - myIdToIcon.remove(settings.getConfiguration().getUniqueID()); - } - - @Override - public Icon getConfigurationIcon(@NotNull final RunnerAndConfigurationSettings settings) { - final int uniqueID = settings.getConfiguration().getUniqueID(); - Icon icon = myIdToIcon.get(uniqueID); - if (icon == null) { - icon = IconDeferrer.getInstance().defer(settings.getConfiguration().getIcon(), Pair.create(myProject, settings), - new Function, Icon>() { - @Override - public Icon fun(Pair projectRunnerAndConfigurationSettingsPair) { - if (myProject.isDisposed()) return null; - - Icon icon; - try { - settings.checkSettings(); - icon = ProgramRunnerUtil.getConfigurationIcon(myProject, settings, false); - } - catch (RuntimeConfigurationException e) { - icon = ProgramRunnerUtil.getConfigurationIcon(myProject, settings, true); - } - - return icon; - } - }); - - myIdToIcon.put(uniqueID, icon); - } - - return icon; - } - - @Override - @Nullable - public RunnerAndConfigurationSettings findConfigurationByName(@Nullable String name) { - if (name == null) return null; - for (RunnerAndConfigurationSettings each : myConfigurations.values()) { - if (name.equals(each.getName())) return each; - } - return null; - } - - @NotNull - @Override - public List getBeforeRunTasks(RunConfiguration settings, Key taskProviderID) { - List tasks = myConfigurationToBeforeTasksMap.get(settings); - if (tasks == null) { - tasks = getBeforeRunTasks(settings); - myConfigurationToBeforeTasksMap.put(settings, tasks); - } - List result = new ArrayList(); - for (BeforeRunTask task : tasks) { - if (task.getProviderId() == taskProviderID) - result.add((T)task); - } - return result; - } - - @Override - @NotNull - public List getBeforeRunTasks(final RunConfiguration settings) { - final List tasks = myConfigurationToBeforeTasksMap.get(settings); - if (tasks != null) { - return getCopies(tasks); - } - return getTemplateBeforeRunTasks(settings); - } - - private List getTemplateBeforeRunTasks(RunConfiguration settings) { - final RunnerAndConfigurationSettings template = getConfigurationTemplate(settings.getFactory()); - final List templateTasks = myConfigurationToBeforeTasksMap.get(template.getConfiguration()); - if (templateTasks != null) { - return getCopies(templateTasks); - } - - final List _tasks = new ArrayList(); - for (BeforeRunTaskProvider provider : Extensions - .getExtensions(BeforeRunTaskProvider.EXTENSION_POINT_NAME, myProject)) { - BeforeRunTask task = provider.createTask(settings); - if (task != null && task.isEnabled()) { - Key providerID = provider.getId(); - _tasks.add(task); - settings.getFactory().configureBeforeRunTaskDefaults(providerID, task); - } - } - return _tasks; - } - - @NotNull - private static List getCopies(List original) { - List result = new ArrayList(); - if (original != null) { - for (BeforeRunTask task : original) { - if (!task.isEnabled()) - continue; - result.add(task.clone()); - } - } - return result; - } - - public void shareConfiguration(final RunConfiguration runConfiguration, final boolean shareConfiguration) { - RunnerAndConfigurationSettings settings = getSettings(runConfiguration); - boolean shouldFire = settings != null && isConfigurationShared(settings) != shareConfiguration; - - if (shareConfiguration && isTemporary(runConfiguration)) makeStable(runConfiguration); - mySharedConfigurations.put(runConfiguration.getUniqueID(), shareConfiguration); - - if (shouldFire) fireRunConfigurationChanged(settings); - } - - @Override - public final void setBeforeRunTasks(final RunConfiguration runConfiguration, @NotNull List tasks, boolean addEnabledTemplateTasksIfAbsent) { - List result = new ArrayList(tasks); - if (addEnabledTemplateTasksIfAbsent) { - List templates = getTemplateBeforeRunTasks(runConfiguration); - Set> idsToSet = new HashSet>(); - for (BeforeRunTask task : tasks) { - idsToSet.add(task.getProviderId()); - } - int i = 0; - for (BeforeRunTask template : templates) { - if (!idsToSet.contains(template.getProviderId())) { - result.add(i, template); - i++; - } - } - } - myConfigurationToBeforeTasksMap.put(runConfiguration, result.isEmpty() ? Collections.emptyList() : result); - fireBeforeRunTasksUpdated(); - } - - public final void resetBeforeRunTasks(final RunConfiguration runConfiguration) { - myConfigurationToBeforeTasksMap.remove(runConfiguration); - fireBeforeRunTasksUpdated(); - } - - @Override - public void addConfiguration(final RunnerAndConfigurationSettings settings, final boolean isShared) { - addConfiguration(settings, isShared, getTemplateBeforeRunTasks(settings.getConfiguration()), false); - } - - public static RunManagerImpl getInstanceImpl(final Project project) { - return (RunManagerImpl)RunManager.getInstance(project); - } - - void removeNotExistingSharedConfigurations(final Set existing) { - List removed = new ArrayList(); - for (Iterator> it = myConfigurations.entrySet().iterator(); it.hasNext(); ) { - Map.Entry entry = it.next(); - final RunnerAndConfigurationSettings settings = entry.getValue(); - if (!settings.isTemplate() && isConfigurationShared(settings) && !existing.contains(getUniqueName(settings.getConfiguration()))) { - removed.add(settings); - invalidateConfigurationIcon(settings); - it.remove(); - } - } - fireRunConfigurationsRemoved(removed); - } - - public void fireRunConfigurationChanged(@NotNull RunnerAndConfigurationSettings settings) { - invalidateConfigurationIcon(settings); - myDispatcher.getMulticaster().runConfigurationChanged(settings); - } - - private void fireRunConfigurationsRemoved(@NotNull List removed) { - myRecentlyUsedTemporaries.removeAll(removed); - for (RunnerAndConfigurationSettings settings : removed) { - myDispatcher.getMulticaster().runConfigurationRemoved(settings); - } - } - - private void fireRunConfigurationSelected() { - myDispatcher.getMulticaster().runConfigurationSelected(); - } - - @Override - public void addRunManagerListener(RunManagerListener listener) { - myDispatcher.addListener(listener); - } - - @Override - public void removeRunManagerListener(RunManagerListener listener) { - myDispatcher.removeListener(listener); - } - - public void fireBeforeRunTasksUpdated() { - myDispatcher.getMulticaster().beforeRunTasksChanged(); - } - - private Map, BeforeRunTaskProvider> myBeforeStepsMap; - private Map> myProviderKeysMap; - - @NotNull - private synchronized BeforeRunTaskProvider getProvider(Key providerId) { - if (myBeforeStepsMap == null) { - initProviderMaps(); - } - return myBeforeStepsMap.get(providerId); - } - - @NotNull - private synchronized Key getProviderKey(String keyString) { - if (myProviderKeysMap == null) { - initProviderMaps(); - } - Key id = myProviderKeysMap.get(keyString); - if (id == null) { - final UnknownBeforeRunTaskProvider provider = new UnknownBeforeRunTaskProvider(keyString); - id = provider.getId(); - myProviderKeysMap.put(keyString, id); - myBeforeStepsMap.put(id, provider); - } - return id; - } - - private void initProviderMaps() { - myBeforeStepsMap = new LinkedHashMap, BeforeRunTaskProvider>(); - myProviderKeysMap = new LinkedHashMap>(); - for (BeforeRunTaskProvider provider : Extensions - .getExtensions(BeforeRunTaskProvider.EXTENSION_POINT_NAME, myProject)) { - final Key id = provider.getId(); - myBeforeStepsMap.put(id, provider); - myProviderKeysMap.put(id.toString(), id); - } - } -} +/* + * Copyright 2000-2009 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. + */ + +package com.intellij.execution.impl; + +import com.intellij.execution.*; +import com.intellij.execution.configurations.*; +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.openapi.components.ProjectComponent; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.*; +import com.intellij.ui.IconDeferrer; +import com.intellij.util.EventDispatcher; +import com.intellij.util.Function; +import com.intellij.util.NullableFunction; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.WeakHashMap; +import org.jdom.Element; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; + + +public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, ProjectComponent { + private final Project myProject; + + private final Map myTypesByName = new LinkedHashMap(); + + private final Map myTemplateConfigurationsMap = + new HashMap(); + private final Map myConfigurations = + new LinkedHashMap(); // template configurations are not included here + private final Map mySharedConfigurations = new TreeMap(); + private final Map> myConfigurationToBeforeTasksMap = new WeakHashMap>(); + + // When readExternal not all configuration may be loaded, so we need to remember the selected configuration + // so that when it is eventually loaded, we can mark is as a selected. + @Nullable private String myLoadedSelectedConfigurationUniqueName = null; + @Nullable private Integer mySelectedConfigurationId = null; + + private Map myIdToIcon = new com.intellij.util.containers.HashMap(); + + @NonNls + protected static final String CONFIGURATION = "configuration"; + protected static final String RECENT = "recent_temporary"; + private ConfigurationType[] myTypes; + private final RunManagerConfig myConfig; + @NonNls + protected static final String NAME_ATTR = "name"; + @NonNls + protected static final String SELECTED_ATTR = "selected"; + @NonNls private static final String METHOD = "method"; + @NonNls private static final String OPTION = "option"; + + private List myUnknownElements = null; + private JDOMExternalizableStringList myOrder = new JDOMExternalizableStringList(); + private final ArrayList myRecentlyUsedTemporaries = new ArrayList(); + private boolean myOrdered = true; + + private final EventDispatcher myDispatcher = EventDispatcher.create(RunManagerListener.class); + + public RunManagerImpl(final Project project, + PropertiesComponent propertiesComponent) { + myConfig = new RunManagerConfig(propertiesComponent, this); + myProject = project; + + initConfigurationTypes(); + } + + // separate method needed for tests + public final void initializeConfigurationTypes(@NotNull final ConfigurationType[] factories) { + Arrays.sort(factories, new Comparator() { + @Override + public int compare(final ConfigurationType o1, final ConfigurationType o2) { + return o1.getDisplayName().compareTo(o2.getDisplayName()); + } + }); + + final ArrayList types = new ArrayList(Arrays.asList(factories)); + types.add(UnknownConfigurationType.INSTANCE); + myTypes = types.toArray(new ConfigurationType[types.size()]); + + for (final ConfigurationType type : factories) { + myTypesByName.put(type.getId(), type); + } + + final UnknownConfigurationType broken = UnknownConfigurationType.INSTANCE; + myTypesByName.put(broken.getId(), broken); + } + + private void initConfigurationTypes() { + final ConfigurationType[] configurationTypes = Extensions.getExtensions(ConfigurationType.CONFIGURATION_TYPE_EP); + initializeConfigurationTypes(configurationTypes); + } + + @Override + public void disposeComponent() { + } + + @Override + public void initComponent() { + } + + @Override + public void projectOpened() { + } + + @Override + @NotNull + public RunnerAndConfigurationSettings createConfiguration(final String name, final ConfigurationFactory factory) { + return createConfiguration(doCreateConfiguration(name, factory, true), factory); + } + + protected RunConfiguration doCreateConfiguration(String name, ConfigurationFactory factory, final boolean fromTemplate) { + if (fromTemplate) { + return factory.createConfiguration(name, getConfigurationTemplate(factory).getConfiguration()); + } + else { + final RunConfiguration configuration = factory.createTemplateConfiguration(myProject, this); + configuration.setName(name); + return configuration; + } + } + + @Override + @NotNull + public RunnerAndConfigurationSettings createConfiguration(final RunConfiguration runConfiguration, + final ConfigurationFactory factory) { + RunnerAndConfigurationSettings template = getConfigurationTemplate(factory); + myConfigurationToBeforeTasksMap.put(runConfiguration, getBeforeRunTasks(template.getConfiguration())); + shareConfiguration(runConfiguration, isConfigurationShared(template)); + RunnerAndConfigurationSettingsImpl settings = new RunnerAndConfigurationSettingsImpl(this, runConfiguration, false); + settings.importRunnerAndConfigurationSettings((RunnerAndConfigurationSettingsImpl)template); + return settings; + } + + @Override + public void projectClosed() { + myTemplateConfigurationsMap.clear(); + } + + @Override + public RunManagerConfig getConfig() { + return myConfig; + } + + @Override + @NotNull + public ConfigurationType[] getConfigurationFactories() { + return myTypes.clone(); + } + + public ConfigurationType[] getConfigurationFactories(final boolean includeUnknown) { + final ConfigurationType[] configurationTypes = myTypes.clone(); + if (!includeUnknown) { + final List types = new ArrayList(); + for (ConfigurationType configurationType : configurationTypes) { + if (!(configurationType instanceof UnknownConfigurationType)) { + types.add(configurationType); + } + } + + return types.toArray(new ConfigurationType[types.size()]); + } + + return configurationTypes; + } + + /** + * Template configuration is not included + */ + @Override + @NotNull + public RunConfiguration[] getConfigurations(@NotNull final ConfigurationType type) { + + final List array = new ArrayList(); + for (RunnerAndConfigurationSettings myConfiguration : getSortedConfigurations()) { + final RunConfiguration configuration = myConfiguration.getConfiguration(); + final ConfigurationType configurationType = configuration.getType(); + if (type.getId().equals(configurationType.getId())) { + array.add(configuration); + } + } + return array.toArray(new RunConfiguration[array.size()]); + } + + @Override + @NotNull + public RunConfiguration[] getAllConfigurations() { + RunConfiguration[] result = new RunConfiguration[myConfigurations.size()]; + int i = 0; + for (Iterator iterator = getSortedConfigurations().iterator(); iterator.hasNext(); i++) { + RunnerAndConfigurationSettings settings = iterator.next(); + result[i] = settings.getConfiguration(); + } + + return result; + } + + @Nullable + public RunnerAndConfigurationSettings getSettings(@Nullable RunConfiguration configuration) { + if (configuration == null) return null; + for (RunnerAndConfigurationSettings settings : getSortedConfigurations()) { + if (settings.getConfiguration() == configuration) return settings; + } + return null; + } + + /** + * Template configuration is not included + */ + @Override + @NotNull + public RunnerAndConfigurationSettings[] getConfigurationSettings(@NotNull final ConfigurationType type) { + + final LinkedHashSet set = new LinkedHashSet(); + for (RunnerAndConfigurationSettings configuration : getSortedConfigurations()) { + final ConfigurationType configurationType = configuration.getType(); + if (configurationType != null && type.getId().equals(configurationType.getId())) { + set.add(configuration); + } + } + return set.toArray(new RunnerAndConfigurationSettings[set.size()]); + } + + public RunnerAndConfigurationSettings getConfigurationTemplate(final ConfigurationFactory factory) { + RunnerAndConfigurationSettings template = myTemplateConfigurationsMap.get(factory.getType().getId() + "." + factory.getName()); + if (template == null) { + template = new RunnerAndConfigurationSettingsImpl(this, factory.createTemplateConfiguration(myProject, this), true); + if (template.getConfiguration() instanceof UnknownRunConfiguration) { + ((UnknownRunConfiguration)template.getConfiguration()).setDoNotStore(true); + } + myTemplateConfigurationsMap.put(factory.getType().getId() + "." + factory.getName(), template); + } + return template; + } + + @Override + public void addConfiguration(RunnerAndConfigurationSettings settings, + boolean shared, + List tasks, boolean addEnabledTemplateTasksIfAbsent) { + final RunConfiguration configuration = settings.getConfiguration(); + + Integer existingId = findConfigurationIdByUniqueName(getUniqueName(configuration)); + Integer newId = configuration.getUniqueID(); + RunnerAndConfigurationSettings existingSettings = null; + + if (existingId != null) { + existingSettings = myConfigurations.remove(existingId); + mySharedConfigurations.remove(existingId); + } + + if (mySelectedConfigurationId != null && mySelectedConfigurationId.equals(existingId)) { + setSelectedConfigurationId(newId); + } + myConfigurations.put(newId, settings); + if (existingId == null) { + refreshUsagesList(configuration); + } + checkRecentsLimit(); + + mySharedConfigurations.put(newId, shared); + setBeforeRunTasks(configuration, tasks, addEnabledTemplateTasksIfAbsent); + + if (existingSettings == settings) { + myDispatcher.getMulticaster().runConfigurationChanged(settings); + } + else { + myDispatcher.getMulticaster().runConfigurationAdded(settings); + } + } + + @Override + public void refreshUsagesList(RunProfile profile) { + if (profile instanceof RunConfiguration && isTemporary((RunConfiguration)profile)) { + myRecentlyUsedTemporaries.remove((RunConfiguration)profile); + myRecentlyUsedTemporaries.add(0, (RunConfiguration)profile); + while(myRecentlyUsedTemporaries.size() > getConfig().getRecentsLimit()) { + myRecentlyUsedTemporaries.remove(myRecentlyUsedTemporaries.size() - 1); + } + } + } + + void checkRecentsLimit() { + List removed = new ArrayList(); + while (getTempConfigurations().length > getConfig().getRecentsLimit()) { + for (Iterator> it = myConfigurations.entrySet().iterator(); it.hasNext(); ) { + Map.Entry entry = it.next(); + if (entry.getValue().isTemporary() && !myRecentlyUsedTemporaries.contains(entry.getValue().getConfiguration())) { + removed.add(entry.getValue()); + it.remove(); + break; + } + } + } + fireRunConfigurationsRemoved(removed); + } + + public void setOrdered(boolean ordered) { + myOrdered = ordered; + } + + public void saveOrder() { + myOrder.clear(); + for (RunnerAndConfigurationSettings each : myConfigurations.values()) { + if (each.getType() instanceof UnknownConfigurationType) continue; + myOrder.add(getUniqueName(each.getConfiguration())); + } + } + + static String getUniqueName(@NotNull RunConfiguration config) { + return config.getType().getDisplayName() + "." + config.getName() + + (config instanceof UnknownRunConfiguration ? config.getUniqueID() : ""); + } + + @Override + public void removeConfiguration(@Nullable RunnerAndConfigurationSettings settings) { + if (settings == null) return; + + for (Iterator it = getSortedConfigurations().iterator(); it.hasNext(); ) { + final RunnerAndConfigurationSettings configuration = it.next(); + if (configuration.equals(settings)) { + if (mySelectedConfigurationId != null && mySelectedConfigurationId == settings.getConfiguration().getUniqueID()) { + setSelectedConfiguration(null); + } + + it.remove(); + invalidateConfigurationIcon(configuration); + myDispatcher.getMulticaster().runConfigurationRemoved(configuration); + break; + } + } + } + + @Override + @Nullable + public RunnerAndConfigurationSettings getSelectedConfiguration() { + if (mySelectedConfigurationId == null && myLoadedSelectedConfigurationUniqueName != null) { + setSelectedConfigurationId(findConfigurationIdByUniqueName(myLoadedSelectedConfigurationUniqueName)); + } + return mySelectedConfigurationId == null ? null : myConfigurations.get(mySelectedConfigurationId); + } + + @Override + public void setSelectedConfiguration(@Nullable RunnerAndConfigurationSettings settings) { + setSelectedConfigurationId(settings == null ? null : settings.getConfiguration().getUniqueID()); + if (settings != null) { + invalidateConfigurationIcon(settings); + } + fireRunConfigurationSelected(); + } + + private void setSelectedConfigurationId(@Nullable Integer id) { + mySelectedConfigurationId = id; + if (mySelectedConfigurationId != null) myLoadedSelectedConfigurationUniqueName = null; + } + + @Override + public Collection getSortedConfigurations() { + if (!myOrdered) { //compatibility + List> order + = new ArrayList>(myConfigurations.size()); + for (RunnerAndConfigurationSettings each : myConfigurations.values()) { + order.add(Pair.create(getUniqueName(each.getConfiguration()), each)); + } + myConfigurations.clear(); + + if (myOrder.isEmpty()) { + // IDEA-63663 Sort run configurations alphabetically if clean checkout + Collections.sort(order, new Comparator>() { + @Override + public int compare(Pair o1, Pair o2) { + boolean temporary1 = o1.getSecond().isTemporary(); + boolean temporary2 = o2.getSecond().isTemporary(); + if (temporary1 == temporary2) { + return o1.first.compareTo(o2.first); + } else { + return temporary1 ? 1 : -1; + } + } + }); + } + else { + Collections.sort(order, new Comparator>() { + @Override + public int compare(Pair o1, Pair o2) { + boolean temporary1 = o1.getSecond().isTemporary(); + boolean temporary2 = o2.getSecond().isTemporary(); + if (temporary1 == temporary2) { + return myOrder.indexOf(o1.first) - myOrder.indexOf(o2.first); + } else { + return temporary1 ? 1 : -1; + } + } + }); + } + + for (Pair each : order) { + RunnerAndConfigurationSettings setting = each.second; + myConfigurations.put(setting.getConfiguration().getUniqueID(), setting); + } + + myOrdered = true; + } + return myConfigurations.values(); + } + + public static boolean canRunConfiguration(@NotNull final RunnerAndConfigurationSettings configuration, + @NotNull final Executor executor) { + try { + configuration.checkSettings(executor); + } + catch (RuntimeConfigurationError er) { + return false; + } + catch (RuntimeConfigurationException e) { + return true; + } + return true; + } + + @Override + public void writeExternal(@NotNull final Element parentNode) throws WriteExternalException { + writeContext(parentNode); + for (final RunnerAndConfigurationSettings runnerAndConfigurationSettings : myTemplateConfigurationsMap.values()) { + if (runnerAndConfigurationSettings.getConfiguration() instanceof UnknownRunConfiguration) { + if (((UnknownRunConfiguration)runnerAndConfigurationSettings.getConfiguration()).isDoNotStore()) { + continue; + } + } + + addConfigurationElement(parentNode, runnerAndConfigurationSettings); + } + + final Collection configurations = getStableConfigurations(); + for (RunnerAndConfigurationSettings configuration : configurations) { + if (!isConfigurationShared(configuration)) { + addConfigurationElement(parentNode, configuration); + } + } + + final JDOMExternalizableStringList order = new JDOMExternalizableStringList(); + //temp && stable configurations, !unknown + for (RunnerAndConfigurationSettings each : myConfigurations.values()) { + if (each.getType() instanceof UnknownConfigurationType) continue; + order.add(getUniqueName(each.getConfiguration())); + } + + order.writeExternal(parentNode); + + final JDOMExternalizableStringList recentList = new JDOMExternalizableStringList(); + for (RunConfiguration each : myRecentlyUsedTemporaries) { + if (each.getType() instanceof UnknownConfigurationType) continue; + recentList.add(getUniqueName(each)); + } + if (!recentList.isEmpty()) { + final Element recent = new Element(RECENT); + parentNode.addContent(recent); + recentList.writeExternal(recent); + } + + if (myUnknownElements != null) { + for (Element unloadedElement : myUnknownElements) { + parentNode.addContent((Element)unloadedElement.clone()); + } + } + } + + public void writeContext(Element parentNode) throws WriteExternalException { + for (RunnerAndConfigurationSettings configurationSettings : myConfigurations.values()) { + if (configurationSettings.isTemporary()) { + addConfigurationElement(parentNode, configurationSettings, CONFIGURATION); + } + } + RunnerAndConfigurationSettings selected = getSelectedConfiguration(); + if (selected != null) { + parentNode.setAttribute(SELECTED_ATTR, getUniqueName(selected.getConfiguration())); + } + } + + void addConfigurationElement(final Element parentNode, RunnerAndConfigurationSettings template) throws WriteExternalException { + addConfigurationElement(parentNode, template, CONFIGURATION); + } + + private void addConfigurationElement(final Element parentNode, RunnerAndConfigurationSettings settings, String elementType) + throws WriteExternalException { + final Element configurationElement = new Element(elementType); + parentNode.addContent(configurationElement); + ((RunnerAndConfigurationSettingsImpl)settings).writeExternal(configurationElement); + + if (!(settings.getConfiguration() instanceof UnknownRunConfiguration)) { + final List tasks = new CopyOnWriteArrayList(getBeforeRunTasks(settings.getConfiguration())); + final Element methodsElement = new Element(METHOD); + Map, BeforeRunTask> templateTasks = new HashMap, BeforeRunTask>(); + List beforeRunTasks = settings.isTemplate() + ? getHardcodedBeforeRunTasks(settings.getConfiguration()) + : getBeforeRunTasks(getConfigurationTemplate(settings.getFactory()).getConfiguration()); + for (BeforeRunTask templateTask : beforeRunTasks) { + templateTasks.put(templateTask.getProviderId(), templateTask); + if (templateTask.isEnabled()) { + boolean found = false; + for (BeforeRunTask realTask : tasks) { + if (realTask.getProviderId() == templateTask.getProviderId()) { + found = true; + break; + } + } + if (!found) { + BeforeRunTask clone = templateTask.clone(); + clone.setEnabled(false); + tasks.add(0, clone); + } + } + } + for (int i = 0, size = tasks.size(); i < size; i++) { + BeforeRunTask task = tasks.get(i); + int j = 0; + BeforeRunTask templateTask = null; + for (Map.Entry, BeforeRunTask> entry : templateTasks.entrySet()) { + if (entry.getKey() == task.getProviderId()) { + templateTask = entry.getValue(); + break; + } + j++; + } + if (task.equals(templateTask) && i == j) { + continue; // not neccesary saving if the task is the same as template and on the same place + } + final Element child = new Element(OPTION); + child.setAttribute(NAME_ATTR, task.getProviderId().toString()); + task.writeExternal(child); + methodsElement.addContent(child); + } + configurationElement.addContent(methodsElement); + } + } + + + @Override + public void readExternal(final Element parentNode) throws InvalidDataException { + clear(); + + final Comparator comparator = new Comparator() { + @Override + public int compare(Element a, Element b) { + final boolean aDefault = Boolean.valueOf(a.getAttributeValue("default", "false")); + final boolean bDefault = Boolean.valueOf(b.getAttributeValue("default", "false")); + return aDefault == bDefault ? 0 : aDefault ? -1 : 1; + } + }; + + final List children = parentNode.getChildren(); + final List sortedElements = new ArrayList(); + for (final Object aChildren : children) { + final Element element = (Element)aChildren; + if (Comparing.strEqual(element.getName(), CONFIGURATION)) { + sortedElements.add(element); + } + } + + Collections.sort(sortedElements, comparator); // ensure templates are loaded first! + + for (final Element element : sortedElements) { + if (loadConfiguration(element, false) == null) { + if (myUnknownElements == null) myUnknownElements = new ArrayList(2); + myUnknownElements.add(element); + } + } + + myOrder.readExternal(parentNode); + myRecentlyUsedTemporaries.clear(); + Element recentNode = parentNode.getChild(RECENT); + if (recentNode != null) { + JDOMExternalizableStringList list = new JDOMExternalizableStringList(); + list.readExternal(recentNode); + for (String name : list) { + Integer id = findConfigurationIdByUniqueName(name); + if (id != null) { + myRecentlyUsedTemporaries.add(myConfigurations.get(id).getConfiguration()); + } + } + } + myOrdered = false; + + myLoadedSelectedConfigurationUniqueName = parentNode.getAttributeValue(SELECTED_ATTR); + setSelectedConfigurationId(findConfigurationIdByUniqueName(myLoadedSelectedConfigurationUniqueName)); + + fireBeforeRunTasksUpdated(); + fireRunConfigurationSelected(); + } + + public void readContext(Element parentNode) throws InvalidDataException { + myLoadedSelectedConfigurationUniqueName = parentNode.getAttributeValue(SELECTED_ATTR); + + for (Object aChildren : parentNode.getChildren()) { + Element element = (Element)aChildren; + RunnerAndConfigurationSettings config = loadConfiguration(element, false); + if (myLoadedSelectedConfigurationUniqueName == null + && config != null + && Boolean.valueOf(element.getAttributeValue(SELECTED_ATTR)).booleanValue()) { + myLoadedSelectedConfigurationUniqueName = getUniqueName(config.getConfiguration()); + } + } + + setSelectedConfigurationId(findConfigurationIdByUniqueName(myLoadedSelectedConfigurationUniqueName)); + + fireRunConfigurationSelected(); + } + + @Nullable + private Integer findConfigurationIdByUniqueName(@Nullable String selectedUniqueName) { + if (selectedUniqueName != null) { + for (RunnerAndConfigurationSettings each : myConfigurations.values()) { + if (selectedUniqueName.equals(getUniqueName(each.getConfiguration()))) { + return each.getConfiguration().getUniqueID(); + } + } + } + return null; + } + + // used by MPS, don't delete + public void clearAll() { + clear(); + myTypesByName.clear(); + initializeConfigurationTypes(new ConfigurationType[0]); + } + + private void clear() { + final List configurations = new ArrayList(myConfigurations.values()); + myConfigurations.clear(); + myUnknownElements = null; + myConfigurationToBeforeTasksMap.clear(); + mySharedConfigurations.clear(); + myTemplateConfigurationsMap.clear(); + mySelectedConfigurationId = null; + myLoadedSelectedConfigurationUniqueName = null; + myIdToIcon.clear(); + myRecentlyUsedTemporaries.clear(); + fireRunConfigurationsRemoved(configurations); + } + + @Nullable + public RunnerAndConfigurationSettings loadConfiguration(final Element element, boolean isShared) throws InvalidDataException { + RunnerAndConfigurationSettingsImpl settings = new RunnerAndConfigurationSettingsImpl(this); + settings.readExternal(element); + ConfigurationFactory factory = settings.getFactory(); + if (factory == null) { + return null; + } + + final Element methodsElement = element.getChild(METHOD); + final List tasks = readStepsBeforeRun(methodsElement, settings); + if (settings.isTemplate()) { + myTemplateConfigurationsMap.put(factory.getType().getId() + "." + factory.getName(), settings); + setBeforeRunTasks(settings.getConfiguration(), tasks, true); + } + else { + addConfiguration(settings, isShared, tasks, true); + if (Boolean.valueOf(element.getAttributeValue(SELECTED_ATTR)).booleanValue()) { //to support old style + setSelectedConfiguration(settings); + } + } + return settings; + } + + @NotNull + private List readStepsBeforeRun(final Element child, RunnerAndConfigurationSettings settings) { + final List result = new ArrayList(); + if (child != null) { + for (Object o : child.getChildren(OPTION)) { + final Element methodElement = (Element)o; + final String providerName = methodElement.getAttributeValue(NAME_ATTR); + final Key id = getProviderKey(providerName); + final BeforeRunTaskProvider provider = getProvider(id); + final BeforeRunTask beforeRunTask = provider.createTask(settings.getConfiguration()); + if (beforeRunTask != null) { + beforeRunTask.readExternal(methodElement); + result.add(beforeRunTask); + } + } + } + return result; + } + + + @Nullable + public ConfigurationType getConfigurationType(final String typeName) { + return myTypesByName.get(typeName); + } + + @Nullable + public ConfigurationFactory getFactory(final String typeName, String factoryName) { + final ConfigurationType type = myTypesByName.get(typeName); + if (factoryName == null) { + factoryName = type != null ? type.getConfigurationFactories()[0].getName() : null; + } + return findFactoryOfTypeNameByName(typeName, factoryName); + } + + + @Nullable + private ConfigurationFactory findFactoryOfTypeNameByName(final String typeName, final String factoryName) { + ConfigurationType type = myTypesByName.get(typeName); + if (type == null) { + type = myTypesByName.get(UnknownConfigurationType.NAME); + } + + return findFactoryOfTypeByName(type, factoryName); + } + + @Nullable + private static ConfigurationFactory findFactoryOfTypeByName(final ConfigurationType type, final String factoryName) { + if (factoryName == null) return null; + + if (type instanceof UnknownConfigurationType) { + return type.getConfigurationFactories()[0]; + } + + final ConfigurationFactory[] factories = type.getConfigurationFactories(); + for (final ConfigurationFactory factory : factories) { + if (factoryName.equals(factory.getName())) return factory; + } + + return null; + } + + @Override + @NotNull + public String getComponentName() { + return "RunManager"; + } + + @Override + public void setTemporaryConfiguration(@Nullable final RunnerAndConfigurationSettings tempConfiguration) { + if (tempConfiguration == null) return; + + tempConfiguration.setTemporary(true); + invalidateConfigurationIcon(tempConfiguration); + + addConfiguration(tempConfiguration, isConfigurationShared(tempConfiguration), + getBeforeRunTasks(tempConfiguration.getConfiguration()), false); + setActiveConfiguration(tempConfiguration); + } + + public static boolean isEditBeforeRun(@NotNull final RunnerAndConfigurationSettings configuration) { + return configuration.isEditBeforeRun(); + } + + Collection getStableConfigurations() { + final Map result = + new LinkedHashMap(myConfigurations); + for (Iterator> it = result.entrySet().iterator(); it.hasNext(); ) { + Map.Entry entry = it.next(); + if (entry.getValue().isTemporary()) { + it.remove(); + } + } + return result.values(); + } + + @Override + public boolean isTemporary(@NotNull final RunConfiguration configuration) { + return Arrays.asList(getTempConfigurations()).contains(configuration); + } + + @Override + public boolean isTemporary(@NotNull RunnerAndConfigurationSettings settings) { + return settings.isTemporary(); + } + + @Override + @NotNull + public RunConfiguration[] getTempConfigurations() { + List configurations = + ContainerUtil.mapNotNull(myConfigurations.values(), new NullableFunction() { + @Override + public RunConfiguration fun(RunnerAndConfigurationSettings settings) { + return settings.isTemporary() ? settings.getConfiguration() : null; + } + }); + return configurations.toArray(new RunConfiguration[configurations.size()]); + } + + @Override + public void makeStable(@NotNull RunConfiguration configuration) { + RunnerAndConfigurationSettings settings = getSettings(configuration); + if (settings != null) { + invalidateConfigurationIcon(settings); + settings.setTemporary(false); + myRecentlyUsedTemporaries.remove(configuration); + if (!myOrder.isEmpty()) { + setOrdered(false); + } + fireRunConfigurationChanged(settings); + } + } + + @Override + @NotNull + public RunnerAndConfigurationSettings createRunConfiguration(String name, ConfigurationFactory type) { + return createConfiguration(name, type); + } + + @Override + public boolean isConfigurationShared(final RunnerAndConfigurationSettings settings) { + Boolean shared = mySharedConfigurations.get(settings.getConfiguration().getUniqueID()); + if (shared == null) { + final RunnerAndConfigurationSettings template = getConfigurationTemplate(settings.getFactory()); + shared = mySharedConfigurations.get(template.getConfiguration().getUniqueID()); + } + return shared != null && shared.booleanValue(); + } + + @Override + @NotNull + public List getBeforeRunTasks(Key taskProviderID) { + final List tasks = new ArrayList(); + final List checkedTemplates = new ArrayList(); + List settingsList = new ArrayList(myConfigurations.values()); + for (RunnerAndConfigurationSettings settings : settingsList) { + final List runTasks = getBeforeRunTasks(settings.getConfiguration()); + for (BeforeRunTask task : runTasks) { + if (task != null && task.isEnabled() && task.getProviderId() == taskProviderID) { + tasks.add((T)task); + } + else { + final RunnerAndConfigurationSettings template = getConfigurationTemplate(settings.getFactory()); + if (!checkedTemplates.contains(template)) { + checkedTemplates.add(template); + final List templateTasks = getBeforeRunTasks(template.getConfiguration()); + for (BeforeRunTask templateTask : templateTasks) { + if (templateTask != null && templateTask.isEnabled() && templateTask.getProviderId() == taskProviderID) { + tasks.add((T)templateTask); + } + } + } + } + } + } + return tasks; + } + + @Override + public void invalidateConfigurationIcon(@NotNull final RunnerAndConfigurationSettings settings) { + myIdToIcon.remove(settings.getConfiguration().getUniqueID()); + } + + @Override + public Icon getConfigurationIcon(@NotNull final RunnerAndConfigurationSettings settings) { + final int uniqueID = settings.getConfiguration().getUniqueID(); + Icon icon = myIdToIcon.get(uniqueID); + if (icon == null) { + icon = IconDeferrer.getInstance().defer(settings.getConfiguration().getIcon(), Pair.create(myProject, settings), + new Function, Icon>() { + @Override + public Icon fun(Pair projectRunnerAndConfigurationSettingsPair) { + if (myProject.isDisposed()) return null; + + Icon icon; + try { + settings.checkSettings(); + icon = ProgramRunnerUtil.getConfigurationIcon(myProject, settings, false); + } + catch (RuntimeConfigurationException e) { + icon = ProgramRunnerUtil.getConfigurationIcon(myProject, settings, true); + } + + return icon; + } + }); + + myIdToIcon.put(uniqueID, icon); + } + + return icon; + } + + @Override + @Nullable + public RunnerAndConfigurationSettings findConfigurationByName(@Nullable String name) { + if (name == null) return null; + for (RunnerAndConfigurationSettings each : myConfigurations.values()) { + if (name.equals(each.getName())) return each; + } + return null; + } + + @NotNull + @Override + public List getBeforeRunTasks(RunConfiguration settings, Key taskProviderID) { + List tasks = myConfigurationToBeforeTasksMap.get(settings); + if (tasks == null) { + tasks = getBeforeRunTasks(settings); + myConfigurationToBeforeTasksMap.put(settings, tasks); + } + List result = new ArrayList(); + for (BeforeRunTask task : tasks) { + if (task.getProviderId() == taskProviderID) + result.add((T)task); + } + return result; + } + + @Override + @NotNull + public List getBeforeRunTasks(final RunConfiguration settings) { + final List tasks = myConfigurationToBeforeTasksMap.get(settings); + if (tasks != null) { + return getCopies(tasks); + } + return getTemplateBeforeRunTasks(settings); + } + + private List getTemplateBeforeRunTasks(RunConfiguration settings) { + final RunnerAndConfigurationSettings template = getConfigurationTemplate(settings.getFactory()); + final List templateTasks = myConfigurationToBeforeTasksMap.get(template.getConfiguration()); + return templateTasks != null ? getCopies(templateTasks) : getHardcodedBeforeRunTasks(settings); + } + + private List getHardcodedBeforeRunTasks(RunConfiguration settings) { + final List _tasks = new ArrayList(); + for (BeforeRunTaskProvider provider : Extensions + .getExtensions(BeforeRunTaskProvider.EXTENSION_POINT_NAME, myProject)) { + BeforeRunTask task = provider.createTask(settings); + if (task != null && task.isEnabled()) { + Key providerID = provider.getId(); + _tasks.add(task); + settings.getFactory().configureBeforeRunTaskDefaults(providerID, task); + } + } + return _tasks; + } + + @NotNull + private static List getCopies(List original) { + List result = new ArrayList(); + if (original != null) { + for (BeforeRunTask task : original) { + if (!task.isEnabled()) + continue; + result.add(task.clone()); + } + } + return result; + } + + public void shareConfiguration(final RunConfiguration runConfiguration, final boolean shareConfiguration) { + RunnerAndConfigurationSettings settings = getSettings(runConfiguration); + boolean shouldFire = settings != null && isConfigurationShared(settings) != shareConfiguration; + + if (shareConfiguration && isTemporary(runConfiguration)) makeStable(runConfiguration); + mySharedConfigurations.put(runConfiguration.getUniqueID(), shareConfiguration); + + if (shouldFire) fireRunConfigurationChanged(settings); + } + + @Override + public final void setBeforeRunTasks(final RunConfiguration runConfiguration, @NotNull List tasks, boolean addEnabledTemplateTasksIfAbsent) { + List result = new ArrayList(tasks); + if (addEnabledTemplateTasksIfAbsent) { + List templates = getTemplateBeforeRunTasks(runConfiguration); + Set> idsToSet = new HashSet>(); + for (BeforeRunTask task : tasks) { + idsToSet.add(task.getProviderId()); + } + int i = 0; + for (BeforeRunTask template : templates) { + if (!idsToSet.contains(template.getProviderId())) { + result.add(i, template); + i++; + } + } + } + myConfigurationToBeforeTasksMap.put(runConfiguration, result.isEmpty() ? Collections.emptyList() : result); + fireBeforeRunTasksUpdated(); + } + + public final void resetBeforeRunTasks(final RunConfiguration runConfiguration) { + myConfigurationToBeforeTasksMap.remove(runConfiguration); + fireBeforeRunTasksUpdated(); + } + + @Override + public void addConfiguration(final RunnerAndConfigurationSettings settings, final boolean isShared) { + addConfiguration(settings, isShared, getTemplateBeforeRunTasks(settings.getConfiguration()), false); + } + + public static RunManagerImpl getInstanceImpl(final Project project) { + return (RunManagerImpl)RunManager.getInstance(project); + } + + void removeNotExistingSharedConfigurations(final Set existing) { + List removed = new ArrayList(); + for (Iterator> it = myConfigurations.entrySet().iterator(); it.hasNext(); ) { + Map.Entry entry = it.next(); + final RunnerAndConfigurationSettings settings = entry.getValue(); + if (!settings.isTemplate() && isConfigurationShared(settings) && !existing.contains(getUniqueName(settings.getConfiguration()))) { + removed.add(settings); + invalidateConfigurationIcon(settings); + it.remove(); + } + } + fireRunConfigurationsRemoved(removed); + } + + public void fireRunConfigurationChanged(@NotNull RunnerAndConfigurationSettings settings) { + invalidateConfigurationIcon(settings); + myDispatcher.getMulticaster().runConfigurationChanged(settings); + } + + private void fireRunConfigurationsRemoved(@NotNull List removed) { + myRecentlyUsedTemporaries.removeAll(removed); + for (RunnerAndConfigurationSettings settings : removed) { + myDispatcher.getMulticaster().runConfigurationRemoved(settings); + } + } + + private void fireRunConfigurationSelected() { + myDispatcher.getMulticaster().runConfigurationSelected(); + } + + @Override + public void addRunManagerListener(RunManagerListener listener) { + myDispatcher.addListener(listener); + } + + @Override + public void removeRunManagerListener(RunManagerListener listener) { + myDispatcher.removeListener(listener); + } + + public void fireBeforeRunTasksUpdated() { + myDispatcher.getMulticaster().beforeRunTasksChanged(); + } + + private Map, BeforeRunTaskProvider> myBeforeStepsMap; + private Map> myProviderKeysMap; + + @NotNull + private synchronized BeforeRunTaskProvider getProvider(Key providerId) { + if (myBeforeStepsMap == null) { + initProviderMaps(); + } + return myBeforeStepsMap.get(providerId); + } + + @NotNull + private synchronized Key getProviderKey(String keyString) { + if (myProviderKeysMap == null) { + initProviderMaps(); + } + Key id = myProviderKeysMap.get(keyString); + if (id == null) { + final UnknownBeforeRunTaskProvider provider = new UnknownBeforeRunTaskProvider(keyString); + id = provider.getId(); + myProviderKeysMap.put(keyString, id); + myBeforeStepsMap.put(id, provider); + } + return id; + } + + private void initProviderMaps() { + myBeforeStepsMap = new LinkedHashMap, BeforeRunTaskProvider>(); + myProviderKeysMap = new LinkedHashMap>(); + for (BeforeRunTaskProvider provider : Extensions + .getExtensions(BeforeRunTaskProvider.EXTENSION_POINT_NAME, myProject)) { + final Key id = provider.getId(); + myBeforeStepsMap.put(id, provider); + myProviderKeysMap.put(id.toString(), id); + } + } +} From a915dc131fe53da5156b3f421d15ec1ba1b76488 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 24 Jul 2012 16:42:10 +0200 Subject: [PATCH 26/51] Cleanup --- .../vfs/impl/local/LocalFileSystemBase.java | 9 +++++++-- .../vfs/impl/local/LocalFileSystemImpl.java | 7 ------- .../openapi/vfs/impl/win32/Win32Kernel.java | 18 ++++++------------ .../vfs/impl/win32/Win32LocalFileSystem.java | 18 ------------------ 4 files changed, 13 insertions(+), 39 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java index 725849b456fc..58079ef5bf21 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java @@ -20,6 +20,7 @@ import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileAttributes; import com.intellij.openapi.util.io.FileSystemUtil; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -728,8 +729,12 @@ public abstract class LocalFileSystemBase extends LocalFileSystem { return ((flags & FileUtil.BA_EXISTS) != 0 && exists(file) ? FileUtil.BA_EXISTS : 0) | ((flags & FileUtil.BA_DIRECTORY) != 0 && isDirectory(file) ? FileUtil.BA_DIRECTORY : 0) | ((flags & FileUtil.BA_REGULAR) != 0 && !isSpecialFile(file) ? FileUtil.BA_REGULAR : 0) | - ((flags & FileUtil.BA_HIDDEN) != 0 && convertToIOFile(file).isHidden() ? FileUtil.BA_HIDDEN : 0) - ; + ((flags & FileUtil.BA_HIDDEN) != 0 && convertToIOFile(file).isHidden() ? FileUtil.BA_HIDDEN : 0); + } + + @Override + public FileAttributes getAttributes(@NotNull final VirtualFile file) { + return FileSystemUtil.getAttributes(FileUtil.toSystemDependentName(file.getPath())); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java index f987be6f184a..3a6286e33fcb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java @@ -20,8 +20,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.io.FileAttributes; -import com.intellij.openapi.util.io.FileSystemUtil; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.LocalFileSystem; @@ -534,11 +532,6 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap } } - @Override - public FileAttributes getAttributes(@NotNull final VirtualFile file) { - return FileSystemUtil.getAttributes(FileUtil.toSystemDependentName(file.getPath())); - } - @NonNls public String toString() { return "LocalFileSystem"; diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java index 09c21e205a1c..d7cf906ac2a4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java @@ -30,13 +30,7 @@ import java.util.Map; /** * @author Dmitry Avdeev */ -public class Win32Kernel { - public static final int FILE_ATTRIBUTE_READONLY = FileInfo.FILE_ATTRIBUTE_READONLY; - public static final int FILE_ATTRIBUTE_HIDDEN = FileInfo.FILE_ATTRIBUTE_HIDDEN; - public static final int FILE_ATTRIBUTE_DIRECTORY = FileInfo.FILE_ATTRIBUTE_DIRECTORY; - public static final int FILE_ATTRIBUTE_DEVICE = FileInfo.FILE_ATTRIBUTE_DEVICE; - public static final int FILE_ATTRIBUTE_REPARSE_POINT = FileInfo.FILE_ATTRIBUTE_REPARSE_POINT; - +class Win32Kernel { private final IdeaWin32 myKernel = IdeaWin32.getInstance(); private final Map myCache = new THashMap(); @@ -72,13 +66,13 @@ public class Win32Kernel { public boolean isDirectory(@NotNull String path) throws FileNotFoundException { FileInfo data = getInfo(path); - return (data.attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; + return (data.attributes & FileInfo.FILE_ATTRIBUTE_DIRECTORY) != 0; } public boolean isWritable(@NotNull String path) throws FileNotFoundException { FileInfo fileInfo = getInfo(path); myCache.remove(path); - return (fileInfo.attributes & FILE_ATTRIBUTE_READONLY) == 0; + return (fileInfo.attributes & FileInfo.FILE_ATTRIBUTE_READONLY) == 0; } public long getTimeStamp(@NotNull String path) throws FileNotFoundException { @@ -120,14 +114,14 @@ public class Win32Kernel { result |= FileUtil.BA_EXISTS; } if ((flags & FileUtil.BA_DIRECTORY) != 0) { - result |= (info.attributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ? 0 : FileUtil.BA_DIRECTORY; + result |= (info.attributes & FileInfo.FILE_ATTRIBUTE_DIRECTORY) == 0 ? 0 : FileUtil.BA_DIRECTORY; } if ((flags & FileUtil.BA_REGULAR) != 0) { - result |= (info.attributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)) != 0 + result |= (info.attributes & (FileInfo.FILE_ATTRIBUTE_DIRECTORY | FileInfo.FILE_ATTRIBUTE_DEVICE | FileInfo.FILE_ATTRIBUTE_REPARSE_POINT)) != 0 ? 0 : FileUtil.BA_REGULAR; } if ((flags & FileUtil.BA_HIDDEN) != 0) { - result |= (info.attributes & FILE_ATTRIBUTE_HIDDEN) == 0 ? 0 : FileUtil.BA_HIDDEN; + result |= (info.attributes & FileInfo.FILE_ATTRIBUTE_HIDDEN) == 0 ? 0 : FileUtil.BA_HIDDEN; } return result; } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java index 113926d3e8bd..d9a3503f8e27 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java @@ -16,9 +16,6 @@ package com.intellij.openapi.vfs.impl.win32; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.io.FileAttributes; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.io.win32.FileInfo; import com.intellij.openapi.util.io.win32.IdeaWin32; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.impl.local.LocalFileSystemBase; @@ -31,8 +28,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Set; -import static com.intellij.util.BitUtil.isSet; - /** * @author Dmitry Avdeev */ @@ -182,17 +177,4 @@ public class Win32LocalFileSystem extends LocalFileSystemBase { return super.getBooleanAttributes(file, flags); } } - - @Override - public FileAttributes getAttributes(@NotNull final VirtualFile file) { - final FileInfo fileInfo = myKernel.doGetInfo(FileUtil.toSystemDependentName(file.getPath())); - if (fileInfo == null) return null; - - final boolean isDirectory = isSet(fileInfo.attributes, Win32Kernel.FILE_ATTRIBUTE_DIRECTORY); - final boolean isSpecial = isSet(fileInfo.attributes, Win32Kernel.FILE_ATTRIBUTE_DEVICE); - final boolean isSymlink = isSet(fileInfo.attributes, Win32Kernel.FILE_ATTRIBUTE_REPARSE_POINT); - final boolean isHidden = isSet(fileInfo.attributes, Win32Kernel.FILE_ATTRIBUTE_HIDDEN); - final boolean isWritable = !isSet(fileInfo.attributes, Win32Kernel.FILE_ATTRIBUTE_READONLY); - return new FileAttributes(isDirectory, isSpecial, isSymlink, isHidden, fileInfo.length, fileInfo.timestamp, isWritable); - } } From 4be57446ede03410fe3ad2be9cd898530ecc52c1 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 24 Jul 2012 17:01:15 +0200 Subject: [PATCH 27/51] wide selection fixes on Win --- .../src/com/intellij/ui/CheckboxTreeBase.java | 4 +- .../com/intellij/ui/treeStructure/Tree.java | 2 +- .../intellij/ide/ui/laf/LafManagerImpl.java | 30 ++++++++++++++- .../util/ui/tree/WideSelectionTreeUI.java | 38 +++++++++++++++++-- 4 files changed, 66 insertions(+), 8 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java b/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java index 4a0a823eb9a2..2903e4cbd78e 100644 --- a/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java +++ b/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -316,7 +316,7 @@ public class CheckboxTreeBase extends Tree { myCheckbox.setVisible(true); myCheckbox.setSelected(state != NodeState.CLEAR); myCheckbox.setEnabled(node.isEnabled() && state != NodeState.PARTIAL); - + myCheckbox.setOpaque(false); myCheckbox.setBackground(null); setBackground(null); } diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java index 5c29f06bb730..e883eb65a4e9 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java @@ -96,7 +96,7 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith public void setUI(final TreeUI ui) { TreeUI actualUI = ui; if (!isCustomUI()) { - if (!(ui instanceof WideSelectionTreeUI) && (UIUtil.isUnderAquaBasedLookAndFeel() || SystemInfo.isWindows)) { //todo[kb] fix on ubunty + if (!(ui instanceof WideSelectionTreeUI) && (UIUtil.isUnderAquaBasedLookAndFeel() || SystemInfo.isWindows) && isMacWideSelection()) { //todo[kb] fix on ubunty actualUI = new WideSelectionTreeUI(isMacWideSelection(), !isFileColorsEnabled()); } } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java index 59c53fce1e3a..ba747981a289 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java @@ -36,6 +36,7 @@ import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; import com.intellij.ui.ScreenUtil; import com.intellij.ui.mac.MacPopupMenuUI; +import com.intellij.util.PlatformUtils; import com.intellij.util.ui.UIUtil; import org.jdom.Element; import org.jetbrains.annotations.NonNls; @@ -45,6 +46,7 @@ import sun.security.action.GetPropertyAction; import javax.swing.*; import javax.swing.event.EventListenerList; +import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.FontUIResource; import javax.swing.plaf.metal.DefaultMetalTheme; import javax.swing.plaf.metal.MetalLookAndFeel; @@ -255,7 +257,7 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo LOG.assertTrue(laf != null); return laf; } - if ("Rubymine".equals(lowercaseProductName) || "Pycharm".equals(lowercaseProductName)) { + if (PlatformUtils.isRubyMine() || PlatformUtils.isPyCharm()) { final String desktop = AccessController.doPrivileged(new GetPropertyAction("sun.desktop")); if ("gnome".equals(desktop)) { UIManager.LookAndFeelInfo laf=findLaf(systemLafClassName); @@ -432,8 +434,8 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo fixPopupWeight(); fixGtkPopupStyle(); - final UIDefaults uiDefaults = UIManager.getLookAndFeelDefaults(); + fixTreeWideSelection(uiDefaults); if (UIUtil.isUnderAquaLookAndFeel()) { // update ui for popup menu to get round corners uiDefaults.put("PopupMenuUI", MacPopupMenuUI.class.getCanonicalName()); @@ -466,6 +468,30 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo fixSeparatorColor(uiDefaults); } + private static void fixTreeWideSelection(UIDefaults uiDefaults) { + if (UIUtil.isUnderAlloyIDEALookAndFeel()) { + final Color bg = new ColorUIResource(56, 117, 215); + uiDefaults.put("Tree.selectionBackground", bg); + uiDefaults.put("MenuItem.selectionBackground", bg); + uiDefaults.put("Menu.selectionBackground", bg); + uiDefaults.put("List.selectionBackground", bg); + uiDefaults.put("ComboBox.selectionBackground", bg); + uiDefaults.put("Table.selectionBackground", bg); + uiDefaults.put("TextArea.selectionBackground", bg); + uiDefaults.put("EditorPane.selectionBackground", bg); + uiDefaults.put("TextPane.selectionBackground", bg); + uiDefaults.put("info", bg); + uiDefaults.put("FormattedTextField.selectionBackground", bg); + uiDefaults.put("textHighlight", bg); + uiDefaults.put("PasswordField.selectionBackground", bg); + uiDefaults.put("TextField.selectionBackground", bg); + uiDefaults.put("RadioButtonMenuItem.selectionBackground", bg); + uiDefaults.put("CheckBoxMenuItem.selectionBackground", bg); + } if (UIUtil.isUnderMetalLookAndFeel()) { + uiDefaults.put("Tree.hash", new ColorUIResource(117, 117, 117)); + } + } + private static void fixSeparatorColor(UIDefaults uiDefaults) { if (UIUtil.isUnderAquaLookAndFeel()) { uiDefaults.put("Separator.background", UIUtil.AQUA_SEPARATOR_BACKGROUND_COLOR); diff --git a/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java b/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java index 6ab5d652a07e..42e3482a8f85 100644 --- a/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java +++ b/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java @@ -17,6 +17,7 @@ package com.intellij.util.ui.tree; import com.intellij.icons.AllIcons; import com.intellij.openapi.util.SystemInfo; +import com.intellij.util.containers.ComparatorUtil; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -54,6 +55,8 @@ public class WideSelectionTreeUI extends BasicTreeUI { private boolean myWideSelection; private boolean myAlwaysPaintRowBackground; private boolean myOldRepaintAllRowValue; + private boolean invertLineColor; + public WideSelectionTreeUI() { this(true, true); @@ -216,7 +219,11 @@ public class WideSelectionTreeUI extends BasicTreeUI { final boolean hasBeenExpanded, final boolean isLeaf) { if (!UIUtil.isUnderAquaBasedLookAndFeel()) { + if (UIUtil.isUnderAlloyIDEALookAndFeel()) { + invertLineColor = tree.getSelectionModel().isRowSelected(row) && tree.hasFocus(); + } super.paintHorizontalPartOfLeg(g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf); + invertLineColor = false; } } @@ -228,17 +235,42 @@ public class WideSelectionTreeUI extends BasicTreeUI { @Override protected void paintVerticalPartOfLeg(final Graphics g, final Rectangle clipBounds, final Insets insets, final TreePath path) { if (!UIUtil.isUnderAquaBasedLookAndFeel()) { + invertLineColor = UIUtil.isUnderAlloyIDEALookAndFeel() && tree.hasFocus() && tree.getSelectionModel().isPathSelected(path); super.paintVerticalPartOfLeg(g, clipBounds, insets, path); + invertLineColor = false; } } @Override - protected void paintHorizontalLine(Graphics g, JComponent c, int y, int left, int right) { - if (!UIUtil.isUnderAquaBasedLookAndFeel()) { - super.paintHorizontalLine(g, c, y, left, right); + protected void paintVerticalLine(Graphics g, JComponent c, int x, int top, int bottom) { + if (tree.hasFocus()) { + int y0 = top, y1 = top; + while (y1 < bottom) { + y0 = y1; + final int row = tree.getRowForPath(tree.getClosestPathForLocation(x, y0 + 1)); + invertLineColor = tree.isRowSelected(row); + g.setColor(getHashColor()); + final Rectangle bounds = tree.getRowBounds(row); + y1 = bounds.y + bounds.height; + super.paintVerticalLine(g, c, x, y0, Math.min(bottom, y1)); + } + invertLineColor = false; + } else { + super.paintVerticalLine(g, c, x, top, bottom); } } + @Override + protected Color getHashColor() { + if (invertLineColor && !ComparatorUtil.equalsNullable(UIUtil.getTreeSelectionForeground(), UIUtil.getTreeForeground())) { + final Color c = UIUtil.getTreeSelectionForeground(); + if (c != null) { + return c.darker(); + } + } + return super.getHashColor(); + } + public boolean isWideSelection() { return myWideSelection; } From 1ee26f5d5c8b626fbb1b5e757316412f9adf67ab Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 24 Jul 2012 19:21:03 +0400 Subject: [PATCH 28/51] IDEA-88652 make FileTypeIndex aware of newly added file types --- .../intellij/psi/search/FileTypeIndex.java | 7 +- .../psi/search/FileTypeIndexTest.java | 65 +++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 platform/platform-tests/testSrc/com/intellij/psi/search/FileTypeIndexTest.java diff --git a/platform/lang-impl/src/com/intellij/psi/search/FileTypeIndex.java b/platform/lang-impl/src/com/intellij/psi/search/FileTypeIndex.java index b81138eb54c8..7ddbeaa25e63 100644 --- a/platform/lang-impl/src/com/intellij/psi/search/FileTypeIndex.java +++ b/platform/lang-impl/src/com/intellij/psi/search/FileTypeIndex.java @@ -65,7 +65,12 @@ public class FileTypeIndex extends ScalarIndexExtension @Override public int getVersion() { - return 1; + FileType[] types = myFileTypeManager.getRegisteredFileTypes(); + int version = 1; + for (FileType type : types) { + version += type.getName().hashCode(); + } + return version; } @Override diff --git a/platform/platform-tests/testSrc/com/intellij/psi/search/FileTypeIndexTest.java b/platform/platform-tests/testSrc/com/intellij/psi/search/FileTypeIndexTest.java new file mode 100644 index 000000000000..bb01e38f9021 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/psi/search/FileTypeIndexTest.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2012 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. + */ +package com.intellij.psi.search; + +import com.intellij.openapi.fileTypes.FileNameMatcher; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.fileTypes.ex.FakeFileType; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.PlatformTestCase; +import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; + +/** + * @author Dmitry Avdeev + * Date: 7/24/12 + */ +public class FileTypeIndexTest extends LightPlatformCodeInsightFixtureTestCase { + + public FileTypeIndexTest() { + PlatformTestCase.initPlatformLangPrefix(); + } + + public void testAddFileType() throws Exception { + FileType foo = new FakeFileType() { + @Override + public boolean isMyFileType(VirtualFile file) { + return true; + } + + @NotNull + @Override + public String getName() { + return "foo"; + } + + @NotNull + @Override + public String getDescription() { + return ""; + } + }; + FileTypeIndex index = new FileTypeIndex(FileTypeManager.getInstance()); + int version = index.getVersion(); + + FileTypeManager.getInstance().registerFileType(foo, Collections.emptyList()); + + assertNotSame(version, index.getVersion()); + } +} From e0cad5f56894f6165ac2855f3138254c039ee61b Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 24 Jul 2012 16:11:00 +0200 Subject: [PATCH 29/51] introduce variable from lambda expression --- .../java-psi-api/src/com/intellij/psi/LambdaUtil.java | 10 ++++------ .../src/com/intellij/psi/PsiLambdaExpressionType.java | 2 +- .../src/com/intellij/psi/PsiTypeVisitor.java | 5 +++++ .../introduceVariable/LambdaExpr.after.java | 11 +++++++++++ .../refactoring/introduceVariable/LambdaExpr.java | 10 ++++++++++ .../LambdaExprNotAccepted.after.java | 11 +++++++++++ .../introduceVariable/LambdaExprNotAccepted.java | 10 ++++++++++ .../intellij/refactoring/IntroduceVariableTest.java | 8 ++++++++ 8 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 java/java-tests/testData/refactoring/introduceVariable/LambdaExpr.after.java create mode 100644 java/java-tests/testData/refactoring/introduceVariable/LambdaExpr.java create mode 100644 java/java-tests/testData/refactoring/introduceVariable/LambdaExprNotAccepted.after.java create mode 100644 java/java-tests/testData/refactoring/introduceVariable/LambdaExprNotAccepted.java diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index f6ac8d0d5636..3c2defafd336 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -117,7 +117,8 @@ public class LambdaUtil { final int parameterIndex = ((PsiParameterList)paramParent).getParameterIndex(param); if (parameterIndex > -1) { final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(param, PsiLambdaExpression.class); - final PsiClassType.ClassResolveResult resolveResult = getFunctionInterfaceType(lambdaExpression); + final PsiType type = getFunctionInterfaceType(lambdaExpression); + final PsiClassType.ClassResolveResult resolveResult = type instanceof PsiClassType ? ((PsiClassType)type).resolveGenerics() : null; if (resolveResult != null) { final MethodSignature methodSignature = getFunction(resolveResult.getElement()); if (methodSignature != null) { @@ -140,7 +141,7 @@ public class LambdaUtil { } @Nullable - public static PsiClassType.ClassResolveResult getFunctionInterfaceType(@Nullable PsiLambdaExpression lambdaExpression) { + public static PsiType getFunctionInterfaceType(@Nullable PsiLambdaExpression lambdaExpression) { if (lambdaExpression != null) { final PsiElement parent = lambdaExpression.getParent(); PsiType type = null; @@ -177,10 +178,7 @@ public class LambdaUtil { type = method.getReturnType(); } } - - if (type instanceof PsiClassType) { - return ((PsiClassType)type).resolveGenerics(); - } + return type; } return null; } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiLambdaExpressionType.java b/java/java-psi-api/src/com/intellij/psi/PsiLambdaExpressionType.java index 530ac9c2128f..0ae5c8aed1b3 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiLambdaExpressionType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiLambdaExpressionType.java @@ -57,7 +57,7 @@ public class PsiLambdaExpressionType extends PsiType { @Override public A accept(@NotNull final PsiTypeVisitor visitor) { - return visitor.visitType(this); + return visitor.visitLambdaExpressionType(this); } @Override diff --git a/java/java-psi-api/src/com/intellij/psi/PsiTypeVisitor.java b/java/java-psi-api/src/com/intellij/psi/PsiTypeVisitor.java index 29b1bce17fb4..828e04dc26ae 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiTypeVisitor.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiTypeVisitor.java @@ -67,4 +67,9 @@ public class PsiTypeVisitor { public A visitDiamondType(PsiDiamondType diamondType) { return visitType(diamondType); } + + @Nullable + public A visitLambdaExpressionType(PsiLambdaExpressionType lambdaExpressionType) { + return visitType(LambdaUtil.getFunctionInterfaceType(lambdaExpressionType.getExpression())); + } } diff --git a/java/java-tests/testData/refactoring/introduceVariable/LambdaExpr.after.java b/java/java-tests/testData/refactoring/introduceVariable/LambdaExpr.after.java new file mode 100644 index 000000000000..39338e0ef223 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/LambdaExpr.after.java @@ -0,0 +1,11 @@ +interface SAM { + X m(int i, int j); + } + +class Foo { + void test() { + SAM c = (i, j)->i + j; + m(c); + } + void m(SAM s) { } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/LambdaExpr.java b/java/java-tests/testData/refactoring/introduceVariable/LambdaExpr.java new file mode 100644 index 000000000000..0d77849b4eb4 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/LambdaExpr.java @@ -0,0 +1,10 @@ +interface SAM { + X m(int i, int j); + } + +class Foo { + void test() { + m((i, j) -> i + j); + } + void m(SAM s) { } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/LambdaExprNotAccepted.after.java b/java/java-tests/testData/refactoring/introduceVariable/LambdaExprNotAccepted.after.java new file mode 100644 index 000000000000..eea91ba171c5 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/LambdaExprNotAccepted.after.java @@ -0,0 +1,11 @@ +interface SAM { + X m(int i, int j); + } + +class Foo { + void test() { + SAM c = (i, j)->"" + i + j; + SAM s3 = m(c); + } + SAM m(SAM s) { return null; } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/LambdaExprNotAccepted.java b/java/java-tests/testData/refactoring/introduceVariable/LambdaExprNotAccepted.java new file mode 100644 index 000000000000..cbb47f93c57d --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/LambdaExprNotAccepted.java @@ -0,0 +1,10 @@ +interface SAM { + X m(int i, int j); + } + +class Foo { + void test() { + SAM s3 = m((i, j) -> "" + i + j); + } + SAM m(SAM s) { return null; } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java index 2a9bcee98340..2f451e09d0b7 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java @@ -335,6 +335,14 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { doTest(new MockIntroduceVariableHandler("c", false, false, false, CommonClassNames.JAVA_LANG_OBJECT)); } + public void testLambdaExpr() throws Exception { + doTest(new MockIntroduceVariableHandler("c", false, false, false, "SAM")); + } + + public void testLambdaExprNotAccepted() throws Exception { + doTest(new MockIntroduceVariableHandler("c", false, false, false, "SAM")); + } + private void doTest(IntroduceVariableBase testMe) throws Exception { @NonNls String baseName = "/refactoring/introduceVariable/" + getTestName(false); configureByFile(baseName + ".java"); From 806ea310affd8c549d25414bd133f7f7398cbc4d Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 24 Jul 2012 16:41:24 +0200 Subject: [PATCH 30/51] copyright: allow string separator (IDEA-89218) --- .../idea/copyright/options/LanguageOptions.java | 10 +++++----- .../idea/copyright/ui/TemplateCommentPanel.form | 2 +- .../idea/copyright/ui/TemplateCommentPanel.java | 4 ++-- .../maddyhome/idea/copyright/util/FileTypeUtil.java | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/options/LanguageOptions.java b/plugins/copyright/src/com/maddyhome/idea/copyright/options/LanguageOptions.java index fcc086af26be..501fa0bec80e 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/options/LanguageOptions.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/options/LanguageOptions.java @@ -26,7 +26,7 @@ public class LanguageOptions implements JDOMExternalizable, Cloneable { public static final int MIN_SEPARATOR_LENGTH = 5; public static final int MAX_SEPARATOR_LENGTH = 300; - public static final char DEFAULT_FILLER = ' '; + public static final String DEFAULT_FILLER = " "; private static final LanguageOptions DEFAULT_SETTINGS_HOLDER = new LanguageOptions(); @@ -144,7 +144,7 @@ public class LanguageOptions implements JDOMExternalizable, Cloneable { result = 29 * result + lenBefore; result = 29 * result + lenAfter; result = 29 * result + (box ? 1 : 0); - result = 29 * result + (int)filler; + result = 29 * result + filler.hashCode(); result = 29 * result + fileTypeOverride; result = 29 * result + (relativeBefore ? 1 : 0); result = 29 * result + (addBlankAfter ? 1 : 0); @@ -234,11 +234,11 @@ public class LanguageOptions implements JDOMExternalizable, Cloneable { this.box = box; } - public char getFiller() { + public String getFiller() { return filler; } - public void setFiller(char filler) { + public void setFiller(String filler) { this.filler = filler; } @@ -262,6 +262,6 @@ public class LanguageOptions implements JDOMExternalizable, Cloneable { public int lenBefore; public int lenAfter; public boolean box; - public char filler; + public String filler; public boolean trim; } \ No newline at end of file diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/TemplateCommentPanel.form b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/TemplateCommentPanel.form index 6eaac456e205..575439743391 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/TemplateCommentPanel.form +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/TemplateCommentPanel.form @@ -189,7 +189,7 @@ - + diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/TemplateCommentPanel.java b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/TemplateCommentPanel.java index 6700b8a09fd0..78d5af9ed0d2 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/TemplateCommentPanel.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/TemplateCommentPanel.java @@ -251,7 +251,7 @@ public class TemplateCommentPanel implements SearchableConfigurable { String filler = txtFiller.getText(); if (filler.length() > 0) { - res.setFiller(filler.charAt(0)); + res.setFiller(filler); } else { res.setFiller(LanguageOptions.DEFAULT_FILLER); @@ -399,7 +399,7 @@ public class TemplateCommentPanel implements SearchableConfigurable { cbSeparatorBefore.setSelected(options.isSeparateBefore()); txtLengthBefore.setText(String.valueOf(options.getLenBefore())); txtLengthAfter.setText(String.valueOf(options.getLenAfter())); - txtFiller.setText(options.getFiller() == LanguageOptions.DEFAULT_FILLER ? "" : Character.toString(options.getFiller())); + txtFiller.setText(options.getFiller() == LanguageOptions.DEFAULT_FILLER ? "" : options.getFiller()); cbBox.setSelected(options.isBox()); final int fileTypeOverride = options.getFileTypeOverride(); diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/util/FileTypeUtil.java b/plugins/copyright/src/com/maddyhome/idea/copyright/util/FileTypeUtil.java index 52e918a15081..b22d843a294b 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/util/FileTypeUtil.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/util/FileTypeUtil.java @@ -66,12 +66,12 @@ public class FileTypeUtil } boolean allowSeparator = getInstance().allowSeparators(type); - char filler = options.getFiller(); + String filler = options.getFiller(); if (!allowSeparator) { if (options.getFiller() == LanguageOptions.DEFAULT_FILLER) { - filler = '~'; + filler = "~"; } } @@ -92,7 +92,7 @@ public class FileTypeUtil StringBuffer post = new StringBuffer(5); if (filler == LanguageOptions.DEFAULT_FILLER) { - filler = open.charAt(open.length() - 1); + filler = open.substring(open.length() - 1); } int offset = 0; if (isBlock) @@ -116,14 +116,14 @@ public class FileTypeUtil } if (!allowBlock) { - close = Character.toString(filler); + close = filler; } } else { if (allowLine) { - close = Character.toString(filler); + close = filler; } pre.append(open); post.append(close); From 445fe5c251d86b02848031178fd44e64543abeeb Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 24 Jul 2012 17:14:45 +0200 Subject: [PATCH 31/51] lambda: inline lambda initialized vars --- .../intellij/psi/controlFlow/ControlFlowAnalyzer.java | 6 ++++++ .../testData/refactoring/inlineLocal/LambdaExpr.java | 11 +++++++++++ .../refactoring/inlineLocal/LambdaExpr.java.after | 10 ++++++++++ .../intellij/refactoring/inline/InlineLocalTest.java | 4 ++++ 4 files changed, 31 insertions(+) create mode 100644 java/java-tests/testData/refactoring/inlineLocal/LambdaExpr.java create mode 100644 java/java-tests/testData/refactoring/inlineLocal/LambdaExpr.java.after diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java index aa64e49df744..bbaa5017f036 100644 --- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java +++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java @@ -1446,6 +1446,12 @@ class ControlFlowAnalyzer extends JavaElementVisitor { finishElement(expression); } + @Override + public void visitLambdaExpression(PsiLambdaExpression expression) { + startElement(expression); + finishElement(expression); + } + @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) { startElement(expression); diff --git a/java/java-tests/testData/refactoring/inlineLocal/LambdaExpr.java b/java/java-tests/testData/refactoring/inlineLocal/LambdaExpr.java new file mode 100644 index 000000000000..1152c963abb8 --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineLocal/LambdaExpr.java @@ -0,0 +1,11 @@ +interface SAM { + X m(int i, int j); + } + +class Foo { + void test() { + SAM c = (i, j)->i + j; + m(c); + } + void m(SAM s) { } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/inlineLocal/LambdaExpr.java.after b/java/java-tests/testData/refactoring/inlineLocal/LambdaExpr.java.after new file mode 100644 index 000000000000..2babe6e21d22 --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineLocal/LambdaExpr.java.after @@ -0,0 +1,10 @@ +interface SAM { + X m(int i, int j); + } + +class Foo { + void test() { + m((i, j)->i + j); + } + void m(SAM s) { } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLocalTest.java b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLocalTest.java index 472d877af6ad..706a560a2744 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLocalTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLocalTest.java @@ -136,6 +136,10 @@ public class InlineLocalTest extends LightCodeInsightTestCase { doTest(false, "Cannot perform refactoring.\n" + "Variable 'x' is accessed for writing."); } + + public void testLambdaExpr() throws Exception { + doTest(true); + } private void doTest(final boolean inlineDef, String conflictMessage) throws Exception { try { From 146765a32ba0b907070ad154b13b0b0559006a51 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 24 Jul 2012 17:47:58 +0200 Subject: [PATCH 32/51] introduce field from lambda expr test --- .../introduceField/afterFromLambdaExpr.java | 14 ++++++++++++++ .../introduceField/beforeFromLambdaExpr.java | 13 +++++++++++++ .../refactoring/IntroduceFieldInSameClassTest.java | 6 ++++++ 3 files changed, 33 insertions(+) create mode 100644 java/java-tests/testData/refactoring/introduceField/afterFromLambdaExpr.java create mode 100644 java/java-tests/testData/refactoring/introduceField/beforeFromLambdaExpr.java diff --git a/java/java-tests/testData/refactoring/introduceField/afterFromLambdaExpr.java b/java/java-tests/testData/refactoring/introduceField/afterFromLambdaExpr.java new file mode 100644 index 000000000000..fe0d2dac99d0 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceField/afterFromLambdaExpr.java @@ -0,0 +1,14 @@ +interface SAM { + X m(int i, int j); + } + +class Foo { + public final int anInt = 0; + + void test() { + m((i, j) -> { + return i + j; + }); + } + void m(SAM s) { } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceField/beforeFromLambdaExpr.java b/java/java-tests/testData/refactoring/introduceField/beforeFromLambdaExpr.java new file mode 100644 index 000000000000..f6e967f2d61e --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceField/beforeFromLambdaExpr.java @@ -0,0 +1,13 @@ +interface SAM { + X m(int i, int j); + } + +class Foo { + void test() { + m((i, j) -> { + 0 + return i + j; + }); + } + void m(SAM s) { } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceFieldInSameClassTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceFieldInSameClassTest.java index c394c2d353d0..3afcde7ff8eb 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceFieldInSameClassTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceFieldInSameClassTest.java @@ -118,6 +118,12 @@ public class IntroduceFieldInSameClassTest extends LightCodeInsightTestCase { performRefactoring(BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, false); checkResultByFile("/refactoring/introduceField/afterLocalVarAnnotations.java"); } + + public void testFromLambdaExpr() throws Exception { + configureByFile("/refactoring/introduceField/beforeFromLambdaExpr.java"); + performRefactoring(BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, false); + checkResultByFile("/refactoring/introduceField/afterFromLambdaExpr.java"); + } public void testStaticFieldInInnerClass() throws Exception { configureByFile("/refactoring/introduceField/beforeStaticFieldInInnerClass.java"); From 7cbfbd4133be44653369e47addd44e47278170a9 Mon Sep 17 00:00:00 2001 From: irengrig Date: Tue, 24 Jul 2012 20:07:03 +0400 Subject: [PATCH 33/51] IDEA-60208 VCS GUI: "Revert" and "Rollback" are used intermixed --- platform/platform-resources/src/idea/VcsActions.xml | 3 +++ .../intellij/openapi/vcs/changes/actions/RollbackAction.java | 4 ++-- .../src/git4idea/actions/GitQuickListContentProvider.java | 2 +- plugins/hg4idea/src/META-INF/plugin.xml | 2 +- plugins/svn4idea/src/META-INF/plugin.xml | 4 ++-- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/platform/platform-resources/src/idea/VcsActions.xml b/platform/platform-resources/src/idea/VcsActions.xml index 0070165c10b3..79425a6bd13f 100644 --- a/platform/platform-resources/src/idea/VcsActions.xml +++ b/platform/platform-resources/src/idea/VcsActions.xml @@ -69,6 +69,9 @@ + + diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RollbackAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RollbackAction.java index 3eb481bc28e7..b735d3e780e6 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RollbackAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RollbackAction.java @@ -82,9 +82,9 @@ public class RollbackAction extends AnAction implements DumbAware { } } e.getPresentation().setEnabled(isEnabled); + String operationName = RollbackUtil.getRollbackOperationName(project); + e.getPresentation().setText(operationName); if (isEnabled) { - String operationName = RollbackUtil.getRollbackOperationName(project); - e.getPresentation().setText(operationName); e.getPresentation().setDescription(operationName + " selected changes"); } } diff --git a/plugins/git4idea/src/git4idea/actions/GitQuickListContentProvider.java b/plugins/git4idea/src/git4idea/actions/GitQuickListContentProvider.java index 6771129b7fbb..b947f866e19d 100644 --- a/plugins/git4idea/src/git4idea/actions/GitQuickListContentProvider.java +++ b/plugins/git4idea/src/git4idea/actions/GitQuickListContentProvider.java @@ -48,7 +48,7 @@ public class GitQuickListContentProvider implements VcsQuickListContentProvider actions.add(new Separator(activeVcs.getDisplayName())); add("CheckinProject", manager, actions); add("CheckinFiles", manager, actions); - add("ChangesView.Rollback", manager, actions); + add("ChangesView.Revert", manager, actions); addSeparator(actions); add("Vcs.ShowTabbedFileHistory", manager, actions); diff --git a/plugins/hg4idea/src/META-INF/plugin.xml b/plugins/hg4idea/src/META-INF/plugin.xml index 46c00acb22ad..baa2474bfdfc 100644 --- a/plugins/hg4idea/src/META-INF/plugin.xml +++ b/plugins/hg4idea/src/META-INF/plugin.xml @@ -36,7 +36,7 @@ - + diff --git a/plugins/svn4idea/src/META-INF/plugin.xml b/plugins/svn4idea/src/META-INF/plugin.xml index ebd5bf5122e2..63d3b346fea7 100644 --- a/plugins/svn4idea/src/META-INF/plugin.xml +++ b/plugins/svn4idea/src/META-INF/plugin.xml @@ -58,7 +58,7 @@ - + @@ -90,7 +90,7 @@ - + From d4ac3d1215b428a60f64516030d87bbd6bfe323a Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 24 Jul 2012 20:06:40 +0400 Subject: [PATCH 34/51] test fixed --- xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.java | 4 ++-- xml/tests/src/com/intellij/xml/XMLCatalogManagerTest.java | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.java b/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.java index 739d0d3880df..f8e6f95f6f8e 100644 --- a/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.java +++ b/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.java @@ -20,7 +20,7 @@ import com.intellij.openapi.options.BaseConfigurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.ui.TextFieldWithBrowseButton; -import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -73,7 +73,7 @@ public class XMLCatalogConfigurable extends BaseConfigurable implements Searchab @Override public boolean isModified() { - return !Comparing.equal(ExternalResourceManagerEx.getInstanceEx().getCatalogPropertiesFile(), myPropertyFile.getText()); + return !StringUtil.notNullize(ExternalResourceManagerEx.getInstanceEx().getCatalogPropertiesFile()).equals(myPropertyFile.getText()); } @Override diff --git a/xml/tests/src/com/intellij/xml/XMLCatalogManagerTest.java b/xml/tests/src/com/intellij/xml/XMLCatalogManagerTest.java index 2905c3081b0c..445c23a4bcac 100644 --- a/xml/tests/src/com/intellij/xml/XMLCatalogManagerTest.java +++ b/xml/tests/src/com/intellij/xml/XMLCatalogManagerTest.java @@ -17,6 +17,7 @@ package com.intellij.xml; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.javaee.ExternalResourceManagerEx; +import com.intellij.javaee.XMLCatalogConfigurable; import com.intellij.javaee.XMLCatalogManager; import com.intellij.testFramework.IdeaTestCase; import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; @@ -75,6 +76,10 @@ public class XMLCatalogManagerTest extends LightPlatformCodeInsightFixtureTestCa } } + public void testConfigurable() throws Exception { + assertFalse(new XMLCatalogConfigurable().isModified()); + } + private XMLCatalogManager getManager() throws IOException { return new XMLCatalogManager(getTestDataPath() + "catalog.properties"); } From ee7c3b42be39a739d72b8b6f3c7b882e081b9034 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 24 Jul 2012 18:49:39 +0200 Subject: [PATCH 35/51] Report broken symlinks on reading file attributes --- bin/win/IdeaWin32.dll | Bin 35840 -> 35840 bytes bin/win/IdeaWin64.dll | Bin 40960 -> 41472 bytes native/IdeaWin32/IdeaWin32.cpp | 30 +++--- .../openapi/util/io/FileAttributes.java | 91 +++++++++--------- .../openapi/util/io/FileSystemUtil.java | 15 ++- .../openapi/util/io/win32/FileInfo.java | 2 + .../util/src/com/intellij/util/BitUtil.java | 4 + .../util/io/FileAttributesReadingTest.java | 24 +++-- 8 files changed, 95 insertions(+), 71 deletions(-) diff --git a/bin/win/IdeaWin32.dll b/bin/win/IdeaWin32.dll index 3cd28fe38ce9f8e5647b48ac14bafb0c774ae849..7dc6bcb7d9bb6cfe4d4047d5260ad5a3fc239660 100644 GIT binary patch delta 2422 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 Z*v%}%?dF0}ujlumUxO@qTASvE{2T7^OK<=H diff --git a/bin/win/IdeaWin64.dll b/bin/win/IdeaWin64.dll index 1a0323b3601f3928b9ed3a6e6b072f70dada87bf..aa37ba4b5a15df537fb3e8a2b41d6a989786b53c 100644 GIT binary patch delta 8604 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 s^zx{+12CsFDW3EtpET3 delta 8485 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 diff --git a/native/IdeaWin32/IdeaWin32.cpp b/native/IdeaWin32/IdeaWin32.cpp index 45b4c0aac26d..5f4d5ebc8a67 100644 --- a/native/IdeaWin32/IdeaWin32.cpp +++ b/native/IdeaWin32/IdeaWin32.cpp @@ -23,6 +23,8 @@ static jfieldID attributesID = NULL; static jfieldID timestampID = NULL; static jfieldID lengthID = NULL; +#define BROKEN_SYMLINK_ATTR -1 + static jclass getFileInfoClass(JNIEnv *env) { return env->FindClass("com/intellij/openapi/util/io/win32/FileInfo"); } @@ -60,9 +62,12 @@ static jobject CreateFileInfo(JNIEnv *env, jstring path, bool append, LPWIN32_FI if (IS_SET(attributes, FILE_ATTRIBUTE_REPARSE_POINT)) { if (IS_SET(lpData->dwReserved0, IO_REPARSE_TAG_SYMLINK)) { + attributes = BROKEN_SYMLINK_ATTR; + timestamp = 0; + length = 0; + size_t nameLen = env->GetStringLength(path) + wcslen(lpData->cFileName) + 2; wchar_t *lpName = (wchar_t *)malloc(nameLen * sizeof(wchar_t)); - if (lpName != NULL) { const jchar *dirName = env->GetStringChars(path, 0); wcscpy_s(lpName, nameLen, (LPCWSTR)dirName); @@ -74,21 +79,16 @@ static jobject CreateFileInfo(JNIEnv *env, jstring path, bool append, LPWIN32_FI // read symlink target attributes HANDLE th = CreateFile(lpName, 0, FILE_SHARE_ATTRIBUTES, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (th != INVALID_HANDLE_VALUE) { + BY_HANDLE_FILE_INFORMATION targetData; + if (GetFileInformationByHandle(th, &targetData)) { + attributes = targetData.dwFileAttributes | FILE_ATTRIBUTE_REPARSE_POINT; + timestamp = pairToInt64(targetData.ftLastWriteTime.dwLowDateTime, targetData.ftLastWriteTime.dwHighDateTime); + length = pairToInt64(targetData.nFileSizeLow, targetData.nFileSizeHigh); + } + CloseHandle(th); + } free(lpName); - if (th == INVALID_HANDLE_VALUE) { - return NULL; // invalid link - } - - BY_HANDLE_FILE_INFORMATION targetData; - BOOL result = GetFileInformationByHandle(th, &targetData); - CloseHandle(th); - if (result == 0) { - return NULL; // invalid link - } - - attributes = targetData.dwFileAttributes | FILE_ATTRIBUTE_REPARSE_POINT; - timestamp = pairToInt64(targetData.ftLastWriteTime.dwLowDateTime, targetData.ftLastWriteTime.dwHighDateTime); - length = pairToInt64(targetData.nFileSizeLow, targetData.nFileSizeHigh); } } else { diff --git a/platform/util/src/com/intellij/openapi/util/io/FileAttributes.java b/platform/util/src/com/intellij/openapi/util/io/FileAttributes.java index 9ed82712a354..f408edf5581b 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileAttributes.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileAttributes.java @@ -17,9 +17,9 @@ package com.intellij.openapi.util.io; import com.intellij.util.StringBuilderSpinAllocator; import org.intellij.lang.annotations.MagicConstant; +import org.jetbrains.annotations.Nullable; import static com.intellij.util.BitUtil.isSet; -import static com.intellij.util.BitUtil.notSet; /** * @version 11.1 @@ -27,13 +27,13 @@ import static com.intellij.util.BitUtil.notSet; */ @SuppressWarnings("OctalInteger") public final class FileAttributes { - public static final int DIRECTORY = 0x0001; - public static final int SPECIAL = 0x0002; - public static final int SYM_LINK = 0x0010; - public static final int HIDDEN = 0x0100; + public enum Type { FILE, DIRECTORY, SPECIAL } - @MagicConstant(flags = {DIRECTORY, SPECIAL, SYM_LINK, HIDDEN}) - public @interface FileType { } + public static final byte SYM_LINK = 0x01; + public static final byte HIDDEN = 0x20; + + @MagicConstant(flags = {SYM_LINK, HIDDEN}) + public @interface Flags { } public static final int OWNER_READ = 0400; public static final int OWNER_WRITE = 0200; @@ -48,14 +48,16 @@ public final class FileAttributes { @MagicConstant(flags = {OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ, GROUP_WRITE, GROUP_EXECUTE, OTHERS_READ, OTHERS_WRITE, OTHERS_EXECUTE}) public @interface Permissions { } + public static final FileAttributes BROKEN_SYMLINK = new FileAttributes(null, SYM_LINK, 0, 0, -1); /** - * {@linkplain #DIRECTORY} and {@linkplain #SPECIAL} bits are mutually exclusive, none of them set means a regular file.
- * {@linkplain #SYM_LINK} bit may be set along with above ones (which then denote a type of a link target).
- * {@linkplain #HIDDEN} bit may be only set on Windows. + * {@code null} means unknown type - typically broken symlink. */ - @FileType - public final int type; + @Nullable + public final Type type; + + @Flags + public final byte flags; /** * In bytes, 0 for special files.
@@ -70,7 +72,7 @@ public final class FileAttributes { public final long lastModified; /** - * UNIX permission bits (for Windows only OWNER_WRITE matters and OWNER_READ/EXECUTE are always set), or -1 if not supported.
+ * UNIX permission bits (for Windows only OWNER_WRITE matters and OWNER_READ/EXECUTE are always set), or {@code -1} if not supported.
* For symlinks - permissions of a link target. */ @Permissions @@ -84,7 +86,8 @@ public final class FileAttributes { final long length, final long lastModified, final boolean isWritable) { - this(type(isDirectory, isSpecial, isSymlink, isHidden), length, lastModified, OWNER_READ | OWNER_EXECUTE | (isWritable ? OWNER_WRITE : 0)); + this(type(isDirectory, isSpecial), flags(isSymlink, isHidden), length, lastModified, + OWNER_READ | OWNER_EXECUTE | (isWritable ? OWNER_WRITE : 0)); } public FileAttributes(final boolean isDirectory, @@ -93,45 +96,37 @@ public final class FileAttributes { final long length, final long lastModified, @Permissions final int permissions) { - this(type(isDirectory, isSpecial, isSymlink, false), length, lastModified, permissions); + this(type(isDirectory, isSpecial), flags(isSymlink, false), length, lastModified, permissions); } - private FileAttributes(@FileType final int type, + private FileAttributes(@Nullable final Type type, + @Flags final byte flags, final long length, final long lastModified, @Permissions final int permissions) { - if (isSet(type, DIRECTORY) && isSet(type, SPECIAL)) { - throw new IllegalArgumentException("DIRECTORY and SPECIAL bits cannot be set simultaneously"); - } - this.type = type; + this.flags = flags; this.length = length; this.lastModified = lastModified; this.permissions = permissions; } - @FileType - private static int type(final boolean isDirectory, final boolean isSpecial, final boolean isSymlink, final boolean isHidden) { - @FileType int type = 0; - if (isDirectory) type |= DIRECTORY; - if (isSpecial) type |= SPECIAL; - if (isSymlink) type |= SYM_LINK; - if (isHidden) type |= HIDDEN; - return type; + private static Type type(final boolean isDirectory, final boolean isSpecial) { + return isSpecial ? Type.SPECIAL : + isDirectory ? Type.DIRECTORY : + Type.FILE; } - /** Is {@code true} for files and symlinks to files (see {@linkplain #isRegularFile()}). */ - public boolean isFile() { - return notSet(type, DIRECTORY | SPECIAL); - } - - /** Is {@code true} for pure regular files only (see {@linkplain #isFile()}). */ - public boolean isRegularFile() { - return notSet(type, DIRECTORY | SPECIAL | SYM_LINK); + @Flags + private static byte flags(final boolean isSymlink, final boolean isHidden) { + @Flags byte flags = 0; + if (isSymlink) flags |= SYM_LINK; + if (isHidden) flags |= HIDDEN; + return flags; } public boolean isSymLink() { - return isSet(type, SYM_LINK); + return isSet(flags, SYM_LINK); } public boolean isWritable() { @@ -143,19 +138,20 @@ public final class FileAttributes { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - final FileAttributes that = (FileAttributes)o; - - if (type != that.type) return false; + FileAttributes that = (FileAttributes)o; + if (flags != that.flags) return false; if (lastModified != that.lastModified) return false; - if (permissions != that.permissions) return false; if (length != that.length) return false; + if (permissions != that.permissions) return false; + if (type != that.type) return false; return true; } @Override public int hashCode() { - int result = type; + int result = type != null ? type.hashCode() : 0; + result = 31 * result + (int)flags; result = 31 * result + (int)(length ^ (length >>> 32)); result = 31 * result + (int)(lastModified ^ (lastModified >>> 32)); result = 31 * result + permissions; @@ -167,10 +163,13 @@ public final class FileAttributes { final StringBuilder sb = StringBuilderSpinAllocator.alloc(); try { sb.append("[type:"); - if (isSet(type, DIRECTORY)) sb.append('d'); - else if (isSet(type, SPECIAL)) sb.append('!'); - else sb.append('f'); - if (isSet(type, SYM_LINK)) sb.append('l'); + if (type == Type.FILE) sb.append('f'); + else if (type == Type.DIRECTORY) sb.append('d'); + else if (type == Type.SPECIAL) sb.append('!'); + else sb.append('-'); + + if (isSet(flags, SYM_LINK)) sb.append('l'); + if (isSet(flags, HIDDEN)) sb.append('.'); sb.append(" length:").append(length); diff --git a/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java index abf9063d28ad..092e129f115b 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java @@ -242,7 +242,15 @@ public class FileSystemUtil { Map attributes = (Map)myReadAttributes.invoke(null, pathObj, mySchema, myNoFollowLinkOptions); final Boolean isSymbolicLink = (Boolean)attributes.get("isSymbolicLink"); if (isSymbolicLink) { - attributes = (Map)myReadAttributes.invoke(null, pathObj, mySchema, myLinkOptions); + try { + attributes = (Map)myReadAttributes.invoke(null, pathObj, mySchema, myLinkOptions); + } + catch (InvocationTargetException e) { + final Throwable cause = e.getCause(); + if (cause != null && "java.nio.file.NoSuchFileException".equals(cause.getClass().getName())) { + return FileAttributes.BROKEN_SYMLINK; + } + } } final boolean isDirectory = (Boolean)attributes.get("isDirectory"); @@ -352,6 +360,7 @@ public class FileSystemUtil { public FileAttributes getAttributes(@NotNull final String path) throws Exception { final FileInfo fileInfo = myInstance.getInfo(path); if (fileInfo == null) return null; + if (fileInfo.attributes == FileInfo.BROKEN_SYMLINK) return FileAttributes.BROKEN_SYMLINK; final boolean isDirectory = isSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_DIRECTORY); final boolean isSpecial = isSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_DEVICE); @@ -433,7 +442,9 @@ public class FileSystemUtil { if (isSymlink) { mySharedMem.clear(); res = SystemInfo.isLinux ? myLibC.__xstat64(0, path, mySharedMem) : myLibC.stat(path, mySharedMem); - if (res != 0) return null; + if (res != 0) { + return FileAttributes.BROKEN_SYMLINK; + } mode = (SystemInfo.isLinux ? mySharedMem.getInt(myModeOffset) : mySharedMem.getShort(myModeOffset)) & LibC.S_MASK; } diff --git a/platform/util/src/com/intellij/openapi/util/io/win32/FileInfo.java b/platform/util/src/com/intellij/openapi/util/io/win32/FileInfo.java index 88693715ac78..0484b3472ca4 100644 --- a/platform/util/src/com/intellij/openapi/util/io/win32/FileInfo.java +++ b/platform/util/src/com/intellij/openapi/util/io/win32/FileInfo.java @@ -24,6 +24,8 @@ import org.intellij.lang.annotations.MagicConstant; * @since 12.0 */ public class FileInfo { + public static final int BROKEN_SYMLINK = -1; + public static final int FILE_ATTRIBUTE_READONLY = 0x0001; public static final int FILE_ATTRIBUTE_HIDDEN = 0x0002; public static final int FILE_ATTRIBUTE_DIRECTORY = 0x0010; diff --git a/platform/util/src/com/intellij/util/BitUtil.java b/platform/util/src/com/intellij/util/BitUtil.java index 485d1ad21c06..a0583dfb98cd 100644 --- a/platform/util/src/com/intellij/util/BitUtil.java +++ b/platform/util/src/com/intellij/util/BitUtil.java @@ -19,6 +19,10 @@ package com.intellij.util; * @since 27.03.2012 */ public class BitUtil { + public static boolean isSet(final byte value, final byte flag) { + return (value & flag) == flag; + } + public static boolean isSet(final int value, final int flag) { return (value & flag) == flag; } diff --git a/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java b/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java index 1f0e65e23b6f..96bfb533002e 100644 --- a/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java +++ b/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java @@ -55,7 +55,8 @@ public class FileAttributesReadingTest { FileUtil.writeToFile(file, myTestData); final FileAttributes attributes = getAttributes(file); - assertEquals(0, attributes.type); + assertEquals(FileAttributes.Type.FILE, attributes.type); + assertEquals(0, attributes.flags); assertEquals(myTestData.length, attributes.length); assertTimestampEquals(file.lastModified(), attributes.lastModified); assertTrue(attributes.isWritable()); @@ -66,7 +67,8 @@ public class FileAttributesReadingTest { final File file = FileUtil.createTempDirectory(myTempDirectory, "test.", ".tmp"); final FileAttributes attributes = getAttributes(file); - assertEquals(FileAttributes.DIRECTORY, attributes.type); + assertEquals(FileAttributes.Type.DIRECTORY, attributes.type); + assertEquals(0, attributes.flags); assertEquals(file.length(), attributes.length); assertTimestampEquals(file.lastModified(), attributes.lastModified); assertTrue(attributes.isWritable()); @@ -78,7 +80,8 @@ public class FileAttributesReadingTest { final File file = new File("/dev/null"); final FileAttributes attributes = getAttributes(file); - assertEquals(FileAttributes.SPECIAL, attributes.type); + assertEquals(FileAttributes.Type.SPECIAL, attributes.type); + assertEquals(0, attributes.flags); assertEquals(0, attributes.length); assertTrue(attributes.isWritable()); } @@ -92,7 +95,8 @@ public class FileAttributesReadingTest { final File link = IoTestUtil.createTempLink(file.getPath(), new File(myTempDirectory, "link").getPath()); final FileAttributes attributes = getAttributes(link); - assertEquals(FileAttributes.SYM_LINK, attributes.type); + assertEquals(FileAttributes.Type.FILE, attributes.type); + assertEquals(FileAttributes.SYM_LINK, attributes.flags); assertEquals(myTestData.length, attributes.length); assertTimestampEquals(file.lastModified(), attributes.lastModified); assertFalse(attributes.isWritable()); @@ -111,7 +115,8 @@ public class FileAttributesReadingTest { final File link2 = IoTestUtil.createTempLink(link1.getPath(), new File(myTempDirectory, "link2").getPath()); final FileAttributes attributes = getAttributes(link2); - assertEquals(FileAttributes.SYM_LINK, attributes.type); + assertEquals(FileAttributes.Type.FILE, attributes.type); + assertEquals(FileAttributes.SYM_LINK, attributes.flags); assertEquals(myTestData.length, attributes.length); assertTimestampEquals(file.lastModified(), attributes.lastModified); assertFalse(attributes.isWritable()); @@ -128,7 +133,8 @@ public class FileAttributesReadingTest { final File link = IoTestUtil.createTempLink(file.getPath(), new File(myTempDirectory, "link").getPath()); final FileAttributes attributes = getAttributes(link); - assertEquals(FileAttributes.DIRECTORY | FileAttributes.SYM_LINK, attributes.type); + assertEquals(FileAttributes.Type.DIRECTORY, attributes.type); + assertEquals(FileAttributes.SYM_LINK, attributes.flags); assertEquals(file.length(), attributes.length); assertTimestampEquals(file.lastModified(), attributes.lastModified); if (SystemInfo.isUnix) assertFalse(attributes.isWritable()); @@ -142,8 +148,10 @@ public class FileAttributesReadingTest { final File file = FileUtil.createTempFile(myTempDirectory, "test.", ".txt", false); final File link = IoTestUtil.createTempLink(file.getPath(), new File(myTempDirectory, "link").getPath()); - final FileAttributes attributes = FileSystemUtil.getAttributes(link); - assertNull(attributes); + final FileAttributes attributes = getAttributes(link); + assertNull(attributes.type); + assertEquals(FileAttributes.SYM_LINK, attributes.flags); + assertEquals(0, attributes.length); final String target = FileSystemUtil.resolveSymLink(link); assertNull(target); From 26ff4c803b0008686c563a408cc29b3ee45ede27 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 24 Jul 2012 18:53:10 +0200 Subject: [PATCH 36/51] StringUtil.charsEqual --- .../util/src/com/intellij/openapi/util/text/StringUtil.java | 3 +++ 1 file changed, 3 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 ec9efc4e0729..a9e8e2a27794 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -2272,6 +2272,9 @@ public class StringUtil extends StringUtilRt { return buffer.toString(); } + public static boolean charsEqual(char a, char b, boolean ignoreCase) { + return ignoreCase ? charsEqualIgnoreCase(a, b) : a == b; + } public static boolean charsEqualIgnoreCase(char a, char b) { return StringUtilRt.charsEqualIgnoreCase(a, b); } From 79bbbc15f2c93f2eda9f8517441931d4cf958c56 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 24 Jul 2012 20:42:09 +0400 Subject: [PATCH 37/51] cleanup --- .../src/com/intellij/execution/impl/RunConfigurable.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java index bde6e685195d..e7b3db32a53f 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java @@ -96,7 +96,7 @@ class RunConfigurable extends BaseConfigurable { this(project, null); } - public RunConfigurable(final Project project, final RunDialogBase runDialog) { + public RunConfigurable(final Project project, @Nullable final RunDialogBase runDialog) { myProject = project; myRunDialog = runDialog; } @@ -183,7 +183,7 @@ class RunConfigurable extends BaseConfigurable { final ConfigurationType[] factories = manager.getConfigurationFactories(); for (ConfigurationType type : factories) { final RunnerAndConfigurationSettings[] configurations = manager.getConfigurationSettings(type); - if (configurations != null && configurations.length > 0) { + if (configurations.length > 0) { final DefaultMutableTreeNode typeNode = new DefaultMutableTreeNode(type); myRoot.add(typeNode); for (RunnerAndConfigurationSettings configuration : configurations) { @@ -640,7 +640,6 @@ class RunConfigurable extends BaseConfigurable { manager.addConfiguration(each.getSettings(), each.isShared(), each.getStepsBeforeLaunch(), false); } - RunnerAndConfigurationSettings selected = manager.getSelectedConfiguration(); for (RunnerAndConfigurationSettings each : toDeleteSettings) { manager.removeConfiguration(each); } @@ -1181,7 +1180,7 @@ class RunConfigurable extends BaseConfigurable { RunnerAndConfigurationSettings selectedSettings = getSettings(treeNode); if (selectedSettings == null) return; - RunnerAndConfigurationSettings siblingSettings = null; + RunnerAndConfigurationSettings siblingSettings; if (myDirection < 0) { siblingSettings = getSettings(treeNode.getPreviousSibling()); } else { From fd8bf041f4f730e5963f43567b250b4870e36a9e Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 24 Jul 2012 21:17:56 +0400 Subject: [PATCH 38/51] test fix --- .../com/intellij/psi/search/FileTypeIndexTest.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/psi/search/FileTypeIndexTest.java b/platform/platform-tests/testSrc/com/intellij/psi/search/FileTypeIndexTest.java index bb01e38f9021..46f46358affc 100644 --- a/platform/platform-tests/testSrc/com/intellij/psi/search/FileTypeIndexTest.java +++ b/platform/platform-tests/testSrc/com/intellij/psi/search/FileTypeIndexTest.java @@ -15,17 +15,15 @@ */ package com.intellij.psi.search; -import com.intellij.openapi.fileTypes.FileNameMatcher; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.fileTypes.ex.FakeFileType; +import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.PlatformTestCase; import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; import org.jetbrains.annotations.NotNull; -import java.util.Collections; - /** * @author Dmitry Avdeev * Date: 7/24/12 @@ -58,8 +56,12 @@ public class FileTypeIndexTest extends LightPlatformCodeInsightFixtureTestCase { FileTypeIndex index = new FileTypeIndex(FileTypeManager.getInstance()); int version = index.getVersion(); - FileTypeManager.getInstance().registerFileType(foo, Collections.emptyList()); - - assertNotSame(version, index.getVersion()); + try { + FileTypeManagerEx.getInstanceEx().registerFileType(foo); + assertNotSame(version, index.getVersion()); + } + finally { + FileTypeManagerEx.getInstanceEx().unregisterFileType(foo); + } } } From 3768d8628e6dac0f3180d24160213a67d29c0632 Mon Sep 17 00:00:00 2001 From: Alexander Kirillin Date: Tue, 24 Jul 2012 22:04:53 +0400 Subject: [PATCH 39/51] OC-3575 Localization: renaming localization keys, find usages --- .../refactoring/rename/inplace/MemberInplaceRenamer.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java index caf14daadbf3..f25af5171b09 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java @@ -181,9 +181,7 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer { try { final PsiNamedElement variable = getVariable(); if (variable != null && !newName.equals(myOldName)) { - final NamesValidator namesValidator = LanguageNamesValidation.INSTANCE.forLanguage(variable.getLanguage()); - LOG.assertTrue(namesValidator != null); - if (namesValidator.isIdentifier(newName, myProject)) { + if (isIdentifier(newName, variable.getLanguage())) { final PsiElement substituted = getSubstituted(); if (substituted == null) { return; From 2de45c677f2ca796dbdd79823ea5cfb574f4caac Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 24 Jul 2012 20:21:01 +0200 Subject: [PATCH 40/51] Cleanup --- .../vfs/impl/local/LocalFileSystemBase.java | 3 + .../{Win32Kernel.java => Win32FsCache.java} | 57 ++++------- .../vfs/impl/win32/Win32LocalFileSystem.java | 96 ++++--------------- .../openapi/util/io/FileSystemUtil.java | 2 +- .../openapi/util/io/win32/FileInfo.java | 4 + 5 files changed, 44 insertions(+), 118 deletions(-) rename platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/{Win32Kernel.java => Win32FsCache.java} (67%) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java index 58079ef5bf21..f5bdf93eaff7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java @@ -52,6 +52,9 @@ import java.util.Locale; public abstract class LocalFileSystemBase extends LocalFileSystem { protected static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl"); + protected static final long DEFAULT_LENGTH = 0; + protected static final long DEFAULT_TIMESTAMP = 0; + private final List myHandlers = new ArrayList(); @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32FsCache.java similarity index 67% rename from platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java rename to platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32FsCache.java index d7cf906ac2a4..0f134d6d2b98 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32FsCache.java @@ -15,22 +15,25 @@ */ package com.intellij.openapi.vfs.impl.win32; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.win32.FileInfo; import com.intellij.openapi.util.io.win32.IdeaWin32; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.Map; /** * @author Dmitry Avdeev */ -class Win32Kernel { +class Win32FsCache { + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.win32.Win32FsCache"); + private final IdeaWin32 myKernel = IdeaWin32.getInstance(); private final Map myCache = new THashMap(); @@ -39,11 +42,12 @@ class Win32Kernel { } @NotNull - public String[] list(@NotNull String absolutePath) { + String[] list(@NotNull String absolutePath) { FileInfo[] fileInfos = myKernel.listChildren(absolutePath.replace('/', '\\') + "\\*.*"); if (fileInfos == null) { return ArrayUtil.EMPTY_STRING_ARRAY; } + ArrayList names = new ArrayList(fileInfos.length); for (FileInfo info : fileInfos) { if (info.name.equals(".")) { @@ -60,41 +64,14 @@ class Win32Kernel { return ArrayUtil.toStringArray(names); } - public void exists(@NotNull String path) throws FileNotFoundException { - getInfo(path); - } - - public boolean isDirectory(@NotNull String path) throws FileNotFoundException { - FileInfo data = getInfo(path); - return (data.attributes & FileInfo.FILE_ATTRIBUTE_DIRECTORY) != 0; - } - - public boolean isWritable(@NotNull String path) throws FileNotFoundException { - FileInfo fileInfo = getInfo(path); - myCache.remove(path); - return (fileInfo.attributes & FileInfo.FILE_ATTRIBUTE_READONLY) == 0; - } - - public long getTimeStamp(@NotNull String path) throws FileNotFoundException { - long timestamp = getInfo(path).timestamp; - return timestamp / 10000 - 11644473600000l; - } - - public long getLength(@NotNull String path) throws FileNotFoundException { - return getInfo(path).length; - } - - @NotNull - private FileInfo getInfo(@NotNull String path) throws FileNotFoundException { - FileInfo info = doGetInfo(path); - if (info == null) { - throw new FileNotFoundException(path); - } - return info; - } - @Nullable - FileInfo doGetInfo(@NotNull String path) { + FileInfo getInfo(@NotNull VirtualFile file) { + // todo[r.sh]: uncomment and remove FS cache usage wherever it's not bulk? + //if (myCache.isEmpty()) { + // LOG.error("Called on empty cache - shouldn't happen"); + //} + + String path = file.getPath(); FileInfo info = myCache.get(path); if (info == null) { info = myKernel.getInfo(path.replace('/', '\\')); @@ -107,8 +84,10 @@ class Win32Kernel { } @FileUtil.FileBooleanAttributes - public int getBooleanAttributes(@NotNull String path, @FileUtil.FileBooleanAttributes int flags) throws FileNotFoundException { - FileInfo info = getInfo(path); + int getBooleanAttributes(@NotNull VirtualFile file, @FileUtil.FileBooleanAttributes int flags) { + FileInfo info = getInfo(file); + if (info == null) return 0; + int result = 0; if ((flags & FileUtil.BA_EXISTS) != 0) { result |= FileUtil.BA_EXISTS; diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java index d9a3503f8e27..e1cd15859bdb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java @@ -15,7 +15,7 @@ */ package com.intellij.openapi.vfs.impl.win32; -import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.io.win32.FileInfo; import com.intellij.openapi.util.io.win32.IdeaWin32; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.impl.local.LocalFileSystemBase; @@ -23,17 +23,16 @@ import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.FileNotFoundException; -import java.util.Arrays; import java.util.Collection; import java.util.Set; +import static com.intellij.util.BitUtil.isSet; +import static com.intellij.util.BitUtil.notSet; + /** * @author Dmitry Avdeev */ public class Win32LocalFileSystem extends LocalFileSystemBase { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.win32.Win32LocalFileSystem"); - public static boolean isAvailable() { return IdeaWin32.isAvailable(); } @@ -46,14 +45,13 @@ public class Win32LocalFileSystem extends LocalFileSystemBase { }; public static Win32LocalFileSystem getWin32Instance() { - if (!isAvailable()) throw new RuntimeException("DLL is not loaded"); + if (!isAvailable()) throw new RuntimeException("Native filesystem for Windows is not loaded"); Win32LocalFileSystem fileSystem = THREAD_LOCAL.get(); - fileSystem.myKernel.clearCache(); + fileSystem.myFsCache.clearCache(); return fileSystem; } - private final Win32Kernel myKernel = new Win32Kernel(); - public static boolean checkMe = false; + private final Win32FsCache myFsCache = new Win32FsCache(); private Win32LocalFileSystem() { } @@ -64,90 +62,37 @@ public class Win32LocalFileSystem extends LocalFileSystemBase { return ArrayUtil.EMPTY_STRING_ARRAY; } - try { - String[] strings = myKernel.list(file.getPath()); - if (checkMe && !Arrays.asList(strings).equals(Arrays.asList(super.list(file)))) { - LOG.error(file.getPath()); - } - return strings; - } - catch (Exception e) { - if (checkMe) { - assert false; - } - return super.list(file); - } + return myFsCache.list(file.getPath()); } @Override public boolean exists(@NotNull VirtualFile fileOrDirectory) { if (fileOrDirectory.getParent() == null) return true; - try { - myKernel.exists(fileOrDirectory.getPath()); - if (checkMe && !super.exists(fileOrDirectory)) { - LOG.error(fileOrDirectory.getPath()); - } - return true; - } - catch (FileNotFoundException e) { - return super.exists(fileOrDirectory); - } + return myFsCache.getInfo(fileOrDirectory) != null; } @Override public boolean isDirectory(@NotNull VirtualFile file) { - try { - boolean b = myKernel.isDirectory(file.getPath()); - if (checkMe && b != super.isDirectory(file)) { - LOG.error(file.getPath()); - } - return b; - } - catch (FileNotFoundException e) { - return super.isDirectory(file); - } + final FileInfo fileInfo = myFsCache.getInfo(file); + return fileInfo != null && isSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_DIRECTORY); } @Override public boolean isWritable(@NotNull VirtualFile file) { - try { - boolean b = myKernel.isWritable(file.getPath()); - if (checkMe && b != super.isWritable(file)) { - LOG.error(file.getPath()); - } - return b; - } - catch (FileNotFoundException e) { - return super.isWritable(file); - } + final FileInfo fileInfo = myFsCache.getInfo(file); + return fileInfo != null && notSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_READONLY); } @Override public long getTimeStamp(@NotNull VirtualFile file) { - try { - long timeStamp = myKernel.getTimeStamp(file.getPath()); - if (checkMe && timeStamp != super.getTimeStamp(file)) { - LOG.error(file.getPath()); - } - return timeStamp; - } - catch (FileNotFoundException e) { - return super.getTimeStamp(file); - } + final FileInfo fileInfo = myFsCache.getInfo(file); + return fileInfo != null ? fileInfo.getTimestamp() : DEFAULT_TIMESTAMP; } @Override public long getLength(@NotNull VirtualFile file) { - try { - long length = myKernel.getLength(file.getPath()); - if (checkMe && length != super.getLength(file)) { - LOG.error(file.getPath()); - } - return length; - } - catch (FileNotFoundException e) { - return super.getLength(file); - } + final FileInfo fileInfo = myFsCache.getInfo(file); + return fileInfo != null ? fileInfo.length : DEFAULT_LENGTH; } @NotNull @@ -170,11 +115,6 @@ public class Win32LocalFileSystem extends LocalFileSystemBase { @Override public int getBooleanAttributes(@NotNull VirtualFile file, int flags) { - try { - return myKernel.getBooleanAttributes(file.getPath(), flags); - } - catch (FileNotFoundException e) { - return super.getBooleanAttributes(file, flags); - } + return myFsCache.getBooleanAttributes(file, flags); } } diff --git a/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java index 092e129f115b..cd59b97badc8 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java @@ -367,7 +367,7 @@ public class FileSystemUtil { final boolean isSymlink = isSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_REPARSE_POINT); final boolean isHidden = isSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_HIDDEN); final boolean isWritable = !isSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_READONLY); - final long timestamp = fileInfo.timestamp / 10000 - 11644473600000l; + final long timestamp = fileInfo.getTimestamp(); return new FileAttributes(isDirectory, isSpecial, isSymlink, isHidden, fileInfo.length, timestamp, isWritable); } diff --git a/platform/util/src/com/intellij/openapi/util/io/win32/FileInfo.java b/platform/util/src/com/intellij/openapi/util/io/win32/FileInfo.java index 0484b3472ca4..4c6eee7f22af 100644 --- a/platform/util/src/com/intellij/openapi/util/io/win32/FileInfo.java +++ b/platform/util/src/com/intellij/openapi/util/io/win32/FileInfo.java @@ -38,6 +38,10 @@ public class FileInfo { public long timestamp; public long length; + public long getTimestamp() { + return timestamp / 10000 - 11644473600000l; + } + public String toString() { return name; } From 27b9fc66d3a66c7b98e75927678d1b9d50f5dc07 Mon Sep 17 00:00:00 2001 From: Andrey Vokin Date: Mon, 23 Jul 2012 18:43:08 +0400 Subject: [PATCH 41/51] Some useful test methods moved from ruby-tests to common test frameworks --- .../testFramework/CodeInsightTestCase.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 platform/testFramework/src/com/intellij/testFramework/CodeInsightTestCase.java diff --git a/platform/testFramework/src/com/intellij/testFramework/CodeInsightTestCase.java b/platform/testFramework/src/com/intellij/testFramework/CodeInsightTestCase.java new file mode 100644 index 000000000000..2f9710cb817d --- /dev/null +++ b/platform/testFramework/src/com/intellij/testFramework/CodeInsightTestCase.java @@ -0,0 +1,55 @@ +package com.intellij.testFramework; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.*; +import com.intellij.testFramework.fixtures.CodeInsightTestFixture; +import org.jetbrains.annotations.NonNls; + +/** + * User: Andrey.Vokin + * Date: 7/23/12 + */ +public class CodeInsightTestCase extends UsefulTestCase { + @NonNls protected static final String CARET_STR = ""; + + protected CodeInsightTestFixture myFixture; + + protected Project getProject() { + return myFixture.getProject(); + } + + protected int findOffsetBySignature(String signature) { + return findOffsetBySignature(signature, myFixture.getFile()); + } + + protected int findOffsetBySignature(String signature, final PsiFile psiFile) { + final String caretSignature = CARET_STR; + int caretOffset = signature.indexOf(caretSignature); + assert caretOffset >= 0; + signature = signature.substring(0, caretOffset) + signature.substring(caretOffset + caretSignature.length()); + int pos = PsiDocumentManager.getInstance(getProject()).getDocument(psiFile).getText().indexOf(signature); + assertTrue(pos >= 0); + return pos + caretOffset; + } + + protected PsiReference findReferenceBySignature(final String signature) { + final int offset = findOffsetBySignature(signature); + return myFixture.getFile().findReferenceAt(offset); + } + + protected PsiElement findPsiBySignature(final String signature) { + return findPsiBySignature(signature, myFixture.getFile()); + } + + protected PsiElement findPsiBySignature(final String signature, final PsiFile psiFile) { + final int offset = findOffsetBySignature(signature, psiFile); + return psiFile.findElementAt(offset); + } + + protected PsiElement findPsiBySignature(final String signature, final VirtualFile file) { + final PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(file); + final int offset = findOffsetBySignature(signature, psiFile); + return psiFile.findElementAt(offset); + } +} From 6a39c45c4b1dd401b08228676e7e49ba9c6ea2eb Mon Sep 17 00:00:00 2001 From: Yuri Denison Date: Wed, 25 Jul 2012 12:24:28 +0400 Subject: [PATCH 42/51] #RUBY-11649 fixed --- .../generation/CommentByBlockCommentHandler.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByBlockCommentHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByBlockCommentHandler.java index 6a879e9000b2..a858bb789133 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByBlockCommentHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByBlockCommentHandler.java @@ -155,6 +155,7 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler { final Boolean value = ((IndentedCommenter)commenter).forceIndentedLineComment(); if (value != null && value == Boolean.TRUE) { selectionStart = myDocument.getLineStartOffset(myDocument.getLineNumber(selectionStart)); + selectionEnd = myDocument.getLineEndOffset(myDocument.getLineNumber(selectionEnd)); } } commentRange(selectionStart, selectionEnd, prefix, suffix, commenter); @@ -162,6 +163,16 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler { else { EditorUtil.fillVirtualSpaceUntilCaret(editor); int caretOffset = myEditor.getCaretModel().getOffset(); + if (commenter instanceof IndentedCommenter) { + final Boolean value = ((IndentedCommenter)commenter).forceIndentedLineComment(); + if (value != null && value == Boolean.TRUE) { + final int lineNumber = myDocument.getLineNumber(caretOffset); + final int start = myDocument.getLineStartOffset(lineNumber); + final int end = myDocument.getLineEndOffset(lineNumber); + commentRange(start, end, prefix, suffix, commenter); + return; + } + } myDocument.insertString(caretOffset, prefix + suffix); myEditor.getCaretModel().moveToOffset(caretOffset + prefix.length()); } From 2e571948abd12b95af2afab4a5372d2ec89a3678 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 25 Jul 2012 10:24:11 +0200 Subject: [PATCH 43/51] IDEA-88179 Allow to switch off completion item selection by typing dot, space etc. --- .../codeInsight/lookup/impl/LookupTypedHandler.java | 8 +++++++- .../platform-resources-en/src/misc/registry.properties | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupTypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupTypedHandler.java index b099d85c5f21..466b3e0dfee2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupTypedHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupTypedHandler.java @@ -43,6 +43,7 @@ import com.intellij.openapi.editor.ex.ScrollingModelEx; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -230,6 +231,9 @@ public class LookupTypedHandler extends TypedHandlerDelegate { } static CharFilter.Result getLookupAction(final char charTyped, final LookupImpl lookup) { + if (!Registry.is("ide.completion.allow.finishing.by.chars")) { + return CharFilter.Result.ADD_TO_PREFIX; + } final CharFilter.Result filtersDecision = getFiltersDecision(charTyped, lookup); final LookupElement currentItem = lookup.getCurrentItem(); @@ -249,7 +253,9 @@ public class LookupTypedHandler extends TypedHandlerDelegate { } } - if (filtersDecision != null) return filtersDecision; + if (filtersDecision != null) { + return filtersDecision; + } throw new AssertionError("Typed char not handler by char filter: c=" + charTyped + "; prefix=" + currentItem + "; filters=" + Arrays.toString(getFilters())); diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index ac695573513b..70b01aa4b497 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -200,6 +200,9 @@ projectView.hide.dot.idea=true show.live.templates.in.completion=false documentation.component.editor.font=false +ide.completion.allow.finishing.by.chars=true +ide.completion.allow.finishing.by.chars.description=Controls whether typing dot, space, etc. may select the current lookup item + ide.completion.middle.matching=true # suppress inspection "UnusedProperty" ide.completion.middle.matching.description=Suggest items in completion that contain the entered string somewhere in the middle. From ad5e700fad09f3e948a00ecda2fb250494a43a2a Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 25 Jul 2012 10:33:29 +0200 Subject: [PATCH 44/51] IDEA-89217 Completion doesn't suggests constants inside annotation array --- .../codeInsight/completion/JavaCompletionContributor.java | 2 +- .../codeInsight/completion/normal/ConstantInAnno.java | 8 ++++++++ .../completion/normal/ConstantInAnno_after.java | 8 ++++++++ .../codeInsight/completion/NormalCompletionTest.groovy | 2 ++ 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normal/ConstantInAnno.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/ConstantInAnno_after.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java index 38a99c323cc0..d7215f034ae9 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java @@ -107,7 +107,7 @@ public class JavaCompletionContributor extends CompletionContributor { @Nullable public static ElementFilter getReferenceFilter(PsiElement position) { // Completion after extends in interface, type parameter and implements in class - final PsiClass containingClass = PsiTreeUtil.getParentOfType(position, PsiClass.class, false, PsiCodeBlock.class, PsiMethod.class, PsiExpressionList.class, PsiVariable.class); + final PsiClass containingClass = PsiTreeUtil.getParentOfType(position, PsiClass.class, false, PsiCodeBlock.class, PsiMethod.class, PsiExpressionList.class, PsiVariable.class, PsiAnnotation.class); if (containingClass != null && psiElement().afterLeaf(PsiKeyword.EXTENDS, PsiKeyword.IMPLEMENTS, ",", "&").accepts(position)) { return new AndFilter(ElementClassFilter.CLASS, new NotFilter(new AssignableFromContextFilter())); } diff --git a/java/java-tests/testData/codeInsight/completion/normal/ConstantInAnno.java b/java/java-tests/testData/codeInsight/completion/normal/ConstantInAnno.java new file mode 100644 index 000000000000..6f6759f83a47 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ConstantInAnno.java @@ -0,0 +1,8 @@ +public final class FileAttributes { + public static final int SYM_LINK = 0x01; + public static final int BROKEN_SYM_LINK = 0x02; + public static final int HIDDEN = 0x20; + + @MagicConstant(flags = {SYM_LINK, BROK, HIDDEN}) + public @interface Flags { } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/ConstantInAnno_after.java b/java/java-tests/testData/codeInsight/completion/normal/ConstantInAnno_after.java new file mode 100644 index 000000000000..f889b8d31f54 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ConstantInAnno_after.java @@ -0,0 +1,8 @@ +public final class FileAttributes { + public static final int SYM_LINK = 0x01; + public static final int BROKEN_SYM_LINK = 0x02; + public static final int HIDDEN = 0x20; + + @MagicConstant(flags = {SYM_LINK, BROKEN_SYM_LINK, HIDDEN}) + public @interface Flags { } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index 2a8845b7d0e1..dd0894ef1294 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -1293,6 +1293,8 @@ public class ListUtils { public void testPackageInMemberType() { doTest() } + public void testConstantInAnno() { doTest() } + public void testClassNameDot() { doTest('.') } public void testClassNameDotBeforeCall() { From 7740567b1ec6b50bb4334a3242aa419ae8be2fec Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 25 Jul 2012 11:05:22 +0200 Subject: [PATCH 45/51] show progress window in the same modality state it was started (IDEA-88788) --- .../openapi/progress/util/ProgressWindow.java | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java index 53221843a101..7f82d992521f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java @@ -18,6 +18,7 @@ package com.intellij.openapi.progress.util; import com.intellij.ide.IdeEventQueue; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; @@ -149,16 +150,16 @@ public class ProgressWindow extends BlockingProgressIndicator implements Disposa } protected void prepareShowDialog() { - UIUtil.invokeLaterIfNeeded(new Runnable() { + // We know at least about one use-case that requires special treatment here: many short (in terms of time) progress tasks are + // executed in a small amount of time. Problem: UI blinks and looks ugly if we show progress dialog that disappears shortly + // for each of them. Solution is to postpone the tasks of showing progress dialog. Hence, it will not be shown at all + // if the task is already finished when the time comes. + Timer timer = UIUtil.createNamedTimer("Progress window timer",myDelayInMillis, new ActionListener() { @Override - public void run() { - // We know at least about one use-case that requires special treatment here: many short (in terms of time) progress tasks are - // executed in a small amount of time. Problem: UI blinks and looks ugly if we show progress dialog that disappears shortly - // for each of them. Solution is to postpone the tasks of showing progress dialog. Hence, it will not be shown at all - // if the task is already finished when the time comes. - Timer timer = UIUtil.createNamedTimer("Progress window timer",myDelayInMillis, new ActionListener() { + public void actionPerformed(ActionEvent e) { + ApplicationManager.getApplication().invokeLater(new Runnable() { @Override - public void actionPerformed(ActionEvent e) { + public void run() { if (isRunning()) { if (myDialog != null) { final DialogWrapper popup = myDialog.myPopup; @@ -179,11 +180,11 @@ public class ProgressWindow extends BlockingProgressIndicator implements Disposa Disposer.dispose(ProgressWindow.this); } } - }); - timer.setRepeats(false); - timer.start(); + }, getModalityState()); } }); + timer.setRepeats(false); + timer.start(); } public void startBlocking() { @@ -353,10 +354,6 @@ public class ProgressWindow extends BlockingProgressIndicator implements Disposa return myTitle; } - protected static int getPercentage(double fraction) { - return (int)(fraction * 99 + 0.5); - } - protected class MyDialog implements Disposable { private long myLastTimeDrawn = -1; private volatile boolean myShouldShowBackground; From 8cdaaee00d8b7a8ca82b397d615afb1a1ed1bb64 Mon Sep 17 00:00:00 2001 From: Evgeny Pasynkov Date: Wed, 25 Jul 2012 12:10:51 +0200 Subject: [PATCH 46/51] move PsiShortNamesCache to java-indexing --- .../intellij/psi/search/PsiShortNamesCache.java | 0 .../psi/impl/CompositeShortNamesCache.java | 0 .../intellij/psi/impl/PsiShortNamesCacheImpl.java | 6 +++--- .../impl/java/stubs/index/JavaFieldNameIndex.java | 0 .../impl/java/stubs/index/JavaMethodNameIndex.java | 0 .../java/stubs/index/JavaShortClassNameIndex.java | 0 .../intellij/core/CoreApplicationEnvironment.java | 1 + .../com/intellij/core/CoreProjectEnvironment.java | 14 ++++++++++++++ .../src/com/intellij/psi/search/FilenameIndex.java | 0 .../util/indexing/ScalarIndexExtension.java | 0 .../uiDesigner/GuiDesignerConfigurable.java | 1 - 11 files changed, 18 insertions(+), 4 deletions(-) rename java/{openapi => java-indexing-api}/src/com/intellij/psi/search/PsiShortNamesCache.java (100%) rename java/{java-impl => java-indexing-impl}/src/com/intellij/psi/impl/CompositeShortNamesCache.java (100%) rename java/{java-impl => java-indexing-impl}/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java (97%) rename java/{java-impl => java-indexing-impl}/src/com/intellij/psi/impl/java/stubs/index/JavaFieldNameIndex.java (100%) rename java/{java-impl => java-indexing-impl}/src/com/intellij/psi/impl/java/stubs/index/JavaMethodNameIndex.java (100%) rename java/{java-impl => java-indexing-impl}/src/com/intellij/psi/impl/java/stubs/index/JavaShortClassNameIndex.java (100%) rename platform/{lang-impl => indexing-impl}/src/com/intellij/psi/search/FilenameIndex.java (100%) rename platform/{lang-impl => indexing-impl}/src/com/intellij/util/indexing/ScalarIndexExtension.java (100%) diff --git a/java/openapi/src/com/intellij/psi/search/PsiShortNamesCache.java b/java/java-indexing-api/src/com/intellij/psi/search/PsiShortNamesCache.java similarity index 100% rename from java/openapi/src/com/intellij/psi/search/PsiShortNamesCache.java rename to java/java-indexing-api/src/com/intellij/psi/search/PsiShortNamesCache.java diff --git a/java/java-impl/src/com/intellij/psi/impl/CompositeShortNamesCache.java b/java/java-indexing-impl/src/com/intellij/psi/impl/CompositeShortNamesCache.java similarity index 100% rename from java/java-impl/src/com/intellij/psi/impl/CompositeShortNamesCache.java rename to java/java-indexing-impl/src/com/intellij/psi/impl/CompositeShortNamesCache.java diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java b/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java similarity index 97% rename from java/java-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java rename to java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java index c6989f730f34..215c9eb22fb5 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java @@ -15,7 +15,7 @@ */ package com.intellij.psi.impl; -import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.impl.java.stubs.index.JavaFieldNameIndex; @@ -42,7 +42,7 @@ import java.util.Collection; import java.util.List; import java.util.Set; -class PsiShortNamesCacheImpl extends PsiShortNamesCache { +public class PsiShortNamesCacheImpl extends PsiShortNamesCache { private final PsiManagerEx myManager; public PsiShortNamesCacheImpl(PsiManagerEx manager) { @@ -225,7 +225,7 @@ class PsiShortNamesCacheImpl extends PsiShortNamesCache { }); for (T member : members) { - ProgressManager.checkCanceled(); + ProgressIndicatorProvider.checkCanceled(); if (!scope.contains(member.getContainingFile().getVirtualFile())) continue; if (!set.add(member)) continue; diff --git a/java/java-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFieldNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFieldNameIndex.java similarity index 100% rename from java/java-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFieldNameIndex.java rename to java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFieldNameIndex.java diff --git a/java/java-impl/src/com/intellij/psi/impl/java/stubs/index/JavaMethodNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaMethodNameIndex.java similarity index 100% rename from java/java-impl/src/com/intellij/psi/impl/java/stubs/index/JavaMethodNameIndex.java rename to java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaMethodNameIndex.java diff --git a/java/java-impl/src/com/intellij/psi/impl/java/stubs/index/JavaShortClassNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaShortClassNameIndex.java similarity index 100% rename from java/java-impl/src/com/intellij/psi/impl/java/stubs/index/JavaShortClassNameIndex.java rename to java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaShortClassNameIndex.java diff --git a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java index b1d7f8dda27c..9602e9463bc2 100644 --- a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java +++ b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java @@ -258,6 +258,7 @@ public class CoreApplicationEnvironment { }); } + public static void registerExtensionPoint(final ExtensionsArea area, final ExtensionPointName extensionPointName, final Class aClass) { final String name = extensionPointName.getName(); diff --git a/platform/core-impl/src/com/intellij/core/CoreProjectEnvironment.java b/platform/core-impl/src/com/intellij/core/CoreProjectEnvironment.java index 9c285ef6a2a3..2f1570b4c56b 100644 --- a/platform/core-impl/src/com/intellij/core/CoreProjectEnvironment.java +++ b/platform/core-impl/src/com/intellij/core/CoreProjectEnvironment.java @@ -20,10 +20,12 @@ import com.intellij.mock.MockFileIndexFacade; import com.intellij.mock.MockProject; import com.intellij.mock.MockResolveScopeManager; import com.intellij.openapi.Disposable; +import com.intellij.openapi.extensions.ExtensionPoint; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.roots.FileIndexFacade; +import com.intellij.openapi.util.Disposer; import com.intellij.psi.PsiFileFactory; import com.intellij.psi.PsiManager; import com.intellij.psi.impl.*; @@ -96,6 +98,18 @@ public class CoreProjectEnvironment { CoreApplicationEnvironment.registerExtensionPoint(Extensions.getArea(myProject), extensionPointName, aClass); } + protected void addProjectExtension(final ExtensionPointName name, final T extension) { + final ExtensionPoint extensionPoint = Extensions.getArea(myProject).getExtensionPoint(name); + extensionPoint.registerExtension(extension); + Disposer.register(myParentDisposable, new Disposable() { + @Override + public void dispose() { + extensionPoint.unregisterExtension(extension); + } + }); + } + + public void registerProjectComponent(final Class interfaceClass, final T implementation) { CoreApplicationEnvironment.registerComponentInstance(myProject.getPicoContainer(), interfaceClass, implementation); } diff --git a/platform/lang-impl/src/com/intellij/psi/search/FilenameIndex.java b/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java similarity index 100% rename from platform/lang-impl/src/com/intellij/psi/search/FilenameIndex.java rename to platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ScalarIndexExtension.java b/platform/indexing-impl/src/com/intellij/util/indexing/ScalarIndexExtension.java similarity index 100% rename from platform/lang-impl/src/com/intellij/util/indexing/ScalarIndexExtension.java rename to platform/indexing-impl/src/com/intellij/util/indexing/ScalarIndexExtension.java diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/GuiDesignerConfigurable.java b/plugins/ui-designer/src/com/intellij/uiDesigner/GuiDesignerConfigurable.java index fa013d413f70..2611a38414b4 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/GuiDesignerConfigurable.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/GuiDesignerConfigurable.java @@ -16,7 +16,6 @@ package com.intellij.uiDesigner; import com.intellij.codeInsight.CodeInsightUtil; -import com.intellij.icons.AllIcons; import com.intellij.ui.ListCellRendererWrapper; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; From 289a6a9b6ce47785ae87676a625e6485864163f5 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 24 Jul 2012 22:05:51 +0400 Subject: [PATCH 47/51] some space added --- ...DebuggerParametersPatcherConfigurable.form | 47 +++++++------------ .../impl/ConfigurationSettingsEditor.form | 8 ++-- .../impl/ConfigurationSettingsEditor.java | 5 +- 3 files changed, 25 insertions(+), 35 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/GenericDebuggerParametersPatcherConfigurable.form b/java/debugger/impl/src/com/intellij/debugger/ui/GenericDebuggerParametersPatcherConfigurable.form index d40facc9a413..01cb7956c2bd 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/GenericDebuggerParametersPatcherConfigurable.form +++ b/java/debugger/impl/src/com/intellij/debugger/ui/GenericDebuggerParametersPatcherConfigurable.form @@ -1,27 +1,24 @@ - + - - + - + - - + - - + @@ -29,8 +26,7 @@ - - + @@ -40,19 +36,17 @@ - + - - + - - + @@ -60,8 +54,7 @@ - - + @@ -73,26 +66,23 @@ - - + - + - - + - - + @@ -100,8 +90,7 @@ - - + @@ -110,8 +99,7 @@ - - + @@ -119,8 +107,7 @@ - - + diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditor.form b/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditor.form index 0027858e1c42..43559ac2fa17 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditor.form +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditor.form @@ -1,6 +1,6 @@ - + @@ -10,8 +10,8 @@ - - + + @@ -28,7 +28,7 @@ - + diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditor.java b/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditor.java index cc0ce68d6fa2..0f24566e9a37 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditor.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditor.java @@ -24,6 +24,7 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.JDOMExternalizable; import com.intellij.openapi.util.Pair; import com.intellij.ui.ColoredListCellRenderer; +import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.ListScrollingUtil; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.containers.Convertor; @@ -145,7 +146,9 @@ class ConfigurationSettingsEditor extends CompositeSettingsEditor Date: Wed, 25 Jul 2012 14:22:53 +0400 Subject: [PATCH 48/51] RunConfigurable: "Share" option moved next to "Name" field --- .../ConfigurationSettingsEditorWrapper.form | 10 +---- .../ConfigurationSettingsEditorWrapper.java | 22 ---------- .../execution/impl/RunConfigurable.java | 2 +- .../impl/SingleConfigurationConfigurable.form | 35 +++++++++------ .../impl/SingleConfigurationConfigurable.java | 44 ++++++++++++++----- .../src/messages/ExecutionBundle.properties | 2 +- 6 files changed, 58 insertions(+), 57 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.form b/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.form index cdd4f53b2fd4..f0d3be5bd025 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.form +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.form @@ -1,6 +1,6 @@ - + @@ -28,14 +28,6 @@ - - - - - - - - diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.java b/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.java index 71aadd855153..a5db03805fb6 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.java @@ -32,8 +32,6 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.util.Collections; import java.util.List; @@ -45,14 +43,11 @@ public class ConfigurationSettingsEditorWrapper extends SettingsEditor CONFIGURATION_EDITOR_KEY = DataKey.create("ConfigurationSettingsEditor"); private JPanel myComponentPlace; - private JCheckBox myCbStoreProjectConfiguration; private JPanel myWholePanel; private JPanel myBeforeLaunchContainer; private BeforeRunStepsPanel myBeforeRunStepsPanel; - private boolean myStoreProjectConfiguration; - private final ConfigurationSettingsEditor myEditor; public ConfigurationSettingsEditorWrapper(final RunnerAndConfigurationSettings settings) { @@ -65,21 +60,9 @@ public class ConfigurationSettingsEditorWrapper extends SettingsEditor - + - + @@ -11,7 +11,7 @@ - + @@ -46,14 +46,14 @@ - + - - + + @@ -71,20 +71,27 @@
- - + + + + + + + + + + + + + + +
- - - - - -
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/SingleConfigurationConfigurable.java b/platform/lang-impl/src/com/intellij/execution/impl/SingleConfigurationConfigurable.java index 2d11fa530911..8a48bb1151ff 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/SingleConfigurationConfigurable.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/SingleConfigurationConfigurable.java @@ -49,18 +49,17 @@ public final class SingleConfigurationConfigurable Date: Wed, 25 Jul 2012 12:58:21 +0200 Subject: [PATCH 49/51] Test plus --- .../openapi/util/io/FileAttributesReadingTest.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java b/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java index 96bfb533002e..8fb880b226ab 100644 --- a/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java +++ b/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java @@ -49,6 +49,16 @@ public class FileAttributesReadingTest { } } + @Test + public void missingFile() throws Exception { + final File file = FileUtil.createTempFile(myTempDirectory, "test.", ".txt", false); + + final FileAttributes attributes = FileSystemUtil.getAttributes(file); + assertNull(attributes); + final String target = FileSystemUtil.resolveSymLink(file); + assertNull(target); + } + @Test public void regularFile() throws Exception { final File file = FileUtil.createTempFile(myTempDirectory, "test.", ".txt", true); From 93bc5abbb96b15e6f4135df337341b42db8f770d Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Wed, 27 Jun 2012 22:41:22 +0400 Subject: [PATCH 50/51] Wrapped stream in CoreLocalVirtualFile with buffered, since simple FileInputStream doesn't support mark/reset. --- .../com/intellij/openapi/vfs/local/CoreLocalVirtualFile.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/core-impl/src/com/intellij/openapi/vfs/local/CoreLocalVirtualFile.java b/platform/core-impl/src/com/intellij/openapi/vfs/local/CoreLocalVirtualFile.java index f2af0d18cf73..77287d053292 100644 --- a/platform/core-impl/src/com/intellij/openapi/vfs/local/CoreLocalVirtualFile.java +++ b/platform/core-impl/src/com/intellij/openapi/vfs/local/CoreLocalVirtualFile.java @@ -126,7 +126,7 @@ public class CoreLocalVirtualFile extends VirtualFile { @Override public InputStream getInputStream() throws IOException { - return VfsUtilCore.inputStreamSkippingBOM(new FileInputStream(myIoFile), this); + return VfsUtilCore.inputStreamSkippingBOM(new BufferedInputStream(new FileInputStream(myIoFile)), this); } @Override From 0a54cefed1acdaf9d560aab8e2b334c72ffd413d Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 25 Jul 2012 13:27:40 +0200 Subject: [PATCH 51/51] correctly calculate relative path for packages --- .../src/com/intellij/core/CoreJavaFileManager.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java b/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java index b6fcf28e23c9..41dda61bab85 100644 --- a/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java +++ b/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java @@ -75,8 +75,9 @@ public class CoreJavaFileManager implements JavaFileManager { final VirtualFile file = dir.getVirtualFile(); for (VirtualFile root : myClasspath) { if (VfsUtilCore.isAncestor(root, file, false)) { - final String relativePath = FileUtil.getRelativePath(root.getPath(), file.getPath(), '.'); - return new PsiPackageImpl(myPsiManager, relativePath); + String relativePath = FileUtil.getRelativePath(root.getPath(), file.getPath(), '/'); + if (relativePath == null) continue; + return new PsiPackageImpl(myPsiManager, relativePath.replace('/', '.')); } } return null;