mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+1
@@ -477,6 +477,7 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo
|
||||
private boolean isNonAnnotatedOverridingNotNull(PsiMethod method, PsiMethod superMethod) {
|
||||
return REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL &&
|
||||
!(method.getReturnType() instanceof PsiPrimitiveType) &&
|
||||
!method.isConstructor() &&
|
||||
!getNullityManager(method).hasNullability(method) &&
|
||||
isNotNullNotInferred(superMethod, true, IGNORE_EXTERNAL_SUPER_NOTNULL);
|
||||
}
|
||||
|
||||
@@ -985,8 +985,8 @@ public class ExpectedTypesProvider {
|
||||
PsiSubstitutor substitutor;
|
||||
if (candidateInfo instanceof MethodCandidateInfo) {
|
||||
final MethodCandidateInfo info = (MethodCandidateInfo)candidateInfo;
|
||||
substitutor = MethodCandidateInfo.ourOverloadGuard
|
||||
.doPreventingRecursion(argumentList, false, () -> info.inferTypeArguments(policy, args, true));
|
||||
substitutor = MethodCandidateInfo.ourOverloadGuard.doPreventingRecursion(argumentList, false,
|
||||
() -> info.inferSubstitutorFromArgs(policy, args));
|
||||
if (!info.isStaticsScopeCorrect() && !method.hasModifierProperty(PsiModifier.STATIC)) continue;
|
||||
}
|
||||
else {
|
||||
@@ -999,8 +999,7 @@ public class ExpectedTypesProvider {
|
||||
|
||||
if (leftArgs != null && candidateInfo instanceof MethodCandidateInfo) {
|
||||
substitutor = MethodCandidateInfo.ourOverloadGuard.doPreventingRecursion(argumentList, false,
|
||||
() -> ((MethodCandidateInfo)candidateInfo)
|
||||
.inferTypeArguments(policy, leftArgs, true));
|
||||
() -> ((MethodCandidateInfo)candidateInfo).inferSubstitutorFromArgs(policy, leftArgs));
|
||||
if (substitutor != null) {
|
||||
inferMethodCallArgumentTypes(argument, forCompletion, leftArgs, index, method, substitutor, array);
|
||||
}
|
||||
|
||||
@@ -806,7 +806,8 @@ public class JavaCompletionUtil {
|
||||
PsiElement composite = leaf == null ? null : leaf.getParent();
|
||||
if (composite instanceof PsiMethodReferenceExpression && LambdaHighlightingUtil.insertSemicolon(composite.getParent())) {
|
||||
insertAdditionalSemicolon = false;
|
||||
} else if (composite instanceof PsiReferenceExpression) {
|
||||
}
|
||||
else if (composite instanceof PsiReferenceExpression) {
|
||||
PsiElement parent = composite.getParent();
|
||||
if (parent instanceof PsiMethodCallExpression) {
|
||||
parent = parent.getParent();
|
||||
@@ -814,6 +815,9 @@ public class JavaCompletionUtil {
|
||||
if (parent instanceof PsiLambdaExpression && !LambdaHighlightingUtil.insertSemicolonAfter((PsiLambdaExpression)parent)) {
|
||||
insertAdditionalSemicolon = false;
|
||||
}
|
||||
if (parent instanceof PsiMethodReferenceExpression && LambdaHighlightingUtil.insertSemicolon(parent.getParent())) {
|
||||
insertAdditionalSemicolon = false;
|
||||
}
|
||||
}
|
||||
if (insertAdditionalSemicolon) {
|
||||
toInsert = TailType.SEMICOLON;
|
||||
|
||||
@@ -159,7 +159,7 @@ public class JavaInheritorsGetter extends CompletionProvider<CompletionParameter
|
||||
}
|
||||
try {
|
||||
final PsiStatement statement = elementFactory
|
||||
.createStatementFromText(canonicalText + " v = new " + erasedText + "<>()", parameters.getOriginalFile());
|
||||
.createStatementFromText(canonicalText + " v = new " + erasedText + "<>()", parameters.getPosition());
|
||||
final PsiVariable declaredVar = (PsiVariable)((PsiDeclarationStatement)statement).getDeclaredElements()[0];
|
||||
final PsiNewExpression initializer = (PsiNewExpression)declaredVar.getInitializer();
|
||||
final boolean hasDefaultConstructorOrNoGenericsOne = PsiDiamondTypeImpl.hasDefaultConstructor(psiClass) ||
|
||||
|
||||
+4
-1
@@ -102,8 +102,11 @@ public class RedundantArrayForVarargsCallInspection extends GenericsInspectionTo
|
||||
}
|
||||
PsiExpression lastArg = args[args.length - 1];
|
||||
PsiParameter lastParameter = parameters[args.length - 1];
|
||||
if (!lastParameter.isVarArgs()) {
|
||||
return;
|
||||
}
|
||||
PsiType lastParamType = lastParameter.getType();
|
||||
LOG.assertTrue(lastParamType instanceof PsiEllipsisType);
|
||||
LOG.assertTrue(lastParamType instanceof PsiEllipsisType, lastParamType);
|
||||
if (!(lastArg instanceof PsiNewExpression)) {
|
||||
return;
|
||||
}
|
||||
|
||||
+19
-3
@@ -32,6 +32,8 @@ import com.intellij.codeInsight.navigation.NavigationUtil;
|
||||
import com.intellij.ide.util.PsiClassListCellRenderer;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.TransactionGuard;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
@@ -477,9 +479,23 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
|
||||
Util.analyzeExpression(myExpr, new ArrayList<>(), classMemberRefs, new ArrayList<>());
|
||||
}
|
||||
|
||||
showDialog(method, methodToSearchFor, occurences, replaceAllOccurrences, delegate, initializerType, mustBeFinal,
|
||||
classMemberRefs, createNameSuggestionGenerator(myExpr, propName, myProject, enteredName));
|
||||
}
|
||||
}
|
||||
|
||||
private void showDialog(PsiMethod method,
|
||||
PsiMethod methodToSearchFor,
|
||||
PsiExpression[] occurences,
|
||||
boolean replaceAllOccurrences,
|
||||
boolean delegate,
|
||||
PsiType initializerType,
|
||||
boolean mustBeFinal,
|
||||
List<UsageInfo> classMemberRefs, NameSuggestionsGenerator nameSuggestionGenerator) {
|
||||
TransactionGuard.getInstance().submitTransactionAndWait(() -> {
|
||||
final IntroduceParameterDialog dialog =
|
||||
new IntroduceParameterDialog(myProject, classMemberRefs, occurences, myLocalVar, myExpr,
|
||||
createNameSuggestionGenerator(myExpr, propName, myProject, enteredName),
|
||||
nameSuggestionGenerator,
|
||||
createTypeSelectorManager(occurences, initializerType), methodToSearchFor, method, getParamsToRemove(method, occurences), mustBeFinal);
|
||||
dialog.setReplaceAllOccurrences(replaceAllOccurrences);
|
||||
dialog.setGenerateDelegate(delegate);
|
||||
@@ -489,9 +505,9 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
|
||||
myEditor.getSelectionModel().removeSelection();
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(cleanSelectionRunnable);
|
||||
ApplicationManager.getApplication().invokeLater(cleanSelectionRunnable, ModalityState.any());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private TypeSelectorManagerImpl createTypeSelectorManager(PsiExpression[] occurences, PsiType initializerType) {
|
||||
|
||||
+14
-2
@@ -118,8 +118,7 @@ public class RootTypeConversionRule extends TypeConversionRule {
|
||||
}
|
||||
|
||||
final PsiType migrationType = methodTypeParamsSubstitutor.substitute(type);
|
||||
if (!originalType.equals(migrationType) &&
|
||||
!TypeConversionUtil.areTypesAssignmentCompatible(migrationType, actualParams[i])) {
|
||||
if (!originalType.equals(migrationType) && !areParametersAssignable(migrationType, i, actualParams)) {
|
||||
labeler.migrateExpressionType(actualParams[i], migrationType, context, false, true);
|
||||
}
|
||||
}
|
||||
@@ -139,6 +138,19 @@ public class RootTypeConversionRule extends TypeConversionRule {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean areParametersAssignable(PsiType migrationType, int paramId, PsiExpression[] actualParams) {
|
||||
if (migrationType instanceof PsiEllipsisType) {
|
||||
for (int i = paramId; i < actualParams.length; i++) {
|
||||
if (!TypeConversionUtil.areTypesAssignmentCompatible(migrationType, actualParams[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return TypeConversionUtil.areTypesAssignmentCompatible(migrationType, actualParams[paramId]);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyStaticMethodConversionDescriptor extends TypeConversionDescriptorBase {
|
||||
private final @NotNull String myTargetClassQName;
|
||||
|
||||
|
||||
+10
-3
@@ -100,14 +100,21 @@ public class JavaGenericsUtil {
|
||||
}
|
||||
PsiMethod psiMethod = (PsiMethod)resolve;
|
||||
|
||||
if (!psiMethod.isVarArgs()) {
|
||||
PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
|
||||
|
||||
int parametersCount = parameters.length;
|
||||
if (parametersCount == 0) {
|
||||
return false;
|
||||
}
|
||||
PsiParameter varargParameter = parameters[parametersCount - 1];
|
||||
if (!varargParameter.isVarArgs()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AnnotationUtil.isAnnotated(psiMethod, "java.lang.SafeVarargs", false, false)) {
|
||||
return false;
|
||||
}
|
||||
int parametersCount = psiMethod.getParameterList().getParametersCount();
|
||||
PsiParameter varargParameter = psiMethod.getParameterList().getParameters()[parametersCount - 1];
|
||||
|
||||
PsiType componentType = ((PsiEllipsisType)varargParameter.getType()).getComponentType();
|
||||
if (isReifiableType(resolveResult.getSubstitutor().substitute(componentType))) {
|
||||
return false;
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import java.util.ArrayList;
|
||||
|
||||
class Test {
|
||||
|
||||
<T> ArrayList<T> foo () {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import java.util.ArrayList;
|
||||
|
||||
class Test {
|
||||
|
||||
<T> ArrayList<T> foo () {
|
||||
return new Arr<caret>
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
class Test {
|
||||
private static <T> void _f(Consumer<T> c) {}
|
||||
|
||||
private static void bar(final String s) {}
|
||||
|
||||
public static void main(String[] argArr) {
|
||||
Test.<String>_f(Test::bar);
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
class Test {
|
||||
private static <T> void _f(Consumer<T> c) {}
|
||||
|
||||
private static void bar(final String s) {}
|
||||
|
||||
public static void main(String[] argArr) {
|
||||
Test.<String>_f(b<caret>);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,10 @@ class P2 {
|
||||
});
|
||||
test(this::<warning descr="Method annotated with @Nullable must not override @NotNull method">getNull</warning>);
|
||||
test(this::getPrimitive);
|
||||
test(this::<warning descr="Not annotated method is used as an override for a method annotated with NotNull">getNonAnnotated</warning>);
|
||||
|
||||
test(WithImplicitConstructor::new);
|
||||
test(WithExplicitConstructor::new);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -29,3 +33,6 @@ class P2 {
|
||||
|
||||
private void test(final NonnullInterface function) { }
|
||||
}
|
||||
|
||||
class WithImplicitConstructor {}
|
||||
class WithExplicitConstructor { WithExplicitConstructor() {} }
|
||||
+4
@@ -42,6 +42,10 @@ public class SmartType17CompletionTest extends LightFixtureCompletionTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testDiamondCollapsedWithMethodTypeParameter() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testDiamondNotCollapsed() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
+4
@@ -156,6 +156,10 @@ public class SmartType18CompletionTest extends LightFixtureCompletionTestCase {
|
||||
}
|
||||
|
||||
public void testStaticMethodReference() { doTest(false); }
|
||||
public void testStaticMethodReferenceInContextWithTypeArgs() {
|
||||
configureByTestName();
|
||||
checkResultByFile("/" + getTestName(false) + "-out.java");
|
||||
}
|
||||
|
||||
public void testOuterMethodReference() { doTest(true); }
|
||||
public void testNoAnonymousOuterMethodReference() { doAntiTest(); }
|
||||
|
||||
@@ -862,6 +862,10 @@ public class TypeMigrationTest extends TypeMigrationTestBase {
|
||||
doTestMethodType("migrationMethod", PsiType.VOID);
|
||||
}
|
||||
|
||||
public void testGenericEllipsis() {
|
||||
doTestFieldType("migrationField", myJavaFacade.getElementFactory().createTypeFromText("Test<Short>", null));
|
||||
}
|
||||
|
||||
private void doTestReturnType(final String methodName, final String migrationType) {
|
||||
start(new RulesProvider() {
|
||||
@Override
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
Types:
|
||||
PsiField:migrationField : Test<java.lang.Short>
|
||||
PsiMethodCallExpression:migrationField.method() : void
|
||||
PsiReferenceExpression:migrationField : Test<java.lang.Short>
|
||||
|
||||
Conversions:
|
||||
migrationField.method() -> $
|
||||
|
||||
New expression type changes:
|
||||
Fails:
|
||||
@@ -0,0 +1,11 @@
|
||||
class Test<X> {
|
||||
private static Test<Short> migrationField;
|
||||
|
||||
private static void m() {
|
||||
migrationField.method();
|
||||
}
|
||||
|
||||
void method(X... xes) {
|
||||
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class Test<X> {
|
||||
private static Test<Integer> migrationField;
|
||||
|
||||
private static void m() {
|
||||
migrationField.method();
|
||||
}
|
||||
|
||||
void method(X... xes) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -119,28 +119,28 @@ public class _JsonLexer implements FlexLexer {
|
||||
/* The ZZ_CMAP_A table has 920 entries */
|
||||
static final char ZZ_CMAP_A[] = zzUnpackCMap(
|
||||
"\11\20\1\3\1\2\2\1\1\2\6\20\4\0\1\3\1\20\1\7\1\0\1\20\2\0\1\11\2\20\1\6\1"+
|
||||
"\17\1\25\1\12\1\15\1\4\1\13\11\14\1\26\5\0\5\20\1\16\5\20\1\23\1\10\1\24\1"+
|
||||
"\0\1\20\1\0\1\34\3\20\1\32\1\33\5\20\1\35\1\20\1\37\3\20\1\30\1\36\1\27\1"+
|
||||
"\31\5\20\1\21\1\0\1\22\7\20\1\5\2\20\1\3\1\0\4\20\4\0\1\20\2\0\1\20\7\0\1"+
|
||||
"\20\4\0\1\20\5\0\7\20\1\0\2\20\4\0\4\20\16\0\5\20\7\0\1\20\1\0\1\20\1\0\5"+
|
||||
"\20\1\0\2\20\2\0\4\20\10\0\1\20\1\0\3\20\1\0\1\20\1\0\4\20\1\0\13\20\1\0\1"+
|
||||
"\20\2\0\6\20\1\0\7\20\1\0\1\20\15\0\1\20\1\0\2\20\1\0\2\20\1\0\4\20\10\0\1"+
|
||||
"\20\4\0\4\20\1\0\4\20\1\0\13\20\2\0\4\20\2\0\11\20\6\0\10\20\2\0\2\20\1\0"+
|
||||
"\3\20\1\0\4\20\2\0\6\20\1\0\1\20\3\0\4\20\2\0\5\20\2\0\4\20\5\0\2\20\1\0\4"+
|
||||
"\20\4\0\2\20\1\0\2\20\1\0\2\20\1\0\2\20\2\0\1\20\1\0\3\20\2\0\3\20\3\0\4\20"+
|
||||
"\1\0\1\20\7\0\3\20\1\0\2\20\1\0\5\20\1\0\3\20\2\0\1\20\11\0\2\20\1\0\6\20"+
|
||||
"\3\0\3\20\1\0\4\20\3\0\2\20\1\0\1\20\1\0\2\20\3\0\2\20\3\0\1\20\6\0\3\20\3"+
|
||||
"\0\3\20\5\0\2\20\2\0\2\20\5\0\1\20\1\0\5\20\1\0\4\20\1\0\1\20\4\0\1\20\4\0"+
|
||||
"\6\20\1\0\1\20\3\0\2\20\5\0\2\20\1\0\1\20\2\0\2\20\1\0\1\20\2\0\1\20\3\0\3"+
|
||||
"\20\1\0\1\20\1\0\1\20\5\0\1\20\1\0\1\20\1\0\1\20\4\0\5\20\1\0\4\20\1\3\10"+
|
||||
"\20\1\0\2\20\4\0\4\20\3\0\1\20\3\0\3\20\5\0\5\20\1\0\1\20\1\0\1\20\1\0\1\20"+
|
||||
"\1\0\1\20\2\0\3\20\1\0\2\20\13\3\5\20\2\1\5\20\1\3\4\0\1\20\12\0\1\3\1\0\1"+
|
||||
"\20\3\0\3\20\1\0\5\20\2\0\1\20\1\0\4\20\1\0\1\20\5\0\5\20\4\0\1\20\1\0\1\3"+
|
||||
"\4\0\3\20\1\0\2\20\2\0\3\20\2\0\5\20\2\0\6\20\1\0\3\20\1\0\2\20\2\0\2\20\1"+
|
||||
"\0\2\20\1\0\2\20\2\0\3\20\3\0\2\20\3\0\2\20\2\0\3\20\4\0\3\20\1\0\2\20\1\0"+
|
||||
"\2\20\3\0\1\20\2\0\5\20\1\0\2\20\1\0\3\20\2\0\1\20\4\0\1\20\2\0\2\20\2\0\4"+
|
||||
"\20\1\0\4\20\1\0\1\20\1\0\5\20\1\0\4\20\2\0\1\20\1\0\1\20\5\0\1\20\1\0\1\20"+
|
||||
"\1\0\3\20");
|
||||
"\17\1\25\1\12\1\15\1\4\1\13\11\14\1\26\1\0\3\20\1\0\5\20\1\16\5\20\1\23\1"+
|
||||
"\10\1\24\2\20\1\0\1\34\3\20\1\32\1\33\5\20\1\35\1\20\1\37\3\20\1\30\1\36\1"+
|
||||
"\27\1\31\5\20\1\21\1\0\1\22\7\20\1\5\2\20\1\3\1\0\4\20\4\0\1\20\2\0\1\20\7"+
|
||||
"\0\1\20\4\0\1\20\5\0\7\20\1\0\2\20\4\0\4\20\16\0\5\20\7\0\1\20\1\0\1\20\1"+
|
||||
"\0\5\20\1\0\2\20\2\0\4\20\10\0\1\20\1\0\3\20\1\0\1\20\1\0\4\20\1\0\13\20\1"+
|
||||
"\0\1\20\2\0\6\20\1\0\7\20\1\0\1\20\15\0\1\20\1\0\2\20\1\0\2\20\1\0\4\20\10"+
|
||||
"\0\1\20\4\0\4\20\1\0\4\20\1\0\13\20\2\0\4\20\2\0\11\20\6\0\10\20\2\0\2\20"+
|
||||
"\1\0\3\20\1\0\4\20\2\0\6\20\1\0\1\20\3\0\4\20\2\0\5\20\2\0\4\20\5\0\2\20\1"+
|
||||
"\0\4\20\4\0\2\20\1\0\2\20\1\0\2\20\1\0\2\20\2\0\1\20\1\0\3\20\2\0\3\20\3\0"+
|
||||
"\4\20\1\0\1\20\7\0\3\20\1\0\2\20\1\0\5\20\1\0\3\20\2\0\1\20\11\0\2\20\1\0"+
|
||||
"\6\20\3\0\3\20\1\0\4\20\3\0\2\20\1\0\1\20\1\0\2\20\3\0\2\20\3\0\1\20\6\0\3"+
|
||||
"\20\3\0\3\20\5\0\2\20\2\0\2\20\5\0\1\20\1\0\5\20\1\0\4\20\1\0\1\20\4\0\1\20"+
|
||||
"\4\0\6\20\1\0\1\20\3\0\2\20\5\0\2\20\1\0\1\20\2\0\2\20\1\0\1\20\2\0\1\20\3"+
|
||||
"\0\3\20\1\0\1\20\1\0\1\20\5\0\1\20\1\0\1\20\1\0\1\20\4\0\5\20\1\0\4\20\1\3"+
|
||||
"\10\20\1\0\2\20\4\0\4\20\3\0\1\20\3\0\3\20\5\0\5\20\1\0\1\20\1\0\1\20\1\0"+
|
||||
"\1\20\1\0\1\20\2\0\3\20\1\0\2\20\13\3\5\20\2\1\5\20\1\3\4\0\1\20\12\0\1\3"+
|
||||
"\1\0\1\20\3\0\3\20\1\0\5\20\2\0\1\20\1\0\4\20\1\0\1\20\5\0\5\20\4\0\1\20\1"+
|
||||
"\0\1\3\4\0\3\20\1\0\2\20\2\0\3\20\2\0\5\20\2\0\6\20\1\0\3\20\1\0\2\20\2\0"+
|
||||
"\2\20\1\0\2\20\1\0\2\20\2\0\3\20\3\0\2\20\3\0\2\20\2\0\3\20\4\0\3\20\1\0\2"+
|
||||
"\20\1\0\2\20\3\0\1\20\2\0\5\20\1\0\2\20\1\0\3\20\2\0\1\20\4\0\1\20\2\0\2\20"+
|
||||
"\2\0\4\20\1\0\4\20\1\0\1\20\1\0\5\20\1\0\4\20\2\0\1\20\1\0\1\20\5\0\1\20\1"+
|
||||
"\0\1\20\1\0\3\20");
|
||||
|
||||
/**
|
||||
* Translates DFA states to action switch labels.
|
||||
|
||||
+3
-2
@@ -43,9 +43,10 @@
|
||||
// auto completion of keywords. Semantically, it represents "bad word" type
|
||||
// of tokens
|
||||
// Could be as loose as [^\s\[\]{}:,\"\']+, but is slightly more restricted
|
||||
// for the time being to match most forms of npm package names in package.json.
|
||||
// for the time being to match most forms of npm package names and semver versions
|
||||
// in package.json.
|
||||
// See https://github.com/npm/validate-npm-package-name
|
||||
IDENTIFIER="regexp:[[:jletterdigit:]~!()*\-./@]+"
|
||||
IDENTIFIER="regexp:[[:jletterdigit:]~!()*\-./@\^<>=]+"
|
||||
]
|
||||
|
||||
extends("container|literal|reference_expression")=value
|
||||
|
||||
@@ -30,7 +30,7 @@ BLOCK_COMMENT="/"\*([^*]|\*+[^*/])*(\*+"/")?
|
||||
DOUBLE_QUOTED_STRING=\"([^\\\"\r\n]|\\[^\r\n])*\"?
|
||||
SINGLE_QUOTED_STRING='([^\\'\r\n]|\\[^\r\n])*'?
|
||||
NUMBER=-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]*)?
|
||||
IDENTIFIER=[[:jletterdigit:]~!()*\-."/"@]+
|
||||
IDENTIFIER=[[:jletterdigit:]~!()*\-."/"@\^<>=]+
|
||||
|
||||
%%
|
||||
<YYINITIAL> {
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
{
|
||||
<weak_warning descr="JSON standard does not allow comments. Use JSMin or similar tool to remove comments before parsing.">/* Property key checks */</weak_warning>
|
||||
"dependencies": {
|
||||
<error descr="JSON standard does not allow such tokens">@foo/bar</error>: <error descr="JSON standard does not allow such tokens">^0.1</error>,
|
||||
<error descr="JSON standard does not allow such tokens">foo.bar</error>: <error descr="JSON standard does not allow such tokens">=1.2</error>
|
||||
},
|
||||
"key1": null,
|
||||
<error descr="JSON standard allows only double quoted string as property key"><error descr="JSON standard does not allow single quoted strings">'key2'</error></error>: null,
|
||||
<error descr="JSON standard does not allow such tokens">key3</error>: null,
|
||||
@@ -10,7 +14,7 @@
|
||||
"key5": <error descr="JSON standard does not allow single quoted strings">'foo'</error>,
|
||||
"key6": <error descr="JSON standard does not allow such tokens">foo</error>,
|
||||
"key7": [42<error descr="JSON standard does not allow trailing comma">,</error>],
|
||||
"key8": false<error descr="JSON standard does not allow trailing comma">,</error>
|
||||
"key8": false<error descr="JSON standard does not allow trailing comma">,</error>
|
||||
}
|
||||
<error descr="JSON standard allows only one top-level value">["another", "top-level", "value"]</error>
|
||||
<error descr="JSON standard allows only one top-level value">null</error>
|
||||
@@ -1,5 +1,11 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
@types/3d-bin.packing: 42
|
||||
@types/3d-bin.packing: 42,
|
||||
"pkg1": ^4.15.0,
|
||||
"pkg2": ~4.15.0,
|
||||
"pkg3": >4.15.0,
|
||||
"pkg4": >=4.15.0,
|
||||
"pkg5": <4.15.0,
|
||||
"pkg6": <=4.15.0
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,60 @@ JsonFile: ExtendedIdentifierToken.json
|
||||
PsiWhiteSpace(' ')
|
||||
JsonNumberLiteral
|
||||
PsiElement(NUMBER)('42')
|
||||
PsiElement(,)(',')
|
||||
PsiWhiteSpace('\n ')
|
||||
JsonProperty
|
||||
JsonStringLiteral
|
||||
PsiElement(DOUBLE_QUOTED_STRING)('"pkg1"')
|
||||
PsiElement(:)(':')
|
||||
PsiWhiteSpace(' ')
|
||||
JsonReferenceExpression
|
||||
PsiElement(IDENTIFIER)('^4.15.0')
|
||||
PsiElement(,)(',')
|
||||
PsiWhiteSpace('\n ')
|
||||
JsonProperty
|
||||
JsonStringLiteral
|
||||
PsiElement(DOUBLE_QUOTED_STRING)('"pkg2"')
|
||||
PsiElement(:)(':')
|
||||
PsiWhiteSpace(' ')
|
||||
JsonReferenceExpression
|
||||
PsiElement(IDENTIFIER)('~4.15.0')
|
||||
PsiElement(,)(',')
|
||||
PsiWhiteSpace('\n ')
|
||||
JsonProperty
|
||||
JsonStringLiteral
|
||||
PsiElement(DOUBLE_QUOTED_STRING)('"pkg3"')
|
||||
PsiElement(:)(':')
|
||||
PsiWhiteSpace(' ')
|
||||
JsonReferenceExpression
|
||||
PsiElement(IDENTIFIER)('>4.15.0')
|
||||
PsiElement(,)(',')
|
||||
PsiWhiteSpace('\n ')
|
||||
JsonProperty
|
||||
JsonStringLiteral
|
||||
PsiElement(DOUBLE_QUOTED_STRING)('"pkg4"')
|
||||
PsiElement(:)(':')
|
||||
PsiWhiteSpace(' ')
|
||||
JsonReferenceExpression
|
||||
PsiElement(IDENTIFIER)('>=4.15.0')
|
||||
PsiElement(,)(',')
|
||||
PsiWhiteSpace('\n ')
|
||||
JsonProperty
|
||||
JsonStringLiteral
|
||||
PsiElement(DOUBLE_QUOTED_STRING)('"pkg5"')
|
||||
PsiElement(:)(':')
|
||||
PsiWhiteSpace(' ')
|
||||
JsonReferenceExpression
|
||||
PsiElement(IDENTIFIER)('<4.15.0')
|
||||
PsiElement(,)(',')
|
||||
PsiWhiteSpace('\n ')
|
||||
JsonProperty
|
||||
JsonStringLiteral
|
||||
PsiElement(DOUBLE_QUOTED_STRING)('"pkg6"')
|
||||
PsiElement(:)(':')
|
||||
PsiWhiteSpace(' ')
|
||||
JsonReferenceExpression
|
||||
PsiElement(IDENTIFIER)('<=4.15.0')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiElement(})('}')
|
||||
PsiWhiteSpace('\n')
|
||||
|
||||
+4
@@ -27,6 +27,7 @@ import com.intellij.packaging.artifacts.ModifiableArtifactModel;
|
||||
import com.intellij.packaging.elements.PackagingElementResolvingContext;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Vladislav.Soroka
|
||||
@@ -71,4 +72,7 @@ public interface IdeModifiableModelsProvider extends IdeModelsProvider {
|
||||
void dispose();
|
||||
|
||||
void setTestModuleProperties(Module testModule, String productionModuleName);
|
||||
|
||||
@Nullable
|
||||
String getProductionModuleName(Module module);
|
||||
}
|
||||
|
||||
+2
@@ -46,6 +46,8 @@ public interface ImportSpec {
|
||||
|
||||
boolean isPreviewMode();
|
||||
|
||||
boolean shouldCreateDirectoriesForEmptyContentRoots();
|
||||
|
||||
boolean isReportRefreshError();
|
||||
|
||||
@Nullable
|
||||
|
||||
+24
@@ -43,6 +43,7 @@ public class ImportSpecBuilder {
|
||||
@Nullable private String myVmOptions;
|
||||
@Nullable private String myArguments;
|
||||
private boolean myUseDefaultCallback;
|
||||
private boolean myCreateDirectoriesForEmptyContentRoots;
|
||||
|
||||
public ImportSpecBuilder(@NotNull Project project, @NotNull ProjectSystemId id) {
|
||||
myProject = project;
|
||||
@@ -50,6 +51,11 @@ public class ImportSpecBuilder {
|
||||
myProgressExecutionMode = ProgressExecutionMode.IN_BACKGROUND_ASYNC;
|
||||
}
|
||||
|
||||
public ImportSpecBuilder(ImportSpec importSpec) {
|
||||
this(importSpec.getProject(), importSpec.getExternalSystemId());
|
||||
apply(importSpec);
|
||||
}
|
||||
|
||||
public ImportSpecBuilder whenAutoImportEnabled() {
|
||||
myWhenAutoImportEnabled = true;
|
||||
return this;
|
||||
@@ -79,6 +85,11 @@ public class ImportSpecBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ImportSpecBuilder createDirectoriesForEmptyContentRoots() {
|
||||
myCreateDirectoriesForEmptyContentRoots = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ImportSpecBuilder dontReportRefreshErrors() {
|
||||
isReportRefreshError = false;
|
||||
return this;
|
||||
@@ -104,6 +115,7 @@ public class ImportSpecBuilder {
|
||||
mySpec.setWhenAutoImportEnabled(myWhenAutoImportEnabled);
|
||||
mySpec.setProgressExecutionMode(myProgressExecutionMode);
|
||||
mySpec.setForceWhenUptodate(myForceWhenUptodate);
|
||||
mySpec.setCreateDirectoriesForEmptyContentRoots(myCreateDirectoriesForEmptyContentRoots);
|
||||
if (myUseDefaultCallback) {
|
||||
mySpec.setCallback(new ExternalProjectRefreshCallback() {
|
||||
@Override
|
||||
@@ -129,4 +141,16 @@ public class ImportSpecBuilder {
|
||||
mySpec.setVmOptions(myVmOptions);
|
||||
return mySpec;
|
||||
}
|
||||
|
||||
private void apply(ImportSpec spec) {
|
||||
myWhenAutoImportEnabled = spec.whenAutoImportEnabled();
|
||||
myProgressExecutionMode = spec.getProgressExecutionMode();
|
||||
myForceWhenUptodate = spec.isForceWhenUptodate();
|
||||
myCreateDirectoriesForEmptyContentRoots = spec.shouldCreateDirectoriesForEmptyContentRoots();
|
||||
myCallback = spec.getCallback();
|
||||
isPreviewMode = spec.isPreviewMode();
|
||||
isReportRefreshError = spec.isReportRefreshError();
|
||||
myArguments = spec.getArguments();
|
||||
myVmOptions = spec.getVmOptions();
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -34,6 +34,7 @@ public class ImportSpecImpl implements ImportSpec {
|
||||
private boolean whenAutoImportEnabled;
|
||||
@Nullable private ExternalProjectRefreshCallback myCallback;
|
||||
private boolean isPreviewMode;
|
||||
private boolean createDirectoriesForEmptyContentRoots;
|
||||
private boolean isReportRefreshError;
|
||||
@Nullable private String myVmOptions;
|
||||
@Nullable private String myArguments;
|
||||
@@ -103,6 +104,15 @@ public class ImportSpecImpl implements ImportSpec {
|
||||
this.isPreviewMode = isPreviewMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCreateDirectoriesForEmptyContentRoots() {
|
||||
return createDirectoriesForEmptyContentRoots;
|
||||
}
|
||||
|
||||
public void setCreateDirectoriesForEmptyContentRoots(boolean createDirectoriesForEmptyContentRoots) {
|
||||
this.createDirectoriesForEmptyContentRoots = createDirectoriesForEmptyContentRoots;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReportRefreshError() {
|
||||
return isReportRefreshError;
|
||||
|
||||
+2
-1
@@ -52,7 +52,8 @@ public class ExternalSystemStartupActivity implements StartupActivity {
|
||||
for (ExternalSystemManager manager : ExternalSystemManager.EP_NAME.getExtensions()) {
|
||||
final boolean isNewProject = project.getUserData(ExternalSystemDataKeys.NEWLY_CREATED_PROJECT) == Boolean.TRUE;
|
||||
if (isNewProject) {
|
||||
ExternalSystemUtil.refreshProjects(new ImportSpecBuilder(project, manager.getSystemId()));
|
||||
ExternalSystemUtil.refreshProjects(new ImportSpecBuilder(project, manager.getSystemId())
|
||||
.createDirectoriesForEmptyContentRoots());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -433,4 +433,10 @@ public abstract class AbstractIdeModifiableModelsProvider extends IdeModelsProvi
|
||||
public void setTestModuleProperties(Module testModule, String productionModuleName) {
|
||||
myProductionModulesForTestModules.put(testModule, productionModuleName);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getProductionModuleName(Module module) {
|
||||
return myProductionModulesForTestModules.get(module);
|
||||
}
|
||||
}
|
||||
|
||||
+40
-8
@@ -15,11 +15,11 @@
|
||||
*/
|
||||
package com.intellij.openapi.externalSystem.service.project.manage;
|
||||
|
||||
import com.intellij.ide.projectView.ProjectView;
|
||||
import com.intellij.ide.projectView.impl.ProjectViewPane;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.externalSystem.model.DataNode;
|
||||
import com.intellij.openapi.externalSystem.model.Key;
|
||||
import com.intellij.openapi.externalSystem.model.ProjectKeys;
|
||||
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
|
||||
import com.intellij.openapi.externalSystem.model.*;
|
||||
import com.intellij.openapi.externalSystem.model.project.ContentRootData;
|
||||
import com.intellij.openapi.externalSystem.model.project.ContentRootData.SourceRoot;
|
||||
import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType;
|
||||
@@ -30,6 +30,7 @@ import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettin
|
||||
import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
|
||||
import com.intellij.openapi.externalSystem.util.Order;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -64,6 +65,8 @@ import java.util.Set;
|
||||
*/
|
||||
@Order(ExternalSystemConstants.BUILTIN_SERVICE_ORDER)
|
||||
public class ContentRootDataService extends AbstractProjectDataService<ContentRootData, ContentEntry> {
|
||||
public static final com.intellij.openapi.util.Key<Boolean> CREATE_EMPTY_DIRECTORIES =
|
||||
com.intellij.openapi.util.Key.create("createEmptyDirectories");
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#" + ContentRootDataService.class.getName());
|
||||
|
||||
@@ -82,6 +85,14 @@ public class ContentRootDataService extends AbstractProjectDataService<ContentRo
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isNewlyImportedProject = project.getUserData(ExternalSystemDataKeys.NEWLY_IMPORTED_PROJECT) == Boolean.TRUE;
|
||||
boolean forceDirectoriesCreation = false;
|
||||
DataNode<ProjectData> projectDataNode = ExternalSystemApiUtil.findParent(toImport.iterator().next(), ProjectKeys.PROJECT);
|
||||
if (projectDataNode != null) {
|
||||
forceDirectoriesCreation = projectDataNode.getUserData(CREATE_EMPTY_DIRECTORIES) == Boolean.TRUE;
|
||||
}
|
||||
|
||||
Set<Module> modulesToExpand = ContainerUtil.newTroveSet();
|
||||
MultiMap<DataNode<ModuleData>, DataNode<ContentRootData>> byModule = ExternalSystemApiUtil.groupBy(toImport, ModuleData.class);
|
||||
for (Map.Entry<DataNode<ModuleData>, Collection<DataNode<ContentRootData>>> entry : byModule.entrySet()) {
|
||||
Module module = entry.getKey().getUserData(AbstractModuleDataService.MODULE_KEY);
|
||||
@@ -93,13 +104,34 @@ public class ContentRootDataService extends AbstractProjectDataService<ContentRo
|
||||
));
|
||||
continue;
|
||||
}
|
||||
importData(modelsProvider, entry.getValue(), module);
|
||||
importData(modelsProvider, entry.getValue(), module, forceDirectoriesCreation);
|
||||
if (forceDirectoriesCreation ||
|
||||
(isNewlyImportedProject &&
|
||||
projectData != null &&
|
||||
projectData.getLinkedExternalProjectPath().equals(ExternalSystemApiUtil.getExternalProjectPath(module)))) {
|
||||
modulesToExpand.add(module);
|
||||
}
|
||||
}
|
||||
if (!modulesToExpand.isEmpty()) {
|
||||
for (Module module : modulesToExpand) {
|
||||
String productionModuleName = modelsProvider.getProductionModuleName(module);
|
||||
if (productionModuleName == null || !modulesToExpand.contains(modelsProvider.findIdeModule(productionModuleName))) {
|
||||
VirtualFile[] roots = modelsProvider.getModifiableRootModel(module).getContentRoots();
|
||||
if (roots.length > 0) {
|
||||
VirtualFile virtualFile = roots[0];
|
||||
ExternalSystemUtil.invokeLater(project, ModalityState.NON_MODAL, () -> {
|
||||
final ProjectView projectView = ProjectView.getInstance(project);
|
||||
projectView.changeViewCB(ProjectViewPane.ID, null).doWhenProcessed(() -> projectView.selectCB(null, virtualFile, false));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void importData(@NotNull IdeModifiableModelsProvider modelsProvider,
|
||||
@NotNull final Collection<DataNode<ContentRootData>> data,
|
||||
@NotNull final Module module) {
|
||||
@NotNull final Module module, boolean forceDirectoriesCreation) {
|
||||
final ModifiableRootModel modifiableRootModel = modelsProvider.getModifiableRootModel(module);
|
||||
final ContentEntry[] contentEntries = modifiableRootModel.getContentEntries();
|
||||
final Map<String, ContentEntry> contentEntriesMap = ContainerUtilRt.newHashMap();
|
||||
@@ -107,8 +139,8 @@ public class ContentRootDataService extends AbstractProjectDataService<ContentRo
|
||||
contentEntriesMap.put(contentEntry.getUrl(), contentEntry);
|
||||
}
|
||||
|
||||
boolean createEmptyContentRootDirectories = false;
|
||||
if (!data.isEmpty()) {
|
||||
boolean createEmptyContentRootDirectories = forceDirectoriesCreation;
|
||||
if (!forceDirectoriesCreation && !data.isEmpty()) {
|
||||
ProjectSystemId projectSystemId = data.iterator().next().getData().getOwner();
|
||||
AbstractExternalSystemSettings externalSystemSettings =
|
||||
ExternalSystemApiUtil.getSettings(module.getProject(), projectSystemId);
|
||||
|
||||
+3
-3
@@ -438,21 +438,21 @@ public class ExternalProjectsDataStorage implements SettingsSavingComponent, Per
|
||||
@Property(surroundWithTag = false)
|
||||
@MapAnnotation(surroundWithTag = false, surroundValueWithTag = false, surroundKeyWithTag = false,
|
||||
keyAttributeName = "path", entryTagName = "projectState")
|
||||
public Map<String, ProjectState> map = ContainerUtil.newConcurrentMap();
|
||||
public final Map<String, ProjectState> map = ContainerUtil.newConcurrentMap();
|
||||
}
|
||||
|
||||
static class ProjectState {
|
||||
@Property(surroundWithTag = false)
|
||||
@MapAnnotation(surroundWithTag = false, surroundValueWithTag = false, surroundKeyWithTag = false,
|
||||
keyAttributeName = "path", entryTagName = "dataType")
|
||||
public Map<String, ModuleState> map = ContainerUtil.newConcurrentMap();
|
||||
public final Map<String, ModuleState> map = ContainerUtil.newConcurrentMap();
|
||||
public boolean isInclusion;
|
||||
}
|
||||
|
||||
static class ModuleState {
|
||||
@Property(surroundWithTag = false)
|
||||
@AbstractCollection(surroundWithTag = false, elementTag = "id")
|
||||
public Set<String> set = ContainerUtil.newConcurrentSet();
|
||||
public final Set<String> set = ContainerUtil.newConcurrentSet();
|
||||
|
||||
public ModuleState() {
|
||||
}
|
||||
|
||||
+7
-1
@@ -101,7 +101,13 @@ public abstract class AbstractExternalProjectSettingsControl<S extends ExternalP
|
||||
if (!myCustomizer.isUseAutoImportBoxHidden() && myUseAutoImportBox != null) {
|
||||
myUseAutoImportBox.setSelected(getInitialSettings().isUseAutoImport());
|
||||
}
|
||||
if (!myCustomizer.isCreateEmptyContentRootDirectoriesBoxHidden() && myCreateEmptyContentRootDirectoriesBox != null) {
|
||||
if(isDefaultModuleCreation) {
|
||||
if(myCreateEmptyContentRootDirectoriesBox != null) {
|
||||
myCreateEmptyContentRootDirectoriesBox.getParent().remove(myCreateEmptyContentRootDirectoriesBox);
|
||||
myCreateEmptyContentRootDirectoriesBox = null;
|
||||
}
|
||||
}
|
||||
if (!isDefaultModuleCreation && !myCustomizer.isCreateEmptyContentRootDirectoriesBoxHidden() && myCreateEmptyContentRootDirectoriesBox != null) {
|
||||
myCreateEmptyContentRootDirectoriesBox.setSelected(getInitialSettings().isCreateEmptyContentRootDirectories());
|
||||
}
|
||||
resetExtraSettings(isDefaultModuleCreation);
|
||||
|
||||
+16
-7
@@ -35,7 +35,6 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.externalSystem.ExternalSystemManager;
|
||||
import com.intellij.openapi.externalSystem.importing.ImportSpec;
|
||||
import com.intellij.openapi.externalSystem.importing.ImportSpecImpl;
|
||||
import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder;
|
||||
import com.intellij.openapi.externalSystem.model.*;
|
||||
import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExecutionSettings;
|
||||
@@ -52,6 +51,7 @@ import com.intellij.openapi.externalSystem.service.internal.ExternalSystemResolv
|
||||
import com.intellij.openapi.externalSystem.service.notification.ExternalSystemNotificationManager;
|
||||
import com.intellij.openapi.externalSystem.service.notification.NotificationSource;
|
||||
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback;
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ContentRootDataService;
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager;
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemTaskActivator;
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
|
||||
@@ -238,7 +238,7 @@ public class ExternalSystemUtil {
|
||||
/**
|
||||
* Asks to refresh all external projects of the target external system linked to the given ide project based on provided spec
|
||||
*
|
||||
* @param specBuilder import specification builder
|
||||
* @param spec import specification
|
||||
*/
|
||||
public static void refreshProjects(@NotNull final ImportSpec spec) {
|
||||
ExternalSystemManager<?, ?, ?, ?, ?> manager = ExternalSystemApiUtil.getManager(spec.getExternalSystemId());
|
||||
@@ -273,8 +273,7 @@ public class ExternalSystemUtil {
|
||||
.clearNotifications(null, NotificationSource.PROJECT_SYNC, spec.getExternalSystemId());
|
||||
|
||||
for (String path : toRefresh) {
|
||||
refreshProject(
|
||||
spec.getProject(), spec.getExternalSystemId(), path, callback, false, spec.getProgressExecutionMode());
|
||||
refreshProject(path, new ImportSpecBuilder(spec).callback(callback).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -394,7 +393,9 @@ public class ExternalSystemUtil {
|
||||
|
||||
ExternalSystemProcessingManager processingManager = ServiceManager.getService(ExternalSystemProcessingManager.class);
|
||||
if (processingManager.findTask(ExternalSystemTaskType.RESOLVE_PROJECT, externalSystemId, externalProjectPath) != null) {
|
||||
callback.onFailure(ExternalSystemBundle.message("error.resolve.already.running", externalProjectPath), null);
|
||||
if (callback != null) {
|
||||
callback.onFailure(ExternalSystemBundle.message("error.resolve.already.running", externalProjectPath), null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -413,7 +414,13 @@ public class ExternalSystemUtil {
|
||||
|
||||
final Throwable error = myTask.getError();
|
||||
if (error == null) {
|
||||
callback.onSuccess(myTask.getExternalProject());
|
||||
if (callback != null) {
|
||||
DataNode<ProjectData> externalProject = myTask.getExternalProject();
|
||||
if (externalProject != null && importSpec.shouldCreateDirectoriesForEmptyContentRoots()) {
|
||||
externalProject.putUserData(ContentRootDataService.CREATE_EMPTY_DIRECTORIES, Boolean.TRUE);
|
||||
}
|
||||
callback.onSuccess(externalProject);
|
||||
}
|
||||
if (!isPreviewMode) {
|
||||
externalSystemTaskActivator.runTasks(externalProjectPath, ExternalSystemTaskActivator.Phase.AFTER_SYNC);
|
||||
}
|
||||
@@ -430,7 +437,9 @@ public class ExternalSystemUtil {
|
||||
);
|
||||
}
|
||||
|
||||
callback.onFailure(message, extractDetails(error));
|
||||
if (callback != null) {
|
||||
callback.onFailure(message, extractDetails(error));
|
||||
}
|
||||
|
||||
ExternalSystemManager<?, ?, ?, ?, ?> manager = ExternalSystemApiUtil.getManager(externalSystemId);
|
||||
if (manager == null) {
|
||||
|
||||
+12
-11
@@ -278,7 +278,7 @@ public abstract class AbstractLayoutCodeProcessor {
|
||||
return new FileTreeIterator(myProject);
|
||||
}
|
||||
|
||||
return new FileTreeIterator(Collections.<PsiFile>emptyList());
|
||||
return new FileTreeIterator(Collections.emptyList());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -355,7 +355,7 @@ public abstract class AbstractLayoutCodeProcessor {
|
||||
LOG.error(e);
|
||||
}
|
||||
};
|
||||
runLayoutCodeProcess(readAction, writeAction, false );
|
||||
runLayoutCodeProcess(readAction, writeAction);
|
||||
}
|
||||
|
||||
private boolean checkFileWritable(final PsiFile file){
|
||||
@@ -396,7 +396,7 @@ public abstract class AbstractLayoutCodeProcessor {
|
||||
return !GeneratedSourcesFilter.isGeneratedSourceByAnyFilter(virtualFile, file.getProject());
|
||||
}
|
||||
|
||||
private void runLayoutCodeProcess(final Runnable readAction, final Runnable writeAction, final boolean globalAction) {
|
||||
private void runLayoutCodeProcess(final Runnable readAction, final Runnable writeAction) {
|
||||
final ProgressWindow progressWindow = new ProgressWindow(true, myProject);
|
||||
progressWindow.setTitle(myCommandName);
|
||||
progressWindow.setText(myProgressText);
|
||||
@@ -418,7 +418,6 @@ public abstract class AbstractLayoutCodeProcessor {
|
||||
}
|
||||
|
||||
final Runnable writeRunnable = () -> CommandProcessor.getInstance().executeCommand(myProject, () -> {
|
||||
if (globalAction) CommandProcessor.getInstance().markCurrentCommandAsGlobal(myProject);
|
||||
try {
|
||||
writeAction.run();
|
||||
|
||||
@@ -544,18 +543,15 @@ public abstract class AbstractLayoutCodeProcessor {
|
||||
}
|
||||
|
||||
private void performFileProcessing(@NotNull PsiFile file) {
|
||||
myProcessors.stream().forEach((processor) -> {
|
||||
Ref<FutureTask<Boolean>> writeTaskRef = Ref.create();
|
||||
|
||||
ApplicationManager.getApplication().runReadAction(() -> writeTaskRef.set(processor.prepareTask(file, myProcessChangedTextOnly)));
|
||||
for (AbstractLayoutCodeProcessor processor : myProcessors) {
|
||||
FutureTask<Boolean> writeTask = ReadAction.compute(() -> processor.prepareTask(file, myProcessChangedTextOnly));
|
||||
|
||||
ProgressIndicatorProvider.checkCanceled();
|
||||
FutureTask<Boolean> writeTask = writeTaskRef.get();
|
||||
|
||||
|
||||
ApplicationManager.getApplication().invokeAndWait(() -> WriteCommandAction.runWriteCommandAction(myProject, myCommandName, null, writeTask));
|
||||
|
||||
checkStop(writeTask, file);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void checkStop(FutureTask<Boolean> task, PsiFile file) {
|
||||
@@ -565,6 +561,11 @@ public abstract class AbstractLayoutCodeProcessor {
|
||||
}
|
||||
}
|
||||
catch (InterruptedException | ExecutionException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof IndexNotReadyException) {
|
||||
LOG.warn(cause);
|
||||
return;
|
||||
}
|
||||
LOG.error("Got unexpected exception during formatting " + file, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,13 +25,8 @@ import com.intellij.ide.GeneralSettings;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -75,12 +70,11 @@ public class TerminateRemoteProcessDialog {
|
||||
};
|
||||
|
||||
AtomicBoolean alreadyGone = new AtomicBoolean(false);
|
||||
Window projectWindow = WindowManager.getInstance().suggestParentWindow(project);
|
||||
Runnable dialogRemover = Messages.createMessageDialogRemover(project);
|
||||
ProcessAdapter listener = new ProcessAdapter() {
|
||||
public void processWillTerminate(ProcessEvent event, boolean willBeDestroyed) {
|
||||
alreadyGone.set(true);
|
||||
UIUtil.invokeLaterIfNeeded(() -> makeCurrentMessageDialogGoAway(
|
||||
projectWindow != null ? projectWindow.getOwnedWindows() : Window.getWindows()));
|
||||
dialogRemover.run();
|
||||
}
|
||||
};
|
||||
processHandler.addProcessListener(listener);
|
||||
@@ -101,17 +95,6 @@ public class TerminateRemoteProcessDialog {
|
||||
return getConfirmation(exitCode, canDisconnect);
|
||||
}
|
||||
|
||||
private static void makeCurrentMessageDialogGoAway(@NotNull Window[] checkWindows) {
|
||||
for (Window w : checkWindows) {
|
||||
JDialog dialog = w instanceof JDialog ? (JDialog)w : null;
|
||||
if (dialog == null || !dialog.isModal()) continue;
|
||||
JButton cancelButton = UIUtil.uiTraverser(dialog.getRootPane()).filter(JButton.class)
|
||||
.filter(b -> CommonBundle.getCancelButtonText().equals(b.getText()))
|
||||
.first();
|
||||
if (cancelButton != null) cancelButton.doClick();
|
||||
}
|
||||
}
|
||||
|
||||
private static GeneralSettings.ProcessCloseConfirmation getConfirmation(int button, boolean withDisconnect) {
|
||||
switch (button) {
|
||||
case 0:
|
||||
|
||||
@@ -531,7 +531,7 @@ public abstract class HierarchyBrowserBaseEx extends HierarchyBrowserBase implem
|
||||
changeView(currentViewType);
|
||||
final HierarchyTreeBuilder builder = getCurrentBuilder();
|
||||
builder.restoreExpandedAndSelectedInfo(storedInfo.get());
|
||||
}, __->!myAlarm.isDisposed());
|
||||
}, __-> isDisposed());
|
||||
}
|
||||
|
||||
protected String getCurrentScopeType() {
|
||||
|
||||
@@ -36,8 +36,10 @@ public class AnsiEscapeDecoder {
|
||||
private static final String M_CSI = "m" + CSI;
|
||||
private static final char BACKSPACE = '\b';
|
||||
|
||||
private Key myCurrentTextAttributes;
|
||||
private final ColoredOutputTypeRegistry myColoredOutputTypeRegistry = ColoredOutputTypeRegistry.getInstance();
|
||||
private Key myCurrentTextAttributes;
|
||||
private String myUnhandledStdout;
|
||||
private String myUnhandledStderr;
|
||||
|
||||
/**
|
||||
* Parses ansi-color codes from text and sends text fragments with color attributes to textAcceptor
|
||||
@@ -48,31 +50,40 @@ public class AnsiEscapeDecoder {
|
||||
* It can implement ColoredChunksAcceptor to receive list of pairs (text, attribute).
|
||||
*/
|
||||
public void escapeText(@NotNull String text, @NotNull Key outputType, @NotNull ColoredTextAcceptor textAcceptor) {
|
||||
text = prependUnhandledText(text, outputType);
|
||||
text = normalizeAsciiControlCharacters(text);
|
||||
int pos = 0;
|
||||
List<Pair<String, Key>> chunks = null;
|
||||
int unhandledSuffixLength = 0;
|
||||
while (true) {
|
||||
int escSeqBeginInd = text.indexOf(CSI, pos);
|
||||
int escSeqBeginInd = findEscSeqBeginIndex(text, pos);
|
||||
if (escSeqBeginInd < 0) {
|
||||
if (escSeqBeginInd < -1) {
|
||||
unhandledSuffixLength = decodeUnhandledSuffixLength(escSeqBeginInd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (pos < escSeqBeginInd) {
|
||||
chunks = processTextChunk(chunks, text.substring(pos, escSeqBeginInd), outputType, textAcceptor);
|
||||
}
|
||||
final int escSeqEndInd = findEscSeqEndIndex(text, escSeqBeginInd);
|
||||
int escSeqEndInd = findConsecutiveEscSequencesEndIndex(text, escSeqBeginInd);
|
||||
if (escSeqEndInd < 0) {
|
||||
if (escSeqEndInd < -1) {
|
||||
unhandledSuffixLength = decodeUnhandledSuffixLength(escSeqEndInd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (text.charAt(escSeqEndInd - 1) == 'm') {
|
||||
String escSeq = text.substring(escSeqBeginInd, escSeqEndInd);
|
||||
if (text.charAt(escSeqEndInd) == 'm') {
|
||||
String escSeq = text.substring(escSeqBeginInd, escSeqEndInd + 1);
|
||||
// this is a simple fix for RUBY-8996:
|
||||
// we replace several consecutive escape sequences with one which contains all these sequences
|
||||
String colorAttribute = StringUtil.replace(escSeq, M_CSI, ";");
|
||||
myCurrentTextAttributes = myColoredOutputTypeRegistry.getOutputKey(colorAttribute);
|
||||
}
|
||||
pos = escSeqEndInd;
|
||||
pos = escSeqEndInd + 1;
|
||||
}
|
||||
if (pos < text.length()) {
|
||||
updateUnhandledSuffix(text, outputType, unhandledSuffixLength);
|
||||
if (unhandledSuffixLength == 0 && pos < text.length()) {
|
||||
chunks = processTextChunk(chunks, text.substring(pos), outputType, textAcceptor);
|
||||
}
|
||||
if (chunks != null && textAcceptor instanceof ColoredChunksAcceptor) {
|
||||
@@ -80,6 +91,30 @@ public class AnsiEscapeDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateUnhandledSuffix(@NotNull String text, @NotNull Key outputType, int unhandledSuffixLength) {
|
||||
String unhandledSuffix = unhandledSuffixLength > 0 ? text.substring(text.length() - unhandledSuffixLength) : null;
|
||||
if (outputType == ProcessOutputTypes.STDOUT) {
|
||||
myUnhandledStdout = unhandledSuffix;
|
||||
}
|
||||
else if (outputType == ProcessOutputTypes.STDERR) {
|
||||
myUnhandledStderr = unhandledSuffix;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String prependUnhandledText(@NotNull String text, @NotNull Key outputType) {
|
||||
String prevUnhandledText = null;
|
||||
if (outputType == ProcessOutputTypes.STDOUT) {
|
||||
prevUnhandledText = myUnhandledStdout;
|
||||
myUnhandledStdout = null;
|
||||
}
|
||||
else if (outputType == ProcessOutputTypes.STDERR) {
|
||||
prevUnhandledText = myUnhandledStderr;
|
||||
myUnhandledStderr = null;
|
||||
}
|
||||
return prevUnhandledText != null ? prevUnhandledText + text : text;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String normalizeAsciiControlCharacters(@NotNull String text) {
|
||||
int ind = text.indexOf(BACKSPACE);
|
||||
@@ -122,29 +157,58 @@ public class AnsiEscapeDecoder {
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Selects all consecutive escape sequences and returns escape sequence end index (exclusive).
|
||||
* If the escape sequence isn't finished, returns -1.
|
||||
/**
|
||||
* Returns the index of the first occurrence of CSI within the passed string that is greater than or equal to {@code fromIndex},
|
||||
* or negative number if CSI is not found: -1 - (length of text suffix to keep in case of an incomplete CSI).
|
||||
*/
|
||||
private static int findEscSeqEndIndex(@NotNull String text, final int escSeqBeginInd) {
|
||||
int beginInd = escSeqBeginInd;
|
||||
while (true) {
|
||||
int letterInd = findEscSeqLetterIndex(text, beginInd);
|
||||
if (letterInd == -1) {
|
||||
return beginInd == escSeqBeginInd ? -1 : beginInd;
|
||||
}
|
||||
if (text.charAt(letterInd) != 'm') {
|
||||
return beginInd == escSeqBeginInd ? letterInd + 1 : beginInd;
|
||||
}
|
||||
beginInd = letterInd + 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static int findEscSeqLetterIndex(@NotNull String text, int escSeqBeginInd) {
|
||||
if (!text.regionMatches(escSeqBeginInd, CSI, 0, CSI.length())) {
|
||||
private static int findEscSeqBeginIndex(@NotNull String text, int fromIndex) {
|
||||
int ind = text.indexOf(CSI.charAt(0), fromIndex);
|
||||
if (ind == -1) {
|
||||
return -1;
|
||||
}
|
||||
int parameterEndInd = escSeqBeginInd + 2;
|
||||
else if (ind == text.length() - 1) {
|
||||
return encodeUnhandledSuffixLength(text, ind);
|
||||
}
|
||||
return text.charAt(ind + 1) == CSI.charAt(1) ? ind : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns end index of all consecutive escape sequences started at {@code firstEscSeqBeginInd}, or
|
||||
* negative number if not found: -1 - (length of string suffix to keep in case of an incomplete last escape sequence).
|
||||
*/
|
||||
private static int findConsecutiveEscSequencesEndIndex(@NotNull String text, int firstEscSeqBeginInd) {
|
||||
int escSeqBeginInd = firstEscSeqBeginInd;
|
||||
int lastMatchedColorEscSeqEndInd = -1;
|
||||
int escSeqEndInd;
|
||||
while ((escSeqEndInd = findEscSeqEndIndex(text, escSeqBeginInd)) >= 0) {
|
||||
if (text.charAt(escSeqEndInd) != 'm') {
|
||||
// Handle non-color escape sequences separately
|
||||
// ColoredOutputTypeRegistry expects only color escape sequences and in a single consecutive text chunk
|
||||
return lastMatchedColorEscSeqEndInd > 0 ? lastMatchedColorEscSeqEndInd : escSeqEndInd;
|
||||
}
|
||||
escSeqBeginInd = escSeqEndInd + 1;
|
||||
lastMatchedColorEscSeqEndInd = escSeqEndInd;
|
||||
if (escSeqEndInd + 1 >= text.length()) {
|
||||
return encodeUnhandledSuffixLength(text, firstEscSeqBeginInd);
|
||||
}
|
||||
if (text.charAt(escSeqEndInd + 1) != CSI.charAt(0)) {
|
||||
break;
|
||||
}
|
||||
if (escSeqEndInd + 2 >= text.length()) {
|
||||
return encodeUnhandledSuffixLength(text, firstEscSeqBeginInd);
|
||||
}
|
||||
if (text.charAt(escSeqEndInd + 2) != CSI.charAt(1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (escSeqEndInd < -1) {
|
||||
return encodeUnhandledSuffixLength(text, firstEscSeqBeginInd);
|
||||
}
|
||||
return lastMatchedColorEscSeqEndInd;
|
||||
}
|
||||
|
||||
private static int findEscSeqEndIndex(@NotNull String text, int escSeqBeginInd) {
|
||||
int parameterEndInd = escSeqBeginInd + CSI.length();
|
||||
while (parameterEndInd < text.length()) {
|
||||
char ch = text.charAt(parameterEndInd);
|
||||
if (Character.isDigit(ch) || ch == ';') {
|
||||
@@ -154,13 +218,21 @@ public class AnsiEscapeDecoder {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (parameterEndInd < text.length()) {
|
||||
char letter = text.charAt(parameterEndInd);
|
||||
if (StringUtil.containsChar("ABCDEFGHJKSTfmisu", letter)) {
|
||||
return parameterEndInd;
|
||||
}
|
||||
if (parameterEndInd == text.length()) {
|
||||
return encodeUnhandledSuffixLength(text, escSeqBeginInd);
|
||||
}
|
||||
return -1;
|
||||
return StringUtil.containsChar("ABCDEFGHJKSTfmisu", text.charAt(parameterEndInd)) ? parameterEndInd : -1;
|
||||
}
|
||||
|
||||
private static int encodeUnhandledSuffixLength(@NotNull String text, int suffixStartInd) {
|
||||
return -1 - (text.length() - suffixStartInd);
|
||||
}
|
||||
|
||||
private static int decodeUnhandledSuffixLength(int encodedUnhandledSuffixLength) {
|
||||
if (encodedUnhandledSuffixLength >= -1) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
return -encodedUnhandledSuffixLength - 1;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+5
-3
@@ -26,6 +26,7 @@ import com.intellij.pom.Navigatable;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.SmartPointerManager;
|
||||
import com.intellij.psi.SmartPsiElementPointer;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.intellij.openapi.util.Conditions.or;
|
||||
@@ -39,8 +40,9 @@ public class PsiElementNavigatable implements Navigatable {
|
||||
|
||||
@Override
|
||||
public final void navigate(boolean requestFocus) {
|
||||
PsiElement element = myPointer.getElement();
|
||||
if (element != null && element.isValid()) {
|
||||
PsiElement originalElement = myPointer.getElement();
|
||||
if (originalElement != null && originalElement.isValid()) {
|
||||
PsiElement element = ObjectUtils.notNull(originalElement.getNavigationElement(), originalElement);
|
||||
VirtualFile file = element.getContainingFile().getVirtualFile();
|
||||
if (file != null) {
|
||||
new Task.Modal(element.getProject(), EditorBundle.message("editor.open.file.progress", file.getName()), true) {
|
||||
@@ -62,7 +64,7 @@ public class PsiElementNavigatable implements Navigatable {
|
||||
@Override
|
||||
public boolean canNavigate() {
|
||||
PsiElement element = myPointer.getElement();
|
||||
return element != null && element.isValid() && element.getContainingFile().getVirtualFile() != null;
|
||||
return element != null && element.isValid() && ObjectUtils.notNull(element.getNavigationElement(), element).getContainingFile().getVirtualFile() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -112,6 +112,24 @@ public class Messages {
|
||||
return UIUtil.getQuestionIcon();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Runnable createMessageDialogRemover(@Nullable Project project) {
|
||||
Window projectWindow = project == null ? null : WindowManager.getInstance().suggestParentWindow(project);
|
||||
return () -> UIUtil.invokeLaterIfNeeded(() -> makeCurrentMessageDialogGoAway(
|
||||
projectWindow != null ? projectWindow.getOwnedWindows() : Window.getWindows()));
|
||||
}
|
||||
|
||||
private static void makeCurrentMessageDialogGoAway(@NotNull Window[] checkWindows) {
|
||||
for (Window w : checkWindows) {
|
||||
JDialog dialog = w instanceof JDialog ? (JDialog)w : null;
|
||||
if (dialog == null || !dialog.isModal()) continue;
|
||||
JButton cancelButton = UIUtil.uiTraverser(dialog.getRootPane()).filter(JButton.class)
|
||||
.filter(b -> CommonBundle.getCancelButtonText().equals(b.getText()))
|
||||
.first();
|
||||
if (cancelButton != null) cancelButton.doClick();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Please, use {@link #showOkCancelDialog} or {@link #showYesNoCancelDialog} if possible (these dialogs implements native OS behavior)!
|
||||
* @return number of button pressed: from 0 up to options.length-1 inclusive, or -1 for Cancel
|
||||
|
||||
@@ -19,10 +19,10 @@ import com.intellij.internal.statistic.beans.ConvertUsagesUtil;
|
||||
import com.intellij.internal.statistic.beans.GroupDescriptor;
|
||||
import com.intellij.internal.statistic.beans.UsageDescriptor;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.xmlb.annotations.MapAnnotation;
|
||||
import com.intellij.util.xmlb.annotations.Tag;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -42,11 +42,11 @@ public class UsageTrigger implements PersistentStateComponent<UsageTrigger.State
|
||||
|
||||
private State myState = new State();
|
||||
|
||||
public static void trigger(@NotNull String feature) {
|
||||
public static void trigger(@NotNull @NonNls String feature) {
|
||||
getInstance().doTrigger(feature);
|
||||
}
|
||||
|
||||
public static void triggerOnce(@NotNull String feature) {
|
||||
public static void triggerOnce(@NotNull @NonNls String feature) {
|
||||
if (!getInstance().myState.myValues.containsKey(feature)) {
|
||||
getInstance().doTrigger(feature);
|
||||
}
|
||||
|
||||
@@ -397,7 +397,7 @@ public final class ActionMenu extends JBMenu {
|
||||
ComponentEvent componentEvent = (ComponentEvent)event;
|
||||
Component component = componentEvent.getComponent();
|
||||
JPopupMenu popup = UIUtil.getParentOfType(JPopupMenu.class, component);
|
||||
if (popup != null && popup.getInvoker() == myComponent) {
|
||||
if (popup != null && popup.getInvoker() == myComponent && popup.isShowing()) {
|
||||
Rectangle bounds = popup.getBounds();
|
||||
if (bounds.isEmpty()) return;
|
||||
bounds.setLocation(popup.getLocationOnScreen());
|
||||
|
||||
@@ -860,12 +860,40 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
};
|
||||
|
||||
if (hasUnsafeBgTasks || option.isToBeShown()) {
|
||||
AtomicBoolean alreadyGone = new AtomicBoolean(false);
|
||||
if (hasUnsafeBgTasks) {
|
||||
Runnable dialogRemover = Messages.createMessageDialogRemover(null);
|
||||
Runnable task = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (alreadyGone.get()) return;
|
||||
if (!ProgressManager.getInstance().hasUnsafeProgressIndicator()) {
|
||||
alreadyGone.set(true);
|
||||
dialogRemover.run();
|
||||
}
|
||||
else {
|
||||
JobScheduler.getScheduler().schedule(this, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
};
|
||||
JobScheduler.getScheduler().schedule(task, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
String name = ApplicationNamesInfo.getInstance().getFullProductName();
|
||||
String message = ApplicationBundle.message(hasUnsafeBgTasks ? "exit.confirm.prompt.tasks" : "exit.confirm.prompt", name);
|
||||
int result = MessageDialogBuilder.yesNo(ApplicationBundle.message("exit.confirm.title"), message)
|
||||
.yesText(ApplicationBundle.message("command.exit"))
|
||||
.noText(CommonBundle.message("button.cancel"))
|
||||
.doNotAsk(option).show();
|
||||
if (alreadyGone.getAndSet(true)) {
|
||||
if (!option.isToBeShown()) {
|
||||
return true;
|
||||
}
|
||||
result = MessageDialogBuilder.yesNo(ApplicationBundle.message("exit.confirm.title"),
|
||||
ApplicationBundle.message("exit.confirm.prompt", name))
|
||||
.yesText(ApplicationBundle.message("command.exit"))
|
||||
.noText(CommonBundle.message("button.cancel"))
|
||||
.doNotAsk(option).show();
|
||||
}
|
||||
if (result != Messages.YES) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+130
-78
@@ -1,8 +1,6 @@
|
||||
package com.intellij.execution.process;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.BufferExposingByteArrayInputStream;
|
||||
import com.intellij.testFramework.PlatformTestCase;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
@@ -10,101 +8,138 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class AnsiEscapeDecoderTest extends PlatformTestCase {
|
||||
|
||||
private static final String STDOUT_KEY = ProcessOutputTypes.STDOUT.toString();
|
||||
private static final String STDERR_KEY = ProcessOutputTypes.STDERR.toString();
|
||||
|
||||
public void testTextWithoutColors() throws Exception {
|
||||
AnsiEscapeDecoder decoder = new AnsiEscapeDecoder();
|
||||
decoder.escapeText("", ProcessOutputTypes.STDOUT, createExpectedAcceptor(
|
||||
Pair.create("", ProcessOutputTypes.STDOUT)
|
||||
));
|
||||
decoder.escapeText("simple text", ProcessOutputTypes.STDOUT, createExpectedAcceptor(
|
||||
Pair.create("simple text", ProcessOutputTypes.STDOUT)
|
||||
));
|
||||
check(new ColoredText(""));
|
||||
check(new ColoredText("simple text").addExpected("simple text", STDOUT_KEY));
|
||||
}
|
||||
|
||||
public void testSingleColoredChunk() throws Exception {
|
||||
AnsiEscapeDecoder decoder = new AnsiEscapeDecoder();
|
||||
decoder.escapeText("Chrome 35.0.1916 (Linux): Executed 0 of 1\u001B[32m SUCCESS\u001B[39m (0 secs / 0 secs)\n", ProcessOutputTypes.STDOUT, createExpectedAcceptor(
|
||||
Pair.create("Chrome 35.0.1916 (Linux): Executed 0 of 1", ProcessOutputTypes.STDOUT),
|
||||
Pair.create(" SUCCESS", ColoredOutputTypeRegistry.getInstance().getOutputKey("\u001B[32m")),
|
||||
Pair.create(" (0 secs / 0 secs)\n", ColoredOutputTypeRegistry.getInstance().getOutputKey("\u001B[39m"))
|
||||
));
|
||||
check(new ColoredText("Chrome 35.0.1916 (Linux): Executed 0 of 1\u001B[32m SUCCESS\u001B[39m (0 secs / 0 secs)\n")
|
||||
.addExpected("Chrome 35.0.1916 (Linux): Executed 0 of 1", STDOUT_KEY)
|
||||
.addExpected(" SUCCESS", "\u001B[32m")
|
||||
.addExpected(" (0 secs / 0 secs)\n", "\u001B[39m"));
|
||||
}
|
||||
|
||||
public void testCompoundEscSeq() throws Exception {
|
||||
AnsiEscapeDecoder decoder = new AnsiEscapeDecoder();
|
||||
decoder.escapeText("E\u001B[41m\u001B[37mE\u001B[0mE", ProcessOutputTypes.STDOUT, createExpectedAcceptor(
|
||||
Pair.create("E", ProcessOutputTypes.STDOUT),
|
||||
Pair.create("E", ColoredOutputTypeRegistry.getInstance().getOutputKey("\u001B[41;37m")),
|
||||
Pair.create("E", ProcessOutputTypes.STDOUT)
|
||||
));
|
||||
check(new ColoredText("E\u001B[41m\u001B[37mE\u001B[0mE")
|
||||
.addExpected("E", STDOUT_KEY)
|
||||
.addExpected("E", "\u001B[41;37m")
|
||||
.addExpected("E", STDOUT_KEY));
|
||||
}
|
||||
|
||||
public void testOtherEscSeq() throws Exception {
|
||||
AnsiEscapeDecoder decoder = new AnsiEscapeDecoder();
|
||||
decoder.escapeText("Plain\u001B[32mGreen\u001B[39mNormal\u001B[1A\u001B[2K\u001B[31mRed\u001B[39m",
|
||||
ProcessOutputTypes.STDOUT,
|
||||
createExpectedAcceptor(
|
||||
Pair.create("Plain", ProcessOutputTypes.STDOUT),
|
||||
Pair.create("Green", ColoredOutputTypeRegistry.getInstance().getOutputKey("\u001B[32m")),
|
||||
Pair.create("Normal", ColoredOutputTypeRegistry.getInstance().getOutputKey("\u001B[39m")),
|
||||
Pair.create("Red", ColoredOutputTypeRegistry.getInstance().getOutputKey("\u001B[31m"))
|
||||
)
|
||||
);
|
||||
check(new ColoredText("Plain\u001B[32mGreen\u001B[39mNormal\u001B[1A\u001B[2K\u001B[31mRed\u001B[39m")
|
||||
.addExpected("Plain", STDOUT_KEY)
|
||||
.addExpected("Green", "\u001B[32m")
|
||||
.addExpected("Normal", "\u001B[39m")
|
||||
.addExpected("Red", "\u001B[31m"));
|
||||
}
|
||||
|
||||
public void testBackspaceControlSequence() throws Exception {
|
||||
check(false, ContainerUtil.newArrayList(
|
||||
new ColoredText(" 10% 0/1 build modules\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b 70% 1/1 build modules")
|
||||
.addExpected(" 70% 1/1 build modules", STDOUT_KEY),
|
||||
new ColoredText(
|
||||
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b 40% 1/2 build modules\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b 30% 1/3 build modules\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b 25% 1/4 build modules")
|
||||
.addExpected("\n 25% 1/4 build modules", STDOUT_KEY)
|
||||
));
|
||||
}
|
||||
|
||||
public void testIncompleteEscapeSequences() throws Exception {
|
||||
check(true, ContainerUtil.newArrayList(
|
||||
new ColoredText("\u001B"),
|
||||
new ColoredText("[33m Hello\u001B[3").addExpected(" Hello", "\u001B[33m"),
|
||||
new ColoredText("4m, Work!").addExpected(", Work!", "\u001B[34m")
|
||||
));
|
||||
|
||||
check(true, ContainerUtil.newArrayList(
|
||||
new ColoredText("\u001B[1;33m<\u001B[34mnamespace\u001B[1")
|
||||
.addExpected("<", "\u001B[1;33m")
|
||||
.addExpected("namespace", "\u001B[34m"),
|
||||
new ColoredText(
|
||||
";33m:abcd\u001B[0m\u001B[1;33m>\u001B[0m0\u001B[1;33m</\u001B[34mnamespace\u001B[1;33m:abcd\u001B[0m\u001B[1;33m>\u001B[0m")
|
||||
.addExpected(":abcd", "\u001B[1;33m")
|
||||
.addExpected(">", "\u001B[0;1;33m")
|
||||
.addExpected("0", "stdout")
|
||||
.addExpected("</", "\u001B[1;33m")
|
||||
.addExpected("namespace", "\u001B[34m")
|
||||
.addExpected(":abcd", "\u001B[1;33m")
|
||||
.addExpected(">", "\u001B[0;1;33m")
|
||||
));
|
||||
}
|
||||
|
||||
private static void check(@NotNull ColoredText text) {
|
||||
check(true, Collections.singletonList(text));
|
||||
}
|
||||
|
||||
private static void check(boolean testCharByCharProcessing, @NotNull List<ColoredText> texts) {
|
||||
AnsiEscapeDecoder decoder = new AnsiEscapeDecoder();
|
||||
decoder.escapeText(" 10% 0/1 build modules\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b 70% 1/1 build modules",
|
||||
ProcessOutputTypes.STDERR,
|
||||
createExpectedAcceptor(
|
||||
Pair.create(" 70% 1/1 build modules", ProcessOutputTypes.STDERR)
|
||||
)
|
||||
);
|
||||
decoder.escapeText("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b 40% 1/2 build modules\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b 30% 1/3 build modules\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b 25% 1/4 build modules",
|
||||
ProcessOutputTypes.STDERR,
|
||||
createExpectedAcceptor(
|
||||
Pair.create("\n 25% 1/4 build modules", ProcessOutputTypes.STDERR)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<Pair<String, String>> toListWithKeyName(@NotNull Collection<Pair<String, Key>> list) {
|
||||
return ContainerUtil.map(list, pair -> Pair.create(pair.first, pair.second.toString()));
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
private static AnsiEscapeDecoder.ColoredChunksAcceptor createExpectedAcceptor(@NotNull final Pair<String, Key>... expected) {
|
||||
return new AnsiEscapeDecoder.ColoredChunksAcceptor() {
|
||||
@Override
|
||||
public void coloredChunksAvailable(@NotNull List<Pair<String, Key>> chunks) {
|
||||
List<Pair<String, String>> expectedWithKeyName = toListWithKeyName(Arrays.asList(expected));
|
||||
List<Pair<String, String>> actualWithKeyName = toListWithKeyName(chunks);
|
||||
Assert.assertEquals(expectedWithKeyName, actualWithKeyName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void coloredTextAvailable(@NotNull String text, @NotNull Key attributes) {
|
||||
throw new RuntimeException(); // shouldn't be called
|
||||
}
|
||||
List<Pair<String, String>> actualColoredChunks = ContainerUtil.newArrayList();
|
||||
//noinspection CodeBlock2Expr
|
||||
AnsiEscapeDecoder.ColoredTextAcceptor acceptor = (text, attributes) -> {
|
||||
actualColoredChunks.add(Pair.create(text, attributes.toString()));
|
||||
};
|
||||
// test stdout
|
||||
for (ColoredText text : texts) {
|
||||
decoder.escapeText(text.myRawText, ProcessOutputTypes.STDOUT, acceptor);
|
||||
}
|
||||
List<Pair<String, String>> expectedColoredChunks = new ArrayList<>();
|
||||
for (ColoredText text : texts) {
|
||||
expectedColoredChunks.addAll(text.myExpectedColoredChunks);
|
||||
}
|
||||
Assert.assertEquals(expectedColoredChunks, actualColoredChunks);
|
||||
|
||||
if (testCharByCharProcessing) {
|
||||
// test stdout char by char
|
||||
actualColoredChunks.clear();
|
||||
decoder = new AnsiEscapeDecoder();
|
||||
for (ColoredText text : texts) {
|
||||
for (int i = 0; i < text.myRawText.length(); i++) {
|
||||
decoder.escapeText(String.valueOf(text.myRawText.charAt(i)), ProcessOutputTypes.STDOUT, acceptor);
|
||||
}
|
||||
}
|
||||
expectedColoredChunks.clear();
|
||||
for (ColoredText text : texts) {
|
||||
for (Pair<String, String> chunk : text.myExpectedColoredChunks) {
|
||||
String chunkText = chunk.first;
|
||||
for (int i = 0; i < chunkText.length(); i++) {
|
||||
expectedColoredChunks.add(Pair.create(String.valueOf(chunkText.charAt(i)), chunk.second));
|
||||
}
|
||||
}
|
||||
}
|
||||
Assert.assertEquals(expectedColoredChunks, actualColoredChunks);
|
||||
}
|
||||
|
||||
// test stderr
|
||||
actualColoredChunks.clear();
|
||||
decoder = new AnsiEscapeDecoder();
|
||||
for (ColoredText text : texts) {
|
||||
decoder.escapeText(text.myRawText, ProcessOutputTypes.STDERR, acceptor);
|
||||
}
|
||||
expectedColoredChunks.clear();
|
||||
for (ColoredText text : texts) {
|
||||
for (Pair<String, String> chunk : text.myExpectedColoredChunks) {
|
||||
expectedColoredChunks.add(Pair.create(chunk.first, STDERR_KEY));
|
||||
}
|
||||
}
|
||||
Assert.assertEquals(expectedColoredChunks, actualColoredChunks);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Process createTestProcess() {
|
||||
// have to be synchronised because used from pooled thread
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(10000);
|
||||
BufferExposingByteArrayInputStream inputStream = new BufferExposingByteArrayInputStream(new byte[0]);
|
||||
AtomicBoolean finished = new AtomicBoolean();
|
||||
return new Process() {
|
||||
@Override
|
||||
@@ -114,17 +149,17 @@ public class AnsiEscapeDecoderTest extends PlatformTestCase {
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
return inputStream;
|
||||
return new ByteArrayInputStream(new byte[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getErrorStream() {
|
||||
return inputStream;
|
||||
return new ByteArrayInputStream(new byte[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int waitFor() {
|
||||
while (!finished.get());
|
||||
while (!finished.get()) {}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -143,11 +178,14 @@ public class AnsiEscapeDecoderTest extends PlatformTestCase {
|
||||
public void testPerformance() throws IOException {
|
||||
Process testProcess = createTestProcess();
|
||||
|
||||
//noinspection CodeBlock2Expr
|
||||
withProcessHandlerFrom(testProcess, handler -> {
|
||||
PlatformTestUtil.startPerformanceTest("ansi color", 15000, ()->{
|
||||
for (int i=0; i<2_000_000;i++) {
|
||||
handler.notifyTextAvailable(i+"Chrome 35.0.1916 (Linux): Executed 0 of 1\u001B[32m SUCCESS\u001B[39m (0 secs / 0 secs)\n", ProcessOutputTypes.STDOUT);
|
||||
handler.notifyTextAvailable(i+"Plain\u001B[32mGreen\u001B[39mNormal\u001B[1A\u001B[2K\u001B[31mRed\u001B[39m\n", ProcessOutputTypes.SYSTEM);
|
||||
PlatformTestUtil.startPerformanceTest("ansi color", 15000, () -> {
|
||||
for (int i = 0; i < 2_000_000; i++) {
|
||||
handler.notifyTextAvailable(i + "Chrome 35.0.1916 (Linux): Executed 0 of 1\u001B[32m SUCCESS\u001B[39m (0 secs / 0 secs)\n",
|
||||
ProcessOutputTypes.STDOUT);
|
||||
handler.notifyTextAvailable(i + "Plain\u001B[32mGreen\u001B[39mNormal\u001B[1A\u001B[2K\u001B[31mRed\u001B[39m\n",
|
||||
ProcessOutputTypes.SYSTEM);
|
||||
}
|
||||
}).cpuBound().assertTiming();
|
||||
});
|
||||
@@ -168,4 +206,18 @@ public class AnsiEscapeDecoderTest extends PlatformTestCase {
|
||||
handler.waitFor();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ColoredText {
|
||||
private final String myRawText;
|
||||
private final List<Pair<String, String>> myExpectedColoredChunks = new ArrayList<>();
|
||||
|
||||
public ColoredText(@NotNull String rawText) {
|
||||
myRawText = rawText;
|
||||
}
|
||||
|
||||
private ColoredText addExpected(@NotNull String text, @NotNull String colorKey) {
|
||||
myExpectedColoredChunks.add(Pair.create(text, colorKey));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,52 +50,53 @@ abstract class RemoteVmConnection : VmConnection<Vm>() {
|
||||
port = address.port
|
||||
setState(ConnectionStatus.WAITING_FOR_CONNECTION, "Connecting to ${address.hostString}:${address.port}")
|
||||
val result = AsyncPromise<Vm>()
|
||||
|
||||
var attemptNumber = 0
|
||||
fun attempt() {
|
||||
connectCancelHandler.set { result.setError("Closed explicitly") }
|
||||
|
||||
val connectionPromise = AsyncPromise<Any?>()
|
||||
connectionPromise.rejected { result.setError(it) }
|
||||
|
||||
result
|
||||
.done {
|
||||
vm = it!!
|
||||
setState(ConnectionStatus.CONNECTED, "Connected to ${connectedAddressToPresentation(address, it)}")
|
||||
startProcessing()
|
||||
}
|
||||
.rejected {
|
||||
if (it !is ConnectException) {
|
||||
LOG.errorIfNotMessage(it)
|
||||
}
|
||||
setState(ConnectionStatus.CONNECTION_FAILED, it.message)
|
||||
}
|
||||
.processed { connectCancelHandler.set(null) }
|
||||
|
||||
createBootstrap(address, result)
|
||||
.connect(address, connectionPromise,
|
||||
maxAttemptCount = if (stopCondition == null) NettyUtil.DEFAULT_CONNECT_ATTEMPT_COUNT else -1,
|
||||
stopCondition = stopCondition)
|
||||
?.closeFuture()?.addListener {
|
||||
if (result.isFulfilled) {
|
||||
close("Process disconnected unexpectedly", ConnectionStatus.DISCONNECTED)
|
||||
}
|
||||
else {
|
||||
if (++attemptNumber > 10 || (stopCondition?.value(null) ?: false)) {
|
||||
result.setError("Cannot establish connection - promptly closed after open")
|
||||
}
|
||||
else {
|
||||
sleep(result, 300)
|
||||
attempt()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val future = ApplicationManager.getApplication().executeOnPooledThread {
|
||||
if (Thread.interrupted()) {
|
||||
return@executeOnPooledThread
|
||||
}
|
||||
|
||||
var attemptNumber = 0
|
||||
fun attempt() {
|
||||
connectCancelHandler.set { result.setError("Closed explicitly") }
|
||||
|
||||
val connectionPromise = AsyncPromise<Any?>()
|
||||
connectionPromise.rejected { result.setError(it) }
|
||||
|
||||
result
|
||||
.done {
|
||||
vm = it!!
|
||||
setState(ConnectionStatus.CONNECTED, "Connected to ${connectedAddressToPresentation(address, it)}")
|
||||
startProcessing()
|
||||
}
|
||||
.rejected {
|
||||
if (it !is ConnectException) {
|
||||
LOG.errorIfNotMessage(it)
|
||||
}
|
||||
setState(ConnectionStatus.CONNECTION_FAILED, it.message)
|
||||
}
|
||||
.processed { connectCancelHandler.set(null) }
|
||||
|
||||
createBootstrap(address, result)
|
||||
.connect(address, connectionPromise,
|
||||
maxAttemptCount = if (stopCondition == null) NettyUtil.DEFAULT_CONNECT_ATTEMPT_COUNT else -1,
|
||||
stopCondition = stopCondition)
|
||||
?.closeFuture()?.addListener {
|
||||
if (result.isFulfilled) {
|
||||
close("Process disconnected unexpectedly", ConnectionStatus.DISCONNECTED)
|
||||
}
|
||||
else {
|
||||
if (++attemptNumber > 10 || (stopCondition?.value(null) ?: false)) {
|
||||
result.setError("Process disconnected unexpectedly")
|
||||
}
|
||||
else {
|
||||
sleep(result, 300)
|
||||
attempt()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
attempt()
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import java.util.stream.LongStream;
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
class CpuTimings {
|
||||
public class CpuTimings {
|
||||
final long[] rawData;
|
||||
long average;
|
||||
private final double myStandardDeviation;
|
||||
@@ -58,7 +58,7 @@ class CpuTimings {
|
||||
@SuppressWarnings("UseOfSystemOutOrSystemErr")
|
||||
static CpuTimings calcStableCpuTiming() {
|
||||
for (int i = 0;; i++) {
|
||||
CpuTimings timings = calcCpuTiming();
|
||||
CpuTimings timings = calcCpuTiming(20, CpuTimings::addBigIntegers);
|
||||
if (timings.myStandardDeviation < 1.8) {
|
||||
return timings;
|
||||
}
|
||||
@@ -73,24 +73,47 @@ class CpuTimings {
|
||||
}
|
||||
}
|
||||
|
||||
private static CpuTimings calcCpuTiming() {
|
||||
int n = 20;
|
||||
long[] elapsed = new long[n];
|
||||
for (int i = 0; i < n; i++) {
|
||||
elapsed[i] = measureCPU();
|
||||
private static CpuTimings calcCpuTiming(int iterationCount, Runnable oneIteration) {
|
||||
long[] elapsed = new long[iterationCount];
|
||||
for (int i = 0; i < iterationCount; i++) {
|
||||
long start = System.currentTimeMillis();
|
||||
oneIteration.run();
|
||||
elapsed[i] = System.currentTimeMillis() - start;
|
||||
}
|
||||
return new CpuTimings(elapsed);
|
||||
}
|
||||
|
||||
private static long measureCPU() {
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
private static void addBigIntegers() {
|
||||
BigInteger k = new BigInteger("1");
|
||||
for (int i = 0; i < 1000000; i++) {
|
||||
k = k.add(new BigInteger("1"));
|
||||
}
|
||||
}
|
||||
|
||||
return System.currentTimeMillis() - start;
|
||||
private static void mulDiv() {
|
||||
long k = 241;
|
||||
for (int i = 0; i < 22_222_222; i++) {
|
||||
k = i % 10 == 3 ? k * 239 : k % 12342;
|
||||
}
|
||||
ensureOdd(k);
|
||||
}
|
||||
|
||||
private static void ensureOdd(long k) {
|
||||
if (k % 2 == 0) {
|
||||
throw new AssertionError("Should be an odd value");
|
||||
}
|
||||
}
|
||||
|
||||
private static void mulDivMemAccess() {
|
||||
int[] array = new int[240_000];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = i * 42 + 1;
|
||||
}
|
||||
int k = 241;
|
||||
for (int i = 0; i < 5_750_000; i++) {
|
||||
k *= array[Math.abs(k) % array.length];
|
||||
}
|
||||
ensureOdd(k);
|
||||
}
|
||||
|
||||
public static double getProcessCpuLoad() {
|
||||
@@ -134,4 +157,14 @@ class CpuTimings {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("UseOfSystemOutOrSystemErr")
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < 20; i++) {
|
||||
// each line can be uncommented alone, to check the results of different benchmarks
|
||||
//System.out.println(calcCpuTiming(20, CpuTimings::addBigIntegers));
|
||||
//System.out.println(calcCpuTiming(20, CpuTimings::mulDivMemAccess));
|
||||
//System.out.println(calcCpuTiming(20, CpuTimings::mulDiv));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -960,10 +960,12 @@ public class ArrayUtil extends ArrayUtilRt {
|
||||
int n = time.length;
|
||||
Arrays.sort(time);
|
||||
long total = 0;
|
||||
for (int i= n /2- n / part /2; i< n /2+ n / part /2; i++) {
|
||||
int start = n / 2 - n / part / 2;
|
||||
int end = n / 2 + n / part / 2;
|
||||
for (int i = start; i < end; i++) {
|
||||
total += time[i];
|
||||
}
|
||||
int middlePartLength = n / part;
|
||||
int middlePartLength = end - start;
|
||||
return middlePartLength == 0 ? 0 : total / middlePartLength;
|
||||
}
|
||||
|
||||
@@ -972,10 +974,12 @@ public class ArrayUtil extends ArrayUtilRt {
|
||||
int n = time.length;
|
||||
Arrays.sort(time);
|
||||
long total = 0;
|
||||
for (int i= n /2- n / part /2; i< n /2+ n / part /2; i++) {
|
||||
int start = n / 2 - n / part / 2;
|
||||
int end = n / 2 + n / part / 2;
|
||||
for (int i = start; i < end; i++) {
|
||||
total += time[i];
|
||||
}
|
||||
int middlePartLength = n / part;
|
||||
int middlePartLength = end - start;
|
||||
return middlePartLength == 0 ? 0 : total / middlePartLength;
|
||||
}
|
||||
|
||||
|
||||
@@ -94,24 +94,26 @@ public class BeanBinding extends NotNullDeserializeBinding {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (filter != null) {
|
||||
if (filter instanceof SkipDefaultsSerializationFilter) {
|
||||
if (((SkipDefaultsSerializationFilter)filter).equal(binding, o)) {
|
||||
Property property = accessor.getAnnotation(Property.class);
|
||||
if (property == null || !property.alwaysWrite()) {
|
||||
if (filter != null) {
|
||||
if (filter instanceof SkipDefaultsSerializationFilter) {
|
||||
if (((SkipDefaultsSerializationFilter)filter).equal(binding, o)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (!filter.accepts(accessor, o)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (!filter.accepts(accessor, o)) {
|
||||
|
||||
//todo: optimize. Cache it.
|
||||
if (property != null && property.filter() != SerializationFilter.class &&
|
||||
!ReflectionUtil.newInstance(property.filter()).accepts(accessor, o)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//todo: optimize. Cache it.
|
||||
Property property = accessor.getAnnotation(Property.class);
|
||||
if (property != null && property.filter() != SerializationFilter.class &&
|
||||
!ReflectionUtil.newInstance(property.filter()).accepts(accessor, o)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element == null) {
|
||||
element = new Element(myTagName);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -31,4 +31,6 @@ public @interface Property {
|
||||
boolean surroundWithTag() default true;
|
||||
|
||||
Class<? extends SerializationFilter> filter() default SerializationFilter.class;
|
||||
|
||||
boolean alwaysWrite() default false;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public class TestLocationDataRule implements GetDataRule {
|
||||
if (fileIndex.isInContent(file) && !fileIndex.isInSource(file) && !fileIndex.isInLibraryClasses(file)) {
|
||||
final VirtualFile parent = file.getParent();
|
||||
final VirtualFile contentRoot = fileIndex.getContentRootForFile(file);
|
||||
if (contentRoot != null) {
|
||||
if (contentRoot != null && parent != null) {
|
||||
final String relativePath = VfsUtilCore.getRelativePath(parent, contentRoot, '/');
|
||||
if (relativePath != null) {
|
||||
final PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(project);
|
||||
|
||||
@@ -136,7 +136,7 @@ public class PsiUtil {
|
||||
return flag;
|
||||
}
|
||||
|
||||
public static boolean isPluginProject(final Project project) {
|
||||
public static boolean isPluginProject(@NotNull final Project project) {
|
||||
return CachedValuesManager.getManager(project).getCachedValue(project, () -> {
|
||||
boolean foundMarkerClass =
|
||||
JavaPsiFacade.getInstance(project).findClass(IDE_PROJECT_MARKER_CLASS,
|
||||
|
||||
+8
-3
@@ -27,6 +27,8 @@ import com.intellij.ide.util.projectWizard.WizardContext;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.externalSystem.importing.ImportSpec;
|
||||
import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder;
|
||||
import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys;
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData;
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectId;
|
||||
@@ -212,9 +214,12 @@ public class GradleModuleBuilder extends AbstractExternalModuleBuilder<GradlePro
|
||||
settings.linkProject(gradleProjectSettings);
|
||||
}
|
||||
|
||||
ExternalSystemUtil.refreshProject(
|
||||
project, GradleConstants.SYSTEM_ID, rootProjectPath, false,
|
||||
ProgressExecutionMode.IN_BACKGROUND_ASYNC);
|
||||
ImportSpec importSpec = new ImportSpecBuilder(project, GradleConstants.SYSTEM_ID)
|
||||
.use(ProgressExecutionMode.IN_BACKGROUND_ASYNC)
|
||||
.createDirectoriesForEmptyContentRoots()
|
||||
.useDefaultCallback()
|
||||
.build();
|
||||
ExternalSystemUtil.refreshProject(rootProjectPath, importSpec);
|
||||
|
||||
final PsiFile psiFile;
|
||||
if (finalBuildScriptFile != null) {
|
||||
|
||||
+15
@@ -47,6 +47,7 @@ import org.jetbrains.plugins.gradle.util.GradleUtil;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
@@ -496,6 +497,20 @@ public class IdeaGradleProjectSettingsControlBuilder implements GradleProjectSet
|
||||
}
|
||||
|
||||
private void resetWrapperControls(String linkedProjectPath, @NotNull GradleProjectSettings settings, boolean isDefaultModuleCreation) {
|
||||
if (isDefaultModuleCreation) {
|
||||
JComponent[] toRemove = new JComponent[]{myUseWrapperWithVerificationButton, myUseWrapperVerificationLabel};
|
||||
for (JComponent component : toRemove) {
|
||||
if (component != null) {
|
||||
Container parent = component.getParent();
|
||||
if (parent != null) {
|
||||
parent.remove(component);
|
||||
}
|
||||
}
|
||||
}
|
||||
myUseWrapperWithVerificationButton = null;
|
||||
myUseWrapperVerificationLabel = null;
|
||||
}
|
||||
|
||||
if (StringUtil.isEmpty(linkedProjectPath) && !isDefaultModuleCreation) {
|
||||
if (myUseLocalDistributionButton != null) {
|
||||
myUseLocalDistributionButton.setSelected(true);
|
||||
|
||||
@@ -466,6 +466,7 @@ def console_exec(thread_id, frame_id, expression, dbg):
|
||||
"""
|
||||
frame = pydevd_vars.find_frame(thread_id, frame_id)
|
||||
|
||||
is_multiline = expression.count('@LINE@') > 1
|
||||
expression = str(expression.replace('@LINE@', '\n'))
|
||||
|
||||
#Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329
|
||||
@@ -484,16 +485,18 @@ def console_exec(thread_id, frame_id, expression, dbg):
|
||||
|
||||
interpreter = ConsoleWriter()
|
||||
|
||||
try:
|
||||
code = compile_command(expression)
|
||||
except (OverflowError, SyntaxError, ValueError):
|
||||
# Case 1
|
||||
interpreter.showsyntaxerror()
|
||||
return False
|
||||
|
||||
if code is None:
|
||||
# Case 2
|
||||
return True
|
||||
if not is_multiline:
|
||||
try:
|
||||
code = compile_command(expression)
|
||||
except (OverflowError, SyntaxError, ValueError):
|
||||
# Case 1
|
||||
interpreter.showsyntaxerror()
|
||||
return False
|
||||
if code is None:
|
||||
# Case 2
|
||||
return True
|
||||
else:
|
||||
code = expression
|
||||
|
||||
#Case 3
|
||||
|
||||
|
||||
@@ -17,9 +17,12 @@ package com.jetbrains.python.actions;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.execution.ExecutionHelper;
|
||||
import com.intellij.execution.ExecutionManager;
|
||||
import com.intellij.execution.console.LanguageConsoleView;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.ui.ExecutionConsole;
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.execution.ui.RunContentManager;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil;
|
||||
@@ -27,15 +30,13 @@ import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.content.ContentManager;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.jetbrains.python.console.PyCodeExecutor;
|
||||
import com.jetbrains.python.console.PydevConsoleRunner;
|
||||
import com.jetbrains.python.console.PythonConsoleRunnerFactory;
|
||||
import com.jetbrains.python.console.PythonConsoleToolWindow;
|
||||
import com.jetbrains.python.console.*;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -176,11 +177,20 @@ public class PyExecuteSelectionAction extends AnAction {
|
||||
ExecutionHelper
|
||||
.selectContentDescriptor(dataContext, project, consoles, "Select console to execute in", descriptor -> {
|
||||
if (descriptor != null && descriptor.getExecutionConsole() instanceof PyCodeExecutor) {
|
||||
consumer.consume((PyCodeExecutor)descriptor.getExecutionConsole());
|
||||
final PythonConsoleToolWindow toolWindow = PythonConsoleToolWindow.getInstance(project);
|
||||
if (toolWindow != null && !toolWindow.getToolWindow().isVisible()) {
|
||||
toolWindow.getToolWindow().show(null);
|
||||
ContentManager contentManager = toolWindow.getToolWindow().getContentManager();
|
||||
ExecutionConsole console = descriptor.getExecutionConsole();
|
||||
consumer.consume((PyCodeExecutor)console);
|
||||
ToolWindow toolWindow;
|
||||
if (console instanceof PythonDebugLanguageConsoleView) {
|
||||
RunContentManager runContentManager = ExecutionManager.getInstance(project).getContentManager();
|
||||
toolWindow = runContentManager.getToolWindowByDescriptor(descriptor);
|
||||
}
|
||||
else {
|
||||
PythonConsoleToolWindow consoleToolWindow = PythonConsoleToolWindow.getInstance(project);
|
||||
toolWindow = consoleToolWindow != null ? consoleToolWindow.getToolWindow() : null;
|
||||
}
|
||||
if (toolWindow != null && !toolWindow.isVisible()) {
|
||||
toolWindow.show(null);
|
||||
ContentManager contentManager = toolWindow.getContentManager();
|
||||
Content content = contentManager.findContent(descriptor.getDisplayName());
|
||||
if (content != null) {
|
||||
contentManager.setSelectedContent(content);
|
||||
|
||||
@@ -61,7 +61,7 @@ public class PythonDebugLanguageConsoleView extends DuplexConsoleView<ConsoleVie
|
||||
@Override
|
||||
public void executeCode(@NotNull String code, @Nullable Editor e) {
|
||||
enableConsole(false);
|
||||
getPydevConsoleView().executeCode(code, e);
|
||||
getPydevConsoleView().executeInConsole(code);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -312,6 +312,7 @@ public class WebBrowserManager extends SimpleModificationTracker implements Pers
|
||||
public void setBrowserPath(@NotNull WebBrowser browser, @Nullable String path, boolean isActive) {
|
||||
((ConfigurableWebBrowser)browser).setPath(path);
|
||||
((ConfigurableWebBrowser)browser).setActive(isActive);
|
||||
incModificationCount();
|
||||
}
|
||||
|
||||
public WebBrowser addBrowser(final @NotNull UUID id,
|
||||
|
||||
Reference in New Issue
Block a user