Merge remote-tracking branch 'origin/master'

This commit is contained in:
Konstantin Bulenkov
2015-09-30 02:35:39 +02:00
92 changed files with 1431 additions and 1322 deletions
+1 -1
View File
@@ -258,7 +258,7 @@
<inspection_tool class="HardcodedActionUrl" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HardwiredNamespacePrefix" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="IOResource" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredTypesString" value="java.io.ByteArrayOutputStream,java.io.ByteArrayInputStream,java.io.StringBufferInputStream,java.io.CharArrayWriter,java.io.CharArrayReader,java.io.StringWriter,java.io.StringReader" />
<option name="ignoredTypesString" value="java.io.ByteArrayOutputStream,java.io.ByteArrayInputStream,java.io.StringBufferInputStream,java.io.CharArrayWriter,java.io.CharArrayReader,java.io.StringWriter,java.io.StringReader,io.netty.buffer.ByteBufOutputStream" />
<option name="insideTryAllowed" value="false" />
</inspection_tool>
<inspection_tool class="IfStatementWithIdenticalBranches" enabled="true" level="WARNING" enabled_by_default="true" />
+1 -1
View File
@@ -194,7 +194,7 @@ LD_LIBRARY_PATH="$IDE_BIN_HOME:$LD_LIBRARY_PATH" "$JAVA_BIN" \
EC=$?
test $EC -ne 88 && exit $EC
if [ -x "$HOME/.@@system_selector@@/restart/restarter.sh" ]; then
$HOME/.@@system_selector@@/restart/restarter.sh
"$HOME/.@@system_selector@@/restart/restarter.sh"
"$RM" -f "$HOME/.@@system_selector@@/restart/restarter.sh"
fi
exec "$0" "$@"
+9 -10
View File
@@ -16,8 +16,7 @@
<isset property="build" />
</condition>
<condition property="test.patterns" value="${testpatterns}"
else="org.jetbrains.android.*;com.android.tools.idea.*;com.google.gct.*;com.intellij.android.*">
<condition property="test.patterns" value="${testpatterns}" else="">
<isset property="testpatterns" />
</condition>
@@ -42,15 +41,15 @@
<sequential>
<java failonerror="true" jar="${project.home}/lib/ant/lib/ant-launcher.jar" fork="true">
<jvmarg line="-Xmx612m -XX:MaxPermSize=152m"/>
<jvmarg value="-Djna.nosys=true" />
<jvmarg value="-Dout=${out.dir}" />
<jvmarg value="-DbuildNumber=${build.number}" />
<jvmarg value="-Didea.test.patterns=${test.patterns}" />
<jvmarg value="-Dproduct=${product.name}" />
<sysproperty key="jna.nosys" value="true" />
<sysproperty key="out" value="${out.dir}" />
<sysproperty key="buildNumber" value="${build.number}" />
<sysproperty key="idea.test.patterns" value="${test.patterns}" />
<sysproperty key="product" value="${product.name}" />
<sysproperty key="java.awt.headless" value="true"/>
<arg line="&quot;-Dgant.script=@{script}&quot;"/>
<arg line="&quot;-Dteamcity.build.tempDir=${tmp.dir}&quot;"/>
<arg line="&quot;-Didea.test.group=ALL_EXCLUDE_DEFINED&quot;"/>
<sysproperty key="gant.script" value="@{script}"/>
<sysproperty key="teamcity.build.tempDir" value="${tmp.dir}"/>
<sysproperty key="idea.test.group" value="ALL_EXCLUDE_DEFINED"/>
<arg value="-f"/>
<arg value="${project.home}/build/gant.xml"/>
</java>
@@ -158,7 +158,8 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
myDebugProcessDispatcher.addListener(new DebugProcessAdapter() {
@Override
public void paused(SuspendContext suspendContext) {
myThreadBlockedMonitor.stopWatching(suspendContext.getThread());
myThreadBlockedMonitor.stopWatching(
suspendContext.getSuspendPolicy() != EventRequest.SUSPEND_ALL ? suspendContext.getThread() : null);
}
});
}
@@ -2143,6 +2144,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
// }
//}
@NotNull
public DebuggerContextImpl getDebuggerContext() {
return mySession.getContextManager().getContext();
}
@@ -24,6 +24,7 @@ import com.intellij.notification.Notification;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.util.Alarm;
import com.intellij.util.SingleAlarm;
@@ -42,6 +43,8 @@ import java.util.HashSet;
* @author egor
*/
public class ThreadBlockedMonitor {
private static final Logger LOG = Logger.getInstance(ThreadBlockedMonitor.class);
private final Collection<ThreadReferenceProxy> myWatchedThreads = new HashSet<ThreadReferenceProxy>();
private final SingleAlarm myAlarm;
@@ -71,14 +74,17 @@ public class ThreadBlockedMonitor {
if (thread != null) {
myWatchedThreads.remove(thread);
}
else {
myWatchedThreads.clear();
}
if (myWatchedThreads.isEmpty()) {
myAlarm.cancel();
}
}
private void onThreadBlocked(@NotNull final ThreadReference blockedThread,
@NotNull final ThreadReference blockingThread,
final DebugProcessImpl process) {
private static void onThreadBlocked(@NotNull final ThreadReference blockedThread,
@NotNull final ThreadReference blockingThread,
final DebugProcessImpl process) {
XDebugSessionImpl.NOTIFICATION_GROUP.createNotification(
DebuggerBundle.message("status.thread.blocked.by", blockedThread.name(), blockingThread.name()),
DebuggerBundle.message("status.thread.blocked.by.resume", blockingThread.name()),
@@ -101,6 +107,11 @@ public class ThreadBlockedMonitor {
}).notify(process.getProject());
}
private ThreadReference getCurrentThread() {
ThreadReferenceProxyImpl threadProxy = myProcess.getDebuggerContext().getThreadProxy();
return threadProxy != null ? threadProxy.getThreadReference() : null;
}
private void checkBlockingThread() {
myProcess.getManagerThread().schedule(new DebuggerCommandImpl() {
@Override
@@ -115,14 +126,16 @@ public class ThreadBlockedMonitor {
vmProxy.canGetCurrentContendedMonitor() ? thread.getThreadReference().currentContendedMonitor() : null;
if (waitedMonitor != null && vmProxy.canGetMonitorInfo()) {
ThreadReference blockingThread = waitedMonitor.owningThread();
if (blockingThread != null) {
if (blockingThread != null
&& blockingThread.suspendCount() > 1
&& getCurrentThread() != blockingThread) {
onThreadBlocked(thread.getThreadReference(), blockingThread, myProcess);
}
}
}
}
catch (IncompatibleThreadStateException e) {
e.printStackTrace();
LOG.info(e);
}
finally {
vmProxy.getVirtualMachine().resume();
@@ -306,7 +306,14 @@ public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy {
InvalidStackFrameException error = null;
for (int attempt = 0; attempt < 2; attempt++) {
try {
return getAllValues().get(localVariable.getVariable());
Map<LocalVariable, Value> values = getAllValues();
LocalVariable variable = localVariable.getVariable();
if (values.containsKey(variable)) {
return values.get(variable);
}
else { // try direct get
return getStackFrame().getValue(variable);
}
}
catch (InvalidStackFrameException e) {
error = e;
@@ -359,6 +366,14 @@ public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy {
catch (AbsentInformationException e) {
throw EvaluateExceptionUtil.createEvaluateException(e);
}
catch (InternalException e) {
// extra logging for IDEA-141270
if (e.errorCode() == 35 || e.errorCode() == 101) {
LOG.info(e);
myAllValues = Collections.emptyMap();
}
else throw e;
}
}
return myAllValues;
}
@@ -45,9 +45,15 @@ public class GraphicsObjectRenderer extends ToStringBasedRenderer implements Ful
Field surfaceField = ((ClassType)value.type()).fieldByName("surfaceData");
if (surfaceField == null) return null;
ObjectReference surfaceDataValue = (ObjectReference)value.getValue(surfaceField);
final Field bufImgField = ((ClassType)surfaceDataValue.type()).fieldByName("bufImg");
if (bufImgField == null) return null;
final Value bufImgValue = surfaceDataValue.getValue(bufImgField);
if (surfaceDataValue == null) return null;
Field imgField = ((ReferenceType)surfaceDataValue.type()).fieldByName("bufImg"); // BufImgSurfaceData
if (imgField == null) {
imgField = ((ReferenceType)surfaceDataValue.type()).fieldByName("offscreenImage"); // CGLSurfaceData
}
if (imgField == null) return null;
final Value bufImgValue = surfaceDataValue.getValue(imgField);
Type type = bufImgValue.type();
if (!(type instanceof ReferenceType) || !DebuggerUtils.instanceOf(type, "java.awt.Image")) {
return null;
@@ -16,10 +16,12 @@
package com.intellij.debugger.ui.tree.render;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.FullValueEvaluatorProvider;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContext;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
import com.intellij.debugger.impl.DebuggerUtilsImpl;
import com.intellij.debugger.settings.NodeRendererSettings;
import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl;
@@ -42,15 +44,27 @@ class IconObjectRenderer extends ToStringBasedRenderer implements FullValueEvalu
}
@Override
public Icon calcValueIcon(ValueDescriptor descriptor, EvaluationContext evaluationContext, DescriptorLabelListener listener)
public Icon calcValueIcon(final ValueDescriptor descriptor, final EvaluationContext evaluationContext, final DescriptorLabelListener listener)
throws EvaluateException {
String getterName = AllIcons.Debugger.Value.getIconHeight() <= 16 ? "iconToBytesPreviewNormal" : "iconToBytesPreviewRetina";
if (!Registry.is("debugger.auto.fetch.icons") || DebuggerUtilsImpl.isRemote(evaluationContext.getDebugProcess())) {
return null; // do not auto load icon for remote
}
else {
return ImageObjectRenderer.getIcon(evaluationContext, descriptor.getValue(), getterName);
}
EvaluationContextImpl evalContext = ((EvaluationContextImpl)evaluationContext);
DebugProcessImpl debugProcess = evalContext.getDebugProcess();
if (!Registry.is("debugger.auto.fetch.icons") || DebuggerUtilsImpl.isRemote(debugProcess)) return null;
debugProcess.getManagerThread().schedule(new SuspendContextCommandImpl(evalContext.getSuspendContext()) {
@Override
public Priority getPriority() {
return Priority.LOW;
}
@Override
public void contextAction() throws Exception {
String getterName = AllIcons.Debugger.Value.getIconHeight() <= 16 ? "iconToBytesPreviewNormal" : "iconToBytesPreviewRetina";
descriptor.setValueIcon(ImageObjectRenderer.getIcon(evaluationContext, descriptor.getValue(), getterName));
listener.labelChanged();
}
});
return null;
}
@Nullable
@@ -17,6 +17,8 @@ package com.intellij.openapi.roots.ui.configuration.projectRoot;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.DumbModePermission;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.impl.libraries.LibraryEx;
import com.intellij.openapi.roots.libraries.Library;
@@ -56,18 +58,24 @@ public class ChangeLibraryLevelAction extends ChangeLibraryLevelActionBase {
final LibraryProjectStructureElement libraryElement = (LibraryProjectStructureElement)selectedElement;
final LibraryEx oldLibrary = (LibraryEx)context.getLibrary(libraryElement.getLibrary().getName(), mySourceConfigurable.getLevel());
LOG.assertTrue(oldLibrary != null);
final Library newLibrary = doCopy(oldLibrary);
if (newLibrary == null) return;
final Collection<ProjectStructureElementUsage> usages = context.getDaemonAnalyzer().getUsages(libraryElement);
for (ProjectStructureElementUsage usage : usages) {
usage.replaceElement(new LibraryProjectStructureElement(context, newLibrary));
}
DumbService.allowStartingDumbModeInside(DumbModePermission.MAY_START_BACKGROUND, new Runnable() {
@Override
public void run() {
final Library newLibrary = doCopy(oldLibrary);
if (newLibrary == null) return;
if (!myCopy) {
mySourceConfigurable.removeLibrary(libraryElement);
}
ProjectStructureConfigurable.getInstance(myProject).selectProjectOrGlobalLibrary(newLibrary, true);
final Collection<ProjectStructureElementUsage> usages = context.getDaemonAnalyzer().getUsages(libraryElement);
for (ProjectStructureElementUsage usage : usages) {
usage.replaceElement(new LibraryProjectStructureElement(context, newLibrary));
}
if (!myCopy) {
mySourceConfigurable.removeLibrary(libraryElement);
}
ProjectStructureConfigurable.getInstance(myProject).selectProjectOrGlobalLibrary(newLibrary, true);
}
});
}
@Override
@@ -26,6 +26,7 @@ import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -413,8 +414,15 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp
}
final PsiType qualifierExpressionType = qualifierExpression.getType();
return qualifierExpressionType != null && !TypeConversionUtil.containsWildcards(qualifierExpressionType)
? qualifierExpressionType.getCanonicalText() : getClassReferenceName(containingClass);
if (qualifierExpressionType != null && !TypeConversionUtil.containsWildcards(qualifierExpressionType)) {
try {
final String canonicalText = qualifierExpressionType.getCanonicalText();
JavaPsiFacade.getElementFactory(containingClass.getProject()).createExpressionFromText(canonicalText + "::foo", qualifierExpression);
return canonicalText;
}
catch (IncorrectOperationException ignore){}
}
return getClassReferenceName(containingClass);
}
private static String getClassReferenceName(PsiClass containingClass) {
@@ -1513,12 +1513,12 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
}
static List<MethodContract> getMethodContracts(@NotNull final PsiMethod method) {
final PsiAnnotation contractAnno = findContractAnnotation(method);
if (contractAnno != null) {
return CachedValuesManager.getCachedValue(contractAnno, new CachedValueProvider<List<MethodContract>>() {
@Nullable
@Override
public Result<List<MethodContract>> compute() {
return CachedValuesManager.getCachedValue(method, new CachedValueProvider<List<MethodContract>>() {
@Nullable
@Override
public Result<List<MethodContract>> compute() {
final PsiAnnotation contractAnno = findContractAnnotation(method);
if (contractAnno != null) {
String text = AnnotationUtil.getStringAttributeValue(contractAnno, null);
if (text != null) {
try {
@@ -1534,12 +1534,10 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
catch (Exception ignored) {
}
}
return Result.create(Collections.<MethodContract>emptyList(), contractAnno, method, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
});
}
return Collections.emptyList();
return Result.create(Collections.<MethodContract>emptyList(), method, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
});
}
@Nullable
@@ -315,7 +315,7 @@ public class JavaTargetElementEvaluator extends TargetElementEvaluatorEx2 implem
if (referenceExpression != null && element instanceof PsiMethod) {
final PsiClass[] memberClass = getMemberClass(referenceExpression, element);
if (memberClass != null && memberClass.length == 1) {
return CachedValuesManager.getCachedValue(referenceExpression, new CachedValueProvider<SearchScope>() {
return CachedValuesManager.getCachedValue(memberClass[0], new CachedValueProvider<SearchScope>() {
@Nullable
@Override
public Result<SearchScope> compute() {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -139,11 +139,8 @@ public class ClassInnerStuffCache {
@Nullable
@Override
public Result<PsiMethod> compute() {
PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory();
String text = "public static " + myClass.getName() + "[] values() { }";
PsiMethod physicalMethod = factory.createMethodFromText(text, myClass);
PsiMethod method = new LightMethod(myClass.getManager(), physicalMethod, myClass);
return new Result<PsiMethod>(method, OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker);
return new Result<PsiMethod>(getSyntheticMethod(text), OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker);
}
});
}
@@ -154,11 +151,8 @@ public class ClassInnerStuffCache {
@Nullable
@Override
public Result<PsiMethod> compute() {
PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory();
String text = "public static " + myClass.getName() + " valueOf(java.lang.String name) throws java.lang.IllegalArgumentException { }";
PsiMethod physicalMethod = factory.createMethodFromText(text, myClass);
PsiMethod method = new LightMethod(myClass.getManager(), physicalMethod, myClass);
return new Result<PsiMethod>(method, OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker);
return new Result<PsiMethod>(getSyntheticMethod(text), OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker);
}
});
}
@@ -236,6 +230,12 @@ public class ClassInnerStuffCache {
return cachedInners;
}
private PsiMethod getSyntheticMethod(String text) {
PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory();
PsiMethod method = factory.createMethodFromText(text, myClass);
return new LightMethod(myClass.getManager(), method, myClass);
}
public void dropCaches() {
myTracker.incModificationCount();
}
@@ -0,0 +1,15 @@
// "Replace lambda with method reference" "true"
import java.util.function.Function;
class Test<T> {
class Bar {
void f( ){
Function<Test<T>.Bar, String> r = Bar::foo;
}
private String foo() {}
}
}
@@ -0,0 +1,15 @@
// "Replace lambda with method reference" "true"
import java.util.function.Function;
class Test<T> {
class Bar {
void f( ){
Function<Test<T>.Bar, String> r = (Test<T>.Bar t) -> t.fo<caret>o();
}
private String foo() {}
}
}
@@ -148,11 +148,11 @@ public class FindInEditorMultiCaretTest extends LightPlatformCodeInsightFixtureT
}
private void nextOccurrence() {
executeHeaderAction(EditorSearchSession.createNextOccurrenceAction());
executeHeaderAction(new NextOccurrenceAction());
}
private void prevOccurrence() {
executeHeaderAction(EditorSearchSession.createPrevOccurrenceAction());
executeHeaderAction(new PrevOccurrenceAction());
}
private void addOccurrence() {
@@ -22,8 +22,6 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.packageDependencies.DependencyValidationManager;
import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
import com.intellij.util.ArrayUtil;
@@ -104,12 +102,7 @@ public abstract class DefaultProjectProfileManager extends ProjectProfileManager
final Profile projectProfile = myProfiles.get(profile);
if (projectProfile != null) {
Element profileElement = new Element(PROFILE);
try {
projectProfile.writeExternal(profileElement);
}
catch (WriteExternalException e) {
LOG.error(e);
}
projectProfile.writeExternal(profileElement);
boolean hasSmthToSave = sortedProfiles.length > 1 || isCustomProfileUsed();
if (!hasSmthToSave) {
for (Element child : profileElement.getChildren()) {
@@ -141,16 +134,12 @@ public abstract class DefaultProjectProfileManager extends ProjectProfileManager
for (Element o : state.getChildren(PROFILE)) {
Profile profile = myApplicationProfileManager.createProfile();
profile.setProfileManager(this);
try {
profile.readExternal(o);
}
catch (InvalidDataException e) {
LOG.error(e);
}
profile.readExternal(o);
profile.setProjectLevel(true);
if (profileKeys.contains(profile.getName())) {
updateProfile(profile);
} else {
}
else {
myProfiles.put(profile.getName(), profile);
}
}
@@ -252,10 +241,6 @@ public abstract class DefaultProjectProfileManager extends ProjectProfileManager
});
}
public void removeProfilesListener(@NotNull ProfileChangeAdapter profilesListener) {
myProfilesListener.remove(profilesListener);
}
public static class ProfileStateSplitter extends MainConfigurationStateSplitter {
@NotNull
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,14 +16,14 @@
package com.intellij.profile;
import com.intellij.openapi.options.Scheme;
import com.intellij.openapi.util.JDOMExternalizable;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
/**
* User: anna
* Date: 20-Nov-2005
*/
public interface Profile extends JDOMExternalizable, Comparable, Scheme {
public interface Profile extends Comparable, Scheme {
void copyFrom(@NotNull Profile profile);
void setLocal(boolean isLocal);
@@ -48,4 +48,8 @@ public interface Profile extends JDOMExternalizable, Comparable, Scheme {
@NotNull
ProfileManager getProfileManager();
void readExternal(Element element);
void writeExternal(Element element);
}
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInspection.ex;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
@@ -27,7 +26,6 @@ import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.options.ExternalInfo;
import com.intellij.openapi.options.ExternalizableScheme;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
@@ -253,7 +251,7 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
}
@Override
public void readExternal(@NotNull Element element) throws InvalidDataException {
public void readExternal(@NotNull Element element) {
super.readExternal(element);
final String version = element.getAttributeValue(VERSION_TAG);
@@ -868,12 +866,6 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
}
}
@Override
@Nullable
public ExternalInfo getExternalInfo() {
return null;
}
@NotNull
public List<ScopeToolState> getAllTools(Project project) {
initInspectionTools(project);
@@ -142,7 +142,7 @@ public class ToolsImpl implements Tools {
return result;
}
public void writeExternal(Element inspectionElement) throws WriteExternalException {
public void writeExternal(@NotNull Element inspectionElement) throws WriteExternalException {
if (myTools != null) {
for (ScopeToolState state : myTools) {
final Element scopeElement = new Element("scope");
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,10 +15,7 @@
*/
package com.intellij.profile;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.util.xmlb.SmartSerializer;
import com.intellij.util.xmlb.annotations.OptionTag;
import com.intellij.util.xmlb.annotations.Transient;
@@ -30,8 +27,6 @@ import org.jetbrains.annotations.NotNull;
* Date: 01-Dec-2005
*/
public abstract class ProfileEx implements Profile {
private static final Logger LOG = Logger.getInstance(ProfileEx.class);
public static final String SCOPE = "scope";
public static final String NAME = "name";
@@ -68,17 +63,9 @@ public abstract class ProfileEx implements Profile {
@Override
public void copyFrom(@NotNull Profile profile) {
try {
Element config = new Element("config");
profile.writeExternal(config);
readExternal(config);
}
catch (WriteExternalException e) {
LOG.error(e);
}
catch (InvalidDataException e) {
LOG.error(e);
}
Element config = new Element("config");
profile.writeExternal(config);
readExternal(config);
}
@Override
@@ -121,7 +108,7 @@ public abstract class ProfileEx implements Profile {
}
@Override
public void readExternal(Element element) throws InvalidDataException {
public void readExternal(Element element) {
mySerializer.readExternal(this, element);
}
@@ -130,7 +117,7 @@ public abstract class ProfileEx implements Profile {
}
@Override
public void writeExternal(Element element) throws WriteExternalException {
public void writeExternal(Element element) {
serializeInto(element, true);
}
@@ -15,6 +15,8 @@
*/
package com.intellij.configurationStore
import com.intellij.ide.actions.ExportableItem
import com.intellij.ide.actions.getExportableComponentsMap
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.*
import com.intellij.openapi.vfs.CharsetToolkit
@@ -33,6 +35,7 @@ import org.junit.ClassRule
import org.junit.Rule
import org.junit.Test
import java.io.ByteArrayInputStream
import java.io.File
import java.io.InputStream
import java.nio.file.Path
import java.nio.file.Paths
@@ -109,6 +112,17 @@ internal class ApplicationStoreTest {
assertThat(oldFile).doesNotExist()
}
@Test fun `export settings`() {
val storageManager = ApplicationManager.getApplication().stateStore.stateStorageManager
val optionsPath = storageManager.expandMacros(StoragePathMacros.APP_CONFIG)
val rootConfigPath = storageManager.expandMacros(ROOT_CONFIG)
val map = getExportableComponentsMap(false, true, storageManager)
assertThat(map.size()).isNotEqualTo(0)
val key = File(optionsPath, "filetypes.xml")
assertThat(map.get(key)).containsExactly(ExportableItem(listOf(key, File(rootConfigPath, "filetypes")), "File types", RoamingType.DEFAULT))
}
private fun createComponentData(foo: String) = """<component name="A" foo="$foo" />"""
@Test fun `remove data from deprecated storage if another component data exists`() {
@@ -40,7 +40,7 @@ private fun StateStorage.ExternalizationSession.save() {
private fun StateStorageBase<*>.setStateAndSave(componentName: String, state: String?) {
var externalizationSession = startExternalization()!!
externalizationSession.setState(null, componentName, if (state == null) Element("state") else JDOMUtil.load(state.reader))
externalizationSession.setState(null, componentName, if (state == null) Element("state") else JDOMUtil.load(state.reader()))
externalizationSession.save()
}
@@ -39,7 +39,7 @@ class ModuleStoreTest {
}
}
private fun VirtualFile.loadModule() = runWriteAction { ModuleManager.getInstance(projectRule.project).loadModule(getPath()) }
private fun VirtualFile.loadModule() = runWriteAction { ModuleManager.getInstance(projectRule.project).loadModule(path) }
fun Path.createModule() = projectRule.createModule(this)
}
@@ -51,8 +51,7 @@ class ModuleStoreTest {
@Test fun `set option`() {
val moduleFile = runWriteAction {
VfsTestUtil.createFile(tempDirManager.newVirtualDirectory("module"), "test.iml", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<module type=\"JAVA_MODULE\" foo=\"bar\" version=\"4\" />")
VfsTestUtil.createFile(tempDirManager.newVirtualDirectory("module"), "test.iml", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"JAVA_MODULE\" foo=\"bar\" version=\"4\" />")
}
moduleFile.loadModule().useAndDispose {
@@ -117,7 +116,7 @@ class ModuleStoreTest {
assertThat(moduleFile).isRegularFile()
val virtualFile = LocalFileSystem.getInstance().findFileByPath(modulePath)!!
val newData = moduleFile.readText().replace("<content url=\"file://\$MODULE_DIR$/${name}\" />\n", "").toByteArray()
val newData = moduleFile.readText().replace("<content url=\"file://\$MODULE_DIR$/$name\" />\n", "").toByteArray()
runWriteAction {
virtualFile.setBinaryContent(newData)
}
@@ -25,6 +25,7 @@ import com.intellij.openapi.project.impl.ProjectManagerImpl
import com.intellij.openapi.util.io.systemIndependentPath
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.*
import com.intellij.util.PathUtil
import org.assertj.core.api.Assertions.assertThat
import org.intellij.lang.annotations.Language
import org.junit.ClassRule
@@ -64,7 +65,7 @@ private fun createOrLoadProject(tempDirManager: TemporaryDirectory, task: (Proje
}
}
class ProjectStoreTest {
internal class ProjectStoreTest {
companion object {
@ClassRule val projectRule = ProjectRule()
}
@@ -76,12 +77,7 @@ class ProjectStoreTest {
@Language("XML")
private val iprFileContent =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project version=\"4\">\n" +
" <component name=\"AATestComponent\">\n" +
" <option name=\"value\" value=\"customValue\" />\n" +
" </component>\n" +
"</project>"
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"AATestComponent\">\n <option name=\"value\" value=\"customValue\" />\n </component>\n</project>"
@State(name = "AATestComponent", storages = arrayOf(Storage(file = StoragePathMacros.PROJECT_FILE)))
private class TestComponent : PersistentStateComponent<TestState> {
@@ -103,6 +99,8 @@ class ProjectStoreTest {
}) { project ->
val testComponent = test(project)
assertThat(project.basePath).isEqualTo(PathUtil.getParentPath((PathUtil.getParentPath(project.projectFilePath!!))))
// test reload on external change
val file = File(project.stateStore.stateStorageManager.expandMacros(StoragePathMacros.PROJECT_FILE))
file.writeText(file.readText().replace("""<option name="value" value="foo" />""", """<option name="value" value="newValue" />"""))
@@ -117,6 +115,8 @@ class ProjectStoreTest {
@Test fun fileBasedStorage() {
loadAndUseProject(tempDirManager, { it.writeChild("test${ProjectFileType.DOT_DEFAULT_EXTENSION}", iprFileContent).path }) { project ->
test(project)
assertThat(project.basePath).isEqualTo(PathUtil.getParentPath(project.projectFilePath!!))
}
}
@@ -375,9 +375,6 @@ data class TestScheme(@field:Attribute private var name: String = "", @field:Att
override @Transient fun setName(newName: String) {
name = newName
}
@Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")
override fun getExternalInfo() = null
}
open class TestSchemesProcessor : BaseSchemeProcessor<TestScheme>() {
@@ -16,13 +16,7 @@
package com.intellij.openapi.options;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface ExternalizableScheme extends Scheme {
@SuppressWarnings({"unused", "deprecation"})
@Nullable
@Deprecated
ExternalInfo getExternalInfo();
void setName(@NotNull String newName);
}
@@ -16,17 +16,10 @@
package com.intellij.openapi.options;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class ExternalizableSchemeAdapter implements ExternalizableScheme {
protected String myName;
@Override
@Nullable
public final ExternalInfo getExternalInfo() {
return null;
}
@Override
@NotNull
public final String getName() {
@@ -339,6 +339,19 @@ public abstract class PsiElementPattern<T extends PsiElement,Self extends PsiEle
});
}
public Self withLastChildSkipping(@NotNull final ElementPattern skip, @NotNull final ElementPattern pattern) {
return with(new PatternCondition<T>("withLastChildSkipping") {
@Override
public boolean accepts(@NotNull T t, ProcessingContext context) {
PsiElement last = t.getLastChild();
while (last != null && skip.accepts(last)) {
last = last.getPrevSibling();
}
return pattern.accepts(last);
}
});
}
public static class Capture<T extends PsiElement> extends PsiElementPattern<T,Capture<T>> {
protected Capture(final Class<T> aClass) {
@@ -0,0 +1,66 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.diff.actions;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.EmptyAction;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
public class ProxyUndoRedoAction extends DumbAwareAction {
@NotNull private final UndoManager myUndoManager;
@NotNull private final TextEditor myEditor;
private final boolean myUndo;
private ProxyUndoRedoAction(@NotNull UndoManager manager, @NotNull TextEditor editor, boolean undo) {
myUndoManager = manager;
myEditor = editor;
myUndo = undo;
}
public static void register(@Nullable Project project, @NotNull Editor editor, @NotNull JComponent component) {
UndoManager undoManager = project != null ? UndoManager.getInstance(project) : UndoManager.getGlobalInstance();
TextEditor textEditor = TextEditorProvider.getInstance().getTextEditor(editor);
if (undoManager != null) {
EmptyAction.setupAction(new ProxyUndoRedoAction(undoManager, textEditor, true), IdeActions.ACTION_UNDO, component);
EmptyAction.setupAction(new ProxyUndoRedoAction(undoManager, textEditor, false), IdeActions.ACTION_REDO, component);
}
}
@Override
public void update(AnActionEvent e) {
e.getPresentation().setEnabled(myUndo ? myUndoManager.isUndoAvailable(myEditor) : myUndoManager.isRedoAvailable(myEditor));
}
@Override
public void actionPerformed(AnActionEvent e) {
if (myUndo) {
myUndoManager.undo(myEditor);
}
else {
myUndoManager.redo(myEditor);
}
}
}
@@ -17,6 +17,7 @@ package com.intellij.diff.merge;
import com.intellij.diff.DiffContext;
import com.intellij.diff.FrameDiffTool;
import com.intellij.diff.actions.ProxyUndoRedoAction;
import com.intellij.diff.comparison.ByLine;
import com.intellij.diff.comparison.ComparisonMergeUtil;
import com.intellij.diff.comparison.ComparisonPolicy;
@@ -44,8 +45,6 @@ import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
@@ -225,10 +224,7 @@ public class TextMergeTool implements MergeTool {
DiffUtil.registerAction(new IgnoreSelectedChangesAction(Side.LEFT, true), myPanel);
DiffUtil.registerAction(new IgnoreSelectedChangesAction(Side.RIGHT, true), myPanel);
if (myUndoManager != null) {
new UndoRedoAction(true).register();
new UndoRedoAction(false).register();
}
ProxyUndoRedoAction.register(getProject(), getEditor(ThreeSide.BASE), myContentPanel);
}
@Override
@@ -1161,43 +1157,6 @@ public class TextMergeTool implements MergeTool {
// Helpers
//
private class UndoRedoAction extends DumbAwareAction {
private final boolean myUndo;
public UndoRedoAction(boolean undo) {
myUndo = undo;
}
public void register() {
EmptyAction.setupAction(this, myUndo ? IdeActions.ACTION_UNDO : IdeActions.ACTION_REDO, myContentPanel);
}
@Override
public void update(AnActionEvent e) {
assert myUndoManager != null;
TextEditor textEditor = getTextEditor();
e.getPresentation().setEnabled(myUndo ? myUndoManager.isUndoAvailable(textEditor) : myUndoManager.isRedoAvailable(textEditor));
}
@Override
public void actionPerformed(AnActionEvent e) {
assert myUndoManager != null;
TextEditor textEditor = getTextEditor();
if (myUndo) {
myUndoManager.undo(textEditor);
}
else {
myUndoManager.redo(textEditor);
}
}
@NotNull
private TextEditor getTextEditor() {
EditorEx editor = getEditor(ThreeSide.BASE);
return TextEditorProvider.getInstance().getTextEditor(editor);
}
}
private class MyDividerPaintable implements DiffDividerDrawUtil.DividerPaintable {
@NotNull private final Side mySide;
@@ -16,6 +16,7 @@
package com.intellij.diff.tools.util.side;
import com.intellij.diff.DiffContext;
import com.intellij.diff.actions.ProxyUndoRedoAction;
import com.intellij.diff.actions.impl.FocusOppositePaneAction;
import com.intellij.diff.actions.impl.OpenInEditorWithMouseAction;
import com.intellij.diff.actions.impl.SetEditorSettingsAction;
@@ -80,6 +81,12 @@ public abstract class TwosideTextDiffViewer extends TwosideDiffViewer<TextEditor
myEditableEditors = TextDiffViewerUtil.getEditableEditors(getEditors());
TextDiffViewerUtil.checkDifferentDocuments(myRequest);
boolean editable1 = DiffUtil.canMakeWritable(getContent1().getDocument());
boolean editable2 = DiffUtil.canMakeWritable(getContent2().getDocument());
if (editable1 ^ editable2) {
ProxyUndoRedoAction.register(getProject(), editable1 ? getEditor1() : getEditor2(), myPanel);
}
}
@Override
@@ -19,7 +19,6 @@ import com.intellij.openapi.editor.colors.ColorKey;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.options.ExternalInfo;
import com.intellij.openapi.options.ExternalizableScheme;
import com.intellij.openapi.util.Comparing;
import org.jetbrains.annotations.Nullable;
@@ -83,10 +82,4 @@ public class EditorColorsSchemeImpl extends AbstractColorsScheme implements Exte
newScheme.setName(getName());
return newScheme;
}
@Override
@Nullable
public ExternalInfo getExternalInfo() {
return null;
}
}
@@ -115,10 +115,10 @@ public class EnvironmentVariablesData {
parent.addContent(envsElement);
}
public void configureCommandLine(@NotNull GeneralCommandLine commandLine, boolean shellParentEnvs) {
public void configureCommandLine(@NotNull GeneralCommandLine commandLine, boolean consoleParentEnvs) {
if (myPassParentEnvs) {
commandLine.withParentEnvironmentType(shellParentEnvs ? GeneralCommandLine.ParentEnvironmentType.CONSOLE
: GeneralCommandLine.ParentEnvironmentType.SYSTEM);
commandLine.withParentEnvironmentType(consoleParentEnvs ? GeneralCommandLine.ParentEnvironmentType.CONSOLE
: GeneralCommandLine.ParentEnvironmentType.SYSTEM);
}
else {
commandLine.withParentEnvironmentType(GeneralCommandLine.ParentEnvironmentType.NONE);
@@ -51,7 +51,8 @@ import java.util.regex.Pattern;
/**
* @author max, andrey.zaytsev
*/
public class EditorSearchSession implements DataProvider,
public class EditorSearchSession implements SearchSession,
DataProvider,
SelectionListener,
SearchResults.SearchResultsListener,
SearchReplaceComponent.Listener {
@@ -87,8 +88,8 @@ public class EditorSearchSession implements DataProvider,
myComponent = SearchReplaceComponent
.buildFor(project, myEditor.getContentComponent())
.addPrimarySearchActions(createPrevOccurrenceAction(),
createNextOccurrenceAction(),
.addPrimarySearchActions(new PrevOccurrenceAction(),
new NextOccurrenceAction(),
new FindAllAction(),
new Separator(),
new AddOccurrenceAction(),
@@ -111,8 +112,8 @@ public class EditorSearchSession implements DataProvider,
new ExcludeAction())
.addExtraReplaceAction(new TogglePreserveCaseAction(),
new ToggleSelectionOnlyAction())
.addReplaceFieldActions(createPrevOccurrenceAction(),
createNextOccurrenceAction())
.addReplaceFieldActions(new PrevOccurrenceAction(),
new NextOccurrenceAction())
.withDataProvider(this)
.withCloseAction(new Runnable() {
@Override
@@ -160,7 +161,7 @@ public class EditorSearchSession implements DataProvider,
}
updateUIWithFindModel();
updateResults(true);
syncFindModels(FindManager.getInstance(getProject()).getFindInFileModel(), myFindModel);
FindUtil.updateFindInFileModel(getProject(), myFindModel);
}
});
@@ -194,6 +195,7 @@ public class EditorSearchSession implements DataProvider,
}
@NotNull
@Override
public SearchReplaceComponent getComponent() {
return myComponent;
}
@@ -219,6 +221,9 @@ public class EditorSearchSession implements DataProvider,
@Override
@Nullable
public Object getData(@NonNls final String dataId) {
if (SearchSession.KEY.is(dataId)) {
return this;
}
if (SESSION_KEY.is(dataId)) {
return this;
}
@@ -289,18 +294,27 @@ public class EditorSearchSession implements DataProvider,
myFindModel.setMultiline(myComponent.isMultiline());
}
@NotNull
@Override
public FindModel getFindModel() {
return myFindModel;
}
private static void syncFindModels(FindModel to, FindModel from) {
to.setCaseSensitive(from.isCaseSensitive());
to.setWholeWordsOnly(from.isWholeWordsOnly());
to.setRegularExpressions(from.isRegularExpressions());
to.setSearchContext(from.getSearchContext());
if (from.isReplaceState()) {
to.setPreserveCase(from.isPreserveCase());
}
@Override
public boolean hasMatches() {
return mySearchResults != null && mySearchResults.hasMatches();
}
@Override
public void searchForward() {
moveCursor(SearchResults.Direction.DOWN);
addTextToRecent(myComponent.getSearchTextComponent());
}
@Override
public void searchBackward() {
moveCursor(SearchResults.Direction.UP);
addTextToRecent(myComponent.getSearchTextComponent());
}
public void updateUIWithFindModel() {
@@ -332,16 +346,6 @@ public class EditorSearchSession implements DataProvider,
}
}
public void searchBackward() {
moveCursor(SearchResults.Direction.UP);
addTextToRecent(myComponent.getSearchTextComponent());
}
public void searchForward() {
moveCursor(SearchResults.Direction.DOWN);
addTextToRecent(myComponent.getSearchTextComponent());
}
public void addTextToRecent(JTextComponent textField) {
myComponent.addTextToRecent(textField);
}
@@ -355,6 +359,7 @@ public class EditorSearchSession implements DataProvider,
myLivePreviewController.moveCursor(direction);
}
@Override
public void close() {
IdeFocusManager.getInstance(getProject()).requestFocus(myEditor.getContentComponent(), false);
@@ -388,7 +393,7 @@ public class EditorSearchSession implements DataProvider,
myComponent.setNotFoundBackground();
myClickToHighlightLabel.setVisible(false);
mySearchResults.clear();
myComponent.setStatusText("Incorrect regular expression");
myComponent.setStatusText(INCORRECT_REGEX_MESSAGE);
return;
}
}
@@ -430,10 +435,6 @@ public class EditorSearchSession implements DataProvider,
myFindModel.setStringToFind(text);
}
public boolean hasMatches() {
return mySearchResults != null && mySearchResults.hasMatches();
}
public void selectAllOccurrences() {
FindUtil.selectSearchResultsInEditor(myEditor, mySearchResults.getOccurrences().iterator(), -1);
}
@@ -451,27 +452,6 @@ public class EditorSearchSession implements DataProvider,
}
@NotNull
static NextOccurrenceAction createNextOccurrenceAction() {
return new NextOccurrenceAction(new PrevNextActionHandler() {
@Override
public void actionPerformed(AnActionEvent e) {
e.getRequiredData(SESSION_KEY).searchForward();
}
});
}
@NotNull
static PrevOccurrenceAction createPrevOccurrenceAction() {
return new PrevOccurrenceAction(new PrevNextActionHandler() {
@Override
public void actionPerformed(AnActionEvent e) {
e.getRequiredData(SESSION_KEY).searchBackward();
}
});
}
private static abstract class ButtonAction extends DumbAwareAction implements CustomComponentAction, ActionListener {
private final String myTitle;
private final char myMnemonic;
@@ -565,12 +545,4 @@ public class EditorSearchSession implements DataProvider,
moveCursor(SearchResults.Direction.DOWN);
}
}
private static abstract class PrevNextActionHandler implements PrevNextOccurrenceAction.Handler {
@Override
public void update(AnActionEvent e) {
EditorSearchSession search = e.getData(SESSION_KEY);
e.getPresentation().setEnabled(search != null && search.hasMatches());
}
}
}
@@ -148,6 +148,17 @@ public class FindUtil {
model.setPromptOnReplace(false);
}
public static void updateFindInFileModel(@Nullable Project project, @NotNull FindModel with) {
FindModel model = FindManager.getInstance(project).getFindInFileModel();
model.setCaseSensitive(with.isCaseSensitive());
model.setWholeWordsOnly(with.isWholeWordsOnly());
model.setRegularExpressions(with.isRegularExpressions());
model.setSearchContext(with.getSearchContext());
if (with.isReplaceState()) {
model.setPreserveCase(with.isPreserveCase());
}
}
private enum Direction {
UP, DOWN
}
@@ -57,9 +57,6 @@ import java.util.EventListener;
import java.util.List;
public class SearchReplaceComponent extends EditorHeaderComponent implements DataProvider {
public static final DataKey<SearchReplaceComponent> COMPONENT_KEY = DataKey.create("search-replace-component");
public static final DataKey<String> STATUS_TEXT_KEY = DataKey.create("search-replace-status-text");
private final EventDispatcher<Listener> myEventDispatcher = EventDispatcher.create(Listener.class);
private final MyTextComponentWrapper mySearchFieldWrapper;
@@ -90,7 +87,7 @@ public class SearchReplaceComponent extends EditorHeaderComponent implements Dat
private final DataProvider myDataProviderDelegate;
private boolean myMultilineMode;
private String myStatusText;
private String myStatusText = "";
@NotNull
public static Builder buildFor(@Nullable Project project, @NotNull JComponent component) {
@@ -225,6 +222,11 @@ public class SearchReplaceComponent extends EditorHeaderComponent implements Dat
myStatusText = status;
}
@NotNull
public String getStatusText() {
return myStatusText;
}
public void replace() {
if (myReplaceAction != null) {
myReplaceAction.run();
@@ -258,12 +260,6 @@ public class SearchReplaceComponent extends EditorHeaderComponent implements Dat
@Nullable
@Override
public Object getData(@NonNls String dataId) {
if (STATUS_TEXT_KEY.is(dataId)) {
return myStatusText;
}
if (COMPONENT_KEY.is(dataId)) {
return this;
}
if (SpeedSearchSupply.SPEED_SEARCH_CURRENT_QUERY.is(dataId)) {
return mySearchTextComponent.getText();
}
@@ -0,0 +1,38 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.find;
import com.intellij.openapi.actionSystem.DataKey;
import org.jetbrains.annotations.NotNull;
public interface SearchSession {
DataKey<SearchSession> KEY = DataKey.create("search.replace.session");
String INCORRECT_REGEX_MESSAGE = "Incorrect regular expression";
@NotNull
FindModel getFindModel();
@NotNull
SearchReplaceComponent getComponent();
boolean hasMatches();
void searchForward();
void searchBackward();
void close();
}
@@ -15,8 +15,8 @@
*/
package com.intellij.find.editorHeaderActions;
import com.intellij.find.EditorSearchSession;
import com.intellij.find.FindModel;
import com.intellij.find.SearchSession;
import org.jetbrains.annotations.NotNull;
public class EditorHeaderSetSearchContextAction extends EditorHeaderToggleAction {
@@ -29,12 +29,12 @@ public class EditorHeaderSetSearchContextAction extends EditorHeaderToggleAction
}
@Override
protected boolean isSelected(@NotNull EditorSearchSession session) {
protected boolean isSelected(@NotNull SearchSession session) {
return session.getFindModel().getSearchContext() == myContext;
}
@Override
protected void setSelected(@NotNull EditorSearchSession session, boolean selected) {
protected void setSelected(@NotNull SearchSession session, boolean selected) {
session.getFindModel().setSearchContext(selected ? myContext : FindModel.SearchContext.ANY);
}
}
@@ -1,6 +1,6 @@
package com.intellij.find.editorHeaderActions;
import com.intellij.find.EditorSearchSession;
import com.intellij.find.SearchSession;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.actionSystem.ex.CheckboxAction;
@@ -34,19 +34,19 @@ public abstract class EditorHeaderToggleAction extends CheckboxAction implements
@Override
public boolean isSelected(AnActionEvent e) {
EditorSearchSession search = e.getData(EditorSearchSession.SESSION_KEY);
SearchSession search = e.getData(SearchSession.KEY);
return search != null && isSelected(search);
}
@Override
public void setSelected(AnActionEvent e, boolean selected) {
EditorSearchSession search = e.getData(EditorSearchSession.SESSION_KEY);
SearchSession search = e.getData(SearchSession.KEY);
if (search != null) {
setSelected(search, selected);
}
}
protected abstract boolean isSelected(@NotNull EditorSearchSession session);
protected abstract boolean isSelected(@NotNull SearchSession session);
protected abstract void setSelected(@NotNull EditorSearchSession session, boolean selected);
protected abstract void setSelected(@NotNull SearchSession session, boolean selected);
}
@@ -15,6 +15,8 @@
*/
package com.intellij.find.editorHeaderActions;
import com.intellij.find.SearchSession;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonShortcuts;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.actionSystem.Shortcut;
@@ -24,8 +26,13 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
public final class NextOccurrenceAction extends PrevNextOccurrenceAction {
public NextOccurrenceAction(@NotNull Handler handler) {
super(IdeActions.ACTION_NEXT_OCCURENCE, handler);
public NextOccurrenceAction() {
super(IdeActions.ACTION_NEXT_OCCURENCE);
}
@Override
public void actionPerformed(AnActionEvent e) {
e.getRequiredData(SearchSession.KEY).searchForward();
}
@NotNull
@@ -15,7 +15,7 @@
*/
package com.intellij.find.editorHeaderActions;
import com.intellij.find.SearchReplaceComponent;
import com.intellij.find.SearchSession;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.util.containers.ContainerUtil;
@@ -25,28 +25,21 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
public abstract class PrevNextOccurrenceAction extends DumbAwareAction implements ContextAwareShortcutProvider {
private final Handler myHandler;
PrevNextOccurrenceAction(@NotNull String templateActionId, @NotNull Handler handler) {
PrevNextOccurrenceAction(@NotNull String templateActionId) {
copyFrom(ActionManager.getInstance().getAction(templateActionId));
myHandler = handler;
}
@Override
public final void update(AnActionEvent e) {
myHandler.update(e);
}
@Override
public final void actionPerformed(AnActionEvent e) {
myHandler.actionPerformed(e);
SearchSession search = e.getData(SearchSession.KEY);
e.getPresentation().setEnabled(search != null && search.hasMatches());
}
@Nullable
@Override
public final ShortcutSet getShortcut(@NotNull DataContext context) {
SearchReplaceComponent searchComponent = SearchReplaceComponent.COMPONENT_KEY.getData(context);
boolean singleLine = searchComponent != null && !searchComponent.isMultiline();
SearchSession search = SearchSession.KEY.getData(context);
boolean singleLine = search != null && !search.getFindModel().isMultiline();
return Utils.shortcutSetOf(singleLine ? ContainerUtil.concat(getDefaultShortcuts(), getSingleLineShortcuts()) : getDefaultShortcuts());
}
@@ -55,11 +48,4 @@ public abstract class PrevNextOccurrenceAction extends DumbAwareAction implement
@NotNull
protected abstract List<Shortcut> getSingleLineShortcuts();
public interface Handler {
void update(AnActionEvent e);
void actionPerformed(AnActionEvent e);
}
}
@@ -15,6 +15,8 @@
*/
package com.intellij.find.editorHeaderActions;
import com.intellij.find.SearchSession;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.actionSystem.KeyboardShortcut;
import com.intellij.openapi.actionSystem.Shortcut;
@@ -27,8 +29,13 @@ import java.awt.event.KeyEvent;
import java.util.List;
public final class PrevOccurrenceAction extends PrevNextOccurrenceAction {
public PrevOccurrenceAction(@NotNull Handler handler) {
super(IdeActions.ACTION_PREVIOUS_OCCURENCE, handler);
public PrevOccurrenceAction() {
super(IdeActions.ACTION_PREVIOUS_OCCURENCE);
}
@Override
public void actionPerformed(AnActionEvent e) {
e.getRequiredData(SearchSession.KEY).searchBackward();
}
@NotNull
@@ -15,7 +15,7 @@
*/
package com.intellij.find.editorHeaderActions;
import com.intellij.find.SearchReplaceComponent;
import com.intellij.find.SearchSession;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.actionSystem.ex.CustomComponentAction;
@@ -29,10 +29,11 @@ import java.awt.*;
public class StatusTextAction extends DumbAwareAction implements CustomComponentAction {
@Override
public void update(AnActionEvent e) {
String statusText = e.getData(SearchReplaceComponent.STATUS_TEXT_KEY);
SearchSession search = e.getData(SearchSession.KEY);
String statusText = search == null ? "" : search.getComponent().getStatusText();
JLabel label = (JLabel)e.getPresentation().getClientProperty(CUSTOM_COMPONENT_PROPERTY);
if (label != null) {
label.setText(StringUtil.notNullize(statusText));
label.setText(statusText);
label.setVisible(StringUtil.isNotEmpty(statusText));
}
}
@@ -15,8 +15,8 @@
*/
package com.intellij.find.editorHeaderActions;
import com.intellij.find.EditorSearchSession;
import com.intellij.find.FindSettings;
import com.intellij.find.SearchSession;
import org.jetbrains.annotations.NotNull;
public class ToggleMatchCase extends EditorHeaderToggleAction {
@@ -25,12 +25,12 @@ public class ToggleMatchCase extends EditorHeaderToggleAction {
}
@Override
protected boolean isSelected(@NotNull EditorSearchSession session) {
protected boolean isSelected(@NotNull SearchSession session) {
return session.getFindModel().isCaseSensitive();
}
@Override
protected void setSelected(@NotNull EditorSearchSession session, boolean selected) {
protected void setSelected(@NotNull SearchSession session, boolean selected) {
session.getFindModel().setCaseSensitive(selected);
FindSettings.getInstance().setLocalCaseSensitive(selected);
}
@@ -17,6 +17,7 @@ package com.intellij.find.editorHeaderActions;
import com.intellij.find.EditorSearchSession;
import com.intellij.find.FindModel;
import com.intellij.find.SearchSession;
import com.intellij.openapi.actionSystem.AnActionEvent;
import org.jetbrains.annotations.NotNull;
@@ -35,12 +36,12 @@ public class TogglePreserveCaseAction extends EditorHeaderToggleAction {
}
@Override
protected boolean isSelected(@NotNull EditorSearchSession session) {
protected boolean isSelected(@NotNull SearchSession session) {
return session.getFindModel().isPreserveCase();
}
@Override
protected void setSelected(@NotNull EditorSearchSession session, boolean selected) {
protected void setSelected(@NotNull SearchSession session, boolean selected) {
session.getFindModel().setPreserveCase(selected);
}
}
@@ -15,9 +15,9 @@
*/
package com.intellij.find.editorHeaderActions;
import com.intellij.find.EditorSearchSession;
import com.intellij.find.FindModel;
import com.intellij.find.FindSettings;
import com.intellij.find.SearchSession;
import org.jetbrains.annotations.NotNull;
public class ToggleRegex extends EditorHeaderToggleAction {
@@ -26,12 +26,12 @@ public class ToggleRegex extends EditorHeaderToggleAction {
}
@Override
protected boolean isSelected(@NotNull EditorSearchSession session) {
protected boolean isSelected(@NotNull SearchSession session) {
return session.getFindModel().isRegularExpressions();
}
@Override
protected void setSelected(@NotNull EditorSearchSession session, boolean selected) {
protected void setSelected(@NotNull SearchSession session, boolean selected) {
FindModel findModel = session.getFindModel();
findModel.setRegularExpressions(selected);
if (selected) {
@@ -1,6 +1,7 @@
package com.intellij.find.editorHeaderActions;
import com.intellij.find.EditorSearchSession;
import com.intellij.find.SearchSession;
import com.intellij.openapi.actionSystem.AnActionEvent;
import org.jetbrains.annotations.NotNull;
@@ -18,12 +19,12 @@ public class ToggleSelectionOnlyAction extends EditorHeaderToggleAction {
}
@Override
protected boolean isSelected(@NotNull EditorSearchSession session) {
protected boolean isSelected(@NotNull SearchSession session) {
return !session.getFindModel().isGlobal();
}
@Override
protected void setSelected(@NotNull EditorSearchSession session, boolean selected) {
protected void setSelected(@NotNull SearchSession session, boolean selected) {
session.getFindModel().setGlobal(!selected);
}
}
@@ -1,7 +1,7 @@
package com.intellij.find.editorHeaderActions;
import com.intellij.find.EditorSearchSession;
import com.intellij.find.FindSettings;
import com.intellij.find.SearchSession;
import com.intellij.openapi.actionSystem.AnActionEvent;
import org.jetbrains.annotations.NotNull;
@@ -14,18 +14,18 @@ public class ToggleWholeWordsOnlyAction extends EditorHeaderToggleAction {
public void update(AnActionEvent e) {
super.update(e);
EditorSearchSession session = e.getData(EditorSearchSession.SESSION_KEY);
SearchSession session = e.getData(SearchSession.KEY);
e.getPresentation().setEnabled(session != null && !session.getFindModel().isRegularExpressions());
e.getPresentation().setVisible(session != null && !session.getFindModel().isMultiline());
}
@Override
protected boolean isSelected(@NotNull EditorSearchSession session) {
protected boolean isSelected(@NotNull SearchSession session) {
return session.getFindModel().isWholeWordsOnly();
}
@Override
protected void setSelected(@NotNull EditorSearchSession session, boolean selected) {
protected void setSelected(@NotNull SearchSession session, boolean selected) {
FindSettings.getInstance().setLocalWholeWordsOnly(selected);
session.getFindModel().setWholeWordsOnly(selected);
}
@@ -360,9 +360,6 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable
}
JDOMUtil.writeDocument(new Document(element), filePath, SystemProperties.getLineSeparator());
}
catch (WriteExternalException e1) {
LOG.error(e1);
}
catch (IOException e1) {
LOG.error(e1);
}
@@ -19,7 +19,6 @@ import com.intellij.ide.IdeBundle;
import com.intellij.ide.util.ElementsChooser;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.ExportableComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
@@ -32,6 +31,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.FieldPanel;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.containers.MultiMap;
import gnu.trove.THashSet;
@@ -57,14 +57,14 @@ public class ChooseComponentsToExportDialog extends DialogWrapper {
private final boolean myShowFilePath;
private final String myDescription;
public ChooseComponentsToExportDialog(@NotNull MultiMap<File, ExportableComponent> fileToComponents,
public ChooseComponentsToExportDialog(@NotNull MultiMap<File, ExportableItem> fileToComponents,
boolean showFilePath, final String title, String description) {
super(false);
myDescription = description;
myShowFilePath = showFilePath;
Map<ExportableComponent, ComponentElementProperties> componentToContainingListElement = new LinkedHashMap<ExportableComponent, ComponentElementProperties>();
for (ExportableComponent component : fileToComponents.values()) {
Map<ExportableItem, ComponentElementProperties> componentToContainingListElement = new LinkedHashMap<ExportableItem, ComponentElementProperties>();
for (ExportableItem component : fileToComponents.values()) {
if (!addToExistingListElement(component, componentToContainingListElement, fileToComponents)) {
ComponentElementProperties componentElementProperties = new ComponentElementProperties();
componentElementProperties.addComponent(component);
@@ -147,12 +147,12 @@ public class ChooseComponentsToExportDialog extends DialogWrapper {
super.doOKAction();
}
private static boolean addToExistingListElement(@NotNull ExportableComponent component,
@NotNull Map<ExportableComponent, ComponentElementProperties> componentToContainingListElement,
@NotNull MultiMap<File, ExportableComponent> fileToComponents) {
private static boolean addToExistingListElement(@NotNull ExportableItem component,
@NotNull Map<ExportableItem, ComponentElementProperties> componentToContainingListElement,
@NotNull MultiMap<File, ExportableItem> fileToComponents) {
File file = null;
for (File exportFile : component.getExportFiles()) {
for (ExportableComponent tiedComponent : fileToComponents.get(exportFile)) {
for (File exportFile : component.getFiles()) {
for (ExportableItem tiedComponent : fileToComponents.get(exportFile)) {
if (tiedComponent == component) {
continue;
}
@@ -234,8 +234,8 @@ public class ChooseComponentsToExportDialog extends DialogWrapper {
return panel;
}
Set<ExportableComponent> getExportableComponents() {
Set<ExportableComponent> components = new THashSet<ExportableComponent>();
Set<ExportableItem> getExportableComponents() {
Set<ExportableItem> components = new THashSet<ExportableItem>();
for (ComponentElementProperties elementProperties : myChooser.getMarkedElements()) {
components.addAll(elementProperties.myComponents);
}
@@ -243,9 +243,9 @@ public class ChooseComponentsToExportDialog extends DialogWrapper {
}
private static class ComponentElementProperties implements ElementsChooser.ElementProperties {
private final Set<ExportableComponent> myComponents = new HashSet<ExportableComponent>();
private final Set<ExportableItem> myComponents = new HashSet<ExportableItem>();
private boolean addComponent(ExportableComponent component) {
private boolean addComponent(ExportableItem component) {
return myComponents.add(component);
}
@@ -263,10 +263,10 @@ public class ChooseComponentsToExportDialog extends DialogWrapper {
public String toString() {
Set<String> names = new LinkedHashSet<String>();
for (ExportableComponent component : myComponents) {
for (ExportableItem component : myComponents) {
names.add(component.getPresentableName());
}
return StringUtil.join(names.toArray(new String[names.size()]), ", ");
return StringUtil.join(ArrayUtil.toStringArray(names), ", ");
}
}
@@ -1,332 +0,0 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.
*/
/**
* @author cdr
*/
package com.intellij.ide.actions;
import com.intellij.AbstractBundle;
import com.intellij.CommonBundle;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.impl.ApplicationImpl;
import com.intellij.openapi.components.*;
import com.intellij.openapi.components.impl.ServiceManagerImpl;
import com.intellij.openapi.components.impl.stores.StateStorageManager;
import com.intellij.openapi.components.impl.stores.StoreUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.PluginDescriptor;
import com.intellij.openapi.options.OptionsBundle;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.util.PairProcessor;
import com.intellij.util.PlatformUtils;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.io.ZipUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ExportSettingsAction extends AnAction implements DumbAware {
private static final Logger LOG = Logger.getInstance(ExportSettingsAction.class);
@Override
public void actionPerformed(@Nullable AnActionEvent e) {
ApplicationManager.getApplication().saveSettings();
ChooseComponentsToExportDialog dialog = new ChooseComponentsToExportDialog(getExportableComponentsMap(true, true), true,
IdeBundle.message("title.select.components.to.export"),
IdeBundle.message(
"prompt.please.check.all.components.to.export"));
if (!dialog.showAndGet()) {
return;
}
Set<ExportableComponent> markedComponents = dialog.getExportableComponents();
if (markedComponents.isEmpty()) {
return;
}
Set<File> exportFiles = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
for (ExportableComponent markedComponent : markedComponents) {
ContainerUtil.addAll(exportFiles, markedComponent.getExportFiles());
}
final File saveFile = dialog.getExportFile();
try {
if (saveFile.exists() && Messages.showOkCancelDialog(
IdeBundle.message("prompt.overwrite.settings.file", FileUtil.toSystemDependentName(saveFile.getPath())),
IdeBundle.message("title.file.already.exists"), Messages.getWarningIcon()) != Messages.OK) {
return;
}
MyZipOutputStream zipOut = new MyZipOutputStream(new BufferedOutputStream(new FileOutputStream(saveFile)));
try {
Set<String> writtenItemRelativePaths = new THashSet<String>();
String configRoot = FileUtilRt.toSystemIndependentName(PathManager.getConfigPath());
for (File file : exportFiles) {
if (file.exists()) {
String relativePath = FileUtilRt.getRelativePath(configRoot, FileUtilRt.toSystemIndependentName(file.getAbsolutePath()), '/');
assert relativePath != null;
ZipUtil.addFileOrDirRecursively(zipOut, null, file, relativePath, null, writtenItemRelativePaths);
}
}
exportInstalledPlugins(zipOut);
ZipEntry zipEntry = new ZipEntry(ImportSettingsFilenameFilter.SETTINGS_JAR_MARKER);
zipOut.putNextEntry(zipEntry);
zipOut.closeEntry();
}
finally {
zipOut.doClose();
}
ShowFilePathAction.showDialog(getEventProject(e), IdeBundle.message("message.settings.exported.successfully"),
IdeBundle.message("title.export.successful"), saveFile, null);
}
catch (IOException e1) {
Messages.showErrorDialog(IdeBundle.message("error.writing.settings", e1.toString()), IdeBundle.message("title.error.writing.file"));
}
}
private static void exportInstalledPlugins(@NotNull MyZipOutputStream zipOut) throws IOException {
List<String> plugins = new ArrayList<String>();
for (IdeaPluginDescriptor descriptor : PluginManagerCore.getPlugins()) {
if (!descriptor.isBundled() && descriptor.isEnabled()) {
plugins.add(descriptor.getPluginId().getIdString());
}
}
if (plugins.isEmpty()) {
return;
}
ZipEntry e = new ZipEntry(PluginManager.INSTALLED_TXT);
zipOut.putNextEntry(e);
try {
PluginManagerCore.writePluginsList(plugins, new OutputStreamWriter(zipOut, CharsetToolkit.UTF8_CHARSET));
}
finally {
zipOut.closeEntry();
}
}
private static class MyZipOutputStream extends ZipOutputStream {
private boolean ignoreClose = true;
public MyZipOutputStream(@NotNull OutputStream out) {
super(out);
}
@Override
public void close() throws IOException {
if (!ignoreClose) {
doClose();
}
}
public void doClose() throws IOException {
super.close();
}
}
@NotNull
public static MultiMap<File, ExportableComponent> getExportableComponentsMap(boolean onlyExisting, boolean computePresentableNames) {
ApplicationImpl application = (ApplicationImpl)ApplicationManager.getApplication();
StateStorageManager storageManager = ComponentsPackage.getStateStore(application).getStateStorageManager();
return getExportableComponentsMap(onlyExisting, computePresentableNames, storageManager);
}
@NotNull
public static MultiMap<File, ExportableComponent> getExportableComponentsMap(final boolean onlyExisting, final boolean computePresentableNames, final @NotNull StateStorageManager storageManager) {
@SuppressWarnings("deprecation")
List<ExportableApplicationComponent> components1 = ComponentsPackage.getComponents(ApplicationManager.getApplication(), ExportableApplicationComponent.class);
List<ExportableComponent> components2 = ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent.class);
final MultiMap<File, ExportableComponent> result = MultiMap.createLinkedSet();
for (ExportableComponent component : ContainerUtil.concat(components1, components2)) {
for (File exportFile : component.getExportFiles()) {
result.putValue(exportFile, component);
}
}
if (onlyExisting) {
for (Iterator<File> it = result.keySet().iterator(); it.hasNext(); ) {
if (!it.next().exists()) {
it.remove();
}
}
}
ServiceManagerImpl.processAllImplementationClasses((ApplicationImpl)ApplicationManager.getApplication(), new PairProcessor<Class<?>, PluginDescriptor>() {
@Override
public boolean process(@NotNull Class<?> aClass, @Nullable PluginDescriptor pluginDescriptor) {
State stateAnnotation = StoreUtil.getStateSpec(aClass);
if (stateAnnotation != null && !StringUtil.isEmpty(stateAnnotation.name())) {
if (ExportableComponent.class.isAssignableFrom(aClass)) {
return true;
}
int storageIndex;
Storage[] storages = stateAnnotation.storages();
if (storages.length == 1) {
storageIndex = 0;
}
else {
return true;
}
Storage storage = storages[storageIndex];
if (storage.roamingType() != RoamingType.DISABLED &&
storage.storageClass().equals(StateStorage.class) &&
storage.scheme() == StorageScheme.DEFAULT &&
!StringUtil.isEmpty(storage.file()) &&
storage.file().startsWith(StoragePathMacros.APP_CONFIG)) {
File additionalExportFile = null;
if (!StringUtil.isEmpty(stateAnnotation.additionalExportFile())) {
String expandedPath = storageManager.expandMacros(stateAnnotation.additionalExportFile());
additionalExportFile = new File(expandedPath);
if (!additionalExportFile.exists()) {
//noinspection deprecation
additionalExportFile = new File(storageManager.expandMacros(StoragePathMacros.ROOT_CONFIG) + '/' + expandedPath);
}
if (onlyExisting && !additionalExportFile.exists()) {
additionalExportFile = null;
}
}
File file = new File(storageManager.expandMacros(storage.file()));
boolean fileExists = !onlyExisting || file.exists();
if (fileExists || additionalExportFile != null) {
File[] files;
if (additionalExportFile == null) {
files = new File[]{file};
}
else {
files = fileExists ? new File[]{file, additionalExportFile} : new File[]{additionalExportFile};
}
ExportableComponentItem item = new ExportableComponentItem(files,
computePresentableNames
? getComponentPresentableName(stateAnnotation, aClass, pluginDescriptor)
: "",
storage.roamingType());
result.putValue(file, item);
if (additionalExportFile != null) {
result.putValue(additionalExportFile, item);
}
}
}
}
return true;
}
});
return result;
}
@NotNull
private static String getComponentPresentableName(@NotNull State state, @NotNull Class<?> aClass, @Nullable PluginDescriptor pluginDescriptor) {
if (state.presentableName() != State.NameGetter.class) {
try {
return ReflectionUtil.newInstance(state.presentableName()).get();
}
catch (Exception e) {
LOG.error(e);
}
}
String defaultName = state.name();
String resourceBundleName;
if (pluginDescriptor != null && pluginDescriptor instanceof IdeaPluginDescriptor && !"com.intellij".equals(pluginDescriptor.getPluginId().getIdString())) {
resourceBundleName = ((IdeaPluginDescriptor)pluginDescriptor).getResourceBundleBaseName();
}
else {
resourceBundleName = OptionsBundle.PATH_TO_BUNDLE;
}
if (resourceBundleName == null) {
return defaultName;
}
ClassLoader classLoader = pluginDescriptor == null ? null : pluginDescriptor.getPluginClassLoader();
classLoader = classLoader == null ? aClass.getClassLoader() : classLoader;
if (classLoader != null) {
String message = messageOrDefault(classLoader, resourceBundleName, defaultName);
if (message != defaultName) {
return message;
}
if (PlatformUtils.isRubyMine()) {
// ruby plugin in RubyMine has id "com.intellij", so, we cannot set "resource-bundle" in plugin.xml
return messageOrDefault(classLoader, "org.jetbrains.plugins.ruby.RBundle", defaultName);
}
}
return defaultName;
}
@NotNull
private static String messageOrDefault(@NotNull ClassLoader classLoader, @NotNull String bundleName, @NotNull String defaultName) {
ResourceBundle bundle = AbstractBundle.getResourceBundle(bundleName, classLoader);
return bundle == null ? defaultName : CommonBundle.messageOrDefault(bundle, "exportable." + defaultName + ".presentable.name", defaultName);
}
public static final class ExportableComponentItem implements ExportableComponent {
private final File[] files;
private final String name;
private final RoamingType roamingType;
public ExportableComponentItem(@NotNull File[] files, @NotNull String name, @NotNull RoamingType roamingType) {
this.files = files;
this.name = name;
this.roamingType = roamingType;
}
@NotNull
@Override
public File[] getExportFiles() {
return files;
}
@NotNull
@Override
public String getPresentableName() {
return name;
}
@NotNull
public RoamingType getRoamingType() {
return roamingType;
}
}
}
@@ -0,0 +1,257 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.ide.actions
import com.intellij.AbstractBundle
import com.intellij.CommonBundle
import com.intellij.ide.IdeBundle
import com.intellij.ide.plugins.IdeaPluginDescriptor
import com.intellij.ide.plugins.PluginManager
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.PathManager
import com.intellij.openapi.application.impl.ApplicationImpl
import com.intellij.openapi.components.*
import com.intellij.openapi.components.impl.ServiceManagerImpl
import com.intellij.openapi.components.impl.stores.StateStorageManager
import com.intellij.openapi.components.impl.stores.StoreUtil
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.extensions.PluginDescriptor
import com.intellij.openapi.options.OptionsBundle
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.ui.Messages
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.FileUtilRt
import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.CharsetToolkit
import com.intellij.util.PairProcessor
import com.intellij.util.PlatformUtils
import com.intellij.util.ReflectionUtil
import com.intellij.util.containers.MultiMap
import com.intellij.util.io.ZipUtil
import gnu.trove.THashSet
import java.io.*
import java.util.*
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
private class ExportSettingsAction : AnAction(), DumbAware {
override fun actionPerformed(e: AnActionEvent?) {
ApplicationManager.getApplication().saveSettings()
val dialog = ChooseComponentsToExportDialog(getExportableComponentsMap(true, true), true,
IdeBundle.message("title.select.components.to.export"),
IdeBundle.message(
"prompt.please.check.all.components.to.export"))
if (!dialog.showAndGet()) {
return
}
val markedComponents = dialog.exportableComponents
if (markedComponents.isEmpty()) {
return
}
val exportFiles = THashSet(FileUtil.FILE_HASHING_STRATEGY)
for (markedComponent in markedComponents) {
exportFiles.addAll(markedComponent.files)
}
val saveFile = dialog.exportFile
try {
if (saveFile.exists() && Messages.showOkCancelDialog(
IdeBundle.message("prompt.overwrite.settings.file", FileUtil.toSystemDependentName(saveFile.path)),
IdeBundle.message("title.file.already.exists"), Messages.getWarningIcon()) != Messages.OK) {
return
}
val zipOut = MyZipOutputStream(BufferedOutputStream(FileOutputStream(saveFile)))
try {
val writtenItemRelativePaths = THashSet<String>()
val configRoot = FileUtilRt.toSystemIndependentName(PathManager.getConfigPath())
for (file in exportFiles) {
if (file.exists()) {
val relativePath = FileUtilRt.getRelativePath(configRoot, FileUtilRt.toSystemIndependentName(file.absolutePath), '/')!!
ZipUtil.addFileOrDirRecursively(zipOut, null, file, relativePath, null, writtenItemRelativePaths)
}
}
exportInstalledPlugins(zipOut)
val zipEntry = ZipEntry(ImportSettingsFilenameFilter.SETTINGS_JAR_MARKER)
zipOut.putNextEntry(zipEntry)
zipOut.closeEntry()
}
finally {
zipOut.doClose()
}
ShowFilePathAction.showDialog(AnAction.getEventProject(e), IdeBundle.message("message.settings.exported.successfully"),
IdeBundle.message("title.export.successful"), saveFile, null)
}
catch (e1: IOException) {
Messages.showErrorDialog(IdeBundle.message("error.writing.settings", e1.toString()), IdeBundle.message("title.error.writing.file"))
}
}
}
private class MyZipOutputStream(out: OutputStream) : ZipOutputStream(out) {
override fun close() {
}
fun doClose() {
super.close()
}
}
data class ExportableItem(val files: List<File>, val presentableName: String, val roamingType: RoamingType)
private val LOG = Logger.getInstance(ExportSettingsAction::class.java)
private fun exportInstalledPlugins(zipOut: MyZipOutputStream) {
val plugins = ArrayList<String>()
for (descriptor in PluginManagerCore.getPlugins()) {
if (!descriptor.isBundled && descriptor.isEnabled) {
plugins.add(descriptor.pluginId.idString)
}
}
if (plugins.isEmpty()) {
return
}
val e = ZipEntry(PluginManager.INSTALLED_TXT)
zipOut.putNextEntry(e)
try {
PluginManagerCore.writePluginsList(plugins, OutputStreamWriter(zipOut, CharsetToolkit.UTF8_CHARSET))
}
finally {
zipOut.closeEntry()
}
}
fun getExportableComponentsMap(onlyExisting: Boolean, computePresentableNames: Boolean, storageManager: StateStorageManager = ApplicationManager.getApplication().stateStore.stateStorageManager): MultiMap<File, ExportableItem> {
val result = MultiMap.createLinkedSet<File, ExportableItem>()
val processor = { component: ExportableComponent ->
val item = ExportableItem(component.exportFiles.toList(), component.presentableName, RoamingType.DEFAULT)
for (exportFile in item.files) {
result.putValue(exportFile, item)
}
}
@Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")
ApplicationManager.getApplication().getComponents(ExportableApplicationComponent::class.java).forEach(processor)
ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent::class.java).forEach(processor)
if (onlyExisting) {
val it = result.keySet().iterator()
while (it.hasNext()) {
if (!it.next().exists()) {
it.remove()
}
}
}
ServiceManagerImpl.processAllImplementationClasses(ApplicationManager.getApplication() as ApplicationImpl, object : PairProcessor<Class<*>, PluginDescriptor> {
override fun process(aClass: Class<*>, pluginDescriptor: PluginDescriptor?): Boolean {
val stateAnnotation = StoreUtil.getStateSpec(aClass)
if (stateAnnotation != null && !StringUtil.isEmpty(stateAnnotation.name)) {
if (ExportableComponent::class.java.isAssignableFrom(aClass)) {
return true
}
val storageIndex: Int
val storages = stateAnnotation.storages
if (storages.size() == 1) {
storageIndex = 0
}
else {
return true
}
val storage = storages[storageIndex]
if (storage.roamingType != RoamingType.DISABLED && storage.storageClass == StateStorage::class && storage.scheme == StorageScheme.DEFAULT && !storage.file.isNullOrEmpty()) {
var additionalExportFile: File? = null
var additionalExportPath = stateAnnotation.additionalExportFile
if (additionalExportPath.isNotEmpty()) {
// backward compatibility - path can contain macro
@Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")
if (additionalExportPath[0] != '$') {
additionalExportPath = StoragePathMacros.ROOT_CONFIG + "/" + additionalExportPath
}
additionalExportFile = File(storageManager.expandMacros(additionalExportPath))
if (onlyExisting && !additionalExportFile.exists()) {
additionalExportFile = null
}
}
val file = File(storageManager.expandMacros(storage.file))
val fileExists = !onlyExisting || file.exists()
if (fileExists || additionalExportFile != null) {
val files = if (additionalExportFile == null) listOf(file) else if (fileExists) listOf(file, additionalExportFile) else listOf(additionalExportFile)
val item = ExportableItem(files, if (computePresentableNames) getComponentPresentableName(stateAnnotation, aClass, pluginDescriptor) else "", storage.roamingType)
result.putValue(file, item)
if (additionalExportFile != null) {
result.putValue(additionalExportFile, item)
}
}
}
}
return true
}
})
return result
}
private fun getComponentPresentableName(state: State, aClass: Class<*>, pluginDescriptor: PluginDescriptor?): String {
val presentableName = state.presentableName.java
if (presentableName != State.NameGetter::class.java) {
try {
return ReflectionUtil.newInstance(presentableName).get()
}
catch (e: Exception) {
LOG.error(e)
}
}
val defaultName = state.name
val resourceBundleName = (if (pluginDescriptor is IdeaPluginDescriptor && "com.intellij" != pluginDescriptor.pluginId.idString) {
pluginDescriptor.resourceBundleBaseName
}
else {
OptionsBundle.PATH_TO_BUNDLE
}) ?: return defaultName
var classLoader = pluginDescriptor?.pluginClassLoader ?: aClass.classLoader
if (classLoader != null) {
val message = messageOrDefault(classLoader, resourceBundleName, defaultName)
if (message !== defaultName) {
return message
}
if (PlatformUtils.isRubyMine()) {
// ruby plugin in RubyMine has id "com.intellij", so, we cannot set "resource-bundle" in plugin.xml
return messageOrDefault(classLoader, "org.jetbrains.plugins.ruby.RBundle", defaultName)
}
}
return defaultName
}
private fun messageOrDefault(classLoader: ClassLoader, bundleName: String, defaultName: String): String {
val bundle = AbstractBundle.getResourceBundle(bundleName, classLoader) ?: return defaultName
return CommonBundle.messageOrDefault(bundle, "exportable.$defaultName.presentable.name", defaultName)
}
@@ -1,180 +0,0 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.
*/
/**
* @author cdr
*/
package com.intellij.ide.actions;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.startup.StartupActionScriptManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.components.ExportableComponent;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.updateSettings.impl.UpdateSettings;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.util.Consumer;
import com.intellij.util.containers.MultiMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
public class ImportSettingsAction extends AnAction implements DumbAware {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
final DataContext dataContext = e.getDataContext();
final Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(dataContext);
ChooseComponentsToExportDialog.chooseSettingsFile(PathManager.getConfigPath(), component, IdeBundle.message("title.import.file.location"), IdeBundle.message("prompt.choose.import.file.path")).doWhenDone(new Consumer<String>() {
@Override
public void consume(String path) {
File saveFile = new File(path);
try {
doImport(saveFile);
}
catch (ZipException e1) {
Messages.showErrorDialog(
IdeBundle.message("error.reading.settings.file", presentableFileName(saveFile), e1.getMessage(), promptLocationMessage()),
IdeBundle.message("title.invalid.file"));
}
catch (IOException e1) {
Messages.showErrorDialog(IdeBundle.message("error.reading.settings.file.2", presentableFileName(saveFile), e1.getMessage()),
IdeBundle.message("title.error.reading.file"));
}
}
});
}
private static void doImport(@NotNull File saveFile) throws IOException {
if (!saveFile.exists()) {
Messages.showErrorDialog(IdeBundle.message("error.cannot.find.file", presentableFileName(saveFile)),
IdeBundle.message("title.file.not.found"));
return;
}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
final ZipEntry magicEntry = new ZipFile(saveFile).getEntry(ImportSettingsFilenameFilter.SETTINGS_JAR_MARKER);
if (magicEntry == null) {
Messages.showErrorDialog(
IdeBundle.message("error.file.contains.no.settings.to.import", presentableFileName(saveFile), promptLocationMessage()),
IdeBundle.message("title.invalid.file"));
return;
}
MultiMap<File, ExportableComponent> fileToComponents = ExportSettingsAction.getExportableComponentsMap(false, true);
List<ExportableComponent> components = getComponentsStored(saveFile, fileToComponents.values());
fileToComponents.values().retainAll(components);
final ChooseComponentsToExportDialog dialog = new ChooseComponentsToExportDialog(fileToComponents, false,
IdeBundle.message("title.select.components.to.import"),
IdeBundle.message("prompt.check.components.to.import"));
if (!dialog.showAndGet()) {
return;
}
final Set<ExportableComponent> chosenComponents = dialog.getExportableComponents();
Set<String> relativeNamesToExtract = new THashSet<String>();
for (ExportableComponent chosenComponent : chosenComponents) {
for (File exportFile : chosenComponent.getExportFiles()) {
String rPath = FileUtilRt.getRelativePath(new File(PathManager.getConfigPath()), exportFile);
assert rPath != null;
relativeNamesToExtract.add(FileUtil.toSystemIndependentName(rPath));
}
}
relativeNamesToExtract.add(PluginManager.INSTALLED_TXT);
final File tempFile = new File(PathManager.getPluginTempPath() + "/" + saveFile.getName());
FileUtil.copy(saveFile, tempFile);
File outDir = new File(PathManager.getConfigPath());
final ImportSettingsFilenameFilter filenameFilter = new ImportSettingsFilenameFilter(relativeNamesToExtract);
StartupActionScriptManager.addActionCommand(new StartupActionScriptManager.UnzipCommand(tempFile, outDir, filenameFilter));
// remove temp file
StartupActionScriptManager.addActionCommand(new StartupActionScriptManager.DeleteCommand(tempFile));
UpdateSettings.getInstance().forceCheckForUpdateAfterRestart();
String key = ApplicationManager.getApplication().isRestartCapable()
? "message.settings.imported.successfully.restart"
: "message.settings.imported.successfully";
if (Messages.showOkCancelDialog(IdeBundle.message(key,
ApplicationNamesInfo.getInstance().getProductName(),
ApplicationNamesInfo.getInstance().getFullProductName()),
IdeBundle.message("title.restart.needed"), Messages.getQuestionIcon()) == Messages.OK) {
((ApplicationEx)ApplicationManager.getApplication()).restart(true);
}
}
private static String presentableFileName(@NotNull File file) {
return "'" + FileUtil.toSystemDependentName(file.getPath()) + "'";
}
private static String promptLocationMessage() {
return IdeBundle.message("message.please.ensure.correct.settings");
}
@NotNull
private static List<ExportableComponent> getComponentsStored(@NotNull File settings,
@NotNull Collection<? extends ExportableComponent> registeredComponents) throws IOException {
THashSet<String> zipEntries = new THashSet<String>();
ZipFile zip = new ZipFile(settings);
try {
Enumeration enumeration = zip.entries();
while (enumeration.hasMoreElements()) {
ZipEntry zipEntry = (ZipEntry)enumeration.nextElement();
zipEntries.add(zipEntry.getName());
}
}
finally {
zip.close();
}
File configPath = new File(PathManager.getConfigPath());
List<ExportableComponent> components = new ArrayList<ExportableComponent>();
for (ExportableComponent component : registeredComponents) {
for (File exportFile : component.getExportFiles()) {
String relativePath = FileUtilRt.getRelativePath(configPath, exportFile);
assert relativePath != null;
relativePath = FileUtilRt.toSystemIndependentName(relativePath);
if (exportFile.getName().indexOf('.') == -1 && !exportFile.isFile()) {
relativePath += '/';
}
if (zipEntries.contains(relativePath)) {
components.add(component);
break;
}
}
}
return components;
}
}
@@ -0,0 +1,156 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.ide.actions
import com.intellij.ide.IdeBundle
import com.intellij.ide.plugins.PluginManager
import com.intellij.ide.startup.StartupActionScriptManager
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.PlatformDataKeys
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ApplicationNamesInfo
import com.intellij.openapi.application.PathManager
import com.intellij.openapi.application.ex.ApplicationEx
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.ui.Messages
import com.intellij.openapi.updateSettings.impl.UpdateSettings
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.FileUtilRt
import com.intellij.util.Consumer
import gnu.trove.THashSet
import java.io.File
import java.io.IOException
import java.util.*
import java.util.zip.ZipException
import java.util.zip.ZipFile
private class ImportSettingsAction : AnAction(), DumbAware {
override fun actionPerformed(e: AnActionEvent) {
val dataContext = e.dataContext
val component = PlatformDataKeys.CONTEXT_COMPONENT.getData(dataContext)
ChooseComponentsToExportDialog.chooseSettingsFile(PathManager.getConfigPath(), component, IdeBundle.message("title.import.file.location"), IdeBundle.message("prompt.choose.import.file.path")).doWhenDone(object : Consumer<String> {
override fun consume(path: String) {
val saveFile = File(path)
try {
doImport(saveFile)
}
catch (e1: ZipException) {
Messages.showErrorDialog(
IdeBundle.message("error.reading.settings.file", presentableFileName(saveFile), e1.getMessage(), promptLocationMessage()),
IdeBundle.message("title.invalid.file"))
}
catch (e1: IOException) {
Messages.showErrorDialog(IdeBundle.message("error.reading.settings.file.2", presentableFileName(saveFile), e1.getMessage()),
IdeBundle.message("title.error.reading.file"))
}
}
})
}
private fun doImport(saveFile: File) {
if (!saveFile.exists()) {
Messages.showErrorDialog(IdeBundle.message("error.cannot.find.file", presentableFileName(saveFile)),
IdeBundle.message("title.file.not.found"))
return
}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
val magicEntry = ZipFile(saveFile).getEntry(ImportSettingsFilenameFilter.SETTINGS_JAR_MARKER)
if (magicEntry == null) {
Messages.showErrorDialog(
IdeBundle.message("error.file.contains.no.settings.to.import", presentableFileName(saveFile), promptLocationMessage()),
IdeBundle.message("title.invalid.file"))
return
}
val fileToComponents = getExportableComponentsMap(false, true)
val components = getComponentsStored(saveFile, fileToComponents.values())
fileToComponents.values().retainAll(components)
val dialog = ChooseComponentsToExportDialog(fileToComponents, false,
IdeBundle.message("title.select.components.to.import"),
IdeBundle.message("prompt.check.components.to.import"))
if (!dialog.showAndGet()) {
return
}
val chosenComponents = dialog.exportableComponents
val relativeNamesToExtract = THashSet<String>()
for (chosenComponent in chosenComponents) {
for (exportFile in chosenComponent.files) {
relativeNamesToExtract.add(FileUtil.toSystemIndependentName(FileUtilRt.getRelativePath(File(PathManager.getConfigPath()), exportFile)!!))
}
}
relativeNamesToExtract.add(PluginManager.INSTALLED_TXT)
val tempFile = File(PathManager.getPluginTempPath(), saveFile.name)
FileUtil.copy(saveFile, tempFile)
val outDir = File(PathManager.getConfigPath())
val filenameFilter = ImportSettingsFilenameFilter(relativeNamesToExtract)
StartupActionScriptManager.addActionCommand(StartupActionScriptManager.UnzipCommand(tempFile, outDir, filenameFilter))
// remove temp file
StartupActionScriptManager.addActionCommand(StartupActionScriptManager.DeleteCommand(tempFile))
UpdateSettings.getInstance().forceCheckForUpdateAfterRestart()
val key = if (ApplicationManager.getApplication().isRestartCapable)
"message.settings.imported.successfully.restart"
else
"message.settings.imported.successfully"
if (Messages.showOkCancelDialog(IdeBundle.message(key,
ApplicationNamesInfo.getInstance().productName,
ApplicationNamesInfo.getInstance().fullProductName),
IdeBundle.message("title.restart.needed"), Messages.getQuestionIcon()) == Messages.OK) {
(ApplicationManager.getApplication() as ApplicationEx).restart(true)
}
}
private fun presentableFileName(file: File) = "'" + FileUtil.toSystemDependentName(file.path) + "'"
private fun promptLocationMessage() = IdeBundle.message("message.please.ensure.correct.settings")
private fun getComponentsStored(settings: File, registeredComponents: Collection<ExportableItem>): List<ExportableItem> {
val zipEntries = THashSet<String>()
val zipFile = ZipFile(settings)
try {
val enumeration = zipFile.entries()
while (enumeration.hasMoreElements()) {
zipEntries.add(enumeration.nextElement().name)
}
}
finally {
zipFile.close()
}
val configPath = File(PathManager.getConfigPath())
val components = ArrayList<ExportableItem>()
for (component in registeredComponents) {
for (exportFile in component.files) {
var relativePath = FileUtilRt.getRelativePath(configPath, exportFile)!!
relativePath = FileUtilRt.toSystemIndependentName(relativePath)
if (exportFile.name.indexOf('.') == -1 && !exportFile.isFile) {
relativePath += '/'
}
if (zipEntries.contains(relativePath)) {
components.add(component)
break
}
}
}
return components
}
}
@@ -15,10 +15,6 @@
*/
package com.intellij.idea;
import com.intellij.CommonBundle;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.DefaultLogger;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
@@ -34,91 +30,134 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufOutputStream;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.io.BuiltInServer;
import org.jetbrains.io.MessageDecoder;
import javax.swing.*;
import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author mike
*/
public final class SocketLock {
private static final Logger LOG = Logger.getInstance(SocketLock.class);
@NonNls private static final String ACTIVATE_COMMAND = "activate ";
private final String configPath;
private final String systemPath;
public enum ActivateStatus {ACTIVATED, NO_INSTANCE, CANNOT_ACTIVATE}
private final AtomicReference<Consumer<List<String>>> activateListener = new AtomicReference<Consumer<List<String>>>();
private static final String PORT_FILE = "port";
private static final String ACTIVATE_COMMAND = "activate ";
private static final String PORT_LOCK_FILE = "port.lock";
private BuiltInServer server;
private final String myConfigPath;
private final String mySystemPath;
private final AtomicReference<Consumer<List<String>>> myActivateListener = new AtomicReference<Consumer<List<String>>>();
private BuiltInServer myServer;
public SocketLock(@NotNull String configPath, @NotNull String systemPath) {
this.configPath = canonicalPath(configPath);
this.systemPath = canonicalPath(systemPath);
myConfigPath = canonicalPath(configPath);
mySystemPath = canonicalPath(systemPath);
}
public void setExternalInstanceListener(@Nullable Consumer<List<String>> consumer) {
activateListener.set(consumer);
myActivateListener.set(consumer);
}
public void dispose() {
if (LOG.isDebugEnabled()) {
LOG.debug("enter: destroyProcess()");
}
log("enter: dispose()");
BuiltInServer server = myServer;
if (server == null) return;
BuiltInServer server = this.server;
boolean doRemovePortMarker = server != null;
try {
if (server != null) {
Disposer.dispose(server);
}
Disposer.dispose(server);
}
finally {
if (doRemovePortMarker) {
try {
executeAndClose(new Executor<Void>() {
@Override
public Void execute(@NotNull List<Closeable> closeables) throws IOException {
File config = new File(configPath);
File system = new File(systemPath);
lockPortMarker(config, closeables);
lockPortMarker(system, closeables);
FileUtil.delete(new File(config, "port"));
FileUtil.delete(new File(system, "port"));
return null;
}
});
}
catch (Throwable e) {
logError(e);
}
try {
underLocks(new Callable<Void>() {
@Override
public Void call() throws Exception {
FileUtil.delete(new File(myConfigPath, PORT_FILE));
FileUtil.delete(new File(mySystemPath, PORT_FILE));
return null;
}
});
}
catch (Exception e) {
Logger.getInstance(SocketLock.class).warn(e);
}
}
}
@Nullable
public BuiltInServer getServer() {
return server;
return myServer;
}
private static void lockPortMarker(@NotNull File parent, @NotNull List<Closeable> list) throws IOException {
FileUtilRt.createDirectory(parent);
FileOutputStream stream = new FileOutputStream(new File(parent, "port.lock"), true);
list.add(stream);
@NotNull
public ActivateStatus lock() throws Exception {
return lock(ArrayUtil.EMPTY_STRING_ARRAY);
}
@NotNull
public ActivateStatus lock(@NotNull final String[] args) throws Exception {
log("enter: lock(config=%s system=%s)", myConfigPath, mySystemPath);
return underLocks(new Callable<ActivateStatus>() {
@Override
public ActivateStatus call() throws Exception {
File portMarkerC = new File(myConfigPath, PORT_FILE);
File portMarkerS = new File(mySystemPath, PORT_FILE);
MultiMap<Integer, String> portToPath = MultiMap.createSmart();
addExistingPort(portMarkerC, myConfigPath, portToPath);
addExistingPort(portMarkerS, mySystemPath, portToPath);
if (!portToPath.isEmpty()) {
for (Map.Entry<Integer, Collection<String>> entry : portToPath.entrySet()) {
ActivateStatus status = tryActivate(entry.getKey(), entry.getValue(), args);
if (status != ActivateStatus.NO_INSTANCE) {
return status;
}
}
}
final String[] lockedPaths = {myConfigPath, mySystemPath};
myServer = BuiltInServer.start(1, 6942, 50, false, new NotNullProducer<ChannelHandler>() {
@NotNull
@Override
public ChannelHandler produce() {
return new MyChannelInboundHandler(lockedPaths, myActivateListener);
}
});
byte[] portBytes = Integer.toString(myServer.getPort()).getBytes(CharsetToolkit.UTF8_CHARSET);
FileUtil.writeToFile(portMarkerC, portBytes);
FileUtil.writeToFile(portMarkerS, portBytes);
return ActivateStatus.NO_INSTANCE;
}
});
}
private <V> V underLocks(@NotNull Callable<V> action) throws Exception {
FileUtilRt.createDirectory(new File(myConfigPath));
FileOutputStream lock1 = new FileOutputStream(new File(myConfigPath, PORT_LOCK_FILE), true);
try {
FileUtilRt.createDirectory(new File(mySystemPath));
FileOutputStream lock2 = new FileOutputStream(new File(mySystemPath, PORT_LOCK_FILE), true);
try {
return action.call();
}
finally {
lock2.close();
}
}
finally {
lock1.close();
}
}
private static void addExistingPort(@NotNull File portMarker, @NotNull String path, @NotNull MultiMap<Integer, String> portToPath) {
@@ -126,189 +165,81 @@ public final class SocketLock {
try {
portToPath.putValue(Integer.parseInt(FileUtilRt.loadFile(portMarker)), path);
}
catch (Throwable e) {
LOG.debug(e);
catch (Exception e) {
log(e);
// don't delete - we overwrite it on write in any case
}
}
}
@Nullable
public ActivateStatus lock() {
return lock(ArrayUtil.EMPTY_STRING_ARRAY);
}
@Nullable
public ActivateStatus lock(@NotNull final String[] args) {
if (LOG.isDebugEnabled()) {
LOG.debug("enter: lock(configPath='" + configPath + "', systemPath='" + systemPath + "')");
}
try {
final File config = new File(configPath);
final File system = new File(systemPath);
final File portMarkerC = new File(config, "port");
final File portMarkerS = new File(system, "port");
return executeAndClose(new Executor<ActivateStatus>() {
@Override
public ActivateStatus execute(@NotNull List<Closeable> closeables) throws Throwable {
lockPortMarker(config, closeables);
lockPortMarker(system, closeables);
MultiMap<Integer, String> portToPath = MultiMap.createSmart();
addExistingPort(portMarkerC, configPath, portToPath);
addExistingPort(portMarkerS, systemPath, portToPath);
if (!portToPath.isEmpty()) {
for (Map.Entry<Integer, Collection<String>> entry : portToPath.entrySet()) {
ActivateStatus status = tryActivate(entry.getKey(), entry.getValue(), args);
if (status != ActivateStatus.NO_INSTANCE) {
return status;
}
}
}
final String[] lockedPaths = {configPath, systemPath};
server = BuiltInServer.start(1, 6942, 50, false, new NotNullProducer<ChannelHandler>() {
@NotNull
@Override
public ChannelHandler produce() {
return new MyChannelInboundHandler(lockedPaths, activateListener);
}
});
byte[] portBytes = Integer.toString(server.getPort()).getBytes(CharsetToolkit.UTF8_CHARSET);
FileUtil.writeToFile(portMarkerC, portBytes);
FileUtil.writeToFile(portMarkerS, portBytes);
return ActivateStatus.NO_INSTANCE;
}
});
}
catch (Throwable e) {
logError(e);
if (Main.isHeadless()) {
Main.showMessage("Cannot lock system folders", e);
}
else {
String pathToLogFile = PathManager.getLogPath() + "/idea.log file".replace('/', File.separatorChar);
JOptionPane.showMessageDialog(
JOptionPane.getRootFrame(),
CommonBundle.message("cannot.start.other.instance.is.running.error.message", ApplicationNamesInfo.getInstance().getProductName(),
pathToLogFile),
CommonBundle.message("title.warning"),
JOptionPane.WARNING_MESSAGE
);
}
return null;
}
}
private interface Executor<T> {
T execute(@NotNull List<Closeable> closeables) throws Throwable;
}
private static <T> T executeAndClose(@NotNull Executor<T> executor) throws Throwable {
List<Closeable> closeables = new ArrayList<Closeable>();
try {
return executor.execute(closeables);
}
finally {
for (Closeable closeable : closeables) {
try {
closeable.close();
}
catch (Throwable e) {
logError(e);
}
}
}
}
private static void logError(@NotNull Throwable e) {
// default logger throws AssertionError and it leads to startup failure without error message dialog
if (LOG instanceof DefaultLogger) {
LOG.warn(e);
}
else {
LOG.error(e);
}
}
@SuppressWarnings({"SocketOpenedButNotSafelyClosed", "IOResourceOpenedButNotSafelyClosed"})
@NotNull
private static ActivateStatus tryActivate(int portNumber, @NotNull Collection<String> paths, @NotNull String[] args) {
Socket socket = null;
try {
socket = new Socket(NetUtils.getLoopbackAddress(), portNumber);
socket.setSoTimeout(300);
Socket socket = new Socket(NetUtils.getLoopbackAddress(), portNumber);
try {
socket.setSoTimeout(300);
boolean result = false;
DataInputStream in = new DataInputStream(socket.getInputStream());
while (true) {
try {
String path = in.readUTF();
if (paths.contains(path)) {
result = true;
// don't break - read all input
boolean result = false;
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed") DataInputStream in = new DataInputStream(socket.getInputStream());
while (true) {
try {
String path = in.readUTF();
if (paths.contains(path)) {
result = true; // don't break - read all input
}
}
catch (IOException ignored) {
break;
}
}
catch (IOException ignored) {
break;
if (result) {
try {
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed") DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeUTF(ACTIVATE_COMMAND + new File(".").getAbsolutePath() + "\0" + StringUtil.join(args, "\0"));
out.flush();
String response = in.readUTF();
if (response.equals("ok")) {
return ActivateStatus.ACTIVATED;
}
}
catch (IOException e) {
log(e);
}
return ActivateStatus.CANNOT_ACTIVATE;
}
}
if (result) {
try {
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeUTF(ACTIVATE_COMMAND + new File(".").getAbsolutePath() + "\0" + StringUtil.join(args, "\0"));
out.flush();
String response = in.readUTF();
if (response.equals("ok")) {
return ActivateStatus.ACTIVATED;
}
}
catch (IOException e) {
LOG.info(e);
}
return ActivateStatus.CANNOT_ACTIVATE;
finally {
socket.close();
}
}
catch (IOException e) {
LOG.debug(e);
}
finally {
if (socket != null) {
try {
socket.close();
}
catch (IOException e) {
LOG.debug(e);
}
}
log(e);
}
return ActivateStatus.NO_INSTANCE;
}
private static class MyChannelInboundHandler extends MessageDecoder {
private final String[] lockedPaths;
private State state = State.HEADER;
private final AtomicReference<Consumer<List<String>>> activateListener;
public MyChannelInboundHandler(@NotNull String[] lockedPaths, @NotNull AtomicReference<Consumer<List<String>>> activateListener) {
this.lockedPaths = lockedPaths;
this.activateListener = activateListener;
}
private enum State {HEADER, CONTENT}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
private final String[] myLockedPaths;
private final AtomicReference<Consumer<List<String>>> myActivateListener;
private State myState = State.HEADER;
public MyChannelInboundHandler(@NotNull String[] lockedPaths, @NotNull AtomicReference<Consumer<List<String>>> activateListener) {
myLockedPaths = lockedPaths;
myActivateListener = activateListener;
}
@Override
public void channelActive(ChannelHandlerContext context) throws Exception {
ByteBuf buffer = context.alloc().ioBuffer(1024);
boolean success = false;
try {
ByteBufOutputStream out = new ByteBufOutputStream(buffer);
for (String path : lockedPaths) {
for (String path : myLockedPaths) {
if (path != null) {
out.writeUTF(path);
}
@@ -324,11 +255,10 @@ public final class SocketLock {
context.writeAndFlush(buffer);
}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
@Override
protected void messageReceived(@NotNull ChannelHandlerContext context, @NotNull ByteBuf input) throws Exception {
while (true) {
switch (state) {
switch (myState) {
case HEADER: {
ByteBuf buffer = getBufferIfSufficient(input, 2, context);
if (buffer == null) {
@@ -336,7 +266,7 @@ public final class SocketLock {
}
contentLength = buffer.readUnsignedShort();
state = State.CONTENT;
myState = State.CONTENT;
}
break;
@@ -348,7 +278,7 @@ public final class SocketLock {
if (StringUtil.startsWith(command, ACTIVATE_COMMAND)) {
List<String> args = StringUtil.split(command.subSequence(ACTIVATE_COMMAND.length(), command.length()).toString(), "\0");
Consumer<List<String>> listener = activateListener.get();
Consumer<List<String>> listener = myActivateListener.get();
if (listener != null) {
listener.consume(args);
}
@@ -371,8 +301,20 @@ public final class SocketLock {
private static String canonicalPath(@NotNull String configPath) {
try {
return new File(configPath).getCanonicalPath();
} catch (IOException ignore) {
}
catch (IOException ignore) {
return configPath;
}
}
private static void log(Exception e) {
Logger.getInstance(SocketLock.class).debug(e);
}
private static void log(String format, Object... args) {
Logger logger = Logger.getInstance(SocketLock.class);
if (logger.isDebugEnabled()) {
logger.debug(String.format(format, args));
}
}
}
@@ -244,6 +244,7 @@ public class StartupUtil {
finally { writer.close(); }
}
@SuppressWarnings("SSBasedInspection")
private static void delete(File ideTempFile) {
if (!FileUtilRt.delete(ideTempFile)) {
ideTempFile.deleteOnExit();
@@ -251,25 +252,36 @@ public class StartupUtil {
}
private synchronized static boolean lockSystemFolders(String[] args) {
assert ourLock == null;
if (ourLock != null) {
throw new AssertionError();
}
ourLock = new SocketLock(PathManager.getConfigPath(), PathManager.getSystemPath());
SocketLock.ActivateStatus activateStatus = ourLock.lock(args);
if (activateStatus != SocketLock.ActivateStatus.NO_INSTANCE) {
if (activateStatus != null && (Main.isHeadless() || activateStatus == SocketLock.ActivateStatus.CANNOT_ACTIVATE)) {
String message = "Only one instance of " + ApplicationNamesInfo.getInstance().getFullProductName() + " can be run at a time.";
Main.showMessage("Too Many Instances", message, true);
}
SocketLock.ActivateStatus status;
try {
status = ourLock.lock(args);
}
catch (Exception e) {
Main.showMessage("Cannot Lock System Folders", e);
return false;
}
ShutDownTracker.getInstance().registerShutdownTask(new Runnable() {
@Override
public void run() {
ourLock.dispose();
}
});
return true;
if (status == SocketLock.ActivateStatus.NO_INSTANCE) {
ShutDownTracker.getInstance().registerShutdownTask(new Runnable() {
@Override
public void run() {
ourLock.dispose();
}
});
return true;
}
else if (Main.isHeadless() || status == SocketLock.ActivateStatus.CANNOT_ACTIVATE) {
String message = "Only one instance of " + ApplicationNamesInfo.getInstance().getFullProductName() + " can be run at a time.";
Main.showMessage("Too Many Instances", message, true);
}
return false;
}
private static void fixProcessEnvironment(Logger log) {
@@ -22,7 +22,6 @@ import com.intellij.lang.Commenter;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.*;
import com.intellij.openapi.fileTypes.ex.ExternalizableFileType;
import com.intellij.openapi.options.ExternalInfo;
import com.intellij.openapi.options.ExternalizableScheme;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.util.*;
@@ -415,10 +414,4 @@ public class AbstractFileType extends UserFileType<AbstractFileType> implements
public void setCommenter(final Commenter commenter) {
myCommenter = commenter;
}
@Override
@Nullable
public ExternalInfo getExternalInfo() {
return null;
}
}
@@ -71,7 +71,7 @@ import java.util.concurrent.atomic.AtomicLong;
@State(
name = "FileTypeManager",
storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/filetypes.xml"),
storages = @Storage(file = "filetypes.xml"),
additionalExportFile = FileTypeManagerImpl.FILE_SPEC
)
public class FileTypeManagerImpl extends FileTypeManagerEx implements PersistentStateComponent<Element>, ApplicationComponent, Disposable {
@@ -15,12 +15,15 @@
*/
package com.intellij.openapi.progress.util;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.ui.GraphicsConfig;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.Gray;
import com.intellij.ui.JBColor;
import com.intellij.util.NotNullProducer;
import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -36,8 +39,26 @@ import java.awt.geom.Rectangle2D;
public class ColorProgressBar extends JComponent {
private static final Dimension PREFERRED_SIZE = new Dimension(146, 17);
public static final Color GREEN = new JBColor(new Color(0x6cad74), new Color(0x4a8c53));
public static final Color RED = new JBColor(new Color(0xd67b76), new Color(0xe55757));
public static final Color GREEN = new JBColor(new NotNullProducer<Color>() {
@NotNull
@Override
public Color produce() {
UISettings settings = UISettings.getInstance();
return settings == null || null == settings.COLOR_BLINDNESS
? new JBColor(new Color(0x6cad74), new Color(0x4a8c53))
: new JBColor(new Color(0x6ca69c), new Color(0x639990));
}
});
public static final Color RED = new JBColor(new NotNullProducer<Color>() {
@NotNull
@Override
public Color produce() {
UISettings settings = UISettings.getInstance();
return settings == null || null == settings.COLOR_BLINDNESS
? new JBColor(new Color(0xd67b76), new Color(0xe55757))
: new JBColor(new Color(0xcc7447), new Color(0xcc7447));
}
});
public static final Color RED_TEXT = new JBColor(new Color(0xb81708), new Color(0xdb5c5c));
public static final Color BLUE = new JBColor(new Color(1, 68, 208), JBColor.blue);
public static final Color YELLOW = new JBColor(new Color(0xa67a21), new Color(0x91703a));
@@ -17,6 +17,8 @@ package org.jetbrains.io;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ExceptionUtil;
import com.intellij.util.NotNullProducer;
import com.intellij.util.net.NetUtils;
import io.netty.bootstrap.ServerBootstrap;
@@ -52,16 +54,25 @@ public class BuiltInServer implements Disposable {
}
@NotNull
public static BuiltInServer start(int workerCount, int firstPort, int portsCount, boolean tryAnyPort, @Nullable NotNullProducer<ChannelHandler> channelHandler) throws Throwable {
return start(new NioEventLoopGroup(workerCount, PooledThreadExecutor.INSTANCE), true, firstPort, portsCount, tryAnyPort, channelHandler);
public static BuiltInServer start(int workerCount,
int firstPort,
int portsCount,
boolean tryAnyPort,
@Nullable NotNullProducer<ChannelHandler> handler) throws Exception {
return start(new NioEventLoopGroup(workerCount, PooledThreadExecutor.INSTANCE), true, firstPort, portsCount, tryAnyPort, handler);
}
@NotNull
public static BuiltInServer start(@NotNull EventLoopGroup eventLoopGroup, boolean isOwnerOfEventLoopGroup, int firstPort, int portsCount, boolean tryAnyPort, @Nullable NotNullProducer<ChannelHandler> channelHandler) throws Throwable {
public static BuiltInServer start(@NotNull EventLoopGroup eventLoopGroup,
boolean isEventLoopGroupOwner,
int firstPort,
int portsCount,
boolean tryAnyPort,
@Nullable NotNullProducer<ChannelHandler> handler) throws Exception {
ChannelRegistrar channelRegistrar = new ChannelRegistrar();
ServerBootstrap bootstrap = NettyUtil.nioServerBootstrap(eventLoopGroup);
configureChildHandler(bootstrap, channelRegistrar, channelHandler);
return new BuiltInServer(eventLoopGroup, bind(firstPort, portsCount, tryAnyPort, bootstrap, channelRegistrar), isOwnerOfEventLoopGroup);
configureChildHandler(bootstrap, channelRegistrar, handler);
return new BuiltInServer(eventLoopGroup, bind(firstPort, portsCount, tryAnyPort, bootstrap, channelRegistrar), isEventLoopGroupOwner);
}
public int getPort() {
@@ -73,7 +84,9 @@ public class BuiltInServer implements Disposable {
return eventLoopGroup;
}
static void configureChildHandler(@NotNull ServerBootstrap bootstrap, @NotNull final ChannelRegistrar channelRegistrar, final @Nullable NotNullProducer<ChannelHandler> channelHandler) {
static void configureChildHandler(@NotNull ServerBootstrap bootstrap,
@NotNull final ChannelRegistrar channelRegistrar,
final @Nullable NotNullProducer<ChannelHandler> channelHandler) {
final PortUnificationServerHandler portUnificationServerHandler = channelHandler == null ? new PortUnificationServerHandler() : null;
bootstrap.childHandler(new ChannelInitializer() {
@Override
@@ -83,41 +96,41 @@ public class BuiltInServer implements Disposable {
});
}
public static boolean isPortForbidden(int port) {
for (int forbiddenPort : FORBIDDEN_PORTS) {
if (port == forbiddenPort) return true;
}
return false;
}
private static int bind(int firstPort,
int portsCount,
boolean tryAnyPort,
@NotNull ServerBootstrap bootstrap,
@NotNull ChannelRegistrar channelRegistrar) throws Exception {
InetAddress address = NetUtils.getLoopbackAddress();
private static int bind(int firstPort, int portsCount, boolean tryAnyPort, @NotNull ServerBootstrap bootstrap, @NotNull ChannelRegistrar channelRegistrar) throws Throwable {
InetAddress loopbackAddress = NetUtils.getLoopbackAddress();
for (int i = 0; i < portsCount; i++) {
int port = firstPort + i;
if (isPortForbidden(i)) {
if (ArrayUtil.indexOf(FORBIDDEN_PORTS, i) >= 0) {
continue;
}
ChannelFuture future = bootstrap.bind(loopbackAddress, port).awaitUninterruptibly();
ChannelFuture future = bootstrap.bind(address, port).awaitUninterruptibly();
if (future.isSuccess()) {
channelRegistrar.add(future.channel());
return port;
}
else if (!tryAnyPort && i == (portsCount - 1)) {
throw future.cause();
ExceptionUtil.rethrowAll(future.cause());
}
}
LOG.info("We cannot bind to our default range, so, try to bind to any free port");
ChannelFuture future = bootstrap.bind(loopbackAddress, 0).awaitUninterruptibly();
ChannelFuture future = bootstrap.bind(address, 0).awaitUninterruptibly();
if (future.isSuccess()) {
channelRegistrar.add(future.channel());
return ((InetSocketAddress)future.channel().localAddress()).getPort();
}
else {
throw future.cause();
ExceptionUtil.rethrowAll(future.cause());
}
return -1; // unreachable
}
@Override
@@ -141,10 +141,7 @@ local.vcs.action.name.undo.command=Undo {0}
local.vcs.action.name.redo.command=Redo {0}
error.reading.color.scheme.from.file.error.message=Error reading color scheme from {0}
corrupted.scheme.file.message.title=Corrupted File
button.background=&Background
vcs.configurable.general.tab.title=General
cannot.start.other.instance.is.running.error.message={0} was unable to create a local connection in order to check whether\nother instance of {0} is currently running on the same machine.\nRunning multiple instances of {0} on the same machine may cause unpredictable\nresults because of sharing system folders.\nPlease troubleshoot your TCP/IP configuration and/or local firewall settings.\nand attach the {1}
button.load.file=Load File
date.frequency=Once {0}
name.label.text=Na&me:
@@ -50,7 +50,7 @@ public class LockSupportTest {
}
@Test(timeout = 30000)
public void testUseCanonicalPathLock() {
public void testUseCanonicalPathLock() throws Exception {
assumeThat(SystemInfo.isFileSystemCaseSensitive, is(false));
String path1 = myTempDir.getPath();
@@ -69,7 +69,7 @@ public class LockSupportTest {
}
@Test(timeout = 30000)
public void testLock() {
public void testLock() throws Exception {
SocketLock lock = new SocketLock(myTempDir.getPath() + "/c", myTempDir.getPath() + "/s");
try {
assertThat(lock.lock(), equalTo(SocketLock.ActivateStatus.NO_INSTANCE));
@@ -80,8 +80,8 @@ public class LockSupportTest {
}
@Test(timeout = 30000)
public void testTwoLocks() {
List<SocketLock> toClose = new ArrayList<SocketLock>();
public void testTwoLocks() throws Exception {
List<SocketLock> toClose = new ArrayList<>();
try {
assertThat(createLock(toClose, myTempDir, "1", "1-").lock(), equalTo(SocketLock.ActivateStatus.NO_INSTANCE));
assertThat(createLock(toClose, myTempDir, "1.1", "1-1").lock(), equalTo(SocketLock.ActivateStatus.NO_INSTANCE));
@@ -92,9 +92,7 @@ public class LockSupportTest {
assertThat(createLock(toClose, myTempDir, "1.1", "1-1").lock(), equalTo(SocketLock.ActivateStatus.ACTIVATED));
}
finally {
for (SocketLock lock : toClose) {
lock.dispose();
}
toClose.forEach(SocketLock::dispose);
}
}
@@ -106,7 +104,7 @@ public class LockSupportTest {
}
@Test(timeout = 30000)
public void testDispose() {
public void testDispose() throws Exception {
SocketLock lock1 = new SocketLock(myTempDir.getPath() + "/1", myTempDir.getPath() + "/1-");
SocketLock lock2 = new SocketLock(myTempDir.getPath() + "/1", myTempDir.getPath() + "/1-");
@@ -36,6 +36,9 @@ public @interface State {
*/
boolean defaultStateAsResource() default false;
/**
* Additional export path (relative to application-level configuration root directory).
*/
String additionalExportFile() default "";
Class<? extends NameGetter> presentableName() default NameGetter.class;
@@ -17,10 +17,7 @@ package com.intellij.remoteServer.impl.configuration.deployment;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.RunConfigurationBase;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.configurations.RuntimeConfigurationException;
import com.intellij.execution.configurations.*;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.Result;
@@ -218,6 +215,27 @@ public class DeployToServerRunConfiguration<S extends ServerConfiguration, D ext
super.writeExternal(element);
}
@Override
public RunConfiguration clone() {
Element element = new Element("tag");
try {
writeExternal(element);
}
catch (WriteExternalException e) {
LOG.error(e);
}
DeployToServerRunConfiguration result = (DeployToServerRunConfiguration)super.clone();
try {
result.readExternal(element);
}
catch (InvalidDataException e) {
LOG.error(e);
}
return result;
}
public static class ConfigurationState {
@Attribute("server-name")
public String myServerName;
@@ -428,7 +428,7 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
public void visitTestFailed(@NotNull final TestFailed testFailed) {
final Map<String, String> attributes = testFailed.getAttributes();
assert testFailed.getFailureMessage() != null : "No failure message for: " + myTestFrameworkName;
LOG.assertTrue(testFailed.getFailureMessage() != null, "No failure message for: " + myTestFrameworkName);
final boolean testError = attributes.get(ATTR_KEY_TEST_ERROR) != null;
TestFailedEvent testFailedEvent = new TestFailedEvent(testFailed, testError,
attributes.get(ATTR_KEY_EXPECTED_FILE_PATH),
@@ -65,7 +65,7 @@ public class TestCaseLoader {
public TestCaseLoader(String classFilterName, boolean forceLoadPerformanceTests) {
myForceLoadPerformanceTests = forceLoadPerformanceTests;
String patterns = System.getProperty(TARGET_TEST_PATTERNS);
if (patterns != null) {
if (!StringUtil.isEmpty(patterns)) {
myTestClassesFilter = new PatternListTestClassFilter(StringUtil.split(patterns, ";"));
System.out.println("Using patterns: [" + patterns +"]");
}
@@ -199,7 +199,7 @@ debugger.close.dialog.on.navigate=true
debugger.close.dialog.on.navigate.description=Close evaluate dialog on Jump to (type) source action
debugger.async.smart.step.into=true
debugger.async.smart.step.into.description=Smart step into anonymous class methods in any thread
debugger.monitor.blocked.threads=false
debugger.monitor.blocked.threads=true
debugger.monitor.blocked.threads.description=Watch if a thread we do stepping in is blocked by another suspended thread
analyze.exceptions.on.the.fly=false
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +24,6 @@ package com.intellij.openapi.vcs.changes.shelf;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.impl.patch.FilePatch;
import com.intellij.openapi.options.ExternalInfo;
import com.intellij.openapi.options.ExternalizableScheme;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.DefaultJDOMExternalizer;
@@ -36,7 +35,6 @@ import com.intellij.openapi.vcs.FileStatus;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.ArrayList;
@@ -90,7 +88,7 @@ public class ShelvedChangeList implements JDOMExternalizable, ExternalizableSche
DATE = new Date(Long.parseLong(element.getAttributeValue(ATTRIBUTE_DATE)));
myRecycled = Boolean.parseBoolean(element.getAttributeValue(ATTRIBUTE_RECYCLED_CHANGELIST));
//noinspection unchecked
final List<Element> children = (List<Element>)element.getChildren(ELEMENT_BINARY);
final List<Element> children = element.getChildren(ELEMENT_BINARY);
myBinaryFiles = new ArrayList<ShelvedBinaryFile>(children.size());
for (Element child : children) {
ShelvedBinaryFile binaryFile = new ShelvedBinaryFile();
@@ -161,12 +159,6 @@ public class ShelvedChangeList implements JDOMExternalizable, ExternalizableSche
return mySchemeName;
}
@Nullable
@Override
public ExternalInfo getExternalInfo() {
return null;
}
@Override
public void setName(@NotNull String newName) {
mySchemeName = newName;
@@ -17,6 +17,8 @@
package com.intellij.vcs.log.graph.impl.facade;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.intellij.openapi.util.Condition;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
@@ -78,7 +80,7 @@ public class PermanentGraphImpl<CommitId> implements PermanentGraph<CommitId>, P
@NotNull private final Set<CommitId> myBranchesCommitId;
@NotNull private final Set<Integer> myBranchNodeIds;
@NotNull private final ReachableNodes myReachableNodes;
@NotNull private final BekIntMap myBekIntMap;
@NotNull private final Supplier<BekIntMap> myBekIntMap;
public PermanentGraphImpl(@NotNull PermanentLinearGraphImpl permanentLinearGraph,
@NotNull GraphLayoutImpl permanentGraphLayout,
@@ -92,7 +94,12 @@ public class PermanentGraphImpl<CommitId> implements PermanentGraph<CommitId>, P
myBranchesCommitId = branchesCommitId;
myBranchNodeIds = permanentCommitsInfo.convertToNodeIds(branchesCommitId);
myReachableNodes = new ReachableNodes(LinearGraphUtils.asLiteLinearGraph(permanentLinearGraph));
myBekIntMap = BekSorter.createBekMap(myPermanentLinearGraph, myPermanentGraphLayout, myPermanentCommitsInfo.getTimestampGetter());
myBekIntMap = Suppliers.memoize(new Supplier<BekIntMap>() {
@Override
public BekIntMap get() {
return BekSorter.createBekMap(myPermanentLinearGraph, myPermanentGraphLayout, myPermanentCommitsInfo.getTimestampGetter());
}
});
}
@NotNull
@@ -105,10 +112,10 @@ public class PermanentGraphImpl<CommitId> implements PermanentGraph<CommitId>, P
baseController = new BaseController(this);
}
else if (sortType == SortType.LinearBek) {
baseController = new LinearBekController(new BekBaseController(this, myBekIntMap), this);
baseController = new LinearBekController(new BekBaseController(this, myBekIntMap.get()), this);
}
else {
baseController = new BekBaseController(this, myBekIntMap);
baseController = new BekBaseController(this, myBekIntMap.get());
}
LinearGraphController controller;
+2 -2
View File
@@ -14,6 +14,6 @@
<orderEntry type="module" module-name="testFramework" scope="TEST" />
<orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
<orderEntry type="library" scope="TEST" name="KotlinJavaRuntime" level="project" />
<orderEntry type="library" name="Guava" level="project" />
</component>
</module>
</module>
@@ -194,7 +194,7 @@ public class GroovyScriptClass extends LightElement implements PsiClass, Synthet
return RecursionManager.doPreventingRecursion(this, false, new Computable<PsiClassType>() {
@Override
public PsiClassType compute() {
return CachedValuesManager.getCachedValue(myFile, new CachedValueProvider<PsiClassType>() {
return CachedValuesManager.getCachedValue(GroovyScriptClass.this, new CachedValueProvider<PsiClassType>() {
@Nullable
@Override
public Result<PsiClassType> compute() {
@@ -276,7 +276,7 @@ public class MvcModuleStructureSynchronizer extends AbstractProjectComponent {
@Override
public void computeInReadAction(@NotNull ProgressIndicator indicator) {
if (!isUpToDate()) {
indicator.cancel();
scheduleRunActions();
return;
}
@@ -51,8 +51,7 @@ class TestMethod extends TestObject {
protected void addJUnit3Parameter(JavaParameters javaParameters, final JUnitConfiguration.Data data, Project project) throws ExecutionException {
final PsiClass psiClass = JavaExecutionUtil.findMainClass(project, data.getMainClassName(), GlobalSearchScope.allScope(project));
LOG.assertTrue(psiClass != null);
if (JUnitUtil.isJUnit4TestClass(psiClass)) {
if (psiClass == null || JUnitUtil.isJUnit4TestClass(psiClass)) {
return;
}
final String methodName = data.getMethodName();
@@ -17,9 +17,11 @@ package org.jetbrains.settingsRepository
import com.intellij.configurationStore.ROOT_CONFIG
import com.intellij.configurationStore.StateStorageManagerImpl
import com.intellij.ide.actions.ExportSettingsAction
import com.intellij.ide.actions.ExportableItem
import com.intellij.ide.actions.getExportableComponentsMap
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.*
import com.intellij.openapi.components.RoamingType
import com.intellij.openapi.components.stateStore
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.FileUtilRt
import java.io.File
@@ -27,7 +29,7 @@ import java.io.File
fun copyLocalConfig(storageManager: StateStorageManagerImpl = ApplicationManager.getApplication()!!.stateStore.stateStorageManager as StateStorageManagerImpl) {
val streamProvider = storageManager.streamProvider!! as IcsManager.IcsStreamProvider
val fileToComponents = ExportSettingsAction.getExportableComponentsMap(true, false, storageManager)
val fileToComponents = getExportableComponentsMap(true, false, storageManager)
for (file in fileToComponents.keySet()) {
val absolutePath = FileUtilRt.toSystemIndependentName(file.absolutePath)
var fileSpec = storageManager.collapseMacros(absolutePath)
@@ -67,20 +69,20 @@ private fun saveDirectory(parent: File, parentFileSpec: String, roamingType: Roa
}
}
private fun getRoamingType(components: Collection<ExportableComponent>): RoamingType {
private fun getRoamingType(components: Collection<ExportableItem>): RoamingType {
for (component in components) {
if (component is ExportSettingsAction.ExportableComponentItem) {
if (component is ExportableItem) {
return component.roamingType
}
else if (component is PersistentStateComponent<*>) {
val stateAnnotation = component.javaClass.getAnnotation(State::class.java)
if (stateAnnotation != null) {
val storages = stateAnnotation.storages
if (!storages.isEmpty()) {
return storages[0].roamingType
}
}
}
// else if (component is PersistentStateComponent<*>) {
// val stateAnnotation = component.javaClass.getAnnotation(State::class.java)
// if (stateAnnotation != null) {
// val storages = stateAnnotation.storages
// if (!storages.isEmpty()) {
// return storages[0].roamingType
// }
// }
// }
}
return RoamingType.DEFAULT
}
@@ -31,39 +31,45 @@ public class IDEATestNGRemoteListener implements ISuiteListener, IResultListener
public synchronized void onStart(final ISuite suite) {
if (suite != null) {
final List<ITestNGMethod> allMethods = suite.getAllMethods();
if (allMethods != null) {
int count = 0;
for (ITestNGMethod method : allMethods) {
if (method.isTest()) count += method.getInvocationCount();
try {
final List<ITestNGMethod> allMethods = suite.getAllMethods();
if (allMethods != null) {
int count = 0;
for (ITestNGMethod method : allMethods) {
if (method.isTest()) count += method.getInvocationCount();
}
myPrintStream.println("##teamcity[testCount count = \'" + count + "\']");
}
myPrintStream.println("##teamcity[testCount count = \'" + count + "\']");
}
catch (NoSuchMethodError ignore) {}
myPrintStream.println("##teamcity[rootName name = '" + suite.getName() + "' location = 'file://" + suite.getXmlSuite().getFileName() + "']");
}
}
public synchronized void onFinish(ISuite suite) {
if (suite != null && suite.getAllInvokedMethods().size() < suite.getAllMethods().size()) {
for (ITestNGMethod method : suite.getAllMethods()) {
if (method.isTest()) {
boolean found = false;
for (IInvokedMethod invokedMethod : suite.getAllInvokedMethods()) {
if (invokedMethod.getTestMethod() == method) {
found = true;
try {
if (suite != null && suite.getAllInvokedMethods().size() < suite.getAllMethods().size()) {
for (ITestNGMethod method : suite.getAllMethods()) {
if (method.isTest()) {
boolean found = false;
for (IInvokedMethod invokedMethod : suite.getAllInvokedMethods()) {
if (invokedMethod.getTestMethod() == method) {
found = true;
break;
}
}
if (!found) {
final String fullEscapedMethodName = escapeName(getShortName(method.getTestClass().getName()) + "." + method.getMethodName());
myPrintStream.println("##teamcity[testStarted name=\'" + fullEscapedMethodName + "\']");
myPrintStream.println("##teamcity[testIgnored name=\'" + fullEscapedMethodName + "\']");
myPrintStream.println("##teamcity[testFinished name=\'" + fullEscapedMethodName + "\']");
break;
}
}
if (!found) {
final String fullEscapedMethodName = escapeName(getShortName(method.getTestClass().getName()) + "." + method.getMethodName());
myPrintStream.println("##teamcity[testStarted name=\'" + fullEscapedMethodName + "\']");
myPrintStream.println("##teamcity[testIgnored name=\'" + fullEscapedMethodName + "\']");
myPrintStream.println("##teamcity[testFinished name=\'" + fullEscapedMethodName + "\']");
break;
}
}
}
}
catch (NoSuchMethodError ignored) {}
for (int i = myCurrentSuites.size() - 1; i >= 0; i--) {
onSuiteFinish(myCurrentSuites.remove(i));
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -68,6 +68,7 @@ public class BoundIconRenderer extends GutterIconRenderer {
}
}
@Override
@NotNull
public Icon getIcon() {
if (myIcon != null) {
@@ -76,13 +77,16 @@ public class BoundIconRenderer extends GutterIconRenderer {
return PlatformIcons.UI_FORM_ICON;
}
@Override
public boolean isNavigateAction() {
return true;
}
@Override
@Nullable
public AnAction getClickAction() {
return new AnAction() {
@Override
public void actionPerformed(AnActionEvent e) {
List<PsiFile> formFiles = getBoundFormFiles();
if (formFiles.size() > 0) {
@@ -104,6 +108,7 @@ public class BoundIconRenderer extends GutterIconRenderer {
};
}
@Override
@Nullable
public String getTooltipText() {
List<PsiFile> formFiles = getBoundFormFiles();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,6 +37,7 @@ import java.util.List;
public class FormClassAnnotator implements Annotator {
private static final Logger LOG = Logger.getInstance("#com.intellij.uiDesigner.binding.FormClassAnnotator");
@Override
public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder holder) {
if (psiElement instanceof PsiField) {
PsiField field = (PsiField) psiElement;
@@ -76,20 +77,24 @@ public class FormClassAnnotator implements Annotator {
final String message = UIDesignerBundle.message("field.is.overwritten.by.generated.code", field.getName());
Annotation annotation = holder.createWarningAnnotation(field.getInitializer(), message);
annotation.registerFix(new IntentionAction() {
@Override
@NotNull
public String getText() {
return message;
}
@Override
@NotNull
public String getFamilyName() {
return UIBundle.message("remove.field.initializer.quick.fix");
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return field.getInitializer() != null;
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
if (!FileModificationService.getInstance().preparePsiElementForWrite(field)) return;
final PsiExpression initializer = field.getInitializer();
@@ -97,6 +102,7 @@ public class FormClassAnnotator implements Annotator {
initializer.delete();
}
@Override
public boolean startInWriteAction() {
return true;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,17 +20,18 @@ import com.intellij.CommonBundle;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.uiDesigner.UIDesignerBundle;
import java.util.ArrayList;
import java.util.List;
/**
* @author yole
*/
public class AddGroupAction extends AnAction {
@Override
public void actionPerformed(AnActionEvent e) {
Project project = e.getData(CommonDataKeys.PROJECT);
if (project == null) return;
@@ -41,15 +42,15 @@ public class AddGroupAction extends AnAction {
UIDesignerBundle.message("title.add.group"),
Messages.getQuestionIcon()
);
if(groupName == null){
if (groupName == null) {
return;
}
Palette palette = Palette.getInstance(project);
// Check that name of the group is unique
final ArrayList<GroupItem> groups = palette.getGroups();
for(int i = groups.size() - 1; i >= 0; i--){
if(groupName.equals(groups.get(i).getName())){
List<GroupItem> groups = palette.getGroups();
for (int i = groups.size() - 1; i >= 0; i--) {
if (groupName.equals(groups.get(i).getName())) {
Messages.showErrorDialog(project,
UIDesignerBundle.message("error.group.name.unique"),
CommonBundle.getErrorTitle());
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,7 +53,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;
/**
* @author Vladimir Kondratyev
@@ -114,6 +114,7 @@ public final class ComponentItemDialog extends DialogWrapper {
updateEnabledTextField();
myTfClassName.getChildComponent().addDocumentListener(new com.intellij.openapi.editor.event.DocumentAdapter() {
@Override
public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent e) {
updateOKAction();
}
@@ -128,12 +129,14 @@ public final class ComponentItemDialog extends DialogWrapper {
UIDesignerBundle.message("add.component.choose.icon")));
myTfNestedForm.addActionListener(new MyChooseFileActionListener(project, new TreeFileChooser.PsiFileFilter() {
@Override
public boolean accept(PsiFile file) {
return file.getFileType().equals(StdFileTypes.GUI_DESIGNER_FORM);
}
}, myTfNestedForm, UIDesignerBundle.message("add.component.choose.form")));
myTfNestedForm.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
updateOKAction();
}
@@ -181,10 +184,11 @@ public final class ComponentItemDialog extends DialogWrapper {
void showGroupChooser(GroupItem defaultGroup) {
myGroupLabel.setVisible(true);
myGroupComboBox.setVisible(true);
final ArrayList<GroupItem> groups = Palette.getInstance(myProject).getGroups();
List<GroupItem> groups = Palette.getInstance(myProject).getGroups();
myGroupComboBox.setModel(new DefaultComboBoxModel(groups.toArray()));
myGroupComboBox.setSelectedItem(defaultGroup);
myGroupComboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
updateOKAction();
}
@@ -205,15 +209,18 @@ public final class ComponentItemDialog extends DialogWrapper {
updateOKAction();
}
@Override
@NotNull
protected Action[] createActions() {
return new Action[]{getOKAction(), getCancelAction(), getHelpAction()};
}
@Override
protected void doHelpAction() {
HelpManager.getInstance().invokeHelp("reference.dialogs.addEditPaletteComponent");
}
@Override
protected void doOKAction() {
// TODO[vova] implement validation
if (myClassRadioButton.isSelected()) {
@@ -294,6 +301,7 @@ public final class ComponentItemDialog extends DialogWrapper {
return true;
}
@Override
protected String getDimensionServiceKey() {
if (myOneOff) {
return "#com.intellij.uiDesigner.palette.ComponentItemDialog.OneOff";
@@ -301,10 +309,12 @@ public final class ComponentItemDialog extends DialogWrapper {
return "#com.intellij.uiDesigner.palette.ComponentItemDialog";
}
@Override
public JComponent getPreferredFocusedComponent() {
return myTfClassName.getChildComponent();
}
@Override
protected JComponent createCenterPanel() {
return myPanel;
}
@@ -365,6 +375,7 @@ public final class ComponentItemDialog extends DialogWrapper {
myProject = project;
}
@Override
public void actionPerformed(final ActionEvent e) {
final TreeClassChooserFactory factory = TreeClassChooserFactory.getInstance(myProject);
final TreeClassChooser chooser = factory.createInheritanceClassChooser(UIDesignerBundle.message("title.choose.component.class"),
@@ -394,6 +405,7 @@ public final class ComponentItemDialog extends DialogWrapper {
myTitle = title;
}
@Override
public void actionPerformed(ActionEvent e) {
final TreeClassChooserFactory factory = TreeClassChooserFactory.getInstance(myProject);
PsiFile formFile = null;
@@ -413,6 +425,7 @@ public final class ComponentItemDialog extends DialogWrapper {
}
private class MyRadioChangeListener implements ChangeListener {
@Override
public void stateChanged(ChangeEvent e) {
updateEnabledTextField();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,17 +20,17 @@ import com.intellij.CommonBundle;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.uiDesigner.UIDesignerBundle;
import java.util.ArrayList;
import java.util.List;
/**
* @author yole
*/
public class EditGroupAction extends AnAction {
@Override
public void actionPerformed(AnActionEvent e) {
Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
GroupItem groupToBeEdited = GroupItem.DATA_KEY.getData(e.getDataContext());
@@ -45,14 +45,14 @@ public class EditGroupAction extends AnAction {
groupToBeEdited.getName(),
null
);
if(groupName == null || groupName.equals(groupToBeEdited.getName())){
if (groupName == null || groupName.equals(groupToBeEdited.getName())) {
return;
}
Palette palette = Palette.getInstance(project);
final ArrayList<GroupItem> groups = palette.getGroups();
for(int i = groups.size() - 1; i >= 0; i--){
if(groupName.equals(groups.get(i).getName())){
List<GroupItem> groups = palette.getGroups();
for (int i = groups.size() - 1; i >= 0; i--) {
if (groupName.equals(groups.get(i).getName())) {
Messages.showErrorDialog(project, UIDesignerBundle.message("error.group.name.unique"),
CommonBundle.getErrorTitle());
return;
@@ -63,7 +63,8 @@ public class EditGroupAction extends AnAction {
palette.fireGroupsChanged();
}
@Override public void update(AnActionEvent e) {
@Override
public void update(AnActionEvent e) {
Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
GroupItem groupItem = GroupItem.DATA_KEY.getData(e.getDataContext());
e.getPresentation().setEnabled(project != null && groupItem != null && !groupItem.isReadOnly());
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package com.intellij.uiDesigner.palette;
import com.intellij.ide.ui.LafManager;
import com.intellij.ide.ui.LafManagerListener;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
@@ -78,7 +77,7 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
private final Map<Class, IntrospectedProperty[]> myClass2Properties;
private final Map<String, ComponentItem> myClassName2Item;
/*All groups in the palette*/
private final ArrayList<GroupItem> myGroups;
private final List<GroupItem> myGroups;
/*Listeners, etc*/
private final List<Listener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private final Project myProject;
@@ -118,7 +117,9 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
return ServiceManager.getService(project, Palette.class);
}
/** Invoked by reflection */
/**
* Invoked by reflection
*/
public Palette(Project project) {
myProject = project;
myLafManagerListener = project == null ? null : new MyLafManagerListener();
@@ -136,31 +137,47 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
}
}
@Override
public Element getState() {
final Element e = new Element("state");
writeExternal(e);
return e;
Element state = new Element("state");
writeGroups(state);
return state;
}
@Override
public void loadState(Element state) {
readExternal(state);
myClass2Properties.clear();
myClassName2Item.clear();
myGroups.clear();
processGroups(state.getChildren(ELEMENT_GROUP));
// Ensure that all predefined items are loaded
LOG.assertTrue(myPanelItem != null);
if (!state.getAttributeValue(ATTRIBUTE_VERSION, "1").equals("2")) {
upgradePalette();
}
}
/**Adds specified listener.*/
public void addListener(@NotNull final Listener l){
/**
* Adds specified listener.
*/
public void addListener(@NotNull final Listener l) {
LOG.assertTrue(!myListeners.contains(l));
myListeners.add(l);
}
/**Removes specified listener.*/
public void removeListener(@NotNull final Listener l){
/**
* Removes specified listener.
*/
public void removeListener(@NotNull final Listener l) {
LOG.assertTrue(myListeners.contains(l));
myListeners.remove(l);
}
void fireGroupsChanged() {
for(Listener listener : myListeners) {
for (Listener listener : myListeners) {
listener.groupsChanged(this);
}
}
@@ -172,37 +189,13 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
}
}
public void readExternal(@NotNull final Element element) {
/*
ApplicationManager.getApplication().assertIsDispatchThread();
*/
// It seems that IDEA inokes readExternal twice: first time for node in defaults XML
// the second time for node in project file. Stupidity... :(
myClass2Properties.clear();
myClassName2Item.clear();
myGroups.clear();
// Parse XML
final List groupElements = element.getChildren(ELEMENT_GROUP);
processGroups(groupElements);
// Ensure that all predefined items are loaded
LOG.assertTrue(myPanelItem != null);
if (!element.getAttributeValue(ATTRIBUTE_VERSION, "1").equals("2")) {
upgradePalette();
}
}
private void upgradePalette() {
// load new components from the predefined Palette2.xml
try {
//noinspection HardCodedStringLiteral
final Document document = new SAXBuilder().build(getClass().getResourceAsStream("/idea/Palette2.xml"));
for(Object o: document.getRootElement().getChildren(ELEMENT_GROUP)) {
Element groupElement = (Element) o;
for(GroupItem group: myGroups) {
Document document = new SAXBuilder().build(getClass().getResourceAsStream("/idea/Palette2.xml"));
for (Element groupElement : document.getRootElement().getChildren(ELEMENT_GROUP)) {
for (GroupItem group : myGroups) {
if (group.getName().equals(groupElement.getAttributeValue(ATTRIBUTE_NAME))) {
upgradeGroup(group, groupElement);
break;
@@ -216,8 +209,8 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
}
private void upgradeGroup(final GroupItem group, final Element groupElement) {
for(Object o: groupElement.getChildren(ELEMENT_ITEM)) {
Element itemElement = (Element) o;
for (Object o : groupElement.getChildren(ELEMENT_ITEM)) {
Element itemElement = (Element)o;
if (itemElement.getAttributeValue(ATTRIBUTE_SINCE_VERSION, "").equals("2")) {
processItemElement(itemElement, group, true);
}
@@ -234,18 +227,11 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
}
}
public void writeExternal(@NotNull final Element element) {
ApplicationManager.getApplication().assertIsDispatchThread();
writeGroups(element);
//element.setAttribute(ATTRIBUTE_VERSION, "2");
}
/**
* @return a predefined palette item which corresponds to the JPanel.
*/
@NotNull
public ComponentItem getPanelItem(){
public ComponentItem getPanelItem() {
return myPanelItem;
}
@@ -263,23 +249,23 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
* @return read-only list of all groups in the palette.
* <em>DO NOT MODIFY OR CACHE THIS LIST</em>.
*/
public ArrayList<GroupItem> getGroups(){
public List<GroupItem> getGroups() {
return myGroups;
}
public GroupItem[] getToolWindowGroups() {
GroupItem[] groups = new GroupItem[myGroups.size()+1];
for(int i=0; i<myGroups.size(); i++) {
groups [i] = myGroups.get(i);
GroupItem[] groups = new GroupItem[myGroups.size() + 1];
for (int i = 0; i < myGroups.size(); i++) {
groups[i] = myGroups.get(i);
}
groups [myGroups.size()] = mySpecialGroup;
groups[myGroups.size()] = mySpecialGroup;
return groups;
}
/**
* @param groups list of new groups.
*/
public void setGroups(@NotNull final ArrayList<GroupItem> groups){
public void setGroups(@NotNull final ArrayList<GroupItem> groups) {
myGroups.clear();
myGroups.addAll(groups);
@@ -288,9 +274,10 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
/**
* Adds specified <code>item</code> to the palette.
*
* @param item item to be added
* @exception java.lang.IllegalArgumentException if an item for the same class
* is already exists in the palette
* @throws IllegalArgumentException if an item for the same class
* is already exists in the palette
*/
public void addItem(@NotNull final GroupItem group, @NotNull final ComponentItem item) {
// class -> item
@@ -309,7 +296,7 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
group.addItem(item);
// Process special predefined item for JPanel
if("javax.swing.JPanel".equals(item.getClassName())){
if ("javax.swing.JPanel".equals(item.getClassName())) {
myPanelItem = item;
}
}
@@ -325,18 +312,18 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
}
public GroupItem findGroup(final ComponentItem componentItem) {
for(GroupItem group: myGroups) {
for (GroupItem group : myGroups) {
if (group.contains(componentItem)) {
return group;
}
}
return null;
return null;
}
/**
* Helper method.
*/
private static GridConstraints processDefaultConstraintsElement(@NotNull final Element element){
private static GridConstraints processDefaultConstraintsElement(@NotNull final Element element) {
final GridConstraints constraints = new GridConstraints();
// grid related attributes
@@ -354,7 +341,7 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
// preferred size
final Element prefSizeElement = element.getChild(ELEMENT_PREFERRED_SIZE);
if (prefSizeElement != null){
if (prefSizeElement != null) {
constraints.myPreferredSize.width = LwXmlReader.getRequiredInt(prefSizeElement, ATTRIBUTE_WIDTH);
constraints.myPreferredSize.height = LwXmlReader.getRequiredInt(prefSizeElement, ATTRIBUTE_HEIGHT);
}
@@ -369,7 +356,7 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
return constraints;
}
private void processItemElement(@NotNull final Element itemElement, @NotNull final GroupItem group, final boolean skipExisting){
private void processItemElement(@NotNull final Element itemElement, @NotNull final GroupItem group, final boolean skipExisting) {
// Class name. It's OK if class does not exist.
final String className = LwXmlReader.getRequiredString(itemElement, ATTRIBUTE_CLASS);
if (skipExisting && getItem(className) != null) {
@@ -399,8 +386,8 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
final HashMap<String, StringDescriptor> propertyName2initialValue = new HashMap<String, StringDescriptor>();
{
final Element initialValues = itemElement.getChild(ELEMENT_INITIAL_VALUES);
if (initialValues != null){
for(final Object o : initialValues.getChildren(ELEMENT_PROPERTY)) {
if (initialValues != null) {
for (final Object o : initialValues.getChildren(ELEMENT_PROPERTY)) {
final Element e = (Element)o;
final String name = LwXmlReader.getRequiredString(e, ATTRIBUTE_NAME);
// TODO[all] currently all initial values are strings
@@ -430,14 +417,11 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
/**
* Reads PaletteElements from
*/
private void processGroups(final List groupElements){
for(final Object groupElement1 : groupElements) {
final Element groupElement = (Element)groupElement1;
final String groupName = LwXmlReader.getRequiredString(groupElement, ATTRIBUTE_NAME);
final GroupItem group = new GroupItem(groupName);
private void processGroups(@NotNull List<Element> groupElements) {
for (Element groupElement : groupElements) {
GroupItem group = new GroupItem(LwXmlReader.getRequiredString(groupElement, ATTRIBUTE_NAME));
myGroups.add(group);
for (final Object o : groupElement.getChildren(ELEMENT_ITEM)) {
final Element itemElement = (Element)o;
for (Element itemElement : groupElement.getChildren(ELEMENT_ITEM)) {
try {
processItemElement(itemElement, group, false);
}
@@ -448,8 +432,10 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
}
}
/** Helper method */
private static void writeDefaultConstraintsElement(@NotNull final Element itemElement, @NotNull final GridConstraints c){
/**
* Helper method
*/
private static void writeDefaultConstraintsElement(@NotNull final Element itemElement, @NotNull final GridConstraints c) {
LOG.assertTrue(ELEMENT_ITEM.equals(itemElement.getName()));
final Element element = new Element(ELEMENT_DEFAULT_CONSTRAINTS);
@@ -494,14 +480,16 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
}
}
/** Helper method */
/**
* Helper method
*/
private static void writeInitialValuesElement(
@NotNull final Element itemElement,
@NotNull final HashMap<String, StringDescriptor> name2value
){
) {
LOG.assertTrue(ELEMENT_ITEM.equals(itemElement.getName()));
if(name2value.size() == 0){ // do not append 'initial-values' subtag
if (name2value.size() == 0) { // do not append 'initial-values' subtag
return;
}
@@ -516,8 +504,10 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
}
}
/** Helper method */
private static void writeComponentItem(@NotNull final Element groupElement, @NotNull final ComponentItem item){
/**
* Helper method
*/
private static void writeComponentItem(@NotNull final Element groupElement, @NotNull final ComponentItem item) {
LOG.assertTrue(ELEMENT_GROUP.equals(groupElement.getName()));
final Element itemElement = new Element(ELEMENT_ITEM);
@@ -527,13 +517,13 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
itemElement.setAttribute(ATTRIBUTE_CLASS, item.getClassName());
// Tooltip text (if any)
if(item.myToolTipText != null){
if (item.myToolTipText != null) {
itemElement.setAttribute(ATTRIBUTE_TOOLTIP_TEXT, item.myToolTipText);
}
// Icon (if any)
final String iconPath = item.getIconPath();
if(iconPath != null){
if (iconPath != null) {
itemElement.setAttribute(ATTRIBUTE_ICON, iconPath);
}
@@ -552,21 +542,18 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
writeInitialValuesElement(itemElement, item.getInitialValues());
}
/**
* @param parentElement element to which all "group" elements will be appended
*/
private void writeGroups(@NotNull final Element parentElement){
for (final GroupItem group : myGroups) {
final Element groupElement = new Element(ELEMENT_GROUP);
private void writeGroups(@NotNull Element parentElement) {
for (GroupItem group : myGroups) {
Element groupElement = new Element(ELEMENT_GROUP);
parentElement.addContent(groupElement);
groupElement.setAttribute(ATTRIBUTE_NAME, group.getName());
final ComponentItem[] itemList = group.getItems();
for (ComponentItem aItemList : itemList) {
for (ComponentItem aItemList : group.getItems()) {
writeComponentItem(groupElement, aItemList);
}
}
}
/**
* Helper method
*/
@@ -575,7 +562,7 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
final Method readMethod,
final Method writeMethod,
final IntEnumEditor.Pair[] pairs
){
) {
return new IntroIntProperty(
name,
readMethod,
@@ -634,8 +621,8 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
property = createIntEnumProperty(name, readMethod, writeMethod, enumPairs);
}
else if (JLabel.class.isAssignableFrom(aClass)) { // special handling for javax.swing.JLabel
if (JLabel.class.isAssignableFrom(aClass) && ("displayedMnemonic".equals(name) || "displayedMnemonicIndex".equals(name)))
{ // skip JLabel#displayedMnemonic and JLabel#displayedMnemonicIndex
if (JLabel.class.isAssignableFrom(aClass) &&
("displayedMnemonic".equals(name) || "displayedMnemonicIndex".equals(name))) { // skip JLabel#displayedMnemonic and JLabel#displayedMnemonicIndex
continue;
}
else {
@@ -710,6 +697,7 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
Condition<RadComponent> filter = null;
if (name.equals(SwingProperties.LABEL_FOR)) {
filter = new Condition<RadComponent>() {
@Override
public boolean value(final RadComponent t) {
ComponentItem item = getItem(t.getComponentClassName());
return item != null && item.isCanAttachLabel();
@@ -756,9 +744,9 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
* property with the such name.
*/
@Nullable
public IntrospectedProperty getIntrospectedProperty(@NotNull final RadComponent component, @NotNull final String name){
public IntrospectedProperty getIntrospectedProperty(@NotNull final RadComponent component, @NotNull final String name) {
final IntrospectedProperty[] properties = getIntrospectedProperties(component);
for (final IntrospectedProperty property: properties) {
for (final IntrospectedProperty property : properties) {
if (name.equals(property.getName())) {
return property;
}
@@ -768,7 +756,7 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
/**
* @return "inplace" property for the component with the specified class.
* <b>DO NOT USE THIS METHOD DIRECTLY</b>. Use {@link com.intellij.uiDesigner.radComponents.RadComponent#getInplaceProperty(int, int) }
* <b>DO NOT USE THIS METHOD DIRECTLY</b>. Use {@link RadComponent#getInplaceProperty(int, int) }
* instead.
*/
@Nullable
@@ -777,17 +765,17 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
final IntrospectedProperty[] properties = getIntrospectedProperties(component);
for (int i = properties.length - 1; i >= 0; i--) {
final IntrospectedProperty property = properties[i];
if(property.getName().equals(inplaceProperty)){
if (property.getName().equals(inplaceProperty)) {
return property;
}
}
return null;
}
public static boolean isRemovable(@NotNull final GroupItem group){
public static boolean isRemovable(@NotNull final GroupItem group) {
final ComponentItem[] items = group.getItems();
for(int i = items.length - 1; i >=0; i--){
if(!items [i].isRemovable()){
for (int i = items.length - 1; i >= 0; i--) {
if (!items[i].isRemovable()) {
return false;
}
}
@@ -797,12 +785,12 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
/**
* Updates UI of editors and renderers of all introspected properties
*/
private final class MyLafManagerListener implements LafManagerListener{
private void updateUI(final Property property){
private final class MyLafManagerListener implements LafManagerListener {
private void updateUI(final Property property) {
final PropertyRenderer renderer = property.getRenderer();
renderer.updateUI();
final PropertyEditor editor = property.getEditor();
if(editor != null){
if (editor != null) {
editor.updateUI();
}
final Property[] children = property.getChildren(null);
@@ -811,6 +799,7 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
}
}
@Override
public void lookAndFeelChanged(final LafManager source) {
for (final IntrospectedProperty[] properties : myClass2Properties.values()) {
LOG.assertTrue(properties != null);
@@ -821,7 +810,7 @@ public final class Palette implements Disposable, PersistentStateComponent<Eleme
}
}
static interface Listener{
interface Listener {
void groupsChanged(Palette palette);
}
}
+2 -1
View File
@@ -19,4 +19,5 @@ IntelliLang-js
IntelliLang-python
rest
python-rest
ipnb
ipnb
editorconfig
@@ -4,7 +4,7 @@ QuerySet is parametrized with model object
class QuerySet(object):
def __init__(self, model=None, query=None, using=None, hints=None):
"""
:rtype: django.db.models.QuerySet[T]
:rtype: django.db.models.query.QuerySet[T]
"""
pass
@@ -50,7 +50,7 @@ public class PyCondaPackageManagerImpl extends PyPackageManagerImpl {
@Override
public boolean hasManagement(boolean cachedOnly) throws ExecutionException {
return findCondaExecutable(mySdk) != null;
return isCondaVEnv(mySdk);
}
@Override
@@ -74,7 +74,7 @@ public class PyCondaPackageManagerImpl extends PyPackageManagerImpl {
}
private ProcessOutput getCondaOutput(@NotNull final String command, List<String> arguments) throws ExecutionException {
final String condaExecutable = findCondaExecutable(mySdk);
final String condaExecutable = PyCondaPackageService.getCondaExecutable();
final String path = getCondaDirectory();
if (path == null) throw new PyExecutionException("Empty conda name for " + mySdk, command, arguments);
@@ -109,6 +109,7 @@ public class PyCondaPackageManagerImpl extends PyPackageManagerImpl {
private String getCondaDirectory() {
final VirtualFile homeDirectory = mySdk.getHomeDirectory();
if (homeDirectory == null) return null;
if (SystemInfo.isWindows) return homeDirectory.getParent().getPath();
return homeDirectory.getParent().getParent().getPath();
}
@@ -147,7 +148,6 @@ public class PyCondaPackageManagerImpl extends PyPackageManagerImpl {
}
final String name = fields.get(0);
final String version = fields.get(1);
final String location = fields.get(2);
final List<PyRequirement> requirements = new ArrayList<PyRequirement>();
if (fields.size() >= 4) {
final String requiresLine = fields.get(3);
@@ -155,25 +155,24 @@ public class PyCondaPackageManagerImpl extends PyPackageManagerImpl {
requirements.addAll(PyRequirement.parse(requiresSpec));
}
if (!"Python".equals(name)) {
packages.add(new PyPackage(name, version, location, requirements));
packages.add(new PyPackage(name, version, "", requirements));
}
}
return packages;
}
@Nullable
public static String findCondaExecutable(Sdk sdk) {
final String condaName = SystemInfo.isWindows ? "conda.exe" : "conda";
public static boolean isCondaVEnv(Sdk sdk) {
final String condaName = "conda-meta";
final VirtualFile homeDirectory = sdk.getHomeDirectory();
if (homeDirectory == null) return null;
final VirtualFile condaExecutable = homeDirectory.getParent().findChild(condaName);
return condaExecutable != null ? condaExecutable.getPath() : null;
if (homeDirectory == null) return false;
final VirtualFile condaExecutable = SystemInfo.isWindows ? homeDirectory.getParent().findChild(condaName) :
homeDirectory.getParent().getParent().findChild(condaName);
return condaExecutable != null;
}
@NotNull
public static String createVirtualEnv(@NotNull String destinationDir, String version) throws ExecutionException {
final String condaName = SystemInfo.isWindows ? "conda.exe" : "conda";
final String condaExecutable = PyCondaPackageService.getCondaExecutable(condaName);
final String condaExecutable = PyCondaPackageService.getCondaExecutable();
if (condaExecutable == null) throw new PyExecutionException("Cannot find conda", "Conda", Collections.<String>emptyList(), new ProcessOutput());
final ArrayList<String> parameters = Lists.newArrayList(condaExecutable, "create", "-p", destinationDir,
@@ -79,12 +79,28 @@ public class PyCondaPackageService implements PersistentStateComponent<PyCondaPa
return CONDA_CHANNELS;
}
public void addChannel(@NotNull final String url) {
CONDA_CHANNELS.add(url);
}
public void removeChannel(@NotNull final String url) {
if (CONDA_CHANNELS.contains(url)) {
CONDA_CHANNELS.remove(url);
}
}
@Nullable
public static String getCondaPython() {
final String condaName = SystemInfo.isWindows ? "python.exe" : "python";
return getCondaExecutable(condaName);
}
@Nullable
public static String getCondaExecutable() {
final String condaName = SystemInfo.isWindows ? "conda.exe" : "conda";
return getCondaExecutable(condaName);
}
@Nullable
public static String getCondaExecutable(@NotNull final String condaName) {
final VirtualFile userHome = LocalFileSystem.getInstance().findFileByPath(SystemProperties.getUserHome().replace('\\', '/'));
@@ -113,11 +129,15 @@ public class PyCondaPackageService implements PersistentStateComponent<PyCondaPa
@Nullable
private static String findExecutable(String condaName, VirtualFile condaFolder) {
if (condaFolder != null) {
final VirtualFile bin = condaFolder.findChild("bin");
final VirtualFile bin = condaFolder.findChild(SystemInfo.isWindows ? "Scripts" : "bin");
if (bin != null) {
final VirtualFile[] children = bin.getChildren();
if (children.length == 0) return null;
final String executableFile = PythonSdkType.getExecutablePath(children[0].getPath(), condaName);
String directoryPath = bin.getPath();
if (!SystemInfo.isWindows) {
final VirtualFile[] children = bin.getChildren();
if (children.length == 0) return null;
directoryPath = children[0].getPath();
}
final String executableFile = PythonSdkType.getExecutablePath(directoryPath, condaName);
if (executableFile != null) {
return executableFile;
}
@@ -39,7 +39,7 @@ public class PyPackageManagersImpl extends PyPackageManagers {
if (PythonSdkType.isRemote(sdk)) {
manager = new PyRemotePackageManagerImpl(sdk);
}
else if (PyCondaPackageManagerImpl.findCondaExecutable(sdk) != null) {
else if (PyCondaPackageManagerImpl.isCondaVEnv(sdk)) {
manager = new PyCondaPackageManagerImpl(sdk);
}
else {
@@ -51,7 +51,7 @@ public class PyPackageManagersImpl extends PyPackageManagers {
}
public PyPackageManagementService getManagementService(Project project, Sdk sdk) {
if (PyCondaPackageManagerImpl.findCondaExecutable(sdk) != null) {
if (PyCondaPackageManagerImpl.isCondaVEnv(sdk)) {
return new PyCondaManagementService(project, sdk);
}
return new PyPackageManagementService(project, sdk);
@@ -15,10 +15,16 @@
*/
package com.jetbrains.python.packaging.ui;
import com.google.common.collect.Lists;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.CapturingProcessHandler;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.CatchingConsumer;
import com.intellij.webcore.packaging.InstalledPackage;
import com.intellij.webcore.packaging.PackageVersionComparator;
import com.intellij.webcore.packaging.RepoPackage;
import com.jetbrains.python.packaging.PyCondaPackageService;
@@ -29,7 +35,7 @@ import java.util.Collections;
import java.util.List;
public class PyCondaManagementService extends PyPackageManagementService {
private static final Logger LOG = Logger.getInstance(PyCondaManagementService.class);
public PyCondaManagementService(@NotNull final Project project, @NotNull final Sdk sdk) {
super(project, sdk);
}
@@ -59,6 +65,53 @@ public class PyCondaManagementService extends PyPackageManagementService {
return result;
}
@Override
public void addRepository(String repositoryUrl) {
final String conda = PyCondaPackageService.getCondaExecutable();
final ArrayList<String> parameters = Lists.newArrayList(conda, "config", "--add", "channels", repositoryUrl, "--force");
final GeneralCommandLine commandLine = new GeneralCommandLine(parameters);
try {
final Process process = commandLine.createProcess();
final CapturingProcessHandler handler = new CapturingProcessHandler(process);
final ProcessOutput result = handler.runProcess();
final int exitCode = result.getExitCode();
if (exitCode != 0) {
final String message = StringUtil.isEmptyOrSpaces(result.getStdout()) && StringUtil.isEmptyOrSpaces(result.getStderr()) ?
"Permission denied" : "Non-zero exit code";
LOG.warn("Failed to add repository " + message);
}
PyCondaPackageService.getInstance().addChannel(repositoryUrl);
}
catch (ExecutionException e) {
LOG.warn("Failed to add repository");
}
}
@Override
public void removeRepository(String repositoryUrl) {
final String conda = PyCondaPackageService.getCondaExecutable();
final ArrayList<String> parameters = Lists.newArrayList(conda, "config", "--remove", "channels", repositoryUrl, "--force");
final GeneralCommandLine commandLine = new GeneralCommandLine(parameters);
try {
final Process process = commandLine.createProcess();
final CapturingProcessHandler handler = new CapturingProcessHandler(process);
final ProcessOutput result = handler.runProcess();
final int exitCode = result.getExitCode();
if (exitCode != 0) {
final String message = StringUtil.isEmptyOrSpaces(result.getStdout()) && StringUtil.isEmptyOrSpaces(result.getStderr()) ?
"Permission denied" : "Non-zero exit code";
LOG.warn("Failed to remove repository " + message);
}
PyCondaPackageService.getInstance().removeChannel(repositoryUrl);
}
catch (ExecutionException e) {
LOG.warn("Failed to remove repository");
}
}
@Override
public boolean canInstallToUser() {
return false;
@@ -71,8 +124,4 @@ public class PyCondaManagementService extends PyPackageManagementService {
consumer.consume(versions);
}
@Override
public void uninstallPackages(List<InstalledPackage> installedPackages, Listener listener) {
super.uninstallPackages(installedPackages, listener);
}
}
@@ -128,7 +128,7 @@ public abstract class AbstractCreateVirtualEnvDialog extends IdeaDialog {
new LocationNameFieldsBinding(project, myDestination, myName, myInitialPath, "Select Location for Virtual Environment");
}
private void setInitialDestination() {
protected void setInitialDestination() {
myInitialPath = "";
final VirtualFile file = VirtualEnvSdkFlavor.getDefaultLocation();
@@ -20,9 +20,11 @@ import com.intellij.facet.ui.FacetValidatorsManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.CollectionComboBoxModel;
import com.intellij.ui.components.JBLabel;
import com.jetbrains.python.packaging.PyCondaPackageManagerImpl;
import com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor;
import com.jetbrains.python.validation.UnsupportedFeaturesUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -55,6 +57,14 @@ public class CreateCondaEnvDialog extends AbstractCreateVirtualEnvDialog {
checkValid();
}
@Override
protected void setInitialDestination() {
final List<VirtualFile> locations = VirtualEnvSdkFlavor.getCondaDefaultLocations();
if (!locations.isEmpty()) {
myInitialPath = locations.get(0).getPath();
}
}
protected void layoutPanel(final List<Sdk> allSdks) {
final GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
@@ -37,7 +37,6 @@ import com.intellij.openapi.ui.popup.ListSeparator;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.util.NullableConsumer;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.packaging.PyCondaPackageService;
@@ -110,8 +109,7 @@ public class PythonSdkDetailsStep extends BaseListPopupStep<String> {
options.add(REMOTE);
}
options.add(VIRTUALENV);
final String condaName = SystemInfo.isWindows ? "conda.exe" : "conda";
if (PyCondaPackageService.getCondaExecutable(condaName) != null) {
if (PyCondaPackageService.getCondaExecutable() != null) {
options.add(CONDA);
}
@@ -316,7 +316,7 @@ public class PythonSdkType extends SdkType {
public static boolean isCondaVirtualEnv(Sdk sdk) {
final String path = sdk.getHomePath();
return path != null && PyCondaPackageManagerImpl.findCondaExecutable(sdk) != null;
return path != null && PyCondaPackageManagerImpl.isCondaVEnv(sdk);
}
@Nullable