From e22d64aab9ada5aca18241d5b3c7243a4bdd3040 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 5 Oct 2017 15:23:35 +0200 Subject: [PATCH 01/28] DocumentCommitThread: fix names (IDEA-CR-24858) --- .../src/com/intellij/psi/impl/DocumentCommitThread.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java b/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java index f78a4e0c3d7e..4db82d47b3bc 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java +++ b/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java @@ -848,9 +848,9 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi oldDocumentText.charAt(prefix) == newDocumentText.charAt(prefix)) { prefix++; } while (suffix < shortestLength - prefix && oldDocumentText.charAt(psiLength - suffix - 1) == newDocumentText.charAt(newDocumentText.length() - suffix - 1)) { suffix++; } - int length = Math.max(prefix, psiLength - suffix); - if (length == 0 && newDocumentText.length() == oldDocumentText.length()) return null; - return TextRange.create(prefix, length); + int end = Math.max(prefix, psiLength - suffix); + if (end == prefix && newDocumentText.length() == oldDocumentText.length()) return null; + return TextRange.create(prefix, end); } public static void doActualPsiChange(@NotNull final PsiFile file, @NotNull final DiffLog diffLog) { From 1966c3fd378280de9e2cac290ae6bdcd6e267df0 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Thu, 5 Oct 2017 16:34:28 +0300 Subject: [PATCH 02/28] debugger agent: support static insert methods --- .../src/com/intellij/rt/debugger/agent/CaptureAgent.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/java/debugger/debugger-agent/src/com/intellij/rt/debugger/agent/CaptureAgent.java b/java/debugger/debugger-agent/src/com/intellij/rt/debugger/agent/CaptureAgent.java index 6a5252d0facf..cf1e3b1c2c28 100644 --- a/java/debugger/debugger-agent/src/com/intellij/rt/debugger/agent/CaptureAgent.java +++ b/java/debugger/debugger-agent/src/com/intellij/rt/debugger/agent/CaptureAgent.java @@ -226,13 +226,15 @@ public class CaptureAgent { // this mv.visitVarInsn(Opcodes.ALOAD, 0); // params - int index = (access & Opcodes.ACC_STATIC) == 0 ? 1 : 0; + boolean isStatic = (access & Opcodes.ACC_STATIC) != 0; + int index = isStatic ? 0 : 1; for (Type t : Type.getMethodType(desc).getArgumentTypes()) { mv.visitVarInsn(t.getOpcode(Opcodes.ILOAD), index); index += t.getSize(); } // original call - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, insertPoint.myClassName, getNewName(insertPoint.myMethodName), desc, false); + mv.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : Opcodes.INVOKESPECIAL, + insertPoint.myClassName, getNewName(insertPoint.myMethodName), desc, false); Label end = new Label(); mv.visitLabel(end); From 90919988f40825b74d0e68b1dc57d039092a9c05 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Thu, 5 Oct 2017 16:34:55 +0300 Subject: [PATCH 03/28] cleanup --- .../settings/CaptureSettingsProvider.java | 101 +++++++++--------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/CaptureSettingsProvider.java b/java/debugger/impl/src/com/intellij/debugger/settings/CaptureSettingsProvider.java index 15fa786e3fa3..2b4a9ef79095 100644 --- a/java/debugger/impl/src/com/intellij/debugger/settings/CaptureSettingsProvider.java +++ b/java/debugger/impl/src/com/intellij/debugger/settings/CaptureSettingsProvider.java @@ -19,57 +19,57 @@ public class CaptureSettingsProvider { private static final KeyProvider THIS_KEY = new StringKeyProvider("this"); static { - CAPTURE_POINTS.add(new AgentCapturePoint("javax/swing/SwingUtilities", "invokeLater", new StringKeyProvider("0"))); - INSERT_POINTS.add(new AgentInsertPoint("java/awt/event/InvocationEvent", "dispatch", - new FieldKeyProvider("java/awt/event/InvocationEvent", "runnable", "Ljava/lang/Runnable;"))); + addCapture("javax/swing/SwingUtilities", "invokeLater", new StringKeyProvider("0")); + addInsert("java/awt/event/InvocationEvent", + "dispatch", + new FieldKeyProvider("java/awt/event/InvocationEvent", "runnable", "Ljava/lang/Runnable;")); - CAPTURE_POINTS.add(new AgentCapturePoint("java/lang/Thread", "start", THIS_KEY)); - INSERT_POINTS.add(new AgentInsertPoint("java/lang/Thread", "run", THIS_KEY)); + addCapture("java/lang/Thread", "start", THIS_KEY); + addInsert("java/lang/Thread", "run", THIS_KEY); - CAPTURE_POINTS.add(new AgentCapturePoint("java/util/concurrent/ExecutorService", "submit", new StringKeyProvider("1"))); - INSERT_POINTS.add(new AgentInsertPoint("java/util/concurrent/Executors$RunnableAdapter", "call", - new FieldKeyProvider("java/util/concurrent/Executors$RunnableAdapter", - "task", - "Ljava/lang/Runnable;"))); + addCapture("java/util/concurrent/ExecutorService", "submit", new StringKeyProvider("1")); + addInsert("java/util/concurrent/Executors$RunnableAdapter", + "call", + new FieldKeyProvider("java/util/concurrent/Executors$RunnableAdapter", + "task", + "Ljava/lang/Runnable;")); - CAPTURE_POINTS.add(new AgentCapturePoint("java/util/concurrent/ThreadPoolExecutor", "execute", new StringKeyProvider("1"))); - INSERT_POINTS.add(new AgentInsertPoint("java/util/concurrent/FutureTask", "run", THIS_KEY)); + addCapture("java/util/concurrent/ThreadPoolExecutor", "execute", new StringKeyProvider("1")); + addInsert("java/util/concurrent/FutureTask", "run", THIS_KEY); - CAPTURE_POINTS.add(new AgentCapturePoint("java/util/concurrent/CompletableFuture", "supplyAsync", new StringKeyProvider("0"))); + addCapture("java/util/concurrent/CompletableFuture", "supplyAsync", new StringKeyProvider("0")); + AgentInsertPoint point = new AgentInsertPoint("java/util/concurrent/CompletableFuture$AsyncSupply", + "run", + new FieldKeyProvider("java/util/concurrent/CompletableFuture$AsyncSupply", + "fn", + "Ljava/util/function/Supplier;")); + point.myInsertPoint.myInsertMethodName = "run$$$capture"; + point.myInsertPoint.myInsertKeyExpression = "f"; + INSERT_POINTS.add(point); - CapturePoint ideInsertPoint = new CapturePoint(); - ideInsertPoint.myInsertClassName = "java.util.concurrent.CompletableFuture$AsyncSupply"; - ideInsertPoint.myInsertMethodName = "run$$$capture"; - ideInsertPoint.myInsertKeyExpression = "f"; - INSERT_POINTS.add(new AgentInsertPoint("java/util/concurrent/CompletableFuture$AsyncSupply", "run", - new FieldKeyProvider("java/util/concurrent/CompletableFuture$AsyncSupply", - "fn", - "Ljava/util/function/Supplier;"), - ideInsertPoint)); + addCapture("java/util/concurrent/CompletableFuture", "runAsync", new StringKeyProvider("0")); + point = new AgentInsertPoint("java/util/concurrent/CompletableFuture$AsyncRun", + "run", + new FieldKeyProvider("java/util/concurrent/CompletableFuture$AsyncRun", + "fn", + "Ljava/lang/Runnable;")); + point.myInsertPoint.myInsertMethodName = "run$$$capture"; + point.myInsertPoint.myInsertKeyExpression = "f"; + INSERT_POINTS.add(point); - CAPTURE_POINTS.add(new AgentCapturePoint("java/util/concurrent/CompletableFuture", "runAsync", new StringKeyProvider("0"))); - ideInsertPoint = new CapturePoint(); - ideInsertPoint.myInsertClassName = "java.util.concurrent.CompletableFuture$AsyncRun"; - ideInsertPoint.myInsertMethodName = "run$$$capture"; - ideInsertPoint.myInsertKeyExpression = "f"; - INSERT_POINTS.add(new AgentInsertPoint("java/util/concurrent/CompletableFuture$AsyncRun", - "run", - new FieldKeyProvider("java/util/concurrent/CompletableFuture$AsyncRun", - "fn", - "Ljava/lang/Runnable;"), - ideInsertPoint)); + addCapture("java/util/concurrent/CompletableFuture", "thenAcceptAsync", new StringKeyProvider("1")); + addInsert("java/util/concurrent/CompletableFuture$UniAccept", + "tryFire", + new FieldKeyProvider("java/util/concurrent/CompletableFuture$UniAccept", + "fn", + "Ljava/util/function/Consumer;")); - CAPTURE_POINTS.add(new AgentCapturePoint("java/util/concurrent/CompletableFuture", "thenAcceptAsync", new StringKeyProvider("1"))); - INSERT_POINTS.add(new AgentInsertPoint("java/util/concurrent/CompletableFuture$UniAccept", "tryFire", - new FieldKeyProvider("java/util/concurrent/CompletableFuture$UniAccept", - "fn", - "Ljava/util/function/Consumer;"))); - - CAPTURE_POINTS.add(new AgentCapturePoint("java/util/concurrent/CompletableFuture", "thenRunAsync", new StringKeyProvider("1"))); - INSERT_POINTS.add(new AgentInsertPoint("java/util/concurrent/CompletableFuture$UniRun", "tryFire", - new FieldKeyProvider("java/util/concurrent/CompletableFuture$UniRun", - "fn", - "Ljava/lang/Runnable;"))); + addCapture("java/util/concurrent/CompletableFuture", "thenRunAsync", new StringKeyProvider("1")); + addInsert("java/util/concurrent/CompletableFuture$UniRun", + "tryFire", + new FieldKeyProvider("java/util/concurrent/CompletableFuture$UniRun", + "fn", + "Ljava/lang/Runnable;")); IDE_INSERT_POINTS = StreamEx.of(INSERT_POINTS).map(p -> p.myInsertPoint).nonNull().toList(); } @@ -127,11 +127,6 @@ public class CaptureSettingsProvider { } } } - - public AgentInsertPoint(String className, String methodName, KeyProvider key, CapturePoint point) { - super(className, methodName, key); - this.myInsertPoint = point; - } } public interface KeyProvider { @@ -167,4 +162,12 @@ public class CaptureSettingsProvider { return myClassName + AgentPoint.SEPARATOR + myFieldName + AgentPoint.SEPARATOR + myFieldDesc; } } + + private static void addCapture(String className, String methodName, KeyProvider key) { + CAPTURE_POINTS.add(new AgentCapturePoint(className, methodName, key)); + } + + private static void addInsert(String className, String methodName, KeyProvider key) { + INSERT_POINTS.add(new AgentInsertPoint(className, methodName, key)); + } } From 1f2abf3afd89e21d194af2c566c728dee660dd93 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Thu, 5 Oct 2017 16:35:13 +0300 Subject: [PATCH 04/28] debugger agent: added netty --- .../intellij/debugger/settings/CaptureSettingsProvider.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/CaptureSettingsProvider.java b/java/debugger/impl/src/com/intellij/debugger/settings/CaptureSettingsProvider.java index 2b4a9ef79095..ab45a95281a1 100644 --- a/java/debugger/impl/src/com/intellij/debugger/settings/CaptureSettingsProvider.java +++ b/java/debugger/impl/src/com/intellij/debugger/settings/CaptureSettingsProvider.java @@ -71,6 +71,10 @@ public class CaptureSettingsProvider { "fn", "Ljava/lang/Runnable;")); + // netty + addCapture("io/netty/util/concurrent/SingleThreadEventExecutor", "addTask", new StringKeyProvider("1")); + addInsert("io/netty/util/concurrent/AbstractEventExecutor", "safeExecute", new StringKeyProvider("0")); + IDE_INSERT_POINTS = StreamEx.of(INSERT_POINTS).map(p -> p.myInsertPoint).nonNull().toList(); } From 2f4dd5c73d88746ee4f514c8262fb9e2fb9dd736 Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Thu, 5 Oct 2017 14:42:21 +0300 Subject: [PATCH 05/28] Support gitlab archives PY-26364 fixed. --- .../python/packaging/PyRequirement.java | 43 +++++++++++-------- .../python/packaging/PyRequirementTest.java | 21 +++------ 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/python/openapi/src/com/jetbrains/python/packaging/PyRequirement.java b/python/openapi/src/com/jetbrains/python/packaging/PyRequirement.java index 203a68cbc36f..142fdc5cb04a 100644 --- a/python/openapi/src/com/jetbrains/python/packaging/PyRequirement.java +++ b/python/openapi/src/com/jetbrains/python/packaging/PyRequirement.java @@ -1,18 +1,16 @@ -/* - * 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. - * 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. - */ +// 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. +// 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.jetbrains.python.packaging; import com.intellij.openapi.editor.Document; @@ -61,6 +59,10 @@ public class PyRequirement { private static final Pattern GITHUB_ARCHIVE_URL = Pattern.compile("https?://github\\.com/[^/\\s]+/(?<" + NAME_GROUP + ">[^/\\s]+)/archive/\\S+" + COMMENT_REGEXP); + @NotNull + private static final Pattern GITLAB_ARCHIVE_URL = + Pattern.compile("https?://gitlab\\.com/[^/\\s]+/(?<" + NAME_GROUP + ">[^/\\s]+)/repository/\\S+" + COMMENT_REGEXP); + @NotNull private static final Pattern ARCHIVE_URL = Pattern.compile("https?://\\S+/" + @@ -309,11 +311,16 @@ public class PyRequirement { @Nullable public static PyRequirement fromLine(@NotNull String line) { - final PyRequirement githubArchiveUrl = parseGithubArchiveUrl(line); + final PyRequirement githubArchiveUrl = parseGitArchiveUrl(GITHUB_ARCHIVE_URL, line); if (githubArchiveUrl != null) { return githubArchiveUrl; } + final PyRequirement gitlabArchiveUrl = parseGitArchiveUrl(GITLAB_ARCHIVE_URL, line); + if (gitlabArchiveUrl != null) { + return gitlabArchiveUrl; + } + final PyRequirement archiveUrl = parseArchiveUrl(line); if (archiveUrl != null) { return archiveUrl; @@ -349,8 +356,8 @@ public class PyRequirement { } @Nullable - private static PyRequirement parseGithubArchiveUrl(@NotNull String line) { - final Matcher matcher = GITHUB_ARCHIVE_URL.matcher(line); + private static PyRequirement parseGitArchiveUrl(@NotNull Pattern pattern, @NotNull String line) { + final Matcher matcher = pattern.matcher(line); if (matcher.matches()) { return new PyRequirement(matcher.group(NAME_GROUP), Collections.emptyList(), Collections.singletonList(dropComments(line, matcher))); diff --git a/python/testSrc/com/jetbrains/python/packaging/PyRequirementTest.java b/python/testSrc/com/jetbrains/python/packaging/PyRequirementTest.java index f2935af155ec..b2cd8af80e79 100644 --- a/python/testSrc/com/jetbrains/python/packaging/PyRequirementTest.java +++ b/python/testSrc/com/jetbrains/python/packaging/PyRequirementTest.java @@ -1,18 +1,4 @@ -/* - * 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. - * 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.jetbrains.python.packaging; import com.intellij.openapi.util.Pair; @@ -80,6 +66,11 @@ public class PyRequirementTest extends PyTestCase { doTest("https://github.com/divio/MyProject1/archive/master.zip?1450634746.0107164"); } + // PY-26364 + public void testGitlabArchiveUrl() { + doTest("https://gitlab.com/mrh1997/MyProject1/repository/master/archive.zip"); + } + // VCS // PY-6328 public void testGit() { From d370ef8c36ceda6a0d85637516ebe4bc01b4a033 Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Thu, 5 Oct 2017 17:00:55 +0300 Subject: [PATCH 06/28] Add `ldap module` -> `pyldap package` mapping PY-26050 fixed. --- python/helpers/tools/packages | 3 ++- .../requirements.txt | 3 ++- .../test1.py | 5 +++-- .../PyPackageRequirementsInspectionTest.java | 17 ++--------------- 4 files changed, 9 insertions(+), 19 deletions(-) diff --git a/python/helpers/tools/packages b/python/helpers/tools/packages index d42369f77337..cc7e96e7f78e 100644 --- a/python/helpers/tools/packages +++ b/python/helpers/tools/packages @@ -4758,4 +4758,5 @@ jenkins python-jenkins pipeline django-pipeline PIL Pillow robot robotframework -cv2 opencv-python \ No newline at end of file +cv2 opencv-python +ldap pyldap \ No newline at end of file diff --git a/python/testData/inspections/PyPackageRequirementsInspection/MismatchBetweenPackageAndRequirement/requirements.txt b/python/testData/inspections/PyPackageRequirementsInspection/MismatchBetweenPackageAndRequirement/requirements.txt index 2ebbfdce0f72..f6d3d9040501 100644 --- a/python/testData/inspections/PyPackageRequirementsInspection/MismatchBetweenPackageAndRequirement/requirements.txt +++ b/python/testData/inspections/PyPackageRequirementsInspection/MismatchBetweenPackageAndRequirement/requirements.txt @@ -13,4 +13,5 @@ django-simple-captcha Pillow pyzmq robotframework -opencv-python \ No newline at end of file +opencv-python +pyldap \ No newline at end of file diff --git a/python/testData/inspections/PyPackageRequirementsInspection/MismatchBetweenPackageAndRequirement/test1.py b/python/testData/inspections/PyPackageRequirementsInspection/MismatchBetweenPackageAndRequirement/test1.py index df580872b8b4..c917427cabb9 100644 --- a/python/testData/inspections/PyPackageRequirementsInspection/MismatchBetweenPackageAndRequirement/test1.py +++ b/python/testData/inspections/PyPackageRequirementsInspection/MismatchBetweenPackageAndRequirement/test1.py @@ -1,4 +1,4 @@ -import factory +import factory import magic import attr import jenkins @@ -13,4 +13,5 @@ import captcha import PIL import zmq import robot -import cv2 \ No newline at end of file +import cv2 +import ldap \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/inspections/PyPackageRequirementsInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyPackageRequirementsInspectionTest.java index 401b6b30cc64..c2427d7dfc9e 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyPackageRequirementsInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyPackageRequirementsInspectionTest.java @@ -1,18 +1,4 @@ -/* - * 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. - * 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.jetbrains.python.inspections; import com.intellij.openapi.projectRoots.Sdk; @@ -71,6 +57,7 @@ public class PyPackageRequirementsInspectionTest extends PyInspectionTestCase { } // PY-11963 + // PY-26050 public void testMismatchBetweenPackageAndRequirement() { doMultiFileTest("test1.py"); } From 9e248d8502461b779d4ebd7948c859b70bca38ad Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Thu, 5 Oct 2017 17:07:43 +0300 Subject: [PATCH 07/28] debugger agent: fixed param idx --- .../rt/debugger/agent/CaptureAgent.java | 51 +++++++++++-------- .../settings/CaptureSettingsProvider.java | 23 +++++---- 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/java/debugger/debugger-agent/src/com/intellij/rt/debugger/agent/CaptureAgent.java b/java/debugger/debugger-agent/src/com/intellij/rt/debugger/agent/CaptureAgent.java index cf1e3b1c2c28..9e64241e6809 100644 --- a/java/debugger/debugger-agent/src/com/intellij/rt/debugger/agent/CaptureAgent.java +++ b/java/debugger/debugger-agent/src/com/intellij/rt/debugger/agent/CaptureAgent.java @@ -22,8 +22,6 @@ public class CaptureAgent { private static Instrumentation ourInstrumentation; private static boolean DEBUG = false; - static final KeyProvider THIS_KEY_PROVIDER = new ParamKeyProvider(0); - private static Map> myCapturePoints = new HashMap>(); private static Map> myInsertPoints = new HashMap>(); @@ -177,7 +175,7 @@ public class CaptureAgent { } @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + public MethodVisitor visitMethod(final int access, String name, final String desc, String signature, String[] exceptions) { if ((access & Opcodes.ACC_BRIDGE) == 0) { for (final CapturePoint capturePoint : myCapturePoints) { if (capturePoint.myMethodName.equals(name)) { @@ -188,7 +186,7 @@ public class CaptureAgent { return new MethodVisitor(api, super.visitMethod(access, name, desc, signature, exceptions)) { @Override public void visitCode() { - capturePoint.myKeyProvider.loadKey(mv); + capturePoint.myKeyProvider.loadKey(mv, (access & Opcodes.ACC_STATIC) != 0, Type.getMethodType(desc).getArgumentTypes()); visitMethodInsn(Opcodes.INVOKESTATIC, CaptureStorage.class.getName().replaceAll("\\.", "/"), "capture", "(Ljava/lang/Object;)V", false); super.visitCode(); } @@ -221,14 +219,16 @@ public class CaptureAgent { Label start = new Label(); mv.visitLabel(start); - insertEnter(mv, insertPoint); + boolean isStatic = (access & Opcodes.ACC_STATIC) != 0; + Type[] argumentTypes = Type.getMethodType(desc).getArgumentTypes(); + + insertEnter(mv, insertPoint, isStatic, argumentTypes); // this mv.visitVarInsn(Opcodes.ALOAD, 0); // params - boolean isStatic = (access & Opcodes.ACC_STATIC) != 0; int index = isStatic ? 0 : 1; - for (Type t : Type.getMethodType(desc).getArgumentTypes()) { + for (Type t : argumentTypes) { mv.visitVarInsn(t.getOpcode(Opcodes.ILOAD), index); index += t.getSize(); } @@ -240,7 +240,7 @@ public class CaptureAgent { mv.visitLabel(end); // regular exit - insertExit(mv, insertPoint); + insertExit(mv, insertPoint, isStatic, argumentTypes); mv.visitInsn(Type.getReturnType(desc).getOpcode(Opcodes.IRETURN)); Label catchLabel = new Label(); @@ -248,21 +248,21 @@ public class CaptureAgent { mv.visitTryCatchBlock(start, end, catchLabel, null); // exception exit - insertExit(mv, insertPoint); + insertExit(mv, insertPoint, isStatic, argumentTypes); mv.visitInsn(Opcodes.ATHROW); mv.visitMaxs(0, 0); mv.visitEnd(); } - private static void insertEnter(MethodVisitor mv, InsertPoint insertPoint) { - insertPoint.myKeyProvider.loadKey(mv); + private static void insertEnter(MethodVisitor mv, InsertPoint insertPoint, boolean isStatic, Type[] argumentTypes) { + insertPoint.myKeyProvider.loadKey(mv, isStatic, argumentTypes); mv.visitMethodInsn(Opcodes.INVOKESTATIC, CaptureStorage.class.getName().replaceAll("\\.", "/"), "insertEnter", "(Ljava/lang/Object;)V", false); } - private static void insertExit(MethodVisitor mv, InsertPoint insertPoint) { - insertPoint.myKeyProvider.loadKey(mv); + private static void insertExit(MethodVisitor mv, InsertPoint insertPoint, boolean isStatic, Type[] argumentTypes) { + insertPoint.myKeyProvider.loadKey(mv, isStatic, argumentTypes); mv.visitMethodInsn(Opcodes.INVOKESTATIC, CaptureStorage.class.getName().replaceAll("\\.", "/"), "insertExit", "(Ljava/lang/Object;)V", false); } @@ -352,6 +352,13 @@ public class CaptureAgent { points.add(new InsertPoint(className, methodName, keyProvider)); } + static final KeyProvider THIS_KEY_PROVIDER = new KeyProvider() { + @Override + public void loadKey(MethodVisitor mv, boolean isStatic, Type[] argumentTypes) { + mv.visitVarInsn(Opcodes.ALOAD, 0); + } + }; + private static KeyProvider createKeyProvider(String[] line) { if ("this".equals(line[0])) { return THIS_KEY_PROVIDER; @@ -365,7 +372,7 @@ public class CaptureAgent { } private interface KeyProvider { - void loadKey(MethodVisitor mv); + void loadKey(MethodVisitor mv, boolean isStatic, Type[] argumentTypes); } private static class FieldKeyProvider implements KeyProvider { @@ -380,22 +387,26 @@ public class CaptureAgent { } @Override - public void loadKey(MethodVisitor mv) { + public void loadKey(MethodVisitor mv, boolean isStatic, Type[] argumentTypes) { mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitFieldInsn(Opcodes.GETFIELD, myClassName, myFieldName, myFieldDesc); } } private static class ParamKeyProvider implements KeyProvider { - int mySlot; + int myIdx; - public ParamKeyProvider(int slot) { - mySlot = slot; + public ParamKeyProvider(int idx) { + myIdx = idx; } @Override - public void loadKey(MethodVisitor mv) { - mv.visitVarInsn(Opcodes.ALOAD, mySlot); + public void loadKey(MethodVisitor mv, boolean isStatic, Type[] argumentTypes) { + int index = isStatic ? 0 : 1; + for (int i = 0; i < myIdx; i++) { + index += argumentTypes[i].getSize(); + } + mv.visitVarInsn(Opcodes.ALOAD, index); } } } diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/CaptureSettingsProvider.java b/java/debugger/impl/src/com/intellij/debugger/settings/CaptureSettingsProvider.java index ab45a95281a1..35d1143b2889 100644 --- a/java/debugger/impl/src/com/intellij/debugger/settings/CaptureSettingsProvider.java +++ b/java/debugger/impl/src/com/intellij/debugger/settings/CaptureSettingsProvider.java @@ -17,9 +17,10 @@ public class CaptureSettingsProvider { private static final List IDE_INSERT_POINTS; private static final KeyProvider THIS_KEY = new StringKeyProvider("this"); + private static final KeyProvider FIRST_PARAM = param(0); static { - addCapture("javax/swing/SwingUtilities", "invokeLater", new StringKeyProvider("0")); + addCapture("javax/swing/SwingUtilities", "invokeLater", FIRST_PARAM); addInsert("java/awt/event/InvocationEvent", "dispatch", new FieldKeyProvider("java/awt/event/InvocationEvent", "runnable", "Ljava/lang/Runnable;")); @@ -27,17 +28,17 @@ public class CaptureSettingsProvider { addCapture("java/lang/Thread", "start", THIS_KEY); addInsert("java/lang/Thread", "run", THIS_KEY); - addCapture("java/util/concurrent/ExecutorService", "submit", new StringKeyProvider("1")); + addCapture("java/util/concurrent/ExecutorService", "submit", FIRST_PARAM); addInsert("java/util/concurrent/Executors$RunnableAdapter", "call", new FieldKeyProvider("java/util/concurrent/Executors$RunnableAdapter", "task", "Ljava/lang/Runnable;")); - addCapture("java/util/concurrent/ThreadPoolExecutor", "execute", new StringKeyProvider("1")); + addCapture("java/util/concurrent/ThreadPoolExecutor", "execute", FIRST_PARAM); addInsert("java/util/concurrent/FutureTask", "run", THIS_KEY); - addCapture("java/util/concurrent/CompletableFuture", "supplyAsync", new StringKeyProvider("0")); + addCapture("java/util/concurrent/CompletableFuture", "supplyAsync", FIRST_PARAM); AgentInsertPoint point = new AgentInsertPoint("java/util/concurrent/CompletableFuture$AsyncSupply", "run", new FieldKeyProvider("java/util/concurrent/CompletableFuture$AsyncSupply", @@ -47,7 +48,7 @@ public class CaptureSettingsProvider { point.myInsertPoint.myInsertKeyExpression = "f"; INSERT_POINTS.add(point); - addCapture("java/util/concurrent/CompletableFuture", "runAsync", new StringKeyProvider("0")); + addCapture("java/util/concurrent/CompletableFuture", "runAsync", FIRST_PARAM); point = new AgentInsertPoint("java/util/concurrent/CompletableFuture$AsyncRun", "run", new FieldKeyProvider("java/util/concurrent/CompletableFuture$AsyncRun", @@ -57,14 +58,14 @@ public class CaptureSettingsProvider { point.myInsertPoint.myInsertKeyExpression = "f"; INSERT_POINTS.add(point); - addCapture("java/util/concurrent/CompletableFuture", "thenAcceptAsync", new StringKeyProvider("1")); + addCapture("java/util/concurrent/CompletableFuture", "thenAcceptAsync", FIRST_PARAM); addInsert("java/util/concurrent/CompletableFuture$UniAccept", "tryFire", new FieldKeyProvider("java/util/concurrent/CompletableFuture$UniAccept", "fn", "Ljava/util/function/Consumer;")); - addCapture("java/util/concurrent/CompletableFuture", "thenRunAsync", new StringKeyProvider("1")); + addCapture("java/util/concurrent/CompletableFuture", "thenRunAsync", FIRST_PARAM); addInsert("java/util/concurrent/CompletableFuture$UniRun", "tryFire", new FieldKeyProvider("java/util/concurrent/CompletableFuture$UniRun", @@ -72,8 +73,8 @@ public class CaptureSettingsProvider { "Ljava/lang/Runnable;")); // netty - addCapture("io/netty/util/concurrent/SingleThreadEventExecutor", "addTask", new StringKeyProvider("1")); - addInsert("io/netty/util/concurrent/AbstractEventExecutor", "safeExecute", new StringKeyProvider("0")); + addCapture("io/netty/util/concurrent/SingleThreadEventExecutor", "addTask", FIRST_PARAM); + addInsert("io/netty/util/concurrent/AbstractEventExecutor", "safeExecute", FIRST_PARAM); IDE_INSERT_POINTS = StreamEx.of(INSERT_POINTS).map(p -> p.myInsertPoint).nonNull().toList(); } @@ -136,6 +137,10 @@ public class CaptureSettingsProvider { public interface KeyProvider { String asString(); } + + private static KeyProvider param(int idx) { + return new StringKeyProvider(Integer.toString(idx)); + } private static class StringKeyProvider implements KeyProvider { private final String myValue; From 1bba81ceb152240907f92713bae8a1d0be1a3053 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Thu, 5 Oct 2017 17:09:17 +0300 Subject: [PATCH 08/28] IDEA-179953 Broken hebrew characters in replace preview --- .../src/com/intellij/ide/ui/laf/IdeaLaf.java | 21 ++----------- .../intellij/ide/ui/laf/LafManagerImpl.java | 18 ++--------- .../util/src/com/intellij/util/ui/UIUtil.java | 30 +++++++++---------- 3 files changed, 19 insertions(+), 50 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/IdeaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/IdeaLaf.java index 4fe90deaca4f..67f224d1e465 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/IdeaLaf.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/IdeaLaf.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2014 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ide.ui.laf; import com.intellij.icons.AllIcons; @@ -26,7 +12,6 @@ import com.sun.java.swing.plaf.windows.WindowsTreeUI; import javax.swing.*; import javax.swing.border.Border; import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.FontUIResource; import javax.swing.plaf.metal.MetalLookAndFeel; import java.awt.*; @@ -44,10 +29,10 @@ public final class IdeaLaf extends MetalLookAndFeel { Pair systemFont = UIUtil.getSystemFontData(); if (systemFont != null) { - LafManagerImpl.initFontDefaults(defaults, new FontUIResource(systemFont.first, Font.PLAIN, systemFont.second)); + LafManagerImpl.initFontDefaults(defaults, UIUtil.getFontWithFallback(systemFont.first, Font.PLAIN, systemFont.second)); } else { - LafManagerImpl.initFontDefaults(defaults, new FontUIResource("Tahoma", Font.PLAIN, 11)); + LafManagerImpl.initFontDefaults(defaults, UIUtil.getFontWithFallback("Tahoma", Font.PLAIN, 11)); } } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java index 5822a244e46b..0c8c2d085e6d 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java @@ -1,18 +1,4 @@ -/* - * 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. - * 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ide.ui.laf; import com.intellij.CommonBundle; @@ -675,7 +661,7 @@ public final class LafManagerImpl extends LafManager implements PersistentStateC UISettings uiSettings = UISettings.getInstance(); if (uiSettings.getOverrideLafFonts()) { storeOriginalFontDefaults(uiDefaults); - initFontDefaults(uiDefaults, new FontUIResource(uiSettings.getFontFace(), Font.PLAIN, uiSettings.getFontSize())); + initFontDefaults(uiDefaults, UIUtil.getFontWithFallback(uiSettings.getFontFace(), Font.PLAIN, uiSettings.getFontSize())); JBUI.setUserScaleFactor(JBUI.getFontScale(uiSettings.getFontSize())); } else { diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 67757481f2e9..a61d5a9a3207 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -1,18 +1,16 @@ -/* - * 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. - * 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. - */ +// 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. +// 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.util.ui; import com.intellij.BundleBase; @@ -2657,7 +2655,7 @@ public class UIUtil { return getFontWithFallback(font.getFamily(), font.getStyle(), font.getSize()); } - public static FontUIResource getFontWithFallback(@NotNull String familyName, @JdkConstants.FontStyle int style, int size) { + public static FontUIResource getFontWithFallback(@Nullable String familyName, @JdkConstants.FontStyle int style, int size) { Font fontWithFallback = new StyleContext().getFont(familyName, style, size); return fontWithFallback instanceof FontUIResource ? (FontUIResource)fontWithFallback : new FontUIResource(fontWithFallback); } From c4e7e59689c04b2b60b798b3f8a3f6a8b3bfda39 Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 5 Oct 2017 17:15:39 +0300 Subject: [PATCH 09/28] platform: fixed loading non-bundled plugins when running from sources --- .../src/com/intellij/ide/plugins/PluginManagerCore.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java index b0bdf73196e5..5848250491fa 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java +++ b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java @@ -462,7 +462,7 @@ public class PluginManagerCore { PluginId pluginId = pluginDescriptor.getPluginId(); File pluginRoot = pluginDescriptor.getPath(); - if (isRunningFromSources()) return null; + if (isUnitTestMode() && isRunningFromSources()) return null; try { final List urls = new ArrayList<>(classPath.length); @@ -520,7 +520,7 @@ public class PluginManagerCore { @NotNull private static ClassLoader[] getParentLoaders(@NotNull Map idToDescriptorMap, @NotNull PluginId[] pluginIds) { - if (isRunningFromSources()) return new ClassLoader[0]; + if (isUnitTestMode() && isRunningFromSources()) return new ClassLoader[0]; LinkedHashSet loaders = new LinkedHashSet<>(pluginIds.length); for (final PluginId id : pluginIds) { From 9c51b9e41007ecb0357eb6adec0d248920017cd7 Mon Sep 17 00:00:00 2001 From: Kirill Kirichenko Date: Thu, 5 Oct 2017 16:53:57 +0300 Subject: [PATCH 10/28] Modifies warning colors for TextField, ComboBoxe and Spinner borders --- .../src/com/intellij/openapi/ui/DialogWrapper.java | 8 ++++---- .../intellij/ide/ui/laf/darcula/DarculaUIUtil.java | 13 ++++++++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java index 975e6d440e33..4761abd3ad2a 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -202,8 +202,8 @@ public abstract class DialogWrapper { private final Alarm myErrorTextAlarm = new Alarm(); - private static final Color BALLOON_BORDER = new JBColor(new Color(0xe0a8a9), new Color(0x73454b)); - private static final Color BALLOON_BACKGROUND = new JBColor(new Color(0xf5e6e7), new Color(0x593d41)); + private static final Color BALLOON_ERROR_BORDER = new JBColor(new Color(0xe0a8a9), new Color(0x73454b)); + private static final Color BALLOON_ERROR_BACKGROUND = new JBColor(new Color(0xf5e6e7), new Color(0x593d41)); /** * Creates modal {@code DialogWrapper}. The currently active window will be the dialog's parent. @@ -2002,8 +2002,8 @@ public abstract class DialogWrapper { .setHideOnKeyOutside(false) .setHideOnClickOutside(false) .setHideOnAction(false) - .setBorderColor(BALLOON_BORDER) - .setFillColor(BALLOON_BACKGROUND) + .setBorderColor(BALLOON_ERROR_BORDER) + .setFillColor(BALLOON_ERROR_BACKGROUND) .setHideOnFrameResize(false) .setRequestFocus(false) .setAnimationCycle(100) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaUIUtil.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaUIUtil.java index 3f8301644c88..73841db1fa6e 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaUIUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaUIUtil.java @@ -64,7 +64,15 @@ public class DarculaUIUtil { public static final Color INACTIVE_ERROR_COLOR = new JBColor(() -> UIUtil.isUnderDefaultMacTheme() ? MAC_INACTIVE_ERROR_COLOR : DEFAULT_INACTIVE_ERROR_COLOR); @SuppressWarnings("UseJBColor") - public static final Color WARNING_COLOR = new Color(0xf6ebbc, true); + private static final Color MAC_ACTIVE_WARNING_COLOR = new Color(0x80e9ad43, true); + private static final Color DEFAULT_ACTIVE_WARNING_COLOR = new JBColor(0xe2a53a, 0xac7920); + + @SuppressWarnings("UseJBColor") + private static final Color MAC_INACTIVE_WARNING_COLOR = new Color(0x80ffda99, true); + private static final Color DEFAULT_INACTIVE_WARNING_COLOR = new JBColor(0xffd385, 0x6e5324); + + public static final Color ACTIVE_WARNING_COLOR = new JBColor(() -> UIUtil.isUnderDefaultMacTheme() ? MAC_ACTIVE_WARNING_COLOR : DEFAULT_ACTIVE_WARNING_COLOR); + public static final Color INACTIVE_WARNING_COLOR = new JBColor(() -> UIUtil.isUnderDefaultMacTheme() ? MAC_INACTIVE_WARNING_COLOR : DEFAULT_INACTIVE_WARNING_COLOR); @SuppressWarnings("UseJBColor") private static final Color MAC_REGULAR_COLOR = new Color(0x80479cfc, true); @@ -81,8 +89,7 @@ public class DarculaUIUtil { warning { public void setGraphicsColor(Graphics2D g, boolean focused) { - g.setColor(WARNING_COLOR); - g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, focused ? 1f : 0.5f)); + g.setColor(focused ? ACTIVE_WARNING_COLOR: INACTIVE_WARNING_COLOR); } }; From 6cf10f607ad82162b965ed32e7c3c98114714fd8 Mon Sep 17 00:00:00 2001 From: Kirill Kirichenko Date: Thu, 5 Oct 2017 17:20:06 +0300 Subject: [PATCH 11/28] Fix CCE in AbstractPopup --- .../src/com/intellij/ui/popup/AbstractPopup.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index dd5ea04fc69b..5f8f4aea2f3c 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -467,8 +467,9 @@ public class AbstractPopup implements JBPopup { @Override public void show(@NotNull RelativePoint aPoint) { - if (Registry.is("ide.helptooltip.enabled")) { - HelpTooltip.onShowMasterPopup((JComponent)aPoint.getOriginalComponent(), this); + Component c = aPoint.getOriginalComponent(); + if (Registry.is("ide.helptooltip.enabled") && c instanceof JComponent) { + HelpTooltip.onShowMasterPopup((JComponent)c, this); } Point screenPoint = aPoint.getScreenPoint(); From 66dc780346e07043f0187372ca6a058e12973939 Mon Sep 17 00:00:00 2001 From: Kirill Kirichenko Date: Thu, 5 Oct 2017 17:20:52 +0300 Subject: [PATCH 12/28] Win10: Fix Spinner editor bounds --- .../intellij/ide/ui/laf/intellij/WinIntelliJSpinnerUI.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJSpinnerUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJSpinnerUI.java index ba9985596cc7..ae144b283343 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJSpinnerUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJSpinnerUI.java @@ -23,7 +23,6 @@ import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import javax.swing.border.EmptyBorder; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicArrowButton; import java.awt.*; @@ -206,10 +205,10 @@ public class WinIntelliJSpinnerUI extends DarculaSpinnerUI { button.setOpaque(false); if (direction == SwingConstants.NORTH) { installNextButtonListeners(button); - button.setBorder(new EmptyBorder(2, 1, 1, 2)); + button.setBorder(JBUI.Borders.empty(2, 1, 1, 2)); } else { installPreviousButtonListeners(button); - button.setBorder(new EmptyBorder(1, 1, 2, 2)); + button.setBorder(JBUI.Borders.empty(1, 1, 2, 2)); } return button; } @@ -278,7 +277,7 @@ public class WinIntelliJSpinnerUI extends DarculaSpinnerUI { Rectangle bounds = editor.getBounds(); Insets i = spinner.getInsets(); - int offset = JBUI.scale(EDITOR_OFFSET - i.left); + int offset = JBUI.scale(EDITOR_OFFSET) - i.left; editor.setBounds(bounds.x + offset, bounds.y, bounds.width - offset, From 64a81ec0f94692df5f7fedc6dc06cd5545a47a82 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Thu, 5 Oct 2017 16:36:35 +0200 Subject: [PATCH 13/28] =?UTF-8?q?New=20project=20creation=20=E2=80=94=20VF?= =?UTF-8?q?S=20must=20be=20used=20to=20write=20workspace.xml=20and=20misc.?= =?UTF-8?q?xml=20to=20ensure=20that=20project=20files=20will=20be=20not=20?= =?UTF-8?q?reloaded=20on=20external=20file=20change=20event?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/FileBasedStorage.kt | 2 +- .../src/ProjectStoreImpl.kt | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/platform/configuration-store-impl/src/FileBasedStorage.kt b/platform/configuration-store-impl/src/FileBasedStorage.kt index e3f406d13484..ffbee63d9d2e 100644 --- a/platform/configuration-store-impl/src/FileBasedStorage.kt +++ b/platform/configuration-store-impl/src/FileBasedStorage.kt @@ -181,7 +181,7 @@ open class FileBasedStorage(file: Path, override fun toString() = file.systemIndependentPath } -fun writeFile(file: Path?, requestor: Any, virtualFile: VirtualFile?, element: Element, lineSeparator: LineSeparator, prependXmlProlog: Boolean): VirtualFile { +internal fun writeFile(file: Path?, requestor: Any, virtualFile: VirtualFile?, element: Element, lineSeparator: LineSeparator, prependXmlProlog: Boolean): VirtualFile { val result = if (file != null && (virtualFile == null || !virtualFile.isValid)) { getOrCreateVirtualFile(requestor, file) } diff --git a/platform/configuration-store-impl/src/ProjectStoreImpl.kt b/platform/configuration-store-impl/src/ProjectStoreImpl.kt index eeb0827d81bd..7bf063ba89a6 100644 --- a/platform/configuration-store-impl/src/ProjectStoreImpl.kt +++ b/platform/configuration-store-impl/src/ProjectStoreImpl.kt @@ -58,6 +58,7 @@ import gnu.trove.THashSet import org.jdom.Element import java.io.File import java.io.IOException +import java.nio.file.FileSystems import java.nio.file.Path import java.nio.file.Paths @@ -490,10 +491,19 @@ private fun writeConfigFile(elements: List, file: Path) { } elements.forEach { wrapper.addContent(it) } // .idea component configuration files uses XML prolog due to historical reasons - file.outputStream().use { - it.write(XML_PROLOG) - it.write(LineSeparator.LF.separatorBytes) - wrapper.write(it) + if (file.fileSystem == FileSystems.getDefault()) { + // VFS must be used to write workspace.xml and misc.xml to ensure that project files will be not reloaded on external file change event + writeFile(file, object : StateStorage.SaveSession { + override fun save() { + } + }, null, wrapper, LineSeparator.LF, true) + } + else { + file.outputStream().use { + it.write(XML_PROLOG) + it.write(LineSeparator.LF.separatorBytes) + wrapper.write(it) + } } } From 925c1ca1f54425bf8bb5eb703e60960e52888575 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Thu, 5 Oct 2017 16:46:09 +0300 Subject: [PATCH 14/28] [groovy] convert ClassNameDiffersFromFileNamePredicate - add file name consumer; - don't run consumer if predicate failed; - disallow rename class/file intentions on inner classes. --- ...ClassNameDiffersFromFileNamePredicate.java | 64 ------------------- .../ClassNameDiffersFromFileNamePredicate.kt | 41 ++++++++++++ .../MoveClassToNewFileIntention.java | 18 +----- 3 files changed, 43 insertions(+), 80 deletions(-) delete mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ClassNameDiffersFromFileNamePredicate.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ClassNameDiffersFromFileNamePredicate.kt diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ClassNameDiffersFromFileNamePredicate.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ClassNameDiffersFromFileNamePredicate.java deleted file mode 100644 index 7cc72e860534..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ClassNameDiffersFromFileNamePredicate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.plugins.groovy.intentions.conversions; - -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.util.Consumer; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate; -import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; - -/** -* @author Maxim.Medvedev -*/ -class ClassNameDiffersFromFileNamePredicate implements PsiElementPredicate { - private final Consumer myClassConsumer; - private final boolean mySearchForClassInMultiClassFile; - - ClassNameDiffersFromFileNamePredicate(@Nullable Consumer classConsumer, boolean searchForClassInMultiClassFile) { - myClassConsumer = classConsumer; - mySearchForClassInMultiClassFile = searchForClassInMultiClassFile; - } - - ClassNameDiffersFromFileNamePredicate(@Nullable Consumer classConsumer) { - this(classConsumer, false); - } - - @Override - public boolean satisfiedBy(@NotNull PsiElement element) { - final PsiElement parent = element.getParent(); - if (!(parent instanceof GrTypeDefinition)) return false; - if (((GrTypeDefinition)parent).getNameIdentifierGroovy() != element) return false; - - final String name = ((GrTypeDefinition)parent).getName(); - if (name == null || name.isEmpty()) return false; - if (myClassConsumer != null) myClassConsumer.consume(((GrTypeDefinition)parent)); - final PsiFile file = element.getContainingFile(); - if (!(file instanceof GroovyFile)) return false; - if (!file.isPhysical()) return false; - if (name.equals(FileUtil.getNameWithoutExtension(file.getName()))) return false; - if (mySearchForClassInMultiClassFile) { - return ((GroovyFile)file).getClasses().length > 1; - } - else { - return !((GroovyFile)file).isScript(); - } - } -} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ClassNameDiffersFromFileNamePredicate.kt b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ClassNameDiffersFromFileNamePredicate.kt new file mode 100644 index 000000000000..759a268bf939 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ClassNameDiffersFromFileNamePredicate.kt @@ -0,0 +1,41 @@ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.groovy.intentions.conversions + +import com.intellij.openapi.util.io.FileUtil.getNameWithoutExtension +import com.intellij.psi.PsiElement +import com.intellij.util.Consumer +import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate +import org.jetbrains.plugins.groovy.lang.psi.GroovyFile +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition + +internal class ClassNameDiffersFromFileNamePredicate @JvmOverloads constructor( + private val searchForClassInMultiClassFile: Boolean = false, + private val classConsumer: Consumer? = null, + private val fileNameConsumer: Consumer? = null +) : PsiElementPredicate { + + internal constructor(consumer: Consumer?) : this(classConsumer = consumer) + + override fun satisfiedBy(element: PsiElement): Boolean { + val clazz = element.parent as? GrTypeDefinition ?: return false + if (clazz.nameIdentifierGroovy !== element) return false + + val className = clazz.name ?: return false + if (className.isEmpty()) return false + + val file = clazz.parent as? GroovyFile ?: return false + if (!file.isPhysical) return false + + val fileName = getNameWithoutExtension(file.name) + if (fileName.isEmpty()) return false + + if (className == fileName) return false + + val result = if (searchForClassInMultiClassFile) file.classes.size > 1 else !file.isScript + if (!result) return false + + classConsumer?.consume(clazz) + fileNameConsumer?.consume(fileName) + return true + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/MoveClassToNewFileIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/MoveClassToNewFileIntention.java index 0d4accacd725..79b59f3cbefd 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/MoveClassToNewFileIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/MoveClassToNewFileIntention.java @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.intentions.conversions; import com.intellij.openapi.application.ApplicationManager; @@ -100,6 +86,6 @@ public class MoveClassToNewFileIntention extends Intention { @NotNull @Override protected PsiElementPredicate getElementPredicate() { - return new ClassNameDiffersFromFileNamePredicate(null, true); + return new ClassNameDiffersFromFileNamePredicate(true); } } From 58a51d234638109104481ecc3eeacc70bcc44e3e Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Thu, 5 Oct 2017 17:27:24 +0300 Subject: [PATCH 15/28] [groovy] add 'Rename Class to File Name' intention (IDEA-175950) --- .../after.groovy.template | 4 ++ .../before.groovy.template | 4 ++ .../description.html | 5 +++ .../GroovyIntentionsBundle.properties | 3 ++ plugins/groovy/src/META-INF/plugin.xml | 5 +++ .../RenameClassToFileNameIntention.kt | 40 +++++++++++++++++++ 6 files changed, 61 insertions(+) create mode 100644 plugins/groovy/groovy-psi/resources/intentionDescriptions/RenameClassToFileNameIntention/after.groovy.template create mode 100644 plugins/groovy/groovy-psi/resources/intentionDescriptions/RenameClassToFileNameIntention/before.groovy.template create mode 100644 plugins/groovy/groovy-psi/resources/intentionDescriptions/RenameClassToFileNameIntention/description.html create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/RenameClassToFileNameIntention.kt diff --git a/plugins/groovy/groovy-psi/resources/intentionDescriptions/RenameClassToFileNameIntention/after.groovy.template b/plugins/groovy/groovy-psi/resources/intentionDescriptions/RenameClassToFileNameIntention/after.groovy.template new file mode 100644 index 000000000000..71bb66000088 --- /dev/null +++ b/plugins/groovy/groovy-psi/resources/intentionDescriptions/RenameClassToFileNameIntention/after.groovy.template @@ -0,0 +1,4 @@ +File name: Foo.groovy + +class Foo { +} \ No newline at end of file diff --git a/plugins/groovy/groovy-psi/resources/intentionDescriptions/RenameClassToFileNameIntention/before.groovy.template b/plugins/groovy/groovy-psi/resources/intentionDescriptions/RenameClassToFileNameIntention/before.groovy.template new file mode 100644 index 000000000000..e54aa7c3f913 --- /dev/null +++ b/plugins/groovy/groovy-psi/resources/intentionDescriptions/RenameClassToFileNameIntention/before.groovy.template @@ -0,0 +1,4 @@ +File name: Foo.groovy + +class Bar { +} \ No newline at end of file diff --git a/plugins/groovy/groovy-psi/resources/intentionDescriptions/RenameClassToFileNameIntention/description.html b/plugins/groovy/groovy-psi/resources/intentionDescriptions/RenameClassToFileNameIntention/description.html new file mode 100644 index 000000000000..3474932ce833 --- /dev/null +++ b/plugins/groovy/groovy-psi/resources/intentionDescriptions/RenameClassToFileNameIntention/description.html @@ -0,0 +1,5 @@ + + +Changes class name to corresponding containing file name + + \ No newline at end of file diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties index d01283d1737e..75e45940ec04 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties @@ -128,6 +128,9 @@ do.you.want.to.change.type.of.parameter.in.method=Do you want to change type of rename.file.with.class.intention.name=Rename file to class name rename.file.with.class.intention.family.name=Rename file to corresponding class name +rename.class.to.file.name.intention.family.name=Rename class to corresponding file name +rename.class.to.0=Rename class to ''{0}'' + move.class.to.new.file.intention.name=Move to separate file move.class.to.new.file.intention.family.name=Move class to separate file diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 0eeaf65bb600..6a834b7b7961 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -1457,6 +1457,11 @@ intention.category.conversions org.jetbrains.plugins.groovy.intentions.conversions.RenameFileWithClassIntention + + org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle + intention.category.conversions + org.jetbrains.plugins.groovy.intentions.conversions.RenameClassToFileNameIntention + org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle intention.category.conversions diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/RenameClassToFileNameIntention.kt b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/RenameClassToFileNameIntention.kt new file mode 100644 index 000000000000..d8d9551cbb38 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/RenameClassToFileNameIntention.kt @@ -0,0 +1,40 @@ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.groovy.intentions.conversions + +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement +import com.intellij.psi.SmartPsiElementPointer +import com.intellij.psi.util.createSmartPointer +import com.intellij.refactoring.RefactoringFactory +import com.intellij.util.Consumer +import org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle.message +import org.jetbrains.plugins.groovy.intentions.base.Intention +import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition + +class RenameClassToFileNameIntention : Intention() { + + private lateinit var myClassPointer: SmartPsiElementPointer + private lateinit var myFileName: String + + override fun getElementPredicate(): PsiElementPredicate = ClassNameDiffersFromFileNamePredicate( + classConsumer = Consumer { + myClassPointer = it.createSmartPointer() + }, + fileNameConsumer = Consumer { fileName -> + myFileName = fileName + } + ) + + override fun isStopElement(element: PsiElement?): Boolean = true + + override fun getText(): String = message("rename.class.to.0", myFileName) + + override fun startInWriteAction(): Boolean = false + + override fun processIntention(element: PsiElement, project: Project, editor: Editor?) { + val clazz = myClassPointer.element ?: return + RefactoringFactory.getInstance(project).createRename(clazz, myFileName).run() + } +} From a392f16adb0f3d99c90ad20d54ff21f7a7164b4b Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 5 Oct 2017 17:55:12 +0300 Subject: [PATCH 16/28] project view: hide unnecessary module grouping nodes (IDEA-180081) It makes no sense to show module grouping nodes for single-module projects; also if there is a common prefix for all module grouping nodes it makes sense to merge all its parent grouping nodes into a single one. --- ...ureTest.kt => ModulesInProjectViewTest.kt} | 73 ++++++++++++++++--- .../impl/nodes/AbstractProjectNode.java | 35 +++++++-- .../impl/nodes/ModuleGroupNode.java | 23 +++++- 3 files changed, 112 insertions(+), 19 deletions(-) rename java/java-tests/testSrc/com/intellij/projectView/{ProjectViewStructureTest.kt => ModulesInProjectViewTest.kt} (60%) diff --git a/java/java-tests/testSrc/com/intellij/projectView/ProjectViewStructureTest.kt b/java/java-tests/testSrc/com/intellij/projectView/ModulesInProjectViewTest.kt similarity index 60% rename from java/java-tests/testSrc/com/intellij/projectView/ProjectViewStructureTest.kt rename to java/java-tests/testSrc/com/intellij/projectView/ModulesInProjectViewTest.kt index ed0e26873af8..21e5edb58147 100644 --- a/java/java-tests/testSrc/com/intellij/projectView/ProjectViewStructureTest.kt +++ b/java/java-tests/testSrc/com/intellij/projectView/ModulesInProjectViewTest.kt @@ -10,11 +10,16 @@ import com.intellij.util.io.generateInVirtualTempDir /** * @author nik */ -class ProjectViewStructureTest : BaseProjectViewTestCase() { +class ModulesInProjectViewTest : BaseProjectViewTestCase() { init { myPrintInfo = Queryable.PrintInfo() } - + + override fun setUp() { + super.setUp() + myStructure.isShowLibraryContents = false + } + fun `test unloaded modules`() { val root = directoryContent { dir("loaded") { @@ -34,7 +39,6 @@ class ProjectViewStructureTest : BaseProjectViewTestCase() { PsiTestUtil.addContentRoot(createModule("unloaded-inner"), root.findFileByRelativePath("loaded/unloaded-inner")) PsiTestUtil.addContentRoot(createModule("unloaded"), root.findChild("unloaded")) PsiTestUtil.addContentRoot(createModule("loaded-inner"), root.findFileByRelativePath("unloaded/loaded-inner")) - myStructure.isShowLibraryContents = false val expected = """ |Project | loaded @@ -61,22 +65,27 @@ class ProjectViewStructureTest : BaseProjectViewTestCase() { fun `test unloaded module with qualified name`() { val root = directoryContent { dir("unloaded") { - dir("subdir") { } + dir("subdir") {} file("y.txt") } + dir("unloaded2") { + dir("subdir") {} + } }.generateInVirtualTempDir() PsiTestUtil.addContentRoot(createModule("foo.bar.unloaded"), root.findChild("unloaded")) + PsiTestUtil.addContentRoot(createModule("unloaded2"), root.findChild("unloaded2")) - myStructure.isShowLibraryContents = false val expected = """ |Project - | Group: foo - | Group: bar - | unloaded - | subdir - | y.txt + | Group: foo.bar + | unloaded + | subdir + | y.txt | foo.bar.unloaded.iml | test unloaded module with qualified name.iml + | unloaded2 + | subdir + | unloaded2.iml | """.trimMargin() assertStructureEqual(expected) @@ -85,5 +94,49 @@ class ProjectViewStructureTest : BaseProjectViewTestCase() { assertStructureEqual(expected) } + fun `test do not show parent groups for single module`() { + val root = directoryContent { + dir("module") { + dir("subdir") {} + } + }.generateInVirtualTempDir() + PsiTestUtil.addContentRoot(createModule("foo.bar.module"), root.findChild("module")) + assertStructureEqual(""" + |Project + | foo.bar.module.iml + | module + | subdir + | test do not show parent groups for single module.iml + | + """.trimMargin()) + } + + fun `test modules with common parent group`() { + val root = directoryContent { + dir("module1") { + dir("subdir") {} + } + dir("module2") { + dir("subdir") {} + } + }.generateInVirtualTempDir() + PsiTestUtil.addContentRoot(createModule("foo.bar.module1"), root.findChild("module1")) + PsiTestUtil.addContentRoot(createModule("foo.baz.module2"), root.findChild("module2")) + assertStructureEqual(""" + |Project + | Group: foo + | Group: bar + | module1 + | subdir + | Group: baz + | module2 + | subdir + | foo.bar.module1.iml + | foo.baz.module2.iml + | test modules with common parent group.iml + | + """.trimMargin()) + } + override fun getTestPath() = null } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/AbstractProjectNode.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/AbstractProjectNode.java index 942e32bec57c..9e85dfbe6b88 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/AbstractProjectNode.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/AbstractProjectNode.java @@ -31,6 +31,7 @@ import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.PlatformIcons; import com.intellij.util.containers.ContainerUtil; +import one.util.streamex.StreamEx; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -43,23 +44,45 @@ public abstract class AbstractProjectNode extends ProjectViewNode { } protected Collection modulesAndGroups(Collection modules) { - Set groups = new LinkedHashSet<>(); + Set topLevelGroups = new LinkedHashSet<>(); Set nonGroupedModules = new LinkedHashSet<>(modules); + List commonGroupsPath = null; for (final ModuleDescription moduleDescription : modules) { final List path = ModuleGrouper.instanceFor(myProject).getGroupPath(moduleDescription); if (!path.isEmpty()) { final String topLevelGroupName = path.get(0); - groups.add(topLevelGroupName); + topLevelGroups.add(topLevelGroupName); nonGroupedModules.remove(moduleDescription); + if (commonGroupsPath == null) { + commonGroupsPath = path; + } + else { + int commonPartLen = Math.min(commonGroupsPath.size(), path.size()); + OptionalLong firstDifference = StreamEx.zip(commonGroupsPath.subList(0, commonPartLen), path.subList(0, commonPartLen), String::equals).indexOf(false); + if (firstDifference.isPresent()) { + commonGroupsPath = commonGroupsPath.subList(0, (int)firstDifference.getAsLong()); + } + } } } + List result = new ArrayList<>(); try { - for (String groupPath : groups) { - result.add(createModuleGroupNode(new ModuleGroup(Collections.singletonList(groupPath)))); + if (modules.size() > 1) { + if (commonGroupsPath != null && !commonGroupsPath.isEmpty()) { + result.add(createModuleGroupNode(new ModuleGroup(commonGroupsPath))); + } + else { + for (String groupPath : topLevelGroups) { + result.add(createModuleGroupNode(new ModuleGroup(Collections.singletonList(groupPath)))); + } + } + for (ModuleDescription moduleDescription : nonGroupedModules) { + ContainerUtil.addIfNotNull(result, createModuleNode(moduleDescription)); + } } - for (ModuleDescription moduleDescription : nonGroupedModules) { - ContainerUtil.addIfNotNull(result, createModuleNode(moduleDescription)); + else { + ContainerUtil.addIfNotNull(result, createModuleNode(ContainerUtil.getFirstItem(modules))); } } catch (ProcessCanceledException e) { diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ModuleGroupNode.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ModuleGroupNode.java index 9d17c3ebf978..d0bcdae7c1f6 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ModuleGroupNode.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ModuleGroupNode.java @@ -28,6 +28,7 @@ import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleGrouper; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFileSystemItem; import com.intellij.util.PlatformIcons; @@ -110,14 +111,30 @@ public abstract class ModuleGroupNode extends ProjectViewNode imple @Override public void update(PresentationData presentation) { - final String[] groupPath = getValue().getGroupPath(); - presentation.setPresentableText(groupPath[groupPath.length-1]); + presentation.setPresentableText(getPresentableName()); presentation.setIcon(PlatformIcons.CLOSED_MODULE_GROUP_ICON); } + @NotNull + private String getPresentableName() { + return StringUtil.join(getRelativeGroupPath(), "."); + } + + private List getRelativeGroupPath() { + AbstractTreeNode parent = getParent(); + List thisPath = getValue().getGroupPathList(); + if (parent instanceof ModuleGroupNode) { + List parentPath = ((ModuleGroupNode)parent).getValue().getGroupPathList(); + if (ContainerUtil.startsWith(thisPath, parentPath)) { + return thisPath.subList(parentPath.size(), thisPath.size()); + } + } + return thisPath; + } + @Override public String getTestPresentation() { - return "Group: " + getValue(); + return "Group: " + getPresentableName(); } @Override From 8e5907723a31f7737eb5977422c0f8588647e884 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Thu, 5 Oct 2017 07:20:43 +0300 Subject: [PATCH 17/28] employ JBTreeTraverser.from()/of() --- .../intellij/codeInsight/CodeInsightUtil.java | 2 +- .../jsonSchema/impl/MatchResult.java | 38 +++++++++---------- .../StructureViewComponent.java | 2 +- .../BlockViewerPsiBasedTree.java | 3 +- .../com/intellij/util/ui/tree/TreeUtil.java | 2 +- .../intellij/openapi/util/io/FileUtil.java | 6 +-- .../src/com/intellij/util/ReflectionUtil.java | 6 +-- .../util/src/com/intellij/util/ui/UIUtil.java | 6 +-- 8 files changed, 32 insertions(+), 33 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java b/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java index 15525bd3e14c..e05809f8274f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java @@ -304,7 +304,7 @@ public class CodeInsightUtil { if (baseClass.hasModifierProperty(PsiModifier.FINAL)) return; if (matcher.getPrefix().length() > 2) { - JBTreeTraverser traverser = new JBTreeTraverser<>(c -> Arrays.asList(c.getInnerClasses())); + JBTreeTraverser traverser = JBTreeTraverser.of(PsiClass::getInnerClasses); AllClassesGetter.processJavaClasses(matcher, context.getProject(), scope, psiClass -> { Iterable inheritors = traverser.withRoot(psiClass).filter(c -> c.isInheritor(baseClass, true)); return ContainerUtil.process(inheritors, inheritorsProcessor); diff --git a/json/src/com/jetbrains/jsonSchema/impl/MatchResult.java b/json/src/com/jetbrains/jsonSchema/impl/MatchResult.java index 10b770a6dfc1..d4aef818aa33 100644 --- a/json/src/com/jetbrains/jsonSchema/impl/MatchResult.java +++ b/json/src/com/jetbrains/jsonSchema/impl/MatchResult.java @@ -15,7 +15,6 @@ */ package com.jetbrains.jsonSchema.impl; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.JBTreeTraverser; import org.jetbrains.annotations.NotNull; @@ -34,24 +33,25 @@ public class MatchResult { } public static MatchResult create(@NotNull JsonSchemaTreeNode root) { - final List schemas = new ArrayList<>(); - final Map> oneOfGroups = new HashMap<>(); - ContainerUtil.process(new JBTreeTraverser(node -> node.getChildren()).withRoot(root).preOrderDfsTraversal(), - node -> { - if (node.getChildren().isEmpty() && !node.isAny() && !node.isNothing() && - SchemaResolveState.normal.equals(node.getResolveState())) { - final int groupNumber = node.getExcludingGroupNumber(); - if (groupNumber < 0) { - schemas.add(node.getSchema()); - } - else { - Set set = oneOfGroups.get(groupNumber); - if (set == null) oneOfGroups.put(groupNumber, (set = new HashSet<>())); - set.add(node.getSchema()); - } - } - return true; - }); + List schemas = new ArrayList<>(); + Map> oneOfGroups = new HashMap<>(); + JBTreeTraverser.from(node -> node.getChildren()) + .withRoot(root) + .preOrderDfsTraversal() + .consumeEach(node -> { + if (node.getChildren().isEmpty() && !node.isAny() && !node.isNothing() && + SchemaResolveState.normal.equals(node.getResolveState())) { + int groupNumber = node.getExcludingGroupNumber(); + if (groupNumber < 0) { + schemas.add(node.getSchema()); + } + else { + Set set = oneOfGroups.get(groupNumber); + if (set == null) oneOfGroups.put(groupNumber, (set = new HashSet<>())); + set.add(node.getSchema()); + } + } + }); return new MatchResult(schemas, new ArrayList<>(oneOfGroups.values())); } } diff --git a/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java b/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java index dd8f3a340634..39243b6c44a7 100644 --- a/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java +++ b/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java @@ -296,7 +296,7 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre @NotNull private static JBTreeTraverser traverser() { - return new JBTreeTraverser<>(o -> (o instanceof Group ? JBIterable.from(((Group)o).getChildren()) : JBIterable.empty())); + return JBTreeTraverser.from(o -> o instanceof Group ? ((Group)o).getChildren() : null); } private JBIterable getSelectedElements() { diff --git a/platform/lang-impl/src/com/intellij/internal/psiView/formattingblocks/BlockViewerPsiBasedTree.java b/platform/lang-impl/src/com/intellij/internal/psiView/formattingblocks/BlockViewerPsiBasedTree.java index 286dd82555ec..10e3e0c5ab01 100644 --- a/platform/lang-impl/src/com/intellij/internal/psiView/formattingblocks/BlockViewerPsiBasedTree.java +++ b/platform/lang-impl/src/com/intellij/internal/psiView/formattingblocks/BlockViewerPsiBasedTree.java @@ -41,7 +41,6 @@ import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.treeStructure.Tree; import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.JBIterable; import com.intellij.util.containers.JBTreeTraverser; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -289,7 +288,7 @@ public class BlockViewerPsiBasedTree implements ViewerPsiBasedTree { private void initMap(BlockTreeNode rootBlockNode, PsiElement psiEl) { myPsiToBlockMap = new HashMap<>(); - JBTreeTraverser traverser = new JBTreeTraverser<>(o -> JBIterable.of(o.getChildren())); + JBTreeTraverser traverser = JBTreeTraverser.of(BlockTreeNode::getChildren); for (BlockTreeNode block : traverser.withRoot(rootBlockNode)) { PsiElement currentElem = null; if (block.getBlock() instanceof ASTBlock) { diff --git a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java index 00f72f98af17..466a1c332583 100644 --- a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java +++ b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java @@ -57,7 +57,7 @@ public final class TreeUtil { TreeModel model = tree.getModel(); Object root = model.getRoot(); TreePath rootPath = root == null ? null : new TreePath(root); - return new JBTreeTraverser(path -> nodeChildren(path.getLastPathComponent(), model) + return JBTreeTraverser.from(path -> nodeChildren(path.getLastPathComponent(), model) .map(o -> path.pathByAddingChild(o))) .withRoot(rootPath); } diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index 3287178e0bfc..3cc99d4993ee 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -1289,15 +1289,15 @@ public class FileUtil extends FileUtilRt { @NotNull public static JBTreeTraverser fileTraverser(@Nullable File root) { - return new JBTreeTraverser(FILE_CHILDREN).withRoot(root); + return FILE_TRAVERSER.withRoot(root); } - private static final Function> FILE_CHILDREN = new Function>() { + private static final JBTreeTraverser FILE_TRAVERSER = JBTreeTraverser.from(new Function>() { @Override public Iterable fun(File file) { return file != null && file.isDirectory() ? JBIterable.of(file.listFiles()) : JBIterable.empty(); } - }; + }); public static boolean processFilesRecursively(@NotNull File root, @NotNull Processor processor) { return fileTraverser(root).bfsTraversal().processEach(processor); diff --git a/platform/util/src/com/intellij/util/ReflectionUtil.java b/platform/util/src/com/intellij/util/ReflectionUtil.java index 47bdc4b9548d..06f700bb4d2a 100644 --- a/platform/util/src/com/intellij/util/ReflectionUtil.java +++ b/platform/util/src/com/intellij/util/ReflectionUtil.java @@ -624,13 +624,13 @@ public class ReflectionUtil { @NotNull public static JBTreeTraverser classTraverser(@Nullable Class root) { - return new JBTreeTraverser(CLASS_STRUCTURE).unique().withRoot(root); + return CLASS_TRAVERSER.unique().withRoot(root); } - private static final Function> CLASS_STRUCTURE = new Function>() { + private static final JBTreeTraverser CLASS_TRAVERSER = JBTreeTraverser.from(new Function>() { @Override public Iterable fun(Class aClass) { return JBIterable.of(aClass.getSuperclass()).append(aClass.getInterfaces()); } - }; + }); } \ No newline at end of file diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index a61d5a9a3207..8c00d0d501ca 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -3156,12 +3156,12 @@ public class UIUtil { @NotNull public static JBTreeTraverser uiTraverser(@Nullable Component component) { - return new JBTreeTraverser(COMPONENT_CHILDREN).withRoot(component); + return UI_TRAVERSER.withRoot(component); } public static final Key> NOT_IN_HIERARCHY_COMPONENTS = Key.create("NOT_IN_HIERARCHY_COMPONENTS"); - private static final Function> COMPONENT_CHILDREN = new Function>() { + private static final JBTreeTraverser UI_TRAVERSER = JBTreeTraverser.from(new Function>() { @Override public JBIterable fun(@NotNull Component c) { JBIterable result; @@ -3189,7 +3189,7 @@ public class UIUtil { } return result; } - }; + }); private static final Function.Mono COMPONENT_PARENT = new Function.Mono() { @Override From 5a22b3ac4580225302b8eb600f0cca76fd44ed11 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Thu, 5 Oct 2017 18:00:41 +0300 Subject: [PATCH 18/28] comment IdeaOpenApiNonCodeMembersContributor in plugin.xml since it breaks tests --- plugins/groovy/src/META-INF/plugin.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 6a834b7b7961..2fe276613034 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -113,7 +113,7 @@ - + From 7535ed913be54ac081618f3c3b9be2beefbf7a12 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Thu, 5 Oct 2017 18:02:54 +0300 Subject: [PATCH 19/28] fixed help topic --- .../debugger/settings/CaptureConfigurable.java | 6 ++++++ .../DebuggerDataViewsConfigurable.java | 18 ++---------------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/CaptureConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/CaptureConfigurable.java index c969d6132bc1..c48714fa5fe8 100644 --- a/java/debugger/impl/src/com/intellij/debugger/settings/CaptureConfigurable.java +++ b/java/debugger/impl/src/com/intellij/debugger/settings/CaptureConfigurable.java @@ -66,6 +66,12 @@ public class CaptureConfigurable implements SearchableConfigurable { @NotNull @Override public String getId() { + return getHelpTopic(); + } + + @NotNull + @Override + public String getHelpTopic() { return "reference.idesettings.debugger.capture"; } diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java index 99038932ae5d..770695874a49 100644 --- a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java +++ b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java @@ -1,18 +1,4 @@ -/* - * 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. - * 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.settings; import com.intellij.debugger.DebuggerBundle; @@ -315,7 +301,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable { @Override @NotNull public String getHelpTopic() { - return "reference.idesettings.debugger.dataviews"; + return "Debugger_Data_Views_Java"; } @Override From 2624b29fd76955a2df786e7462dd4dacceb24e10 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 5 Oct 2017 17:02:44 +0200 Subject: [PATCH 20/28] prefer exact empty range when restoring anchors/smart pointers (fixes HbStructureViewTest) --- .../src/com/intellij/psi/impl/smartPointers/Identikit.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/Identikit.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/Identikit.java index 39c14aaacbc3..e7a14a05f98c 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/Identikit.java +++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/Identikit.java @@ -94,7 +94,7 @@ public abstract class Identikit { PsiElement result = findParent(startOffset, endOffset, anchor); if (endOffset == startOffset) { - while (result == null && anchor.getTextRange().getStartOffset() == endOffset) { + while ((result == null || result.getTextRange().getStartOffset() != startOffset) && anchor.getTextRange().getStartOffset() == endOffset) { anchor = PsiTreeUtil.prevLeaf(anchor, false); if (anchor == null) break; From 5910105296c5c2094df00f4a73ae70b9ec45ce51 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Thu, 5 Oct 2017 18:24:51 +0300 Subject: [PATCH 21/28] rename TokenSet#WS to WHITE_SPACE (IDEA-CR-25143) --- .idea/inspectionProfiles/idea_default.xml | 2 +- platform/core-api/src/com/intellij/lang/ParserDefinition.java | 2 +- platform/core-api/src/com/intellij/psi/tree/TokenSet.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.idea/inspectionProfiles/idea_default.xml b/.idea/inspectionProfiles/idea_default.xml index 6950f21f96bf..6d25b3482a80 100644 --- a/.idea/inspectionProfiles/idea_default.xml +++ b/.idea/inspectionProfiles/idea_default.xml @@ -761,7 +761,7 @@ - + diff --git a/platform/core-api/src/com/intellij/lang/ParserDefinition.java b/platform/core-api/src/com/intellij/lang/ParserDefinition.java index 927ca720c0f6..cea99fe63aca 100644 --- a/platform/core-api/src/com/intellij/lang/ParserDefinition.java +++ b/platform/core-api/src/com/intellij/lang/ParserDefinition.java @@ -53,7 +53,7 @@ public interface ParserDefinition { */ @NotNull default TokenSet getWhitespaceTokens() { - return TokenSet.WS; + return TokenSet.WHITE_SPACE; } /** diff --git a/platform/core-api/src/com/intellij/psi/tree/TokenSet.java b/platform/core-api/src/com/intellij/psi/tree/TokenSet.java index 7cfff18498fd..2016569529ef 100644 --- a/platform/core-api/src/com/intellij/psi/tree/TokenSet.java +++ b/platform/core-api/src/com/intellij/psi/tree/TokenSet.java @@ -21,7 +21,7 @@ public class TokenSet { public static final TokenSet ANY = new TokenSet(Short.MAX_VALUE, (short)0) { @Override public boolean contains(IElementType t) { return true; } }; - public static final TokenSet WS = doCreate(TokenType.WHITE_SPACE); + public static final TokenSet WHITE_SPACE = doCreate(TokenType.WHITE_SPACE); private final short myShift; private final short myMax; @@ -97,7 +97,7 @@ public class TokenSet { public static TokenSet create(@NotNull IElementType... types) { if (types.length == 0) return EMPTY; if (types.length == 1 && types[0] == TokenType.WHITE_SPACE) { - return WS; + return WHITE_SPACE; } return doCreate(types); } From a496c82a8fc4dd73a3c8c6c69560a8d89661009d Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 5 Oct 2017 18:40:47 +0300 Subject: [PATCH 22/28] project configuration: do not set module groups for new modules (IDEA-179968) --- .../ui/configuration/actions/NewModuleInGroupAction.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/actions/NewModuleInGroupAction.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/actions/NewModuleInGroupAction.java index f5e031ecff0d..b4efa5864650 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/actions/NewModuleInGroupAction.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/actions/NewModuleInGroupAction.java @@ -20,6 +20,7 @@ import com.intellij.openapi.actionSystem.ActionPlaces; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleGrouperKt; import com.intellij.openapi.module.impl.ModuleManagerImpl; /** @@ -47,9 +48,11 @@ public class NewModuleInGroupAction extends NewModuleAction { @Override protected void processCreatedModule(final Module module, final Object dataFromContext) { - ModuleGroup group = (ModuleGroup) dataFromContext; - if (group != null) { - ModuleManagerImpl.getInstanceImpl(module.getProject()).setModuleGroupPath(module, group.getGroupPath()); + if (!ModuleGrouperKt.isQualifiedModuleNamesEnabled(module.getProject())) { + ModuleGroup group = (ModuleGroup) dataFromContext; + if (group != null) { + ModuleManagerImpl.getInstanceImpl(module.getProject()).setModuleGroupPath(module, group.getGroupPath()); + } } } } From 632fd799c7898f41945443f9c0d5a6955ddd571e Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 5 Oct 2017 18:42:58 +0300 Subject: [PATCH 23/28] 'Project Structure' dialog: suggest prefix for new module names If a module group is selected in 'Project Structure' dialog use its name as a prefix for module name if 'New Module' action is invoked (see also IDEA-179968). --- .../projectWizard/ModuleNameLocationComponent.java | 2 +- .../ide/projectWizard/NewProjectWizard.java | 3 ++- .../ui/configuration/ModulesConfigurator.java | 8 ++++---- .../projectRoot/ModuleStructureConfigurable.java | 14 +++++++++++--- .../ide/util/projectWizard/WizardContext.java | 9 +++++++++ .../openapi/ui/MasterDetailsComponent.java | 12 ++++++++---- 6 files changed, 35 insertions(+), 13 deletions(-) diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ModuleNameLocationComponent.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ModuleNameLocationComponent.java index 7b1103611db4..cb4e303fa081 100644 --- a/java/idea-ui/src/com/intellij/ide/projectWizard/ModuleNameLocationComponent.java +++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ModuleNameLocationComponent.java @@ -197,7 +197,7 @@ public class ModuleNameLocationComponent { VirtualFile baseDir = project.getBaseDir(); if (baseDir != null) { //e.g. was deleted final String baseDirPath = baseDir.getPath(); - String moduleName = ProjectWizardUtil.findNonExistingFileName(baseDirPath, "untitled", ""); + String moduleName = ProjectWizardUtil.findNonExistingFileName(baseDirPath, myWizardContext.getDefaultModuleName(), ""); String contentRoot = baseDirPath + "/" + moduleName; if (!Comparing.strEqual(project.getName(), myWizardContext.getProjectName()) && !myWizardContext.isCreatingNewProject() && diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java b/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java index 038959e1ddb1..03f37f5989f9 100644 --- a/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java +++ b/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java @@ -39,8 +39,9 @@ public class NewProjectWizard extends AbstractProjectWizard { init(modulesProvider); } - public NewProjectWizard(Project project, Component dialogParent, ModulesProvider modulesProvider) { + public NewProjectWizard(Project project, Component dialogParent, ModulesProvider modulesProvider, String defaultModuleName) { super(IdeBundle.message("title.add.module"), project, dialogParent); + myWizardContext.setDefaultModuleName(defaultModuleName); init(modulesProvider); } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java index c1424e0615b2..8d97e808fa73 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java @@ -370,9 +370,9 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change @Nullable - public List addModule(Component parent, boolean anImport) { + public List addModule(Component parent, boolean anImport, String defaultModuleName) { if (myProject.isDefault()) return null; - final ProjectBuilder builder = runModuleWizard(parent, anImport); + final ProjectBuilder builder = runModuleWizard(parent, anImport, defaultModuleName); if (builder != null ) { final List modules = new ArrayList<>(); final List committedModules; @@ -426,7 +426,7 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change } @Nullable - ProjectBuilder runModuleWizard(Component dialogParent, boolean anImport) { + private ProjectBuilder runModuleWizard(Component dialogParent, boolean anImport, String defaultModuleName) { AbstractProjectWizard wizard; if (anImport) { wizard = ImportModuleAction.selectFileAndCreateWizard(myProject, dialogParent); @@ -438,7 +438,7 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change } } else { - wizard = new NewProjectWizard(myProject, dialogParent, this); + wizard = new NewProjectWizard(myProject, dialogParent, this, defaultModuleName); } if (!wizard.showAndGet()) { return null; diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java index 9e2964f35bdd..b91dd49eee5f 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java @@ -541,8 +541,8 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple return myContext.myModulesConfigurator.getFacetsConfigurator(); } - private void addModule(boolean anImport) { - final List modules = myContext.myModulesConfigurator.addModule(myTree, anImport); + private void addModule(boolean anImport, String defaultModuleName) { + final List modules = myContext.myModulesConfigurator.addModule(myTree, anImport, defaultModuleName); if (modules != null) { for (Module module : modules) { addModuleNode(module); @@ -1006,7 +1006,15 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple @Override public void actionPerformed(final AnActionEvent e) { - addModule(myImport); + String defaultModuleName = "untitled"; + MyNode selectedNode = getSelectedNode(); + if (ModuleGrouperKt.isQualifiedModuleNamesEnabled(myProject) && selectedNode instanceof ModuleGroupNodeImpl) { + ModuleGroup group = ((ModuleGroupNode)selectedNode).getModuleGroup(); + if (group != null && !group.getGroupPathList().isEmpty()) { + defaultModuleName = StringUtil.join(group.getGroupPathList(), ".") + ".untitled"; + } + } + addModule(myImport, defaultModuleName); } } diff --git a/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java b/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java index c2dde7532fc6..1566d3cacda2 100644 --- a/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java +++ b/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java @@ -57,6 +57,7 @@ public class WizardContext extends UserDataHolderBase { private ModulesProvider myModulesProvider; private boolean myProjectFileDirectorySetExplicitly; private AbstractWizard myWizard; + private String myDefaultModuleName = "untitled"; public void setProjectStorageFormat(StorageScheme format) { myProjectStorageFormat = format; @@ -86,6 +87,14 @@ public class WizardContext extends UserDataHolderBase { myWizard = wizard; } + public void setDefaultModuleName(String defaultModuleName) { + myDefaultModuleName = defaultModuleName; + } + + public String getDefaultModuleName() { + return myDefaultModuleName; + } + public interface Listener { void buttonsUpdateRequested(); void nextStepRequested(); diff --git a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java index ab2e811663a7..e43bfc9034d1 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java @@ -601,12 +601,16 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom return null; } + public final MyNode getSelectedNode() { + TreePath path = myTree.getSelectionPath(); + return path != null ? (MyNode)path.getLastPathComponent() : null; + } + @Nullable public NamedConfigurable getSelectedConfigurable() { - final TreePath selectionPath = myTree.getSelectionPath(); - if (selectionPath != null) { - MyNode node = (MyNode)selectionPath.getLastPathComponent(); - final NamedConfigurable configurable = node.getConfigurable(); + MyNode selectedNode = getSelectedNode(); + if (selectedNode != null) { + final NamedConfigurable configurable = selectedNode.getConfigurable(); LOG.assertTrue(configurable != null, "already disposed"); return configurable; } From 33ac210e7b18e273031611ec32b44ef0ac0546e2 Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Thu, 5 Oct 2017 17:52:08 +0200 Subject: [PATCH 24/28] show shortened classpath preview (IDEA-165946) --- .../JavaTestFrameworkRunnableState.java | 21 ++++++++++++---- .../application/ApplicationConfiguration.java | 12 ++++++++++ .../openapi/projectRoots/JdkUtil.java | 24 +++++++++++++++---- .../execution/filters/ArgumentFileFilter.kt | 8 ++++++- 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/java/execution/impl/src/com/intellij/execution/JavaTestFrameworkRunnableState.java b/java/execution/impl/src/com/intellij/execution/JavaTestFrameworkRunnableState.java index ebeb4b2eef6e..d2cb63307cdb 100644 --- a/java/execution/impl/src/com/intellij/execution/JavaTestFrameworkRunnableState.java +++ b/java/execution/impl/src/com/intellij/execution/JavaTestFrameworkRunnableState.java @@ -19,6 +19,7 @@ import com.intellij.ExtensionPoints; import com.intellij.debugger.impl.GenericDebuggerRunnerSettings; import com.intellij.diagnostic.logging.OutputFileUtil; import com.intellij.execution.configurations.*; +import com.intellij.execution.filters.ArgumentFileFilter; import com.intellij.execution.impl.ConsoleBuffer; import com.intellij.execution.process.OSProcessHandler; import com.intellij.execution.process.ProcessAdapter; @@ -66,10 +67,7 @@ import org.jetbrains.jps.model.serialization.PathMacroUtil; import java.io.*; import java.net.InetAddress; import java.net.ServerSocket; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import java.util.*; public abstract class JavaTestFrameworkRunnableState @@ -82,6 +80,7 @@ public abstract class JavaTestFrameworkRunnableState myArgumentFileFilters = new ArrayList<>(); public void setRemoteConnectionCreator(RemoteConnectionCreator remoteConnectionCreator) { this.remoteConnectionCreator = remoteConnectionCreator; @@ -128,6 +127,16 @@ public abstract class JavaTestFrameworkRunnableState content = commandLine.getUserData(JdkUtil.COMMAND_LINE_CONTENT); + if (content != null) { + content.forEach((key, value) -> myArgumentFileFilters.add(new ArgumentFileFilter(key, value))); + } + return commandLine; + } + @NotNull @Override public ExecutionResult execute(@NotNull Executor executor, @NotNull ProgramRunner runner) throws ExecutionException { @@ -143,6 +152,10 @@ public abstract class JavaTestFrameworkRunnableState content = line.getUserData(JdkUtil.COMMAND_LINE_CONTENT); + if (content != null) { + content.forEach((key, value) -> addConsoleFilters(new ArgumentFileFilter(key, value))); + } + return line; + } + @NotNull @Override protected OSProcessHandler startProcess() throws ExecutionException { diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java index 11a861ef196c..f0268dc21841 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java @@ -25,6 +25,7 @@ import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.io.JarUtil; @@ -34,6 +35,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.encoding.EncodingManager; import com.intellij.util.PathUtil; import com.intellij.util.PathsList; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.execution.ParametersListUtil; import com.intellij.util.lang.UrlClassLoader; import gnu.trove.THashMap; @@ -53,6 +55,8 @@ import java.util.jar.Manifest; * @author max */ public class JdkUtil { + public static Key> COMMAND_LINE_CONTENT = Key.create("command.line.content"); + /** * The VM property is needed to workaround incorrect escaped URLs handling in WebSphere, * see IDEA-126859 for additional details @@ -250,6 +254,8 @@ public class JdkUtil { } } + commandLine.putUserData(COMMAND_LINE_CONTENT, ContainerUtil.stringMap(argFile.getAbsolutePath(), FileUtil.loadFile(argFile))); + appendEncoding(javaParameters, commandLine, vmParameters); commandLine.addParameter("@" + argFile.getAbsolutePath()); @@ -325,12 +331,16 @@ public class JdkUtil { } File classpathFile = FileUtil.createTempFile("idea_classpath", null); + PathsList classPath = javaParameters.getClassPath(); try (PrintWriter writer = new PrintWriter(classpathFile)) { - for (String path : javaParameters.getClassPath().getPathList()) { + for (String path : classPath.getPathList()) { writer.println(path); } } + Map map = ContainerUtil.stringMap(classpathFile.getAbsolutePath(), classPath.getPathsString()); + commandLine.putUserData(COMMAND_LINE_CONTENT, map); + Set classpath = new LinkedHashSet<>(); classpath.add(PathUtil.getJarPathForClass(commandLineWrapper)); if (UrlClassLoader.class.getName().equals(vmParameters.getPropertyValue("java.system.class.loader"))) { @@ -348,12 +358,14 @@ public class JdkUtil { if (vmParamsFile != null) { commandLine.addParameter("@vm_params"); commandLine.addParameter(vmParamsFile.getAbsolutePath()); + map.put(vmParamsFile.getAbsolutePath(), FileUtil.loadFile(vmParamsFile)); OSProcessHandler.deleteFileOnTermination(commandLine, vmParamsFile); } if (appParamsFile != null) { commandLine.addParameter("@app_params"); commandLine.addParameter(appParamsFile.getAbsolutePath()); + map.put(appParamsFile.getAbsolutePath(), FileUtil.loadFile(appParamsFile)); OSProcessHandler.deleteFileOnTermination(commandLine, appParamsFile); } } @@ -372,6 +384,7 @@ public class JdkUtil { Manifest manifest = new Manifest(); manifest.getMainAttributes().putValue("Created-By", ApplicationNamesInfo.getInstance().getFullProductName()); + String manifestText = "Manifest.MF"; if (dynamicVMOptions) { List properties = new ArrayList<>(); for (String param : vmParameters.getList()) { @@ -383,6 +396,7 @@ public class JdkUtil { } } manifest.getMainAttributes().putValue("VM-Options", ParametersListUtil.join(properties)); + manifestText += "VM-Options: " + ParametersListUtil.join(properties) + "\n"; } else { commandLine.addParameters(vmParameters.getList()); @@ -392,12 +406,12 @@ public class JdkUtil { if (dynamicParameters) { manifest.getMainAttributes().putValue("Program-Parameters", ParametersListUtil.join(javaParameters.getProgramParametersList().getList())); + manifestText += "Program-Parameters: " + ParametersListUtil.join(javaParameters.getProgramParametersList().getList()) + "\n"; } boolean notEscape = vmParameters.hasParameter(PROPERTY_DO_NOT_ESCAPE_CLASSPATH_URL); - List classPathList = javaParameters.getClassPath().getPathList(); - - File classpathJarFile = CommandLineWrapperUtil.createClasspathJarFile(manifest, classPathList, notEscape); + PathsList path = javaParameters.getClassPath(); + File classpathJarFile = CommandLineWrapperUtil.createClasspathJarFile(manifest, path.getPathList(), notEscape); String jarFilePath = classpathJarFile.getAbsolutePath(); commandLine.addParameter("-classpath"); @@ -407,6 +421,8 @@ public class JdkUtil { } commandLine.addParameter(jarFilePath); + commandLine.putUserData(COMMAND_LINE_CONTENT, ContainerUtil.stringMap(jarFilePath, manifestText + "Class-Path: " + path.getPathsString())); + OSProcessHandler.deleteFileOnTermination(commandLine, classpathJarFile); } catch (IOException e) { diff --git a/platform/platform-impl/src/com/intellij/execution/filters/ArgumentFileFilter.kt b/platform/platform-impl/src/com/intellij/execution/filters/ArgumentFileFilter.kt index 9616b428acb6..b5f5e833562d 100644 --- a/platform/platform-impl/src/com/intellij/execution/filters/ArgumentFileFilter.kt +++ b/platform/platform-impl/src/com/intellij/execution/filters/ArgumentFileFilter.kt @@ -6,11 +6,17 @@ import java.io.File /** * A console filter which looks for a given path in an output and creates a link for viewing a content of that file. */ -class ArgumentFileFilter : Filter { +class ArgumentFileFilter() : Filter { @Volatile private var filePath: String? = null @Volatile private var fileText: String? = null private var triggered = false + constructor(filePath: String?, fileText: String?) : this() { + this.filePath = filePath + this.fileText = fileText + } + + fun setPath(path: String) { filePath = path fileText = File(path).readText() From aec34583a3871f837c706c8f99304fdf867426a6 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 5 Oct 2017 18:03:05 +0200 Subject: [PATCH 25/28] [java] parses references in @uses and @provides tags --- .../lang/java/parser/JavadocParser.java | 25 +++------ .../javadocParsing/ProvidesTag.java | 4 ++ .../javadocParsing/ProvidesTag.txt | 52 +++++++++++++++++++ .../parser-full/javadocParsing/ThrowsTag.java | 4 ++ .../parser-full/javadocParsing/ThrowsTag.txt | 37 +++++++++++++ .../parser-full/javadocParsing/UsesTag.java | 4 ++ .../parser-full/javadocParsing/UsesTag.txt | 52 +++++++++++++++++++ .../java/parser/JavadocParsingTest.java | 20 ++----- 8 files changed, 165 insertions(+), 33 deletions(-) create mode 100644 java/java-tests/testData/psi/parser-full/javadocParsing/ProvidesTag.java create mode 100644 java/java-tests/testData/psi/parser-full/javadocParsing/ProvidesTag.txt create mode 100644 java/java-tests/testData/psi/parser-full/javadocParsing/ThrowsTag.java create mode 100644 java/java-tests/testData/psi/parser-full/javadocParsing/ThrowsTag.txt create mode 100644 java/java-tests/testData/psi/parser-full/javadocParsing/UsesTag.java create mode 100644 java/java-tests/testData/psi/parser-full/javadocParsing/UsesTag.txt diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/JavadocParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/JavadocParser.java index 4b0aea42f76a..ef9aac468b8e 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/JavadocParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/JavadocParser.java @@ -1,18 +1,4 @@ -/* - * 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. - * 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.lang.java.parser; import com.intellij.lang.PsiBuilder; @@ -26,6 +12,10 @@ import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Set; + +import static com.intellij.util.containers.ContainerUtil.newTroveSet; + public class JavadocParser { private static final TokenSet TAG_VALUES_SET = TokenSet.create( JavaDocTokenType.DOC_TAG_VALUE_TOKEN, JavaDocTokenType.DOC_TAG_VALUE_COMMA, JavaDocTokenType.DOC_TAG_VALUE_DOT, @@ -40,10 +30,9 @@ public class JavadocParser { private static final String SEE_TAG = "@see"; private static final String LINK_TAG = "@link"; private static final String LINK_PLAIN_TAG = "@linkplain"; - private static final String THROWS_TAG = "@throws"; - private static final String EXCEPTION_TAG = "@exception"; private static final String PARAM_TAG = "@param"; private static final String VALUE_TAG = "@value"; + private static final Set REFERENCE_TAGS = newTroveSet("@throws", "@exception", "@provides", "@uses"); private static Key BRACE_SCOPE_KEY = Key.create("Javadoc.Parser.Brace.Scope"); @@ -139,7 +128,7 @@ public class JavadocParser { JavaParserUtil.getLanguageLevel(builder).isAtLeast(LanguageLevel.JDK_1_4) && LINK_PLAIN_TAG.equals(tagName) && isInline) { parseSeeTagValue(builder, false); } - else if (!isInline && (THROWS_TAG.equals(tagName) || EXCEPTION_TAG.equals(tagName))) { + else if (!isInline && REFERENCE_TAGS.contains(tagName)) { PsiBuilder.Marker tagValue = builder.mark(); builder.remapCurrentToken(JavaDocElementType.DOC_REFERENCE_HOLDER); builder.advanceLexer(); diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/ProvidesTag.java b/java/java-tests/testData/psi/parser-full/javadocParsing/ProvidesTag.java new file mode 100644 index 000000000000..9bbecf79772d --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/javadocParsing/ProvidesTag.java @@ -0,0 +1,4 @@ +/** + * @provides java.nio.file.FileSystem just for fun + */ +class Test {} \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/ProvidesTag.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/ProvidesTag.txt new file mode 100644 index 000000000000..a8834a9916b3 --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/javadocParsing/ProvidesTag.txt @@ -0,0 +1,52 @@ +PsiJavaFile:ProvidesTag.java + PsiImportList + + PsiClass:Test + PsiDocComment + PsiDocToken:DOC_COMMENT_START('/**') + PsiWhiteSpace('\n ') + PsiDocToken:DOC_COMMENT_LEADING_ASTERISKS('*') + PsiDocToken:DOC_COMMENT_DATA(' ') + PsiDocTag:@provides + PsiDocToken:DOC_TAG_NAME('@provides') + PsiWhiteSpace(' ') + PsiElement(DOC_TAG_VALUE_ELEMENT) + PsiElement(DOC_REFERENCE_HOLDER) + PsiJavaCodeReferenceElement:java.nio.file.FileSystem + PsiJavaCodeReferenceElement:java.nio.file + PsiJavaCodeReferenceElement:java.nio + PsiJavaCodeReferenceElement:java + PsiIdentifier:java('java') + PsiReferenceParameterList + + PsiJavaToken:DOT('.') + PsiIdentifier:nio('nio') + PsiReferenceParameterList + + PsiJavaToken:DOT('.') + PsiIdentifier:file('file') + PsiReferenceParameterList + + PsiJavaToken:DOT('.') + PsiIdentifier:FileSystem('FileSystem') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiDocToken:DOC_COMMENT_DATA('just for fun') + PsiWhiteSpace('\n ') + PsiDocToken:DOC_COMMENT_END('*/') + PsiWhiteSpace('\n') + PsiModifierList: + + PsiKeyword:class('class') + PsiWhiteSpace(' ') + PsiIdentifier:Test('Test') + PsiTypeParameterList + + PsiReferenceList + + PsiReferenceList + + PsiWhiteSpace(' ') + PsiJavaToken:LBRACE('{') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/ThrowsTag.java b/java/java-tests/testData/psi/parser-full/javadocParsing/ThrowsTag.java new file mode 100644 index 000000000000..64fcb3ee5e20 --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/javadocParsing/ThrowsTag.java @@ -0,0 +1,4 @@ +/** + * @throws E an exception + */ +class Test {} \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/ThrowsTag.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/ThrowsTag.txt new file mode 100644 index 000000000000..008a9b22c489 --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/javadocParsing/ThrowsTag.txt @@ -0,0 +1,37 @@ +PsiJavaFile:ThrowsTag.java + PsiImportList + + PsiClass:Test + PsiDocComment + PsiDocToken:DOC_COMMENT_START('/**') + PsiWhiteSpace('\n ') + PsiDocToken:DOC_COMMENT_LEADING_ASTERISKS('*') + PsiDocToken:DOC_COMMENT_DATA(' ') + PsiDocTag:@throws + PsiDocToken:DOC_TAG_NAME('@throws') + PsiWhiteSpace(' ') + PsiElement(DOC_TAG_VALUE_ELEMENT) + PsiElement(DOC_REFERENCE_HOLDER) + PsiJavaCodeReferenceElement:E + PsiIdentifier:E('E') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiDocToken:DOC_COMMENT_DATA('an exception') + PsiWhiteSpace('\n ') + PsiDocToken:DOC_COMMENT_END('*/') + PsiWhiteSpace('\n') + PsiModifierList: + + PsiKeyword:class('class') + PsiWhiteSpace(' ') + PsiIdentifier:Test('Test') + PsiTypeParameterList + + PsiReferenceList + + PsiReferenceList + + PsiWhiteSpace(' ') + PsiJavaToken:LBRACE('{') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/UsesTag.java b/java/java-tests/testData/psi/parser-full/javadocParsing/UsesTag.java new file mode 100644 index 000000000000..209cebb6f567 --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/javadocParsing/UsesTag.java @@ -0,0 +1,4 @@ +/** + * @uses java.nio.file.FileSystem because it can + */ +class Test {} \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/UsesTag.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/UsesTag.txt new file mode 100644 index 000000000000..5d54e1f14862 --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/javadocParsing/UsesTag.txt @@ -0,0 +1,52 @@ +PsiJavaFile:UsesTag.java + PsiImportList + + PsiClass:Test + PsiDocComment + PsiDocToken:DOC_COMMENT_START('/**') + PsiWhiteSpace('\n ') + PsiDocToken:DOC_COMMENT_LEADING_ASTERISKS('*') + PsiDocToken:DOC_COMMENT_DATA(' ') + PsiDocTag:@uses + PsiDocToken:DOC_TAG_NAME('@uses') + PsiWhiteSpace(' ') + PsiElement(DOC_TAG_VALUE_ELEMENT) + PsiElement(DOC_REFERENCE_HOLDER) + PsiJavaCodeReferenceElement:java.nio.file.FileSystem + PsiJavaCodeReferenceElement:java.nio.file + PsiJavaCodeReferenceElement:java.nio + PsiJavaCodeReferenceElement:java + PsiIdentifier:java('java') + PsiReferenceParameterList + + PsiJavaToken:DOT('.') + PsiIdentifier:nio('nio') + PsiReferenceParameterList + + PsiJavaToken:DOT('.') + PsiIdentifier:file('file') + PsiReferenceParameterList + + PsiJavaToken:DOT('.') + PsiIdentifier:FileSystem('FileSystem') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiDocToken:DOC_COMMENT_DATA('because it can') + PsiWhiteSpace('\n ') + PsiDocToken:DOC_COMMENT_END('*/') + PsiWhiteSpace('\n') + PsiModifierList: + + PsiKeyword:class('class') + PsiWhiteSpace(' ') + PsiIdentifier:Test('Test') + PsiTypeParameterList + + PsiReferenceList + + PsiReferenceList + + PsiWhiteSpace(' ') + PsiJavaToken:LBRACE('{') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/parser/JavadocParsingTest.java b/java/java-tests/testSrc/com/intellij/java/parser/JavadocParsingTest.java index fa36e63f7015..2c4377464f1a 100644 --- a/java/java-tests/testSrc/com/intellij/java/parser/JavadocParsingTest.java +++ b/java/java-tests/testSrc/com/intellij/java/parser/JavadocParsingTest.java @@ -1,18 +1,4 @@ -/* - * 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. - * 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.java.parser; public class JavadocParsingTest extends JavaParsingTestCase { @@ -93,4 +79,8 @@ public class JavadocParsingTest extends JavaParsingTestCase { public void testValueQualified() { doTest(true); } public void testValueUnqualifiedWithHash() { doTest(true); } public void testValueUnqualifiedWithoutHash() { doTest(true); } + + public void testThrowsTag() { doTest(true); } + public void testUsesTag() { doTest(true); } + public void testProvidesTag() { doTest(true); } } \ No newline at end of file From 2f16a29c5c4097b33c1e1274f441527714f6edd6 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 5 Oct 2017 18:15:08 +0200 Subject: [PATCH 26/28] adapt CompilerReferencesTest to psi invalidation on root change --- .../intellij/java/compiler/CompilerReferencesTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/java/compiler/CompilerReferencesTest.java b/java/java-tests/testSrc/com/intellij/java/compiler/CompilerReferencesTest.java index 3b5acb3c24ae..d8342e7c2faf 100644 --- a/java/java-tests/testSrc/com/intellij/java/compiler/CompilerReferencesTest.java +++ b/java/java-tests/testSrc/com/intellij/java/compiler/CompilerReferencesTest.java @@ -123,10 +123,10 @@ public class CompilerReferencesTest extends CompilerReferencesTestBase { } public void testExtensionRename() { - final PsiFile file = myFixture.configureByFiles(getName() + "/Bar.java", getName() + "/Foo.txt")[1]; + VirtualFile file = myFixture.configureByFiles(getName() + "/Bar.java", getName() + "/Foo.txt")[1].getVirtualFile(); rebuildProject(); assertOneElement(getReferentFilesForElementUnderCaret()); - myFixture.renameElement(file, "Foo.java"); + myFixture.renameElement(getPsiManager().findFile(file), "Foo.java"); final PsiClass foo = myFixture.findClass("Foo"); assertNotNull(foo); final CompilerReferenceServiceImpl compilerReferenceService = (CompilerReferenceServiceImpl) CompilerReferenceService @@ -136,10 +136,10 @@ public class CompilerReferencesTest extends CompilerReferencesTestBase { } public void testReverseExtensionRename() { - final PsiFile file = myFixture.configureByFiles(getName() + "/Bar.java", getName() + "/Foo.java")[1]; + VirtualFile file = myFixture.configureByFiles(getName() + "/Bar.java", getName() + "/Foo.java")[1].getVirtualFile(); rebuildProject(); assertSize(2, getReferentFilesForElementUnderCaret()); - myFixture.renameElement(file, "Foo.txt"); + myFixture.renameElement(getPsiManager().findFile(file), "Foo.txt"); assertEquals("Bar.java", assertOneElement(getReferentFilesForElementUnderCaret()).getName()); } From 8435d98365af2c0223612bcc9b40037be23e8777 Mon Sep 17 00:00:00 2001 From: "Maxim.Kolmakov" Date: Thu, 5 Oct 2017 18:39:30 +0200 Subject: [PATCH 27/28] [gui-tests] Return exists method --- .../testGuiFramework/impl/GuiTestCase.kt | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestCase.kt b/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestCase.kt index 1a0f52015aaa..7a089a668bcf 100644 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestCase.kt +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestCase.kt @@ -44,6 +44,7 @@ import com.intellij.ui.components.labels.LinkLabel import org.fest.swing.exception.ActionFailedException import org.fest.swing.exception.ComponentLookupException import org.fest.swing.exception.WaitTimedOutError +import org.fest.swing.fixture.AbstractComponentFixture import org.fest.swing.fixture.JListFixture import org.fest.swing.fixture.JTableFixture import org.fest.swing.fixture.JTextComponentFixture @@ -96,7 +97,7 @@ open class GuiTestCase { /** * default timeout to find target component for fixture. Using seconds as time unit. */ - val defaultTimeout = 120L + var defaultTimeout = 120L val settingsTitle: String = if (isMac()) "Preferences" else "Settings" val defaultSettingsTitle: String = if (isMac()) "Default Preferences" else "Default Settings" @@ -639,6 +640,25 @@ open class GuiTestCase { return ExtendedTreeFixture(guiTestRule.robot(), myTree) } + fun exists(fixture: () -> AbstractComponentFixture<*, *, *>): Boolean { + val tmp = defaultTimeout + defaultTimeout = 0 + try { + fixture.invoke() + defaultTimeout = tmp + } + catch (ex: Exception) { + when (ex) { + is ComponentLookupException, + is WaitTimedOutError -> { + defaultTimeout = tmp; return false + } + else -> throw ex + } + } + return true + } + //*********SOME EXTENSION FUNCTIONS FOR FIXTURES fun JListFixture.doubleClickItem(itemName: String) { From ddae298befe55d07cc3b0c9f4af17c79df06c78f Mon Sep 17 00:00:00 2001 From: "Maxim.Kolmakov" Date: Thu, 5 Oct 2017 19:14:17 +0200 Subject: [PATCH 28/28] [gui-tests] GUI-42 Can't Click on browse button in NodeJS settings --- .../src/com/intellij/testGuiFramework/generators/Generators.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/generators/Generators.kt b/platform/testGuiFramework/src/com/intellij/testGuiFramework/generators/Generators.kt index fa52c449d3be..1daac66e5d13 100644 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/generators/Generators.kt +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/generators/Generators.kt @@ -103,7 +103,8 @@ class ComponentWithBrowseButtonGenerator : ComponentCodeGenerator