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:
@@ -20,7 +20,6 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
|
||||
import com.intellij.openapi.progress.util.ReadTask;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
@@ -93,7 +92,7 @@ public abstract class DefaultMessageHandler implements BuilderMessageHandler {
|
||||
protected abstract void handleBuildEvent(UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage.BuildEvent event);
|
||||
|
||||
private void handleConstantSearchTask(final Channel channel, final UUID sessionId, final CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask task) {
|
||||
ProgressIndicatorUtils.scheduleWithWriteActionPriority(new ProgressIndicatorBase(), myTaskExecutor, new ReadTask() {
|
||||
ProgressIndicatorUtils.scheduleWithWriteActionPriority(myTaskExecutor, new ReadTask() {
|
||||
@Override
|
||||
public Continuation runBackgroundProcess(@NotNull ProgressIndicator indicator) throws ProcessCanceledException {
|
||||
return DumbService.getInstance(myProject).runReadActionInSmartMode(new Computable<Continuation>() {
|
||||
|
||||
@@ -155,7 +155,7 @@ public class MethodCandidateInfo extends CandidateInfo{
|
||||
}
|
||||
return level;
|
||||
}
|
||||
}, substitutor);
|
||||
}, substitutor, isVarargs(), true);
|
||||
if (level > ApplicabilityLevel.NOT_APPLICABLE && !isTypeArgumentsApplicable(new Computable<PsiSubstitutor>() {
|
||||
@Override
|
||||
public PsiSubstitutor compute() {
|
||||
@@ -236,15 +236,17 @@ public class MethodCandidateInfo extends CandidateInfo{
|
||||
return true;
|
||||
}
|
||||
|
||||
private <T> T computeForOverloadedCandidate(final Computable<T> computable, final PsiSubstitutor substitutor) {
|
||||
private <T> T computeForOverloadedCandidate(final Computable<T> computable,
|
||||
final PsiSubstitutor substitutor,
|
||||
boolean varargs, boolean applicabilityCheck) {
|
||||
Map<PsiElement, CurrentCandidateProperties> map = CURRENT_CANDIDATE.get();
|
||||
if (map == null) {
|
||||
map = ContainerUtil.createConcurrentWeakMap();
|
||||
CURRENT_CANDIDATE.set(map);
|
||||
}
|
||||
final PsiElement argumentList = getMarkerList();
|
||||
final CurrentCandidateProperties alreadyThere = map.put(argumentList,
|
||||
new CurrentCandidateProperties(this, substitutor, isVarargs(), true));
|
||||
final CurrentCandidateProperties alreadyThere =
|
||||
map.put(argumentList, new CurrentCandidateProperties(this, substitutor, varargs, applicabilityCheck));
|
||||
try {
|
||||
return computable.compute();
|
||||
}
|
||||
@@ -369,40 +371,32 @@ public class MethodCandidateInfo extends CandidateInfo{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If iterated through all candidates, should be called under {@link #ourOverloadGuard} guard so results won't be cached on the top level call
|
||||
*/
|
||||
@NotNull
|
||||
public PsiSubstitutor inferTypeArguments(@NotNull ParameterTypeInferencePolicy policy,
|
||||
@NotNull PsiExpression[] arguments,
|
||||
public PsiSubstitutor inferTypeArguments(@NotNull final ParameterTypeInferencePolicy policy,
|
||||
@NotNull final PsiExpression[] arguments,
|
||||
boolean includeReturnConstraint) {
|
||||
Map<PsiElement, CurrentCandidateProperties> map = CURRENT_CANDIDATE.get();
|
||||
if (map == null) {
|
||||
map = ContainerUtil.createConcurrentWeakMap();
|
||||
CURRENT_CANDIDATE.set(map);
|
||||
}
|
||||
final PsiMethod method = getElement();
|
||||
final PsiElement argumentList = getMarkerList();
|
||||
final CurrentCandidateProperties alreadyThere =
|
||||
map.put(argumentList, new CurrentCandidateProperties(this, super.getSubstitutor(), policy.isVarargsIgnored() || isVarargs(), !includeReturnConstraint));
|
||||
try {
|
||||
PsiTypeParameter[] typeParameters = method.getTypeParameters();
|
||||
return computeForOverloadedCandidate(new Computable<PsiSubstitutor>() {
|
||||
@Override
|
||||
public PsiSubstitutor compute() {
|
||||
final PsiMethod method = MethodCandidateInfo.this.getElement();
|
||||
PsiTypeParameter[] typeParameters = method.getTypeParameters();
|
||||
|
||||
if (isRawSubstitution()) {
|
||||
return JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createRawSubstitutor(mySubstitutor, typeParameters);
|
||||
}
|
||||
if (MethodCandidateInfo.this.isRawSubstitution()) {
|
||||
return JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createRawSubstitutor(mySubstitutor, typeParameters);
|
||||
}
|
||||
|
||||
final PsiElement parent = getParent();
|
||||
if (parent == null) return PsiSubstitutor.EMPTY;
|
||||
Project project = method.getProject();
|
||||
JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project);
|
||||
return javaPsiFacade.getResolveHelper()
|
||||
.inferTypeArguments(typeParameters, method.getParameterList().getParameters(), arguments, mySubstitutor, parent, policy, myLanguageLevel);
|
||||
}
|
||||
finally {
|
||||
if (alreadyThere == null) {
|
||||
map.remove(argumentList);
|
||||
} else {
|
||||
map.put(argumentList, alreadyThere);
|
||||
final PsiElement parent = MethodCandidateInfo.this.getParent();
|
||||
if (parent == null) return PsiSubstitutor.EMPTY;
|
||||
Project project = method.getProject();
|
||||
JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project);
|
||||
return javaPsiFacade.getResolveHelper()
|
||||
.inferTypeArguments(typeParameters, method.getParameterList().getParameters(), arguments, mySubstitutor, parent, policy,
|
||||
myLanguageLevel);
|
||||
}
|
||||
}
|
||||
}, super.getSubstitutor(), policy.isVarargsIgnored() || isVarargs(), !includeReturnConstraint);
|
||||
}
|
||||
|
||||
private boolean isRawSubstitution() {
|
||||
|
||||
+17
-1
@@ -79,7 +79,7 @@ public class InferenceSessionContainer {
|
||||
});
|
||||
if (topLevelCall != null) {
|
||||
|
||||
final InferenceSession session;
|
||||
InferenceSession session;
|
||||
if (MethodCandidateInfo.isOverloadCheck() || !PsiDiamondType.ourDiamondGuard.currentStack().isEmpty() || LambdaUtil.isLambdaParameterCheck()) {
|
||||
session = startTopLevelInference(topLevelCall);
|
||||
}
|
||||
@@ -91,6 +91,22 @@ public class InferenceSessionContainer {
|
||||
return new Result<InferenceSession>(startTopLevelInference(topLevelCall), PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
});
|
||||
|
||||
if (session != null) {
|
||||
//reject cached top level session if it was based on wrong candidate: check nested session if candidate (it's type parameters) are the same
|
||||
//such situations are avoided when overload resolution is performed (MethodCandidateInfo.isOverloadCheck above)
|
||||
//but situations when client code iterates through PsiResolveHelper.getReferencedMethodCandidates or similar are impossible to guess
|
||||
final Map<PsiElement, InferenceSession> sessions = session.getInferenceSessionContainer().myNestedSessions;
|
||||
final InferenceSession childSession = sessions.get(parent);
|
||||
if (childSession != null) {
|
||||
for (PsiTypeParameter parameter : typeParameters) {
|
||||
if (!childSession.getInferenceSubstitution().getSubstitutionMap().containsKey(parameter)) {
|
||||
session = startTopLevelInference(topLevelCall);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (session != null) {
|
||||
|
||||
-3
@@ -134,9 +134,6 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
|
||||
checkPrimitiveVarargs(conflicts, getActualParametersLength());
|
||||
if (conflicts.size() == 1) return conflicts.get(0);
|
||||
|
||||
checkAccessStaticLevels(conflicts, false);
|
||||
if (conflicts.size() == 1) return conflicts.get(0);
|
||||
|
||||
Set<CandidateInfo> uniques = new THashSet<CandidateInfo>(conflicts);
|
||||
if (uniques.size() == 1) return uniques.iterator().next();
|
||||
return null;
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import java.util.function.Function;
|
||||
import java.util.*;
|
||||
|
||||
class Test {
|
||||
void m(Set<String> i) {
|
||||
final List<String> getters = new ArrayList<String>(ma<caret>p(i, new Function<String, String>() {
|
||||
@Override
|
||||
public String apply(String propertyName) {
|
||||
return propertyName;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
public static <T,V> List<V> map(Iterable<? extends T> iterable, Function<T, V> mapping) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T,V> List<V> map(Collection<? extends T> iterable, Function<T, V> mapping) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
class A<T> {
|
||||
public void testMethod(T... values) {}
|
||||
public void testMethod1(T values) {}
|
||||
}
|
||||
|
||||
class B extends A<Integer> {
|
||||
public static void testMethod(String... values) {}
|
||||
public static void testMethod1(String values) {}
|
||||
}
|
||||
|
||||
class Test45 {
|
||||
public static void main(String[] args) {
|
||||
B.testMethod<error descr="Ambiguous method call: both 'B.testMethod(String...)' and 'A.testMethod(Integer...)' match">()</error>;
|
||||
B.testMethod1<error descr="Ambiguous method call: both 'B.testMethod1(String)' and 'A.testMethod1(Integer)' match">(null)</error>;
|
||||
}
|
||||
}
|
||||
+20
@@ -20,6 +20,8 @@ import com.intellij.codeInsight.ExpectedTypesProvider;
|
||||
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -88,6 +90,24 @@ public class Java8ExpressionsCheckTest extends LightDaemonAnalyzerTestCase {
|
||||
doTestConfiguredFile(false, false, filePath);
|
||||
}
|
||||
|
||||
public void testRejectCachedTopLevelSessionIfItCorrespondsToTheWrongOverload() throws Exception {
|
||||
final String filePath = BASE_PATH + "/" + getTestName(false) + ".java";
|
||||
configureByFile(filePath);
|
||||
PsiMethodCallExpression methodCall =
|
||||
PsiTreeUtil.getParentOfType(getFile().findElementAt(getEditor().getCaretModel().getOffset()), PsiMethodCallExpression.class);
|
||||
assertNotNull(methodCall);
|
||||
final PsiResolveHelper helper = JavaPsiFacade.getInstance(methodCall.getProject()).getResolveHelper();
|
||||
CandidateInfo[] candidates = helper.getReferencedMethodCandidates(methodCall, false, true);
|
||||
for (CandidateInfo candidate : candidates) {
|
||||
if (candidate instanceof MethodCandidateInfo) {
|
||||
//try to cache top level session
|
||||
candidate.getSubstitutor();
|
||||
}
|
||||
}
|
||||
|
||||
doTestConfiguredFile(false, false, filePath);
|
||||
}
|
||||
|
||||
private void doTestCachedUnresolved() {
|
||||
configureByFile(BASE_PATH + "/" + getTestName(false) + ".java");
|
||||
PsiMethodCallExpression callExpression =
|
||||
|
||||
+4
@@ -225,6 +225,10 @@ public class OverloadResolutionTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIgnoreStaticCorrectnessDuringOverloadResolution() throws Exception {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(true);
|
||||
}
|
||||
|
||||
@@ -100,10 +100,6 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
|
||||
if (componentsRegistered != null) {
|
||||
componentsRegistered.run();
|
||||
}
|
||||
|
||||
if (indicator != null) {
|
||||
indicator.setIndeterminate(false);
|
||||
}
|
||||
createComponents(indicator);
|
||||
myComponentsCreated = true;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.intellij.openapi.actionSystem.ex.ActionUtil;
|
||||
import com.intellij.openapi.application.ApplicationInfo;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.TransactionGuard;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.help.HelpManager;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
@@ -1647,8 +1646,6 @@ public abstract class DialogWrapper {
|
||||
if (ApplicationManager.getApplication().isWriteAccessAllowed()) {
|
||||
LOG.error("Project-modal dialogs should not be shown under a write action.");
|
||||
}
|
||||
TransactionGuard.getInstance().assertInsideTransaction(
|
||||
false, "Project-modal dialogs should not be shown inside a transaction. See TransactionGuard documentation.");
|
||||
}
|
||||
|
||||
final AsyncResult<Boolean> result = new AsyncResult<Boolean>();
|
||||
|
||||
+10
-12
@@ -255,27 +255,25 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener
|
||||
}
|
||||
}
|
||||
|
||||
private double myProgressMaximum;
|
||||
private int myCurrentProgress;
|
||||
|
||||
private void initializeProgress() {
|
||||
private static void initializeProgress() {
|
||||
ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
|
||||
if (indicator != null) {
|
||||
indicator.setText(IdeBundle.message("loading.editors"));
|
||||
indicator.setText2("");
|
||||
indicator.setIndeterminate(false);
|
||||
indicator.setFraction(0);
|
||||
|
||||
myProgressMaximum = countFiles(mySplittersElement);
|
||||
myCurrentProgress = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int getEditorsCount() {
|
||||
return mySplittersElement == null ? 0 : countFiles(mySplittersElement);
|
||||
}
|
||||
|
||||
private double myProgressStep;
|
||||
|
||||
public void setProgressStep(double step) { myProgressStep = step; }
|
||||
|
||||
private void updateProgress() {
|
||||
ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
|
||||
if (indicator != null) {
|
||||
myCurrentProgress++;
|
||||
indicator.setFraction(myCurrentProgress / myProgressMaximum);
|
||||
indicator.setFraction(indicator.getFraction() + myProgressStep);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ class ProgressDialog implements Disposable {
|
||||
|
||||
if (myProgressBar.isShowing()) {
|
||||
final int perc = (int)(fraction * 100);
|
||||
myProgressBar.setIndeterminate(perc == 0 || myProgressWindow.isIndeterminate());
|
||||
myProgressBar.setIndeterminate(myProgressWindow.isIndeterminate());
|
||||
myProgressBar.setValue(perc);
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -66,6 +66,10 @@ public class ProgressIndicatorUtils {
|
||||
scheduleWithWriteActionPriority(progressIndicator, PooledThreadExecutor.INSTANCE, readTask);
|
||||
}
|
||||
|
||||
public static void scheduleWithWriteActionPriority(@NotNull Executor executor, @NotNull ReadTask task) {
|
||||
scheduleWithWriteActionPriority(new ProgressIndicatorBase(), executor, task);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #runInReadActionWithWriteActionPriority(Runnable)}, optionally allowing to pass a {@link ProgressIndicatorUtils}
|
||||
* instance, which can be used to cancel action externally.
|
||||
|
||||
@@ -415,4 +415,9 @@ public class ProgressWindow extends ProgressIndicatorBase implements BlockingPro
|
||||
myDialog.enableCancelButtonIfNeeded(enable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getTitle() + " " + System.identityHashCode(this) + ": running="+isRunning()+"; canceled="+isCanceled();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,11 @@ import com.intellij.openapi.components.impl.stores.StoreUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.impl.EditorsSplitters;
|
||||
import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.impl.ModuleManagerImpl;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
@@ -74,6 +79,7 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project
|
||||
private final AtomicBoolean mySavingInProgress = new AtomicBoolean(false);
|
||||
private String myName;
|
||||
private final boolean myLight;
|
||||
private static boolean ourClassesAreLoaded;
|
||||
|
||||
/**
|
||||
* @param filePath System-independent path
|
||||
@@ -276,22 +282,15 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project
|
||||
public void init() {
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
final ProgressIndicator progressIndicator = isDefault() ? null : ProgressIndicatorProvider.getGlobalProgressIndicator();
|
||||
if (progressIndicator != null) {
|
||||
progressIndicator.pushState();
|
||||
}
|
||||
try {
|
||||
init(progressIndicator);
|
||||
}
|
||||
finally {
|
||||
if (progressIndicator != null) {
|
||||
progressIndicator.popState();
|
||||
}
|
||||
}
|
||||
ProgressIndicator progressIndicator = isDefault() ? null : ProgressIndicatorProvider.getGlobalProgressIndicator();
|
||||
init(progressIndicator);
|
||||
|
||||
long time = System.currentTimeMillis() - start;
|
||||
LOG.info(getComponentConfigCount() + " project components initialized in " + time + " ms");
|
||||
|
||||
if (!isDefault()) {
|
||||
distributeProgress();
|
||||
}
|
||||
ApplicationManager.getApplication().getMessageBus().syncPublisher(ProjectLifecycleListener.TOPIC).projectComponentsInitialized(this);
|
||||
|
||||
//noinspection SynchronizeOnThis
|
||||
@@ -301,6 +300,33 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setProgressDuringInit(@NotNull ProgressIndicator indicator) {
|
||||
indicator.setFraction(getPercentageOfComponentsLoaded() / (ourClassesAreLoaded ? 10 : 2));
|
||||
}
|
||||
|
||||
private void distributeProgress() {
|
||||
ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
|
||||
if (indicator == null) return;
|
||||
|
||||
double toDistribute = 1 - indicator.getFraction();
|
||||
ModuleManagerImpl moduleManager = (ModuleManagerImpl)ModuleManager.getInstance(this);
|
||||
int modulesCount = moduleManager.getModulePathsCount();
|
||||
EditorsSplitters splitters = ((FileEditorManagerImpl)FileEditorManager.getInstance(this)).getMainSplitters();
|
||||
int editors = splitters.getEditorsCount();
|
||||
|
||||
double modulesPart = (ourClassesAreLoaded || editors == 0) ? toDistribute : toDistribute * 0.5;
|
||||
if (modulesCount != 0) {
|
||||
|
||||
double step = modulesPart / modulesCount;
|
||||
moduleManager.setProgressStep(step);
|
||||
}
|
||||
|
||||
if (editors != 0) {
|
||||
splitters.setProgressStep(toDistribute - modulesPart / editors);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
if (ApplicationManagerEx.getApplicationEx().isDoNotSave()) {
|
||||
@@ -359,6 +385,7 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project
|
||||
LOG.error(component.toString(), e);
|
||||
}
|
||||
}
|
||||
ourClassesAreLoaded = true;
|
||||
}
|
||||
|
||||
private void projectClosed() {
|
||||
|
||||
@@ -215,7 +215,6 @@ public class ProjectManagerImpl extends ProjectManagerEx implements Disposable {
|
||||
ProgressIndicator indicator = myProgressManager.getProgressIndicator();
|
||||
if (indicator != null && !project.isDefault()) {
|
||||
indicator.setText(ProjectBundle.message("loading.components.for", project.getName()));
|
||||
indicator.setIndeterminate(true);
|
||||
}
|
||||
|
||||
ApplicationManager.getApplication().getMessageBus().syncPublisher(ProjectLifecycleListener.TOPIC).beforeProjectLoaded(project);
|
||||
|
||||
+2
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,11 +28,4 @@ public class UpdateStrategyCustomization {
|
||||
public boolean forceEapUpdateChannelForEapBuilds() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the updater will allow patch updates to cross major version boundaries.
|
||||
*/
|
||||
public boolean allowMajorVersionUpdate() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
-22
@@ -23,8 +23,6 @@ import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.ui.ColorUtil;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.LicensingFacade;
|
||||
import com.intellij.util.text.DateFormatUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -33,7 +31,6 @@ import javax.swing.*;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import javax.swing.event.HyperlinkListener;
|
||||
import java.awt.*;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author anna
|
||||
@@ -76,25 +73,6 @@ public abstract class AbstractUpdateDialog extends DialogWrapper {
|
||||
app.invokeLater(() -> app.restart(true));
|
||||
}
|
||||
|
||||
protected void initLicensingInfo(@NotNull UpdateChannel channel, @SuppressWarnings("UnusedParameters") @NotNull BuildInfo build) {
|
||||
LicensingFacade facade = LicensingFacade.getInstance();
|
||||
if (facade != null) {
|
||||
if (channel.getLicensing().equals(UpdateChannel.LICENSING_EAP)) {
|
||||
myLicenseInfo = IdeBundle.message("updates.channel.bundled.key");
|
||||
}
|
||||
else {
|
||||
Date buildDate = build.getReleaseDate();
|
||||
Date expiration = facade.getLicenseExpirationDate();
|
||||
if (buildDate != null && facade.isPerpetualForProduct(buildDate)) {
|
||||
myLicenseInfo = IdeBundle.message("updates.fallback.build");
|
||||
}
|
||||
else if (expiration != null && expiration.after(new Date())) {
|
||||
myLicenseInfo = IdeBundle.message("updates.subscription.active.till", DateFormatUtil.formatAboutDialogDate(expiration));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void configureMessageArea(@NotNull JEditorPane area) {
|
||||
String messageBody = myEnableLink ? IdeBundle.message("updates.configure.label", ShowSettingsUtil.getSettingsMenuName()) : "";
|
||||
configureMessageArea(area, messageBody, null, null);
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 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.
|
||||
@@ -22,7 +22,7 @@ public enum ChannelStatus {
|
||||
EAP("eap", "Early Access Program"),
|
||||
MILESTONE("milestone", "Milestone Releases"),
|
||||
BETA("beta", "Beta Releases or Public Previews"),
|
||||
RELEASE("release", "New Major Version Releases");
|
||||
RELEASE("release", "Stable Releases");
|
||||
|
||||
private final String myCode;
|
||||
private final String myDisplayName;
|
||||
@@ -53,4 +53,4 @@ public enum ChannelStatus {
|
||||
public String toString() {
|
||||
return myDisplayName;
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
-38
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.updateSettings.impl;
|
||||
|
||||
import com.intellij.openapi.util.BuildNumber;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -22,61 +23,48 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class CheckForUpdateResult {
|
||||
private final BuildInfo myNewBuildInSelectedChannel;
|
||||
private final UpdateChannel myUpdatedChannel;
|
||||
private final UpdateChannel myChannelToPropose;
|
||||
private final List<String> myAllChannelIds;
|
||||
private final UpdateStrategy.State myState;
|
||||
private final BuildInfo myNewBuild;
|
||||
private final UpdateChannel myUpdatedChannel;
|
||||
private final Exception myError;
|
||||
|
||||
public CheckForUpdateResult(@Nullable BuildInfo newBuildInSelectedChannel,
|
||||
@Nullable UpdateChannel updated,
|
||||
@Nullable UpdateChannel channelToPropose,
|
||||
@NotNull List<String> allChannelsIds) {
|
||||
myNewBuildInSelectedChannel = newBuildInSelectedChannel;
|
||||
myUpdatedChannel = updated;
|
||||
myChannelToPropose = channelToPropose;
|
||||
myAllChannelIds = allChannelsIds;
|
||||
public CheckForUpdateResult(@Nullable BuildInfo newBuild, @Nullable UpdateChannel updatedChannel) {
|
||||
myState = UpdateStrategy.State.LOADED;
|
||||
myNewBuild = newBuild;
|
||||
myUpdatedChannel = updatedChannel;
|
||||
myError = null;
|
||||
}
|
||||
|
||||
public CheckForUpdateResult(@NotNull UpdateStrategy.State state, @Nullable Exception e) {
|
||||
myNewBuildInSelectedChannel = null;
|
||||
myUpdatedChannel = null;
|
||||
myChannelToPropose = null;
|
||||
myAllChannelIds = Collections.emptyList();
|
||||
myState = state;
|
||||
myNewBuild = null;
|
||||
myUpdatedChannel = null;
|
||||
myError = e;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BuildInfo getNewBuildInSelectedChannel() {
|
||||
return myNewBuildInSelectedChannel;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public UpdateChannel getUpdatedChannel() {
|
||||
return myUpdatedChannel;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public UpdateChannel getChannelToPropose() {
|
||||
return myChannelToPropose;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<String> getAllChannelsIds() {
|
||||
return myAllChannelIds;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public UpdateStrategy.State getState() {
|
||||
return myState;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BuildInfo getNewBuild() {
|
||||
return myNewBuild;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PatchInfo findPatchForBuild(@NotNull BuildNumber build) {
|
||||
List<PatchInfo> patches = myNewBuild != null ? myNewBuild.getPatches() : Collections.emptyList();
|
||||
return patches.stream().filter(p -> p.isAvailable() && p.getFromBuild().compareTo(build) == 0).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public UpdateChannel getUpdatedChannel() {
|
||||
return myUpdatedChannel;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Exception getError() {
|
||||
return myError;
|
||||
}
|
||||
}
|
||||
}
|
||||
-101
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.openapi.updateSettings.impl;
|
||||
|
||||
import com.intellij.ide.BrowserUtil;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.ui.BrowserHyperlinkListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
class NewChannelDialog extends AbstractUpdateDialog {
|
||||
private final UpdateChannel myChannel;
|
||||
private final BuildInfo myLatestBuild;
|
||||
|
||||
public NewChannelDialog(@NotNull UpdateChannel channel) {
|
||||
super(false);
|
||||
myChannel = channel;
|
||||
myLatestBuild = channel.getLatestBuild();
|
||||
assert myLatestBuild != null;
|
||||
|
||||
initLicensingInfo(myChannel, myLatestBuild);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
return new NewChannelPanel().myPanel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Action[] createActions() {
|
||||
return new Action[]{
|
||||
getOKAction(),
|
||||
|
||||
new AbstractAction(IdeBundle.message("updates.remind.later.button")) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
UpdateSettings.getInstance().forgetChannelId(myChannel.getId());
|
||||
doCancelAction();
|
||||
}
|
||||
},
|
||||
|
||||
getCancelAction()
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getOkButtonText() {
|
||||
return IdeBundle.message("updates.more.info.button");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCancelButtonText() {
|
||||
return IdeBundle.message("updates.ignore.update.button");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doOKAction() {
|
||||
BrowserUtil.browse(Objects.requireNonNull(myChannel.getHomePageUrl(), "missing URL for channel " + myChannel.getId()));
|
||||
super.doOKAction();
|
||||
}
|
||||
|
||||
private class NewChannelPanel {
|
||||
private JPanel myPanel;
|
||||
private JEditorPane myMessageArea;
|
||||
private JEditorPane myLicenseArea;
|
||||
|
||||
private NewChannelPanel() {
|
||||
String message = IdeBundle.message("updates.channel.name.message", myChannel.getName(), myLatestBuild.getMessage());
|
||||
configureMessageArea(myMessageArea, message, null, BrowserHyperlinkListener.INSTANCE);
|
||||
|
||||
if (myLicenseInfo != null) {
|
||||
configureMessageArea(myLicenseArea, myLicenseInfo, null, BrowserHyperlinkListener.INSTANCE);
|
||||
}
|
||||
else {
|
||||
myLicenseArea.setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.openapi.updateSettings.impl.NewChannelDialog.NewChannelPanel">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridBagLayout">
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="515" height="56"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="1f0d5" class="javax.swing.JEditorPane" binding="myMessageArea">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="150" height="50"/>
|
||||
</grid>
|
||||
<gridbag weightx="1.0" weighty="0.0"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<contentType value="text/html"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="63fa1" class="javax.swing.JEditorPane" binding="myLicenseArea">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="150" height="50"/>
|
||||
</grid>
|
||||
<gridbag top="10" left="0" bottom="0" right="0" weightx="0.0" weighty="0.0"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<contentType value="text/html"/>
|
||||
</properties>
|
||||
</component>
|
||||
<vspacer id="e7d5c">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
<gridbag weightx="0.0" weighty="0.0"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 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.
|
||||
@@ -26,7 +26,7 @@ import javax.swing.*;
|
||||
* @author pti
|
||||
*/
|
||||
class NoUpdatesDialog extends AbstractUpdateDialog {
|
||||
protected NoUpdatesDialog(boolean enableLink) {
|
||||
NoUpdatesDialog(boolean enableLink) {
|
||||
super(enableLink);
|
||||
init();
|
||||
}
|
||||
@@ -57,4 +57,4 @@ class NoUpdatesDialog extends AbstractUpdateDialog {
|
||||
configureMessageArea(myMessageArea);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -38,7 +38,7 @@ class PluginUpdateInfoDialog extends AbstractUpdateDialog {
|
||||
private final Collection<PluginDownloader> myUploadedPlugins;
|
||||
private final boolean myPlatformUpdate;
|
||||
|
||||
public PluginUpdateInfoDialog(Collection<PluginDownloader> uploadedPlugins, boolean enableLink) {
|
||||
PluginUpdateInfoDialog(Collection<PluginDownloader> uploadedPlugins, boolean enableLink) {
|
||||
super(enableLink);
|
||||
myUploadedPlugins = uploadedPlugins;
|
||||
myPlatformUpdate = false;
|
||||
|
||||
+14
-57
@@ -37,9 +37,7 @@ import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.progress.Task
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.ui.DialogWrapper
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.openapi.updateSettings.UpdateStrategyCustomization
|
||||
import com.intellij.openapi.util.ActionCallback
|
||||
import com.intellij.openapi.util.BuildNumber
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
@@ -56,7 +54,6 @@ import com.intellij.util.ui.UIUtil
|
||||
import com.intellij.xml.util.XmlStringUtil
|
||||
import org.apache.http.client.utils.URIBuilder
|
||||
import org.jdom.JDOMException
|
||||
import org.jetbrains.annotations.Contract
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.net.URISyntaxException
|
||||
@@ -133,9 +130,7 @@ object UpdateChecker {
|
||||
val result = checkPlatformUpdate(updateSettings)
|
||||
|
||||
if (manualCheck && result.state == UpdateStrategy.State.LOADED) {
|
||||
val settings = UpdateSettings.getInstance()
|
||||
settings.saveLastCheckedInfo()
|
||||
settings.setKnownChannelIds(result.allChannelsIds)
|
||||
UpdateSettings.getInstance().saveLastCheckedInfo()
|
||||
}
|
||||
else if (result.state == UpdateStrategy.State.CONNECTION_ERROR) {
|
||||
val e = result.error
|
||||
@@ -149,24 +144,16 @@ object UpdateChecker {
|
||||
|
||||
indicator?.text = IdeBundle.message("updates.checking.plugins")
|
||||
|
||||
val buildNumber: BuildNumber? = result.newBuild?.apiVersion
|
||||
val incompatiblePlugins: MutableCollection<IdeaPluginDescriptor>? = if (buildNumber != null) HashSet<IdeaPluginDescriptor>() else null
|
||||
|
||||
val updatedPlugins: Collection<PluginDownloader>?
|
||||
val incompatiblePlugins: MutableCollection<IdeaPluginDescriptor>?
|
||||
|
||||
if (newChannelReady(result.channelToPropose)) {
|
||||
updatedPlugins = null
|
||||
incompatiblePlugins = null
|
||||
try {
|
||||
updatedPlugins = checkPluginsUpdate(updateSettings, indicator, incompatiblePlugins, buildNumber)
|
||||
}
|
||||
else {
|
||||
val buildNumber: BuildNumber? = result.newBuildInSelectedChannel?.apiVersion
|
||||
|
||||
incompatiblePlugins = if (buildNumber != null) HashSet<IdeaPluginDescriptor>() else null
|
||||
try {
|
||||
updatedPlugins = checkPluginsUpdate(updateSettings, indicator, incompatiblePlugins, buildNumber)
|
||||
}
|
||||
catch (e: IOException) {
|
||||
showErrorMessage(manualCheck, IdeBundle.message("updates.error.connection.failed", e.message))
|
||||
return
|
||||
}
|
||||
catch (e: IOException) {
|
||||
showErrorMessage(manualCheck, IdeBundle.message("updates.error.connection.failed", e.message))
|
||||
return
|
||||
}
|
||||
|
||||
// show result
|
||||
@@ -215,10 +202,7 @@ object UpdateChecker {
|
||||
return CheckForUpdateResult(UpdateStrategy.State.NOTHING_LOADED, null)
|
||||
}
|
||||
|
||||
val appInfo = ApplicationInfo.getInstance()
|
||||
val majorVersion = Integer.parseInt(appInfo.majorVersion)
|
||||
val customization = UpdateStrategyCustomization.getInstance()
|
||||
val strategy = UpdateStrategy(majorVersion, appInfo.build, updateInfo, settings, customization)
|
||||
val strategy = UpdateStrategy(ApplicationInfo.getInstance().build, updateInfo, settings)
|
||||
return strategy.checkForUpdates()
|
||||
}
|
||||
|
||||
@@ -362,11 +346,6 @@ object UpdateChecker {
|
||||
}
|
||||
}
|
||||
|
||||
@Contract("null -> false")
|
||||
private fun newChannelReady(channelToPropose: UpdateChannel?): Boolean {
|
||||
return channelToPropose?.getLatestBuild() != null
|
||||
}
|
||||
|
||||
private fun showUpdateResult(project: Project?,
|
||||
checkForUpdateResult: CheckForUpdateResult,
|
||||
updateSettings: UpdateSettings,
|
||||
@@ -374,14 +353,14 @@ object UpdateChecker {
|
||||
incompatiblePlugins: Collection<IdeaPluginDescriptor>?,
|
||||
enableLink: Boolean,
|
||||
alwaysShowResults: Boolean) {
|
||||
val channelToPropose = checkForUpdateResult.channelToPropose
|
||||
val updatedChannel = checkForUpdateResult.updatedChannel
|
||||
val latestBuild = checkForUpdateResult.newBuildInSelectedChannel
|
||||
val newBuild = checkForUpdateResult.newBuild
|
||||
|
||||
if (updatedChannel != null && latestBuild != null) {
|
||||
if (updatedChannel != null && newBuild != null) {
|
||||
val runnable = {
|
||||
val patch = checkForUpdateResult.findPatchForBuild(ApplicationInfo.getInstance().build)
|
||||
val forceHttps = updateSettings.canUseSecureConnection()
|
||||
UpdateInfoDialog(updatedChannel, latestBuild, enableLink, forceHttps, updatedPlugins, incompatiblePlugins).show()
|
||||
UpdateInfoDialog(updatedChannel, newBuild, patch, enableLink, forceHttps, updatedPlugins, incompatiblePlugins).show()
|
||||
}
|
||||
|
||||
if (alwaysShowResults) {
|
||||
@@ -392,28 +371,6 @@ object UpdateChecker {
|
||||
showNotification(project, message, runnable, NotificationUniqueType.UPDATE_IN_CHANNEL)
|
||||
}
|
||||
}
|
||||
else if (newChannelReady(channelToPropose)) {
|
||||
val runnable = {
|
||||
val dialog = NewChannelDialog(channelToPropose!!)
|
||||
dialog.show()
|
||||
// once we informed that new product is available (when new channel was detected), remember the fact
|
||||
if (dialog.exitCode == DialogWrapper.CANCEL_EXIT_CODE &&
|
||||
checkForUpdateResult.state == UpdateStrategy.State.LOADED &&
|
||||
!updateSettings.knownChannelsIds.contains(channelToPropose.id)) {
|
||||
val newIds = ArrayList(updateSettings.knownChannelsIds)
|
||||
newIds.add(channelToPropose.id)
|
||||
updateSettings.setKnownChannelIds(newIds)
|
||||
}
|
||||
}
|
||||
|
||||
if (alwaysShowResults) {
|
||||
runnable.invoke()
|
||||
}
|
||||
else {
|
||||
val message = IdeBundle.message("updates.new.version.available", ApplicationNamesInfo.getInstance().fullProductName)
|
||||
showNotification(project, message, runnable, NotificationUniqueType.NEW_CHANNEL)
|
||||
}
|
||||
}
|
||||
else if (updatedPlugins != null && !updatedPlugins.isEmpty()) {
|
||||
val runnable = { PluginUpdateInfoDialog(updatedPlugins, enableLink).show() }
|
||||
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
*/
|
||||
package com.intellij.openapi.updateSettings.impl
|
||||
|
||||
import com.intellij.openapi.application.ApplicationInfo
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.util.BuildNumber
|
||||
import com.intellij.openapi.util.BuildRange
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import org.jdom.Element
|
||||
import org.jdom.JDOMException
|
||||
@@ -27,23 +27,15 @@ import java.util.*
|
||||
|
||||
class UpdatesInfo(node: Element) {
|
||||
private val products = node.getChildren("product").map { Product(it) }
|
||||
|
||||
val productsCount: Int
|
||||
get() = products.size
|
||||
|
||||
fun getProduct(code: String): Product? = products.find { it.hasCode(code) }
|
||||
operator fun get(code: String): Product? = products.find { code in it.codes }
|
||||
}
|
||||
|
||||
class Product(node: Element) {
|
||||
val name: String = node.getAttributeValue("name") ?: throw JDOMException("product.name missing")
|
||||
val name: String = node.getAttributeValue("name") ?: throw JDOMException("product@name missing")
|
||||
val codes: Set<String> = node.getChildren("code").map { it.value.trim() }.toSet()
|
||||
val channels: List<UpdateChannel> = node.getChildren("channel").map { UpdateChannel(it) }
|
||||
private val codes = node.getChildren("code").map { it.value.trim() }.toSet()
|
||||
|
||||
fun hasCode(code: String): Boolean = codes.contains(code)
|
||||
|
||||
fun findUpdateChannelById(id: String): UpdateChannel? = channels.find { it.id == id }
|
||||
|
||||
fun getAllChannelIds(): List<String> = channels.map { it.id }
|
||||
override fun toString() = codes.firstOrNull() ?: "-"
|
||||
}
|
||||
|
||||
class UpdateChannel(node: Element) {
|
||||
@@ -52,74 +44,50 @@ class UpdateChannel(node: Element) {
|
||||
const val LICENSING_PRODUCTION = "production"
|
||||
}
|
||||
|
||||
val id: String = node.getAttributeValue("id") ?: throw JDOMException("channel.id missing")
|
||||
val name: String = node.getAttributeValue("name") ?: throw JDOMException("channel.name missing")
|
||||
val id: String = node.getAttributeValue("id") ?: throw JDOMException("channel@id missing")
|
||||
val status: ChannelStatus = ChannelStatus.fromCode(node.getAttributeValue("status"))
|
||||
val licensing: String = node.getAttributeValue("licensing", LICENSING_PRODUCTION)
|
||||
val majorVersion: Int = node.getAttributeValue("majorVersion")?.toInt() ?: -1
|
||||
val homePageUrl: String? = node.getAttributeValue("url")
|
||||
val feedbackUrl: String? = node.getAttributeValue("feedback")
|
||||
val evalDays: Int = node.getAttributeValue("evalDays")?.toInt() ?: 30
|
||||
private val builds = node.getChildren("build").map { BuildInfo(it) }
|
||||
val builds: List<BuildInfo> = node.getChildren("build").map { BuildInfo(it) }
|
||||
|
||||
fun getLatestBuild(): BuildInfo? = latestBuild(builds)
|
||||
fun getLatestBuild(baseline: Int): BuildInfo? = latestBuild(builds.filter { it.number.baselineVersion == baseline })
|
||||
|
||||
private fun latestBuild(builds: List<BuildInfo>) =
|
||||
builds.fold(null as BuildInfo?) { best, candidate -> if (best == null || best.compareTo(candidate) < 0) candidate else best }
|
||||
override fun toString() = id
|
||||
}
|
||||
|
||||
class BuildInfo(node: Element) : Comparable<BuildInfo> {
|
||||
val number: BuildNumber = BuildNumber.fromString(node.getAttributeValue("number") ?: throw JDOMException("build.number missing"))
|
||||
val apiVersion: BuildNumber = node.getAttributeValue("apiVersion")?.let { BuildNumber.fromString(it, number.productCode) } ?: number
|
||||
class BuildInfo(node: Element) {
|
||||
val number: BuildNumber = BuildNumber.fromString(node.getAttributeValue("number") ?: throw JDOMException("build@number missing"))
|
||||
val apiVersion: BuildNumber = BuildNumber.fromString(node.getAttributeValue("apiVersion"), number.productCode) ?: number
|
||||
val version: String = node.getAttributeValue("version") ?: ""
|
||||
val message: String = node.getChild("message")?.value ?: ""
|
||||
val releaseDate: Date? = node.getAttributeValue("releaseDate")?.let {
|
||||
try { SimpleDateFormat("yyyyMMdd", Locale.US).parse(it) } // same as the 'majorReleaseDate' in ApplicationInfo.xml
|
||||
val releaseDate: Date? = parseDate(node.getAttributeValue("releaseDate"))
|
||||
val target: BuildRange? = BuildRange.fromStrings(node.getAttributeValue("targetSince"), node.getAttributeValue("targetUntil"))
|
||||
val buttons: List<ButtonInfo> = node.getChildren("button").map { ButtonInfo(it) }
|
||||
val patches: List<PatchInfo> = node.getChildren("patch").map { PatchInfo(it) }
|
||||
|
||||
private fun parseDate(value: String?): Date? = value?.let {
|
||||
try {
|
||||
SimpleDateFormat("yyyyMMdd", Locale.US).parse(it) // same as the 'majorReleaseDate' in ApplicationInfo.xml
|
||||
}
|
||||
catch (e: ParseException) {
|
||||
Logger.getInstance(BuildInfo::class.java).info("Failed to parse build release date " + it)
|
||||
null
|
||||
}
|
||||
}
|
||||
val buttons: List<ButtonInfo> = node.getChildren("button").map { ButtonInfo(it) }
|
||||
private val patches = node.getChildren("patch").map { PatchInfo(it) }
|
||||
|
||||
/**
|
||||
* Returns -1 if version information is missing or does not match to expected format "majorVer.minorVer"
|
||||
*/
|
||||
val majorVersion: Int
|
||||
get() {
|
||||
val dotIndex = version.indexOf('.')
|
||||
if (dotIndex > 0) {
|
||||
try {
|
||||
return version.substring(0, dotIndex).toInt()
|
||||
}
|
||||
catch (ignored: NumberFormatException) { }
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
fun findPatchForCurrentBuild(): PatchInfo? = findPatchForBuild(ApplicationInfo.getInstance().build)
|
||||
|
||||
fun findPatchForBuild(currentBuild: BuildNumber): PatchInfo? =
|
||||
patches.find { it.isAvailable && it.fromBuild.asStringWithoutProductCode() == currentBuild.asStringWithoutProductCode() }
|
||||
|
||||
override fun compareTo(other: BuildInfo): Int = number.compareTo(other.number)
|
||||
|
||||
override fun toString(): String = "BuildInfo(number=$number)"
|
||||
override fun toString() = "${number}/${version}"
|
||||
}
|
||||
|
||||
class ButtonInfo(node: Element) {
|
||||
val name: String = node.getAttributeValue("name") ?: throw JDOMException("button.name missing")
|
||||
val url: String = node.getAttributeValue("url") ?: throw JDOMException("button.url missing")
|
||||
val name: String = node.getAttributeValue("name") ?: throw JDOMException("button@name missing")
|
||||
val url: String = node.getAttributeValue("url") ?: throw JDOMException("button@url missing")
|
||||
val isDownload: Boolean = node.getAttributeValue("download") != null // a button marked with this attribute is hidden when a patch is available
|
||||
|
||||
override fun toString() = name
|
||||
}
|
||||
|
||||
class PatchInfo(node: Element) {
|
||||
val fromBuild: BuildNumber = BuildNumber.fromString(node.getAttributeValue("from") ?: throw JDOMException("patch.from missing"))
|
||||
val fromBuild: BuildNumber = BuildNumber.fromString(node.getAttributeValue("from") ?: throw JDOMException("patch@from missing"))
|
||||
val size: String? = node.getAttributeValue("size")
|
||||
val isAvailable: Boolean = node.getAttributeValue("exclusions")?.split(",")?.none { it.trim() == osSuffix } ?: true
|
||||
val isAvailable: Boolean = node.getAttributeValue("exclusions")?.splitToSequence(",")?.none { it.trim() == osSuffix } ?: true
|
||||
|
||||
val osSuffix: String
|
||||
get() = if (SystemInfo.isWindows) "win" else if (SystemInfo.isMac) "mac" else if (SystemInfo.isUnix) "unix" else "unknown"
|
||||
|
||||
+39
-15
@@ -29,16 +29,20 @@ import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.BrowserHyperlinkListener;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.LicensingFacade;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.text.DateFormatUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -48,25 +52,26 @@ class UpdateInfoDialog extends AbstractUpdateDialog {
|
||||
private final UpdateChannel myUpdatedChannel;
|
||||
private final boolean myForceHttps;
|
||||
private final Collection<PluginDownloader> myUpdatedPlugins;
|
||||
private final BuildInfo myLatestBuild;
|
||||
private final BuildInfo myNewBuild;
|
||||
private final PatchInfo myPatch;
|
||||
private final boolean myWriteProtected;
|
||||
|
||||
protected UpdateInfoDialog(@NotNull UpdateChannel channel,
|
||||
@NotNull BuildInfo latestBuild,
|
||||
boolean enableLink,
|
||||
boolean forceHttps,
|
||||
Collection<PluginDownloader> updatedPlugins,
|
||||
Collection<IdeaPluginDescriptor> incompatiblePlugins) {
|
||||
UpdateInfoDialog(@NotNull UpdateChannel channel,
|
||||
@NotNull BuildInfo newBuild,
|
||||
@Nullable PatchInfo patch,
|
||||
boolean enableLink,
|
||||
boolean forceHttps,
|
||||
Collection<PluginDownloader> updatedPlugins,
|
||||
Collection<IdeaPluginDescriptor> incompatiblePlugins) {
|
||||
super(enableLink);
|
||||
myUpdatedChannel = channel;
|
||||
myForceHttps = forceHttps;
|
||||
myUpdatedPlugins = updatedPlugins;
|
||||
myLatestBuild = latestBuild;
|
||||
myPatch = myLatestBuild.findPatchForCurrentBuild();
|
||||
myNewBuild = newBuild;
|
||||
myPatch = patch;
|
||||
myWriteProtected = myPatch != null && !new File(PathManager.getHomePath()).canWrite();
|
||||
getCancelAction().putValue(DEFAULT_ACTION, Boolean.TRUE);
|
||||
initLicensingInfo(myUpdatedChannel, myLatestBuild);
|
||||
initLicensingInfo(myUpdatedChannel, myNewBuild);
|
||||
init();
|
||||
|
||||
if (incompatiblePlugins != null && !incompatiblePlugins.isEmpty()) {
|
||||
@@ -80,6 +85,25 @@ class UpdateInfoDialog extends AbstractUpdateDialog {
|
||||
}
|
||||
}
|
||||
|
||||
private void initLicensingInfo(@NotNull UpdateChannel channel, @NotNull BuildInfo build) {
|
||||
LicensingFacade facade = LicensingFacade.getInstance();
|
||||
if (facade != null) {
|
||||
if (channel.getLicensing().equals(UpdateChannel.LICENSING_EAP)) {
|
||||
myLicenseInfo = IdeBundle.message("updates.channel.bundled.key");
|
||||
}
|
||||
else {
|
||||
Date buildDate = build.getReleaseDate();
|
||||
Date expiration = facade.getLicenseExpirationDate();
|
||||
if (buildDate != null && facade.isPerpetualForProduct(buildDate)) {
|
||||
myLicenseInfo = IdeBundle.message("updates.fallback.build");
|
||||
}
|
||||
else if (expiration != null && expiration.after(new Date())) {
|
||||
myLicenseInfo = IdeBundle.message("updates.subscription.active.till", DateFormatUtil.formatAboutDialogDate(expiration));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
return new UpdateInfoPanel().myPanel;
|
||||
@@ -105,7 +129,7 @@ class UpdateInfoDialog extends AbstractUpdateDialog {
|
||||
});
|
||||
}
|
||||
|
||||
List<ButtonInfo> buttons = myLatestBuild.getButtons();
|
||||
List<ButtonInfo> buttons = myNewBuild.getButtons();
|
||||
if (buttons.isEmpty()) {
|
||||
actions.add(new AbstractAction(IdeBundle.message("updates.more.info.button")) {
|
||||
@Override
|
||||
@@ -125,7 +149,7 @@ class UpdateInfoDialog extends AbstractUpdateDialog {
|
||||
actions.add(new AbstractAction(IdeBundle.message("updates.ignore.update.button")) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String build = myLatestBuild.getNumber().asStringWithoutProductCode();
|
||||
String build = myNewBuild.getNumber().asStringWithoutProductCode();
|
||||
UpdateSettings.getInstance().getIgnoredBuildNumbers().add(build);
|
||||
doCancelAction();
|
||||
}
|
||||
@@ -143,7 +167,7 @@ class UpdateInfoDialog extends AbstractUpdateDialog {
|
||||
|
||||
private void downloadPatchAndRestart() {
|
||||
try {
|
||||
UpdateChecker.installPlatformUpdate(myPatch, myLatestBuild.getNumber(), myForceHttps);
|
||||
UpdateChecker.installPlatformUpdate(myPatch, myNewBuild.getNumber(), myForceHttps);
|
||||
|
||||
if (myUpdatedPlugins != null && !myUpdatedPlugins.isEmpty()) {
|
||||
new PluginUpdateInfoDialog(getContentPanel(), myUpdatedPlugins).show();
|
||||
@@ -196,7 +220,7 @@ class UpdateInfoDialog extends AbstractUpdateDialog {
|
||||
ApplicationInfo appInfo = ApplicationInfo.getInstance();
|
||||
ApplicationNamesInfo appNames = ApplicationNamesInfo.getInstance();
|
||||
|
||||
String message = myLatestBuild.getMessage();
|
||||
String message = myNewBuild.getMessage();
|
||||
final String fullProductName = appNames.getFullProductName();
|
||||
if (StringUtil.isEmpty(message)) {
|
||||
message = IdeBundle.message("updates.new.version.available", fullProductName);
|
||||
@@ -217,7 +241,7 @@ class UpdateInfoDialog extends AbstractUpdateDialog {
|
||||
appInfo.getBuild().asStringWithoutProductCode()
|
||||
)
|
||||
);
|
||||
myNewVersion.setText(formatVersion(myLatestBuild.getVersion(), myLatestBuild.getNumber().asStringWithoutProductCode()));
|
||||
myNewVersion.setText(formatVersion(myNewBuild.getVersion(), myNewBuild.getNumber().asStringWithoutProductCode()));
|
||||
|
||||
if (myPatch != null && !StringUtil.isEmptyOrSpaces(myPatch.getSize())) {
|
||||
myPatchInfo.setText(myPatch.getSize() + " MB");
|
||||
|
||||
+2
-16
@@ -38,7 +38,6 @@ import java.util.List;
|
||||
public class UpdateSettings implements PersistentStateComponent<UpdateSettings.State>, UserUpdateSettings {
|
||||
public static class State {
|
||||
@CollectionBean public final List<String> pluginHosts = new SmartList<String>();
|
||||
@CollectionBean public final List<String> knownUpdateChannels = new SmartList<String>();
|
||||
@CollectionBean public final List<String> ignoredBuildNumbers = new SmartList<String>();
|
||||
|
||||
public boolean CHECK_NEEDED = true;
|
||||
@@ -98,21 +97,6 @@ public class UpdateSettings implements PersistentStateComponent<UpdateSettings.S
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getKnownChannelsIds() {
|
||||
return new ArrayList<String>(myState.knownUpdateChannels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setKnownChannelIds(@NotNull List<String> ids) {
|
||||
myState.knownUpdateChannels.clear();
|
||||
myState.knownUpdateChannels.addAll(ids);
|
||||
}
|
||||
|
||||
public void forgetChannelId(String id) {
|
||||
myState.knownUpdateChannels.remove(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getIgnoredBuildNumbers() {
|
||||
return myState.ignoredBuildNumbers;
|
||||
@@ -150,6 +134,7 @@ public class UpdateSettings implements PersistentStateComponent<UpdateSettings.S
|
||||
return myState.SECURE_CONNECTION && NetUtils.isSniEnabled();
|
||||
}
|
||||
|
||||
//<editor-fold desc="Deprecated stuff.">
|
||||
/** @deprecated use {@link #getSelectedChannelStatus()} (to be removed in IDEA 17) */
|
||||
@SuppressWarnings("unused")
|
||||
public String getUpdateChannelType() {
|
||||
@@ -161,4 +146,5 @@ public class UpdateSettings implements PersistentStateComponent<UpdateSettings.S
|
||||
public void setUpdateChannelType(@NotNull String value) {
|
||||
myState.UPDATE_CHANNEL_TYPE = value;
|
||||
}
|
||||
//</editor-fold>
|
||||
}
|
||||
+24
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,8 @@ package com.intellij.openapi.updateSettings.impl;
|
||||
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationInfo;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -26,11 +28,14 @@ import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.options.SearchableConfigurable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.updateSettings.UpdateStrategyCustomization;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.CollectionComboBoxModel;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.ui.components.labels.ActionLink;
|
||||
import com.intellij.util.net.NetUtils;
|
||||
import com.intellij.util.text.DateFormatUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -40,6 +45,7 @@ import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author pti
|
||||
@@ -146,13 +152,14 @@ public class UpdateSettingsConfigurable extends BaseConfigurable implements Sear
|
||||
private final UpdateSettings mySettings;
|
||||
private JPanel myPanel;
|
||||
private JCheckBox myCheckForUpdates;
|
||||
private JComboBox myUpdateChannels;
|
||||
private JComboBox<ChannelStatus> myUpdateChannels;
|
||||
private JButton myCheckNow;
|
||||
private JBLabel myChannelWarning;
|
||||
private JCheckBox myUseSecureConnection;
|
||||
private JLabel myBuildNumber;
|
||||
private JLabel myVersionNumber;
|
||||
private JLabel myLastCheckedDate;
|
||||
@SuppressWarnings("unused") private ActionLink myIgnoredBuildsLink;
|
||||
|
||||
public UpdatesSettingsPanel(boolean checkNowEnabled) {
|
||||
mySettings = UpdateSettings.getInstance();
|
||||
@@ -207,6 +214,21 @@ public class UpdateSettingsConfigurable extends BaseConfigurable implements Sear
|
||||
myChannelWarning.setForeground(JBColor.RED);
|
||||
}
|
||||
|
||||
private void createUIComponents() {
|
||||
myIgnoredBuildsLink = new ActionLink(IdeBundle.message("updates.settings.ignored"), new AnAction() {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
List<String> buildNumbers = mySettings.getIgnoredBuildNumbers();
|
||||
String text = StringUtil.join(buildNumbers, "\n");
|
||||
String result = Messages.showMultilineInputDialog(null, null, IdeBundle.message("updates.settings.ignored.title"), text, null, null);
|
||||
if (result != null) {
|
||||
buildNumbers.clear();
|
||||
buildNumbers.addAll(StringUtil.split(result, "\n"));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateLastCheckedLabel() {
|
||||
long time = mySettings.getLastTimeChecked();
|
||||
myLastCheckedDate.setText(time == 0 ? IdeBundle.message("updates.last.check.never") : DateFormatUtil.formatPrettyDateTime(time));
|
||||
|
||||
-125
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.openapi.updateSettings.impl;
|
||||
|
||||
import com.intellij.openapi.updateSettings.UpdateStrategyCustomization;
|
||||
import com.intellij.openapi.util.BuildNumber;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class UpdateStrategy {
|
||||
public enum State {LOADED, CONNECTION_ERROR, NOTHING_LOADED}
|
||||
|
||||
private final int myMajorVersion;
|
||||
private final BuildNumber myCurrentBuild;
|
||||
private final UpdatesInfo myUpdatesInfo;
|
||||
private final UserUpdateSettings myUpdateSettings;
|
||||
private final ChannelStatus myChannelStatus;
|
||||
private final UpdateStrategyCustomization myStrategyCustomization;
|
||||
|
||||
/** @deprecated use {@link #UpdateStrategy(int, BuildNumber, UpdatesInfo, UserUpdateSettings, UpdateStrategyCustomization)} */
|
||||
@SuppressWarnings("unused")
|
||||
public UpdateStrategy(int majorVersion,
|
||||
@NotNull BuildNumber currentBuild,
|
||||
@NotNull UpdatesInfo updatesInfo,
|
||||
@NotNull UserUpdateSettings updateSettings) {
|
||||
this(majorVersion, currentBuild, updatesInfo, updateSettings, UpdateStrategyCustomization.getInstance());
|
||||
}
|
||||
|
||||
public UpdateStrategy(int majorVersion,
|
||||
@NotNull BuildNumber currentBuild,
|
||||
@NotNull UpdatesInfo updatesInfo,
|
||||
@NotNull UserUpdateSettings updateSettings,
|
||||
@NotNull UpdateStrategyCustomization customization) {
|
||||
myMajorVersion = majorVersion;
|
||||
myCurrentBuild = currentBuild;
|
||||
myUpdatesInfo = updatesInfo;
|
||||
myUpdateSettings = updateSettings;
|
||||
myChannelStatus = updateSettings.getSelectedChannelStatus();
|
||||
myStrategyCustomization = customization;
|
||||
}
|
||||
|
||||
public final CheckForUpdateResult checkForUpdates() {
|
||||
Product product = myUpdatesInfo.getProduct(myCurrentBuild.getProductCode());
|
||||
|
||||
if (product == null || product.getChannels().isEmpty()) {
|
||||
return new CheckForUpdateResult(State.NOTHING_LOADED, null);
|
||||
}
|
||||
|
||||
UpdateChannel updatedChannel = null;
|
||||
BuildInfo newBuild = null;
|
||||
List<UpdateChannel> activeChannels = getActiveChannels(product);
|
||||
for (UpdateChannel channel : activeChannels) {
|
||||
BuildInfo latestBuild = channel.getLatestBuild(myCurrentBuild.getBaselineVersion());
|
||||
if (latestBuild == null || latestBuild.getNumber().compareTo(myCurrentBuild) <= 0) {
|
||||
latestBuild = channel.getLatestBuild();
|
||||
}
|
||||
if (isNewVersion(latestBuild)) {
|
||||
updatedChannel = channel;
|
||||
newBuild = latestBuild;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateChannel channelToPropose = null;
|
||||
for (UpdateChannel channel : product.getChannels()) {
|
||||
if (!myUpdateSettings.getKnownChannelsIds().contains(channel.getId()) &&
|
||||
channel.getMajorVersion() >= myMajorVersion &&
|
||||
channel.getStatus().compareTo(myChannelStatus) >= 0 &&
|
||||
isNewVersion(channel.getLatestBuild()) &&
|
||||
(channelToPropose == null || isBetter(channelToPropose, channel))) {
|
||||
channelToPropose = channel;
|
||||
}
|
||||
}
|
||||
|
||||
return new CheckForUpdateResult(newBuild, updatedChannel, channelToPropose, product.getAllChannelIds());
|
||||
}
|
||||
|
||||
private List<UpdateChannel> getActiveChannels(Product product) {
|
||||
List<UpdateChannel> result = new ArrayList<UpdateChannel>();
|
||||
|
||||
for (UpdateChannel channel : product.getChannels()) {
|
||||
// If the update is to a new version and on a stabler channel, choose it.
|
||||
if ((channel.getMajorVersion() >= myMajorVersion && channel.getStatus().compareTo(myChannelStatus) >= 0) &&
|
||||
(myStrategyCustomization.allowMajorVersionUpdate() ||
|
||||
channel.getMajorVersion() == myMajorVersion ||
|
||||
channel.getStatus() == ChannelStatus.EAP && myChannelStatus == ChannelStatus.EAP)) {
|
||||
// Prefer channel that has same status as our selected channel status
|
||||
if (channel.getMajorVersion() == myMajorVersion && channel.getStatus().compareTo(myChannelStatus) == 0) {
|
||||
result.add(0, channel);
|
||||
}
|
||||
else {
|
||||
result.add(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isNewVersion(BuildInfo latestBuild) {
|
||||
return latestBuild != null &&
|
||||
!myUpdateSettings.getIgnoredBuildNumbers().contains(latestBuild.getNumber().asStringWithoutProductCode()) &&
|
||||
myCurrentBuild.compareTo(latestBuild.getNumber()) < 0;
|
||||
}
|
||||
|
||||
private static boolean isBetter(UpdateChannel channelToPropose, UpdateChannel channel) {
|
||||
return channel.getMajorVersion() > channelToPropose.getMajorVersion() ||
|
||||
channel.getMajorVersion() == channelToPropose.getMajorVersion() && channel.getStatus().compareTo(channelToPropose.getStatus()) > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.openapi.updateSettings.impl
|
||||
|
||||
import com.intellij.openapi.updateSettings.UpdateStrategyCustomization
|
||||
import com.intellij.openapi.util.BuildNumber
|
||||
|
||||
class UpdateStrategy(private val currentBuild: BuildNumber, private val updates: UpdatesInfo, private val settings: UserUpdateSettings) {
|
||||
enum class State {
|
||||
LOADED, CONNECTION_ERROR, NOTHING_LOADED
|
||||
}
|
||||
|
||||
fun checkForUpdates(): CheckForUpdateResult {
|
||||
val product = updates[currentBuild.productCode]
|
||||
if (product == null || product.channels.isEmpty()) {
|
||||
return CheckForUpdateResult(State.NOTHING_LOADED, null)
|
||||
}
|
||||
|
||||
val selectedChannel = settings.selectedChannelStatus
|
||||
val ignoredBuilds = settings.ignoredBuildNumbers.toSet()
|
||||
|
||||
val result = product.channels.asSequence()
|
||||
.filter { ch -> ch.status >= selectedChannel } // filter out inapplicable channels
|
||||
.sortedBy { ch -> ch.status } // sort by stability, asc
|
||||
.map { ch -> ch.builds.asSequence().filter { build -> isApplicable(build, ignoredBuilds) } to ch } // filter out inapplicable builds
|
||||
.map { p -> maxBuild(p.first) to p.second } // max build in a channel, preferring same baseline
|
||||
.filter { p -> p.first != null }
|
||||
.maxBy { p -> p.first!!.number }
|
||||
|
||||
return CheckForUpdateResult(result?.first, result?.second)
|
||||
}
|
||||
|
||||
private fun isApplicable(candidate: BuildInfo, ignoredBuilds: Set<String>) =
|
||||
candidate.number > currentBuild &&
|
||||
candidate.number.asStringWithoutProductCode() !in ignoredBuilds &&
|
||||
candidate.target?.inRange(currentBuild) ?: true
|
||||
|
||||
private fun maxBuild(builds: Sequence<BuildInfo>) =
|
||||
builds.filter { it.number.baselineVersion == currentBuild.baselineVersion }.maxBy { it.number } ?: builds.maxBy { it.number }
|
||||
|
||||
//<editor-fold desc="Deprecated stuff.">
|
||||
|
||||
@Deprecated("use {@link #UpdateStrategy(BuildNumber, UpdatesInfo, UserUpdateSettings)}")
|
||||
constructor(@Suppress("UNUSED_PARAMETER") majorVersion: Int,
|
||||
@Suppress("UNUSED_PARAMETER") currentBuild: BuildNumber,
|
||||
@Suppress("UNUSED_PARAMETER") updatesInfo: UpdatesInfo,
|
||||
@Suppress("UNUSED_PARAMETER") updateSettings: UserUpdateSettings) : this(currentBuild, updatesInfo, updateSettings) {
|
||||
}
|
||||
|
||||
|
||||
@Deprecated("use {@link #UpdateStrategy(BuildNumber, UpdatesInfo, UserUpdateSettings)}")
|
||||
constructor(@Suppress("UNUSED_PARAMETER") majorVersion: Int,
|
||||
@Suppress("UNUSED_PARAMETER") currentBuild: BuildNumber,
|
||||
@Suppress("UNUSED_PARAMETER") updatesInfo: UpdatesInfo,
|
||||
@Suppress("UNUSED_PARAMETER") updateSettings: UserUpdateSettings,
|
||||
@Suppress("UNUSED_PARAMETER") customization: UpdateStrategyCustomization) : this(currentBuild, updatesInfo, updateSettings) {
|
||||
}
|
||||
|
||||
//</editor-fold>
|
||||
}
|
||||
+78
-64
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.openapi.updateSettings.impl.UpdateSettingsConfigurable.UpdatesSettingsPanel">
|
||||
<grid id="5aa87" binding="myPanel" layout-manager="GridLayoutManager" row-count="5" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="5aa87" binding="myPanel" layout-manager="GridLayoutManager" row-count="10" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="62" y="37" width="816" height="434"/>
|
||||
@@ -8,91 +8,57 @@
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="e409a" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="10" left="0" bottom="20" right="0"/>
|
||||
<component id="1aa0e" class="javax.swing.JCheckBox" binding="myCheckForUpdates">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="2" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<selected value="true"/>
|
||||
<text resource-bundle="messages/IdeBundle" key="updates.settings.checkbox"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="8eae8" class="javax.swing.JComboBox" binding="myUpdateChannels">
|
||||
<constraints>
|
||||
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="1aa0e" class="javax.swing.JCheckBox" binding="myCheckForUpdates">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<selected value="true"/>
|
||||
<text resource-bundle="messages/IdeBundle" key="updates.settings.checkbox"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="8eae8" class="javax.swing.JComboBox" binding="myUpdateChannels">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="cc207" class="javax.swing.JButton" binding="myCheckNow">
|
||||
<constraints>
|
||||
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages/IdeBundle" key="updates.settings.check.now.button"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="fdc45" class="com.intellij.ui.components.JBLabel" binding="myChannelWarning">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages/IdeBundle" key="updates.settings.unstable"/>
|
||||
<visible value="false"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="fc5f1" class="javax.swing.JCheckBox" binding="myUseSecureConnection">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages/IdeBundle" key="updates.settings.secure"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<component id="36fbb" class="javax.swing.JLabel">
|
||||
</component>
|
||||
<component id="cc207" class="javax.swing.JButton" binding="myCheckNow">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages/IdeBundle" key="updates.settings.current.version"/>
|
||||
<text resource-bundle="messages/IdeBundle" key="updates.settings.check.now.button"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="bd9c5" class="javax.swing.JLabel" binding="myVersionNumber">
|
||||
<component id="fdc45" class="com.intellij.ui.components.JBLabel" binding="myChannelWarning">
|
||||
<constraints>
|
||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
<grid row="1" column="0" row-span="1" col-span="5" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="4.5.4"/>
|
||||
<text resource-bundle="messages/IdeBundle" key="updates.settings.unstable"/>
|
||||
<visible value="false"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="6af7e" class="javax.swing.JLabel">
|
||||
<component id="fc5f1" class="javax.swing.JCheckBox" binding="myUseSecureConnection">
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="2" column="0" row-span="1" col-span="4" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages/IdeBundle" key="updates.settings.build.number"/>
|
||||
<text resource-bundle="messages/IdeBundle" key="updates.settings.secure"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="b6709" class="javax.swing.JLabel" binding="myBuildNumber">
|
||||
<component id="456b6" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
<grid row="3" column="0" row-span="1" col-span="4" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="3352"/>
|
||||
<text value=" "/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="db163" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages/IdeBundle" key="updates.settings.last.check"/>
|
||||
@@ -100,20 +66,68 @@
|
||||
</component>
|
||||
<component id="6b5cb" class="javax.swing.JLabel" binding="myLastCheckedDate">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
<grid row="4" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="01.05.2005"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="36fbb" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages/IdeBundle" key="updates.settings.current.version"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="bd9c5" class="javax.swing.JLabel" binding="myVersionNumber">
|
||||
<constraints>
|
||||
<grid row="5" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="4.5.4"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="6af7e" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages/IdeBundle" key="updates.settings.build.number"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="b6709" class="javax.swing.JLabel" binding="myBuildNumber">
|
||||
<constraints>
|
||||
<grid row="6" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="3352"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="51da0" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="7" column="0" row-span="1" col-span="4" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value=" "/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="23c67" class="com.intellij.ui.components.labels.ActionLink" binding="myIgnoredBuildsLink" custom-create="true">
|
||||
<constraints>
|
||||
<grid row="8" column="0" row-span="1" col-span="4" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages/IdeBundle" key="updates.settings.ignored"/>
|
||||
</properties>
|
||||
</component>
|
||||
<hspacer id="fdc69">
|
||||
<constraints>
|
||||
<grid row="3" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
<grid row="2" column="4" row-span="7" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</hspacer>
|
||||
<vspacer id="3d6db">
|
||||
<constraints>
|
||||
<grid row="4" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
<grid row="9" column="0" row-span="1" col-span="5" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
</children>
|
||||
|
||||
+4
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 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,13 +20,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
public interface UserUpdateSettings {
|
||||
@NotNull
|
||||
List<String> getKnownChannelsIds();
|
||||
|
||||
List<String> getIgnoredBuildNumbers();
|
||||
|
||||
void setKnownChannelIds(List<String> ids);
|
||||
|
||||
@NotNull
|
||||
ChannelStatus getSelectedChannelStatus();
|
||||
}
|
||||
@NotNull ChannelStatus getSelectedChannelStatus();
|
||||
@NotNull List<String> getIgnoredBuildNumbers();
|
||||
}
|
||||
@@ -906,7 +906,6 @@ updates.error.connection.failed=Connection failed ({0}). Please check network co
|
||||
updates.error.plugin.description.failed=Failed to load plugin descriptions from: \"{0}\"
|
||||
update.notifications.title=Platform and Plugin Updates
|
||||
update.notifications.group=Platform and Plugin Updates
|
||||
updates.channel.name.message=<b>{0}</b>: {1}
|
||||
updates.channel.bundled.key=The new version has an expiration date and does not require a license key.
|
||||
updates.fallback.build=You have perpetual fallback license for the new version.
|
||||
updates.subscription.active.till=Your subscription is active until {0}.
|
||||
@@ -935,9 +934,11 @@ updates.settings.check.now.button=&Check Now
|
||||
updates.settings.checkbox=Automatically check updates for
|
||||
updates.settings.unstable=Please note that this channel is less stable than your current one.
|
||||
updates.settings.secure=Use secure connection
|
||||
updates.settings.build.number=Build number:
|
||||
updates.settings.current.version=Current version:
|
||||
updates.settings.last.check=Last checked:
|
||||
updates.settings.build.number=Build number
|
||||
updates.settings.current.version=Current version
|
||||
updates.settings.last.check=Last checked
|
||||
updates.settings.ignored=View/edit Ignored builds
|
||||
updates.settings.ignored.title=Ignored Builds
|
||||
update.plugin.host.url.message=Repository URL:
|
||||
update.no.update.hosts=No plugin repositories configured
|
||||
update.edit.plugin.host.title=Edit Repository
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.updates;
|
||||
|
||||
import com.intellij.openapi.updateSettings.impl.UpdatesInfo;
|
||||
import com.intellij.util.JdomKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
public class InfoReader {
|
||||
@NotNull
|
||||
public static UpdatesInfo read(@NotNull String fileName) {
|
||||
return read(InfoReader.class.getResource(fileName));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static UpdatesInfo read(@NotNull URL url) {
|
||||
try (InputStream stream = url.openStream()) {
|
||||
return new UpdatesInfo(JdomKt.loadElement(stream));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.updates
|
||||
|
||||
import com.intellij.openapi.updateSettings.impl.ChannelStatus
|
||||
import com.intellij.openapi.updateSettings.impl.UpdateChannel
|
||||
import com.intellij.openapi.updateSettings.impl.UpdatesInfo
|
||||
import com.intellij.openapi.util.BuildNumber
|
||||
import com.intellij.util.loadElement
|
||||
import org.junit.Test
|
||||
import java.net.URL
|
||||
import java.text.SimpleDateFormat
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
class UpdateInfoParsingTest {
|
||||
@Test fun liveJetbrainsUpdateFile() {
|
||||
val info = load(URL("http://www.jetbrains.com/updates/updates.xml").readText())
|
||||
assertNotNull(info["IC"])
|
||||
}
|
||||
|
||||
@Test fun liveAndroidUpdateFile() {
|
||||
val info = load(URL("https://dl.google.com/android/studio/patches/updates.xml").readText())
|
||||
assertNotNull(info["AI"])
|
||||
}
|
||||
|
||||
@Test fun emptyChannels() {
|
||||
val info = load("""
|
||||
<products>
|
||||
<product name="IntelliJ IDEA">
|
||||
<code>IU</code>
|
||||
<code>IC</code>
|
||||
</product>
|
||||
</products>""".trimIndent())
|
||||
val product = info["IU"]!!
|
||||
assertEquals("IntelliJ IDEA", product.name)
|
||||
assertEquals(0, product.channels.size)
|
||||
assertEquals(product, info["IC"])
|
||||
}
|
||||
|
||||
@Test fun oneProductOnly() {
|
||||
val info = load("""
|
||||
<products>
|
||||
<product name="IntelliJ IDEA">
|
||||
<code>IU</code>
|
||||
|
||||
<channel id="idea90" name="IntelliJ IDEA 9 updates" status="release" url="https://www.jetbrains.com/idea/whatsnew">
|
||||
<build number="95.627" version="9.0.4">
|
||||
<message>IntelliJ IDEA 9.0.4 is available. Please visit https://www.jetbrains.com/idea to learn more and download it.</message>
|
||||
<patch from="95.429" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="IDEA10EAP" name="IntelliJ IDEA X EAP" status="eap" licensing="eap" url="http://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP">
|
||||
<build number="98.520" version="10" releaseDate="20110403">
|
||||
<message>IntelliJ IDEA X RC is available. Please visit hhttp://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP to learn more.</message>
|
||||
<!-- <patch from="98.486" size="1"/> -->
|
||||
</build>
|
||||
</channel>
|
||||
</product>
|
||||
</products>""".trimIndent())
|
||||
|
||||
val product = info["IU"]!!
|
||||
assertEquals("IntelliJ IDEA", product.name)
|
||||
assertEquals(2, product.channels.size)
|
||||
|
||||
val channel = product.channels.find { it.id == "IDEA10EAP" }!!
|
||||
assertEquals(ChannelStatus.EAP, channel.status)
|
||||
assertEquals(UpdateChannel.LICENSING_EAP, channel.licensing)
|
||||
assertNotNull(channel.homePageUrl)
|
||||
assertEquals(1, channel.builds.size)
|
||||
|
||||
val build = channel.builds[0]
|
||||
assertEquals(BuildNumber.fromString("98.520"), build.number)
|
||||
assertEquals("2011-04-03", SimpleDateFormat("yyyy-MM-dd").format(build.releaseDate))
|
||||
assertEquals(0, build.patches.size)
|
||||
|
||||
assertEquals(1, product.channels.find { it.id == "idea90" }!!.builds[0].patches.size)
|
||||
}
|
||||
|
||||
@Test fun targetRanges() {
|
||||
val info = load("""
|
||||
<products>
|
||||
<product name="IntelliJ IDEA">
|
||||
<code>IU</code>
|
||||
<channel id="IDEA_EAP" status="eap">
|
||||
<build number="2016.2.123" version="2016.2" targetSince="0" targetUntil="145.*"/>
|
||||
<build number="2016.2.123" version="2016.2" targetSince="2016.1" targetUntil="2016.1.*"/>
|
||||
<build number="2016.1.11" version="2016.1"/>
|
||||
</channel>
|
||||
</product>
|
||||
</products>""".trimIndent())
|
||||
assertEquals(2, info["IU"]!!.channels[0].builds.count { it.target != null })
|
||||
}
|
||||
|
||||
private fun load(text: String) = UpdatesInfo(loadElement(text))
|
||||
}
|
||||
@@ -1,244 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.updates;
|
||||
|
||||
import com.intellij.openapi.updateSettings.UpdateStrategyCustomization;
|
||||
import com.intellij.openapi.updateSettings.impl.*;
|
||||
import com.intellij.openapi.util.BuildNumber;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class UpdateStrategyTest {
|
||||
@Test
|
||||
public void testWithUndefinedSelection() {
|
||||
// could be if somebody used before previous version of IDEA
|
||||
TestUpdateSettings settings = new TestUpdateSettings(ChannelStatus.EAP);
|
||||
UpdateStrategyCustomization customization = new UpdateStrategyCustomization();
|
||||
UpdateStrategy strategy = new UpdateStrategy(9, BuildNumber.fromString("IU-98.520"), InfoReader.read("idea-same.xml"), settings, customization);
|
||||
|
||||
CheckForUpdateResult result = strategy.checkForUpdates();
|
||||
assertEquals(UpdateStrategy.State.LOADED, result.getState());
|
||||
assertNull(result.getNewBuildInSelectedChannel());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithUserSelection() {
|
||||
// assume user has version 9 eap - and used eap channel - we want to introduce new eap
|
||||
TestUpdateSettings settings = new TestUpdateSettings(ChannelStatus.EAP);
|
||||
UpdateStrategyCustomization customization = new UpdateStrategyCustomization();
|
||||
UpdateStrategy strategy = new UpdateStrategy(9, BuildNumber.fromString("IU-95.429"), InfoReader.read("idea-new9eap.xml"), settings, customization);
|
||||
|
||||
CheckForUpdateResult result = strategy.checkForUpdates();
|
||||
assertEquals(UpdateStrategy.State.LOADED, result.getState());
|
||||
BuildInfo update = result.getNewBuildInSelectedChannel();
|
||||
assertNotNull(update);
|
||||
assertEquals("95.627", update.getNumber().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnore() {
|
||||
// assume user has version 9 eap - and used eap channel - we want to introduce new eap
|
||||
TestUpdateSettings settings = new TestUpdateSettings(ChannelStatus.EAP, "95.627", "98.620");
|
||||
UpdateStrategyCustomization customization = new UpdateStrategyCustomization();
|
||||
UpdateStrategy strategy = new UpdateStrategy(9, BuildNumber.fromString("IU-95.429"), InfoReader.read("idea-new9eap.xml"), settings, customization);
|
||||
|
||||
CheckForUpdateResult result = strategy.checkForUpdates();
|
||||
assertEquals(UpdateStrategy.State.LOADED, result.getState());
|
||||
BuildInfo update = result.getNewBuildInSelectedChannel();
|
||||
assertNull(update);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNewChannelAppears() {
|
||||
// assume user has version 9 eap subscription (default or selected)
|
||||
// and new channel appears - eap of version 10 is there
|
||||
TestUpdateSettings settings = new TestUpdateSettings(ChannelStatus.RELEASE);
|
||||
UpdateStrategyCustomization customization = new UpdateStrategyCustomization();
|
||||
UpdateStrategy strategy = new UpdateStrategy(9, BuildNumber.fromString("IU-95.627"), InfoReader.read("idea-newChannel-release.xml"), settings, customization);
|
||||
|
||||
CheckForUpdateResult result = strategy.checkForUpdates();
|
||||
assertEquals(UpdateStrategy.State.LOADED, result.getState());
|
||||
BuildInfo update = result.getNewBuildInSelectedChannel();
|
||||
assertNull(update);
|
||||
|
||||
UpdateChannel newChannel = result.getChannelToPropose();
|
||||
assertNotNull(newChannel);
|
||||
assertEquals("IDEA10EAP", newChannel.getId());
|
||||
assertEquals("IntelliJ IDEA X EAP", newChannel.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNewChannelWithOlderBuild() {
|
||||
TestUpdateSettings settings = new TestUpdateSettings(ChannelStatus.EAP);
|
||||
UpdateStrategyCustomization customization = new UpdateStrategyCustomization();
|
||||
UpdateStrategy strategy = new UpdateStrategy(10, BuildNumber.fromString("IU-107.80"), InfoReader.read("idea-newChannel.xml"), settings, customization);
|
||||
|
||||
CheckForUpdateResult result = strategy.checkForUpdates();
|
||||
assertEquals(UpdateStrategy.State.LOADED, result.getState());
|
||||
BuildInfo update = result.getNewBuildInSelectedChannel();
|
||||
assertNull(update);
|
||||
|
||||
UpdateChannel newChannel = result.getChannelToPropose();
|
||||
assertNull(newChannel);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNewChannelAndNewBuildAppear() {
|
||||
// assume user has version 9 eap subscription (default or selected)
|
||||
// and new channels appears - eap of version 10 is there
|
||||
// and new build withing old channel appears also
|
||||
// we need to show only one dialog
|
||||
TestUpdateSettings settings = new TestUpdateSettings(ChannelStatus.EAP);
|
||||
UpdateStrategyCustomization customization = new UpdateStrategyCustomization();
|
||||
UpdateStrategy strategy = new UpdateStrategy(9, BuildNumber.fromString("IU-95.429"), InfoReader.read("idea-newChannel.xml"), settings, customization);
|
||||
|
||||
CheckForUpdateResult result = strategy.checkForUpdates();
|
||||
assertEquals(UpdateStrategy.State.LOADED, result.getState());
|
||||
BuildInfo update = result.getNewBuildInSelectedChannel();
|
||||
assertNotNull(update);
|
||||
assertEquals("95.627", update.getNumber().toString());
|
||||
|
||||
UpdateChannel newChannel = result.getChannelToPropose();
|
||||
assertNotNull(newChannel);
|
||||
assertEquals("IDEA10EAP", newChannel.getId());
|
||||
assertEquals("IntelliJ IDEA X EAP", newChannel.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChannelWithCurrentStatusPreferred() {
|
||||
BuildNumber currentBuild = BuildNumber.fromString("IU-139.658");
|
||||
TestUpdateSettings settings = new TestUpdateSettings(ChannelStatus.EAP);
|
||||
UpdateStrategyCustomization customization = new UpdateStrategyCustomization();
|
||||
UpdateStrategy strategy = new UpdateStrategy(14, currentBuild, InfoReader.read("idea-patchAvailable.xml"), settings, customization);
|
||||
|
||||
CheckForUpdateResult result = strategy.checkForUpdates();
|
||||
assertEquals(UpdateStrategy.State.LOADED, result.getState());
|
||||
|
||||
UpdateChannel channel = result.getUpdatedChannel();
|
||||
assertNotNull(channel);
|
||||
assertEquals(ChannelStatus.EAP, channel.getStatus());
|
||||
|
||||
BuildInfo selectedChannel = result.getNewBuildInSelectedChannel();
|
||||
assertNotNull(selectedChannel);
|
||||
assertNotNull(selectedChannel.findPatchForBuild(currentBuild));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStableUpdatePreferredByDefault() {
|
||||
BuildNumber currentBuild = BuildNumber.fromString("IU-143.381");
|
||||
TestUpdateSettings settings = new TestUpdateSettings(ChannelStatus.RELEASE);
|
||||
UpdateStrategyCustomization customization = new UpdateStrategyCustomization();
|
||||
UpdateStrategy strategy = new UpdateStrategy(15, currentBuild, InfoReader.read("idea-123280.xml"), settings, customization);
|
||||
|
||||
CheckForUpdateResult result = strategy.checkForUpdates();
|
||||
assertEquals(UpdateStrategy.State.LOADED, result.getState());
|
||||
|
||||
UpdateChannel channel = result.getUpdatedChannel();
|
||||
assertNotNull(channel);
|
||||
assertEquals(ChannelStatus.RELEASE, channel.getStatus());
|
||||
|
||||
BuildInfo build = result.getNewBuildInSelectedChannel();
|
||||
assertNotNull(build);
|
||||
assertEquals("143.382", build.getNumber().toString());
|
||||
assertNotNull(build.findPatchForBuild(currentBuild));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStableChannelProposedByDefault() {
|
||||
BuildNumber currentBuild = BuildNumber.fromString("IU-143.381");
|
||||
TestUpdateSettings settings = new TestUpdateSettings(ChannelStatus.RELEASE);
|
||||
UpdateStrategyCustomization customization = new UpdateStrategyCustomization();
|
||||
UpdateStrategy strategy = new UpdateStrategy(15, currentBuild, InfoReader.read("idea-123280.xml"), settings, customization);
|
||||
|
||||
CheckForUpdateResult result = strategy.checkForUpdates();
|
||||
assertEquals(UpdateStrategy.State.LOADED, result.getState());
|
||||
UpdateChannel channelToPropose = result.getChannelToPropose();
|
||||
assertNotNull(channelToPropose);
|
||||
assertEquals("IDEA_Release", channelToPropose.getId());
|
||||
|
||||
settings.setKnownChannelIds(Collections.singletonList(channelToPropose.getId()));
|
||||
result = strategy.checkForUpdates();
|
||||
assertEquals(UpdateStrategy.State.LOADED, result.getState());
|
||||
assertNull(result.getChannelToPropose());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParallelCampaignsInChannel() {
|
||||
BuildNumber currentBuild = BuildNumber.fromString("IU-143.381");
|
||||
TestUpdateSettings settings = new TestUpdateSettings(ChannelStatus.EAP);
|
||||
UpdateStrategyCustomization customization = new UpdateStrategyCustomization();
|
||||
UpdateStrategy strategy = new UpdateStrategy(15, currentBuild, InfoReader.read("idea-2eap.xml"), settings, customization);
|
||||
|
||||
CheckForUpdateResult result = strategy.checkForUpdates();
|
||||
assertEquals(UpdateStrategy.State.LOADED, result.getState());
|
||||
BuildInfo build = result.getNewBuildInSelectedChannel();
|
||||
assertNotNull(build);
|
||||
assertEquals("143.888", build.getNumber().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCrossingParallelCampaignsInChannel() {
|
||||
BuildNumber currentBuild = BuildNumber.fromString("IU-143.888");
|
||||
TestUpdateSettings settings = new TestUpdateSettings(ChannelStatus.EAP);
|
||||
UpdateStrategyCustomization customization = new UpdateStrategyCustomization();
|
||||
UpdateStrategy strategy = new UpdateStrategy(15, currentBuild, InfoReader.read("idea-2eap.xml"), settings, customization);
|
||||
|
||||
CheckForUpdateResult result = strategy.checkForUpdates();
|
||||
assertEquals(UpdateStrategy.State.LOADED, result.getState());
|
||||
BuildInfo build = result.getNewBuildInSelectedChannel();
|
||||
assertNotNull(build);
|
||||
assertEquals("144.888", build.getNumber().toString());
|
||||
}
|
||||
|
||||
private static class TestUpdateSettings implements UserUpdateSettings {
|
||||
private final ChannelStatus myChannelStatus;
|
||||
private final List<String> myIgnoredBuildNumbers;
|
||||
private List<String> myKnownChannelIds = Collections.emptyList();
|
||||
|
||||
public TestUpdateSettings(ChannelStatus channelStatus, String... ignoredBuilds) {
|
||||
myChannelStatus = channelStatus;
|
||||
myIgnoredBuildNumbers = Arrays.asList(ignoredBuilds);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getKnownChannelsIds() {
|
||||
return myKnownChannelIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getIgnoredBuildNumbers() {
|
||||
return myIgnoredBuildNumbers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setKnownChannelIds(List<String> ids) {
|
||||
myKnownChannelIds = ids;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ChannelStatus getSelectedChannelStatus() {
|
||||
return myChannelStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.updates
|
||||
|
||||
import com.intellij.openapi.updateSettings.impl.*
|
||||
import com.intellij.openapi.util.BuildNumber
|
||||
import com.intellij.util.loadElement
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertNull
|
||||
|
||||
class UpdateStrategyTest {
|
||||
@Test fun `channel contains no builds`() {
|
||||
val result = check("IU-145.258", ChannelStatus.RELEASE, """<channel id="IDEA_Release" status="release" licensing="release"/>""")
|
||||
assertNull(result.newBuild)
|
||||
}
|
||||
|
||||
@Test fun `already on the latest build`() {
|
||||
val result = check("IU-145.258", ChannelStatus.RELEASE, """
|
||||
<channel id="IDEA15_Release" status="release" licensing="release">
|
||||
<build number="143.2332" version="15.0.5"/>
|
||||
</channel>
|
||||
<channel id="IDEA_Release" status="release" licensing="release">
|
||||
<build number="145.258" version="2016.1"/>
|
||||
</channel>""")
|
||||
assertNull(result.newBuild)
|
||||
}
|
||||
|
||||
@Test fun `patch exclusions`() {
|
||||
val result = check("IU-145.258", ChannelStatus.RELEASE, """
|
||||
<channel id="IDEA_Release" status="release" licensing="release">
|
||||
<build number="145.597" version="2016.1.1">
|
||||
<patch from="145.596"/>
|
||||
<patch from="145.258" exclusions="win,mac,unix"/>
|
||||
</build>
|
||||
</channel>""")
|
||||
assertNotNull(result.findPatchForBuild(BuildNumber.fromString("145.596")))
|
||||
assertNull(result.findPatchForBuild(BuildNumber.fromString("145.258")))
|
||||
}
|
||||
|
||||
@Test fun `order of builds does not matter`() {
|
||||
val resultDesc = check("IU-143.2332", ChannelStatus.RELEASE, """
|
||||
<channel id="IDEA_Release" status="release" licensing="release">
|
||||
<build number="145.597" version="2016.1.1"/>
|
||||
<build number="145.258" version="2016.1"/>
|
||||
</channel>""")
|
||||
assertEquals("145.597", resultDesc.newBuild?.number.toString())
|
||||
|
||||
val resultAsc = check("IU-143.2332", ChannelStatus.RELEASE, """
|
||||
<channel id="IDEA_Release" status="release" licensing="release">
|
||||
<build number="145.258" version="2016.1"/>
|
||||
<build number="145.597" version="2016.1.1"/>
|
||||
</channel>""")
|
||||
assertEquals("145.597", resultAsc.newBuild?.number.toString())
|
||||
}
|
||||
|
||||
@Test fun `newer updates are preferred`() {
|
||||
val result = check("IU-145.258", ChannelStatus.EAP, """
|
||||
<channel id="IDEA_EAP" status="eap" licensing="eap">
|
||||
<build number="145.596" version="2016.1.1 EAP"/>
|
||||
</channel>
|
||||
<channel id="IDEA_Release" status="release" licensing="release">
|
||||
<build number="145.597" version="2016.1.1"/>
|
||||
</channel>""")
|
||||
assertEquals("145.597", result.newBuild?.number.toString())
|
||||
}
|
||||
|
||||
@Test fun `newer updates are preferred over more stable ones`() {
|
||||
val result = check("IU-145.257", ChannelStatus.EAP, """
|
||||
<channel id="IDEA_EAP" status="eap" licensing="eap">
|
||||
<build number="145.596" version="2016.1.1 EAP"/>
|
||||
</channel>
|
||||
<channel id="IDEA_Beta" status="beta" licensing="release">
|
||||
<build number="145.257" version="2016.1 RC2"/>
|
||||
</channel>
|
||||
<channel id="IDEA_Release" status="release" licensing="release">
|
||||
<build number="145.258" version="2016.1"/>
|
||||
</channel>""")
|
||||
assertEquals("145.596", result.newBuild?.number.toString())
|
||||
}
|
||||
|
||||
@Test fun `newer updates from non-allowed channels are ignored`() {
|
||||
val channels = """
|
||||
<channel id="IDEA_EAP" status="eap" licensing="eap">
|
||||
<build number="145.596" version="2016.1.1 EAP"/>
|
||||
</channel>
|
||||
<channel id="IDEA_Beta" status="beta" licensing="release">
|
||||
<build number="145.257" version="2016.1 RC2"/>
|
||||
</channel>
|
||||
<channel id="IDEA_Release" status="release" licensing="release">
|
||||
<build number="145.258" version="2016.1"/>
|
||||
</channel>"""
|
||||
assertEquals("145.258", check("IU-145.256", ChannelStatus.RELEASE, channels).newBuild?.number.toString())
|
||||
assertNull(check("IU-145.258", ChannelStatus.RELEASE, channels).newBuild)
|
||||
}
|
||||
|
||||
@Test fun `ignored updates are excluded`() {
|
||||
val result = check("IU-145.258", ChannelStatus.EAP, """
|
||||
<channel id="IDEA_EAP" status="eap" licensing="eap">
|
||||
<build number="145.596" version="2016.1.1 EAP"/>
|
||||
<build number="145.595" version="2016.1.1 EAP"/>
|
||||
</channel>""", listOf("145.596"))
|
||||
assertEquals("145.595", result.newBuild?.number.toString())
|
||||
}
|
||||
|
||||
@Test fun `updates can be targeted for specific builds`() {
|
||||
val channels = """
|
||||
<channel id="IDEA_EAP" status="eap" licensing="eap">
|
||||
<build number="145.596" version="2016.1.1 EAP" targetSince="145.595" targetUntil="145.*"/> <!-- this build is not for everyone -->
|
||||
<build number="145.595" version="2016.1.1 EAP"/>
|
||||
</channel>"""
|
||||
assertEquals("145.595", check("IU-145.258", ChannelStatus.EAP, channels).newBuild?.number.toString())
|
||||
assertEquals("145.596", check("IU-145.595", ChannelStatus.EAP, channels).newBuild?.number.toString())
|
||||
}
|
||||
|
||||
@Test fun `updates from the same baseline are preferred`() {
|
||||
val result = check("IU-143.2287", ChannelStatus.RELEASE, """
|
||||
<channel id="IDEA_Release" status="release" licensing="release">
|
||||
<build number="143.2332" version="15.0.5"/>
|
||||
<build number="145.597" version="2016.1.1"/>
|
||||
</channel>""")
|
||||
assertEquals("143.2332", result.newBuild?.number.toString())
|
||||
}
|
||||
|
||||
@Test fun `cross-baseline updates are perfectly legal`() {
|
||||
val result = check("IU-143.2332", ChannelStatus.EAP, """
|
||||
<channel id="IDEA_Release" status="release" licensing="release">
|
||||
<build number="143.2332" version="15.0.5"/>
|
||||
<build number="145.597" version="2016.1.1"/>
|
||||
</channel>""")
|
||||
assertEquals("145.597", result.newBuild?.number.toString())
|
||||
}
|
||||
|
||||
private fun check(currentBuild: String,
|
||||
selectedChannel: ChannelStatus,
|
||||
testData: String,
|
||||
ignoredBuilds: List<String> = emptyList()): CheckForUpdateResult {
|
||||
val updates = UpdatesInfo(loadElement("""
|
||||
<products>
|
||||
<product name="IntelliJ IDEA">
|
||||
<code>IU</code>
|
||||
${testData}
|
||||
</product>
|
||||
</products>"""))
|
||||
val settings = object : UserUpdateSettings {
|
||||
override fun getSelectedChannelStatus() = selectedChannel
|
||||
override fun getIgnoredBuildNumbers() = ignoredBuilds
|
||||
}
|
||||
val result = UpdateStrategy(BuildNumber.fromString(currentBuild), updates, settings).checkForUpdates()
|
||||
assertEquals(UpdateStrategy.State.LOADED, result.state)
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -1,100 +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.
|
||||
*/
|
||||
package com.intellij.ide.updates;
|
||||
|
||||
import com.intellij.openapi.updateSettings.impl.*;
|
||||
import com.intellij.openapi.util.BuildNumber;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
public class UpdatesInfoParserTest {
|
||||
@Test
|
||||
public void testLiveJetbrainsUpdateFile() throws MalformedURLException {
|
||||
UpdatesInfo info = InfoReader.read(new URL("http://www.jetbrains.com/updates/updates.xml"));
|
||||
assertNotNull(info.getProduct("IC"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLiveAndroidUpdateFile() throws MalformedURLException {
|
||||
UpdatesInfo info = InfoReader.read(new URL("https://dl.google.com/android/studio/patches/updates.xml"));
|
||||
assertNotNull(info.getProduct("AI"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidXmlParsing() {
|
||||
UpdatesInfo info = InfoReader.read("current.xml");
|
||||
assertEquals(5, info.getProductsCount());
|
||||
|
||||
Product product = info.getProduct("IU");
|
||||
assertNotNull(product);
|
||||
checkProduct(product, "IntelliJ IDEA", "maiaEAP", "IDEA10EAP", "idea90");
|
||||
|
||||
UpdateChannel channel = product.findUpdateChannelById("IDEA10EAP");
|
||||
assertNotNull(channel);
|
||||
assertEquals(ChannelStatus.EAP, channel.getStatus());
|
||||
assertEquals(UpdateChannel.LICENSING_EAP, channel.getLicensing());
|
||||
assertNotNull(channel.getHomePageUrl());
|
||||
assertNotNull(channel.getFeedbackUrl());
|
||||
|
||||
BuildInfo build = channel.getLatestBuild();
|
||||
assertNotNull(build);
|
||||
assertEquals(BuildNumber.fromString("98.520"), build.getNumber());
|
||||
Date date = build.getReleaseDate();
|
||||
assertNotNull(date);
|
||||
assertEquals("2011-04-03", new SimpleDateFormat("yyyy-MM-dd").format(date));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyChannels() {
|
||||
UpdatesInfo info = InfoReader.read("emptyChannels.xml");
|
||||
|
||||
Product product = info.getProduct("IU");
|
||||
assertNotNull(product);
|
||||
assertEquals(0, product.getChannels().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneProductOnly() {
|
||||
UpdatesInfo info = InfoReader.read("oneProductOnly.xml");
|
||||
assertNotNull(info);
|
||||
|
||||
Product product = info.getProduct("IU");
|
||||
assertNotNull(product);
|
||||
checkProduct(product, "IntelliJ IDEA", "maiaEAP", "IDEA10EAP", "idea90");
|
||||
|
||||
UpdateChannel channel = product.findUpdateChannelById("IDEA10EAP");
|
||||
assertNotNull(channel);
|
||||
|
||||
BuildInfo build = channel.getLatestBuild();
|
||||
assertNotNull(build);
|
||||
assertEquals(BuildNumber.fromString("98.520"), build.getNumber());
|
||||
}
|
||||
|
||||
private static void checkProduct(Product product, String name, String... channels) {
|
||||
assertEquals(name, product.getName());
|
||||
assertEquals(channels.length, product.getChannels().size());
|
||||
for (String channel : channels) {
|
||||
assertNotNull(product.findUpdateChannelById(channel));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
<products>
|
||||
<product name="IntelliJ IDEA">
|
||||
<code>IU</code>
|
||||
<code>IC</code>
|
||||
|
||||
<channel id="maiaEAP" name="IntelliJ IDEA 9 updates" status="release"
|
||||
url="https://www.jetbrains.com/idea/whatsnew"
|
||||
feedback="http://youtrack.jetbrains.net">
|
||||
<build number="95.627" version="9.0.4">
|
||||
<message>IntelliJ IDEA 9.0.4 is available.
|
||||
Please visit https://www.jetbrains.com/idea to learn more and download it.
|
||||
</message>
|
||||
<patch from="95.429" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="idea90" name="IntelliJ IDEA 9 updates" status="release" url="https://www.jetbrains.com/idea/whatsnew">
|
||||
<build number="95.627" version="9.0.4">
|
||||
<message>IntelliJ IDEA 9.0.4 is available.
|
||||
Please visit https://www.jetbrains.com/idea to learn more and download it.
|
||||
</message>
|
||||
<patch from="95.429" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="IDEA10EAP" name="IntelliJ IDEA X EAP" status="eap" licensing="eap"
|
||||
url="http://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP"
|
||||
feedback="http://youtrack.jetbrains.net">
|
||||
<build number="98.520" version="10" releaseDate="20110403">
|
||||
<message>IntelliJ IDEA X RC is available.
|
||||
Please visit http://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP to learn more and download it.
|
||||
</message>
|
||||
<!--<patch from="98.486" size="1"/>-->
|
||||
</build>
|
||||
</channel>
|
||||
</product>
|
||||
|
||||
<product name="RubyMine">
|
||||
<code>RM</code>
|
||||
<channel id="rm20" name="RubyMine 2.0.2" status="Release"
|
||||
url="https://www.jetbrains.com/ruby"
|
||||
feedback="http://youtrack.jetbrains.net">
|
||||
<build number="97.122" version="3.0">
|
||||
<message>RubyMine 3.0 is available.
|
||||
Please visit https://www.jetbrains.com/ruby to learn more and download it.
|
||||
</message>
|
||||
</build>
|
||||
</channel>
|
||||
<channel id="rm25" name="RubyMine 3.0" status="Release"
|
||||
url="https://www.jetbrains.com/ruby/"
|
||||
feedback="http://youtrack.jetbrains.net">
|
||||
<build number="97.122" version="3.0">
|
||||
<message>RubyMine 3.0 is available.
|
||||
Please visit https://www.jetbrains.com/ruby to learn more and download it.
|
||||
</message>
|
||||
</build>
|
||||
</channel>
|
||||
<channel id="rm30" name="RubyMine 3.0" status="Release"
|
||||
url="https://www.jetbrains.com/ruby/"
|
||||
feedback="http://youtrack.jetbrains.net">
|
||||
<build number="97.122" version="3.0">
|
||||
<message>RubyMine 3.0 Release Candidate 2 is available.
|
||||
Please visit https://www.jetbrains.com/ruby to learn more and download it.
|
||||
</message>
|
||||
</build>
|
||||
</channel>
|
||||
<channel id="rm25EAP" name="RubyMine 3.0" status="EAP"
|
||||
url="https://www.jetbrains.com/ruby/"
|
||||
feedback="http://youtrack.jetbrains.net">
|
||||
<build number="97.122" version="3.0">
|
||||
<message>RubyMine 3.0 is available.
|
||||
Please visit https://www.jetbrains.com/ruby to learn more and download it.
|
||||
</message>
|
||||
</build>
|
||||
</channel>
|
||||
</product>
|
||||
|
||||
<product name="PyCharm">
|
||||
<code>PY</code>
|
||||
<channel id="pycharm" name="PyCharm 1.0" status="EAP"
|
||||
url="https://www.jetbrains.com/pycharm"
|
||||
feedback="http://youtrack.jetbrains.net">
|
||||
<build number="97.87" version="1.0.1">
|
||||
<message>PyCharm 1.0.1 is available.
|
||||
Please visit www.jetbrains.com/pycharm to download it.
|
||||
</message>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="pycharm10" name="PyCharm 1.0" status="Release"
|
||||
url="https://www.jetbrains.com/pycharm"
|
||||
feedback="http://youtrack.jetbrains.net">
|
||||
<build number="97.87" version="1.0.1">
|
||||
<message>PyCharm 1.0.1 is available.
|
||||
Please visit www.jetbrains.com/pycharm to download it.
|
||||
</message>
|
||||
</build>
|
||||
</channel>
|
||||
</product>
|
||||
|
||||
<product name="PhpStorm">
|
||||
<code>PS</code>
|
||||
<channel id="WI1EAP" name="PhpStorm 1.0.2" status="EAP"
|
||||
url="https://www.jetbrains.com/phpstorm"
|
||||
feedback="http://devnet.jetbrains.net/community/wi/">
|
||||
<build number="95.503" version="1.0.2">
|
||||
<message>PhpStorm 1.0.2 is available.
|
||||
Please visit https://www.jetbrains.com/phpstorm to download it.
|
||||
</message>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="WI1" name="PhpStorm 1.0.2" status="release"
|
||||
url="https://www.jetbrains.com/phpstorm"
|
||||
feedback="http://devnet.jetbrains.net/community/wi/">
|
||||
<build number="95.503" version="1.0.2">
|
||||
<message>PhpStorm 1.0.2 is available.
|
||||
Please visit https://www.jetbrains.com/phpstorm to download it.
|
||||
</message>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="WI2EAP" name="PhpStorm 2.0" status="EAP"
|
||||
url="http://confluence.jetbrains.net/display/WI/"
|
||||
feedback="http://devnet.jetbrains.net/community/wi/">
|
||||
<build number="98.521" version="2.0">
|
||||
<message>PhpStorm 2.0 EAP update is available.
|
||||
Please visit http://confluence.jetbrains.net/display/WI/ to download it.
|
||||
</message>
|
||||
<patch from="98.458" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="WI2" name="PhpStorm 2.0" status="release"
|
||||
url="https://www.jetbrains.com/phpstorm"
|
||||
feedback="http://devnet.jetbrains.net/community/wi/">
|
||||
<build number="95.503" version="2.0">
|
||||
<message>PhpStorm 2.0 is available.
|
||||
Please visit https://www.jetbrains.com/phpstorm to download it.
|
||||
</message>
|
||||
</build>
|
||||
</channel>
|
||||
</product>
|
||||
|
||||
<product name="WebStorm">
|
||||
<code>WS</code>
|
||||
<channel id="WI1EAP" name="WebStorm 1.0.2" status="EAP"
|
||||
url="https://www.jetbrains.com/webstorm"
|
||||
feedback="http://devnet.jetbrains.net/community/wi/">
|
||||
<build number="95.503" version="1.0.2">
|
||||
<message>WebStorm 1.0.2 is available.
|
||||
Please visit https://www.jetbrains.com/webstorm to download it.
|
||||
</message>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="WI1" name="WebStorm 1.0.2" status="release"
|
||||
url="https://www.jetbrains.com/webstorm"
|
||||
feedback="http://devnet.jetbrains.net/community/wi/">
|
||||
<build number="95.503" version="1.0.2">
|
||||
<message>WebStorm 1.0.2 is available.
|
||||
Please visit https://www.jetbrains.com/webstorm to download it.
|
||||
</message>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="WI2EAP" name="WebStorm 2.0" status="EAP"
|
||||
url="http://confluence.jetbrains.net/display/WI/"
|
||||
feedback="http://devnet.jetbrains.net/community/wi/">
|
||||
<build number="98.521" version="2.0">
|
||||
<message>WebStorm 2.0 EAP update is available.
|
||||
Please visit http://confluence.jetbrains.net/display/WI/ to download it.
|
||||
</message>
|
||||
<patch from="98.458" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="WI2" name="WebStorm 2.0" status="release"
|
||||
url="https://www.jetbrains.com/webstorm"
|
||||
feedback="http://devnet.jetbrains.net/community/wi/">
|
||||
<build number="95.503" version="1.0.2">
|
||||
<message>WebStorm 1.0.2 is available.
|
||||
Please visit https://www.jetbrains.com/webstorm to download it.
|
||||
</message>
|
||||
</build>
|
||||
</channel>
|
||||
</product>
|
||||
</products>
|
||||
@@ -1,6 +0,0 @@
|
||||
<products>
|
||||
<product name="IntelliJ IDEA">
|
||||
<code>IU</code>
|
||||
<code>IC</code>
|
||||
</product>
|
||||
</products>
|
||||
@@ -1,32 +0,0 @@
|
||||
<products>
|
||||
<product name="IntelliJ IDEA">
|
||||
<code>IU</code>
|
||||
<code>IC</code>
|
||||
|
||||
<channel id="IDEA_15_EAP" name="IntelliJ IDEA 15 EAP" status="eap" url="" feedback="" majorVersion="15" licensing="eap">
|
||||
<build number="143.747" version="15.0.2 EAP" releaseDate="20151102">
|
||||
<message/>
|
||||
<button name="Download" url="https://confluence.jetbrains.com/display/IDEADEV/IDEA+15+EAP" download="true" />
|
||||
<button name="Release Notes" url="https://confluence.jetbrains.com/display/IDEADEV/IntelliJ+IDEA+15+143.747.6+Release+Notes" />
|
||||
<patch from="143.381" size="from 4 to 20" />
|
||||
<patch from="143.382" size="from 4 to 18" />
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="IDEA_Beta" name="IntelliJ IDEA Beta" status="beta" url="" feedback="" majorVersion="15" licensing="eap"/>
|
||||
|
||||
<channel id="IDEA_Release" name="IntelliJ IDEA Release" status="release" url="" feedback="" majorVersion="15" licensing="release">
|
||||
<build number="143.382" version="15.0.1" releaseDate="20151102">
|
||||
<message/>
|
||||
<button name="Release Notes" url="https://confluence.jetbrains.com/display/IDEADEV/IntelliJ+IDEA+15.0.1+Release+Notes" />
|
||||
<patch from="143.381" size="from 1 to 12" />
|
||||
</build>
|
||||
<build number="143.381" version="15" releaseDate="20151102">
|
||||
<message/>
|
||||
<button name="Download" url="https://www.jetbrains.com/idea/download/" download="true" />
|
||||
<button name="What's New" url="https://www.jetbrains.com/idea/whatsnew/"/>
|
||||
<patch from="143.380" size="from 1 to 11" />
|
||||
</build>
|
||||
</channel>
|
||||
</product>
|
||||
</products>
|
||||
@@ -1,20 +0,0 @@
|
||||
<products>
|
||||
<product name="IntelliJ IDEA">
|
||||
<code>IU</code>
|
||||
<code>IC</code>
|
||||
|
||||
<channel id="IDEA_EAP" name="IntelliJ IDEA EAP" status="eap" url="" feedback="" majorVersion="15" licensing="eap">
|
||||
<build number="143.888" version="15.0.3 EAP">
|
||||
<message/>
|
||||
<button name="Download" url="" download="true" />
|
||||
<button name="Release Notes" url="" />
|
||||
</build>
|
||||
<build number="144.888" version="15.1 EAP">
|
||||
<message/>
|
||||
<button name="Download" url="" download="true" />
|
||||
<button name="Release Notes" url="" />
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
</product>
|
||||
</products>
|
||||
@@ -1,36 +0,0 @@
|
||||
<products>
|
||||
<product name="IntelliJ IDEA">
|
||||
<code>IU</code>
|
||||
<code>IC</code>
|
||||
<channel id="maiaEAP" name="IntelliJ IDEA 9 updates" status="release" majorVersion="9"
|
||||
url="https://www.jetbrains.com/idea/whatsnew"
|
||||
feedback="http://youtrack.jetbrains.net">
|
||||
<build number="95.627" version="9.0.4">
|
||||
<message>IntelliJ IDEA 9.0.4 is available.
|
||||
Please visit https://www.jetbrains.com/idea to learn more and download it.
|
||||
</message>
|
||||
<patch from="95.429" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="idea90" name="IntelliJ IDEA 9 updates" status="release" majorVersion="9"
|
||||
url="https://www.jetbrains.com/idea/whatsnew">
|
||||
<build number="95.627" version="9.0.4">
|
||||
<message>IntelliJ IDEA 9.0.4 is available.
|
||||
Please visit https://www.jetbrains.com/idea to learn more and download it.
|
||||
</message>
|
||||
<patch from="95.429" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="IDEA10EAP" name="IntelliJ IDEA X EAP" status="eap" majorVersion="10"
|
||||
url="http://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP">
|
||||
<build number="98.620" version="10">
|
||||
<message>IntelliJ IDEA X RC is available.
|
||||
Please visit http://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP to learn more and download it.
|
||||
</message>
|
||||
<!--<patch from="98.486" size="1"/>-->
|
||||
</build>
|
||||
</channel>
|
||||
</product>
|
||||
</products>
|
||||
@@ -1,39 +0,0 @@
|
||||
<products>
|
||||
<product name="IntelliJ IDEA">
|
||||
<code>IU</code>
|
||||
<code>IC</code>
|
||||
|
||||
<channel id="maiaEAP" name="IntelliJ IDEA 9 updates" status="release" majorVersion="9"
|
||||
url="https://www.jetbrains.com/idea/whatsnew"
|
||||
feedback="http://youtrack.jetbrains.net">
|
||||
<build number="95.627" version="9.0.4">
|
||||
<message>IntelliJ IDEA 9.0.4 is available.
|
||||
Please visit https://www.jetbrains.com/idea to learn more and download it.
|
||||
</message>
|
||||
<patch from="95.429" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="idea90" name="IntelliJ IDEA 9 updates" status="release" majorVersion="9"
|
||||
url="https://www.jetbrains.com/idea/whatsnew">
|
||||
<build number="95.627" version="9.0.4">
|
||||
<message>IntelliJ IDEA 9.0.4 is available.
|
||||
Please visit https://www.jetbrains.com/idea to learn more and download it.
|
||||
</message>
|
||||
<patch from="95.429" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="IDEA10EAP" name="IntelliJ IDEA X EAP" status="release" majorVersion="10"
|
||||
url="http://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP">
|
||||
<build number="98.520" version="10">
|
||||
<message>IntelliJ IDEA X RC is available.
|
||||
Please visit http://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP to learn more and download it.
|
||||
</message>
|
||||
<!--<patch from="98.486" size="1"/>-->
|
||||
</build>
|
||||
</channel>
|
||||
</product>
|
||||
|
||||
|
||||
</products>
|
||||
@@ -1,39 +0,0 @@
|
||||
<products>
|
||||
<product name="IntelliJ IDEA">
|
||||
<code>IU</code>
|
||||
<code>IC</code>
|
||||
|
||||
<channel id="maiaEAP" name="IntelliJ IDEA 9 updates" status="release" majorVersion="9"
|
||||
url="https://www.jetbrains.com/idea/whatsnew"
|
||||
feedback="http://youtrack.jetbrains.net">
|
||||
<build number="95.627" version="9.0.4">
|
||||
<message>IntelliJ IDEA 9.0.4 is available.
|
||||
Please visit https://www.jetbrains.com/idea to learn more and download it.
|
||||
</message>
|
||||
<patch from="95.429" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="idea90" name="IntelliJ IDEA 9 updates" status="release" majorVersion="9"
|
||||
url="https://www.jetbrains.com/idea/whatsnew">
|
||||
<build number="95.627" version="9.0.4">
|
||||
<message>IntelliJ IDEA 9.0.4 is available.
|
||||
Please visit https://www.jetbrains.com/idea to learn more and download it.
|
||||
</message>
|
||||
<patch from="95.429" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="IDEA10EAP" name="IntelliJ IDEA X EAP" status="eap" majorVersion="10"
|
||||
url="http://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP">
|
||||
<build number="98.520" version="10">
|
||||
<message>IntelliJ IDEA X RC is available.
|
||||
Please visit http://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP to learn more and download it.
|
||||
</message>
|
||||
<!--<patch from="98.486" size="1"/>-->
|
||||
</build>
|
||||
</channel>
|
||||
</product>
|
||||
|
||||
|
||||
</products>
|
||||
@@ -1,34 +0,0 @@
|
||||
<products>
|
||||
<product name="IntelliJ IDEA">
|
||||
<code>IU</code>
|
||||
<code>IC</code>
|
||||
<channel id="maiaEAP" name="IntelliJ IDEA 9 updates" status="release"
|
||||
url="https://www.jetbrains.com/idea/whatsnew"
|
||||
feedback="http://youtrack.jetbrains.net">
|
||||
<build number="95.627" version="9.0.4">
|
||||
<message>IntelliJ IDEA 9.0.4 is available.
|
||||
Please visit https://www.jetbrains.com/idea to learn more and download it.
|
||||
</message>
|
||||
<patch from="95.429" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="idea90" name="IntelliJ IDEA 9 updates" status="release" url="https://www.jetbrains.com/idea/whatsnew">
|
||||
<build number="95.627" version="9.0.4">
|
||||
<message>IntelliJ IDEA 9.0.4 is available.
|
||||
Please visit https://www.jetbrains.com/idea to learn more and download it.
|
||||
</message>
|
||||
<patch from="95.429" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="IDEA10EAP" name="IntelliJ IDEA X EAP" status="eap" url="http://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP">
|
||||
<build number="98.620" version="10">
|
||||
<message>IntelliJ IDEA X RC is available.
|
||||
Please visit http://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP to learn more and download it.
|
||||
</message>
|
||||
<!--<patch from="98.486" size="1"/>-->
|
||||
</build>
|
||||
</channel>
|
||||
</product>
|
||||
</products>
|
||||
@@ -1,37 +0,0 @@
|
||||
<products>
|
||||
<product name="IntelliJ IDEA">
|
||||
<code>IU</code>
|
||||
<code>IC</code>
|
||||
|
||||
<channel id="IDEA14" name="IntelliJ IDEA 14" status="release"
|
||||
url="https://www.jetbrains.com/idea/download"
|
||||
feedback="http://youtrack.jetbrains.net"
|
||||
majorVersion="14">
|
||||
<build number="139.659" version="14.0.2" releaseDate="20141103">
|
||||
<message>IntelliJ IDEA 14.0.2 build 139.659 is available.</message>
|
||||
<button name="Download" url="https://www.jetbrains.com/idea/download" download="true"/>
|
||||
<button name="What's New" url="https://www.jetbrains.com/idea/whatsnew/index.html"/>
|
||||
<button name="Release Notes" url="https://confluence.jetbrains.com/display/IDEADEV/IntelliJ+IDEA+14.0.2+Release+Notes"/>
|
||||
<patch from="139.224" size="30" />
|
||||
<patch from="139.225" size="30" />
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="IDEA_14_EAP" name="IntelliJ IDEA 14 EAP" status="eap"
|
||||
url="https://confluence.jetbrains.com/display/IDEADEV/IDEA+14+EAP"
|
||||
feedback="http://youtrack.jetbrains.net"
|
||||
majorVersion="14">
|
||||
<build number="139.659" version="14.0.2" releaseDate="20141103">
|
||||
<message>IntelliJ IDEA 14.0.2 build 139.659 is available.</message>
|
||||
<button name="Download" url="https://confluence.jetbrains.com/display/IDEADEV/IDEA+14+EAP" download="true"/>
|
||||
<button name="Release Notes" url="https://confluence.jetbrains.com/display/IDEADEV/IntelliJ+IDEA+14+139.659.2+Release+Notes"/>
|
||||
<patch from="139.658" size="10" />
|
||||
<patch from="139.224" size="30" />
|
||||
<patch from="139.225" size="30" />
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
</product>
|
||||
|
||||
|
||||
</products>
|
||||
@@ -1,36 +0,0 @@
|
||||
<products>
|
||||
<product name="IntelliJ IDEA">
|
||||
<code>IU</code>
|
||||
<code>IC</code>
|
||||
<channel id="maiaEAP" name="IntelliJ IDEA 9 updates" status="release" majorVersion="9"
|
||||
url="https://www.jetbrains.com/idea/whatsnew"
|
||||
feedback="http://youtrack.jetbrains.net">
|
||||
<build number="95.627" version="9.0.4">
|
||||
<message>IntelliJ IDEA 9.0.4 is available.
|
||||
Please visit https://www.jetbrains.com/idea to learn more and download it.
|
||||
</message>
|
||||
<patch from="95.429" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="idea90" name="IntelliJ IDEA 9 updates" status="release" majorVersion="9"
|
||||
url="https://www.jetbrains.com/idea/whatsnew">
|
||||
<build number="95.627" version="9.0.4">
|
||||
<message>IntelliJ IDEA 9.0.4 is available.
|
||||
Please visit https://www.jetbrains.com/idea to learn more and download it.
|
||||
</message>
|
||||
<patch from="95.429" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="IDEA10EAP" name="IntelliJ IDEA X EAP" status="eap" majorVersion="10"
|
||||
url="http://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP">
|
||||
<build number="98.520" version="10">
|
||||
<message>IntelliJ IDEA X RC is available.
|
||||
Please visit http://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP to learn more and download it.
|
||||
</message>
|
||||
<!--<patch from="98.486" size="1"/>-->
|
||||
</build>
|
||||
</channel>
|
||||
</product>
|
||||
</products>
|
||||
@@ -1,36 +0,0 @@
|
||||
<products>
|
||||
<product name="IntelliJ IDEA">
|
||||
<code>IU</code>
|
||||
<code>IC</code>
|
||||
|
||||
<channel id="maiaEAP" name="IntelliJ IDEA 9 updates" status="release"
|
||||
url="https://www.jetbrains.com/idea/whatsnew"
|
||||
feedback="http://youtrack.jetbrains.net">
|
||||
<build number="95.627" version="9.0.4">
|
||||
<message>IntelliJ IDEA 9.0.4 is available.
|
||||
Please visit https://www.jetbrains.com/idea to learn more and download it.
|
||||
</message>
|
||||
<patch from="95.429" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="idea90" name="IntelliJ IDEA 9 updates" status="release" url="https://www.jetbrains.com/idea/whatsnew">
|
||||
<build number="95.627" version="9.0.4">
|
||||
<message>IntelliJ IDEA 9.0.4 is available.
|
||||
Please visit https://www.jetbrains.com/idea to learn more and download it.
|
||||
</message>
|
||||
<patch from="95.429" size="2"/>
|
||||
</build>
|
||||
</channel>
|
||||
|
||||
<channel id="IDEA10EAP" name="IntelliJ IDEA X EAP" status="eap" url="http://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP">
|
||||
<build number="98.520" version="10">
|
||||
<message>IntelliJ IDEA X RC is available.
|
||||
Please visit http://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP to learn more and download it.
|
||||
</message>
|
||||
<!--<patch from="98.486" size="1"/>-->
|
||||
</build>
|
||||
</channel>
|
||||
</product>
|
||||
|
||||
</products>
|
||||
+11
-9
@@ -255,10 +255,9 @@ public abstract class ModuleManagerImpl extends ModuleManager implements Project
|
||||
final List<Module> modulesWithUnknownTypes = new ArrayList<Module>();
|
||||
List<ModuleLoadingErrorDescription> errors = new ArrayList<ModuleLoadingErrorDescription>();
|
||||
|
||||
for (int i = 0; i < myModulePaths.size(); i++) {
|
||||
ModulePath modulePath = myModulePaths.get(i);
|
||||
for (ModulePath modulePath : myModulePaths) {
|
||||
if (progressIndicator != null) {
|
||||
progressIndicator.setFraction((double) i / myModulePaths.size());
|
||||
progressIndicator.setFraction(progressIndicator.getFraction() + myProgressStep);
|
||||
}
|
||||
try {
|
||||
final Module module = moduleModel.loadModuleInternal(modulePath.getPath());
|
||||
@@ -274,8 +273,9 @@ public abstract class ModuleManagerImpl extends ModuleManager implements Project
|
||||
myFailedModulePaths.remove(modulePath);
|
||||
}
|
||||
catch (IOException e) {
|
||||
errors.add(ModuleLoadingErrorDescription.create(ProjectBundle.message("module.cannot.load.error", modulePath.getPath(), e.getMessage()),
|
||||
modulePath, this));
|
||||
errors
|
||||
.add(ModuleLoadingErrorDescription.create(ProjectBundle.message("module.cannot.load.error", modulePath.getPath(), e.getMessage()),
|
||||
modulePath, this));
|
||||
}
|
||||
catch (ModuleWithNameAlreadyExists moduleWithNameAlreadyExists) {
|
||||
errors.add(ModuleLoadingErrorDescription.create(moduleWithNameAlreadyExists.getMessage(), modulePath, this));
|
||||
@@ -285,12 +285,14 @@ public abstract class ModuleManagerImpl extends ModuleManager implements Project
|
||||
onModuleLoadErrors(errors);
|
||||
|
||||
showUnknownModuleTypeNotification(modulesWithUnknownTypes);
|
||||
|
||||
if (progressIndicator != null) {
|
||||
progressIndicator.setIndeterminate(true);
|
||||
}
|
||||
}
|
||||
|
||||
public int getModulePathsCount() { return myModulePaths == null ? 0 : myModulePaths.size(); }
|
||||
|
||||
private double myProgressStep;
|
||||
|
||||
public void setProgressStep(double step) { myProgressStep = step; }
|
||||
|
||||
protected boolean isUnknownModuleType(@NotNull Module module) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.testFramework;
|
||||
|
||||
import com.intellij.execution.process.ProcessIOExecutorService;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
@@ -92,7 +93,10 @@ public class ThreadTracker {
|
||||
wellKnownOffenders.add("VM Thread");
|
||||
wellKnownOffenders.add("YJPAgent-Telemetry");
|
||||
|
||||
longRunningThreadCreated(ApplicationManager.getApplication(), "Periodic tasks thread", "ApplicationImpl pooled thread");
|
||||
longRunningThreadCreated(ApplicationManager.getApplication(),
|
||||
"Periodic tasks thread",
|
||||
"ApplicationImpl pooled thread ",
|
||||
ProcessIOExecutorService.POOLED_THREAD_PREFIX);
|
||||
}
|
||||
|
||||
// marks Thread with this name as long-running, which should be ignored from the thread-leaking checks
|
||||
|
||||
@@ -66,8 +66,8 @@ public class BaseOSProcessHandler extends ProcessHandler implements TaskExecutor
|
||||
* @param task a task to run
|
||||
*/
|
||||
@NotNull
|
||||
protected Future<?> executeOnPooledThread(@NotNull Runnable task) {
|
||||
return AppExecutorUtil.getAppExecutorService().submit(task);
|
||||
protected Future<?> executeOnPooledThread(@NotNull final Runnable task) {
|
||||
return ProcessIOExecutorService.INSTANCE.submit(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.intellij.execution.process;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A thread pool for long-running workers needed for handling child processes, to avoid occupying workers in the main application pool
|
||||
* and constantly creating new threads there.
|
||||
*
|
||||
* @since 2016.2
|
||||
* @author peter
|
||||
*/
|
||||
public class ProcessIOExecutorService extends ThreadPoolExecutor {
|
||||
public static final String POOLED_THREAD_PREFIX = "Process I/O pool ";
|
||||
public static final ProcessIOExecutorService INSTANCE = new ProcessIOExecutorService();
|
||||
|
||||
/**
|
||||
* 3 for each process: ProcessWaitFor + 2 x BaseDataReader (stdout and stderr)
|
||||
* Allow for at least 2 processes: fsnotifier and external build/VCS/run configuration
|
||||
*/
|
||||
private static final int CORE_POOL_SIZE = 3 * 3;
|
||||
|
||||
private ProcessIOExecutorService() {
|
||||
super(CORE_POOL_SIZE, Integer.MAX_VALUE, 1, TimeUnit.MINUTES, new SynchronousQueue<Runnable>(), new ThreadFactory() {
|
||||
private final AtomicInteger counter = new AtomicInteger();
|
||||
@NotNull
|
||||
@Override
|
||||
public Thread newThread(@NotNull final Runnable r) {
|
||||
Thread thread = new Thread(r, POOLED_THREAD_PREFIX + counter.incrementAndGet());
|
||||
thread.setPriority(Thread.NORM_PRIORITY - 1);
|
||||
return thread;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ public class ProcessWaitFor {
|
||||
public void run() {
|
||||
String oldThreadName = Thread.currentThread().getName();
|
||||
if (!StringUtil.isEmptyOrSpaces(presentableName)) {
|
||||
Thread.currentThread().setName(StringUtil.first("ProcessWaitFor: " + presentableName, 120, true));
|
||||
Thread.currentThread().setName(oldThreadName + ": " + StringUtil.first("ProcessWaitFor: " + presentableName, 120, true));
|
||||
}
|
||||
int exitCode = 0;
|
||||
try {
|
||||
|
||||
@@ -55,7 +55,7 @@ public abstract class BaseDataReader {
|
||||
public void run() {
|
||||
String oldThreadName = Thread.currentThread().getName();
|
||||
if (!StringUtil.isEmptyOrSpaces(presentableName)) {
|
||||
Thread.currentThread().setName(StringUtil.first("BaseDataReader: " + presentableName, 120, true));
|
||||
Thread.currentThread().setName(oldThreadName + ": " + StringUtil.first("BaseDataReader: " + presentableName, 120, true));
|
||||
}
|
||||
try {
|
||||
doRun();
|
||||
|
||||
@@ -1686,7 +1686,9 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
Future future = ourUpdateAlarm.get();
|
||||
if (future == null) break;
|
||||
|
||||
UIUtil.dispatchAllInvocationEvents();
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) {
|
||||
UIUtil.dispatchAllInvocationEvents();
|
||||
}
|
||||
try {
|
||||
future.get(10, TimeUnit.MILLISECONDS);
|
||||
break;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2015 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2016 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -153,6 +153,7 @@ public class ControlFlowUtils {
|
||||
boolean hasDefaultCase = false;
|
||||
for (PsiStatement statement : statements) {
|
||||
if (statement instanceof PsiSwitchLabelStatement) {
|
||||
numCases++;
|
||||
final PsiSwitchLabelStatement switchLabelStatement = (PsiSwitchLabelStatement)statement;
|
||||
if (switchLabelStatement.isDefaultCase()) {
|
||||
hasDefaultCase = true;
|
||||
@@ -164,7 +165,6 @@ public class ControlFlowUtils {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
numCases++;
|
||||
}
|
||||
final boolean isEnum = isEnumSwitch(switchStatement);
|
||||
if (!hasDefaultCase && !isEnum) {
|
||||
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
package com.siyeh.igtest.bugs;
|
||||
|
||||
public class LoopStatementsThatDontLoopInspection
|
||||
{
|
||||
private final int m_foo = 3;
|
||||
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
new LoopStatementsThatDontLoopInspection().foo();
|
||||
}
|
||||
|
||||
public LoopStatementsThatDontLoopInspection()
|
||||
{
|
||||
}
|
||||
|
||||
public static boolean isContainingHash( final String s )
|
||||
{
|
||||
final char[] c = s.toCharArray();
|
||||
|
||||
for( int i = 0; i < c.length; i++ )
|
||||
{
|
||||
switch( c[i] )
|
||||
{
|
||||
case '#':
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void foo() throws Exception
|
||||
{
|
||||
System.out.println("m_foo =" + m_foo);
|
||||
for(; ;)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
while(true)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
break;
|
||||
}
|
||||
while(true);
|
||||
|
||||
while(true)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
// for(; ;)
|
||||
//{
|
||||
// return;
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
package com.siyeh.igtest.bugs;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class LoopStatementsThatDontLoop
|
||||
{
|
||||
private final int m_foo = 3;
|
||||
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
new LoopStatementsThatDontLoop().foo();
|
||||
}
|
||||
|
||||
public LoopStatementsThatDontLoop()
|
||||
{
|
||||
}
|
||||
|
||||
public static boolean isContainingHash( final String s )
|
||||
{
|
||||
final char[] c = s.toCharArray();
|
||||
|
||||
for( int i = 0; i < c.length; i++ )
|
||||
{
|
||||
switch( c[i] )
|
||||
{
|
||||
case '#':
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void foo() throws Exception
|
||||
{
|
||||
System.out.println("m_foo =" + m_foo);
|
||||
<warning descr="'for' statement does not loop">for</warning>(; ;)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
<warning descr="'while' statement does not loop">while</warning>(true)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
<warning descr="'do' statement does not loop">do</warning>
|
||||
{
|
||||
break;
|
||||
}
|
||||
while(true);
|
||||
|
||||
<warning descr="'while' statement does not loop">while</warning>(true)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
<warning descr="'for' statement does not loop">for</warning>(<error descr="Unreachable statement">;</error> ;)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum Modification {
|
||||
NONE, SET, REMOVE;
|
||||
}
|
||||
|
||||
boolean foo(List<Modification> list){
|
||||
for (Modification modification : list) {
|
||||
switch (modification) {
|
||||
case SET:
|
||||
case REMOVE:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
<warning descr="'for' statement does not loop">for</warning> (Modification modification : list) {
|
||||
switch (modification) {
|
||||
case SET:
|
||||
case REMOVE:
|
||||
return true;
|
||||
case NONE:
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.siyeh.ig.controlflow;
|
||||
|
||||
import com.intellij.codeInspection.InspectionProfileEntry;
|
||||
import com.siyeh.ig.LightInspectionTestCase;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
public class LoopStatementsThatDontLoopInspectionTest extends LightInspectionTestCase {
|
||||
|
||||
public void testLoopStatementsThatDontLoop() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected InspectionProfileEntry getInspection() {
|
||||
return new LoopStatementsThatDontLoopInspection();
|
||||
}
|
||||
}
|
||||
+1
-4
@@ -26,7 +26,6 @@ import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
|
||||
import com.intellij.openapi.progress.util.ReadTask;
|
||||
import com.intellij.openapi.project.DumbAwareRunnable;
|
||||
@@ -296,9 +295,7 @@ public class MvcModuleStructureSynchronizer extends AbstractProjectComponent {
|
||||
return !myProject.isDisposed() && orderSnapshot.equals(takeOrderSnapshot());
|
||||
}
|
||||
};
|
||||
GuiUtils.invokeLaterIfNeeded(
|
||||
() -> ProgressIndicatorUtils.scheduleWithWriteActionPriority(new ProgressIndicatorBase(), ourExecutor, task),
|
||||
ModalityState.NON_MODAL);
|
||||
GuiUtils.invokeLaterIfNeeded(() -> ProgressIndicatorUtils.scheduleWithWriteActionPriority(ourExecutor, task), ModalityState.NON_MODAL);
|
||||
}
|
||||
|
||||
private LinkedHashSet<Pair<Object, SyncAction>> takeOrderSnapshot() {
|
||||
|
||||
@@ -74,11 +74,10 @@ public class HtmlLexer extends BaseHtmlLexer {
|
||||
if (hasSeenStyle()) {
|
||||
if (hasSeenTag() && isStartOfEmbeddmentTagContent(tokenType)) {
|
||||
Language stylesheetLanguage = getStyleLanguage();
|
||||
IElementType currentStylesheetElementType;
|
||||
if ((stylesheetLanguage == null || LanguageUtil.isInjectableLanguage(stylesheetLanguage)) &&
|
||||
(currentStylesheetElementType = getCurrentStylesheetElementType()) != null) {
|
||||
if (stylesheetLanguage == null || LanguageUtil.isInjectableLanguage(stylesheetLanguage)) {
|
||||
myTokenEnd = skipToTheEndOfTheEmbeddment();
|
||||
tokenType = currentStylesheetElementType;
|
||||
IElementType currentStylesheetElementType = getCurrentStylesheetElementType();
|
||||
tokenType = currentStylesheetElementType == null ? XmlTokenType.XML_DATA_CHARACTERS : currentStylesheetElementType;
|
||||
}
|
||||
} else if (ourInlineStyleElementType!=null && isStartOfEmbeddmentAttributeValue(tokenType) && hasSeenAttribute()) {
|
||||
tokenType = ourInlineStyleElementType;
|
||||
@@ -86,11 +85,10 @@ public class HtmlLexer extends BaseHtmlLexer {
|
||||
} else if (hasSeenScript()) {
|
||||
if (hasSeenTag() && isStartOfEmbeddmentTagContent(tokenType)) {
|
||||
Language scriptLanguage = getScriptLanguage();
|
||||
IElementType currentScriptElementType;
|
||||
if ((scriptLanguage == null || LanguageUtil.isInjectableLanguage(scriptLanguage)) &&
|
||||
(currentScriptElementType = getCurrentScriptElementType()) != null) {
|
||||
if (scriptLanguage == null || LanguageUtil.isInjectableLanguage(scriptLanguage)) {
|
||||
myTokenEnd = skipToTheEndOfTheEmbeddment();
|
||||
tokenType = currentScriptElementType;
|
||||
IElementType currentScriptElementType = getCurrentScriptElementType();
|
||||
tokenType = currentScriptElementType == null ? XmlTokenType.XML_DATA_CHARACTERS : currentScriptElementType;
|
||||
}
|
||||
} else if (hasSeenAttribute() && isStartOfEmbeddmentAttributeValue(tokenType) && ourInlineScriptElementType!=null) {
|
||||
myTokenEnd = skipToTheEndOfTheEmbeddment();
|
||||
|
||||
Reference in New Issue
Block a user