mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+1
-1
@@ -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" />
|
||||
|
||||
@@ -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" "$@"
|
||||
|
||||
@@ -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=""-Dgant.script=@{script}""/>
|
||||
<arg line=""-Dteamcity.build.tempDir=${tmp.dir}""/>
|
||||
<arg line=""-Didea.test.group=ALL_EXCLUDE_DEFINED""/>
|
||||
<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;
|
||||
}
|
||||
|
||||
+9
-3
@@ -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;
|
||||
|
||||
+22
-8
@@ -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
|
||||
|
||||
+18
-10
@@ -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
|
||||
|
||||
+10
-2
@@ -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) {
|
||||
|
||||
+9
-11
@@ -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();
|
||||
}
|
||||
|
||||
+15
@@ -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() {}
|
||||
}
|
||||
}
|
||||
+15
@@ -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);
|
||||
}
|
||||
|
||||
+1
-9
@@ -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
|
||||
|
||||
-7
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -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();
|
||||
}
|
||||
+3
-3
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -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);
|
||||
}
|
||||
|
||||
+9
-2
@@ -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
|
||||
|
||||
+6
-20
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-2
@@ -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);
|
||||
}
|
||||
|
||||
+3
-2
@@ -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) {
|
||||
|
||||
+3
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -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);
|
||||
}
|
||||
|
||||
-3
@@ -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);
|
||||
}
|
||||
|
||||
+15
-15
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+23
-2
@@ -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;
|
||||
|
||||
+22
-4
@@ -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;
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+2
-10
@@ -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;
|
||||
|
||||
+11
-4
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
+1
-1
@@ -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() {
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user