diff --git a/java/compiler/tests/com/intellij/compiler/artifacts/ui/ArtifactEditorTestCase.java b/java/compiler/tests/com/intellij/compiler/artifacts/ui/ArtifactEditorTestCase.java index 3c74644ece14..9b18c4aa0e3a 100644 --- a/java/compiler/tests/com/intellij/compiler/artifacts/ui/ArtifactEditorTestCase.java +++ b/java/compiler/tests/com/intellij/compiler/artifacts/ui/ArtifactEditorTestCase.java @@ -11,6 +11,7 @@ import com.intellij.openapi.util.Ref; import com.intellij.packaging.artifacts.Artifact; import com.intellij.packaging.elements.PackagingElementFactory; import com.intellij.util.PathUtil; +import org.jetbrains.annotations.NotNull; import java.util.Arrays; import java.util.Collections; @@ -79,7 +80,7 @@ public abstract class ArtifactEditorTestCase extends PackagingElementsTestCase { final Ref dialogShown = Ref.create(false); final TestDialog oldDialog = Messages.setTestDialog(new TestDialog() { @Override - public int show(String message) { + public int show(@NotNull String message) { dialogShown.set(true); return 0; } diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java index 03a223ad2080..8fffd0fcc2ef 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java @@ -2,6 +2,7 @@ package com.intellij.debugger.actions; import com.intellij.debugger.SourcePosition; +import com.intellij.debugger.engine.DebugProcessImpl; import com.intellij.debugger.engine.DebuggerUtils; import com.intellij.debugger.engine.SuspendContextImpl; import com.intellij.debugger.engine.evaluation.EvaluateException; @@ -26,7 +27,10 @@ import com.intellij.psi.*; import com.intellij.util.DocumentUtil; import com.intellij.util.Range; import com.intellij.util.ThreeState; +import com.intellij.util.containers.ContainerUtil; import com.sun.jdi.Location; +import com.sun.jdi.Method; +import com.sun.jdi.ReferenceType; import one.util.streamex.StreamEx; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -338,42 +342,67 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler { if (!targets.isEmpty()) { StackFrameProxyImpl frameProxy = suspendContext != null ? suspendContext.getFrameProxy() : null; if (frameProxy != null) { + // sanity check try { - Location location = frameProxy.location(); - MethodBytecodeUtil.visit(location.method(), location.codeIndex(), new MethodVisitor(Opcodes.API_VERSION) { - boolean myLineMatch = false; - - @Override - public void visitLineNumber(int line, Label start) { - myLineMatch = lines.isWithin(line - 1); - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - if (myLineMatch) { - Iterator iterator = targets.iterator(); - while (iterator.hasNext()) { - SmartStepTarget e = iterator.next(); - if (e instanceof MethodSmartStepTarget && - DebuggerUtilsEx.methodMatches(((MethodSmartStepTarget)e).getMethod(), - owner.replace("/", "."), name, desc, - suspendContext.getDebugProcess())) { - iterator.remove(); - MethodSmartStepTarget target = (MethodSmartStepTarget)e; - // fix ordinals - existingMethodCalls(targets, target.getMethod()) - .forEach(t -> { - int ordinal = t.getOrdinal(); - if (ordinal > target.getOrdinal()) { - t.setOrdinal(ordinal - 1); - } - }); - break; - } + List methodTargets = + StreamEx.of(targets) + .select(MethodSmartStepTarget.class) + .filter(target -> !target.needsBreakpointRequest()) + .toList(); + visitLinesMethods(frameProxy.location(), true, lines, (opcode, owner, name, desc, itf) -> { + if (name.startsWith("access$")) { // bridge method + ReferenceType cls = ContainerUtil.getFirstItem(frameProxy.getVirtualMachine().classesByName(owner)); + if (cls != null) { + Method method = DebuggerUtils.findMethod(cls, name, desc); + if (method != null) { + MethodBytecodeUtil.visit(method, new MethodVisitor(Opcodes.API_VERSION) { + @Override + public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { + if ("java/lang/AbstractMethodError".equals(owner)) { + return; + } + removeMatchingMethod(methodTargets, owner, name, desc, suspendContext.getDebugProcess()); + } + }, false); } } } - }, true); + else { + removeMatchingMethod(methodTargets, owner, name, desc, suspendContext.getDebugProcess()); + } + }); + if (!methodTargets.isEmpty()) { + return Collections.emptyList(); + } + } + catch (Exception e) { + LOG.error(e); + } + + // remove already executed + try { + visitLinesMethods(frameProxy.location(), false, lines, (opcode, owner, name, desc, itf) -> { + Iterator iterator = targets.iterator(); + while (iterator.hasNext()) { + SmartStepTarget e = iterator.next(); + if (e instanceof MethodSmartStepTarget && + DebuggerUtilsEx.methodMatches(((MethodSmartStepTarget)e).getMethod(), + owner.replace("/", "."), name, desc, + suspendContext.getDebugProcess())) { + iterator.remove(); + MethodSmartStepTarget target = (MethodSmartStepTarget)e; + // fix ordinals + existingMethodCalls(targets, target.getMethod()) + .forEach(t -> { + int ordinal = t.getOrdinal(); + if (ordinal > target.getOrdinal()) { + t.setOrdinal(ordinal - 1); + } + }); + break; + } + } + }); } catch (Exception e) { LOG.info(e); @@ -386,6 +415,42 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler { return Collections.emptyList(); } + private static void removeMatchingMethod(List targets, + String owner, + String name, + String desc, + DebugProcessImpl process) { + Iterator iterator = targets.iterator(); + while (iterator.hasNext()) { + if (DebuggerUtilsEx.methodMatches(iterator.next().getMethod(), owner.replace("/", "."), name, desc, process)) { + iterator.remove(); + break; + } + } + } + + private interface MethodInsnVisitor { + void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf); + } + + private static void visitLinesMethods(Location location, boolean full, Range lines, MethodInsnVisitor visitor) { + MethodBytecodeUtil.visit(location.method(), full ? Long.MAX_VALUE : location.codeIndex(), new MethodVisitor(Opcodes.API_VERSION) { + boolean myLineMatch = false; + + @Override + public void visitLineNumber(int line, Label start) { + myLineMatch = lines.isWithin(line - 1); + } + + @Override + public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { + if (myLineMatch) { + visitor.visitMethodInsn(opcode, owner, name, desc, itf); + } + } + }, true); + } + private static StreamEx existingMethodCalls(List targets, PsiMethod psiMethod) { return StreamEx.of(targets) .select(MethodSmartStepTarget.class) diff --git a/java/execution/impl/src/com/intellij/execution/testDiscovery/indices/TestFilesIndex.java b/java/execution/impl/src/com/intellij/execution/testDiscovery/indices/TestFilesIndex.java index 8158d3d34cfe..ad96c0b44db2 100644 --- a/java/execution/impl/src/com/intellij/execution/testDiscovery/indices/TestFilesIndex.java +++ b/java/execution/impl/src/com/intellij/execution/testDiscovery/indices/TestFilesIndex.java @@ -38,7 +38,7 @@ public class TestFilesIndex extends MapReduceIndex { @Nullable Collection getTestDataFor(int testId) throws IOException { ForwardIndex forwardIndex = getForwardIndexMap(); - KeyCollectionForwardIndexAccessor forwardIndexAccessor = (KeyCollectionForwardIndexAccessor)getForwardIndexAccessor(); + KeyCollectionForwardIndexAccessor forwardIndexAccessor = (KeyCollectionForwardIndexAccessor)getForwardIndexAccessor(); return forwardIndexAccessor.deserializeData(forwardIndex.get(testId)); } diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java index 465798769829..e0fefcf09d6e 100644 --- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java +++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java @@ -29,11 +29,11 @@ import com.intellij.ui.components.JBList; import com.intellij.ui.popup.list.GroupedItemsListRenderer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.JBUI; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; import javax.swing.*; -import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; import java.util.Collections; @@ -55,7 +55,7 @@ public class ProjectTemplateList extends JPanel { add(myPanel, BorderLayout.CENTER); GroupedItemsListRenderer renderer = new GroupedItemsListRenderer(new ListItemDescriptorAdapter() { - @Nullable + @NotNull @Override public String getTextFor(ProjectTemplate value) { return value.getName(); @@ -80,12 +80,7 @@ public class ProjectTemplateList extends JPanel { } }; myList.setCellRenderer(renderer); - myList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - updateSelection(); - } - }); + myList.getSelectionModel().addListSelectionListener(__ -> updateSelection()); Messages.installHyperlinkSupport(myDescriptionPane); } @@ -104,7 +99,7 @@ public class ProjectTemplateList extends JPanel { } } - public void setTemplates(List list, boolean preserveSelection) { + public void setTemplates(List list, boolean preserveSelection) { Collections.sort(list, (o1, o2) -> Comparing.compare(o1 instanceof ArchivedProjectTemplate, o2 instanceof ArchivedProjectTemplate)); int index = preserveSelection ? myList.getSelectedIndex() : -1; @@ -142,13 +137,10 @@ public class ProjectTemplateList extends JPanel { myList.setSelectedValue(template, true); } } - myList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - ProjectTemplate template = getSelectedTemplate(); - if (template != null) { - PropertiesComponent.getInstance().setValue(PROJECT_WIZARD_TEMPLATE, template.getName()); - } + myList.getSelectionModel().addListSelectionListener(__ -> { + ProjectTemplate template = getSelectedTemplate(); + if (template != null) { + PropertiesComponent.getInstance().setValue(PROJECT_WIZARD_TEMPLATE, template.getName()); } }); } @@ -166,7 +158,7 @@ public class ProjectTemplateList extends JPanel { } @TestOnly - public boolean setSelectedTemplate(String name) { + boolean setSelectedTemplate(@NotNull String name) { ListModel model1 = myList.getModel(); for (int j = 0; j < model1.getSize(); j++) { if (name.equals(((ProjectTemplate)model1.getElementAt(j)).getName())) { diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java index 587722001237..b0a6de73fd35 100644 --- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java +++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java @@ -54,8 +54,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; import java.awt.*; import java.net.URL; import java.util.HashMap; @@ -70,9 +68,9 @@ import java.util.*; public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, Disposable { private static final Logger LOG = Logger.getInstance(ProjectTypeStep.class); - public static final Convertor PROVIDER_STRING_CONVERTOR = + private static final Convertor PROVIDER_STRING_CONVERTOR = o -> o.getId(); - public static final Function NODE_STRING_FUNCTION = FrameworkSupportNodeBase::getId; + private static final Function NODE_STRING_FUNCTION = FrameworkSupportNodeBase::getId; private static final String TEMPLATES_CARD = "templates card"; private static final String FRAMEWORKS_CARD = "frameworks card"; private static final String PROJECT_WIZARD_GROUP = "project.wizard.group"; @@ -106,12 +104,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D myProjectTypeList.setModel(new CollectionListModel<>(groups)); myProjectTypeList.setSelectionModel(new SingleSelectionModel()); - myProjectTypeList.addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - updateSelection(); - } - }); + myProjectTypeList.addListSelectionListener(__ -> updateSelection()); myProjectTypeList.setCellRenderer(new GroupedItemsListRenderer(new ListItemDescriptorAdapter() { @Nullable @Override @@ -187,19 +180,9 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D } }; - myProjectTypeList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - projectTypeChanged(); - } - }); + myProjectTypeList.getSelectionModel().addListSelectionListener(__ -> projectTypeChanged()); - myTemplatesList.addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - updateSelection(); - } - }); + myTemplatesList.addListSelectionListener(__ -> updateSelection()); for (TemplatesGroup templatesGroup : myTemplatesMap.keySet()) { ModuleBuilder builder = templatesGroup.getModuleBuilder(); @@ -239,7 +222,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D return ContainerUtil.intersects(Arrays.asList(roles), acceptable); } - public static MultiMap getTemplatesMap(WizardContext context) { + private static MultiMap getTemplatesMap(WizardContext context) { ProjectTemplatesFactory[] factories = ProjectTemplatesFactory.EP_NAME.getExtensions(); final MultiMap groups = new MultiMap<>(); for (ProjectTemplatesFactory factory : factories) { @@ -351,7 +334,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D } // new TemplatesGroup selected - public void projectTypeChanged() { + private void projectTypeChanged() { TemplatesGroup group = getSelectedGroup(); if (group == null || group == myLastSelectedGroup) return; myLastSelectedGroup = group; @@ -431,7 +414,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D showCard(TEMPLATES_CARD); } - private void setTemplatesList(TemplatesGroup group, Collection templates, boolean preserveSelection) { + private void setTemplatesList(TemplatesGroup group, Collection templates, boolean preserveSelection) { List list = new ArrayList<>(templates); ModuleBuilder moduleBuilder = group.getModuleBuilder(); if (moduleBuilder != null && !(moduleBuilder instanceof TemplateModuleBuilder)) { @@ -463,7 +446,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D } @Nullable - public ProjectTemplate getSelectedTemplate() { + private ProjectTemplate getSelectedTemplate() { return myCurrentCard == TEMPLATES_CARD ? myTemplatesList.getSelectedTemplate() : null; } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/UIRootConfigurationAccessor.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/UIRootConfigurationAccessor.java index f6e38b3d0a93..f6e038178ef9 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/UIRootConfigurationAccessor.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/UIRootConfigurationAccessor.java @@ -77,14 +77,12 @@ public class UIRootConfigurationAccessor extends RootConfigurationAccessor { @Override @Nullable public String getProjectSdkName(final Project project) { - final String projectJdkName = ProjectRootManager.getInstance(project).getProjectSdkName(); final Sdk projectJdk = getProjectSdk(project); if (projectJdk != null) { return projectJdk.getName(); } - else { - final ProjectSdksModel projectJdksModel = ProjectStructureConfigurable.getInstance(project).getProjectJdksModel(); - return projectJdksModel.findSdk(projectJdkName) == null ? projectJdkName : null; - } + final String projectJdkName = ProjectRootManager.getInstance(project).getProjectSdkName(); + final ProjectSdksModel projectJdksModel = ProjectStructureConfigurable.getInstance(project).getProjectJdksModel(); + return projectJdkName != null && projectJdksModel.findSdk(projectJdkName) == null ? projectJdkName : null; } } diff --git a/java/idea-ui/src/com/intellij/platform/templates/RemoteTemplatesFactory.java b/java/idea-ui/src/com/intellij/platform/templates/RemoteTemplatesFactory.java index 95efcaacb7f4..cf95264bd20b 100644 --- a/java/idea-ui/src/com/intellij/platform/templates/RemoteTemplatesFactory.java +++ b/java/idea-ui/src/com/intellij/platform/templates/RemoteTemplatesFactory.java @@ -17,6 +17,7 @@ import com.intellij.util.NullableFunction; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.util.io.HttpRequests; +import org.intellij.lang.annotations.Language; import org.jdom.Element; import org.jdom.JDOMException; import org.jetbrains.annotations.NotNull; @@ -74,7 +75,7 @@ public class RemoteTemplatesFactory extends ProjectTemplatesFactory { @NotNull @TestOnly - public static MultiMap createFromText(@NotNull String value) throws IOException, JDOMException { + public static MultiMap createFromText(@NotNull @Language("XML") String value) throws IOException, JDOMException { return create(JDOMUtil.load(value)); } diff --git a/java/idea-ui/testSrc/com/intellij/ide/projectWizard/RemoteTemplatesTest.java b/java/idea-ui/testSrc/com/intellij/ide/projectWizard/RemoteTemplatesTest.java index 74d08af7eae8..a7a215254843 100644 --- a/java/idea-ui/testSrc/com/intellij/ide/projectWizard/RemoteTemplatesTest.java +++ b/java/idea-ui/testSrc/com/intellij/ide/projectWizard/RemoteTemplatesTest.java @@ -19,24 +19,25 @@ import com.intellij.util.containers.MultiMap; */ public class RemoteTemplatesTest extends NewProjectWizardTestCase { public void testParsing() throws Exception { - MultiMap map = RemoteTemplatesFactory.createFromText("\n" + - " \n" + - " \n" + - ""); + MultiMap map = RemoteTemplatesFactory.createFromText( + "\n" + + " \n" + + " \n" + + ""); assertEquals(1, map.size()); ProjectTemplate facelets = map.values().iterator().next(); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java b/java/java-analysis-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java index f5d1902c52d1..e407ca42b7e5 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java @@ -65,7 +65,7 @@ public class AnnotateMethodFix implements LocalQuickFix { @Override public boolean startInWriteAction() { - return false; + return !annotateOverriddenMethods(); } @Override diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TrackingDfaMemoryState.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TrackingDfaMemoryState.java index c896c5bfc981..ac9b3667d3c5 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TrackingDfaMemoryState.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TrackingDfaMemoryState.java @@ -7,8 +7,11 @@ import com.intellij.codeInspection.dataFlow.instructions.Instruction; import com.intellij.codeInspection.dataFlow.value.*; import com.intellij.codeInspection.dataFlow.value.DfaRelationValue.RelationType; import com.intellij.openapi.util.Pair; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiExpression; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ObjectUtils; +import com.siyeh.ig.psiutils.ExpressionUtils; import one.util.streamex.EntryStream; import one.util.streamex.StreamEx; import org.jetbrains.annotations.Contract; @@ -244,6 +247,20 @@ public class TrackingDfaMemoryState extends DfaMemoryStateImpl { return findChange(change -> change.getExpression() == expression, false); } + @Contract("null -> null") + @Nullable + MemoryStateChange findSubExpressionPush(@Nullable PsiExpression expression) { + if (expression == null) return null; + PsiElement topElement = ExpressionUtils.getPassThroughParent(expression); + return findChange(change -> { + PsiExpression changeExpression = change.getExpression(); + if (changeExpression == null) return false; + return changeExpression == expression || + (PsiTreeUtil.isAncestor(expression, changeExpression, true) && + ExpressionUtils.getPassThroughParent(changeExpression) == topElement); + }, false); + } + MemoryStateChange findRelation(DfaVariableValue value, @NotNull Predicate relationPredicate, boolean startFromSelf) { return findChange(change -> { Change varChange = change.myChanges.get(value); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TrackingRunner.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TrackingRunner.java index e83126b62b61..127e89f6a22c 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TrackingRunner.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TrackingRunner.java @@ -9,6 +9,7 @@ import com.intellij.codeInspection.dataFlow.instructions.*; import com.intellij.codeInspection.dataFlow.rangeSet.LongRangeSet; import com.intellij.codeInspection.dataFlow.value.*; import com.intellij.codeInspection.dataFlow.value.DfaRelationValue.RelationType; +import com.intellij.lang.ASTNode; import com.intellij.openapi.editor.Document; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Pair; @@ -16,6 +17,8 @@ import com.intellij.openapi.util.Segment; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; +import com.intellij.psi.impl.source.tree.ChildRole; +import com.intellij.psi.impl.source.tree.CompositeElement; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiUtil; import com.intellij.util.ArrayUtil; @@ -24,6 +27,7 @@ import com.intellij.util.containers.ContainerUtil; import com.siyeh.ig.psiutils.BoolUtils; import com.siyeh.ig.psiutils.ExpressionUtils; import one.util.streamex.StreamEx; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -333,9 +337,10 @@ public class TrackingRunner extends StandardDataFlowRunner { Warning caused by narrowing conversion Warning caused by unary minus Warning caused by final field initializer - TODO: 3. Check how it works with + Literal is not-null + TODO: 3. Check how it works with: Inliners (notably: Stream API) - Ternary operators + Boxed numbers TODO: 4. Check for possible performance disasters (likely on some code patterns current algo might blow up) TODO: 5. Problem when interesting state doesn't reach the current condition, need to do something with this */ @@ -370,8 +375,8 @@ public class TrackingRunner extends StandardDataFlowRunner { Instruction instruction = change.myInstruction; if (instruction instanceof AssignInstruction && change.myTopOfStack == value) { PsiExpression rValue = ((AssignInstruction)instruction).getRExpression(); - CauseItem item = new CauseItem("'" + value + "' was assigned", rValue); - MemoryStateChange push = change.findExpressionPush(rValue); + CauseItem item = createAssignmentCause((AssignInstruction)instruction, value); + MemoryStateChange push = change.findSubExpressionPush(rValue); if (push != null) { item.addChildren(findConstantValueCause(rValue, push, expectedValue)); } @@ -385,6 +390,29 @@ public class TrackingRunner extends StandardDataFlowRunner { return new CauseItem[0]; } + @NotNull + @Contract("_, _ -> new") + private static CauseItem createAssignmentCause(AssignInstruction instruction, DfaValue target) { + PsiExpression rExpression = instruction.getRExpression(); + PsiElement anchor = null; + if (rExpression != null) { + PsiElement parent = PsiUtil.skipParenthesizedExprUp(rExpression.getParent()); + if (parent instanceof PsiAssignmentExpression) { + anchor = ((PsiAssignmentExpression)parent).getOperationSign(); + } + else if (parent instanceof PsiVariable) { + ASTNode node = parent.getNode(); + if (node instanceof CompositeElement) { + anchor = ((CompositeElement)node).findChildByRoleAsPsiElement(ChildRole.INITIALIZER_EQ); + } + } + if (anchor == null) { + anchor = rExpression; + } + } + return new CauseItem("'" + target + "' was assigned", anchor); + } + private static CauseItem[] findBooleanResultCauses(PsiExpression expression, MemoryStateChange history, boolean value) { @@ -578,17 +606,17 @@ public class TrackingRunner extends StandardDataFlowRunner { } if (instruction instanceof AssignInstruction) { DfaValue target = change.myTopOfStack; - PsiExpression rValue = PsiUtil.skipParenthesizedExprDown(((AssignInstruction)instruction).getRExpression()); + PsiExpression rValue = ((AssignInstruction)instruction).getRExpression(); + CauseItem item = createAssignmentCause((AssignInstruction)instruction, target); if (target == value) { - CauseItem item = new CauseItem("'" + target + "' was assigned", rValue); - MemoryStateChange rValuePush = change.findExpressionPush(rValue); + MemoryStateChange rValuePush = change.findSubExpressionPush(rValue); if (rValuePush != null) { item.addChildren(findRelationCause(relation.myRelationType, rValuePush, counterPartChange)); } return item; } if (target == relation.myCounterpart) { - return new CauseItem("'" + target + "' was assigned", rValue); + return item; } } PsiExpression expression = change.getExpression(); @@ -617,14 +645,11 @@ public class TrackingRunner extends StandardDataFlowRunner { if (factDef != null && expression != null) { DfaValue value = factUse.myTopOfStack; if (factDef.myInstruction instanceof AssignInstruction && factDef.myTopOfStack == value) { - PsiExpression rExpression = PsiUtil.skipParenthesizedExprDown(((AssignInstruction)factDef.myInstruction).getRExpression()); - while (rExpression instanceof PsiTypeCastExpression) { - rExpression = PsiUtil.skipParenthesizedExprDown(((PsiTypeCastExpression)rExpression).getOperand()); - } + PsiExpression rExpression = ((AssignInstruction)factDef.myInstruction).getRExpression(); if (rExpression != null) { - MemoryStateChange rValuePush = factDef.findExpressionPush(rExpression); + MemoryStateChange rValuePush = factDef.findSubExpressionPush(rExpression); if (rValuePush != null) { - CauseItem assignmentItem = new CauseItem("'" + value + "' was assigned", rExpression); + CauseItem assignmentItem = createAssignmentCause((AssignInstruction)factDef.myInstruction, value); Pair rValueFact = rValuePush.findFact(rValuePush.myTopOfStack, DfaFactType.NULLABILITY); assignmentItem.addChildren(findNullabilityCause(rValuePush, rValueFact.first, nullability)); return assignmentItem; @@ -636,6 +661,12 @@ public class TrackingRunner extends StandardDataFlowRunner { return new CauseItem("'" + expression.getText() + "' is known to be '" + nullability.getPresentationName() + "' from #ref", defExpression); } } + if (expression instanceof PsiTypeCastExpression) { + MemoryStateChange operandPush = factUse.findSubExpressionPush(((PsiTypeCastExpression)expression).getOperand()); + if (operandPush != null) { + return findNullabilityCause(operandPush, factDef, nullability); + } + } if (expression instanceof PsiMethodCallExpression) { PsiMethodCallExpression call = (PsiMethodCallExpression)expression; PsiMethod method = call.resolveMethod(); @@ -791,11 +822,11 @@ public class TrackingRunner extends StandardDataFlowRunner { CauseItem item = new CauseItem(String.format(template, rangeText), factUse); if (factDef != null) { if (factDef.myInstruction instanceof AssignInstruction && factDef.myTopOfStack == value) { - PsiExpression rExpression = PsiUtil.skipParenthesizedExprDown(((AssignInstruction)factDef.myInstruction).getRExpression()); + PsiExpression rExpression = ((AssignInstruction)factDef.myInstruction).getRExpression(); if (rExpression != null) { - MemoryStateChange rValuePush = factDef.findExpressionPush(rExpression); + MemoryStateChange rValuePush = factDef.findSubExpressionPush(rExpression); if (rValuePush != null) { - CauseItem assignmentItem = new CauseItem("'" + value + "' was assigned", rExpression); + CauseItem assignmentItem = createAssignmentCause((AssignInstruction)factDef.myInstruction, value); Pair rValueFact = rValuePush.findFact(rValuePush.myTopOfStack, DfaFactType.RANGE); assignmentItem.addChildren(findRangeCause(rValuePush, rValueFact.first, range, "Value is %s")); item.addChildren(assignmentItem); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java index f8c6df99fa65..e4245aedb290 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java @@ -550,21 +550,19 @@ public class RefJavaManagerImpl extends RefJavaManager { //TODO support suppressions by comment tag in kotlin private void processComments(@NotNull UElement node) { for (UComment comment : node.getComments()) { - if (comment instanceof UComment) { - PsiElement psi = comment.getSourcePsi(); - if (psi instanceof PsiDocComment) { - final PsiDocTag[] tags = ((PsiDocComment)psi).getTags(); - for (PsiDocTag tag : tags) { - if (Comparing.strEqual(tag.getName(), SuppressionUtilCore.SUPPRESS_INSPECTIONS_TAG_NAME)) { - final PsiElement[] dataElements = tag.getDataElements(); - if (dataElements.length > 0) { - final PsiModifierListOwner listOwner = PsiTreeUtil.getParentOfType(psi, PsiModifierListOwner.class); - if (listOwner != null) { - final WritableRefElement element = (WritableRefElement)myRefManager.getReference(listOwner); - if (element != null) { - String suppression = StringUtil.join(dataElements, PsiElement::getText, ","); - element.addSuppression(suppression); - } + PsiElement psi = comment.getSourcePsi(); + if (psi instanceof PsiDocComment) { + final PsiDocTag[] tags = ((PsiDocComment)psi).getTags(); + for (PsiDocTag tag : tags) { + if (Comparing.strEqual(tag.getName(), SuppressionUtilCore.SUPPRESS_INSPECTIONS_TAG_NAME)) { + final PsiElement[] dataElements = tag.getDataElements(); + if (dataElements.length > 0) { + final PsiModifierListOwner listOwner = PsiTreeUtil.getParentOfType(psi, PsiModifierListOwner.class); + if (listOwner != null) { + final WritableRefElement element = (WritableRefElement)myRefManager.getReference(listOwner); + if (element != null) { + String suppression = StringUtil.join(dataElements, PsiElement::getText, ","); + element.addSuppression(suppression); } } } diff --git a/java/java-impl/src/com/intellij/codeInsight/NullableNotNullManagerImpl.java b/java/java-impl/src/com/intellij/codeInsight/NullableNotNullManagerImpl.java index 0096c12ebe6e..807c25dc7ea8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/NullableNotNullManagerImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/NullableNotNullManagerImpl.java @@ -240,8 +240,10 @@ public class NullableNotNullManagerImpl extends NullableNotNullManager implement if (container instanceof PsiPackage) { PsiFile file = annotation.getContainingFile(); ProjectFileIndex index = ProjectRootManager.getInstance(file.getProject()).getFileIndex(); - VirtualFile annotationRoot = index.getClassRootForFile(file.getVirtualFile()); - VirtualFile ownerRoot = index.getClassRootForFile(owner.getContainingFile().getVirtualFile()); + VirtualFile annotationFile = file.getVirtualFile(); + VirtualFile annotationRoot = annotationFile == null ? null : index.getClassRootForFile(annotationFile); + VirtualFile ownerFile = owner.getContainingFile().getVirtualFile(); + VirtualFile ownerRoot = ownerFile == null ? null : index.getClassRootForFile(ownerFile); if (ownerRoot != null && !ownerRoot.equals(annotationRoot)) { continue; } diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/fix/FindDfaProblemCauseFix.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/fix/FindDfaProblemCauseFix.java index 332648d6cb94..c8a185c6e684 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/fix/FindDfaProblemCauseFix.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/fix/FindDfaProblemCauseFix.java @@ -147,7 +147,7 @@ public class FindDfaProblemCauseFix implements LocalQuickFix, LowPriorityAction highlighter.getAndSet(null).dropHighlight(); } }) - .setItemChosenCallback(cause -> ReadAction.run(() -> navigate(editor, file, cause.myCauseItem))) + .setItemChosenCallback(cause -> navigate(editor, file, cause.myCauseItem)) .createPopup(); popup.showInBestPositionFor(editor); } diff --git a/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java b/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java index 937a159d39df..d0e29c8b26ae 100644 --- a/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java +++ b/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java @@ -20,7 +20,6 @@ import com.intellij.lang.java.JavaLanguage; import com.intellij.navigation.ChooseByNameContributorEx; import com.intellij.navigation.GotoClassContributor; import com.intellij.navigation.NavigationItem; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiFile; @@ -30,41 +29,15 @@ import com.intellij.psi.presentation.java.SymbolPresentationUtil; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiShortNamesCache; import com.intellij.psi.util.ClassUtil; -import com.intellij.util.ArrayUtil; import com.intellij.util.Processor; -import com.intellij.util.Processors; import com.intellij.util.indexing.FindSymbolParameters; import com.intellij.util.indexing.IdFilter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; import java.util.regex.Matcher; public class DefaultClassNavigationContributor implements ChooseByNameContributorEx, GotoClassContributor { - @Override - @NotNull - public String[] getNames(Project project, boolean includeNonProjectItems) { - GlobalSearchScope scope = includeNonProjectItems ? GlobalSearchScope.allScope(project) : GlobalSearchScope.projectScope(project); - List result = new ArrayList<>(); - Processor processor = Processors.cancelableCollectProcessor(result); - - processNames(processor, scope, IdFilter.getProjectIdFilter(project, includeNonProjectItems)); - - return ArrayUtil.toStringArray(result); - } - - @Override - @NotNull - public NavigationItem[] getItemsByName(String name, final String pattern, Project project, boolean includeNonProjectItems) { - List result = new ArrayList<>(); - Processor processor = Processors.cancelableCollectProcessor(result); - processElementsWithName(name, processor, FindSymbolParameters.wrap(pattern, project, includeNonProjectItems)); - - return result.isEmpty() ? NavigationItem.EMPTY_NAVIGATION_ITEM_ARRAY : - result.toArray(NavigationItem.EMPTY_NAVIGATION_ITEM_ARRAY); - } @Override public String getQualifiedName(final NavigationItem item) { diff --git a/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultSymbolNavigationContributor.java b/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultSymbolNavigationContributor.java index bba5b597d4b5..e302d7363ed6 100644 --- a/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultSymbolNavigationContributor.java +++ b/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultSymbolNavigationContributor.java @@ -30,51 +30,13 @@ import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.Comparator; +import java.util.Iterator; +import java.util.Set; public class DefaultSymbolNavigationContributor implements ChooseByNameContributorEx, GotoClassContributor { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.gotoByName.DefaultSymbolNavigationContributor"); - @Override - @NotNull - public String[] getNames(Project project, boolean includeNonProjectItems) { - PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project); - Set set = new HashSet<>(); - Collections.addAll(set, cache.getAllMethodNames()); - Collections.addAll(set, cache.getAllFieldNames()); - Collections.addAll(set, cache.getAllClassNames()); - return ArrayUtil.toStringArray(set); - } - - @Override - @NotNull - public NavigationItem[] getItemsByName(String name, final String pattern, Project project, boolean includeNonProjectItems) { - GlobalSearchScope scope = includeNonProjectItems ? GlobalSearchScope.allScope(project) : GlobalSearchScope.projectScope(project); - PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project); - - Condition qualifiedMatcher = getQualifiedNameMatcher(pattern); - - List result = new ArrayList<>(); - for (PsiMethod method : cache.getMethodsByName(name, scope)) { - if (!method.isConstructor() && isOpenable(method) && !hasSuperMethod(method, scope, qualifiedMatcher, pattern)) { - result.add(method); - } - } - for (PsiField field : cache.getFieldsByName(name, scope)) { - if (isOpenable(field)) { - result.add(field); - } - } - for (PsiClass aClass : cache.getClassesByName(name, scope)) { - if (isOpenable(aClass)) { - result.add(aClass); - } - } - PsiMember[] array = result.toArray(PsiMember.EMPTY_ARRAY); - Arrays.sort(array, MyComparator.INSTANCE); - return array; - } - @Nullable @Override public String getQualifiedName(NavigationItem item) { diff --git a/java/java-impl/src/com/intellij/lang/java/actions/RangeExpression.kt b/java/java-impl/src/com/intellij/lang/java/actions/RangeExpression.kt index 996b598b53c7..89e4119bd8b2 100644 --- a/java/java-impl/src/com/intellij/lang/java/actions/RangeExpression.kt +++ b/java/java-impl/src/com/intellij/lang/java/actions/RangeExpression.kt @@ -29,7 +29,5 @@ internal class RangeExpression( override fun calculateQuickResult(context: ExpressionContext): Result? = calculateResult(context) - override fun requiresCommittedPSI(): Boolean = false - override fun calculateLookupItems(context: ExpressionContext): Array = LookupElement.EMPTY_ARRAY } diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/AndChainCause.java b/java/java-tests/testData/inspection/dataFlow/tracker/AndChainCause.java index 049802081148..3d069abcaf51 100644 --- a/java/java-tests/testData/inspection/dataFlow/tracker/AndChainCause.java +++ b/java/java-tests/testData/inspection/dataFlow/tracker/AndChainCause.java @@ -2,7 +2,7 @@ Value is always false (x > 6 && y > 10) Operand #1 of &&-chain is false (x > 6) Left operand is 5 (x) - 'x' was assigned (5) + 'x' was assigned (=) */ class Test { diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/AssignTernaryNotNull.java b/java/java-tests/testData/inspection/dataFlow/tracker/AssignTernaryNotNull.java new file mode 100644 index 000000000000..c1714d2564cc --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/tracker/AssignTernaryNotNull.java @@ -0,0 +1,19 @@ +/* +Value is always false (foo == null) + 'foo' was assigned (=) + One of the following happens: + Expression cannot be null as it's newly created object (new String("foo")) + or expression cannot be null as it's newly created object (new String("bar")) + */ + +import org.jetbrains.annotations.Nullable; + +class Test { + + void test(boolean b) { + String foo = b ? new String("foo") : new String("bar"); + if (foo == null) { + + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/AssignTernaryNumeric.java b/java/java-tests/testData/inspection/dataFlow/tracker/AssignTernaryNumeric.java new file mode 100644 index 000000000000..70f6d8cb7c0c --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/tracker/AssignTernaryNumeric.java @@ -0,0 +1,20 @@ +/* +Value is always false (foo > 3) + One of the following happens: + Left operand is 1 (foo) + 'foo' was assigned (=) + or left operand is 2 (foo) + 'foo' was assigned (=) + */ + +import org.jetbrains.annotations.Nullable; + +class Test { + + void test(boolean b) { + int foo = b ? 1 : 2; + if (foo > 3) { + + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/AssignTrue.java b/java/java-tests/testData/inspection/dataFlow/tracker/AssignTrue.java index aeda8421d734..66e86679428a 100644 --- a/java/java-tests/testData/inspection/dataFlow/tracker/AssignTrue.java +++ b/java/java-tests/testData/inspection/dataFlow/tracker/AssignTrue.java @@ -1,6 +1,6 @@ /* Value is always true (b) - 'b' was assigned (true) + 'b' was assigned (=) */ class Test { diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/AssignmentChain.java b/java/java-tests/testData/inspection/dataFlow/tracker/AssignmentChain.java index c0e285d885f5..10f926616c2c 100644 --- a/java/java-tests/testData/inspection/dataFlow/tracker/AssignmentChain.java +++ b/java/java-tests/testData/inspection/dataFlow/tracker/AssignmentChain.java @@ -1,6 +1,6 @@ /* Value is always false (s == null) - 's' was assigned (s1) + 's' was assigned (=) Condition 's1 != null' was checked before (s1 == null) */ class Test { diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/BooleanReassignedMultipleTimes.java b/java/java-tests/testData/inspection/dataFlow/tracker/BooleanReassignedMultipleTimes.java index d8c52295a223..2e1873057cc1 100644 --- a/java/java-tests/testData/inspection/dataFlow/tracker/BooleanReassignedMultipleTimes.java +++ b/java/java-tests/testData/inspection/dataFlow/tracker/BooleanReassignedMultipleTimes.java @@ -1,9 +1,9 @@ /* Value is always false (b4) - 'b4' was assigned (b3) - 'b3' was assigned (b2) - 'b2' was assigned (b1) - 'b1' was assigned (b) + 'b4' was assigned (=) + 'b3' was assigned (=) + 'b2' was assigned (=) + 'b1' was assigned (=) 'b == false' was established from condition (b) */ import org.jetbrains.annotations.NotNull; diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/IfBothNotNull.java b/java/java-tests/testData/inspection/dataFlow/tracker/IfBothNotNull.java index 5c50466df0ae..d98c29b51121 100644 --- a/java/java-tests/testData/inspection/dataFlow/tracker/IfBothNotNull.java +++ b/java/java-tests/testData/inspection/dataFlow/tracker/IfBothNotNull.java @@ -1,9 +1,9 @@ /* Value is always false (x == null) One of the following happens: - 'x' was assigned (new Object()) + 'x' was assigned (=) Expression cannot be null as it's newly created object (new Object()) - or 'x' was assigned ("foo") + or 'x' was assigned (=) Expression cannot be null as it's literal ("foo") */ diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/IfBothNotNullReassign.java b/java/java-tests/testData/inspection/dataFlow/tracker/IfBothNotNullReassign.java index 4ec0164c1e60..a8600713f5be 100644 --- a/java/java-tests/testData/inspection/dataFlow/tracker/IfBothNotNullReassign.java +++ b/java/java-tests/testData/inspection/dataFlow/tracker/IfBothNotNullReassign.java @@ -1,10 +1,10 @@ /* Value is always false (y == null) - 'y' was assigned (x) + 'y' was assigned (=) One of the following happens: - 'x' was assigned (new Object()) + 'x' was assigned (=) Expression cannot be null as it's newly created object (new Object()) - or 'x' was assigned ("foo") + or 'x' was assigned (=) Expression cannot be null as it's literal ("foo") */ diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/IndexOfPlusOne.java b/java/java-tests/testData/inspection/dataFlow/tracker/IndexOfPlusOne.java index 723134684363..cf76c452591e 100644 --- a/java/java-tests/testData/inspection/dataFlow/tracker/IndexOfPlusOne.java +++ b/java/java-tests/testData/inspection/dataFlow/tracker/IndexOfPlusOne.java @@ -1,10 +1,10 @@ /* Value is always true (j >= 0) Left operand is >= 0 (j) - 'j' was assigned (i + 1) + 'j' was assigned (=) Result of '+' is >= 0 (i + 1) Left operand is in {-1..Integer.MAX_VALUE-1} (i) - 'i' was assigned (s.indexOf(' ')) + 'i' was assigned (=) Value is in {-1..Integer.MAX_VALUE-1} (s.indexOf(' ')) */ diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/NotNullAnnotated.java b/java/java-tests/testData/inspection/dataFlow/tracker/NotNullAnnotated.java index 3068cea4665e..fd9dc371bc76 100644 --- a/java/java-tests/testData/inspection/dataFlow/tracker/NotNullAnnotated.java +++ b/java/java-tests/testData/inspection/dataFlow/tracker/NotNullAnnotated.java @@ -1,6 +1,6 @@ /* Value is always false (s1 == null) - 's1' was assigned (s.trim()) + 's1' was assigned (=) Method 'trim' is externally annotated as 'non-null' (trim) */ class Test { diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/NotNullAssignmentInside.java b/java/java-tests/testData/inspection/dataFlow/tracker/NotNullAssignmentInside.java index dfd2f8826c6f..33911032b225 100644 --- a/java/java-tests/testData/inspection/dataFlow/tracker/NotNullAssignmentInside.java +++ b/java/java-tests/testData/inspection/dataFlow/tracker/NotNullAssignmentInside.java @@ -1,6 +1,6 @@ /* Value is always true ((s = new Object()) != null) - 's' was assigned (new Object()) + 's' was assigned (=) Expression cannot be null as it's newly created object (new Object()) */ diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/NotNullObvious.java b/java/java-tests/testData/inspection/dataFlow/tracker/NotNullObvious.java index f04337b8c62b..0d91a307f444 100644 --- a/java/java-tests/testData/inspection/dataFlow/tracker/NotNullObvious.java +++ b/java/java-tests/testData/inspection/dataFlow/tracker/NotNullObvious.java @@ -1,6 +1,6 @@ /* Value is always true (s != null) - 's' was assigned (new Object()) + 's' was assigned (=) Expression cannot be null as it's newly created object (new Object()) */ diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/NotNullParameterAssigned.java b/java/java-tests/testData/inspection/dataFlow/tracker/NotNullParameterAssigned.java index 93672617a45c..2bf593da57fc 100644 --- a/java/java-tests/testData/inspection/dataFlow/tracker/NotNullParameterAssigned.java +++ b/java/java-tests/testData/inspection/dataFlow/tracker/NotNullParameterAssigned.java @@ -1,6 +1,6 @@ /* Value is always true (null == s) - 's' was assigned (null) + 's' was assigned (=) */ import org.jetbrains.annotations.NotNull; diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/NpeAnnotation.java b/java/java-tests/testData/inspection/dataFlow/tracker/NpeAnnotation.java index 959ae680bb56..8c3b99bf7971 100644 --- a/java/java-tests/testData/inspection/dataFlow/tracker/NpeAnnotation.java +++ b/java/java-tests/testData/inspection/dataFlow/tracker/NpeAnnotation.java @@ -1,6 +1,6 @@ /* May be null (s) - 's' was assigned (loadString()) + 's' was assigned (=) Method 'loadString' is annotated as 'nullable' (@Nullable) */ diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/NpeWithCast.java b/java/java-tests/testData/inspection/dataFlow/tracker/NpeWithCast.java index 0b29d755e77b..bcbea75779a7 100644 --- a/java/java-tests/testData/inspection/dataFlow/tracker/NpeWithCast.java +++ b/java/java-tests/testData/inspection/dataFlow/tracker/NpeWithCast.java @@ -1,6 +1,6 @@ /* May be null (foo) - 'foo' was assigned (getFoo()) + 'foo' was assigned (=) Method 'getFoo' is annotated as 'nullable' (@Nullable) */ diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/NullWasCheckedNullAssigned.java b/java/java-tests/testData/inspection/dataFlow/tracker/NullWasCheckedNullAssigned.java index 591e81dca8be..85422b9cf437 100644 --- a/java/java-tests/testData/inspection/dataFlow/tracker/NullWasCheckedNullAssigned.java +++ b/java/java-tests/testData/inspection/dataFlow/tracker/NullWasCheckedNullAssigned.java @@ -1,6 +1,6 @@ /* Value is always false (s == s1) - 's1' was assigned (null) + 's1' was assigned (=) and condition 's != null' was checked before (null == s) */ class Test { diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/OrChainCause.java b/java/java-tests/testData/inspection/dataFlow/tracker/OrChainCause.java index f69840cc093c..593ef0c5b6a8 100644 --- a/java/java-tests/testData/inspection/dataFlow/tracker/OrChainCause.java +++ b/java/java-tests/testData/inspection/dataFlow/tracker/OrChainCause.java @@ -6,14 +6,14 @@ Value is always true (x || (a+b)+(c+d)==10) Result of '+' is 10 ((a+b)+(c+d)) Result of '+' is 3 (a+b) Left operand is 1 (a) - 'a' was assigned (1) + 'a' was assigned (=) and right operand is 2 (b) - 'b' was assigned (2) + 'b' was assigned (=) and result of '+' is 7 (c+d) Left operand is 3 (c) - 'c' was assigned (3) + 'c' was assigned (=) and right operand is 4 (d) - 'd' was assigned (4) + 'd' was assigned (=) */ class Test { diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTrackerTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTrackerTest.java index e6a5170a1421..ecd2335e9557 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTrackerTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTrackerTest.java @@ -149,4 +149,6 @@ public class DataFlowInspectionTrackerTest extends LightCodeInsightFixtureTestCa public void testNpeSimple() { doTest(); } public void testNpeAnnotation() { doTest(); } public void testNpeWithCast() { doTest(); } + public void testAssignTernaryNotNull() { doTest(); } + public void testAssignTernaryNumeric() { doTest(); } } diff --git a/java/java-tests/testSrc/com/intellij/openapi/command/undo/EditorTypingAndNavigationUndoTest.java b/java/java-tests/testSrc/com/intellij/openapi/command/undo/EditorTypingAndNavigationUndoTest.java index 2a5767fb341b..6aad98050964 100644 --- a/java/java-tests/testSrc/com/intellij/openapi/command/undo/EditorTypingAndNavigationUndoTest.java +++ b/java/java-tests/testSrc/com/intellij/openapi/command/undo/EditorTypingAndNavigationUndoTest.java @@ -287,7 +287,7 @@ public class EditorTypingAndNavigationUndoTest extends EditorUndoTestCase { Ref message = new Ref<>(); Messages.setTestDialog(new TestDialog() { @Override - public int show(String m) { + public int show(@NotNull String m) { message.set(m); return Messages.YES; } diff --git a/java/java-tests/testSrc/com/intellij/openapi/command/undo/GlobalUndoTest.java b/java/java-tests/testSrc/com/intellij/openapi/command/undo/GlobalUndoTest.java index 3683c8ff0553..f59aa28e0520 100644 --- a/java/java-tests/testSrc/com/intellij/openapi/command/undo/GlobalUndoTest.java +++ b/java/java-tests/testSrc/com/intellij/openapi/command/undo/GlobalUndoTest.java @@ -78,7 +78,7 @@ public class GlobalUndoTest extends UndoTestCase implements TestDialog { } @Override - public int show(String message) { + public int show(@NotNull String message) { myConfirmationWasRequested = true; return 0; } diff --git a/java/testFramework/src/com/intellij/ide/projectWizard/ProjectWizardTestCase.java b/java/testFramework/src/com/intellij/ide/projectWizard/ProjectWizardTestCase.java index 75980c93b05f..08584124d808 100644 --- a/java/testFramework/src/com/intellij/ide/projectWizard/ProjectWizardTestCase.java +++ b/java/testFramework/src/com/intellij/ide/projectWizard/ProjectWizardTestCase.java @@ -127,18 +127,18 @@ public abstract class ProjectWizardTestCase ext return createModuleFromWizard(project); } - protected Module createModuleFromWizard(@NotNull Project project) { + private Module createModuleFromWizard(@NotNull Project project) { return new NewModuleAction().createModuleFromWizard(project, null, myWizard); } - protected void runWizard(@NotNull String group, - @Nullable final String name, - @Nullable Project project, - @Nullable final Consumer adjuster) throws IOException { + private void runWizard(@NotNull String group, + @Nullable final String name, + @Nullable Project project, + @Nullable final Consumer adjuster) throws IOException { createWizard(project); ProjectTypeStep step = (ProjectTypeStep)myWizard.getCurrentStepObject(); if (!step.setSelectedTemplate(group, name)) { - throw new IllegalArgumentException(group + '/' + name + " template not found, available groups " + step.availableTemplateGroupsToString()); + throw new IllegalArgumentException(group + '/' + name + " template not found. Available groups: " + step.availableTemplateGroupsToString()); } runWizard(step1 -> { @@ -151,7 +151,7 @@ public abstract class ProjectWizardTestCase ext }); } - protected void runWizard(@Nullable Consumer adjuster) { + private void runWizard(@Nullable Consumer adjuster) { while (true) { ModuleWizardStep currentStep = myWizard.getCurrentStepObject(); if (adjuster != null) { @@ -236,7 +236,7 @@ public abstract class ProjectWizardTestCase ext return ContainerUtil.getFirstItem(ImportModuleAction.createFromWizard(project, myWizard)); } - private static T computeInWriteSafeContext(Supplier supplier) { + private static T computeInWriteSafeContext(Supplier supplier) { Ref module = Ref.create(); ApplicationManager.getApplication().invokeLater(() -> module.set(supplier.get())); UIUtil.dispatchAllInvocationEvents(); diff --git a/jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdkReference.java b/jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdkReference.java index 390fbdd6ca8d..e7342c43c6c3 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdkReference.java +++ b/jps/model-api/src/org/jetbrains/jps/model/library/sdk/JpsSdkReference.java @@ -15,6 +15,7 @@ */ package org.jetbrains.jps.model.library.sdk; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.model.JpsElement; import org.jetbrains.jps.model.JpsElementReference; import org.jetbrains.jps.model.library.JpsTypedLibrary; @@ -23,5 +24,6 @@ import org.jetbrains.jps.model.library.JpsTypedLibrary; * @author nik */ public interface JpsSdkReference

extends JpsElementReference>> { + @NotNull String getSdkName(); } diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceBase.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceBase.java index 3822a0d9128b..9a5e9207ef94 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceBase.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceBase.java @@ -30,6 +30,7 @@ public abstract class JpsNamedElementReferenceBase implements JpsElementReference { private static final JpsElementChildRole> PARENT_REFERENCE_ROLE = JpsElementChildRoleBase .create("parent"); + @NotNull protected final String myElementName; protected JpsNamedElementReferenceBase(@NotNull String elementName, @NotNull JpsElementReference parentReference) { diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsWrappedJavaSdkReferenceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsWrappedJavaSdkReferenceImpl.java index fdc678f7b820..a9fcd9c57aa6 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsWrappedJavaSdkReferenceImpl.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsWrappedJavaSdkReferenceImpl.java @@ -53,6 +53,7 @@ public class JpsWrappedJavaSdkReferenceImpl extends JpsCompositeElementBase> sdk = resolve(); diff --git a/jvm/jvm-analysis-api/src/com/intellij/codeInspection/NlsCapitalizationUtil.java b/jvm/jvm-analysis-api/src/com/intellij/codeInspection/NlsCapitalizationUtil.java new file mode 100644 index 000000000000..187512fa000b --- /dev/null +++ b/jvm/jvm-analysis-api/src/com/intellij/codeInspection/NlsCapitalizationUtil.java @@ -0,0 +1,51 @@ +// Copyright 2000-2019 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.codeInspection; + +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class NlsCapitalizationUtil { + + public static boolean isCapitalizationSatisfied(String value, Nls.Capitalization capitalization) { + if (StringUtil.isEmpty(value) || capitalization == Nls.Capitalization.NotSpecified) { + return true; + } + value = value.replace("&", ""); + return capitalization == Nls.Capitalization.Title + ? StringUtil.wordsToBeginFromUpperCase(value).equals(value) + : checkSentenceCapitalization(value); + } + + private static boolean checkSentenceCapitalization(@NotNull String value) { + List words = StringUtil.split(value, " "); + if (words.size() == 0) return true; + if (Character.isLetter(words.get(0).charAt(0)) && !isCapitalizedWord(words.get(0))) return false; + if (words.size() == 1) return true; + int capitalized = 1; + for (int i = 1, size = words.size(); i < size; i++) { + String word = words.get(i); + if (isCapitalizedWord(word)) { + // check for abbreviations like SQL or I18n + if (word.length() == 1 || !Character.isLowerCase(word.charAt(1))) { + continue; + } + capitalized++; + } + } + return capitalized / words.size() < 0.2; // allow reasonable amount of capitalized words + } + + private static boolean isCapitalizedWord(String word) { + return word.length() > 0 && Character.isLetter(word.charAt(0)) && Character.isUpperCase(word.charAt(0)); + } + + @NotNull + public static String fixValue(String string, Nls.Capitalization capitalization) { + return capitalization == Nls.Capitalization.Title + ? StringUtil.wordsToBeginFromUpperCase(string) + : StringUtil.capitalize(StringUtil.wordsToBeginFromLowerCase(string)); + } +} diff --git a/jvm/jvm-analysis-java-tests/testSrc/com/intellij/codeInspection/NlsCapitalizationUtilTest.java b/jvm/jvm-analysis-java-tests/testSrc/com/intellij/codeInspection/NlsCapitalizationUtilTest.java new file mode 100644 index 000000000000..2856e77576c5 --- /dev/null +++ b/jvm/jvm-analysis-java-tests/testSrc/com/intellij/codeInspection/NlsCapitalizationUtilTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2019 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.codeInspection; + +import junit.framework.TestCase; +import org.jetbrains.annotations.Nls; + +import static com.intellij.codeInspection.NlsCapitalizationUtil.isCapitalizationSatisfied; + +public class NlsCapitalizationUtilTest extends TestCase { + + public void testCapitalization() { + assertTrue(isCapitalizationSatisfied("Fix SQL issues", Nls.Capitalization.Sentence)); + assertTrue(isCapitalizationSatisfied("Fix I18n issues", Nls.Capitalization.Sentence)); + assertTrue(isCapitalizationSatisfied("Fix C issues", Nls.Capitalization.Sentence)); + assertTrue(isCapitalizationSatisfied("@charset is invalid", Nls.Capitalization.Sentence)); + assertTrue(isCapitalizationSatisfied("Add 'this' qualifier", Nls.Capitalization.Sentence)); + assertTrue(isCapitalizationSatisfied("Add 'this' qualifier", Nls.Capitalization.Sentence)); + assertTrue(isCapitalizationSatisfied("Please select the configuration file (usually named IntelliLang.xml) to import.", + Nls.Capitalization.Sentence)); + assertFalse(isCapitalizationSatisfied("Foo Bar", Nls.Capitalization.Sentence)); + assertTrue(isCapitalizationSatisfied("Foo", Nls.Capitalization.Sentence)); + } +} \ No newline at end of file diff --git a/platform/build-scripts/icons/intellij.platform.images.build.iml b/platform/build-scripts/icons/intellij.platform.images.build.iml index ad4ea565c164..e230818c12e7 100644 --- a/platform/build-scripts/icons/intellij.platform.images.build.iml +++ b/platform/build-scripts/icons/intellij.platform.images.build.iml @@ -10,12 +10,12 @@ - + \ No newline at end of file diff --git a/platform/built-in-server/src/org/jetbrains/ide/OpenFileHttpService.kt b/platform/built-in-server/src/org/jetbrains/ide/OpenFileHttpService.kt index 14b92be3c6ae..2630963c3bdf 100644 --- a/platform/built-in-server/src/org/jetbrains/ide/OpenFileHttpService.kt +++ b/platform/built-in-server/src/org/jetbrains/ide/OpenFileHttpService.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2018 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. +// Copyright 2000-2019 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.ide import com.intellij.ide.impl.ProjectUtil.focusProjectWindow @@ -72,7 +72,7 @@ internal class OpenFileHttpService : RestService() { val apiRequest: OpenFileRequest if (request.method() === HttpMethod.POST) { - apiRequest = gson.value.fromJson(createJsonReader(request), OpenFileRequest::class.java) + apiRequest = gson.fromJson(createJsonReader(request), OpenFileRequest::class.java) } else { apiRequest = OpenFileRequest() @@ -82,7 +82,7 @@ internal class OpenFileHttpService : RestService() { apiRequest.focused = getBooleanParameter("focused", urlDecoder, true) } - val prefixLength = 1 + PREFIX.length + 1 + serviceName.length + 1 + val prefixLength = 1 + PREFIX.length + 1 + getServiceName().length + 1 val path = urlDecoder.path() if (path.length > prefixLength) { val matcher = LINE_AND_COLUMN.matcher(path).region(prefixLength, path.length) diff --git a/platform/built-in-server/src/org/jetbrains/ide/RestService.java b/platform/built-in-server/src/org/jetbrains/ide/RestService.java deleted file mode 100644 index f2fe5613f4d5..000000000000 --- a/platform/built-in-server/src/org/jetbrains/ide/RestService.java +++ /dev/null @@ -1,309 +0,0 @@ -// Copyright 2000-2019 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.ide; - -import com.google.common.base.Supplier; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; -import com.google.gson.stream.MalformedJsonException; -import com.intellij.ide.IdeBundle; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; -import com.intellij.openapi.util.NotNullLazyValue; -import com.intellij.openapi.util.Ref; -import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream; -import com.intellij.openapi.util.registry.Registry; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.util.text.StringUtilRt; -import com.intellij.openapi.wm.IdeFocusManager; -import com.intellij.openapi.wm.IdeFrame; -import com.intellij.ui.AppIcon; -import com.intellij.util.ExceptionUtil; -import com.intellij.util.ObjectUtils; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.io.NettyKt; -import com.intellij.util.net.NetUtils; -import io.netty.buffer.ByteBufInputStream; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.*; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.builtInWebServer.BuiltInWebServerKt; -import org.jetbrains.io.Responses; - -import javax.swing.*; -import java.awt.*; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.lang.reflect.InvocationTargetException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static com.intellij.ide.impl.ProjectUtil.showYesNoDialog; - -/** - * Document your service using apiDoc. To extract big example from source code, consider to use *.coffee file near your source file. - * (or Python/Ruby, but coffee recommended because it's plugin is lightweight). See {@link AboutHttpService} for example. - * - * Don't create JsonReader/JsonWriter directly, use only provided {@link #createJsonReader}, {@link #createJsonWriter} methods (to ensure that you handle in/out according to REST API guidelines). - * - * @see Best Practices for Designing a Pragmatic RESTful API. - */ -public abstract class RestService extends HttpRequestHandler { - protected static final Logger LOG = Logger.getInstance(RestService.class); - public static final String PREFIX = "api"; - - protected final NotNullLazyValue gson = new NotNullLazyValue() { - @NotNull - @Override - protected Gson compute() { - return new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); - } - }; - - private final LoadingCache abuseCounter = - CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(CacheLoader.from((Supplier)AtomicInteger::new)); - - private final Cache trustedOrigins = - CacheBuilder.newBuilder().maximumSize(1024).expireAfterWrite(1, TimeUnit.DAYS).build(); - - @Override - public final boolean isSupported(@NotNull FullHttpRequest request) { - if (!isMethodSupported(request.method())) { - return false; - } - - String uri = request.uri(); - - if (isPrefixlessAllowed() && checkPrefix(uri, getServiceName())) { - return true; - } - - String serviceName = getServiceName(); - int minLength = 1 + PREFIX.length() + 1 + serviceName.length(); - if (uri.length() >= minLength && - uri.charAt(0) == '/' && - uri.regionMatches(true, 1, PREFIX, 0, PREFIX.length()) && - uri.regionMatches(true, 2 + PREFIX.length(), serviceName, 0, serviceName.length())) { - if (uri.length() == minLength) { - return true; - } - else { - char c = uri.charAt(minLength); - return c == '/' || c == '?'; - } - } - return false; - } - - /** - * Service url must be "/api/$serviceName", but to preserve backward compatibility, prefixless path could be also supported - */ - protected boolean isPrefixlessAllowed() { - return false; - } - - /** - * Use human-readable name or UUID if it is an internal service. - */ - @NotNull - protected abstract String getServiceName(); - - protected boolean isMethodSupported(@NotNull HttpMethod method) { - return method == HttpMethod.GET; - } - - @Override - public final boolean process(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) { - try { - AtomicInteger counter = abuseCounter.get(((InetSocketAddress)context.channel().remoteAddress()).getAddress()); - if (counter.incrementAndGet() > Registry.intValue("ide.rest.api.requests.per.minute", 30)) { - Responses.send(Responses.orInSafeMode(HttpResponseStatus.TOO_MANY_REQUESTS, HttpResponseStatus.OK), context.channel(), request); - return true; - } - - if (!isHostTrusted(request, urlDecoder)) { - Responses.send(Responses.orInSafeMode(HttpResponseStatus.FORBIDDEN, HttpResponseStatus.OK), context.channel(), request); - return true; - } - - String error = execute(urlDecoder, request, context); - if (error != null) { - Responses.send(HttpResponseStatus.BAD_REQUEST, context.channel(), request, error); - } - } - catch (Throwable e) { - HttpResponseStatus status; - // JsonReader exception - //noinspection InstanceofCatchParameter - if (e instanceof MalformedJsonException || (e instanceof IllegalStateException && e.getMessage().startsWith("Expected a "))) { - LOG.warn(e); - status = HttpResponseStatus.BAD_REQUEST; - } - else { - LOG.error(e); - status = HttpResponseStatus.INTERNAL_SERVER_ERROR; - } - Responses.send(status, context.channel(), request, ExceptionUtil.getThrowableText(e)); - } - return true; - } - - @SuppressWarnings("deprecation") - protected boolean isHostTrusted(@NotNull FullHttpRequest request, @NotNull QueryStringDecoder urlDecoder) throws InterruptedException, InvocationTargetException { - return isHostTrusted(request); - } - - /** - * @deprecated Use {@link #isHostTrusted(FullHttpRequest, QueryStringDecoder)} - */ - @SuppressWarnings("DeprecatedIsStillUsed") - @Deprecated - // e.g. upsource trust to configured host - protected boolean isHostTrusted(@NotNull FullHttpRequest request) throws InterruptedException, InvocationTargetException { - if (BuiltInWebServerKt.isSignedRequest(request)) { - return true; - } - - String referrer = NettyKt.getOrigin(request); - if (referrer == null) { - referrer = NettyKt.getReferrer(request); - } - - String host; - try { - host = StringUtil.nullize(referrer == null ? null : new URI(referrer).getHost()); - } - catch (URISyntaxException ignored) { - return false; - } - - Ref isTrusted = Ref.create(); - if (host != null) { - if (NetUtils.isLocalhost(host)) { - isTrusted.set(true); - } - else { - isTrusted.set(trustedOrigins.getIfPresent(host)); - } - } - - if (isTrusted.isNull()) { - SwingUtilities.invokeAndWait(() -> { - AppIcon.getInstance().requestAttention(null, true); - isTrusted.set(showYesNoDialog( - IdeBundle.message("warning.use.rest.api", getServiceName(), ObjectUtils.chooseNotNull(host, "unknown host")), - "title.use.rest.api")); - if (host != null) { - trustedOrigins.put(host, isTrusted.get()); - } - }); - } - return isTrusted.get(); - } - - protected static void activateLastFocusedFrame() { - IdeFrame frame = IdeFocusManager.getGlobalInstance().getLastFocusedFrame(); - if (frame instanceof Window) { - ((Window)frame).toFront(); - } - } - - /** - * Return error or send response using {@link #sendOk(FullHttpRequest, ChannelHandlerContext)}, {@link #send(BufferExposingByteArrayOutputStream, HttpRequest, ChannelHandlerContext)} - */ - @Nullable("error text or null if successful") - public abstract String execute(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) throws IOException; - - @NotNull - protected static JsonReader createJsonReader(@NotNull FullHttpRequest request) { - JsonReader reader = new JsonReader(new InputStreamReader(new ByteBufInputStream(request.content()), StandardCharsets.UTF_8)); - reader.setLenient(true); - return reader; - } - - @NotNull - protected static JsonWriter createJsonWriter(@NotNull OutputStream out) { - JsonWriter writer = new JsonWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8)); - writer.setIndent(" "); - return writer; - } - - @Nullable - protected static Project getLastFocusedOrOpenedProject() { - IdeFrame lastFocusedFrame = IdeFocusManager.getGlobalInstance().getLastFocusedFrame(); - Project project = lastFocusedFrame == null ? null : lastFocusedFrame.getProject(); - if (project == null) { - Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); - return openProjects.length > 0 ? openProjects[0] : null; - } - return project; - } - - protected static void sendOk(@NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) { - sendStatus(HttpResponseStatus.OK, HttpUtil.isKeepAlive(request), context.channel()); - } - - protected static void sendStatus(@NotNull HttpResponseStatus status, boolean keepAlive, @NotNull Channel channel) { - DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status); - HttpUtil.setContentLength(response, 0); - Responses.addCommonHeaders(response); - Responses.addNoCache(response); - if (keepAlive) { - HttpUtil.setKeepAlive(response, true); - } - response.headers().set("X-Frame-Options", "Deny"); - Responses.send(response, channel, !keepAlive); - } - - protected static void send(@NotNull BufferExposingByteArrayOutputStream byteOut, @NotNull HttpRequest request, @NotNull ChannelHandlerContext context) { - HttpResponse response = Responses.response("application/json", Unpooled.wrappedBuffer(byteOut.getInternalBuffer(), 0, byteOut.size())); - sendResponse(request, context, response); - } - - protected static void sendResponse(@NotNull HttpRequest request, @NotNull ChannelHandlerContext context, @NotNull HttpResponse response) { - Responses.addNoCache(response); - response.headers().set("X-Frame-Options", "Deny"); - Responses.send(response, context.channel(), request); - } - - @Nullable - protected static String getStringParameter(@NotNull String name, @NotNull QueryStringDecoder urlDecoder) { - return ContainerUtil.getLastItem(urlDecoder.parameters().get(name)); - } - - protected static int getIntParameter(@NotNull String name, @NotNull QueryStringDecoder urlDecoder) { - return StringUtilRt.parseInt(StringUtil.nullize(ContainerUtil.getLastItem(urlDecoder.parameters().get(name)), true), -1); - } - - protected static boolean getBooleanParameter(@NotNull String name, @NotNull QueryStringDecoder urlDecoder) { - return getBooleanParameter(name, urlDecoder, false); - } - - protected static boolean getBooleanParameter(@NotNull String name, @NotNull QueryStringDecoder urlDecoder, boolean defaultValue) { - List values = urlDecoder.parameters().get(name); - if (ContainerUtil.isEmpty(values)) { - return defaultValue; - } - - String value = values.get(values.size() - 1); - // if just name specified, so, true - return value.isEmpty() || Boolean.parseBoolean(value); - } -} diff --git a/platform/built-in-server/src/org/jetbrains/ide/RestService.kt b/platform/built-in-server/src/org/jetbrains/ide/RestService.kt new file mode 100644 index 000000000000..fa2a6926ca4c --- /dev/null +++ b/platform/built-in-server/src/org/jetbrains/ide/RestService.kt @@ -0,0 +1,281 @@ +// Copyright 2000-2019 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.ide + +import com.google.common.base.Supplier +import com.google.common.cache.CacheBuilder +import com.google.common.cache.CacheLoader +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import com.google.gson.stream.JsonReader +import com.google.gson.stream.JsonWriter +import com.google.gson.stream.MalformedJsonException +import com.intellij.ide.IdeBundle +import com.intellij.ide.impl.ProjectUtil.showYesNoDialog +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.ModalityState +import com.intellij.openapi.diagnostic.logger +import com.intellij.openapi.project.Project +import com.intellij.openapi.project.ProjectManager +import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream +import com.intellij.openapi.util.registry.Registry +import com.intellij.openapi.util.text.StringUtilRt +import com.intellij.openapi.wm.IdeFocusManager +import com.intellij.ui.AppIcon +import com.intellij.util.ExceptionUtil +import com.intellij.util.io.origin +import com.intellij.util.io.referrer +import com.intellij.util.net.NetUtils +import com.intellij.util.text.nullize +import io.netty.buffer.ByteBufInputStream +import io.netty.buffer.Unpooled +import io.netty.channel.Channel +import io.netty.channel.ChannelHandlerContext +import io.netty.handler.codec.http.* +import org.jetbrains.builtInWebServer.isSignedRequest +import org.jetbrains.io.* +import java.awt.Window +import java.io.IOException +import java.io.OutputStream +import java.lang.reflect.InvocationTargetException +import java.net.InetAddress +import java.net.InetSocketAddress +import java.net.URI +import java.net.URISyntaxException +import java.util.concurrent.TimeUnit +import java.util.concurrent.atomic.AtomicInteger + +/** + * Document your service using [apiDoc](http://apidocjs.com). To extract big example from source code, consider to use *.coffee file near your source file. + * (or Python/Ruby, but coffee recommended because it's plugin is lightweight). See [AboutHttpService] for example. + * + * Don't create JsonReader/JsonWriter directly, use only provided [.createJsonReader], [.createJsonWriter] methods (to ensure that you handle in/out according to REST API guidelines). + * + * @see [Best Practices for Designing a Pragmatic REST API](http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api). + */ +abstract class RestService : HttpRequestHandler() { + companion object { + @JvmField + val LOG = logger() + + const val PREFIX = "api" + + @JvmStatic + protected fun activateLastFocusedFrame() { + (IdeFocusManager.getGlobalInstance().lastFocusedFrame as? Window)?.toFront() + } + + @JvmStatic + protected fun createJsonReader(request: FullHttpRequest): JsonReader { + val reader = JsonReader(ByteBufInputStream(request.content()).reader()) + reader.isLenient = true + return reader + } + + @JvmStatic + protected fun createJsonWriter(out: OutputStream): JsonWriter { + val writer = JsonWriter(out.writer()) + writer.setIndent(" ") + return writer + } + + @JvmStatic + fun getLastFocusedOrOpenedProject(): Project? { + return IdeFocusManager.getGlobalInstance().lastFocusedFrame?.project ?: ProjectManager.getInstance().openProjects.firstOrNull() + } + + @JvmStatic + protected fun sendOk(request: FullHttpRequest, context: ChannelHandlerContext) { + sendStatus(HttpResponseStatus.OK, HttpUtil.isKeepAlive(request), context.channel()) + } + + @JvmStatic + protected fun sendStatus(status: HttpResponseStatus, keepAlive: Boolean, channel: Channel) { + val response = DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status) + HttpUtil.setContentLength(response, 0) + response.addCommonHeaders() + response.addNoCache() + if (keepAlive) { + HttpUtil.setKeepAlive(response, true) + } + response.headers().set("X-Frame-Options", "Deny") + response.send(channel, !keepAlive) + } + + @JvmStatic + protected fun send(byteOut: BufferExposingByteArrayOutputStream, request: HttpRequest, context: ChannelHandlerContext) { + val response = response("application/json", Unpooled.wrappedBuffer(byteOut.internalBuffer, 0, byteOut.size())) + sendResponse(request, context, response) + } + + @JvmStatic + protected fun sendResponse(request: HttpRequest, context: ChannelHandlerContext, response: HttpResponse) { + response.addNoCache() + response.headers().set("X-Frame-Options", "Deny") + response.send(context.channel(), request) + } + + @Suppress("SameParameterValue") + @JvmStatic + protected fun getStringParameter(name: String, urlDecoder: QueryStringDecoder): String? { + return urlDecoder.parameters().get(name)?.lastOrNull() + } + + @JvmStatic + protected fun getIntParameter(name: String, urlDecoder: QueryStringDecoder): Int { + return StringUtilRt.parseInt(getStringParameter(name, urlDecoder).nullize(nullizeSpaces = true), -1) + } + + @JvmOverloads + @JvmStatic + protected fun getBooleanParameter(name: String, urlDecoder: QueryStringDecoder, defaultValue: Boolean = false): Boolean { + val values = urlDecoder.parameters().get(name) ?: return defaultValue + // if just name specified, so, true + val value = values.lastOrNull() ?: return true + return value.toBoolean() + } + } + + protected val gson: Gson by lazy { + GsonBuilder() + .setPrettyPrinting() + .disableHtmlEscaping() + .create() + } + + private val abuseCounter = CacheBuilder.newBuilder() + .expireAfterWrite(1, TimeUnit.MINUTES) + .build(CacheLoader.from(Supplier { AtomicInteger() })) + + private val trustedOrigins = CacheBuilder.newBuilder() + .maximumSize(1024) + .expireAfterWrite(1, TimeUnit.DAYS) + .build() + + /** + * Service url must be "/api/$serviceName", but to preserve backward compatibility, prefixless path could be also supported + */ + protected open val isPrefixlessAllowed: Boolean + get() = false + + /** + * Use human-readable name or UUID if it is an internal service. + */ + protected abstract fun getServiceName(): String + + override fun isSupported(request: FullHttpRequest): Boolean { + if (!isMethodSupported(request.method())) { + return false + } + + val uri = request.uri() + + if (isPrefixlessAllowed && checkPrefix(uri, getServiceName())) { + return true + } + + val serviceName = getServiceName() + val minLength = 1 + PREFIX.length + 1 + serviceName.length + if (uri.length >= minLength && + uri[0] == '/' && + uri.regionMatches(1, PREFIX, 0, PREFIX.length, ignoreCase = true) && + uri.regionMatches(2 + PREFIX.length, serviceName, 0, serviceName.length, ignoreCase = true)) { + if (uri.length == minLength) { + return true + } + else { + val c = uri[minLength] + return c == '/' || c == '?' + } + } + return false + } + + protected open fun isMethodSupported(method: HttpMethod): Boolean { + return method === HttpMethod.GET + } + + override fun process(urlDecoder: QueryStringDecoder, request: FullHttpRequest, context: ChannelHandlerContext): Boolean { + try { + val counter = abuseCounter.get((context.channel().remoteAddress() as InetSocketAddress).address) + if (counter.incrementAndGet() > Registry.intValue("ide.rest.api.requests.per.minute", 30)) { + HttpResponseStatus.TOO_MANY_REQUESTS.orInSafeMode(HttpResponseStatus.OK).send(context.channel(), request) + return true + } + + if (!isHostTrusted(request, urlDecoder)) { + HttpResponseStatus.FORBIDDEN.orInSafeMode(HttpResponseStatus.OK).send(context.channel(), request) + return true + } + + val error = execute(urlDecoder, request, context) + if (error != null) { + HttpResponseStatus.BAD_REQUEST.send(context.channel(), request, error) + } + } + catch (e: Throwable) { + val status: HttpResponseStatus? + // JsonReader exception + if (e is MalformedJsonException || e is IllegalStateException && e.message!!.startsWith("Expected a ")) { + LOG.warn(e) + status = HttpResponseStatus.BAD_REQUEST + } + else { + LOG.error(e) + status = HttpResponseStatus.INTERNAL_SERVER_ERROR + } + status.send(context.channel(), request, ExceptionUtil.getThrowableText(e)) + } + + return true + } + + @Throws(InterruptedException::class, InvocationTargetException::class) + protected open fun isHostTrusted(request: FullHttpRequest, urlDecoder: QueryStringDecoder): Boolean { + @Suppress("DEPRECATION") + return isHostTrusted(request) + } + + @Deprecated("Use {@link #isHostTrusted(FullHttpRequest, QueryStringDecoder)}") + @Throws(InterruptedException::class, InvocationTargetException::class) + // e.g. upsource trust to configured host + protected open fun isHostTrusted(request: FullHttpRequest): Boolean { + if (request.isSignedRequest()) { + return true + } + + val referrer = request.origin ?: request.referrer + val host = try { + if (referrer == null) null else URI(referrer).host.nullize() + } + catch (ignored: URISyntaxException) { + return false + } + + if (host != null) { + if (NetUtils.isLocalhost(host)) { + return true + } + else { + trustedOrigins.getIfPresent(host)?.let { + return it + } + } + } + + var isTrusted = false + ApplicationManager.getApplication().invokeAndWait({ + AppIcon.getInstance().requestAttention(null, true) + isTrusted = showYesNoDialog(IdeBundle.message("warning.use.rest.api", getServiceName(), host ?: "unknown host"), "title.use.rest.api") + if (host != null) { + trustedOrigins.put(host, isTrusted) + } + }, ModalityState.any()) + return isTrusted + } + + /** + * Return error or send response using [.sendOk], [.send] + */ + @Throws(IOException::class) + abstract fun execute(urlDecoder: QueryStringDecoder, request: FullHttpRequest, context: ChannelHandlerContext): String? +} diff --git a/platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java b/platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java index 7c7c256d94b7..44d4588d041a 100644 --- a/platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java +++ b/platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java @@ -1,4 +1,4 @@ -// 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. +// Copyright 2000-2019 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.util; import com.intellij.openapi.components.ServiceManager; @@ -65,7 +65,7 @@ public abstract class PropertiesComponent extends SimpleModificationTracker { public abstract void setValues(@NonNls @NotNull String name, String[] values); - public static PropertiesComponent getInstance(Project project) { + public static PropertiesComponent getInstance(@NotNull Project project) { return ServiceManager.getService(project, PropertiesComponent.class); } diff --git a/platform/core-impl/src/com/intellij/diagnostic/PerformanceWatcher.java b/platform/core-impl/src/com/intellij/diagnostic/PerformanceWatcher.java index 019ee46d8181..043d809401cd 100644 --- a/platform/core-impl/src/com/intellij/diagnostic/PerformanceWatcher.java +++ b/platform/core-impl/src/com/intellij/diagnostic/PerformanceWatcher.java @@ -33,6 +33,7 @@ import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.List; +import java.util.Objects; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -306,13 +307,23 @@ public class PerformanceWatcher implements Disposable { for (int i = 0; i < commonPart.size() && i < stackTraceElements.length; i++) { StackTraceElement el1 = commonPart.get(commonPart.size() - i - 1); StackTraceElement el2 = stackTraceElements[stackTraceElements.length - i - 1]; - if (!el1.equals(el2)) { + if (!compareStackTraceElements(el1, el2)) { return commonPart.subList(commonPart.size() - i, commonPart.size()); } } return commonPart; } + // same as java.lang.StackTraceElement.equals, but do not care about the line number + private static boolean compareStackTraceElements(StackTraceElement el1, StackTraceElement el2) { + if (el1 == el2) { + return true; + } + return el1.getClassName().equals(el2.getClassName()) && + Objects.equals(el1.getMethodName(), el2.getMethodName()) && + Objects.equals(el1.getFileName(), el2.getFileName()); + } + private class SwingThreadRunnable implements Runnable { private final long myCreationMillis; diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java index 4a0c8e7d7eb3..01e6c9c598b6 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java @@ -424,10 +424,9 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase i DefaultActionGroup actionGroup = new DefaultActionGroup(); if (executionConsole instanceof BuildView) { actionGroup.addAll(((BuildView)executionConsole).getSwitchActions()); - actionGroup.add(new ShowExecutionErrorsOnlyAction((BuildView)executionConsole)); + actionGroup.add(BuildTreeFilters.createFilteringActionsGroup((BuildView)executionConsole)); } - DefaultExecutionResult executionResult = - new DefaultExecutionResult(executionConsole, processHandler, actionGroup.getChildren(null)); + DefaultExecutionResult executionResult = new DefaultExecutionResult(executionConsole, processHandler, actionGroup.getChildren(null)); executionResult.setRestartActions(restartActions); return executionResult; } diff --git a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemImportingTestCase.java b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemImportingTestCase.java index 44acb1ff4036..abc9aef055a4 100644 --- a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemImportingTestCase.java +++ b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemImportingTestCase.java @@ -554,7 +554,7 @@ public abstract class ExternalSystemImportingTestCase extends ExternalSystemTest final AtomicInteger counter = new AtomicInteger(); Messages.setTestDialog(new TestDialog() { @Override - public int show(String message) { + public int show(@NotNull String message) { counter.set(counter.get() + 1); return 0; } @@ -566,7 +566,7 @@ public abstract class ExternalSystemImportingTestCase extends ExternalSystemTest final AtomicInteger counter = new AtomicInteger(); Messages.setTestDialog(new TestDialog() { @Override - public int show(String message) { + public int show(@NotNull String message) { counter.set(counter.get() + 1); return 1; } diff --git a/platform/lang-api/src/com/intellij/codeInsight/template/Expression.java b/platform/lang-api/src/com/intellij/codeInsight/template/Expression.java index 853bb75d36ac..2cf64cce2e1e 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/template/Expression.java +++ b/platform/lang-api/src/com/intellij/codeInsight/template/Expression.java @@ -32,13 +32,4 @@ public abstract class Expression { public String getAdvertisingText() { return null; } - - /** - * @return true if {@link Expression#calculateResult(com.intellij.codeInsight.template.ExpressionContext)} or - * {@link Expression#calculateQuickResult(com.intellij.codeInsight.template.ExpressionContext)} - * require committed PSI for their calculation or false otherwise - */ - public boolean requiresCommittedPSI() { - return true; - } } diff --git a/platform/lang-api/src/com/intellij/codeInsight/template/impl/TextExpression.java b/platform/lang-api/src/com/intellij/codeInsight/template/impl/TextExpression.java index c80a695ad13a..6a09c465aaac 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/template/impl/TextExpression.java +++ b/platform/lang-api/src/com/intellij/codeInsight/template/impl/TextExpression.java @@ -37,11 +37,6 @@ public class TextExpression extends Expression { return calculateResult(expressionContext); } - @Override - public boolean requiresCommittedPSI() { - return false; - } - @Override public LookupElement[] calculateLookupItems(ExpressionContext expressionContext) { return LookupElement.EMPTY_ARRAY; diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java index 2a29e38899c9..5c30c2847f95 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java @@ -244,7 +244,7 @@ public abstract class SdkType implements SdkTypeId { * @param parentComponent the parent component for showing the dialog. * @param selectedSdk current selected sdk in parentComponent * @param sdkCreatedCallback the callback to which the created SDK is passed. - * @implSpec method's implementations should not add sdk to the jdkTable neither invoke {@link SdkType#setupSdkPaths}. Only create and + * @implSpec method's implementations should not add sdk to the jdkTable neither invoke {@link SdkType#setupSdkPaths}. Only create and * and pass to the callback. The rest is done by {@link com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel#setupSdk(Sdk, Consumer)} */ public void showCustomCreateUI(@NotNull SdkModel sdkModel, diff --git a/platform/lang-impl/src/com/intellij/application/options/CodeStyleAbstractPanel.java b/platform/lang-impl/src/com/intellij/application/options/CodeStyleAbstractPanel.java index c6eab2b33fa1..478266b4e72e 100644 --- a/platform/lang-impl/src/com/intellij/application/options/CodeStyleAbstractPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/CodeStyleAbstractPanel.java @@ -64,7 +64,7 @@ public abstract class CodeStyleAbstractPanel implements Disposable, ComponentHig private final List myPreviewRangesToHighlight = new ArrayList<>(); - private final Editor myEditor; + private final EditorEx myEditor; private final CodeStyleSettings mySettings; private boolean myShouldUpdatePreview; protected static final int[] ourWrappings = @@ -134,7 +134,7 @@ public abstract class CodeStyleAbstractPanel implements Disposable, ComponentHig } @Nullable - private Editor createEditor() { + private EditorEx createEditor() { if (StringUtil.isEmpty(getPreviewText())) return null; EditorFactory editorFactory = EditorFactory.getInstance(); Document editorDocument = editorFactory.createDocument(""); @@ -159,7 +159,7 @@ public abstract class CodeStyleAbstractPanel implements Disposable, ComponentHig protected void updatePreview(boolean useDefaultSample) { if (myEditor == null) return; updateEditor(useDefaultSample); - updatePreviewHighlighter((EditorEx)myEditor); + updatePreviewHighlighter(myEditor); } private void updateEditor(boolean useDefaultSample) { @@ -167,7 +167,6 @@ public abstract class CodeStyleAbstractPanel implements Disposable, ComponentHig return; } - Project project = ProjectUtil.guessCurrentProject(getPanel()); if (myEditor.isDisposed()) return; if (myLastDocumentModificationStamp != myEditor.getDocument().getModificationStamp()) { @@ -177,8 +176,19 @@ public abstract class CodeStyleAbstractPanel implements Disposable, ComponentHig myTextToReformat = StringUtil.convertLineSeparators(ObjectUtils.notNull(getPreviewText(), "")); } + updateEditorState(true); + } + + protected void setEditorText(@NotNull String text, boolean updateHighlighter) { + myTextToReformat = StringUtil.convertLineSeparators(text); + if (updateHighlighter) updatePreviewHighlighter(myEditor); + updateEditorState(false); + } + + private void updateEditorState(boolean collectChanges) { int currOffs = myEditor.getScrollingModel().getVerticalScrollOffset(); - CommandProcessor.getInstance().executeCommand(project, () -> replaceText(project), null, null); + Project project = ProjectUtil.guessCurrentProject(getPanel()); + CommandProcessor.getInstance().executeCommand(project, () -> replaceText(project, collectChanges), null, null); myEditor.getSettings().setRightMargin(getAdjustedRightMargin()); myLastDocumentModificationStamp = myEditor.getDocument().getModificationStamp(); @@ -192,11 +202,11 @@ public abstract class CodeStyleAbstractPanel implements Disposable, ComponentHig protected abstract int getRightMargin(); - private void replaceText(final Project project) { + private void replaceText(final Project project, boolean collectChanges) { ApplicationManager.getApplication().runWriteAction(() -> { try { Document beforeReformat = null; - if (myEditor.getDocument().getTextLength() > 0) { + if (collectChanges && myEditor.getDocument().getTextLength() > 0) { beforeReformat = collectChangesBeforeCurrentSettingsAppliance(project); } @@ -596,6 +606,12 @@ public abstract class CodeStyleAbstractPanel implements Disposable, ComponentHig return myCurrentSettings; } +@Nullable + protected CodeStyleSettings getModelSettings() { + CodeStyleSchemesModel model = myModel; + return model != null ? model.getCloneSettings(model.getSelectedScheme()) : null; + } + public void setupCopyFromMenu(JPopupMenu copyMenu) { copyMenu.removeAll(); } diff --git a/platform/lang-impl/src/com/intellij/application/options/TabbedLanguageCodeStylePanel.java b/platform/lang-impl/src/com/intellij/application/options/TabbedLanguageCodeStylePanel.java index 050a00ae98e1..c535feda28fa 100644 --- a/platform/lang-impl/src/com/intellij/application/options/TabbedLanguageCodeStylePanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/TabbedLanguageCodeStylePanel.java @@ -584,7 +584,7 @@ public abstract class TabbedLanguageCodeStylePanel extends CodeStyleAbstractPane } @Nullable - private CommonCodeStyleSettings.IndentOptions getIndentOptions(CodeStyleSettings settings) { + protected CommonCodeStyleSettings.IndentOptions getIndentOptions(CodeStyleSettings settings) { return settings.getCommonSettings(getDefaultLanguage()).getIndentOptions(); } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/group/ArrangementGroupingRulesControl.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/group/ArrangementGroupingRulesControl.java index 02ce1aa65099..b07b2d41578b 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/group/ArrangementGroupingRulesControl.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/group/ArrangementGroupingRulesControl.java @@ -164,6 +164,7 @@ public class ArrangementGroupingRulesControl extends JBTable { ArrangementGroupingComponent component = (ArrangementGroupingComponent)value; component.setRowIndex(row + 1); component.setHighlight(myRowUnderMouse == row || table.isRowSelected(row)); + component.revalidate(); return component; } else if (value instanceof ArrangementRepresentationAware) { diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form index db842f605c07..b76a6bd1f5d1 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form @@ -311,12 +311,13 @@ + - + @@ -420,7 +421,7 @@ - + diff --git a/platform/lang-impl/src/com/intellij/build/AbstractViewManager.java b/platform/lang-impl/src/com/intellij/build/AbstractViewManager.java index 029d8a0d35d0..3e10468e35ca 100644 --- a/platform/lang-impl/src/com/intellij/build/AbstractViewManager.java +++ b/platform/lang-impl/src/com/intellij/build/AbstractViewManager.java @@ -121,7 +121,7 @@ public abstract class AbstractViewManager implements ViewManager, BuildProgressL toolbarActions.removeAll(); toolbarActions.addAll(view.createConsoleActions()); toolbarActions.add(new PinBuildViewAction(buildsView)); - toolbarActions.add(new ShowExecutionErrorsOnlyAction(view)); + toolbarActions.add(BuildTreeFilters.createFilteringActionsGroup(view)); } @Nullable diff --git a/platform/lang-impl/src/com/intellij/build/BuildTreeConsoleView.java b/platform/lang-impl/src/com/intellij/build/BuildTreeConsoleView.java index 533174c4c1e7..39e771f2268f 100644 --- a/platform/lang-impl/src/com/intellij/build/BuildTreeConsoleView.java +++ b/platform/lang-impl/src/com/intellij/build/BuildTreeConsoleView.java @@ -11,6 +11,10 @@ import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.ui.ConsoleView; import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.execution.ui.ExecutionConsole; +import com.intellij.ide.CommonActionsManager; +import com.intellij.ide.IdeBundle; +import com.intellij.ide.OccurenceNavigator; +import com.intellij.ide.OccurenceNavigatorSupport; import com.intellij.ide.actions.EditSourceAction; import com.intellij.ide.ui.UISettings; import com.intellij.ide.util.treeView.NodeRenderer; @@ -56,10 +60,8 @@ import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import java.awt.*; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; @@ -77,7 +79,7 @@ import static com.intellij.util.ui.UIUtil.getTreeSelectionForeground; /** * @author Vladislav.Soroka */ -public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildConsoleView, Filterable { +public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildConsoleView, Filterable, OccurenceNavigator { private static final Logger LOG = Logger.getInstance(BuildTreeConsoleView.class); @NonNls private static final String TREE = "tree"; @@ -94,13 +96,14 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon private final Tree myTree; private final ExecutionNode myRootNode; private final ExecutionNode myBuildProgressRootNode; - @Nullable - private volatile Predicate myExecutionTreeFilter; + private final Set> myNodeFilters; + private final ProblemOccurrenceNavigatorSupport myOccurrenceNavigatorSupport; public BuildTreeConsoleView(Project project, BuildDescriptor buildDescriptor, @Nullable ExecutionConsole executionConsole, @NotNull BuildViewSettingsProvider buildViewSettingsProvider) { + myNodeFilters = ContainerUtil.newConcurrentSet(); myProject = project; myWorkingDir = FileUtil.toSystemIndependentName(buildDescriptor.getWorkingDir()); @@ -125,6 +128,9 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon new ConsoleViewHandler(myProject, myTree, myBuildProgressRootNode, this, executionConsole, buildViewSettingsProvider); myThreeComponentsSplitter.setSecondComponent(myConsoleViewHandler.getComponent()); myPanel.add(myThreeComponentsSplitter, BorderLayout.CENTER); + BuildTreeFilters.install(this); + myRootNode.setFilter(getFilter()); + myOccurrenceNavigatorSupport = new ProblemOccurrenceNavigatorSupport(myTree); } private void installContextMenu(@NotNull StartBuildEvent startBuildEvent) { @@ -143,8 +149,14 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon ActionUtil.copyFrom(edit, "EditSource"); group.add(edit); group.addSeparator(); - group.add(new ShowExecutionErrorsOnlyAction(this)); - + group.addAll(BuildTreeFilters.createFilteringActionsGroup(this)); + group.addSeparator(); + //Initializing prev and next occurrences actions + final CommonActionsManager actionsManager = CommonActionsManager.getInstance(); + final AnAction prevAction = actionsManager.createPrevOccurenceAction(this); + group.add(prevAction); + final AnAction nextAction = actionsManager.createNextOccurenceAction(this); + group.add(nextAction); PopupHandler.installPopupHandler(myTree, group, "BuildView"); }); } @@ -162,20 +174,35 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon return true; } + @NotNull @Override - @Nullable public Predicate getFilter() { - return myExecutionTreeFilter; + return executionNode -> executionNode == getBuildProgressRootNode() || + executionNode.isRunning() || + executionNode.isFailed() || + myNodeFilters.stream().anyMatch(predicate -> predicate.test(executionNode)); } @Override - public void setFilter(@Nullable Predicate executionTreeFilter) { - myExecutionTreeFilter = executionTreeFilter; - ExecutionNode buildProgressRootNode = getBuildProgressRootNode(); + public void addFilter(@NotNull Predicate executionTreeFilter) { + myNodeFilters.add(executionTreeFilter); + updateFilter(); + } + + @Override + public void removeFilter(@NotNull Predicate filter) { + myNodeFilters.remove(filter); + updateFilter(); + } + + @Override + public boolean contains(@NotNull Predicate filter) { + return myNodeFilters.contains(filter); + } + + private void updateFilter() { ExecutionNode rootElement = getRootElement(); - Predicate predicate = executionTreeFilter == null ? null : - node -> node == buildProgressRootNode || executionTreeFilter.test(node); - rootElement.setFilter(predicate); + rootElement.setFilter(getFilter()); scheduleUpdate(rootElement); } @@ -315,6 +342,38 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon } } + @Override + public boolean hasNextOccurence() { + return myOccurrenceNavigatorSupport.hasNextOccurence(); + } + + @Override + public boolean hasPreviousOccurence() { + return myOccurrenceNavigatorSupport.hasPreviousOccurence(); + } + + @Override + public OccurenceInfo goNextOccurence() { + return myOccurrenceNavigatorSupport.goNextOccurence(); + } + + @Override + public OccurenceInfo goPreviousOccurence() { + return myOccurrenceNavigatorSupport.goPreviousOccurence(); + } + + @NotNull + @Override + public String getNextOccurenceActionName() { + return myOccurrenceNavigatorSupport.getNextOccurenceActionName(); + } + + @NotNull + @Override + public String getPreviousOccurenceActionName() { + return myOccurrenceNavigatorSupport.getPreviousOccurenceActionName(); + } + @NotNull private static TreeVisitor visitor(@NotNull ExecutionNode executionNode) { return path -> { @@ -502,7 +561,13 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon if (eventKind == MessageEvent.Kind.ERROR || eventKind == MessageEvent.Kind.WARNING) { SimpleNode p = parentNode; do { - ((ExecutionNode)p).reportChildMessageKind(eventKind); + ExecutionNode executionNode = (ExecutionNode)p; + boolean warningUpdate = eventKind == MessageEvent.Kind.WARNING && !executionNode.hasWarnings(); + executionNode.reportChildMessageKind(eventKind); + if (warningUpdate) { + executionNode.cleanUpCache(); + scheduleUpdate(executionNode); + } } while ((p = p.getParent()) instanceof ExecutionNode); scheduleUpdate(getRootElement()); @@ -745,6 +810,41 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon } } + private static class ProblemOccurrenceNavigatorSupport extends OccurenceNavigatorSupport { + ProblemOccurrenceNavigatorSupport(final Tree tree) { + super(tree); + } + + @Override + protected Navigatable createDescriptorForNode(@NotNull DefaultMutableTreeNode node) { + Object userObject = node.getUserObject(); + if (!(userObject instanceof ExecutionNode)) { + return null; + } + final ExecutionNode executionNode = (ExecutionNode)userObject; + if (executionNode.getChildCount() > 0 || !executionNode.hasWarnings() && !executionNode.isFailed()) { + return null; + } + List navigatables = executionNode.getNavigatables(); + if (!navigatables.isEmpty()) { + return navigatables.get(0); + } + return null; + } + + @NotNull + @Override + public String getNextOccurenceActionName() { + return IdeBundle.message("action.next.problem"); + } + + @NotNull + @Override + public String getPreviousOccurenceActionName() { + return IdeBundle.message("action.previous.problem"); + } + } + private static class MyTree extends Tree { private MyTree(TreeModel treemodel) { super(treemodel); diff --git a/platform/lang-impl/src/com/intellij/build/BuildView.java b/platform/lang-impl/src/com/intellij/build/BuildView.java index 8f8d586ada65..2e09cfec3765 100644 --- a/platform/lang-impl/src/com/intellij/build/BuildView.java +++ b/platform/lang-impl/src/com/intellij/build/BuildView.java @@ -32,6 +32,7 @@ import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.execution.ui.ExecutionConsole; import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.execution.ui.actions.CloseAction; +import com.intellij.ide.OccurenceNavigator; import com.intellij.ide.actions.PinActiveTabAction; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; @@ -56,7 +57,7 @@ import java.util.function.Supplier; */ @ApiStatus.Experimental public class BuildView extends CompositeView - implements BuildProgressListener, ConsoleView, DataProvider, Filterable { + implements BuildProgressListener, ConsoleView, DataProvider, Filterable, OccurenceNavigator { public static final String CONSOLE_VIEW_NAME = "consoleView"; private final AtomicReference myStartBuildEventRef = new AtomicReference<>(); private final BuildDescriptor myBuildDescriptor; @@ -365,17 +366,75 @@ public class BuildView extends CompositeView return getEventView() != null; } + @NotNull @Override public Predicate getFilter() { BuildTreeConsoleView eventView = getEventView(); - return eventView == null ? null : eventView.getFilter(); + return eventView == null ? executionNode -> true : eventView.getFilter(); } @Override - public void setFilter(Predicate filter) { + public void addFilter(@NotNull Predicate filter) { BuildTreeConsoleView eventView = getEventView(); if (eventView != null) { - eventView.setFilter(filter); + eventView.addFilter(filter); } } + + @Override + public void removeFilter(@NotNull Predicate filter) { + BuildTreeConsoleView eventView = getEventView(); + if (eventView != null) { + eventView.removeFilter(filter); + } + } + + @Override + public boolean contains(@NotNull Predicate filter) { + BuildTreeConsoleView eventView = getEventView(); + return eventView != null && eventView.contains(filter); + } + + @NotNull + private OccurenceNavigator getOccurenceNavigator() { + BuildTreeConsoleView eventView = getEventView(); + if (eventView != null) return eventView; + ExecutionConsole executionConsole = getConsoleView(); + if (executionConsole instanceof OccurenceNavigator) { + return (OccurenceNavigator)executionConsole; + } + return EMPTY; + } + + @Override + public boolean hasNextOccurence() { + return getOccurenceNavigator().hasNextOccurence(); + } + + @Override + public boolean hasPreviousOccurence() { + return getOccurenceNavigator().hasPreviousOccurence(); + } + + @Override + public OccurenceInfo goNextOccurence() { + return getOccurenceNavigator().goNextOccurence(); + } + + @Override + public OccurenceInfo goPreviousOccurence() { + return getOccurenceNavigator().goPreviousOccurence(); + } + + @NotNull + @Override + public String getNextOccurenceActionName() { + return getOccurenceNavigator().getNextOccurenceActionName(); + } + + @NotNull + @Override + public String getPreviousOccurenceActionName() { + return getOccurenceNavigator().getPreviousOccurenceActionName(); + } } diff --git a/platform/lang-impl/src/com/intellij/build/ExecutionNode.java b/platform/lang-impl/src/com/intellij/build/ExecutionNode.java index 260851bd8472..d399faeade25 100644 --- a/platform/lang-impl/src/com/intellij/build/ExecutionNode.java +++ b/platform/lang-impl/src/com/intellij/build/ExecutionNode.java @@ -57,7 +57,7 @@ public class ExecutionNode extends CachingSimpleNode { private static final Icon NODE_ICON_DEFAULT = ICON_16; private static final Icon NODE_ICON_RUNNING = new AnimatedIcon.FS(); - private final Collection myChildrenList = new ConcurrentLinkedDeque<>(); //ContainerUtil.newSmartList(); + private final Collection myChildrenList = new ConcurrentLinkedDeque<>(); private final AtomicInteger myErrors = new AtomicInteger(); private final AtomicInteger myWarnings = new AtomicInteger(); private long startTime; @@ -228,6 +228,11 @@ public class ExecutionNode extends CachingSimpleNode { return endTime <= 0 && !isSkipped(myResult) && !isFailed(myResult); } + public boolean hasWarnings() { + return myWarnings.get() > 0 || + (myResult instanceof MessageEventResult && ((MessageEventResult)myResult).getKind() == MessageEvent.Kind.WARNING); + } + public boolean isFailed() { return isFailed(myResult) || myErrors.get() > 0 || @@ -295,25 +300,6 @@ public class ExecutionNode extends CachingSimpleNode { } } - ExecutionNode copy(ExecutionNode parent) { - ExecutionNode copy = new ExecutionNode(myProject, parent); - copy.startTime = startTime; - copy.endTime = endTime; - copy.myTitle = myTitle; - copy.myTooltip = myTooltip; - copy.myHint = myHint; - copy.myResult = myResult; - copy.myAutoExpandNode = myAutoExpandNode; - copy.myNavigatable = myNavigatable; - copy.myPreferredIconValue = myPreferredIconValue; - copy.myErrors.set(myErrors.get()); - copy.myWarnings.set(myWarnings.get()); - copy.myFilter = myFilter; - copy.myName = myName; - copy.myClosedIcon = myClosedIcon; - return copy; - } - private String getCurrentHint() { String hint = myHint; int warnings = myWarnings.get(); diff --git a/platform/lang-impl/src/com/intellij/build/Filterable.java b/platform/lang-impl/src/com/intellij/build/Filterable.java index 2bcd1cf601a2..06bf2def0732 100644 --- a/platform/lang-impl/src/com/intellij/build/Filterable.java +++ b/platform/lang-impl/src/com/intellij/build/Filterable.java @@ -1,12 +1,19 @@ // Copyright 2000-2019 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.build; +import org.jetbrains.annotations.NotNull; + import java.util.function.Predicate; public interface Filterable { boolean isFilteringEnabled(); + @NotNull Predicate getFilter(); - void setFilter(Predicate filter); + void addFilter(@NotNull Predicate filter); + + void removeFilter(@NotNull Predicate filter); + + boolean contains(@NotNull Predicate filter); } diff --git a/platform/lang-impl/src/com/intellij/build/ShowExecutionErrorsOnlyAction.java b/platform/lang-impl/src/com/intellij/build/ShowExecutionErrorsOnlyAction.java deleted file mode 100644 index 4731037a3cf2..000000000000 --- a/platform/lang-impl/src/com/intellij/build/ShowExecutionErrorsOnlyAction.java +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2000-2019 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.build; - -import com.intellij.icons.AllIcons; -import com.intellij.ide.util.PropertiesComponent; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.Presentation; -import com.intellij.openapi.actionSystem.ToggleAction; -import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.util.registry.Registry; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Predicate; - -/** - * @author Vladislav.Soroka - */ -@ApiStatus.Experimental -public class ShowExecutionErrorsOnlyAction extends ToggleAction implements DumbAware { - private static final Predicate ERROR_FILTER = node -> node.isRunning() || node.isFailed(); - private final Filterable myFilterable; - private final String mySelectionStateKey; - - public ShowExecutionErrorsOnlyAction(@NotNull Filterable filterable) { - this(filterable, "build.toolwindow.show.errors.only.selection.state"); - } - - public ShowExecutionErrorsOnlyAction(@NotNull Filterable filterable, @Nullable String selectionStateKey) { - super("Show Errors Only", "Show Errors Only", AllIcons.General.Error); - myFilterable = filterable; - mySelectionStateKey = selectionStateKey; - } - - @Override - public boolean isSelected(@NotNull AnActionEvent e) { - final Presentation presentation = e.getPresentation(); - if (!Registry.is("build.view.side-by-side", true)) { - presentation.setVisible(false); - return false; - } - boolean filteringEnabled = myFilterable.isFilteringEnabled(); - presentation.setEnabledAndVisible(filteringEnabled); - if (filteringEnabled && mySelectionStateKey != null && - PropertiesComponent.getInstance().getBoolean(mySelectionStateKey, true) && - myFilterable.getFilter() != ERROR_FILTER) { - setSelected(e, true); - } - - return myFilterable.getFilter() == ERROR_FILTER; - } - - @Override - public void setSelected(@NotNull AnActionEvent e, boolean state) { - myFilterable.setFilter(state ? ERROR_FILTER : null); - if (mySelectionStateKey != null) { - PropertiesComponent.getInstance().setValue(mySelectionStateKey, state, true); - } - } -} diff --git a/platform/lang-impl/src/com/intellij/build/buildTreeFilters.kt b/platform/lang-impl/src/com/intellij/build/buildTreeFilters.kt new file mode 100644 index 000000000000..4b5d73d7e217 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/build/buildTreeFilters.kt @@ -0,0 +1,103 @@ +// Copyright 2000-2019 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. +@file:JvmName("BuildTreeFilters") +package com.intellij.build + +import com.intellij.icons.AllIcons +import com.intellij.ide.util.PropertiesComponent +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.actionSystem.DefaultActionGroup +import com.intellij.openapi.actionSystem.ToggleAction +import com.intellij.openapi.project.DumbAware +import com.intellij.openapi.util.registry.Registry +import org.jetbrains.annotations.ApiStatus +import java.util.function.Predicate + +private val SUCCESSFUL_STEPS_FILTER = Predicate { node: ExecutionNode -> !node.isFailed && !node.hasWarnings() } +private val WARNINGS_FILTER = Predicate { node: ExecutionNode -> node.hasWarnings() } + +@ApiStatus.Experimental +fun createFilteringActionsGroup(filterable: Filterable): DefaultActionGroup { + val actionGroup = DefaultActionGroup("Filters", true) + actionGroup.templatePresentation.icon = AllIcons.Actions.Show + actionGroup.add(WarningsToggleAction(filterable)) + actionGroup.add(SuccessfulStepsToggleAction(filterable)) + return actionGroup +} + +@ApiStatus.Experimental +fun install(filterable: Filterable) { + val filteringEnabled = filterable.isFilteringEnabled + if (!filteringEnabled) return + SuccessfulStepsToggleAction.install(filterable) + WarningsToggleAction.install(filterable) +} + +@ApiStatus.Experimental +open class FilterToggleAction constructor(text: String, + private val stateKey: String?, + private val filterable: Filterable, + private val filter: Predicate, + private val defaultState: Boolean) : ToggleAction(text), DumbAware { + override fun isSelected(e: AnActionEvent): Boolean { + val presentation = e.presentation + if (!Registry.`is`("build.view.side-by-side", true)) { + presentation.isVisible = false + return false + } + val filteringEnabled = filterable.isFilteringEnabled + presentation.isEnabledAndVisible = filteringEnabled + if (filteringEnabled && stateKey != null && + PropertiesComponent.getInstance().getBoolean(stateKey, defaultState) && + !filterable.contains(filter)) { + setSelected(e, true) + } + + return filterable.contains(filter) + } + + override fun setSelected(e: AnActionEvent, state: Boolean) { + if (state) { + filterable.addFilter(filter) + } + else { + filterable.removeFilter(filter) + } + if (stateKey != null) { + PropertiesComponent.getInstance().setValue(stateKey, state, defaultState) + } + } + + companion object { + fun install(filterable: Filterable, + filter: Predicate, + stateKey: String, + defaultState: Boolean) { + if (PropertiesComponent.getInstance().getBoolean(stateKey, defaultState) && + !filterable.contains(filter)) { + filterable.addFilter(filter) + } + } + } +} + +@ApiStatus.Experimental +class SuccessfulStepsToggleAction(filterable: Filterable) : + FilterToggleAction("Show Successful Steps", STATE_KEY, filterable, SUCCESSFUL_STEPS_FILTER, false), DumbAware { + companion object { + private const val STATE_KEY = "build.toolwindow.show.successful.steps.selection.state" + fun install(filterable: Filterable) { + install(filterable, SUCCESSFUL_STEPS_FILTER, STATE_KEY, false) + } + } +} + +@ApiStatus.Experimental +class WarningsToggleAction(filterable: Filterable) : + FilterToggleAction("Show Warnings", STATE_KEY, filterable, WARNINGS_FILTER, true), DumbAware { + companion object { + private const val STATE_KEY = "build.toolwindow.show.warnings.selection.state" + fun install(filterable: Filterable) { + install(filterable, WARNINGS_FILTER, STATE_KEY, true) + } + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java index c1b98e7bc53a..eb01d9da3f2e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java @@ -6,6 +6,7 @@ import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementPresentation; import com.intellij.navigation.ChooseByNameContributor; +import com.intellij.navigation.ChooseByNameContributorEx; import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileNameMatcher; @@ -33,9 +34,10 @@ import com.intellij.psi.impl.source.resolve.reference.impl.providers.*; import com.intellij.psi.search.FilenameIndex; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.ProjectScope; -import com.intellij.util.ArrayUtil; import com.intellij.util.ProcessingContext; +import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.indexing.FindSymbolParameters; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -116,13 +118,15 @@ public class FilePathCompletionContributor extends CompletionContributor { if (contextFile != null) { - final String[] fileNames = getAllNames(project); - final Set resultNames = new TreeSet<>(); - for (String fileName : fileNames) { - if (filenameMatchesPrefixOrType(fileName, prefix, set.getSuitableFileTypes(), parameters.getInvocationCount())) { + Set resultNames = new TreeSet<>(); + String finalPrefix = prefix; + processAllNames(project, fileName -> { + if (filenameMatchesPrefixOrType(fileName, finalPrefix, set.getSuitableFileTypes(), + parameters.getInvocationCount())) { resultNames.add(fileName); } - } + return true; + }); final ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex(); @@ -180,16 +184,19 @@ public class FilePathCompletionContributor extends CompletionContributor { extend(CompletionType.BASIC, psiElement(), provider); } - private static boolean filenameMatchesPrefixOrType(final String fileName, final String prefix, final FileType[] suitableFileTypes, final int invocationCount) { - final boolean prefixMatched = prefix.length() == 0 || StringUtil.startsWithIgnoreCase(fileName, prefix); + private static boolean filenameMatchesPrefixOrType(String fileName, + String prefix, + FileType[] suitableFileTypes, + int invocationCount) { + boolean prefixMatched = prefix.length() == 0 || StringUtil.startsWithIgnoreCase(fileName, prefix); if (prefixMatched && (suitableFileTypes.length == 0 || invocationCount > 2)) return true; if (prefixMatched) { - final String extension = FileUtilRt.getExtension(fileName); + String extension = FileUtilRt.getExtension(fileName); if (extension.length() == 0) return false; - for (final FileType fileType : suitableFileTypes) { - for (final FileNameMatcher matcher : FileTypeManager.getInstance().getAssociations(fileType)) { + for (FileType fileType : suitableFileTypes) { + for (FileNameMatcher matcher : FileTypeManager.getInstance().getAssociations(fileType)) { if (FileNameMatcherEx.acceptsCharSequence(matcher, fileName)) return true; } } @@ -237,12 +244,15 @@ public class FilePathCompletionContributor extends CompletionContributor { return true; } - private static String[] getAllNames(@NotNull final Project project) { - Set names = new HashSet<>(); - final ChooseByNameContributor[] nameContributors = ChooseByNameContributor.FILE_EP_NAME.getExtensions(); - for (final ChooseByNameContributor contributor : nameContributors) { + private static void processAllNames(@NotNull Project project, @NotNull Processor processor) { + for (ChooseByNameContributor contributor : ChooseByNameContributor.FILE_EP_NAME.getExtensionList()) { try { - ContainerUtil.addAll(names, contributor.getNames(project, false)); + if (contributor instanceof ChooseByNameContributorEx) { + ((ChooseByNameContributorEx)contributor).processNames(processor, FindSymbolParameters.searchScopeFor(project, false), null); + } + else { + ContainerUtil.process(contributor.getNames(project, false), processor); + } } catch (ProcessCanceledException ex) { // index corruption detected, ignore @@ -251,8 +261,6 @@ public class FilePathCompletionContributor extends CompletionContributor { LOG.error(ex); } } - - return ArrayUtil.toStringArray(names); } @Nullable diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/EmptyExpression.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/EmptyExpression.java index d3ed5c500cac..57e0881da359 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/EmptyExpression.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/EmptyExpression.java @@ -38,11 +38,6 @@ public class EmptyExpression extends Expression { return null; } - @Override - public boolean requiresCommittedPSI() { - return false; - } - @Override public LookupElement[] calculateLookupItems(ExpressionContext context) { return null; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionHintComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionHintComponent.java index 078cad6563cd..f9bd626dca67 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionHintComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionHintComponent.java @@ -340,7 +340,7 @@ public class IntentionHintComponent implements Disposable, ScrollAwareHint { if (!e.isPopupTrigger() && e.getButton() == MouseEvent.BUTTON1) { AnAction action = ActionManager.getInstance().getAction(IdeActions.ACTION_SHOW_INTENTION_ACTIONS); AnActionEvent event = AnActionEvent.createFromInputEvent(e, ActionPlaces.MOUSE_SHORTCUT, null, SimpleDataContext.getProjectContext(project)); - ActionsCollector.getInstance().record(project, action, event, null); + ActionsCollector.getInstance().record(project, action, event, file.getLanguage()); showPopup(true); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ConstantNode.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ConstantNode.java index 4448d0b6a1d0..6a9966f7ed3b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ConstantNode.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ConstantNode.java @@ -39,11 +39,6 @@ public class ConstantNode extends Expression { return myValue; } - @Override - public boolean requiresCommittedPSI() { - return false; - } - @Override public LookupElement[] calculateLookupItems(ExpressionContext context) { return LookupElement.EMPTY_ARRAY; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/EmptyNode.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/EmptyNode.java index 1066c841d18e..95befd7418d3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/EmptyNode.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/EmptyNode.java @@ -35,11 +35,6 @@ public class EmptyNode extends Expression { return null; } - @Override - public boolean requiresCommittedPSI() { - return false; - } - @Override public LookupElement[] calculateLookupItems(ExpressionContext context) { return null; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/SelectionNode.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/SelectionNode.java index 53c5b07c6302..040c4a9ff626 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/SelectionNode.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/SelectionNode.java @@ -45,8 +45,4 @@ public class SelectionNode extends Expression { return calculateQuickResult(context); } - @Override - public boolean requiresCommittedPSI() { - return false; - } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java index 0f3079a4c6d9..88a7d1de6d58 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java @@ -832,13 +832,11 @@ public class TemplateState implements Disposable { int start = mySegments.getSegmentStart(segmentNumber); int end = mySegments.getSegmentEnd(segmentNumber); - if(!isQuick || expressionNode.requiresCommittedPSI()) { - PsiDocumentManager.getInstance(myProject).commitDocument(myDocument); - } + PsiDocumentManager.getInstance(myProject).commitDocument(myDocument); PsiFile psiFile = getPsiFile(); PsiElement element = psiFile != null ? psiFile.findElementAt(start) : null; - if (element != null && !element.isValid()) { - element = null; + if (element != null) { + PsiUtilCore.ensureValid(element); } ExpressionContext context = createExpressionContext(start); @@ -860,8 +858,8 @@ public class TemplateState implements Disposable { if (defaultValue != null && resultIsNullOrEmpty) { result = defaultValue.calculateResult(context); } - if (element != null && !element.isValid()) { - element = null; + if (element != null) { + PsiUtilCore.ensureValid(element); } if (result == null || result.equalsToText(oldValue, element)) return; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/VariableNode.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/VariableNode.java index c1198c977201..8dc75cc4e686 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/VariableNode.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/VariableNode.java @@ -47,11 +47,6 @@ public class VariableNode extends Expression { return TemplateManagerImpl.getTemplateState(context.getEditor()).getVariableValue(getName()); } - @Override - public boolean requiresCommittedPSI() { - return myInitialValue != null && myInitialValue.requiresCommittedPSI(); - } - @Override public LookupElement[] calculateLookupItems(ExpressionContext context) { if (myInitialValue == null){ diff --git a/platform/lang-impl/src/com/intellij/execution/ExecutorRegistryImpl.java b/platform/lang-impl/src/com/intellij/execution/ExecutorRegistryImpl.java index 1ab856652a1a..ea6408007b27 100644 --- a/platform/lang-impl/src/com/intellij/execution/ExecutorRegistryImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ExecutorRegistryImpl.java @@ -332,7 +332,8 @@ public class ExecutorRegistryImpl extends ExecutorRegistry implements Disposable if (configuration instanceof CompoundRunConfiguration) { RunManager runManager = RunManager.getInstance(project); for (SettingsAndEffectiveTarget settingsAndEffectiveTarget : ((CompoundRunConfiguration)configuration).getConfigurationsWithEffectiveRunTargets()) { - run(project, settingsAndEffectiveTarget.getConfiguration(), runManager.findSettings(configuration), dataContext); + RunConfiguration subConfiguration = settingsAndEffectiveTarget.getConfiguration(); + run(project, subConfiguration, runManager.findSettings(subConfiguration), dataContext); } } else { diff --git a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereUI.java b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereUI.java index 3a0d2cf8464a..20595163d120 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereUI.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereUI.java @@ -349,7 +349,7 @@ public class SearchEverywhereUI extends BigPopupUI implements DataProvider, Quic @NotNull @Override public AnAction[] getChildren(@Nullable AnActionEvent e) { - if (e == null) return EMPTY_ARRAY; + if (e == null || mySelectedTab == null) return EMPTY_ARRAY; return mySelectedTab.actions.toArray(EMPTY_ARRAY); } }); @@ -424,7 +424,6 @@ public class SearchEverywhereUI extends BigPopupUI implements DataProvider, Quic contributorsPanel.add(tab); myTabs.add(tab); }); - switchToTab(allTab); return contributorsPanel; } @@ -1427,8 +1426,8 @@ public class SearchEverywhereUI extends BigPopupUI implements DataProvider, Quic @Override public void update(@NotNull AnActionEvent e) { - Boolean enabled = mySelectedTab.getContributor().map(contributor -> contributor.showInFindResults()).orElse(true); - e.getPresentation().setEnabled(enabled); + SearchEverywhereContributor contributor = mySelectedTab == null ? null : mySelectedTab.contributor; + e.getPresentation().setEnabled(contributor == null || contributor.showInFindResults()); } } diff --git a/platform/lang-impl/src/com/intellij/ide/extensionResources/ExtensionsRootType.java b/platform/lang-impl/src/com/intellij/ide/extensionResources/ExtensionsRootType.java index e8b7f99b600a..05eb47b58d3c 100644 --- a/platform/lang-impl/src/com/intellij/ide/extensionResources/ExtensionsRootType.java +++ b/platform/lang-impl/src/com/intellij/ide/extensionResources/ExtensionsRootType.java @@ -8,7 +8,11 @@ import com.intellij.ide.scratch.RootType; import com.intellij.ide.scratch.ScratchFileService; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.extensions.PluginDescriptor; import com.intellij.openapi.extensions.PluginId; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.io.FileUtil; @@ -19,6 +23,7 @@ import com.intellij.util.ObjectUtils; import com.intellij.util.PlatformUtils; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.DigestUtil; +import one.util.streamex.StreamEx; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,8 +33,10 @@ import java.io.IOException; import java.net.URL; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; +import java.util.Enumeration; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; /** *

Extensions root type provide a common interface for plugins to access resources that are modifiable by the user.

@@ -191,17 +198,24 @@ public class ExtensionsRootType extends RootType { private static List getBundledResourceUrls(@NotNull PluginId pluginId, @NotNull String path) throws IOException { String resourcesPath = EXTENSIONS_PATH + "/" + path; IdeaPluginDescriptor plugin = PluginManager.getPlugin(pluginId); - ClassLoader pluginClassLoader = plugin != null ? plugin.getPluginClassLoader() : null; - Set urls = plugin == null ? null : ContainerUtil.newLinkedHashSet(ContainerUtil.toList(pluginClassLoader.getResources(resourcesPath))); - if (urls == null) return ContainerUtil.emptyList(); + if (plugin == null) return ContainerUtil.emptyList(); + ClassLoader pluginClassLoader = plugin.getPluginClassLoader(); + final Enumeration resources = pluginClassLoader.getResources(resourcesPath); + if (resources == null) return ContainerUtil.emptyList(); + if (plugin.getUseIdeaClassLoader()) return ContainerUtil.toList(resources); - PluginId corePluginId = PluginId.findId(PluginManagerCore.CORE_PLUGIN_ID); - IdeaPluginDescriptor corePlugin = ObjectUtils.notNull(PluginManager.getPlugin(corePluginId)); - ClassLoader coreClassLoader = corePlugin.getPluginClassLoader(); - if (coreClassLoader != pluginClassLoader && !plugin.getUseIdeaClassLoader() && !pluginId.equals(corePluginId)) { - urls.removeAll(ContainerUtil.toList(coreClassLoader.getResources(resourcesPath))); + final Set urls = ContainerUtil.newLinkedHashSet(ContainerUtil.toList(resources)); + // exclude parent classloader resources from list + final List dependentPluginClassLoaders = StreamEx.of(plugin.getDependentPluginIds()) + .map(PluginManager::getPlugin) + .nonNull() + .map(PluginDescriptor::getPluginClassLoader) + .without(pluginClassLoader) + .collect(Collectors.toList()); + + for (ClassLoader classLoader : dependentPluginClassLoaders) { + urls.removeAll(ContainerUtil.toList(classLoader.getResources(resourcesPath))); } - return ContainerUtil.newArrayList(urls); } @@ -269,13 +283,23 @@ public class ExtensionsRootType extends RootType { FileUtil.rename(file, newName); } - private void extractBundledExtensionsIfNeeded(@NotNull PluginId pluginId) throws IOException { - if (!ApplicationManager.getApplication().isDispatchThread()) return; - + private void extractBundledExtensionsIfNeeded(@NotNull PluginId pluginId) { IdeaPluginDescriptor plugin = PluginManager.getPlugin(pluginId); if (plugin == null || !ResourceVersions.getInstance().shouldUpdateResourcesOf(plugin)) return; - extractBundledResources(pluginId, ""); - ResourceVersions.getInstance().resourcesUpdated(plugin); + Task.Backgroundable extractResourcesInBackground = + new Task.Backgroundable(null, "Extracting bundled extensions for plugin: " + pluginId.getIdString()) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + try { + extractBundledResources(pluginId, ""); + ApplicationManager.getApplication().invokeLater(() -> ResourceVersions.getInstance().resourcesUpdated(plugin)); + } + catch (IOException ex) { + LOG.warn("Failed to extract bundled extensions for plugin: " + plugin.getName(), ex); + } + } + }; + ProgressManager.getInstance().run(extractResourcesInBackground); } } diff --git a/platform/lang-impl/src/com/intellij/ide/extensionResources/RestoreBundledExtensionsAction.java b/platform/lang-impl/src/com/intellij/ide/extensionResources/RestoreBundledExtensionsAction.java index e83bef678bad..e5a8949da00c 100644 --- a/platform/lang-impl/src/com/intellij/ide/extensionResources/RestoreBundledExtensionsAction.java +++ b/platform/lang-impl/src/com/intellij/ide/extensionResources/RestoreBundledExtensionsAction.java @@ -4,8 +4,12 @@ package com.intellij.ide.extensionResources; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.extensions.PluginId; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; import org.jetbrains.annotations.NotNull; import java.io.IOException; @@ -29,11 +33,20 @@ public class RestoreBundledExtensionsAction extends DumbAwareAction { assert file != null && pluginId != null && path != null; - try { - extensionsRootType.extractBundledResources(pluginId, path); - } - catch (IOException ex) { - ExtensionsRootType.LOG.warn("Failed to extract bundled extensions for " + file.getPath(), ex); - } + Task.Backgroundable extractResourcesInBackground = new Task.Backgroundable( + e.getProject(), + "Extracting bundled extensions for plugin: " + pluginId.getIdString()) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + try { + extensionsRootType.extractBundledResources(pluginId, path); + VirtualFileManager.getInstance().refreshWithoutFileWatcher(true); + } + catch (IOException ex) { + ExtensionsRootType.LOG.warn("Failed to extract bundled extensions for " + file.getPath(), ex); + } + } + }; + ProgressManager.getInstance().run(extractResourcesInBackground); } } diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java index 711641ee0d0b..dfd2499ec4c3 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java @@ -16,6 +16,10 @@ import com.intellij.openapi.progress.util.ProgressIndicatorBase; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.pom.PomTargetPsiElement; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.ArrayUtil; import com.intellij.util.Processor; import com.intellij.util.Processors; @@ -180,7 +184,8 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModelE if (LOG.isDebugEnabled()) { LOG.debug(System.currentTimeMillis() - contributorStarted + "," + contributor + ","); } - } else { + } + else { NavigationItem[] itemsByName = contributor.getItemsByName(name, parameters.getLocalPatternName(), myProject, searchInLibraries); for (NavigationItem item : itemsByName) { canceled.checkCanceled(); @@ -188,6 +193,9 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModelE PluginException.logPluginError(LOG, "null item from contributor " + contributor + " for name " + name, null, contributor.getClass()); continue; } + VirtualFile file = item instanceof PsiElement && !(item instanceof PomTargetPsiElement) + ? PsiUtilCore.getVirtualFile((PsiElement)item) : null; + if (file != null && !parameters.getSearchScope().contains(file)) continue; if (acceptItem(item)) { items.add(item); diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultFileNavigationContributor.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultFileNavigationContributor.java index 2e15d71d6b3d..6e5aa1400628 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultFileNavigationContributor.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultFileNavigationContributor.java @@ -19,49 +19,18 @@ import com.intellij.navigation.ChooseByNameContributorEx; import com.intellij.navigation.NavigationItem; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectUtil; import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.PsiFileSystemItem; import com.intellij.psi.search.FilenameIndex; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.util.ArrayUtil; import com.intellij.util.Processor; -import com.intellij.util.Processors; import com.intellij.util.indexing.FindSymbolParameters; import com.intellij.util.indexing.IdFilter; -import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.List; - public class DefaultFileNavigationContributor implements ChooseByNameContributorEx, DumbAware { private static final Logger LOG = Logger.getInstance(DefaultFileNavigationContributor.class); - @Override - @NotNull - public String[] getNames(Project project, boolean includeNonProjectItems) { - THashSet names = new THashSet<>(1000); - IdFilter filter = IdFilter.getProjectIdFilter(project, includeNonProjectItems); - processNames(s -> { - names.add(s); - return true; - }, FindSymbolParameters.searchScopeFor(project, includeNonProjectItems), filter); - if (LOG.isDebugEnabled()) { - LOG.debug("All names retrieved2:" + names.size()); - } - return ArrayUtil.toStringArray(names); - } - - @Override - @NotNull - public NavigationItem[] getItemsByName(String name, final String pattern, Project project, boolean includeNonProjectItems) { - List result = new ArrayList<>(); - Processor processor = Processors.cancelableCollectProcessor(result); - processElementsWithName(name, processor, FindSymbolParameters.wrap(pattern, project, includeNonProjectItems)); - - return result.isEmpty() ? NavigationItem.EMPTY_NAVIGATION_ITEM_ARRAY : result.toArray(NavigationItem.EMPTY_NAVIGATION_ITEM_ARRAY); - } @Override public void processNames(@NotNull final Processor processor, @NotNull GlobalSearchScope scope, IdFilter filter) { diff --git a/platform/lang-impl/src/com/intellij/navigation/ChooseByNameContributorEx.java b/platform/lang-impl/src/com/intellij/navigation/ChooseByNameContributorEx.java index f6e1f0aceba6..77df680dbd2a 100644 --- a/platform/lang-impl/src/com/intellij/navigation/ChooseByNameContributorEx.java +++ b/platform/lang-impl/src/com/intellij/navigation/ChooseByNameContributorEx.java @@ -15,13 +15,18 @@ */ package com.intellij.navigation; +import com.intellij.openapi.project.Project; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.ArrayUtil; import com.intellij.util.Processor; import com.intellij.util.indexing.FindSymbolParameters; import com.intellij.util.indexing.IdFilter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; + public interface ChooseByNameContributorEx extends ChooseByNameContributor { void processNames(@NotNull Processor processor, @@ -31,4 +36,24 @@ public interface ChooseByNameContributorEx extends ChooseByNameContributor { void processElementsWithName(@NotNull String name, @NotNull Processor processor, @NotNull FindSymbolParameters parameters); + + /** @deprecated Use {@link #processNames(Processor, GlobalSearchScope, IdFilter)} instead */ + @Deprecated + @Override + @NotNull + default String[] getNames(Project project, boolean includeNonProjectItems) { + List result = new ArrayList<>(); + processNames(result::add, FindSymbolParameters.searchScopeFor(project, includeNonProjectItems), null); + return ArrayUtil.toStringArray(result); + } + + /** @deprecated Use {@link #processElementsWithName(String, Processor, FindSymbolParameters)} instead */ + @Deprecated + @Override + @NotNull + default NavigationItem[] getItemsByName(String name, String pattern, Project project, boolean includeNonProjectItems) { + List result = new ArrayList<>(); + processElementsWithName(name, result::add, FindSymbolParameters.simple(project, includeNonProjectItems)); + return result.isEmpty() ? NavigationItem.EMPTY_NAVIGATION_ITEM_ARRAY : result.toArray(NavigationItem.EMPTY_NAVIGATION_ITEM_ARRAY); + } } diff --git a/platform/lang-impl/src/com/intellij/navigation/JBProtocolNavigateCommand.kt b/platform/lang-impl/src/com/intellij/navigation/JBProtocolNavigateCommand.kt index d1e1b6b26241..40dfdd130d7f 100644 --- a/platform/lang-impl/src/com/intellij/navigation/JBProtocolNavigateCommand.kt +++ b/platform/lang-impl/src/com/intellij/navigation/JBProtocolNavigateCommand.kt @@ -25,7 +25,7 @@ import com.intellij.openapi.wm.IdeFocusManager import java.io.File import java.util.regex.Pattern -class JBProtocolNavigateCommand : JBProtocolCommand(NAVIGATE_COMMAND) { +internal class JBProtocolNavigateCommand : JBProtocolCommand(NAVIGATE_COMMAND) { override fun perform(target: String, parameters: Map) { // handles URLs of the following types: diff --git a/platform/lang-impl/src/com/intellij/openapi/util/objectTree/DisposerDebugger.java b/platform/lang-impl/src/com/intellij/openapi/util/objectTree/DisposerDebugger.java index ce3b98b22fc5..839a3d91dab5 100644 --- a/platform/lang-impl/src/com/intellij/openapi/util/objectTree/DisposerDebugger.java +++ b/platform/lang-impl/src/com/intellij/openapi/util/objectTree/DisposerDebugger.java @@ -255,7 +255,7 @@ public class DisposerDebugger implements UiDebuggerExtension, Disposable { } private void queueUpdate() { - UIUtil.invokeLaterIfNeeded(() -> myTreeBuilder.refilter()); + UIUtil.invokeLaterIfNeeded(() -> myTreeBuilder.refilterAsync()); } @Override @@ -275,7 +275,7 @@ public class DisposerDebugger implements UiDebuggerExtension, Disposable { public void clear() { myModificationToFilter = Disposer.getTree().getModification(); - myTreeBuilder.refilter(); + myTreeBuilder.refilterAsync(); } } diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingForwardIndexAccessor.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingForwardIndexAccessor.java index be57c5c9296a..d3cbf854301a 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingForwardIndexAccessor.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingForwardIndexAccessor.java @@ -5,7 +5,6 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.indexing.FileContent; import com.intellij.util.indexing.ID; -import com.intellij.util.indexing.impl.InputData; import com.intellij.util.indexing.impl.InputDataDiffBuilder; import com.intellij.util.indexing.impl.forward.AbstractForwardIndexAccessor; import com.intellij.util.io.DataExternalizer; @@ -20,7 +19,7 @@ import java.io.IOException; import java.util.Collections; import java.util.Map; -class StubUpdatingForwardIndexAccessor extends AbstractForwardIndexAccessor { +class StubUpdatingForwardIndexAccessor extends AbstractForwardIndexAccessor { StubUpdatingForwardIndexAccessor() {super(new DataExternalizer() { private volatile boolean myEnsuredStubElementTypesLoaded; @@ -69,10 +68,10 @@ class StubUpdatingForwardIndexAccessor extends AbstractForwardIndexAccessor data) { - return getIndexedStubs(data.getKeyValues()); + public IndexedStubs convertToDataType(@Nullable Map map, + @Nullable FileContent content) { + return getIndexedStubs(map); } @Override diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MyLookupExpression.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MyLookupExpression.java index 47666922659f..1c3a7597b6d5 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MyLookupExpression.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MyLookupExpression.java @@ -97,11 +97,6 @@ public class MyLookupExpression extends Expression { return new TextResult(myName); } - @Override - public boolean requiresCommittedPSI() { - return false; - } - @Override public String getAdvertisingText() { return myAdvertisementText; diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FindSymbolParameters.java b/platform/lang-impl/src/com/intellij/util/indexing/FindSymbolParameters.java index 7618193430f5..b77176415d46 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FindSymbolParameters.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FindSymbolParameters.java @@ -7,7 +7,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.search.EverythingGlobalScope; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.ProjectScope; -import com.intellij.util.ObjectUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -69,12 +68,12 @@ public class FindSymbolParameters { } public static FindSymbolParameters wrap(@NotNull String pattern, @NotNull Project project, boolean searchInLibraries) { - return new FindSymbolParameters(pattern, pattern, searchScopeFor(project, searchInLibraries), null); + return new FindSymbolParameters(pattern, pattern, searchScopeFor(project, searchInLibraries), + IdFilter.getProjectIdFilter(project, searchInLibraries)); } public static FindSymbolParameters wrap(@NotNull String pattern, @NotNull GlobalSearchScope scope) { - IdFilter idFilter = IdFilter.getProjectIdFilter(ObjectUtils.notNull(scope.getProject()), scope.isSearchInLibraries()); - return new FindSymbolParameters(pattern, pattern, scope, idFilter); + return new FindSymbolParameters(pattern, pattern, scope, null); } public static FindSymbolParameters simple(@NotNull Project project, boolean searchInLibraries) { diff --git a/platform/lang-impl/src/com/intellij/util/indexing/HashIdForwardIndexAccessor.java b/platform/lang-impl/src/com/intellij/util/indexing/HashIdForwardIndexAccessor.java index 0b97d75a0f57..ccad9895626b 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/HashIdForwardIndexAccessor.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/HashIdForwardIndexAccessor.java @@ -1,7 +1,6 @@ // Copyright 2000-2019 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.util.indexing; -import com.intellij.util.indexing.impl.InputData; import com.intellij.util.indexing.impl.InputDataDiffBuilder; import com.intellij.util.indexing.impl.MapInputDataDiffBuilder; import com.intellij.util.indexing.impl.forward.AbstractMapForwardIndexAccessor; @@ -14,8 +13,8 @@ import java.io.IOException; import java.util.Map; class HashIdForwardIndexAccessor - extends AbstractMapForwardIndexAccessor - implements IntForwardIndexAccessor { + extends AbstractMapForwardIndexAccessor + implements IntForwardIndexAccessor { private final UpdatableSnapshotInputMappingIndex mySnapshotInputMappingIndex; HashIdForwardIndexAccessor(@NotNull UpdatableSnapshotInputMappingIndex snapshotInputMappingIndex) { @@ -36,13 +35,12 @@ class HashIdForwardIndexAccessor } @Override - public int serializeIndexedDataToInt(@NotNull InputData data) { - return data == InputData.empty() ? 0 : ((HashedInputData)data).getHashId(); - } - - @Nullable - @Override - public Integer convertToDataType(@NotNull InputData data) { - return serializeIndexedDataToInt(data); + public int convertToInt(@Nullable Map map, @Nullable Input content) { + try { + return mySnapshotInputMappingIndex.getHashId(content); + } + catch (IOException e) { + throw new RuntimeException(e); + } } } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/HashedInputData.java b/platform/lang-impl/src/com/intellij/util/indexing/HashedInputData.java deleted file mode 100644 index 017f4d824268..000000000000 --- a/platform/lang-impl/src/com/intellij/util/indexing/HashedInputData.java +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2000-2019 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.util.indexing; - -import com.intellij.util.indexing.impl.InputData; -import org.jetbrains.annotations.NotNull; - -import java.util.Map; - -public class HashedInputData extends InputData { - private final int myHashId; - - protected HashedInputData(@NotNull Map values, int hashId) { - super(values); - myHashId = hashId; - } - - public int getHashId() { - return myHashId; - } -} diff --git a/platform/lang-impl/src/com/intellij/util/indexing/SharedMapForwardIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/SharedMapForwardIndex.java index 2bad7017ab12..4264e2da4149 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/SharedMapForwardIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/SharedMapForwardIndex.java @@ -26,10 +26,10 @@ public class SharedMapForwardIndex implements ForwardIndex { // only verification purpose @Nullable - private final AbstractForwardIndexAccessor myAccessor; + private final AbstractForwardIndexAccessor myAccessor; public SharedMapForwardIndex(@NotNull IndexExtension extension, - @Nullable AbstractForwardIndexAccessor accessor, + @Nullable AbstractForwardIndexAccessor accessor, @Nullable File verificationIndexStorageFile, boolean verificationIndexHasChunks) throws IOException { myIndexId = (ID)extension.getName(); diff --git a/platform/lang-impl/src/com/intellij/util/indexing/SnapshotInputMappingIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/SnapshotInputMappingIndex.java index 52c3575e4391..a72497ac243a 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/SnapshotInputMappingIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/SnapshotInputMappingIndex.java @@ -1,7 +1,6 @@ // Copyright 2000-2019 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.util.indexing; -import com.intellij.util.indexing.impl.InputData; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -13,5 +12,5 @@ import java.util.Map; @ApiStatus.Experimental public interface SnapshotInputMappingIndex extends Closeable { @Nullable - InputData readData(@NotNull Input content) throws IOException; + Map readData(@NotNull Input content) throws IOException; } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/SnapshotInputMappings.java b/platform/lang-impl/src/com/intellij/util/indexing/SnapshotInputMappings.java index e0ebd2ed7634..2962d50957ce 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/SnapshotInputMappings.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/SnapshotInputMappings.java @@ -13,7 +13,6 @@ import com.intellij.util.CompressionUtil; import com.intellij.util.ExceptionUtil; import com.intellij.util.SystemProperties; import com.intellij.util.indexing.impl.DebugAssertions; -import com.intellij.util.indexing.impl.InputData; import com.intellij.util.indexing.impl.forward.AbstractForwardIndexAccessor; import com.intellij.util.indexing.impl.forward.PersistentMapBasedForwardIndex; import com.intellij.util.io.*; @@ -71,13 +70,12 @@ class SnapshotInputMappings implements UpdatableSnapshotInput @Nullable @Override - public InputData readData(@NotNull Input content) throws IOException { + public Map readData(@NotNull Input content) throws IOException { Map data = null; - int hashId = 0; if (doReadSavedPersistentData) { if (myContents == null || !myContents.isBusyReading() || DebugAssertions.EXTRA_SANITY_CHECKS) { // avoid blocking read, we can calculate index value - hashId = getHashId(content); + int hashId = getHashId(content); ByteArraySequence bytes = readContents(hashId); if (bytes != null) { @@ -98,32 +96,25 @@ class SnapshotInputMappings implements UpdatableSnapshotInput } } } - return data == null ? null : new HashedInputData<>(data, hashId); + return data; } @Override - public InputData putData(@Nullable Input content, @NotNull InputData data) throws IOException { - int hashId; - InputData result; - if (data instanceof HashedInputData) { - hashId = ((HashedInputData)data).getHashId(); - result = data; - } else { - hashId = getHashId(content); - result = hashId == 0 ? InputData.empty() : new HashedInputData<>(data.getKeyValues(), hashId); - } - boolean saved = savePersistentData(data.getKeyValues(), hashId); + public void putData(@Nullable Input content, @NotNull Map data) throws IOException { + int hashId = getHashId(content); + boolean saved = savePersistentData(data, hashId); if (DebugAssertions.EXTRA_SANITY_CHECKS) { if (saved) { try { - myIndexingTrace.put(hashId, getContentDebugData(content) + "," + ExceptionUtil.getThrowableText(new Throwable())); + myIndexingTrace.put(hashId, getContentDebugData(content) + + "," + + ExceptionUtil.getThrowableText(new Throwable())); } catch (IOException ex) { LOG.error(ex); } } } - return result; } @NotNull @@ -132,7 +123,8 @@ class SnapshotInputMappings implements UpdatableSnapshotInput return "[" + content.getFile().getPath() + ";" + content.getFileType().getName() + ";" + content.getCharset() + "]"; } - private int getHashId(@Nullable Input content) throws IOException { + @Override + public int getHashId(@Nullable Input content) throws IOException { return content == null ? 0 : getHashOfContent((FileContent) content); } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/UpdatableSnapshotInputMappingIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/UpdatableSnapshotInputMappingIndex.java index b9a467618a98..26176227537d 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/UpdatableSnapshotInputMappingIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/UpdatableSnapshotInputMappingIndex.java @@ -1,7 +1,6 @@ // Copyright 2000-2019 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.util.indexing; -import com.intellij.util.indexing.impl.InputData; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -14,7 +13,9 @@ public interface UpdatableSnapshotInputMappingIndex extends S @NotNull Map readData(int hashId) throws IOException; - InputData putData(@NotNull Input content, @NotNull InputData data) throws IOException; + void putData(@NotNull Input content, @NotNull Map data) throws IOException; + + int getHashId(@Nullable Input content) throws IOException; void flush() throws IOException; diff --git a/platform/lang-impl/src/com/intellij/util/indexing/VfsAwareMapReduceIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/VfsAwareMapReduceIndex.java index 8045098dd39a..13601fb70ff7 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/VfsAwareMapReduceIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/VfsAwareMapReduceIndex.java @@ -72,7 +72,7 @@ public class VfsAwareMapReduceIndex extends MapReduceIndex extension, @NotNull IndexStorage storage, @Nullable ForwardIndex forwardIndexMap, - @Nullable ForwardIndexAccessor forwardIndexAccessor, + @Nullable ForwardIndexAccessor forwardIndexAccessor, @Nullable SnapshotInputMappingIndex snapshotInputMappings) { super(extension, storage, forwardIndexMap, forwardIndexAccessor, null); SharedIndicesData.registerIndex((ID)myIndexId, extension); @@ -89,8 +89,8 @@ public class VfsAwareMapReduceIndex extends MapReduceIndex mapInput(@Nullable Input content) { - InputData data; + protected Map mapInput(@Nullable Input content) { + Map data; boolean containsSnapshotData = true; if (mySnapshotInputMappings != null && !myInMemoryMode.get() && content != null) { try { @@ -108,7 +108,7 @@ public class VfsAwareMapReduceIndex extends MapReduceIndex extends MapReduceIndex data) throws IOException { + protected void updateForwardIndex(int inputId, @NotNull Map data, @Nullable Object forwardIndexData) throws IOException { if (myInMemoryMode.get()) { synchronized (myInMemoryKeysAndValues) { - myInMemoryKeysAndValues.put(inputId, data.getKeyValues()); + myInMemoryKeysAndValues.put(inputId, data); } } else { - super.updateForwardIndex(inputId, data); + super.updateForwardIndex(inputId, data, forwardIndexData); } } @@ -248,7 +248,7 @@ public class VfsAwareMapReduceIndex extends MapReduceIndex forwardIndexAccessor = (AbstractMapForwardIndexAccessor)getForwardIndexAccessor(); + AbstractMapForwardIndexAccessor forwardIndexAccessor = (AbstractMapForwardIndexAccessor)getForwardIndexAccessor(); return forwardIndexAccessor.convertToInputDataMap(serializedInputData); } // in future we will get rid of forward index for SingleEntryFileBasedIndexExtension @@ -319,7 +319,7 @@ public class VfsAwareMapReduceIndex extends MapReduceIndex ForwardIndexAccessor getForwardIndexAccessor(@NotNull IndexExtension indexExtension) { + private static ForwardIndexAccessor getForwardIndexAccessor(@NotNull IndexExtension indexExtension) { if (!shouldCreateForwardIndex(indexExtension)) return null; return new MapForwardIndexAccessor<>(new InputMapExternalizer<>(indexExtension)); } diff --git a/platform/platform-api/src/com/intellij/ide/ui/search/ConfigurableHit.java b/platform/platform-api/src/com/intellij/ide/ui/search/ConfigurableHit.java deleted file mode 100644 index bf7f22b0e65d..000000000000 --- a/platform/platform-api/src/com/intellij/ide/ui/search/ConfigurableHit.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.ide.ui.search; - -import com.intellij.openapi.options.Configurable; - -import java.util.Set; -import java.util.LinkedHashSet; - -public final class ConfigurableHit { - - private final Set myNameHits = new LinkedHashSet<>(); - private final Set myContentHits = new LinkedHashSet<>(); - - private final Set myNameFullHit = new LinkedHashSet<>(); - - ConfigurableHit() { - } - - public Set getNameHits() { - return myNameHits; - } - - public Set getNameFullHits() { - return myNameFullHit; - } - - public Set getContentHits() { - return myContentHits; - } - - public Set getAll() { - final LinkedHashSet all = new LinkedHashSet<>(myNameHits.size() + myContentHits.size()); - all.addAll(myNameHits); - all.addAll(myContentHits); - return all; - } -} diff --git a/platform/platform-api/src/com/intellij/ide/ui/search/ConfigurableHit.kt b/platform/platform-api/src/com/intellij/ide/ui/search/ConfigurableHit.kt new file mode 100644 index 000000000000..1b4d71d48cc8 --- /dev/null +++ b/platform/platform-api/src/com/intellij/ide/ui/search/ConfigurableHit.kt @@ -0,0 +1,15 @@ +// Copyright 2000-2019 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.search + +import com.intellij.openapi.options.Configurable +import java.util.* + +data class ConfigurableHit(val contentHits: Set, val nameHits: Set, val nameFullHits: Set) { + val all: Set + get() { + val all = LinkedHashSet(nameHits.size + contentHits.size) + all.addAll(nameHits) + all.addAll(contentHits) + return all + } +} diff --git a/platform/platform-api/src/com/intellij/ide/ui/search/SearchableOptionsRegistrar.java b/platform/platform-api/src/com/intellij/ide/ui/search/SearchableOptionsRegistrar.java index 13dee75186b6..070b2b87f933 100644 --- a/platform/platform-api/src/com/intellij/ide/ui/search/SearchableOptionsRegistrar.java +++ b/platform/platform-api/src/com/intellij/ide/ui/search/SearchableOptionsRegistrar.java @@ -1,5 +1,4 @@ -// Copyright 2000-2018 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. - +// Copyright 2000-2019 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.search; import com.intellij.openapi.components.ServiceManager; @@ -11,22 +10,22 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.event.DocumentEvent; -import java.util.Map; +import java.util.List; import java.util.Set; public abstract class SearchableOptionsRegistrar{ public static final String SEARCHABLE_OPTIONS_XML = "searchableOptions.xml"; - public static SearchableOptionsRegistrar getInstance(){ + public static SearchableOptionsRegistrar getInstance() { return ServiceManager.getService(SearchableOptionsRegistrar.class); } @NotNull - public abstract ConfigurableHit getConfigurables(final ConfigurableGroup[] groups, - final DocumentEvent.EventType type, - final Set configurables, - final String option, - final Project project); + public abstract ConfigurableHit getConfigurables(@NotNull List groups, + final DocumentEvent.EventType type, + @Nullable Set configurables, + @NotNull String option, + @Nullable Project project); @Nullable public abstract String getInnerPath(SearchableConfigurable configurable, String option); @@ -39,11 +38,7 @@ public abstract class SearchableOptionsRegistrar{ public abstract Set replaceSynonyms(Set options, SearchableConfigurable configurable); - public abstract Map> findPossibleExtension(@NotNull String prefix, final Project project); - - public abstract Set getProcessedWordsWithoutStemming(@NotNull String text); public abstract Set getProcessedWords(@NotNull String text); - } diff --git a/platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java b/platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java index 9d4fb44dbf63..0a8858503f54 100644 --- a/platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java +++ b/platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java @@ -22,7 +22,6 @@ import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; import com.intellij.ui.ComponentTreeWatcher; import com.intellij.util.ArrayUtil; -import com.intellij.util.containers.JBTreeTraverser; import com.intellij.util.ui.DialogUtil; import com.intellij.util.ui.UIUtil; import org.intellij.lang.annotations.MagicConstant; @@ -183,9 +182,7 @@ public class MnemonicHelper extends ComponentTreeWatcher { private static class MnemonicFixer implements ContainerListener { void addTo(Component component) { - JBTreeTraverser traverser = UIUtil.uiTraverser(component) - .expandAndFilter(o -> !(o instanceof CellRendererPane)); - for (Component c : traverser) { + for (Component c : UIUtil.uiTraverser(component)) { if (c instanceof Container) ((Container)c).addContainerListener(this); if (c instanceof ActionButtonComponent) fixMacMnemonicKeyStroke((JComponent)c, null); MnemonicWrapper.getWrapper(c); @@ -193,9 +190,7 @@ public class MnemonicHelper extends ComponentTreeWatcher { } void removeFrom(Component component) { - JBTreeTraverser traverser = UIUtil.uiTraverser(component) - .expandAndFilter(o -> !(o instanceof CellRendererPane)); - for (Container c : traverser.traverse().filter(Container.class)) { + for (Container c : UIUtil.uiTraverser(component).filter(Container.class)) { c.removeContainerListener(this); } } diff --git a/platform/platform-api/src/com/intellij/openapi/options/ShowSettingsUtil.java b/platform/platform-api/src/com/intellij/openapi/options/ShowSettingsUtil.java index d6e2aaca64d7..9ed57389c36c 100644 --- a/platform/platform-api/src/com/intellij/openapi/options/ShowSettingsUtil.java +++ b/platform/platform-api/src/com/intellij/openapi/options/ShowSettingsUtil.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 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. +// Copyright 2000-2019 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.openapi.options; import com.intellij.openapi.components.ServiceManager; @@ -23,7 +23,7 @@ public abstract class ShowSettingsUtil { public abstract void showSettingsDialog(@Nullable Project project, @NotNull String nameToSelect); - public abstract void showSettingsDialog(@NotNull final Project project, final Configurable toSelect); + public abstract void showSettingsDialog(@NotNull Project project, @Nullable Configurable toSelect); public abstract void showSettingsDialog(@Nullable Project project, @NotNull Class configurableClass, @@ -47,13 +47,6 @@ public abstract class ShowSettingsUtil { public abstract boolean editConfigurable(Component parent, String dimensionServiceKey, Configurable configurable); - /** - * @deprecated create a new instance of configurable instead - * to remove in IDEA 15 - */ - @Deprecated - public abstract T findProjectConfigurable(Project project, Class confClass); - public static String getSettingsMenuName() { return SystemInfo.isMac ? "Preferences" : "Settings"; } diff --git a/platform/platform-api/src/com/intellij/openapi/ui/TestDialog.java b/platform/platform-api/src/com/intellij/openapi/ui/TestDialog.java index 73b0999833eb..b3a4ce413b09 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/TestDialog.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/TestDialog.java @@ -1,25 +1,14 @@ // Copyright 2000-2018 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.openapi.ui; -public interface TestDialog { - TestDialog DEFAULT = new TestDialog() { - @Override - public int show(String message) { - throw new RuntimeException(message); - } - }; - TestDialog OK = new TestDialog() { - @Override - public int show(String message) { - return 0; - } - }; - TestDialog NO = new TestDialog() { - @Override - public int show(String message) { - return Messages.NO; - } - }; +import org.jetbrains.annotations.NotNull; - int show(String message); +public interface TestDialog { + TestDialog DEFAULT = message -> { + throw new RuntimeException(message); + }; + TestDialog OK = __ -> Messages.OK; + TestDialog NO = __ -> Messages.NO; + + int show(@NotNull String message); } diff --git a/platform/platform-api/src/com/intellij/ui/speedSearch/ElementFilter.java b/platform/platform-api/src/com/intellij/ui/speedSearch/ElementFilter.java index 4bc4961937fe..60c5e681a2bc 100644 --- a/platform/platform-api/src/com/intellij/ui/speedSearch/ElementFilter.java +++ b/platform/platform-api/src/com/intellij/ui/speedSearch/ElementFilter.java @@ -1,24 +1,13 @@ -/* - * 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-2019 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.ui.speedSearch; import com.intellij.openapi.Disposable; -import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.concurrency.Promise; +import org.jetbrains.concurrency.Promises; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; @@ -27,7 +16,8 @@ public interface ElementFilter { boolean shouldBeShowing(T value); interface Active extends ElementFilter { - ActionCallback fireUpdate(@Nullable final T preferredSelection, final boolean adjustSelection, final boolean now); + @NotNull + Promise fireUpdate(@Nullable final T preferredSelection, final boolean adjustSelection, final boolean now); void addListener(Listener listener, Disposable parent); @@ -35,14 +25,9 @@ public interface ElementFilter { Set> myListeners = new CopyOnWriteArraySet<>(); @Override - public ActionCallback fireUpdate(@Nullable final T preferredSelection, final boolean adjustSelection, final boolean now) { - final ActionCallback result = new ActionCallback(myListeners.size()); - - for (final Listener myListener : myListeners) { - myListener.update(preferredSelection, adjustSelection, now).doWhenProcessed(result.createSetDoneRunnable()); - } - - return result; + @NotNull + public Promise fireUpdate(@Nullable T preferredSelection, boolean adjustSelection, boolean now) { + return Promises.all(ContainerUtil.map(myListeners, listener -> listener.update(preferredSelection, adjustSelection, now))); } @Override @@ -59,6 +44,7 @@ public interface ElementFilter { } interface Listener { - ActionCallback update(@Nullable final T preferredSelection, final boolean adjustSelection, final boolean now); + @NotNull + Promise update(@Nullable final T preferredSelection, final boolean adjustSelection, final boolean now); } } \ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/ui/tabs/newImpl/TabLabel.java b/platform/platform-api/src/com/intellij/ui/tabs/newImpl/TabLabel.java index a22ad2262d3c..cd1aaeeb322f 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/newImpl/TabLabel.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/newImpl/TabLabel.java @@ -182,14 +182,20 @@ public class TabLabel extends JPanel implements Accessible { @Override public Insets getInsets() { Insets insets = super.getInsets(); + boolean hasCloseButtonOnTheLeft = false; if (myTabs.isEditorTabs() && UISettings.getShadowInstance().getShowCloseButton() && hasIcons()) { if (UISettings.getShadowInstance().getCloseTabButtonOnTheRight()) { insets.right -= JBUI.scale(4); } else { + hasCloseButtonOnTheLeft = true; insets.left -= JBUI.scale(4); } } + // We reserve extra space inside file icon for (*) marker but mostly this space looks like wasted one + if (myTabs.isEditorTabs() && UISettings.getShadowInstance().getMarkModifiedTabsWithAsterisk() && !hasCloseButtonOnTheLeft) { + insets.left -= JBUI.scale(7); + } return insets; } diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeBuilder.java b/platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeBuilder.java index 8ae2e5bfb541..952d771ca137 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeBuilder.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeBuilder.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2009 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-2019 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.ui.treeStructure.filtered; import com.intellij.ide.util.treeView.AbstractTreeBuilder; @@ -28,7 +14,11 @@ import com.intellij.ui.treeStructure.Tree; import com.intellij.util.ui.tree.TreeUtil; import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.concurrency.AsyncPromise; +import org.jetbrains.concurrency.Promise; +import org.jetbrains.concurrency.Promises; import javax.swing.*; import javax.swing.event.TreeSelectionEvent; @@ -60,8 +50,9 @@ public class FilteringTreeBuilder extends AbstractTreeBuilder { if (filter instanceof ElementFilter.Active) { ((ElementFilter.Active)filter).addListener(new ElementFilter.Listener() { + @NotNull @Override - public ActionCallback update(final Object preferredSelection, final boolean adjustSelection, final boolean now) { + public Promise update(final Object preferredSelection, final boolean adjustSelection, final boolean now) { return refilter(preferredSelection, adjustSelection, now); } }, this); @@ -116,50 +107,65 @@ public class FilteringTreeBuilder extends AbstractTreeBuilder { return true; } + @NotNull + @Deprecated public ActionCallback refilter() { + //noinspection unchecked + return Promises.toActionCallback((Promise)refilter(null, true, false)); + } + + @SuppressWarnings("UnusedReturnValue") + @NotNull + public Promise refilterAsync() { return refilter(null, true, false); } - public ActionCallback refilter(@Nullable final Object preferredSelection, final boolean adjustSelection, final boolean now) { + @NotNull + public Promise refilter(@Nullable final Object preferredSelection, final boolean adjustSelection, final boolean now) { if (myRefilterQueue != null) { myRefilterQueue.cancelAllUpdates(); } - final ActionCallback callback = new ActionCallback(); + + AsyncPromise result = new AsyncPromise<>(); final Runnable afterCancelUpdate = new Runnable() { @Override public void run() { if (myRefilterQueue == null || now) { - refilterNow(preferredSelection, adjustSelection).doWhenDone(callback.createSetDoneRunnable()); + refilterNow(preferredSelection, adjustSelection) + .onSuccess(o -> result.setResult(null)); } else { myRefilterQueue.queue(new Update(this) { @Override public void run() { - refilterNow(preferredSelection, adjustSelection).notifyWhenDone(callback); + refilterNow(preferredSelection, adjustSelection); } @Override public void setRejected() { super.setRejected(); - callback.setDone(); + result.setResult(null); } }); } } }; + if (!isDisposed()) { if (!ApplicationManager.getApplication().isUnitTestMode()) { getUi().cancelUpdate().doWhenProcessed(afterCancelUpdate); - } else { + } + else { afterCancelUpdate.run(); } } - return callback; + return result; } - protected ActionCallback refilterNow(final Object preferredSelection, final boolean adjustSelection) { + @NotNull + protected Promise refilterNow(Object preferredSelection, boolean adjustSelection) { final ActionCallback selectionDone = new ActionCallback(); getFilteredStructure().refilter(); @@ -191,28 +197,32 @@ public class FilteringTreeBuilder extends AbstractTreeBuilder { }; if (!ApplicationManager.getApplication().isUnitTestMode()) { queueUpdate().doWhenProcessed(selectionRunnable); - } else { + } + else { selectionRunnable.run(); } - final ActionCallback result = new ActionCallback(); - - selectionDone.doWhenDone(new Runnable() { + AsyncPromise result = new AsyncPromise<>(); + selectionDone + .doWhenDone(new Runnable() { @Override public void run() { if (!ApplicationManager.getApplication().isUnitTestMode()) { scrollSelectionToVisible(new Runnable() { @Override public void run() { - getReady(this).notify(result); + getReady(this) + .doWhenDone(() -> result.setResult(null)) + .doWhenRejected(s -> result.setError(s)); } }, false); - } else { - result.setDone(); + } + else { + result.setResult(null); } } - }).notifyWhenRejected(result); - + }) + .doWhenRejected(() -> result.cancel(true)); return result; } diff --git a/platform/platform-impl/src/com/intellij/diagnostic/IdeaFreezeReporter.java b/platform/platform-impl/src/com/intellij/diagnostic/IdeaFreezeReporter.java index 8433e6538716..f468f5397e7f 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/IdeaFreezeReporter.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/IdeaFreezeReporter.java @@ -50,7 +50,7 @@ public class IdeaFreezeReporter { if (Registry.is("performance.watcher.freeze.report") && lengthInSeconds > FREEZE_THRESHOLD && // check that we have at least half of the dumps required - myCurrentDumps.size() >= lengthInSeconds * 500 / Registry.intValue("performance.watcher.unresponsive.interval.ms") && + myCurrentDumps.size() >= Math.max(3, lengthInSeconds * 500 / Registry.intValue("performance.watcher.unresponsive.interval.ms")) && !ContainerUtil.isEmpty(myStacktraceCommonPart) && !DebugAttachDetector.isAttached()) { int size = Math.min(myCurrentDumps.size(), 20); // report up to 20 dumps diff --git a/platform/platform-impl/src/com/intellij/ide/IdePopupManager.java b/platform/platform-impl/src/com/intellij/ide/IdePopupManager.java index 30d1e03e8d52..d14fa8820c49 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdePopupManager.java +++ b/platform/platform-impl/src/com/intellij/ide/IdePopupManager.java @@ -16,8 +16,11 @@ package com.intellij.ide; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher; import com.intellij.openapi.ui.popup.IdePopupEventDispatcher; import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.wm.ex.IdeFrameEx; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; @@ -25,6 +28,7 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; +import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.WindowEvent; @@ -35,6 +39,7 @@ public final class IdePopupManager implements IdeEventQueue.EventDispatcher { private static final Logger LOG = Logger.getInstance("com.intellij.ide.IdePopupManager"); private final List myDispatchStack = ContainerUtil.createLockFreeCopyOnWriteList(); + private boolean myIgnoreNextKeyTypedEvent; boolean isPopupActive() { for (IdePopupEventDispatcher each : myDispatchStack) { @@ -80,6 +85,24 @@ public final class IdePopupManager implements IdeEventQueue.EventDispatcher { closeAllPopups(); } } + else if (e instanceof KeyEvent) { + // the following is copied from IdeKeyEventDispatcher + KeyEvent keyEvent = (KeyEvent)e; + Object source = keyEvent.getSource(); + if (myIgnoreNextKeyTypedEvent) { + if (KeyEvent.KEY_TYPED == e.getID()) return true; + myIgnoreNextKeyTypedEvent = false; + } + else if (SystemInfo.isMac && InputEvent.ALT_DOWN_MASK == keyEvent.getModifiersEx() && + Registry.is("ide.mac.alt.mnemonic.without.ctrl") && source instanceof Component) { + // the myIgnoreNextKeyTypedEvent changes event processing to support Alt-based mnemonics on Mac only + if ((KeyEvent.KEY_TYPED == e.getID() && !IdeEventQueue.getInstance().isInputMethodEnabled()) || + IdeKeyEventDispatcher.hasMnemonicInWindow((Component)source, keyEvent)) { + myIgnoreNextKeyTypedEvent = true; + return false; + } + } + } if (e instanceof KeyEvent || e instanceof MouseEvent) { for (int i = myDispatchStack.size() - 1; (i >= 0 && i < myDispatchStack.size()); i--) { diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ProjectViewEditSourceAction.kt b/platform/platform-impl/src/com/intellij/ide/actions/ProjectViewEditSourceAction.kt new file mode 100644 index 000000000000..23b2571e0f03 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/actions/ProjectViewEditSourceAction.kt @@ -0,0 +1,23 @@ +// Copyright 2000-2019 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.actions + +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.fileEditor.OpenFileDescriptor +import com.intellij.pom.NavigatableWithText + +/** + * @author yole + */ +class ProjectViewEditSourceAction : BaseNavigateToSourceAction(true) { + override fun update(e: AnActionEvent) { + super.update(e) + if (!e.presentation.isVisible || !e.presentation.isEnabled) return + val navigatables = getNavigatables(e.dataContext) + e.presentation.isEnabledAndVisible = + navigatables != null && + navigatables + .filterIsInstance() + .mapNotNull { it.getNavigateActionText(true) } + .isNotEmpty() + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java index 35a2f3295ab6..9366a085fc7b 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java @@ -22,6 +22,8 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.function.Consumer; import java.util.function.Predicate; @@ -38,10 +40,8 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil { } @NotNull - public static DialogWrapper getDialog(@Nullable Project project, @NotNull ConfigurableGroup[] groups, @Nullable Configurable toSelect) { - project = getProject(project); - final ConfigurableGroup[] filteredGroups = filterEmptyGroups(groups); - return SettingsDialogFactory.getInstance().create(project, filteredGroups, toSelect, null); + public static DialogWrapper getDialog(@Nullable Project project, @NotNull List groups, @Nullable Configurable toSelect) { + return SettingsDialogFactory.getInstance().create(getProject(project), filterEmptyGroups(groups), toSelect, null); } /** @@ -81,7 +81,7 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil { @Override public void showSettingsDialog(@NotNull Project project, @NotNull ConfigurableGroup... group) { try { - getDialog(project, group, null).show(); + getDialog(project, Arrays.asList(group), null).show(); } catch (Exception e) { LOG.error(e); @@ -125,50 +125,53 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil { additionalConfiguration.accept(config); } - getDialog(project, groups, config).show(); + getDialog(project, Arrays.asList(groups), config).show(); } @Override - public void showSettingsDialog(@Nullable final Project project, @NotNull final String nameToSelect) { - ConfigurableGroup[] groups = getConfigurableGroups(project, true); - Project actualProject = getProject(project); - - groups = filterEmptyGroups(groups); - getDialog(actualProject, groups, findPreselectedByDisplayName(nameToSelect, groups)).show(); + public void showSettingsDialog(@Nullable Project project, @NotNull String nameToSelect) { + ConfigurableGroup group = ConfigurableExtensionPointUtil.getConfigurableGroup(project, /* withIdeSettings = */ true); + List groups = group.getConfigurables().length == 0 ? Collections.emptyList() : Collections.singletonList(group); + getDialog(project, groups, findPreselectedByDisplayName(nameToSelect, groups)).show(); } @Nullable - private static Configurable findPreselectedByDisplayName(final String preselectedConfigurableDisplayName, ConfigurableGroup[] groups) { - final List all = SearchUtil.expand(groups); - for (Configurable each : all) { - if (preselectedConfigurableDisplayName.equals(each.getDisplayName())) return each; + private static Configurable findPreselectedByDisplayName(@NotNull String preselectedConfigurableDisplayName, @NotNull List groups) { + for (ConfigurableGroup eachGroup : groups) { + for (Configurable configurable : SearchUtil.expandGroup(eachGroup)) { + if (preselectedConfigurableDisplayName.equals(configurable.getDisplayName())) { + return configurable; + } + } } return null; } - public static void showSettingsDialog(@Nullable Project project, final String id2Select, final String filter) { - ConfigurableGroup[] group = getConfigurableGroups(project, true); + public static void showSettingsDialog(@Nullable Project project, @Nullable String idToSelect, final String filter) { + ConfigurableGroup group = ConfigurableExtensionPointUtil.getConfigurableGroup(project, /* withIdeSettings = */ true); + if (group.getConfigurables().length == 0) { + group = null; + } - group = filterEmptyGroups(group); - final Configurable configurable2Select = id2Select == null ? null : new ConfigurableVisitor.ByID(id2Select).find(group); - - SettingsDialogFactory.getInstance().create(getProject(project), group, configurable2Select, filter).show(); + Configurable configurableToSelect = idToSelect == null ? null : new ConfigurableVisitor.ByID(idToSelect).find(group); + SettingsDialogFactory.getInstance().create(getProject(project), Collections.singletonList(group), configurableToSelect, filter).show(); } @Override - public void showSettingsDialog(@NotNull final Project project, final Configurable toSelect) { - getDialog(project, getConfigurableGroups(project, true), toSelect).show(); + public void showSettingsDialog(@NotNull Project project, @Nullable Configurable toSelect) { + List groups = Collections.singletonList(ConfigurableExtensionPointUtil.getConfigurableGroup(project, /* withIdeSettings = */ true)); + getDialog(project, groups, toSelect).show(); } @NotNull - private static ConfigurableGroup[] filterEmptyGroups(@NotNull final ConfigurableGroup[] group) { + private static List filterEmptyGroups(@NotNull List group) { List groups = new ArrayList<>(); for (ConfigurableGroup g : group) { if (g.getConfigurables().length > 0) { groups.add(g); } } - return groups.toArray(new ConfigurableGroup[0]); + return groups; } @Override @@ -176,11 +179,6 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil { return editConfigurable(project, createDimensionKey(configurable), configurable); } - @Override - public T findProjectConfigurable(final Project project, final Class confClass) { - return ConfigurableExtensionPointUtil.findProjectConfigurable(project, confClass); - } - @Override public boolean editConfigurable(Project project, String dimensionServiceKey, @NotNull Configurable configurable) { return editConfigurable(project, dimensionServiceKey, configurable, isWorthToShowApplyButton(configurable)); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/ConfigurableOptionsTopHitProvider.java b/platform/platform-impl/src/com/intellij/ide/ui/ConfigurableOptionsTopHitProvider.java index 56bae505a2cd..20e33946a379 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/ConfigurableOptionsTopHitProvider.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/ConfigurableOptionsTopHitProvider.java @@ -3,6 +3,7 @@ package com.intellij.ide.ui; import com.intellij.ide.ui.search.BooleanOptionDescription; import com.intellij.ide.ui.search.OptionDescription; +import com.intellij.ide.ui.search.SearchUtil; import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.Configurable; @@ -10,6 +11,7 @@ import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.ex.ConfigurableVisitor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -17,6 +19,7 @@ import javax.swing.*; import javax.swing.border.Border; import javax.swing.border.TitledBorder; import java.awt.*; +import java.util.List; import java.util.*; /** @@ -64,7 +67,12 @@ public abstract class ConfigurableOptionsTopHitProvider extends OptionsTopHitPro * @return an option prefix or {@code null} to ignore this option */ protected String getOptionName(JCheckBox checkbox) { - String name = StringUtil.stripHtml(checkbox.getText(), false); + return getOptionName(checkbox.getText()); + } + + @Nullable + protected String getOptionName(@NotNull String text) { + String name = StringUtil.stripHtml(text, false); if (StringUtil.isEmpty(name)) { return null; } @@ -95,6 +103,21 @@ public abstract class ConfigurableOptionsTopHitProvider extends OptionsTopHitPro options.add(new Option(configurable, checkbox, option)); } } + else if (component instanceof JComboBox) { + JComboBox combo = (JComboBox)component; + if (!combo.isEditable()) { + JLabel label = UIUtil.uiChildren(combo.getParent()).takeWhile(o -> o != combo).filter(JLabel.class).last(); + String baseName = label == null ? null : getOptionName(label.getText()); + if (baseName != null) { + String optionName = (baseName + " ").replace(": ", " | "); + List list = SearchUtil.getItemsFromComboBox(combo); + for (int i = 0, len = list.size(); i < len; i++) { + String s = optionName + list.get(i); + options.add(new Option2(configurable, combo, s, i)); + } + } + } + } else if (component instanceof Container) { Container container = (Container)component; for (int i = 0; i < container.getComponentCount(); i++) { @@ -129,10 +152,10 @@ public abstract class ConfigurableOptionsTopHitProvider extends OptionsTopHitPro } private static final class Option extends BooleanOptionDescription implements Disposable { - private final Configurable myConfigurable; - private final JCheckBox myCheckBox; + final Configurable myConfigurable; + final JCheckBox myCheckBox; - private Option(Configurable configurable, JCheckBox checkbox, String option) { + Option(Configurable configurable, JCheckBox checkbox, String option) { super(option, ConfigurableVisitor.ByID.getID(configurable)); myConfigurable = configurable; myCheckBox = checkbox; @@ -161,4 +184,42 @@ public abstract class ConfigurableOptionsTopHitProvider extends OptionsTopHitPro } } } + + private static final class Option2 extends BooleanOptionDescription implements Disposable { + final Configurable myConfigurable; + final JComboBox myComboBox; + final int myIndex; + final int myPrevIndex; + + Option2(Configurable configurable, JComboBox comboBox, String option, int index) { + super(option, ConfigurableVisitor.ByID.getID(configurable)); + myConfigurable = configurable; + myComboBox = comboBox; + myIndex = index; + myPrevIndex = myComboBox.getSelectedIndex(); + } + + @Override + public void dispose() { + myConfigurable.disposeUIResources(); + } + + @Override + public boolean isOptionEnabled() { + return myComboBox.getSelectedIndex() == myIndex; + } + + @Override + public void setOptionState(boolean selected) { + if (selected != (myComboBox.getSelectedIndex() == myIndex)) { + myComboBox.setSelectedIndex(selected ? myIndex : myPrevIndex); + try { + myConfigurable.apply(); + } + catch (ConfigurationException exception) { + LOG.debug(exception); + } + } + } + } } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/search/SearchUtil.java b/platform/platform-impl/src/com/intellij/ide/ui/search/SearchUtil.java index 0edf0a2d5d8c..305dc51a8a10 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/search/SearchUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/search/SearchUtil.java @@ -12,6 +12,7 @@ import com.intellij.ui.JBColor; import com.intellij.ui.SimpleColoredComponent; import com.intellij.ui.SimpleTextAttributes; import com.intellij.ui.TabbedPaneWrapper; +import com.intellij.util.CollectConsumer; import com.intellij.util.ReflectionUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Nls; @@ -25,6 +26,7 @@ import javax.swing.plaf.basic.BasicComboPopup; import java.awt.*; import java.util.List; import java.util.*; +import java.util.function.Consumer; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -205,7 +207,7 @@ public class SearchUtil { } @NotNull - private static List getItemsFromComboBox(@NotNull JComboBox comboBox) { + public static List getItemsFromComboBox(@NotNull JComboBox comboBox) { ListCellRenderer renderer = comboBox.getRenderer(); if (renderer == null) renderer = new DefaultListCellRenderer(); @@ -553,25 +555,37 @@ public class SearchUtil { return withoutQuoted + " " + filter.substring(beg); } - public static List expand(ConfigurableGroup[] groups) { - final ArrayList result = new ArrayList<>(); - for (ConfigurableGroup eachGroup : groups) { - result.addAll(expandGroup(eachGroup)); + @NotNull + public static List expand(@NotNull ConfigurableGroup[] groups) { + List result = new ArrayList<>(); + CollectConsumer consumer = new CollectConsumer<>(result); + for (ConfigurableGroup group : groups) { + processExpandedGroups(group, consumer); } return result; } - public static List expandGroup(final ConfigurableGroup group) { - final Configurable[] configurables = group.getConfigurables(); + @NotNull + public static List expandGroup(@NotNull ConfigurableGroup group) { + List result = new ArrayList<>(); + processExpandedGroups(group, new CollectConsumer<>(result)); + return result; + } + + public static void processExpandedGroups(@NotNull ConfigurableGroup group, @NotNull Consumer consumer) { + Configurable[] configurables = group.getConfigurables(); List result = new ArrayList<>(); ContainerUtil.addAll(result, configurables); for (Configurable each : configurables) { addChildren(each, result); } - //noinspection deprecation - return ContainerUtil.filter(result, configurable -> !(configurable instanceof SearchableConfigurable.Parent) || - ((SearchableConfigurable.Parent)configurable).isVisible()); + for (Configurable configurable : result) { + //noinspection deprecation + if (!(configurable instanceof SearchableConfigurable.Parent) || ((SearchableConfigurable.Parent)configurable).isVisible()) { + consumer.accept(configurable); + } + } } private static void addChildren(Configurable configurable, List list) { @@ -585,7 +599,6 @@ public class SearchUtil { } private static final class SearchableConfigurableAdapter implements SearchableConfigurable { - private final SearchableConfigurable myOriginal; private final UnnamedConfigurable myDelegate; diff --git a/platform/platform-impl/src/com/intellij/ide/ui/search/SearchableOptionsRegistrarImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/search/SearchableOptionsRegistrarImpl.java index 728f15111ed2..52756f13c4ce 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/search/SearchableOptionsRegistrarImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/search/SearchableOptionsRegistrarImpl.java @@ -1,13 +1,11 @@ -// Copyright 2000-2018 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. +// Copyright 2000-2019 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.search; -import com.intellij.application.options.CodeStyle; import com.intellij.codeStyle.CodeStyleFacade; import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.ide.plugins.PluginManagerConfigurable; import com.intellij.ide.plugins.PluginManagerCore; -import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ex.ApplicationInfoEx; import com.intellij.openapi.diagnostic.Logger; @@ -21,6 +19,7 @@ import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ArrayUtil; +import com.intellij.util.CollectConsumer; import com.intellij.util.ObjectUtils; import com.intellij.util.ResourceUtil; import com.intellij.util.containers.ContainerUtil; @@ -69,7 +68,6 @@ public class SearchableOptionsRegistrarImpl extends SearchableOptionsRegistrar { }; private static final Logger LOG = Logger.getInstance("#com.intellij.ide.ui.search.SearchableOptionsRegistrarImpl"); - private static final int LOAD_FACTOR = 20; @NonNls private static final Pattern REG_EXP = Pattern.compile("[\\W&&[^-]]+"); @@ -289,66 +287,71 @@ public class SearchableOptionsRegistrarImpl extends SearchableOptionsRegistrar { myStorage.put(ByteArrayCharSequence.convertToBytesIfPossible(option), configs); } - @SuppressWarnings("StringToUpperCaseOrToLowerCaseWithoutLocale") @Override @NotNull - public ConfigurableHit getConfigurables(ConfigurableGroup[] groups, + public ConfigurableHit getConfigurables(@NotNull List groups, final DocumentEvent.EventType type, - Set configurables, - String option, - Project project) { - - final ConfigurableHit hits = new ConfigurableHit(); - final Set contentHits = hits.getContentHits(); - - Set options = getProcessedWordsWithoutStemming(option); + @Nullable Set configurables, + @NotNull String option, + @Nullable Project project) { + Set contentHits = new LinkedHashSet<>(); if (configurables == null) { + CollectConsumer consumer = new CollectConsumer<>(contentHits); for (ConfigurableGroup group : groups) { - contentHits.addAll(SearchUtil.expandGroup(group)); + SearchUtil.processExpandedGroups(group, consumer); } } else { contentHits.addAll(configurables); } - String optionToCheck = option.trim().toLowerCase(); + String optionToCheck = option.trim().toLowerCase(Locale.ENGLISH); + Set options = getProcessedWordsWithoutStemming(optionToCheck); + + Set nameHits = new LinkedHashSet<>(); + Set nameFullHits = new LinkedHashSet<>(); + for (Configurable each : contentHits) { if (each.getDisplayName() == null) continue; - final String displayName = each.getDisplayName().toLowerCase(); + final String displayName = each.getDisplayName().toLowerCase(Locale.ENGLISH); final List allWords = StringUtil.getWordsIn(displayName); if (displayName.contains(optionToCheck)) { - hits.getNameFullHits().add(each); - hits.getNameHits().add(each); + nameFullHits.add(each); + nameHits.add(each); } for (String eachWord : allWords) { if (eachWord.startsWith(optionToCheck)) { - hits.getNameHits().add(each); + nameHits.add(each); break; } } if (options.isEmpty()) { - hits.getNameHits().add(each); - hits.getNameFullHits().add(each); + nameHits.add(each); + nameFullHits.add(each); } } - final Set currentConfigurables = new HashSet<>(contentHits); - if (options.isEmpty()) { //operate with substring + final Set currentConfigurables = type == DocumentEvent.EventType.CHANGE ? new THashSet<>(contentHits) : null; + // operate with substring + if (options.isEmpty()) { String[] components = REG_EXP.split(optionToCheck); if (components.length > 0) { Collections.addAll(options, components); - } else { + } + else { options.add(option); } } + Set helpIds = null; for (String opt : options) { final Set optionIds = getAcceptableDescriptions(opt); if (optionIds == null) { contentHits.clear(); - return hits; + return new ConfigurableHit(contentHits, nameHits, nameFullHits); } + final Set ids = new HashSet<>(); for (OptionDescription id : optionIds) { ids.add(id.getConfigurableId()); @@ -358,6 +361,7 @@ public class SearchableOptionsRegistrarImpl extends SearchableOptionsRegistrar { } helpIds.retainAll(ids); } + if (helpIds != null) { for (Iterator it = contentHits.iterator(); it.hasNext();) { Configurable configurable = it.next(); @@ -370,13 +374,13 @@ public class SearchableOptionsRegistrarImpl extends SearchableOptionsRegistrar { } } } - if (currentConfigurables.equals(contentHits) && !(configurables == null && type == DocumentEvent.EventType.CHANGE)) { + + if (type == DocumentEvent.EventType.CHANGE && configurables != null && currentConfigurables.equals(contentHits)) { return getConfigurables(groups, DocumentEvent.EventType.CHANGE, null, option, project); } - return hits; + return new ConfigurableHit(contentHits, nameHits, nameFullHits); } - @Nullable public synchronized Set getAcceptableDescriptions(final String prefix) { if (prefix == null) return null; @@ -458,43 +462,6 @@ public class SearchableOptionsRegistrarImpl extends SearchableOptionsRegistrar { return myHighlightOption2Synonym.get(Couple.of(option, configurable.getId())); } - @Override - public Map> findPossibleExtension(@NotNull String prefix, final Project project) { - loadHugeFilesIfNecessary(); - final boolean perProject = CodeStyle.usesOwnSettings(project); - final Map> result = new THashMap<>(); - int count = 0; - final Set prefixes = getProcessedWordsWithoutStemming(prefix); - for (String opt : prefixes) { - Set configs = getAcceptableDescriptions(opt); - if (configs == null) continue; - for (OptionDescription description : configs) { - String groupName = description.getGroupName(); - if (perProject) { - if (Comparing.strEqual(groupName, ApplicationBundle.message("title.global.code.style"))) { - groupName = ApplicationBundle.message("title.project.code.style"); - } - } - else { - if (Comparing.strEqual(groupName, ApplicationBundle.message("title.project.code.style"))) { - groupName = ApplicationBundle.message("title.global.code.style"); - } - } - Set foundHits = result.get(groupName); - if (foundHits == null) { - foundHits = new THashSet<>(); - result.put(groupName, foundHits); - } - foundHits.add(description.getHit()); - count++; - } - } - if (count > LOAD_FACTOR) { - result.clear(); - } - return result; - } - @Override public void addOption(String option, String path, final String hit, final String configurableId, final String configurableDisplayName) { putOptionWithHelpId(option, configurableId, configurableDisplayName, hit, path); @@ -502,13 +469,17 @@ public class SearchableOptionsRegistrarImpl extends SearchableOptionsRegistrar { @Override public Set getProcessedWordsWithoutStemming(@NotNull String text) { - Set result = new HashSet<>(); - @NonNls final String toLowerCase = text.toLowerCase(); - final String[] options = REG_EXP.split(toLowerCase); - for (String opt : options) { - if (isStopWord(opt)) continue; - final String processed = PorterStemmerUtil.stem(opt); - if (isStopWord(processed)) continue; + Set result = new THashSet<>(); + for (String opt : REG_EXP.split(text.toLowerCase(Locale.ENGLISH))) { + if (isStopWord(opt)) { + continue; + } + + String processed = PorterStemmerUtil.stem(opt); + if (isStopWord(processed)) { + continue; + } + result.add(opt); } return result; diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/eventLog/validator/SensitiveDataValidator.java b/platform/platform-impl/src/com/intellij/internal/statistic/eventLog/validator/SensitiveDataValidator.java index e7f0728f4c39..0badb50a5a3c 100644 --- a/platform/platform-impl/src/com/intellij/internal/statistic/eventLog/validator/SensitiveDataValidator.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/eventLog/validator/SensitiveDataValidator.java @@ -3,73 +3,116 @@ package com.intellij.internal.statistic.eventLog.validator; import com.intellij.internal.statistic.eventLog.EventLogConfiguration; import com.intellij.internal.statistic.eventLog.EventLogGroup; +import com.intellij.internal.statistic.eventLog.FeatureUsageData; import com.intellij.internal.statistic.eventLog.validator.persistence.FUSWhiteListPersistence; import com.intellij.internal.statistic.eventLog.validator.rules.EventContext; import com.intellij.internal.statistic.eventLog.validator.rules.beans.WhiteListGroupRules; import com.intellij.internal.statistic.service.fus.FUStatisticsWhiteListGroupsService; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.BuildNumber; import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.concurrency.Semaphore; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; -import static com.intellij.internal.statistic.eventLog.validator.ValidationResultType.ACCEPTED; +import static com.intellij.internal.statistic.eventLog.validator.ValidationResultType.*; public class SensitiveDataValidator { - private static NotNullLazyValue me = NotNullLazyValue.createValue(() -> new SensitiveDataValidator()); + private static final NotNullLazyValue me = NotNullLazyValue.createValue( + () -> ApplicationManager.getApplication().isUnitTestMode() ? new BlindSensitiveDataValidator() : new SensitiveDataValidator() + ); + + private final Semaphore mySemaphore; + private final AtomicBoolean isWhiteListInitialized; public static SensitiveDataValidator getInstance() { return me.getValue(); } - protected SensitiveDataValidator() {} + protected SensitiveDataValidator() { + mySemaphore = new Semaphore(); + isWhiteListInitialized = new AtomicBoolean(false); + updateValidators(FUSWhiteListPersistence.getCachedWhiteList()); + } - protected final Map eventsValidators = ContainerUtil.createConcurrentSoftMap(); + protected final Map eventsValidators = ContainerUtil.newConcurrentMap(); public String guaranteeCorrectEventId(@NotNull EventLogGroup group, @NotNull EventContext context) { + if (isUnreachableWhitelist()) return UNREACHABLE_WHITELIST.getDescription(); + ValidationResultType validationResultType = validateEvent(group, context); return validationResultType == ACCEPTED ? context.eventId : validationResultType.getDescription(); } public Map guaranteeCorrectEventData(@NotNull EventLogGroup group, @NotNull EventContext context) { WhiteListGroupRules whiteListRule = eventsValidators.get(group.getId()); - if (whiteListRule == null || !whiteListRule.areEventDataRulesDefined()) return context.eventData; // there are no rules to validate - Map validatedData = ContainerUtil.newConcurrentMap(); // TODO: don't create validatedData map if all keys are accepted (just return context.eventData) + Map validatedData = + ContainerUtil.newConcurrentMap(); // TODO: don't create validatedData map if all keys are accepted (just return context.eventData) for (Map.Entry entry : context.eventData.entrySet()) { String key = entry.getKey(); Object entryValue = entry.getValue(); - ValidationResultType resultType = whiteListRule.validateEventData(key, entryValue, context); + + ValidationResultType resultType = validateEventData(context, whiteListRule, key, entryValue); validatedData.put(key, resultType == ACCEPTED ? entryValue : resultType.getDescription()); } return validatedData; } + private ValidationResultType validateEventData(@NotNull EventContext context, + @Nullable WhiteListGroupRules whiteListRule, + @NotNull String key, + @NotNull Object entryValue) { + if (isUnreachableWhitelist()) return UNREACHABLE_WHITELIST; + if (whiteListRule == null) return UNDEFINED_RULE; + if (FeatureUsageData.Companion.getPlatformDataKeys().contains(key)) return ACCEPTED; + return whiteListRule.validateEventData(key, entryValue, context); + } + public SensitiveDataValidator update() { - String whiteListContent = getWhiteListContent(); + updateValidators(getWhiteListContent()); + return this; + } + + private void updateValidators(@Nullable String whiteListContent) { if (whiteListContent != null) { - FUStatisticsWhiteListGroupsService.WLGroups groups = FUStatisticsWhiteListGroupsService.parseWhiteListContent(whiteListContent); - if (groups != null) { - final BuildNumber buildNumber = BuildNumber.fromString(EventLogConfiguration.INSTANCE.getBuild()); - final Map result = groups.groups.stream(). - filter(group -> group.accepts(buildNumber)). - collect(Collectors.toMap(group -> group.id, group -> createRules(group, groups.rules))); + mySemaphore.down(); + try { eventsValidators.clear(); - eventsValidators.putAll(result); + isWhiteListInitialized.set(false); + FUStatisticsWhiteListGroupsService.WLGroups groups = FUStatisticsWhiteListGroupsService.parseWhiteListContent(whiteListContent); + if (groups != null) { + final BuildNumber buildNumber = BuildNumber.fromString(EventLogConfiguration.INSTANCE.getBuild()); + final Map result = groups.groups.stream(). + filter(group -> group.accepts(buildNumber)). + collect(Collectors.toMap(group -> group.id, group -> createRules(group, groups.rules))); + + eventsValidators.putAll(result); + + isWhiteListInitialized.set(true); + } + } + finally { + mySemaphore.up(); } } - return this; + } + + private boolean isUnreachableWhitelist() { + return !isWhiteListInitialized.get(); } public ValidationResultType validateEvent(@NotNull EventLogGroup group, @NotNull EventContext context) { WhiteListGroupRules whiteListRule = eventsValidators.get(group.getId()); if (whiteListRule == null || !whiteListRule.areEventIdRulesDefined()) { - return ACCEPTED; // there are no rules (eventId and eventData) to validate + return UNDEFINED_RULE; // there are no rules (eventId and eventData) to validate } return whiteListRule.validateEventId(context); @@ -91,4 +134,17 @@ public class SensitiveDataValidator { } return FUSWhiteListPersistence.getCachedWhiteList(); } + + + private static class BlindSensitiveDataValidator extends SensitiveDataValidator { + @Override + public String guaranteeCorrectEventId(@NotNull EventLogGroup group, @NotNull EventContext context) { + return context.eventId; + } + + @Override + public Map guaranteeCorrectEventData(@NotNull EventLogGroup group, @NotNull EventContext context) { + return context.eventData; + } + } } diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/eventLog/validator/ValidationResultType.java b/platform/platform-impl/src/com/intellij/internal/statistic/eventLog/validator/ValidationResultType.java index 114303a40963..f8d34f1a6edd 100644 --- a/platform/platform-impl/src/com/intellij/internal/statistic/eventLog/validator/ValidationResultType.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/eventLog/validator/ValidationResultType.java @@ -8,6 +8,7 @@ public enum ValidationResultType { REJECTED("validation.unmatched_rule"), INCORRECT_RULE("validation.incorrect_rule"), UNDEFINED_RULE("validation.undefined_rule"), + UNREACHABLE_WHITELIST("validation.unreachable.whitelist"), PERFORMANCE_ISSUE("validation.performance_issue"); private final String value; diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/updater/StatisticsJobsScheduler.java b/platform/platform-impl/src/com/intellij/internal/statistic/updater/StatisticsJobsScheduler.java index 9b04777d05e8..cf2694b7b018 100644 --- a/platform/platform-impl/src/com/intellij/internal/statistic/updater/StatisticsJobsScheduler.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/updater/StatisticsJobsScheduler.java @@ -74,7 +74,7 @@ public class StatisticsJobsScheduler implements ApplicationInitializedListener { } private static void runSensitiveDataValidatorUpdater() { - JobScheduler.getScheduler().scheduleWithFixedDelay(() -> SensitiveDataValidator.getInstance().update(), 1, 180, TimeUnit.MINUTES); + JobScheduler.getScheduler().scheduleWithFixedDelay(() -> SensitiveDataValidator.getInstance().update(), 3, 180, TimeUnit.MINUTES); } private static void runEventLogStatisticsService() { diff --git a/platform/platform-impl/src/com/intellij/openapi/application/JBProtocolCommand.java b/platform/platform-impl/src/com/intellij/openapi/application/JBProtocolCommand.java index f48b440f1a29..5edc20544e6c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/JBProtocolCommand.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/JBProtocolCommand.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-2019 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.openapi.application; import com.intellij.openapi.extensions.ExtensionPointName; @@ -25,7 +11,7 @@ import java.util.Map; * @author Konstantin Bulenkov */ public abstract class JBProtocolCommand { - public static final ExtensionPointName EP_NAME = new ExtensionPointName<>("com.intellij.jbProtocolCommand"); + private static final ExtensionPointName EP_NAME = new ExtensionPointName<>("com.intellij.jbProtocolCommand"); private final String myCommand; public JBProtocolCommand(@NotNull String command) { @@ -37,12 +23,12 @@ public abstract class JBProtocolCommand { return myCommand; } - public abstract void perform(String target, Map parameters); + public abstract void perform(String target, @NotNull Map parameters); @Nullable public static JBProtocolCommand findCommand(@Nullable String commandName) { if (commandName != null) { - for (JBProtocolCommand command : EP_NAME.getExtensions()) { + for (JBProtocolCommand command : EP_NAME.getIterable()) { if (command.getCommandName().equals(commandName)) { return command; } diff --git a/platform/platform-impl/src/com/intellij/openapi/application/JBProtocolShutdownCommand.java b/platform/platform-impl/src/com/intellij/openapi/application/JBProtocolShutdownCommand.java index c463ee907d6e..8567eed53e2f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/JBProtocolShutdownCommand.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/JBProtocolShutdownCommand.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-2019 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.openapi.application; import com.intellij.CommonBundle; @@ -20,23 +6,24 @@ import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.ui.MessageDialogBuilder; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; import java.util.Map; /** * @author Konstantin Bulenkov */ -public class JBProtocolShutdownCommand extends JBProtocolCommand { - - public JBProtocolShutdownCommand() { +final class JBProtocolShutdownCommand extends JBProtocolCommand { + JBProtocolShutdownCommand() { super("shutdown"); } @Override - public void perform(String target, Map parameters) { + public void perform(String target, @NotNull Map parameters) { if (StringUtil.isEmpty(target)) { ApplicationManager.getApplication().exit(); - } else { + } + else { MessageDialogBuilder.YesNo confirmExitDialog = MessageDialogBuilder.yesNo(ApplicationBundle.message("exit.confirm.title"), target) .yesText(ApplicationBundle.message("command.exit")).noText( CommonBundle.message("button.cancel")); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index 97e5e3ecde1a..2853fc4a7447 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -2018,7 +2018,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse ActionGroup actionGroup = renderer.getPopupMenuActions(); if (actionGroup != null) { if (checkDumbAware(actionGroup)) { - actionManager.createActionPopupMenu(ActionPlaces.UNKNOWN, actionGroup).getComponent().show(this, e.getX(), e.getY()); + actionManager.createActionPopupMenu(ActionPlaces.EDITOR_GUTTER_POPUP, actionGroup).getComponent().show(this, e.getX(), e.getY()); } else { notifyNotDumbAware(); @@ -2033,7 +2033,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse group = (ActionGroup)CustomActionsSchema.getInstance().getCorrectedAction(IdeActions.GROUP_EDITOR_GUTTER); } if (group != null) { - ActionPopupMenu popupMenu = actionManager.createActionPopupMenu(ActionPlaces.UNKNOWN, group); + ActionPopupMenu popupMenu = actionManager.createActionPopupMenu(ActionPlaces.EDITOR_GUTTER_POPUP, group); popupMenu.getComponent().show(this, e.getX(), e.getY()); } e.consume(); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSaverDialogImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSaverDialogImpl.java index 4ce0e3ec90e6..120e3825b92b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSaverDialogImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSaverDialogImpl.java @@ -6,6 +6,7 @@ import com.intellij.openapi.fileChooser.FileSaverDialog; import com.intellij.openapi.fileChooser.FileSystemTree; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileWrapper; import com.intellij.ui.DocumentAdapter; @@ -108,12 +109,12 @@ public class FileSaverDialogImpl extends FileChooserDialogImpl implements FileSa private void updateFileName(List selection) { for (VirtualFile file : selection) { if (file.isDirectory()) { - myPathTextField.getField().setText(file.getPath()); + myPathTextField.getField().setText(VfsUtil.getReadableUrl(file)); } else { myFileName.setText(file.getName()); final VirtualFile parent = file.getParent(); if (parent != null) { - myPathTextField.getField().setText(parent.getPath()); + myPathTextField.getField().setText(VfsUtil.getReadableUrl(parent)); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java index 5b77d2e77be8..8f97a7966eec 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java @@ -900,7 +900,7 @@ public class EditorWindow { final Icon modifiedIcon; UISettings settings = UISettings.getInstance(); - if (settings.getMarkModifiedTabsWithAsterisk() || !settings.getHideTabsIfNeed()) { + if (settings.getMarkModifiedTabsWithAsterisk()) { Icon crop = IconUtil.cropIcon(AllIcons.General.Modified, new JBRectangle(3, 3, 7, 7)); modifiedIcon = settings.getMarkModifiedTabsWithAsterisk() && composite != null && composite.isModified() ? crop : new EmptyIcon(7, 7); count++; diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java index 4e4ee541b22a..18fb0f2f5a54 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java @@ -52,6 +52,7 @@ import com.intellij.util.ui.MacUIUtil; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.plaf.basic.ComboPopup; @@ -437,7 +438,8 @@ public final class IdeKeyEventDispatcher implements Disposable { if (SystemInfo.isMac && InputEvent.ALT_DOWN_MASK == e.getModifiersEx() && Registry.is("ide.mac.alt.mnemonic.without.ctrl")) { // the myIgnoreNextKeyTypedEvent changes event processing to support Alt-based mnemonics on Mac only - if ((KeyEvent.KEY_TYPED == e.getID() && !IdeEventQueue.getInstance().isInputMethodEnabled()) || hasMnemonicInWindow(focusOwner, e)) { + if ((KeyEvent.KEY_TYPED == e.getID() && !IdeEventQueue.getInstance().isInputMethodEnabled()) || + hasMnemonicInWindow(focusOwner, e)) { myIgnoreNextKeyTypedEvent = true; return false; } @@ -521,7 +523,7 @@ public final class IdeKeyEventDispatcher implements Disposable { return secondKeyStrokes; } - private static boolean hasMnemonicInWindow(Component focusOwner, KeyEvent event) { + public static boolean hasMnemonicInWindow(Component focusOwner, KeyEvent event) { return KeyEvent.KEY_TYPED == event.getID() && hasMnemonicInWindow(focusOwner, event.getKeyChar()) || KeyEvent.KEY_PRESSED == event.getID() && hasMnemonicInWindow(focusOwner, event.getKeyCode()); } @@ -532,43 +534,44 @@ public final class IdeKeyEventDispatcher implements Disposable { return hasMnemonic(container, keyCode) || hasMnemonicInBalloons(container, keyCode); } - private static boolean hasMnemonic(final Container container, final int keyCode) { - if (container == null) return false; + private static boolean hasMnemonic(@Nullable Container container, int keyCode) { + Component component = UIUtil.uiTraverser(container) + .traverse() + .find(c -> hasMnemonic(c, keyCode)); + return component != null; + } - final Component[] components = container.getComponents(); - for (Component component : components) { - if (component instanceof AbstractButton) { - final AbstractButton button = (AbstractButton)component; - if (button instanceof JBOptionButton) { - if (((JBOptionButton)button).isOkToProcessDefaultMnemonics() || - button.getMnemonic() == keyCode) - { - return true; - } - } else { - if (button.getMnemonic() == keyCode) return true; + private static boolean hasMnemonic(@Nullable Component component, int keyCode) { + if (component instanceof AbstractButton) { + AbstractButton button = (AbstractButton)component; + if (button instanceof JBOptionButton) { + if (((JBOptionButton)button).isOkToProcessDefaultMnemonics() || + button.getMnemonic() == keyCode) { + return true; } } - if (component instanceof JLabel) { - final JLabel label = (JLabel)component; - if (label.getDisplayedMnemonic() == keyCode) return true; - } - if (component instanceof ActionButtonWithText) { - if (((ActionButtonWithText)component).getMnemonic() == keyCode) return true; - } - if (component instanceof Container) { - if (hasMnemonic((Container)component, keyCode)) return true; + else { + if (button.getMnemonic() == keyCode) return true; } } + if (component instanceof JLabel) { + JLabel label = (JLabel)component; + if (label.getDisplayedMnemonic() == keyCode) return true; + } + if (component instanceof ActionButtonWithText) { + if (((ActionButtonWithText)component).getMnemonic() == keyCode) return true; + } return false; } private static boolean hasMnemonicInBalloons(Container container, int code) { - final Component parent = UIUtil.findUltimateParent(container); + Component parent = UIUtil.findUltimateParent(container); if (parent instanceof RootPaneContainer) { final JLayeredPane pane = ((RootPaneContainer)parent).getLayeredPane(); for (Component component : pane.getComponents()) { - if (component instanceof ComponentWithMnemonics && component instanceof Container && hasMnemonic((Container)component, code)) { + if (component instanceof ComponentWithMnemonics && + component instanceof Container && + hasMnemonic((Container)component, code)) { return true; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java index 7f690a7cbae6..58f570240ba9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java @@ -121,7 +121,9 @@ public class ConfigurableExtensionPointUtil { * @return the root configurable group that represents a tree of settings */ public static ConfigurableGroup getConfigurableGroup(@Nullable Project project, boolean withIdeSettings) { - if (!withIdeSettings && project == null) project = ProjectManager.getInstance().getDefaultProject(); + if (!withIdeSettings && project == null) { + project = ProjectManager.getInstance().getDefaultProject(); + } return getConfigurableGroup(getConfigurables(project, withIdeSettings), project); } @@ -132,16 +134,16 @@ public class ConfigurableExtensionPointUtil { */ public static ConfigurableGroup getConfigurableGroup(@NotNull List configurables, @Nullable Project project) { Map> map = groupConfigurables(configurables); - Map> tree = ContainerUtil.newHashMap(); + Map> tree = new THashMap<>(); for (Map.Entry> entry : map.entrySet()) { addGroup(tree, project, entry.getKey(), entry.getValue(), null); } + SortedConfigurableGroup root = getGroup(tree, "root"); if (!tree.isEmpty()) { - for (String groupId : tree.keySet()) { - LOG.warn("ignore group: " + groupId); - } + LOG.warn("ignore groups: " + tree.keySet()); } + if (root != null && root.myList != null && Registry.is("ide.settings.replace.group.with.single.configurable")) { replaceGroupWithSingleConfigurable(root.myList); } @@ -198,7 +200,7 @@ public class ConfigurableExtensionPointUtil { return node.myValue; } - private static void addGroup(Map> tree, Project project, + private static void addGroup(@NotNull Map> tree, Project project, String groupId, List configurables, ResourceBundle alternative) { String id = "configurable.group." + groupId; ResourceBundle bundle = getBundle(id + ".settings.display.name", configurables, alternative); @@ -250,6 +252,7 @@ public class ConfigurableExtensionPointUtil { * @param configurables a list of settings to process * @return the map of different groups of settings */ + @NotNull public static Map> groupConfigurables(@NotNull List configurables) { Map> tree = new THashMap<>(); for (Configurable configurable : configurables) { @@ -346,8 +349,9 @@ public class ConfigurableExtensionPointUtil { * @param withIdeSettings specifies whether to load application settings or not * @return the list of all valid settings according to parameters */ + @NotNull private static List getConfigurables(@Nullable Project project, boolean withIdeSettings) { - List list = ContainerUtil.newArrayList(); + List list = new ArrayList<>(); if (withIdeSettings) { Application application = ApplicationManager.getApplication(); if (application != null) { @@ -436,81 +440,6 @@ public class ConfigurableExtensionPointUtil { return !isValid(each, null) || (filter != null && !filter.isIncluded(each)); } - /* - private static void dumpConfigurable(ExtensionPointName> configurablesExtensionPoint, - ConfigurableEP ep, - Configurable configurable) { - if (configurable != null && !(configurable instanceof ConfigurableGroup)) { - if (ep.instanceClass != null && (configurable instanceof SearchableConfigurable) && (configurable instanceof Configurable.Composite)) { - Element element = dump(ep, configurable, StringUtil.getShortName(configurablesExtensionPoint.getName())); - final Configurable[] configurables = ((Configurable.Composite)configurable).getConfigurables(); - for (Configurable child : configurables) { - final Element dump = dump(null, child, "configurable"); - element.addContent(dump); - } - final StringWriter out = new StringWriter(); - try { - new XMLOutputter(Format.getPrettyFormat()).output(element, out); - } - catch (IOException e) { - } - System.out.println(out); - } - } - } - - private static Element dump(@Nullable ConfigurableEP ep, - Configurable configurable, String name) { - Element element = new Element(name); - if (ep != null) { - element.setAttribute("instance", ep.instanceClass); - String id = ep.id == null ? ((SearchableConfigurable)configurable).getId() : ep.id; - element.setAttribute("id", id); - } - else { - element.setAttribute("instance", configurable.getClass().getName()); - if (configurable instanceof SearchableConfigurable) { - element.setAttribute("id", ((SearchableConfigurable)configurable).getId()); - } - } - - CommonBundle.lastKey = null; - String displayName = configurable.getDisplayName(); - if (CommonBundle.lastKey != null) { - element.setAttribute("key", CommonBundle.lastKey).setAttribute("bundle", CommonBundle.lastBundle); - } - else { - element.setAttribute("displayName", displayName); - } - if (configurable instanceof NonDefaultProjectConfigurable) { - element.setAttribute("nonDefaultProject", "true"); - } - return element; - } - */ - - /** - * @deprecated create a new instance of configurable instead - */ - @Deprecated - @NotNull - public static T findProjectConfigurable(@NotNull Project project, @NotNull Class configurableClass) { - return findConfigurable(Configurable.PROJECT_CONFIGURABLE.getExtensionList(project), configurableClass); - } - - @NotNull - private static T findConfigurable(@NotNull List> extensions, Class configurableClass) { - for (ConfigurableEP extension : extensions) { - if (extension.canCreateConfigurable()) { - final Configurable configurable = extension.createConfigurable(); - if (configurableClass.isInstance(configurable)) { - return configurableClass.cast(configurable); - } - } - } - throw new IllegalArgumentException("Cannot find configurable of " + configurableClass); - } - @Nullable public static Configurable createProjectConfigurableForProvider(@NotNull Project project, Class providerClass) { return createConfigurableForProvider(Configurable.PROJECT_CONFIGURABLE.getExtensionList(project), providerClass); diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableVisitor.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableVisitor.java index 3eb08decdf84..08b11f2f9d96 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableVisitor.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableVisitor.java @@ -1,26 +1,14 @@ -/* - * 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-2019 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.openapi.options.ex; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurableGroup; import com.intellij.openapi.options.SearchableConfigurable; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -36,7 +24,13 @@ public abstract class ConfigurableVisitor { protected abstract boolean accept(Configurable configurable); + @Nullable public final Configurable find(@NotNull ConfigurableGroup... groups) { + return find(Arrays.asList(groups)); + } + + @Nullable + public final Configurable find(@NotNull List groups) { for (ConfigurableGroup group : groups) { Configurable result = find(group.getConfigurables()); if (result != null) { @@ -64,7 +58,7 @@ public abstract class ConfigurableVisitor { return null; } - public final List findAll(@NotNull ConfigurableGroup... groups) { + public final List findAll(@NotNull List groups) { List list = new ArrayList<>(); for (ConfigurableGroup group : groups) { add(list, group.getConfigurables()); diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/Settings.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/Settings.java index 3cb6c0b46318..cab249e6709b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/ex/Settings.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/Settings.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 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.openapi.options.ex; import com.intellij.openapi.actionSystem.DataKey; @@ -23,8 +9,11 @@ import com.intellij.openapi.options.UnnamedConfigurable; import com.intellij.openapi.util.ActionCallback; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.concurrency.Promise; +import org.jetbrains.concurrency.Promises; import java.util.IdentityHashMap; +import java.util.List; /** * @author Sergey.Malenkov @@ -32,11 +21,11 @@ import java.util.IdentityHashMap; public abstract class Settings { public static final DataKey KEY = DataKey.create("settings.editor"); - private final ConfigurableGroup[] myGroups; + private final List myGroups; private final IdentityHashMap myMap = new IdentityHashMap<>(); - protected Settings(@NotNull ConfigurableGroup... groups) { + protected Settings(@NotNull List groups) { myGroups = groups; } @@ -52,9 +41,7 @@ public abstract class Settings { @NotNull public final ActionCallback select(Configurable configurable) { - return configurable != null - ? selectImpl(choose(configurable, myMap.get(configurable))) - : ActionCallback.REJECTED; + return configurable == null ? ActionCallback.REJECTED : Promises.toActionCallback(selectImpl(choose(configurable, myMap.get(configurable)))); } @NotNull @@ -68,7 +55,8 @@ public abstract class Settings { return callback; } - protected abstract ActionCallback selectImpl(Configurable configurable); + @NotNull + protected abstract Promise selectImpl(Configurable configurable); private T unwrap(Configurable configurable, Class type) { T result = ConfigurableWrapper.cast(type, configurable); diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/AbstractEditor.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/AbstractEditor.java index 304978bd990f..4459d8431fb4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/AbstractEditor.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/AbstractEditor.java @@ -1,27 +1,12 @@ -/* - * 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-2019 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.openapi.options.newEditor; import com.intellij.openapi.Disposable; import com.intellij.openapi.util.Disposer; +import org.jetbrains.annotations.NotNull; -import javax.swing.Action; -import javax.swing.JComponent; -import javax.swing.JPanel; -import java.awt.BorderLayout; +import javax.swing.*; +import java.awt.*; /** * @author Sergey.Malenkov @@ -29,8 +14,9 @@ import java.awt.BorderLayout; abstract class AbstractEditor extends JPanel implements Disposable { volatile boolean myDisposed; - AbstractEditor(Disposable parent) { + AbstractEditor(@NotNull Disposable parent) { super(new BorderLayout()); + Disposer.register(parent, this); } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/ConfigurableEditor.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/ConfigurableEditor.java index b2ffb310dec2..997126b2adfc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/ConfigurableEditor.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/ConfigurableEditor.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 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. +// Copyright 2000-2019 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.openapi.options.newEditor; import com.intellij.CommonBundle; @@ -29,6 +29,8 @@ import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; import org.jetbrains.annotations.NotNull; +import org.jetbrains.concurrency.Promise; +import org.jetbrains.concurrency.Promises; import javax.swing.*; import java.awt.*; @@ -235,18 +237,20 @@ class ConfigurableEditor extends AbstractEditor implements AnActionListener, AWT return true; } - final ActionCallback select(final Configurable configurable) { + @NotNull + final Promise select(final Configurable configurable) { assert !myDisposed : "Already disposed"; ActionCallback callback = myCardPanel.select(configurable, false); - callback.doWhenDone(() -> { - myConfigurable = configurable; - updateCurrent(configurable, false); - postUpdateCurrent(configurable); - if (configurable != null) { - FeatureUsageUiEventsKt.getUiEventLogger().logSelectConfigurable(getConfigurableEventId(configurable), configurable.getClass()); - } - }); - return callback; + callback + .doWhenDone(() -> { + myConfigurable = configurable; + updateCurrent(configurable, false); + postUpdateCurrent(configurable); + if (configurable != null) { + FeatureUsageUiEventsKt.getUiEventLogger().logSelectConfigurable(getConfigurableEventId(configurable), configurable.getClass()); + } + }); + return Promises.toPromise(callback); } final boolean setError(ConfigurationException exception) { diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/ISettingsTreeViewFactory.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/ISettingsTreeViewFactory.java index 7c0c36dedaab..5ac943096fae 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/ISettingsTreeViewFactory.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/ISettingsTreeViewFactory.java @@ -1,22 +1,11 @@ -/* - * 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-2019 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.openapi.options.newEditor; import com.intellij.openapi.options.ConfigurableGroup; +import org.jetbrains.annotations.NotNull; + +import java.util.List; public interface ISettingsTreeViewFactory { - SettingsTreeView createTreeView(SettingsFilter filter, ConfigurableGroup[] groups); + SettingsTreeView createTreeView(SettingsFilter filter, @NotNull List groups); } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditorColleague.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditorColleague.java index 3af12bf432b8..09e2e2128f96 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditorColleague.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditorColleague.java @@ -1,39 +1,48 @@ -// Copyright 2000-2018 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. +// Copyright 2000-2019 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.openapi.options.newEditor; import com.intellij.openapi.options.Configurable; -import com.intellij.openapi.util.ActionCallback; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.concurrency.Promise; +import org.jetbrains.concurrency.Promises; public interface OptionsEditorColleague { - ActionCallback onSelected(@Nullable Configurable configurable, final Configurable oldConfigurable); + @NotNull + Promise onSelected(@Nullable Configurable configurable, final Configurable oldConfigurable); - ActionCallback onModifiedAdded(final Configurable configurable); + @NotNull + Promise onModifiedAdded(final Configurable configurable); - ActionCallback onModifiedRemoved(final Configurable configurable); + @NotNull + Promise onModifiedRemoved(final Configurable configurable); - ActionCallback onErrorsChanged(); + @NotNull + Promise onErrorsChanged(); class Adapter implements OptionsEditorColleague { + @NotNull @Override - public ActionCallback onSelected(@Nullable final Configurable configurable, final Configurable oldConfigurable) { - return ActionCallback.DONE; + public Promise onSelected(@Nullable final Configurable configurable, final Configurable oldConfigurable) { + return Promises.resolvedPromise(); } + @NotNull @Override - public ActionCallback onModifiedAdded(final Configurable configurable) { - return ActionCallback.DONE; + public Promise onModifiedAdded(final Configurable configurable) { + return Promises.resolvedPromise(); } + @NotNull @Override - public ActionCallback onModifiedRemoved(final Configurable configurable) { - return ActionCallback.DONE; + public Promise onModifiedRemoved(final Configurable configurable) { + return Promises.resolvedPromise(); } + @NotNull @Override - public ActionCallback onErrorsChanged() { - return ActionCallback.DONE; + public Promise onErrorsChanged() { + return Promises.resolvedPromise(); } } - } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditorContext.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditorContext.java index adbdefd82987..a4a0a8a28b0a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditorContext.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditorContext.java @@ -1,13 +1,15 @@ -// Copyright 2000-2018 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. +// Copyright 2000-2019 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.openapi.options.newEditor; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; -import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.MultiValuesMap; +import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.concurrency.Promise; +import org.jetbrains.concurrency.Promises; import java.util.*; import java.util.concurrent.CopyOnWriteArraySet; @@ -22,70 +24,80 @@ public class OptionsEditorContext { private final Map myConfigurableToParentMap = new HashMap<>(); private final MultiValuesMap myParentToChildrenMap = new MultiValuesMap<>(); - ActionCallback fireSelected(@Nullable final Configurable configurable, @NotNull OptionsEditorColleague requestor) { - if (myCurrentConfigurable == configurable) return ActionCallback.REJECTED; + @NotNull + Promise fireSelected(@Nullable final Configurable configurable, @NotNull OptionsEditorColleague requestor) { + if (myCurrentConfigurable == configurable) { + return Promises.rejectedPromise(); + } final Configurable old = myCurrentConfigurable; myCurrentConfigurable = configurable; return notify(new ColleagueAction() { + @NotNull @Override - public ActionCallback process(final OptionsEditorColleague colleague) { + public Promise process(final OptionsEditorColleague colleague) { return colleague.onSelected(configurable, old); } }, requestor); - } - ActionCallback fireModifiedAdded(@NotNull final Configurable configurable, @Nullable OptionsEditorColleague requestor) { - if (myModified.contains(configurable)) return ActionCallback.REJECTED; + @NotNull + Promise fireModifiedAdded(@NotNull final Configurable configurable, @Nullable OptionsEditorColleague requestor) { + if (myModified.contains(configurable)) { + return Promises.rejectedPromise(); + } myModified.add(configurable); return notify(new ColleagueAction() { + @NotNull @Override - public ActionCallback process(final OptionsEditorColleague colleague) { + public Promise process(final OptionsEditorColleague colleague) { return colleague.onModifiedAdded(configurable); } }, requestor); } - ActionCallback fireModifiedRemoved(@NotNull final Configurable configurable, @Nullable OptionsEditorColleague requestor) { - if (!myModified.contains(configurable)) return ActionCallback.REJECTED; + @NotNull + Promise fireModifiedRemoved(@NotNull final Configurable configurable, @Nullable OptionsEditorColleague requestor) { + if (!myModified.contains(configurable)) { + return Promises.rejectedPromise(); + } myModified.remove(configurable); return notify(new ColleagueAction() { + @NotNull @Override - public ActionCallback process(final OptionsEditorColleague colleague) { + public Promise process(final OptionsEditorColleague colleague) { return colleague.onModifiedRemoved(configurable); } }, requestor); } - ActionCallback fireErrorsChanged(final Map errors, OptionsEditorColleague requestor) { - if (myErrors.equals(errors)) return ActionCallback.REJECTED; + @NotNull + Promise fireErrorsChanged(final Map errors, OptionsEditorColleague requestor) { + if (myErrors.equals(errors)) { + return Promises.rejectedPromise(); + } myErrors = errors != null ? errors : new HashMap<>(); return notify(new ColleagueAction() { + @NotNull @Override - public ActionCallback process(final OptionsEditorColleague colleague) { + public Promise process(final OptionsEditorColleague colleague) { return colleague.onErrorsChanged(); } }, requestor); } - ActionCallback notify(ColleagueAction action, OptionsEditorColleague requestor) { - final ActionCallback.Chunk chunk = new ActionCallback.Chunk(); - for (OptionsEditorColleague each : myColleagues) { - if (each != requestor) { - chunk.add(action.process(each)); - } - } - - return chunk.getWhenProcessed(); + @NotNull + Promise notify(@NotNull ColleagueAction action, OptionsEditorColleague requestor) { + //noinspection unchecked + return (Promise)Promises.all(ContainerUtil.mapNotNull(myColleagues, it -> it == requestor ? null : action.process(it))); } public void fireReset(final Configurable configurable) { @@ -127,7 +139,8 @@ public class OptionsEditorContext { } interface ColleagueAction { - ActionCallback process(OptionsEditorColleague colleague); + @NotNull + Promise process(OptionsEditorColleague colleague); } public Configurable getCurrentConfigurable() { diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsDialog.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsDialog.java index 89ce635a598c..90439b118368 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsDialog.java @@ -27,6 +27,7 @@ import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.util.ArrayList; +import java.util.List; import static com.intellij.openapi.actionSystem.IdeActions.ACTION_FIND; @@ -56,15 +57,17 @@ public class SettingsDialog extends DialogWrapper implements DataProvider { init(configurable, null); } - public SettingsDialog(@NotNull Project project, @NotNull ConfigurableGroup[] groups, Configurable configurable, String filter) { + public SettingsDialog(@NotNull Project project, @NotNull List groups, @Nullable Configurable configurable, @Nullable String filter) { super(project, true); + myDimensionServiceKey = DIMENSION_KEY; myEditor = new SettingsEditor(myDisposable, project, groups, configurable, filter, this::treeViewFactory); myApplyButtonNeeded = true; init(null, project); } - protected SettingsTreeView treeViewFactory(SettingsFilter filter, ConfigurableGroup[] groups) { + @NotNull + protected SettingsTreeView treeViewFactory(SettingsFilter filter, List groups) { return new SettingsTreeView(filter, groups); } @@ -73,7 +76,7 @@ public class SettingsDialog extends DialogWrapper implements DataProvider { TransactionGuard.getInstance().submitTransactionAndWait(() -> super.show()); } - private void init(Configurable configurable, @Nullable Project project) { + private void init(@Nullable Configurable configurable, @Nullable Project project) { String name = configurable == null ? null : configurable.getDisplayName(); String title = CommonBundle.settingsTitle(); if (project != null && project.isDefault()) { @@ -81,8 +84,12 @@ public class SettingsDialog extends DialogWrapper implements DataProvider { title, StringUtil.capitalize(IdeUICustomization.getInstance().getProjectConceptName())); } setTitle(name == null ? title : name.replace('\n', ' ')); + ShortcutSet set = getFindActionShortcutSet(); - if (set != null) new FindAction().registerCustomShortcutSet(set, getRootPane(), myDisposable); + if (set != null) { + new FindAction().registerCustomShortcutSet(set, getRootPane(), myDisposable); + } + init(); } @@ -189,6 +196,7 @@ public class SettingsDialog extends DialogWrapper implements DataProvider { super.doCancelAction(source); } + @Nullable static ShortcutSet getFindActionShortcutSet() { AnAction action = ActionManager.getInstance().getAction(ACTION_FIND); return action == null ? null : action.getShortcutSet(); diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsDialogFactory.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsDialogFactory.java index 92a74db36600..c397e48ddc8f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsDialogFactory.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsDialogFactory.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-2019 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.openapi.options.newEditor; import com.intellij.openapi.components.ServiceManager; @@ -21,23 +7,34 @@ import com.intellij.openapi.options.ConfigurableGroup; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.awt.*; +import java.util.Arrays; +import java.util.List; public class SettingsDialogFactory { public static SettingsDialogFactory getInstance() { return ServiceManager.getService(SettingsDialogFactory.class); } + @NotNull public DialogWrapper create(Project project, String key, @NotNull Configurable configurable, boolean showApplyButton, boolean showResetButton){ return new SettingsDialog(project, key, configurable, showApplyButton, showResetButton); } + @NotNull public DialogWrapper create(@NotNull Component parent, String key, @NotNull Configurable configurable, boolean showApplyButton, boolean showResetButton){ return new SettingsDialog(parent, key, configurable, showApplyButton, showResetButton); } + @NotNull public DialogWrapper create(@NotNull Project project, @NotNull ConfigurableGroup[] groups, Configurable configurable, String filter){ + return create(project, Arrays.asList(groups), configurable, filter); + } + + @NotNull + public DialogWrapper create(@NotNull Project project, @NotNull List groups, @Nullable Configurable configurable, @Nullable String filter) { return new SettingsDialog(project, groups, configurable, filter); } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsEditor.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsEditor.java index bf9eaffbd3a3..ebbc50e4aeb7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsEditor.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsEditor.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 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. +// Copyright 2000-2019 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.openapi.options.newEditor; import com.intellij.ide.util.PropertiesComponent; @@ -12,7 +12,6 @@ import com.intellij.openapi.options.ex.ConfigurableWrapper; import com.intellij.openapi.options.ex.Settings; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.LoadingDecorator; -import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; @@ -27,16 +26,16 @@ import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.concurrency.Promise; +import org.jetbrains.concurrency.Promises; import javax.swing.*; import java.awt.*; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.List; +import java.util.*; /** * @author Sergey.Malenkov @@ -49,7 +48,6 @@ final class SettingsEditor extends AbstractEditor implements DataProvider { private final PropertiesComponent myProperties; private final Settings mySettings; private final SettingsSearch mySearch; - private final JPanel mySearchPanel; private final SettingsFilter myFilter; private final SettingsTreeView myTreeView; private final ConfigurableEditor myEditor; @@ -61,18 +59,19 @@ final class SettingsEditor extends AbstractEditor implements DataProvider { private final Map myControllers = new HashMap<>(); private ConfigurableController myLastController; - SettingsEditor(Disposable parent, - Project project, - ConfigurableGroup[] groups, - Configurable configurable, + SettingsEditor(@NotNull Disposable parent, + @NotNull Project project, + @NotNull List groups, + @Nullable Configurable configurable, final String filter, final ISettingsTreeViewFactory factory) { super(parent); myProperties = PropertiesComponent.getInstance(project); mySettings = new Settings(groups) { + @NotNull @Override - protected ActionCallback selectImpl(Configurable configurable) { + protected Promise selectImpl(Configurable configurable) { myFilter.update(null, false, true); return myTreeView.select(configurable); } @@ -88,8 +87,8 @@ final class SettingsEditor extends AbstractEditor implements DataProvider { myTreeView.myTree.processKeyEvent(event); } }; - mySearchPanel = new JPanel(new VerticalLayout(0)); - mySearchPanel.add(VerticalLayout.CENTER, mySearch); + JPanel searchPanel = new JPanel(new VerticalLayout(0)); + searchPanel.add(VerticalLayout.CENTER, mySearch); myFilter = new SettingsFilter(project, groups, mySearch) { @Override Configurable getConfigurable(SimpleNode node) { @@ -114,15 +113,16 @@ final class SettingsEditor extends AbstractEditor implements DataProvider { } }; myFilter.myContext.addColleague(new OptionsEditorColleague() { + @NotNull @Override - public ActionCallback onSelected(@Nullable Configurable configurable, Configurable oldConfigurable) { + public Promise onSelected(@Nullable Configurable configurable, Configurable oldConfigurable) { if (configurable != null) { myProperties.setValue(SELECTED_CONFIGURABLE, ConfigurableVisitor.ByID.getID(configurable)); myLoadingDecorator.startLoading(false); } checkModified(oldConfigurable); - ActionCallback result = myEditor.select(configurable); - result.doWhenDone(() -> { + Promise result = myEditor.select(configurable); + result.onSuccess(it -> { updateController(configurable); //requestFocusToEditor(); // TODO myLoadingDecorator.stopLoading(); @@ -130,28 +130,31 @@ final class SettingsEditor extends AbstractEditor implements DataProvider { return result; } + @NotNull @Override - public ActionCallback onModifiedAdded(Configurable configurable) { + public Promise onModifiedAdded(Configurable configurable) { return updateIfCurrent(configurable); } + @NotNull @Override - public ActionCallback onModifiedRemoved(Configurable configurable) { + public Promise onModifiedRemoved(Configurable configurable) { return updateIfCurrent(configurable); } + @NotNull @Override - public ActionCallback onErrorsChanged() { + public Promise onErrorsChanged() { return updateIfCurrent(myFilter.myContext.getCurrentConfigurable()); } - private ActionCallback updateIfCurrent(Configurable configurable) { + private Promise updateIfCurrent(Configurable configurable) { if (configurable != null && configurable == myFilter.myContext.getCurrentConfigurable()) { updateStatus(configurable); - return ActionCallback.DONE; + return Promises.resolvedPromise(); } else { - return ActionCallback.REJECTED; + return Promises.rejectedPromise("rejected"); } } }); @@ -206,12 +209,12 @@ final class SettingsEditor extends AbstractEditor implements DataProvider { myEditor.setPreferredSize(JBUI.size(800, 600)); myLoadingDecorator = new LoadingDecorator(myEditor, this, 10, true); myBanner = new Banner(myEditor.getResetAction()); - mySearchPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + searchPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); myBanner.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 10)); mySearch.setBackground(UIUtil.SIDE_PANEL_BACKGROUND); - mySearchPanel.setBackground(UIUtil.SIDE_PANEL_BACKGROUND); + searchPanel.setBackground(UIUtil.SIDE_PANEL_BACKGROUND); JComponent left = new JPanel(new BorderLayout()); - left.add(BorderLayout.NORTH, mySearchPanel); + left.add(BorderLayout.NORTH, searchPanel); left.add(BorderLayout.CENTER, myTreeView); JComponent right = new JPanel(new BorderLayout()); right.add(BorderLayout.NORTH, myBanner); @@ -243,11 +246,17 @@ final class SettingsEditor extends AbstractEditor implements DataProvider { configurable = ConfigurableVisitor.ALL.find(groups); } } - myTreeView.select(configurable).doWhenDone(() -> myFilter.update(filter, false, true)); + + myTreeView.select(configurable) + .onSuccess(it -> myFilter.update(filter, false, true)); + Disposer.register(this, myTreeView); installSpotlightRemover(); - mySearch.getTextEditor().addActionListener( - event -> myTreeView.select(myFilter.myContext.getCurrentConfigurable()).doWhenDone(this::requestFocusToEditor)); + //noinspection CodeBlock2Expr + mySearch.getTextEditor().addActionListener(event -> { + myTreeView.select(myFilter.myContext.getCurrentConfigurable()) + .onSuccess(o -> requestFocusToEditor()); + }); } private void requestFocusToEditor() { diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsFilter.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsFilter.java index ed742b6b99e8..ddefa9580112 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsFilter.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsFilter.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 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. +// Copyright 2000-2019 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.openapi.options.newEditor; import com.intellij.ide.ui.search.ConfigurableHit; @@ -8,7 +8,6 @@ import com.intellij.openapi.options.ConfigurableGroup; import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.options.ex.ConfigurableWrapper; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.LightColors; @@ -21,6 +20,7 @@ import org.jetbrains.annotations.NotNull; import javax.swing.event.DocumentEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.List; import java.util.Set; public abstract class SettingsFilter extends ElementFilter.Active.Impl { @@ -30,7 +30,7 @@ public abstract class SettingsFilter extends ElementFilter.Active.Impl myGroups; private final SearchableOptionsRegistrar myRegistrar = SearchableOptionsRegistrar.getInstance(); private Set myFiltered; @@ -39,7 +39,7 @@ public abstract class SettingsFilter extends ElementFilter.Active.Impl groups, SearchTextField search) { myProject = project; myGroups = groups; mySearch = search; @@ -120,7 +120,7 @@ public abstract class SettingsFilter extends ElementFilter.Active.Impl configurables, Set hits) { diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java index c421c10c563c..3d10d2b7bcd6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 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. +// Copyright 2000-2019 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.openapi.options.newEditor; import com.intellij.icons.AllIcons; @@ -14,7 +14,6 @@ import com.intellij.openapi.options.*; import com.intellij.openapi.options.ex.ConfigurableWrapper; import com.intellij.openapi.options.ex.SortedConfigurableGroup; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.registry.Registry; @@ -38,6 +37,9 @@ import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.concurrency.AsyncPromise; +import org.jetbrains.concurrency.Promise; +import org.jetbrains.concurrency.Promises; import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; @@ -80,7 +82,7 @@ public class SettingsTreeView extends JComponent implements Accessible, Disposab private Configurable myQueuedConfigurable; private MyControl myControl; - public SettingsTreeView(SettingsFilter filter, ConfigurableGroup[] groups) { + public SettingsTreeView(SettingsFilter filter, List groups) { myFilter = filter; myRoot = new MyRoot(groups); myTree = new MyTree(); @@ -376,49 +378,61 @@ public class SettingsTreeView extends JComponent implements Accessible, Disposab myScroller.setBounds(0, 0, getWidth(), getHeight()); } - ActionCallback select(@Nullable final Configurable configurable) { + @NotNull + Promise select(@Nullable Configurable configurable) { if (myBuilder.isSelectionBeingAdjusted()) { - return ActionCallback.REJECTED; + return Promises.rejectedPromise(); } - final ActionCallback callback = new ActionCallback(); + + AsyncPromise promise = new AsyncPromise<>(); myQueuedConfigurable = configurable; myQueue.queue(new Update(this) { @Override public void run() { - if (configurable == myQueuedConfigurable) { - if (configurable == null) { - fireSelected(null, callback); - } - else { - myBuilder.getReady(this).doWhenDone(() -> { - if (configurable != myQueuedConfigurable) return; + if (configurable != myQueuedConfigurable) { + return; + } - MyNode editorNode = findNode(configurable); - FilteringTreeStructure.FilteringNode editorUiNode = myBuilder.getVisibleNodeFor(editorNode); - if (editorUiNode == null) return; + if (configurable == null) { + fireSelected(null) + .processed(promise); + } + else { + myBuilder.getReady(this).doWhenDone(() -> { + if (configurable != myQueuedConfigurable) return; - if (!myBuilder.getSelectedElements().contains(editorUiNode)) { - myBuilder.select(editorUiNode, () -> fireSelected(configurable, callback)); - } - else { - myBuilder.scrollSelectionToVisible(() -> fireSelected(configurable, callback), false); - } - }); - } + MyNode editorNode = findNode(configurable); + FilteringTreeStructure.FilteringNode editorUiNode = myBuilder.getVisibleNodeFor(editorNode); + if (editorUiNode == null) return; + + @SuppressWarnings("CodeBlock2Expr") + Runnable handler = () -> { + fireSelected(configurable) + .processed(promise); + }; + + if (myBuilder.getSelectedElements().contains(editorUiNode)) { + myBuilder.scrollSelectionToVisible(handler, false); + } + else { + myBuilder.select(editorUiNode, handler); + } + }); } } @Override public void setRejected() { super.setRejected(); - callback.setRejected(); + promise.setError("rejected"); } }); - return callback; + return promise; } - private void fireSelected(Configurable configurable, ActionCallback callback) { - myFilter.myContext.fireSelected(configurable, this).doWhenProcessed(callback.createSetDoneRunnable()); + @NotNull + private Promise fireSelected(Configurable configurable) { + return myFilter.myContext.fireSelected(configurable, this); } @Override @@ -426,39 +440,43 @@ public class SettingsTreeView extends JComponent implements Accessible, Disposab myQueuedConfigurable = null; } + @NotNull @Override - public ActionCallback onSelected(@Nullable Configurable configurable, Configurable oldConfigurable) { + public Promise onSelected(@Nullable Configurable configurable, Configurable oldConfigurable) { return select(configurable); } + @NotNull @Override - public ActionCallback onModifiedAdded(Configurable configurable) { + public Promise onModifiedAdded(Configurable configurable) { myTree.repaint(); - return ActionCallback.DONE; + return Promises.resolvedPromise(); } + @NotNull @Override - public ActionCallback onModifiedRemoved(Configurable configurable) { + public Promise onModifiedRemoved(Configurable configurable) { myTree.repaint(); - return ActionCallback.DONE; + return Promises.resolvedPromise(); } + @NotNull @Override - public ActionCallback onErrorsChanged() { - return ActionCallback.DONE; + public Promise onErrorsChanged() { + return Promises.resolvedPromise(); } private final class MyRoot extends CachingSimpleNode { - private final ConfigurableGroup[] myGroups; + private final List myGroups; - private MyRoot(ConfigurableGroup[] groups) { + private MyRoot(List groups) { super(null); myGroups = groups; } @Override protected SimpleNode[] buildChildren() { - if (myGroups == null || myGroups.length == 0) { + if (myGroups == null || myGroups.isEmpty()) { return NO_CHILDREN; } ArrayList list = new ArrayList<>(); @@ -922,8 +940,9 @@ public class SettingsTreeView extends JComponent implements Accessible, Disposab return false; } + @NotNull @Override - protected ActionCallback refilterNow(Object preferredSelection, boolean adjustSelection) { + protected Promise refilterNow(Object preferredSelection, boolean adjustSelection) { final List toRestore = new ArrayList<>(); if (myFilter.myContext.isHoldingFilter() && !myWasHoldingFilter && myToExpandOnResetFilter == null) { AbstractTreeUi ui = myBuilder.getUi(); @@ -936,14 +955,14 @@ public class SettingsTreeView extends JComponent implements Accessible, Disposab myWasHoldingFilter = myFilter.myContext.isHoldingFilter(); - ActionCallback result = super.refilterNow(preferredSelection, adjustSelection); myRefilteringNow = true; - return result.doWhenDone(() -> { - myRefilteringNow = false; - if (!myFilter.myContext.isHoldingFilter() && getSelectedElements().isEmpty()) { - restoreExpandedState(toRestore); - } - }); + return super.refilterNow(preferredSelection, adjustSelection) + .onSuccess(o -> { + myRefilteringNow = false; + if (!myFilter.myContext.isHoldingFilter() && getSelectedElements().isEmpty()) { + restoreExpandedState(toRestore); + } + }); } private void restoreExpandedState(List toRestore) { diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/JBProtocolOpenProjectCommand.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/JBProtocolOpenProjectCommand.java index 9306509f500e..a879e31e280a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/JBProtocolOpenProjectCommand.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/JBProtocolOpenProjectCommand.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-2019 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.openapi.project.impl; import com.intellij.ide.impl.ProjectUtil; @@ -21,21 +7,31 @@ import com.intellij.openapi.application.JBProtocolCommand; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; +import org.jetbrains.annotations.NotNull; +import java.io.UnsupportedEncodingException; import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; import java.util.Map; /** * @author Konstantin Bulenkov */ -public class JBProtocolOpenProjectCommand extends JBProtocolCommand { - public JBProtocolOpenProjectCommand() { +final class JBProtocolOpenProjectCommand extends JBProtocolCommand { + JBProtocolOpenProjectCommand() { super("open"); } @Override - public void perform(String target, Map parameters) { - String path = URLDecoder.decode(target); + public void perform(String target, @NotNull Map parameters) { + String path; + try { + path = URLDecoder.decode(target, StandardCharsets.UTF_8.name()); + } + catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + String projectPath = StringUtil.trimStart(path, LocalFileSystem.PROTOCOL_PREFIX); ApplicationManager.getApplication().invokeLater( () -> ProjectUtil.openProject(projectPath, null, true), ModalityState.NON_MODAL); diff --git a/platform/platform-impl/src/com/intellij/ui/popup/tree/TreePopupImpl.java b/platform/platform-impl/src/com/intellij/ui/popup/tree/TreePopupImpl.java index f7775fdb5cb6..bf7bb0f78bf5 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/tree/TreePopupImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/tree/TreePopupImpl.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 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. +// Copyright 2000-2019 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.ui.popup.tree; import com.intellij.icons.AllIcons; @@ -18,7 +18,6 @@ import com.intellij.ui.popup.WizardPopup; import com.intellij.ui.treeStructure.SimpleTree; import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder; import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure; -import com.intellij.util.Range; import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.NotNull; @@ -456,7 +455,7 @@ public class TreePopupImpl extends WizardPopup implements TreePopup, NextStepHan @Override protected void onSpeedSearchPatternChanged() { - myBuilder.refilter(); + myBuilder.refilterAsync(); } @Override diff --git a/platform/platform-impl/src/org/jetbrains/io/Responses.kt b/platform/platform-impl/src/org/jetbrains/io/Responses.kt index 993b92653687..16567faae523 100644 --- a/platform/platform-impl/src/org/jetbrains/io/Responses.kt +++ b/platform/platform-impl/src/org/jetbrains/io/Responses.kt @@ -41,6 +41,7 @@ fun HttpResponse.setDate() { } fun HttpResponse.addNoCache(): HttpResponse { + @Suppress("SpellCheckingInspection") headers().add(HttpHeaderNames.CACHE_CONTROL, "no-cache, no-store, must-revalidate, max-age=0") headers().add(HttpHeaderNames.PRAGMA, "no-cache") return this @@ -121,11 +122,10 @@ fun HttpResponseStatus.send(channel: Channel, request: HttpRequest? = null, desc } fun HttpResponseStatus.orInSafeMode(safeStatus: HttpResponseStatus): HttpResponseStatus { - if (Registry.`is`("ide.http.server.response.actual.status", true) || (ApplicationManager.getApplication()?.isUnitTestMode ?: false)) { - return this - } - else { - return safeStatus + @Suppress("NullableBooleanElvis") + return when { + Registry.`is`("ide.http.server.response.actual.status", true) || ApplicationManager.getApplication()?.isUnitTestMode ?: false -> this + else -> safeStatus } } diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index eb1737274c9d..1fa6abc3b54a 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -785,7 +785,7 @@ settings.code.style.import.xml.error.can.not.load=Can''t load code style scheme group.richcopy=Rich-text copy combobox.enable.richcopy.by.default=Copy as rich text by default -combobox.richcopy.color.scheme=Color scheme +combobox.richcopy.color.scheme=Color scheme: combobox.richcopy.color.scheme.active=Active scheme settings.code.style.default.general=Default diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 82fad1f2f133..8d05b2b51b77 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -98,6 +98,8 @@ errortree.note=Note: action.show.warnings=Show warnings action.next.message=Next Message action.previous.message=Previous Message +action.next.problem=Next Problem +action.previous.problem=Previous Problem action.stop=Stop errortree.prefix.line=line ({0}) checkbox.errortree.export.details=Details diff --git a/platform/platform-resources-en/src/messages/OptionsBundle.properties b/platform/platform-resources-en/src/messages/OptionsBundle.properties index ac623b33d3e7..bad56b3012cf 100644 --- a/platform/platform-resources-en/src/messages/OptionsBundle.properties +++ b/platform/platform-resources-en/src/messages/OptionsBundle.properties @@ -299,6 +299,9 @@ configurable.group.profiler.settings.description=\ # for com.intellij.psi.css.codeStyle.CssLanguageCodeStyleSettingsProvider.STYLESHEET_GROUP stylesheet.code.style.group.settings.description=Configure the code style used in the style sheet languages. +# suppress inspection "UnusedProperty" - for generating list of inner configurables, see ConfigurableEditor#createDefaultContent +sql.code.style.group.settings.description=Configure the code style used in SQL dialects. + configurable.default.project.tooltip=For new {0}s configurable.current.project.tooltip=For current {0} diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt index bf71c48500c1..1c67338a3899 100644 --- a/platform/platform-resources/src/brokenPlugins.txt +++ b/platform/platform-resources/src/brokenPlugins.txt @@ -115,4 +115,5 @@ Bazel 2018.12.03.0.2 2018.11.12.0.4 ru.makkarpov.ucl 0.1 0.1.1 0.1.2 com.undo_software.clion.reverse 2.0.0 "Randori Compiler" 0.2.0 0.2.1 0.2.3 0.2.4 0.3.0 -Docker 173.2605 191.4212.41 191.4738.6 \ No newline at end of file +Docker 173.2605 191.4212.41 191.4738.6 +"Log Support" 1.0.11-11_and_newer \ No newline at end of file diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index b372ab35d646..cdd6722fa986 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -513,6 +513,8 @@ + diff --git a/platform/platform-tests/testSrc/com/intellij/ide/util/treeView/FilteringTreeBuilderTest.java b/platform/platform-tests/testSrc/com/intellij/ide/util/treeView/FilteringTreeBuilderTest.java index dfafa2598438..c6de34f5f6de 100644 --- a/platform/platform-tests/testSrc/com/intellij/ide/util/treeView/FilteringTreeBuilderTest.java +++ b/platform/platform-tests/testSrc/com/intellij/ide/util/treeView/FilteringTreeBuilderTest.java @@ -1,7 +1,6 @@ -// Copyright 2000-2018 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. +// Copyright 2000-2019 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.util.treeView; -import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Ref; import com.intellij.ui.TreeUIHelper; @@ -9,7 +8,9 @@ import com.intellij.ui.speedSearch.ElementFilter; import com.intellij.ui.treeStructure.*; import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder; import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.concurrency.Promise; import java.util.LinkedHashMap; @@ -175,7 +176,7 @@ public class FilteringTreeBuilderTest extends BaseTreeTestCase { myFilter.update(text, selection); } - private class Node extends CachingSimpleNode { + private static class Node extends CachingSimpleNode { private final LinkedHashMap myKids = new LinkedHashMap<>(); @@ -209,7 +210,6 @@ public class FilteringTreeBuilderTest extends BaseTreeTestCase { @Override protected void updateFileStatus() { - } } @@ -240,7 +240,8 @@ public class FilteringTreeBuilderTest extends BaseTreeTestCase { return value.toString().startsWith(myPattern); } - public ActionCallback update(final String pattern, Object selection) { + @NotNull + public Promise update(final String pattern, Object selection) { myPattern = pattern; return fireUpdate(selection, true, false); } diff --git a/platform/platform-tests/testSrc/com/intellij/internal/statistics/SensitiveDataValidatorTest.kt b/platform/platform-tests/testSrc/com/intellij/internal/statistics/SensitiveDataValidatorTest.kt index 14e7a145241e..c0bac868ee95 100644 --- a/platform/platform-tests/testSrc/com/intellij/internal/statistics/SensitiveDataValidatorTest.kt +++ b/platform/platform-tests/testSrc/com/intellij/internal/statistics/SensitiveDataValidatorTest.kt @@ -79,8 +79,8 @@ class SensitiveDataValidatorTest : UsefulTestCase() { assertEmpty(validator.getEventRules(eventLogGroup)) assertTrue(validator.getEventDataRules(eventLogGroup).isEmpty()) - assertEventAccepted(validator, eventLogGroup, "") - assertEventDataAccepted(validator, eventLogGroup, "", "") + assertUndefinedRule(validator, eventLogGroup, "") + assertEventDataUndefinedRule(validator, eventLogGroup, "", "") } @Test @@ -197,6 +197,10 @@ class SensitiveDataValidatorTest : UsefulTestCase() { TestCase.assertEquals(ValidationResultType.ACCEPTED, validator.validateEvent(eventLogGroup, EventContext.create(s, Collections.emptyMap()))) } + private fun assertUndefinedRule(validator: SensitiveDataValidator, eventLogGroup: EventLogGroup, s: String) { + TestCase.assertEquals(ValidationResultType.UNDEFINED_RULE, validator.validateEvent(eventLogGroup, EventContext.create(s, Collections.emptyMap()))) + } + private fun assertEventRejected(validator: SensitiveDataValidator, eventLogGroup: EventLogGroup, s: String) { TestCase.assertEquals(ValidationResultType.REJECTED, validator.validateEvent(eventLogGroup, EventContext.create(s, Collections.emptyMap()))) } @@ -204,6 +208,10 @@ class SensitiveDataValidatorTest : UsefulTestCase() { private fun assertEventDataAccepted(validator: TestSensitiveDataValidator, eventLogGroup: EventLogGroup, key: String, dataValue: String) { TestCase.assertEquals(ValidationResultType.ACCEPTED, validator.validateEventData(eventLogGroup, key, dataValue)) } + + private fun assertEventDataUndefinedRule(validator: TestSensitiveDataValidator, eventLogGroup: EventLogGroup, key: String, dataValue: String) { + TestCase.assertEquals(ValidationResultType.UNDEFINED_RULE, validator.validateEventData(eventLogGroup, key, dataValue)) + } private fun assertEventDataRejected(validator: TestSensitiveDataValidator, eventLogGroup: EventLogGroup, key: String, dataValue: String) { TestCase.assertEquals(ValidationResultType.REJECTED, validator.validateEventData(eventLogGroup, key, dataValue)) } @@ -245,7 +253,7 @@ class SensitiveDataValidatorTest : UsefulTestCase() { if (FeatureUsageData.platformDataKeys.contains(key)) return ValidationResultType.ACCEPTED val whiteListRule = eventsValidators[group.id] - return if (whiteListRule == null || !whiteListRule.areEventDataRulesDefined()) ValidationResultType.ACCEPTED + return if (whiteListRule == null || !whiteListRule.areEventDataRulesDefined()) ValidationResultType.UNDEFINED_RULE else whiteListRule.validateEventData(key, value, EventContext.create("", Collections.emptyMap())) // there are no configured rules } } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/encoding/FileEncodingTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/encoding/FileEncodingTest.java index 3db58a3108fa..e3a606d73d50 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/encoding/FileEncodingTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/encoding/FileEncodingTest.java @@ -79,7 +79,7 @@ public class FileEncodingTest extends PlatformTestCase implements TestDialog { private TestDialog myOldTestDialogValue; @Override - public int show(String message) { + public int show(@NotNull String message) { return 0; } diff --git a/platform/platform-tests/testSrc/com/intellij/search/SearchableOptionsTest.java b/platform/platform-tests/testSrc/com/intellij/search/SearchableOptionsTest.java index a097867ad97d..562dc3aa8be6 100644 --- a/platform/platform-tests/testSrc/com/intellij/search/SearchableOptionsTest.java +++ b/platform/platform-tests/testSrc/com/intellij/search/SearchableOptionsTest.java @@ -1,29 +1,17 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 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.search; -import com.intellij.ide.actions.ShowSettingsUtilImpl; import com.intellij.ide.fileTemplates.impl.AllFileTemplatesConfigurable; import com.intellij.ide.ui.search.ConfigurableHit; import com.intellij.ide.ui.search.SearchableOptionsRegistrar; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurableGroup; +import com.intellij.openapi.options.ex.ConfigurableExtensionPointUtil; import com.intellij.testFramework.LightPlatformTestCase; import javax.swing.event.DocumentEvent; +import java.util.Collections; +import java.util.List; import java.util.Set; /** @@ -31,7 +19,7 @@ import java.util.Set; */ public class SearchableOptionsTest extends LightPlatformTestCase { public void testFindCodeTemplates() { - ConfigurableGroup[] groups = ShowSettingsUtilImpl.getConfigurableGroups(getProject(), false); + List groups = Collections.singletonList(ConfigurableExtensionPointUtil.getConfigurableGroup(getProject(), false)); ConfigurableHit configurables = SearchableOptionsRegistrar.getInstance().getConfigurables(groups, DocumentEvent.EventType.INSERT, null, "method", getProject()); Set configurableSet = configurables.getAll(); for (Configurable configurable : configurableSet) { diff --git a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/JpsOrderEntryFactory.java b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/JpsOrderEntryFactory.java deleted file mode 100644 index 0b83fe2e6cf0..000000000000 --- a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/JpsOrderEntryFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2000-2012 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.project.model.impl.module; - -import com.intellij.project.model.impl.module.dependencies.*; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jps.model.module.*; - -/** - * @author nik - */ -public class JpsOrderEntryFactory { - public static JpsOrderEntry createOrderEntry(@NotNull JpsRootModel model, JpsDependencyElement dependencyElement) { - if (dependencyElement instanceof JpsModuleSourceDependency) { - return new JpsModuleSourceOrderEntry(model, (JpsModuleSourceDependency)dependencyElement); - } - if (dependencyElement instanceof JpsModuleDependency) { - return new JpsModuleOrderEntry(model, (JpsModuleDependency)dependencyElement); - } - if (dependencyElement instanceof JpsLibraryDependency) { - return new JpsLibraryOrderEntry(model, (JpsLibraryDependency)dependencyElement); - } - if (dependencyElement instanceof JpsSdkDependency) { - final JpsSdkDependency sdkDependency = (JpsSdkDependency)dependencyElement; - if (sdkDependency.isInherited()) { - return new JpsInheritedSdkOrderEntry(model, sdkDependency); - } - return new JpsModuleSdkOrderEntry(model, sdkDependency); - } - throw new UnsupportedOperationException(); - } -} diff --git a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/JpsRootModel.java b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/JpsRootModel.java index 94309ab2f117..d43cb4aed55b 100644 --- a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/JpsRootModel.java +++ b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/JpsRootModel.java @@ -21,10 +21,8 @@ import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModuleRootModel; import com.intellij.openapi.roots.OrderEntry; import com.intellij.openapi.roots.impl.RootModelBase; -import com.intellij.openapi.vfs.pointers.VirtualFilePointer; import com.intellij.project.model.impl.module.content.JpsContentEntry; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jps.model.module.JpsDependencyElement; import org.jetbrains.jps.model.module.JpsModule; import java.util.ArrayList; @@ -36,26 +34,14 @@ import java.util.List; */ public class JpsRootModel extends RootModelBase implements ModuleRootModel { private final Module myModule; - private final JpsModule myJpsModule; - public VirtualFilePointer myExplodedDirectoryPointer; private final List myContentEntries; - private final List myOrderEntries; public JpsRootModel(Module module, JpsModule jpsModule) { myModule = module; - myJpsModule = jpsModule; myContentEntries = new ArrayList<>(); - for (String contentRoot : myJpsModule.getContentRootsList().getUrls()) { + for (String contentRoot : jpsModule.getContentRootsList().getUrls()) { myContentEntries.add(new JpsContentEntry(jpsModule, this, contentRoot)); } - myOrderEntries = new ArrayList<>(); - for (JpsDependencyElement element : myJpsModule.getDependenciesList().getDependencies()) { - myOrderEntries.add(JpsOrderEntryFactory.createOrderEntry(this, element)); - } - } - - public JpsModule getJpsModule() { - return myJpsModule; } @NotNull @@ -72,7 +58,7 @@ public class JpsRootModel extends RootModelBase implements ModuleRootModel { @NotNull @Override public OrderEntry[] getOrderEntries() { - return myOrderEntries.toArray(OrderEntry.EMPTY_ARRAY); + return OrderEntry.EMPTY_ARRAY; } @Override @@ -83,8 +69,4 @@ public class JpsRootModel extends RootModelBase implements ModuleRootModel { public Project getProject() { return myModule.getProject(); } - - public boolean isExcludeExplodedDirectory() { - return false; - } } diff --git a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsExportableOrderEntry.java b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsExportableOrderEntry.java deleted file mode 100644 index 2ba7616617b1..000000000000 --- a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsExportableOrderEntry.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2000-2012 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.project.model.impl.module.dependencies; - -import com.intellij.openapi.roots.DependencyScope; -import com.intellij.openapi.roots.ExportableOrderEntry; -import com.intellij.project.model.impl.module.JpsRootModel; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jps.model.java.JpsJavaDependencyExtension; -import org.jetbrains.jps.model.java.JpsJavaDependencyScope; -import org.jetbrains.jps.model.java.JpsJavaExtensionService; -import org.jetbrains.jps.model.module.JpsDependencyElement; - -/** - * @author nik - */ -public abstract class JpsExportableOrderEntry extends JpsOrderEntry implements ExportableOrderEntry { - public JpsExportableOrderEntry(@NotNull JpsRootModel rootModel, @NotNull E dependencyElement) { - super(rootModel, dependencyElement); - } - - @Override - public boolean isExported() { - final JpsJavaDependencyExtension extension = getExtension(); - return extension != null && extension.isExported(); - } - - @Override - public void setExported(boolean value) { - JpsJavaExtensionService.getInstance().getOrCreateDependencyExtension(myDependencyElement).setExported(value); - } - - @NotNull - @Override - public DependencyScope getScope() { - final JpsJavaDependencyExtension extension = getExtension(); - return extension != null ? DependencyScope.valueOf(extension.getScope().name()) : DependencyScope.COMPILE; - } - - @Nullable - private JpsJavaDependencyExtension getExtension() { - return JpsJavaExtensionService.getInstance().getDependencyExtension(myDependencyElement); - } - - @Override - public void setScope(@NotNull DependencyScope scope) { - final JpsJavaDependencyExtension extension = JpsJavaExtensionService.getInstance().getOrCreateDependencyExtension(myDependencyElement); - extension.setScope(JpsJavaDependencyScope.valueOf(scope.name())); - } -} diff --git a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsInheritedSdkOrderEntry.java b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsInheritedSdkOrderEntry.java deleted file mode 100644 index 7008c3190f45..000000000000 --- a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsInheritedSdkOrderEntry.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2000-2012 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.project.model.impl.module.dependencies; - -import com.intellij.openapi.roots.InheritedJdkOrderEntry; -import com.intellij.openapi.roots.RootPolicy; -import com.intellij.project.model.impl.module.JpsRootModel; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jps.model.module.JpsSdkDependency; - -/** - * @author nik - */ -public class JpsInheritedSdkOrderEntry extends JpsSdkOrderEntryBase implements InheritedJdkOrderEntry { - public JpsInheritedSdkOrderEntry(@NotNull JpsRootModel rootModel, @NotNull JpsSdkDependency dependencyElement) { - super(rootModel, dependencyElement); - } - - @Override - public R accept(@NotNull RootPolicy policy, @Nullable R initialValue) { - return policy.visitInheritedJdkOrderEntry(this, initialValue); - } -} diff --git a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsLibraryOrderEntry.java b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsLibraryOrderEntry.java deleted file mode 100644 index 7b2046936450..000000000000 --- a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsLibraryOrderEntry.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2000-2012 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.project.model.impl.module.dependencies; - -import com.intellij.openapi.roots.LibraryOrderEntry; -import com.intellij.openapi.roots.OrderRootType; -import com.intellij.openapi.roots.RootPolicy; -import com.intellij.openapi.roots.impl.libraries.LibraryTableImplUtil; -import com.intellij.openapi.roots.libraries.Library; -import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.project.model.impl.module.JpsRootModel; -import com.intellij.util.ArrayUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jps.model.JpsCompositeElement; -import org.jetbrains.jps.model.JpsElementReference; -import org.jetbrains.jps.model.JpsGlobal; -import org.jetbrains.jps.model.JpsProject; -import org.jetbrains.jps.model.module.JpsLibraryDependency; -import org.jetbrains.jps.model.module.JpsModule; - -/** - * @author nik - */ -public class JpsLibraryOrderEntry extends JpsExportableOrderEntry implements LibraryOrderEntry { - public JpsLibraryOrderEntry(@NotNull JpsRootModel rootModel, @NotNull JpsLibraryDependency dependencyElement) { - super(rootModel, dependencyElement); - } - - @Override - public Library getLibrary() { - return null; - } - - @Override - @NotNull - public String getLibraryName() { - return myDependencyElement.getLibraryReference().getLibraryName(); - } - - @NotNull - @Override - public String getPresentableName() { - return getLibraryName(); - } - - @NotNull - @Override - public VirtualFile[] getFiles(@NotNull OrderRootType type) { - return getRootFiles(type); - } - - @NotNull - @Override - public String[] getUrls(@NotNull OrderRootType rootType) { - return getRootUrls(rootType); - } - - @NotNull - @Override - public VirtualFile[] getRootFiles(@NotNull OrderRootType type) { - final Library library = getLibrary(); - return library != null ? library.getFiles(type) : VirtualFile.EMPTY_ARRAY; - } - - @NotNull - @Override - public String[] getRootUrls(@NotNull OrderRootType type) { - final Library library = getLibrary(); - return library != null ? library.getUrls(type) : ArrayUtil.EMPTY_STRING_ARRAY; - } - - @Override - public String getLibraryLevel() { - final JpsElementReference reference = myDependencyElement.getLibraryReference().getParentReference(); - final JpsCompositeElement parent = reference.resolve(); - if (parent instanceof JpsGlobal) return LibraryTablesRegistrar.APPLICATION_LEVEL; - if (parent instanceof JpsProject) return LibraryTablesRegistrar.PROJECT_LEVEL; - if (parent instanceof JpsModule) return LibraryTableImplUtil.MODULE_LEVEL; - return LibraryTablesRegistrar.PROJECT_LEVEL; - } - - @Override - public boolean isModuleLevel() { - return LibraryTableImplUtil.MODULE_LEVEL.equals(getLibraryLevel()); - } - - @Override - public R accept(@NotNull RootPolicy policy, @Nullable R initialValue) { - return policy.visitLibraryOrderEntry(this, initialValue); - } -} diff --git a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsModuleOrderEntry.java b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsModuleOrderEntry.java deleted file mode 100644 index 540d4fe56dd5..000000000000 --- a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsModuleOrderEntry.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2000-2012 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.project.model.impl.module.dependencies; - -import com.intellij.openapi.module.Module; -import com.intellij.openapi.roots.ModuleOrderEntry; -import com.intellij.openapi.roots.OrderRootType; -import com.intellij.openapi.roots.OrderRootsEnumerator; -import com.intellij.openapi.roots.RootPolicy; -import com.intellij.openapi.roots.impl.ModuleRootManagerImpl; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.project.model.impl.module.JpsRootModel; -import com.intellij.util.ArrayUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jps.model.module.JpsModuleDependency; - -/** - * @author nik - */ -public class JpsModuleOrderEntry extends JpsExportableOrderEntry implements ModuleOrderEntry { - public JpsModuleOrderEntry(@NotNull JpsRootModel rootModel, JpsModuleDependency dependencyElement) { - super(rootModel, dependencyElement); - } - - @Override - public Module getModule() { - return null; - } - - @NotNull - @Override - public String getModuleName() { - return myDependencyElement.getModuleReference().getModuleName(); - } - - @NotNull - @Override - public String getPresentableName() { - return getModuleName(); - } - - @Override - @NotNull - public VirtualFile[] getFiles(@NotNull OrderRootType type) { - final OrderRootsEnumerator enumerator = getEnumerator(type); - return enumerator != null ? enumerator.getRoots() : VirtualFile.EMPTY_ARRAY; - } - - @Nullable - private OrderRootsEnumerator getEnumerator(OrderRootType type) { - final Module module = getModule(); - if (module == null) return null; - - return ModuleRootManagerImpl.getCachingEnumeratorForType(type, module); - } - - @Override - @NotNull - public String[] getUrls(@NotNull OrderRootType rootType) { - final OrderRootsEnumerator enumerator = getEnumerator(rootType); - return enumerator != null ? enumerator.getUrls() : ArrayUtil.EMPTY_STRING_ARRAY; - } - - @Override - public R accept(@NotNull RootPolicy policy, @Nullable R initialValue) { - return policy.visitModuleOrderEntry(this, initialValue); - } -} diff --git a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsModuleSdkOrderEntry.java b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsModuleSdkOrderEntry.java deleted file mode 100644 index ce9d8dac2794..000000000000 --- a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsModuleSdkOrderEntry.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2000-2012 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.project.model.impl.module.dependencies; - -import com.intellij.openapi.roots.ModuleJdkOrderEntry; -import com.intellij.openapi.roots.RootPolicy; -import com.intellij.project.model.impl.module.JpsRootModel; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jps.model.module.JpsSdkDependency; - -/** - * @author nik - */ -public class JpsModuleSdkOrderEntry extends JpsSdkOrderEntryBase implements ModuleJdkOrderEntry { - public JpsModuleSdkOrderEntry(@NotNull JpsRootModel rootModel, @NotNull JpsSdkDependency dependencyElement) { - super(rootModel, dependencyElement); - } - - @Override - public R accept(@NotNull RootPolicy policy, @Nullable R initialValue) { - return policy.visitModuleJdkOrderEntry(this, initialValue); - } -} diff --git a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsModuleSourceOrderEntry.java b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsModuleSourceOrderEntry.java deleted file mode 100644 index 7cbacc265d83..000000000000 --- a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsModuleSourceOrderEntry.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2000-2012 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.project.model.impl.module.dependencies; - -import com.intellij.openapi.project.ProjectBundle; -import com.intellij.openapi.roots.*; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.project.model.impl.module.JpsRootModel; -import com.intellij.util.ArrayUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jps.model.module.JpsModuleSourceDependency; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author nik - */ -public class JpsModuleSourceOrderEntry extends JpsOrderEntry implements ModuleSourceOrderEntry { - public JpsModuleSourceOrderEntry(@NotNull JpsRootModel rootModel, @NotNull JpsModuleSourceDependency dependencyElement) { - super(rootModel, dependencyElement); - } - - @Override - public R accept(@NotNull RootPolicy policy, @Nullable R initialValue) { - return policy.visitModuleSourceOrderEntry(this, initialValue); - } - - @NotNull - @Override - public String getPresentableName() { - return ProjectBundle.message("project.root.module.source"); - } - - @Override - @NotNull - public VirtualFile[] getFiles(@NotNull OrderRootType type) { - if (OrderRootType.SOURCES.equals(type)) { - return getRootModel().getSourceRoots(); - } - return VirtualFile.EMPTY_ARRAY; - } - - @Override - @NotNull - public String[] getUrls(@NotNull OrderRootType type) { - if (OrderRootType.SOURCES.equals(type)) { - final ContentEntry[] content = getRootModel().getContentEntries(); - List result = new ArrayList<>(); - for (ContentEntry contentEntry : content) { - final SourceFolder[] sourceFolders = contentEntry.getSourceFolders(); - for (SourceFolder sourceFolder : sourceFolders) { - final String url = sourceFolder.getUrl(); - result.add(url); - } - } - return ArrayUtil.toStringArray(result); - } - return ArrayUtil.EMPTY_STRING_ARRAY; - } - - @Override - @NotNull - public ModuleRootModel getRootModel() { - return myRootModel; - } -} diff --git a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsOrderEntry.java b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsOrderEntry.java deleted file mode 100644 index b0d000aae13c..000000000000 --- a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsOrderEntry.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2000-2012 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.project.model.impl.module.dependencies; - -import com.intellij.openapi.module.Module; -import com.intellij.openapi.roots.OrderEntry; -import com.intellij.project.model.impl.module.JpsRootModel; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jps.model.module.JpsDependencyElement; - -/** - * @author nik - */ -public abstract class JpsOrderEntry implements OrderEntry { - @NotNull - protected final JpsRootModel myRootModel; - @NotNull - protected final E myDependencyElement; - - protected JpsOrderEntry(@NotNull JpsRootModel rootModel, @NotNull E dependencyElement) { - myRootModel = rootModel; - myDependencyElement = dependencyElement; - } - - @NotNull - @Override - public Module getOwnerModule() { - return myRootModel.getModule(); - } - - @Override - public boolean isSynthetic() { - return false; - } - - @Override - public boolean isValid() { - return true; - } - - @Override - public int compareTo(OrderEntry o) { - throw new UnsupportedOperationException("'compareTo' not implemented in " + getClass().getName()); - } -} diff --git a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsSdkOrderEntryBase.java b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsSdkOrderEntryBase.java deleted file mode 100644 index 0516e69e3c43..000000000000 --- a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/dependencies/JpsSdkOrderEntryBase.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2000-2012 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.project.model.impl.module.dependencies; - -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.roots.JdkOrderEntry; -import com.intellij.openapi.roots.OrderRootType; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.project.model.JpsSdkManager; -import com.intellij.project.model.impl.module.JpsRootModel; -import com.intellij.util.ArrayUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jps.model.library.JpsLibrary; -import org.jetbrains.jps.model.library.sdk.JpsSdkReference; -import org.jetbrains.jps.model.module.JpsSdkDependency; - -/** - * @author nik - */ -public abstract class JpsSdkOrderEntryBase extends JpsOrderEntry implements JdkOrderEntry { - public JpsSdkOrderEntryBase(@NotNull JpsRootModel rootModel, @NotNull JpsSdkDependency dependencyElement) { - super(rootModel, dependencyElement); - } - - @Override - public String getJdkName() { - final JpsSdkReference reference = myDependencyElement.getSdkReference(); - return reference != null ? reference.getSdkName() : null; - } - - @NotNull - @Override - public VirtualFile[] getFiles(@NotNull OrderRootType type) { - return getRootFiles(type); - } - - @NotNull - @Override - public String[] getUrls(@NotNull OrderRootType rootType) { - return getRootUrls(rootType); - } - - @Override - public Sdk getJdk() { - final JpsLibrary library = myDependencyElement.resolveSdk(); - if (library == null) return null; - return JpsSdkManager.getInstance().getSdk(library); - } - - @NotNull - @Override - public String getPresentableName() { - return "< " + getJdkName() + " >"; - } - - @NotNull - @Override - public VirtualFile[] getRootFiles(@NotNull OrderRootType type) { - final Sdk sdk = getJdk(); - if (sdk == null) return VirtualFile.EMPTY_ARRAY; - return sdk.getRootProvider().getFiles(type); - } - - @NotNull - @Override - public String[] getRootUrls(@NotNull OrderRootType type) { - final Sdk jdk = getJdk(); - if (jdk == null) return ArrayUtil.EMPTY_STRING_ARRAY; - return jdk.getRootProvider().getUrls(type); - } - - @Override - public boolean isSynthetic() { - return true; - } -} diff --git a/platform/testFramework/src/com/intellij/testFramework/propertyBased/MadTestingUtil.java b/platform/testFramework/src/com/intellij/testFramework/propertyBased/MadTestingUtil.java index fe2572f26898..a1bb973e14e8 100644 --- a/platform/testFramework/src/com/intellij/testFramework/propertyBased/MadTestingUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/propertyBased/MadTestingUtil.java @@ -181,6 +181,8 @@ public class MadTestingUtil { for (String shortId : except) { disableInspection(project, profile, shortId); } + // instantiate all tools to avoid extension loading in inconvenient moment + profile.getAllEnabledInspectionTools(project).forEach(state -> state.getTool().getTool()); ProjectInspectionProfileManager manager = (ProjectInspectionProfileManager)InspectionProjectProfileManager.getInstance(project); manager.addProfile(profile); diff --git a/platform/util/src/com/intellij/openapi/application/JetBrainsProtocolHandler.java b/platform/util/src/com/intellij/openapi/application/JetBrainsProtocolHandler.java index d771b130938c..16c83f402704 100644 --- a/platform/util/src/com/intellij/openapi/application/JetBrainsProtocolHandler.java +++ b/platform/util/src/com/intellij/openapi/application/JetBrainsProtocolHandler.java @@ -1,22 +1,9 @@ -/* - * 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-2019 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.openapi.application; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collections; @@ -64,7 +51,8 @@ public class JetBrainsProtocolHandler { } else { ourParameters.put(key, value); } - } else { + } + else { ourParameters.put(keyValue, ""); } } @@ -102,6 +90,7 @@ public class JetBrainsProtocolHandler { ourCommand = null; } + @NotNull public static Map getParameters() { init(); return Collections.unmodifiableMap(ourParameters); diff --git a/platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java b/platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java index d0fc924210b3..99d87d6b2542 100644 --- a/platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java +++ b/platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java @@ -18,7 +18,6 @@ import java.util.MissingResourceException; * @author Konstantin Bulenkov */ public class RegistryValue { - private final Registry myRegistry; private final String myKey; @Nullable private final RegistryKeyDescriptor myKeyDescriptor; @@ -121,7 +120,7 @@ public class RegistryValue { if (myKeyDescriptor != null) { return myKeyDescriptor.isRestartRequired(); } - return Boolean.valueOf(get(myKey + ".restartRequired", "false", false)); + return Boolean.parseBoolean(get(myKey + ".restartRequired", "false", false)); } public boolean isChangedFromDefault() { @@ -191,37 +190,22 @@ public class RegistryValue { LOG.info("Registry value '" + myKey + "' has changed to '" + value + '\''); } - public void setValue(boolean value, Disposable parentDisposable) { + public void setValue(boolean value, @NotNull Disposable parentDisposable) { final boolean prev = asBoolean(); setValue(value); - Disposer.register(parentDisposable, new Disposable() { - @Override - public void dispose() { - setValue(prev); - } - }); + Disposer.register(parentDisposable, () -> setValue(prev)); } - public void setValue(int value, Disposable parentDisposable) { + public void setValue(int value, @NotNull Disposable parentDisposable) { final int prev = asInteger(); setValue(value); - Disposer.register(parentDisposable, new Disposable() { - @Override - public void dispose() { - setValue(prev); - } - }); + Disposer.register(parentDisposable, () -> setValue(prev)); } - public void setValue(String value, Disposable parentDisposable) { + public void setValue(String value, @NotNull Disposable parentDisposable) { final String prev = asString(); setValue(value); - Disposer.register(parentDisposable, new Disposable() { - @Override - public void dispose() { - setValue(prev); - } - }); + Disposer.register(parentDisposable, () -> setValue(prev)); } boolean isChangedSinceAppStart() { @@ -234,12 +218,7 @@ public class RegistryValue { public void addListener(@NotNull final RegistryValueListener listener, @NotNull Disposable parent) { myListeners.add(listener); - Disposer.register(parent, new Disposable() { - @Override - public void dispose() { - myListeners.remove(listener); - } - }); + Disposer.register(parent, () -> myListeners.remove(listener)); } @Override diff --git a/platform/util/src/com/intellij/util/indexing/impl/InputData.java b/platform/util/src/com/intellij/util/indexing/impl/InputData.java deleted file mode 100644 index 1761f3a44217..000000000000 --- a/platform/util/src/com/intellij/util/indexing/impl/InputData.java +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2000-2019 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.util.indexing.impl; - -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.Map; - -public class InputData { - private static final InputData EMPTY = new InputData<>(Collections.emptyMap()); - - @SuppressWarnings("unchecked") - public static InputData empty() { - return EMPTY; - } - - @NotNull - private final Map myKeyValues; - - protected InputData(@NotNull Map values) { - myKeyValues = values; - } - - @NotNull - public Map getKeyValues() { - return myKeyValues; - } -} diff --git a/platform/util/src/com/intellij/util/indexing/impl/MapReduceIndex.java b/platform/util/src/com/intellij/util/indexing/impl/MapReduceIndex.java index 4e3c0c544ade..1db858cf0985 100644 --- a/platform/util/src/com/intellij/util/indexing/impl/MapReduceIndex.java +++ b/platform/util/src/com/intellij/util/indexing/impl/MapReduceIndex.java @@ -56,7 +56,7 @@ public abstract class MapReduceIndex implements InvertedIndex< protected final ForwardIndex myForwardIndex; //new private final com.intellij.util.indexing.impl.forward.ForwardIndex myForwardIndexMap; - private final ForwardIndexAccessor myForwardIndexAccessor; + private final ForwardIndexAccessor myForwardIndexAccessor; private final ReentrantReadWriteLock myLock = createLock(); private final boolean myUseIntForwardIndex; @@ -85,7 +85,7 @@ public abstract class MapReduceIndex implements InvertedIndex< protected MapReduceIndex(@NotNull IndexExtension extension, @NotNull IndexStorage storage, @Nullable com.intellij.util.indexing.impl.forward.ForwardIndex forwardIndexMap, - @Nullable ForwardIndexAccessor forwardIndexAccessor, + @Nullable ForwardIndexAccessor forwardIndexAccessor, @Nullable ForwardIndex forwardIndex) { myIndexId = extension.getName(); myExtension = extension; @@ -102,7 +102,7 @@ public abstract class MapReduceIndex implements InvertedIndex< protected MapReduceIndex(@NotNull IndexExtension extension, @NotNull IndexStorage storage, @Nullable com.intellij.util.indexing.impl.forward.ForwardIndex forwardIndex, - @Nullable ForwardIndexAccessor forwardIndexAccessor) { + @Nullable ForwardIndexAccessor forwardIndexAccessor) { this(extension, storage, forwardIndex, forwardIndexAccessor, null); } @@ -117,7 +117,7 @@ public abstract class MapReduceIndex implements InvertedIndex< return myForwardIndexMap; } - public ForwardIndexAccessor getForwardIndexAccessor() { + public ForwardIndexAccessor getForwardIndexAccessor() { return myForwardIndexAccessor; } @@ -266,19 +266,26 @@ public abstract class MapReduceIndex implements InvertedIndex< @NotNull protected UpdateData calculateUpdateData(final int inputId, @Nullable Input content) { - final InputData data = mapInput(content); - return createUpdateData(data.getKeyValues(), + final Map data = mapInput(content); + Object forwardIndexData; + if (myForwardIndexAccessor != null) { + forwardIndexData = myForwardIndexAccessor.convertToDataType(data, content); + } else { + forwardIndexData = null; + } + return createUpdateData(data, () -> getKeysDiffBuilder(inputId), - () -> updateForwardIndex(inputId, data)); + () -> updateForwardIndex(inputId, data, forwardIndexData)); } - protected void updateForwardIndex(int inputId, @NotNull InputData data) throws IOException { - if (myForwardIndex != null) myForwardIndex.putInputData(inputId, data.getKeyValues()); + protected void updateForwardIndex(int inputId, @NotNull Map data, @Nullable Object forwardIndexData) throws IOException { + if (myForwardIndex != null) myForwardIndex.putInputData(inputId, data); if (myForwardIndexMap != null) { if (myUseIntForwardIndex) { - ((IntForwardIndex)myForwardIndexMap).putInt(inputId, ((IntForwardIndexAccessor)myForwardIndexAccessor).serializeIndexedDataToInt(data)); + ((IntForwardIndex)myForwardIndexMap).putInt(inputId, (Integer)forwardIndexData); } else { - myForwardIndexMap.put(inputId, myForwardIndexAccessor.serializeIndexedData(data)); + //noinspection unchecked + myForwardIndexMap.put(inputId, ((ForwardIndexAccessor)myForwardIndexAccessor).serializeIndexedData(forwardIndexData)); } } } @@ -306,14 +313,14 @@ public abstract class MapReduceIndex implements InvertedIndex< } @NotNull - protected InputData mapInput(@Nullable Input content) { + protected Map mapInput(@Nullable Input content) { if (content == null) { - return InputData.empty(); + return Collections.emptyMap(); } Map data = myIndexer.map(content); checkValuesHaveProperEqualsAndHashCode(data, myIndexId, myValueExternalizer); checkCanceled(); - return new InputData<>(data); + return data; } public abstract void checkCanceled(); diff --git a/platform/util/src/com/intellij/util/indexing/impl/forward/AbstractForwardIndexAccessor.java b/platform/util/src/com/intellij/util/indexing/impl/forward/AbstractForwardIndexAccessor.java index 539b58e161a8..cb57a5b0c829 100644 --- a/platform/util/src/com/intellij/util/indexing/impl/forward/AbstractForwardIndexAccessor.java +++ b/platform/util/src/com/intellij/util/indexing/impl/forward/AbstractForwardIndexAccessor.java @@ -5,7 +5,6 @@ import com.intellij.openapi.util.ThreadLocalCachedByteArray; import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream; import com.intellij.openapi.util.io.ByteArraySequence; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.indexing.impl.InputData; import com.intellij.util.indexing.impl.InputDataDiffBuilder; import com.intellij.util.io.DataExternalizer; import com.intellij.util.io.DataOutputStream; @@ -19,7 +18,7 @@ import java.io.IOException; import java.util.Map; @ApiStatus.Experimental -public abstract class AbstractForwardIndexAccessor implements ForwardIndexAccessor { +public abstract class AbstractForwardIndexAccessor implements ForwardIndexAccessor { @NotNull private final DataExternalizer myDataTypeExternalizer; @@ -41,16 +40,8 @@ public abstract class AbstractForwardIndexAccessor impleme return createDiffBuilder(inputId, deserializeData(sequence)); } - @Nullable - public abstract DataType convertToDataType(@NotNull InputData data); - @Nullable @Override - public ByteArraySequence serializeIndexedData(@NotNull InputData data) throws IOException { - return serializeIndexedData(convertToDataType(data)); - } - - @Nullable public ByteArraySequence serializeIndexedData(@Nullable DataType data) throws IOException { if (data == null) return null; return serializeToByteSeq(data, myDataTypeExternalizer, getBufferInitialSize(data)); diff --git a/platform/util/src/com/intellij/util/indexing/impl/forward/AbstractMapForwardIndexAccessor.java b/platform/util/src/com/intellij/util/indexing/impl/forward/AbstractMapForwardIndexAccessor.java index c09e785d53d0..8e67ffafdfc0 100644 --- a/platform/util/src/com/intellij/util/indexing/impl/forward/AbstractMapForwardIndexAccessor.java +++ b/platform/util/src/com/intellij/util/indexing/impl/forward/AbstractMapForwardIndexAccessor.java @@ -11,7 +11,7 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.Map; -public abstract class AbstractMapForwardIndexAccessor extends AbstractForwardIndexAccessor { +public abstract class AbstractMapForwardIndexAccessor extends AbstractForwardIndexAccessor { public AbstractMapForwardIndexAccessor(@NotNull DataExternalizer externalizer) { super(externalizer); } diff --git a/platform/util/src/com/intellij/util/indexing/impl/forward/ForwardIndexAccessor.java b/platform/util/src/com/intellij/util/indexing/impl/forward/ForwardIndexAccessor.java index e4b97517f88a..cd1368cd51dc 100644 --- a/platform/util/src/com/intellij/util/indexing/impl/forward/ForwardIndexAccessor.java +++ b/platform/util/src/com/intellij/util/indexing/impl/forward/ForwardIndexAccessor.java @@ -2,26 +2,32 @@ package com.intellij.util.indexing.impl.forward; import com.intellij.openapi.util.io.ByteArraySequence; -import com.intellij.util.indexing.impl.InputData; import com.intellij.util.indexing.impl.InputDataDiffBuilder; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.Map; -@ApiStatus.Experimental -public interface ForwardIndexAccessor { +/** + * + * @param should not hold strong reference to Input because it may lead to OOMs + */ +public interface ForwardIndexAccessor { /** * creates a diff builder for given inputId. */ @NotNull InputDataDiffBuilder getDiffBuilder(int inputId, @Nullable ByteArraySequence sequence) throws IOException; + /** + * convert mapped key-values and input to a data type before it will be serialized + */ + DataType convertToDataType(@Nullable Map map, @Nullable Input content); + /** * serialize indexed data to forward index format. */ @Nullable - ByteArraySequence serializeIndexedData(@NotNull InputData data) throws IOException; + ByteArraySequence serializeIndexedData(@Nullable DataType data) throws IOException; } \ No newline at end of file diff --git a/platform/util/src/com/intellij/util/indexing/impl/forward/IntForwardIndexAccessor.java b/platform/util/src/com/intellij/util/indexing/impl/forward/IntForwardIndexAccessor.java index e0404ae75ced..26501c30133a 100644 --- a/platform/util/src/com/intellij/util/indexing/impl/forward/IntForwardIndexAccessor.java +++ b/platform/util/src/com/intellij/util/indexing/impl/forward/IntForwardIndexAccessor.java @@ -2,7 +2,6 @@ package com.intellij.util.indexing.impl.forward; import com.intellij.openapi.util.io.ByteArraySequence; -import com.intellij.util.indexing.impl.InputData; import com.intellij.util.indexing.impl.InputDataDiffBuilder; import com.intellij.util.io.EnumeratorIntegerDescriptor; import org.jetbrains.annotations.NotNull; @@ -11,17 +10,22 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.Map; -public interface IntForwardIndexAccessor extends ForwardIndexAccessor { +public interface IntForwardIndexAccessor extends ForwardIndexAccessor { @NotNull @Override default InputDataDiffBuilder getDiffBuilder(int inputId, @Nullable ByteArraySequence sequence) throws IOException { return getDiffBuilderFromInt(inputId, sequence == null ? 0 : AbstractForwardIndexAccessor.deserializeFromByteSeq(sequence, EnumeratorIntegerDescriptor.INSTANCE)); } + @Override + default Integer convertToDataType(@Nullable Map map, @Nullable Input content) { + return convertToInt(map, content); + } + @Nullable @Override - default ByteArraySequence serializeIndexedData(@NotNull InputData data) throws IOException { - return AbstractForwardIndexAccessor.serializeToByteSeq(serializeIndexedDataToInt(data), EnumeratorIntegerDescriptor.INSTANCE, 8); + default ByteArraySequence serializeIndexedData(@Nullable Integer data) throws IOException { + return data == null ? null : AbstractForwardIndexAccessor.serializeToByteSeq(data, EnumeratorIntegerDescriptor.INSTANCE, 8); } /** @@ -30,5 +34,8 @@ public interface IntForwardIndexAccessor extends ForwardIndexAccesso @NotNull InputDataDiffBuilder getDiffBuilderFromInt(int inputId, int value) throws IOException; - int serializeIndexedDataToInt(@NotNull InputData data); + /** + * convert mapped key-values and input to a data type before it will be serialized + */ + int convertToInt(@Nullable Map map, @Nullable Input content); } diff --git a/platform/util/src/com/intellij/util/indexing/impl/forward/KeyCollectionForwardIndexAccessor.java b/platform/util/src/com/intellij/util/indexing/impl/forward/KeyCollectionForwardIndexAccessor.java index e66324e782c4..ad3d2b862ede 100644 --- a/platform/util/src/com/intellij/util/indexing/impl/forward/KeyCollectionForwardIndexAccessor.java +++ b/platform/util/src/com/intellij/util/indexing/impl/forward/KeyCollectionForwardIndexAccessor.java @@ -5,7 +5,6 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.indexing.IndexExtension; import com.intellij.util.indexing.IndexId; import com.intellij.util.indexing.impl.CollectionInputDataDiffBuilder; -import com.intellij.util.indexing.impl.InputData; import com.intellij.util.indexing.impl.InputDataDiffBuilder; import com.intellij.util.indexing.impl.InputIndexDataExternalizer; import com.intellij.util.io.DataExternalizer; @@ -14,18 +13,16 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.IOException; import java.util.Collection; import java.util.Map; -import java.util.Set; @ApiStatus.Experimental -public class KeyCollectionForwardIndexAccessor extends AbstractForwardIndexAccessor> { +public class KeyCollectionForwardIndexAccessor extends AbstractForwardIndexAccessor, Input> { public KeyCollectionForwardIndexAccessor(@NotNull DataExternalizer> externalizer) { super(externalizer); } - public KeyCollectionForwardIndexAccessor(@NotNull IndexExtension extension) { + public KeyCollectionForwardIndexAccessor(@NotNull IndexExtension extension) { this(extension.getKeyDescriptor(), extension.getName()); } @@ -38,11 +35,9 @@ public class KeyCollectionForwardIndexAccessor extends AbstractForwa return new CollectionInputDataDiffBuilder<>(inputId, keys); } - @Nullable @Override - public Collection convertToDataType(@NotNull InputData data) { - Set keys = data.getKeyValues().keySet(); - return keys.isEmpty() ? null : keys; + public Collection convertToDataType(@Nullable Map map, @Nullable Input content) { + return ContainerUtil.isEmpty(map) ? null : map.keySet(); } @Override diff --git a/platform/util/src/com/intellij/util/indexing/impl/forward/MapForwardIndexAccessor.java b/platform/util/src/com/intellij/util/indexing/impl/forward/MapForwardIndexAccessor.java index b15cc162d024..fb907c0d3bc2 100644 --- a/platform/util/src/com/intellij/util/indexing/impl/forward/MapForwardIndexAccessor.java +++ b/platform/util/src/com/intellij/util/indexing/impl/forward/MapForwardIndexAccessor.java @@ -1,15 +1,13 @@ // Copyright 2000-2019 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.util.indexing.impl.forward; -import com.intellij.util.indexing.impl.InputData; import com.intellij.util.io.DataExternalizer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.IOException; import java.util.Map; -public class MapForwardIndexAccessor extends AbstractMapForwardIndexAccessor> { +public class MapForwardIndexAccessor extends AbstractMapForwardIndexAccessor, Input> { public MapForwardIndexAccessor(@NotNull DataExternalizer> externalizer) { super(externalizer); } @@ -24,9 +22,9 @@ public class MapForwardIndexAccessor extends AbstractMapForwa protected int getBufferInitialSize(@NotNull Map map) { return 4 * map.size(); } - @Nullable + @Override - public Map convertToDataType(@NotNull InputData data) { - return data.getKeyValues(); + public Map convertToDataType(@Nullable Map map, @Nullable Input content) { + return map; } } diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 0017f236b94a..df427c61f253 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -3520,7 +3520,7 @@ public class UIUtil { @NotNull public static JBTreeTraverser uiTraverser(@Nullable Component component) { - return UI_TRAVERSER.withRoot(component); + return UI_TRAVERSER.withRoot(component).expandAndFilter(o -> !(o instanceof CellRendererPane)); } public static final Key> NOT_IN_HIERARCHY_COMPONENTS = Key.create("NOT_IN_HIERARCHY_COMPONENTS"); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/UpdateRequestsQueue.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/UpdateRequestsQueue.java index dc20db3c7065..eca9658369c8 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/UpdateRequestsQueue.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/UpdateRequestsQueue.java @@ -1,6 +1,7 @@ // Copyright 2000-2018 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.openapi.vcs.changes; +import com.intellij.diagnostic.ThreadDumper; import com.intellij.ide.startup.impl.StartupManagerImpl; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; @@ -139,7 +140,7 @@ public class UpdateRequestsQueue { myWaitingUpdateCompletionSemaphores.add(semaphore); } if (!semaphore.waitFor(100 * 1000)) { - LOG.error("Too long VCS update"); + LOG.error("Too long VCS update\n" + ThreadDumper.dumpThreadsToString()); return; } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/JBProtocolCheckoutCommand.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/JBProtocolCheckoutCommand.java index 0cd83adee2a5..f0cf24069d40 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/JBProtocolCheckoutCommand.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/JBProtocolCheckoutCommand.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-2019 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.openapi.vcs.checkout; import com.intellij.openapi.application.JBProtocolCommand; @@ -23,22 +9,23 @@ import com.intellij.openapi.vcs.CheckoutProvider; import com.intellij.openapi.vcs.CheckoutProviderEx; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.ui.AppIcon; +import org.jetbrains.annotations.NotNull; import java.util.Map; /** * @author Konstantin Bulenkov */ -public class JBProtocolCheckoutCommand extends JBProtocolCommand { +final class JBProtocolCheckoutCommand extends JBProtocolCommand { private static final String REPOSITORY_NAME_KEY = "checkout.repo"; - public JBProtocolCheckoutCommand() { + JBProtocolCheckoutCommand() { super("checkout"); } @Override - public void perform(String vcsId, Map parameters) { + public void perform(String vcsId, @NotNull Map parameters) { String repository = parameters.get(REPOSITORY_NAME_KEY); if (StringUtil.isEmpty(repository)) { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsChangesLazilyParsedDetails.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsChangesLazilyParsedDetails.java index 6ecbf8127f40..6569a4b83352 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsChangesLazilyParsedDetails.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsChangesLazilyParsedDetails.java @@ -20,11 +20,13 @@ import com.google.common.base.Suppliers; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.LocalFilePath; -import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.ContainerUtil; -import com.intellij.vcs.log.*; +import com.intellij.vcs.log.Hash; +import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.VcsShortCommitDetails; +import com.intellij.vcs.log.VcsUser; import com.intellij.vcs.log.impl.VcsStatusMerger.MergedStatusInfo; import org.jetbrains.annotations.NotNull; @@ -33,6 +35,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiFunction; /** * Allows to postpone changes parsing, which might take long for a large amount of commits, @@ -52,31 +55,21 @@ public class VcsChangesLazilyParsedDetails extends VcsCommitMetadataImpl impleme @NotNull ChangesParser changesParser) { super(hash, parents, commitTime, root, subject, author, message, committer, authorTime); myChangesParser = changesParser; - myChanges.set(reportedChanges.isEmpty() ? EMPTY_CHANGES : new UnparsedChanges(project, reportedChanges)); + myChanges.set(reportedChanges.isEmpty() ? EMPTY_CHANGES : new UnparsedChanges(project, reportedChanges, (sources, parent) -> { + return myChangesParser.parseStatusInfo(project, this, sources, parent); + })); } @NotNull @Override public Collection getChanges() { - try { - return myChanges.get().getMergedChanges(); - } - catch (VcsException e) { - LOG.error("Error happened when parsing changes", e); - return Collections.emptyList(); - } + return myChanges.get().getMergedChanges(); } @NotNull @Override public Collection getChanges(int parent) { - try { - return myChanges.get().getChanges(parent); - } - catch (VcsException e) { - LOG.error("Error happened when parsing changes", e); - return Collections.emptyList(); - } + return myChanges.get().getChanges(parent); } public int size() { @@ -89,11 +82,7 @@ public class VcsChangesLazilyParsedDetails extends VcsCommitMetadataImpl impleme } else { for (int i = 0; i < getParents().size(); i++) { - try { - size += changes.getChanges(i).size(); - } - catch (VcsException ignored) { - } + size += changes.getChanges(i).size(); } } return size; @@ -101,10 +90,10 @@ public class VcsChangesLazilyParsedDetails extends VcsCommitMetadataImpl impleme public interface Changes { @NotNull - Collection getMergedChanges() throws VcsException; + Collection getMergedChanges(); @NotNull - Collection getChanges(int parent) throws VcsException; + Collection getChanges(int parent); } protected static class EmptyChanges implements Changes { @@ -125,15 +114,18 @@ public class VcsChangesLazilyParsedDetails extends VcsCommitMetadataImpl impleme @NotNull protected final Project myProject; @NotNull protected final List> myChangesOutput; @NotNull private final VcsStatusMerger myStatusMerger = new VcsFileStatusInfoMerger(); + @NotNull private final BiFunction, Integer, List> myParser; public UnparsedChanges(@NotNull Project project, - @NotNull List> changesOutput) { + @NotNull List> changesOutput, + @NotNull BiFunction, Integer, List> parser) { myProject = project; myChangesOutput = changesOutput; + myParser = parser; } @NotNull - protected ParsedChanges parseChanges() throws VcsException { + protected ParsedChanges parseChanges() { List mergedChanges = parseMergedChanges(); List> changes = computeChanges(mergedChanges); ParsedChanges parsedChanges = new ParsedChanges(mergedChanges, changes); @@ -142,43 +134,41 @@ public class VcsChangesLazilyParsedDetails extends VcsCommitMetadataImpl impleme } @NotNull - private List parseMergedChanges() throws VcsException { + private List parseMergedChanges() { List> statuses = getMergedStatusInfo(); - List changes = myChangesParser.parseStatusInfo(myProject, VcsChangesLazilyParsedDetails.this, - ContainerUtil.map(statuses, MergedStatusInfo::getStatusInfo), 0); + List changes = myParser.apply(ContainerUtil.map(statuses, MergedStatusInfo::getStatusInfo), 0); LOG.assertTrue(changes.size() == statuses.size(), "Incorrectly parsed statuses " + statuses + " to changes " + changes); if (getParents().size() <= 1) return changes; // each merge change knows about all changes to parents List wrappedChanges = new ArrayList<>(statuses.size()); for (int i = 0; i < statuses.size(); i++) { - wrappedChanges.add(new MyMergedChange(changes.get(i), statuses.get(i))); + wrappedChanges.add(new MyMergedChange(changes.get(i), statuses.get(i), myParser)); } return wrappedChanges; } @NotNull @Override - public Collection getMergedChanges() throws VcsException { + public Collection getMergedChanges() { return parseChanges().getMergedChanges(); } @NotNull @Override - public Collection getChanges(int parent) throws VcsException { + public Collection getChanges(int parent) { return parseChanges().getChanges(parent); } @NotNull - private List> computeChanges(@NotNull Collection mergedChanges) - throws VcsException { + private List> computeChanges(@NotNull Collection mergedChanges) { if (myChangesOutput.size() == 1) { return Collections.singletonList(mergedChanges); } else { List> changes = ContainerUtil.newArrayListWithCapacity(myChangesOutput.size()); for (int i = 0; i < myChangesOutput.size(); i++) { - changes.add(myChangesParser.parseStatusInfo(myProject, VcsChangesLazilyParsedDetails.this, myChangesOutput.get(i), i)); + changes.add(myParser.apply(myChangesOutput.get(i), i)); } return changes; } @@ -198,34 +188,27 @@ public class VcsChangesLazilyParsedDetails extends VcsCommitMetadataImpl impleme public List> getChangesOutput() { return myChangesOutput; } + } - private class MyMergedChange extends MergedChange { - @NotNull private final MergedStatusInfo myStatusInfo; - @NotNull private final Supplier> mySourceChanges; + private static class MyMergedChange extends MergedChange { + @NotNull private final Supplier> mySourceChanges; - MyMergedChange(@NotNull Change change, @NotNull MergedStatusInfo statusInfo) { - super(change); - myStatusInfo = statusInfo; - mySourceChanges = Suppliers.memoize(() -> { - List sourceChanges = ContainerUtil.newArrayList(); - try { - for (int parent = 0; parent < myStatusInfo.getMergedStatusInfos().size(); parent++) { - List statusInfos = Collections.singletonList(myStatusInfo.getMergedStatusInfos().get(parent)); - sourceChanges.addAll(myChangesParser.parseStatusInfo(myProject, VcsChangesLazilyParsedDetails.this, statusInfos, - parent)); - } - } - catch (VcsException e) { - LOG.error(e); - } - return sourceChanges; - }); - } + MyMergedChange(@NotNull Change change, @NotNull MergedStatusInfo statusInfo, + @NotNull BiFunction, Integer, List> parser) { + super(change); + mySourceChanges = Suppliers.memoize(() -> { + List sourceChanges = ContainerUtil.newArrayList(); + for (int parent = 0; parent < statusInfo.getMergedStatusInfos().size(); parent++) { + List statusInfos = Collections.singletonList(statusInfo.getMergedStatusInfos().get(parent)); + sourceChanges.addAll(parser.apply(statusInfos, parent)); + } + return sourceChanges; + }); + } - @Override - public List getSourceChanges() { - return mySourceChanges.get(); - } + @Override + public List getSourceChanges() { + return mySourceChanges.get(); } } @@ -255,6 +238,6 @@ public class VcsChangesLazilyParsedDetails extends VcsCommitMetadataImpl impleme List parseStatusInfo(@NotNull Project project, @NotNull VcsShortCommitDetails commit, @NotNull List changes, - int parentIndex) throws VcsException; + int parentIndex); } } diff --git a/plugins/devkit/devkit-core/resources/META-INF/plugin.xml b/plugins/devkit/devkit-core/resources/META-INF/plugin.xml index 797c505c6bba..a9530604fabf 100644 --- a/plugins/devkit/devkit-core/resources/META-INF/plugin.xml +++ b/plugins/devkit/devkit-core/resources/META-INF/plugin.xml @@ -75,26 +75,32 @@ language="XML"/> @@ -104,61 +110,62 @@ enabledByDefault="true" level="ERROR" implementationClass="org.jetbrains.idea.devkit.inspections.RegistrationProblemsInspection"/> diff --git a/plugins/devkit/devkit-core/resources/org/jetbrains/idea/devkit/DevKitBundle.properties b/plugins/devkit/devkit-core/resources/org/jetbrains/idea/devkit/DevKitBundle.properties index 51c3e35c8ab3..64ab7ca9cf7c 100644 --- a/plugins/devkit/devkit-core/resources/org/jetbrains/idea/devkit/DevKitBundle.properties +++ b/plugins/devkit/devkit-core/resources/org/jetbrains/idea/devkit/DevKitBundle.properties @@ -144,6 +144,9 @@ class.implementation=implementation structure.sort.alphabetically.in.groups=Sort Alphabetically in Groups inspections.group.name=Plugin DevKit +inspections.group.descriptor=Plugin Descriptor +inspections.group.description.file=Description File +inspections.group.code=Code inspections.plugin.xml.inner.class.must.be.separated.with.dollar=Inner class must be separated with '$' inspections.plugin.xml.plugin.should.have.jetbrains.vendor=Plugin developed as a part of IntelliJ IDEA project should specify 'JetBrains' as its vendor inspections.plugin.xml.plugin.should.include.jetbrains.vendor=Plugin developed as a part of IntelliJ IDEA project should include 'JetBrains' as one of its vendors diff --git a/plugins/devkit/devkit-core/src/projectRoots/IdeaJdk.java b/plugins/devkit/devkit-core/src/projectRoots/IdeaJdk.java index cb7083566fcd..8e2f7ef005f6 100644 --- a/plugins/devkit/devkit-core/src/projectRoots/IdeaJdk.java +++ b/plugins/devkit/devkit-core/src/projectRoots/IdeaJdk.java @@ -331,8 +331,7 @@ public class IdeaJdk extends JavaDependentSdkType implements JavaSdkType { String sdkHome = ObjectUtils.notNull(sdk.getHomePath()); JpsModel model = JpsSerializationManager.getInstance().loadModel(sdkHome, PathManager.getOptionsPath()); JpsSdkReference sdkRef = model.getProject().getSdkReferencesTable().getSdkReference(JpsJavaSdkType.INSTANCE); - String sdkName = sdkRef == null ? null : sdkRef.getSdkName(); - Sdk internalJava = sdkModel.findSdk(sdkName); + Sdk internalJava = sdkRef == null ? null : sdkModel.findSdk(sdkRef.getSdkName()); if (internalJava != null && isValidInternalJdk(sdk, internalJava)) { setInternalJdk(sdk, sdkModificator, internalJava); } diff --git a/plugins/git4idea/src/git4idea/GitCommit.java b/plugins/git4idea/src/git4idea/GitCommit.java index 279e8473c8d3..1f0bbfad60e1 100644 --- a/plugins/git4idea/src/git4idea/GitCommit.java +++ b/plugins/git4idea/src/git4idea/GitCommit.java @@ -49,7 +49,7 @@ public final class GitCommit extends VcsChangesLazilyParsedDetails { public List parseStatusInfo(@NotNull Project project, @NotNull VcsShortCommitDetails commit, @NotNull List changes, - int parentIndex) throws VcsException { + int parentIndex) { String parentHash = null; if (parentIndex < commit.getParents().size()) { parentHash = commit.getParents().get(parentIndex).asString(); diff --git a/plugins/git4idea/src/git4idea/GitContentRevision.java b/plugins/git4idea/src/git4idea/GitContentRevision.java index c42a78d174c0..76eba029b479 100644 --- a/plugins/git4idea/src/git4idea/GitContentRevision.java +++ b/plugins/git4idea/src/git4idea/GitContentRevision.java @@ -126,16 +126,19 @@ public class GitContentRevision implements ByteBackedContentRevision { } @NotNull - public static FilePath createPath(@NotNull VirtualFile vcsRoot, - @NotNull String path, - boolean unescapePath) throws VcsException { - String absolutePath = makeAbsolutePath(vcsRoot, path, unescapePath); + public static FilePath createPathFromEscaped(@NotNull VirtualFile vcsRoot, @NotNull String path) throws VcsException { + String absolutePath = makeAbsolutePath(vcsRoot, GitUtil.unescapePath(path)); return VcsUtil.getFilePath(absolutePath, false); } @NotNull - private static String makeAbsolutePath(@NotNull VirtualFile vcsRoot, @NotNull String path, boolean unescapePath) throws VcsException { - String unescapedPath = unescapePath ? GitUtil.unescapePath(path) : path; + public static FilePath createPath(@NotNull VirtualFile vcsRoot, @NotNull String unescapedPath) { + String absolutePath = makeAbsolutePath(vcsRoot, unescapedPath); + return VcsUtil.getFilePath(absolutePath, false); + } + + @NotNull + private static String makeAbsolutePath(@NotNull VirtualFile vcsRoot, @NotNull String unescapedPath) { return vcsRoot.getPath() + "/" + unescapedPath; } @@ -173,7 +176,8 @@ public class GitContentRevision implements ByteBackedContentRevision { @Nullable Charset charset) { if (path.getFileType().isBinary()) { return new GitBinaryContentRevision(path, revisionNumber, project); - } else { + } + else { return new GitContentRevision(path, revisionNumber, project, charset); } } diff --git a/plugins/git4idea/src/git4idea/GitStatisticsCollector.kt b/plugins/git4idea/src/git4idea/GitStatisticsCollector.kt index 259b99e6ea9a..974fc29996bf 100644 --- a/plugins/git4idea/src/git4idea/GitStatisticsCollector.kt +++ b/plugins/git4idea/src/git4idea/GitStatisticsCollector.kt @@ -24,7 +24,7 @@ class GitStatisticsCollector : ProjectUsagesCollector() { val usages = hashSetOf() usages.add(UsageDescriptor("config.repo.sync." + settings.syncSetting.name, 1)) - usages.add(UsageDescriptor("config.update.type." + settings.updateType.name, 1)) + usages.add(UsageDescriptor("config.update.type." + settings.updateMethod.name, 1)) usages.add(UsageDescriptor("config.save.policy." + settings.updateChangesPolicy().name, 1)) usages.add(getBooleanUsage("config.ssh", appSettings.isUseIdeaSsh)) diff --git a/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java b/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java index 419b91d94ec2..fd212e646412 100644 --- a/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java +++ b/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java @@ -143,7 +143,7 @@ public class GitChangeUtils { final ContentRevision before; final ContentRevision after; final String path = tokens[tokens.length - 1]; - final FilePath filePath = GitContentRevision.createPath(vcsRoot, path, true); + final FilePath filePath = GitContentRevision.createPathFromEscaped(vcsRoot, path); switch (tokens[0].charAt(0)) { case 'C': case 'A': @@ -167,7 +167,7 @@ public class GitChangeUtils { break; case 'R': status = FileStatus.MODIFIED; - final FilePath oldFilePath = GitContentRevision.createPath(vcsRoot, tokens[1], true); + final FilePath oldFilePath = GitContentRevision.createPathFromEscaped(vcsRoot, tokens[1]); before = GitContentRevision.createRevision(oldFilePath, parentRevision, project); after = GitContentRevision.createRevision(filePath, thisRevision, project); break; diff --git a/plugins/git4idea/src/git4idea/config/GitVcsPanel.java b/plugins/git4idea/src/git4idea/config/GitVcsPanel.java index 6c1d83970935..3eb1eac393b6 100644 --- a/plugins/git4idea/src/git4idea/config/GitVcsPanel.java +++ b/plugins/git4idea/src/git4idea/config/GitVcsPanel.java @@ -186,7 +186,7 @@ public class GitVcsPanel implements ConfigurableUi, } @NotNull - public UpdateMethod getUpdateType() { + public UpdateMethod getUpdateMethod() { return myState.getUpdateMethod(); } - public void setUpdateType(UpdateMethod updateType) { + public void setUpdateMethod(UpdateMethod updateType) { myState.setUpdateMethod(updateType); } diff --git a/plugins/git4idea/src/git4idea/history/GitChangesParser.java b/plugins/git4idea/src/git4idea/history/GitChangesParser.java index f6e5dd02fbbb..965341dda79b 100644 --- a/plugins/git4idea/src/git4idea/history/GitChangesParser.java +++ b/plugins/git4idea/src/git4idea/history/GitChangesParser.java @@ -43,7 +43,7 @@ public class GitChangesParser { @NotNull List statusInfos, @NotNull String hash, @NotNull Date date, - @Nullable String parentsHash) throws VcsException { + @Nullable String parentsHash) { GitRevisionNumber thisRevision = new GitRevisionNumber(hash, date); GitRevisionNumber parentRevision = parentsHash == null ? null : new GitRevisionNumber(parentsHash); @@ -59,11 +59,11 @@ public class GitChangesParser { @NotNull VirtualFile vcsRoot, @NotNull VcsRevisionNumber thisRevision, @Nullable VcsRevisionNumber parentRevision, - @NotNull VcsFileStatusInfo statusInfo) throws VcsException { + @NotNull VcsFileStatusInfo statusInfo) { final ContentRevision before; final ContentRevision after; final String path = statusInfo.getFirstPath(); - final FilePath filePath = GitContentRevision.createPath(vcsRoot, path, false); + final FilePath filePath = GitContentRevision.createPath(vcsRoot, path); FileStatus status; switch (statusInfo.getType()) { @@ -85,7 +85,7 @@ public class GitChangesParser { case MOVED: status = FileStatus.MODIFIED; String secondPath = statusInfo.getSecondPath(); - final FilePath filePathAfterRename = secondPath == null ? filePath : GitContentRevision.createPath(vcsRoot, secondPath, false); + final FilePath filePathAfterRename = secondPath == null ? filePath : GitContentRevision.createPath(vcsRoot, secondPath); before = GitContentRevision.createRevision(filePath, parentRevision, project); after = GitContentRevision.createRevision(filePathAfterRename, thisRevision, project); break; diff --git a/plugins/git4idea/src/git4idea/push/GitPushOperation.java b/plugins/git4idea/src/git4idea/push/GitPushOperation.java index 3efa12e0be8f..7df1ac031136 100644 --- a/plugins/git4idea/src/git4idea/push/GitPushOperation.java +++ b/plugins/git4idea/src/git4idea/push/GitPushOperation.java @@ -443,15 +443,15 @@ public class GitPushOperation { UpdateMethod updateMethod = settings.getUpdateMethod(); mySettings.setUpdateAllRootsIfPushRejected(settings.shouldUpdateAllRoots()); if (!rebaseOverMergeDetected // don't overwrite explicit "rebase" with temporary "merge" caused by merge commits - && mySettings.getUpdateType() != updateMethod && mySettings.getUpdateType() != UpdateMethod.BRANCH_DEFAULT) { // don't overwrite "branch default" setting - mySettings.setUpdateType(updateMethod); + && mySettings.getUpdateMethod() != updateMethod && mySettings.getUpdateMethod() != UpdateMethod.BRANCH_DEFAULT) { // don't overwrite "branch default" setting + mySettings.setUpdateMethod(updateMethod); } } @NotNull private PushUpdateSettings readPushUpdateSettings() { boolean updateAllRoots = mySettings.shouldUpdateAllRootsIfPushRejected(); - UpdateMethod updateMethod = mySettings.getUpdateType(); + UpdateMethod updateMethod = mySettings.getUpdateMethod(); if (updateMethod == UpdateMethod.BRANCH_DEFAULT) { // deliberate limitation: we have only 2 buttons => choose method from the 1st repo if different updateMethod = GitUpdater.resolveUpdateMethod(myPushSpecs.keySet().iterator().next()); diff --git a/plugins/git4idea/src/git4idea/status/GitChangesCollector.java b/plugins/git4idea/src/git4idea/status/GitChangesCollector.java index a063ccb1a6b7..5a3374f200e0 100644 --- a/plugins/git4idea/src/git4idea/status/GitChangesCollector.java +++ b/plugins/git4idea/src/git4idea/status/GitChangesCollector.java @@ -235,7 +235,7 @@ class GitChangesCollector { final char xStatus = xyStatus.charAt(0); final char yStatus = xyStatus.charAt(1); - final FilePath filepath = GitContentRevision.createPath(myVcsRoot, path, false); + final FilePath filepath = GitContentRevision.createPath(myVcsRoot, path); switch (xStatus) { case ' ': @@ -308,7 +308,7 @@ class GitChangesCollector { case 'R': //noinspection AssignmentToForLoopParameter pos += 1; // read the "from" filepath which is separated also by NUL character. - FilePath oldFilepath = GitContentRevision.createPath(myVcsRoot, split[pos], false); + FilePath oldFilepath = GitContentRevision.createPath(myVcsRoot, split[pos]); if (yStatus == 'D') { reportDeleted(oldFilepath, head); diff --git a/plugins/git4idea/src/git4idea/update/GitUpdateEnvironment.java b/plugins/git4idea/src/git4idea/update/GitUpdateEnvironment.java index 5ee76d76f688..8480c55a584c 100644 --- a/plugins/git4idea/src/git4idea/update/GitUpdateEnvironment.java +++ b/plugins/git4idea/src/git4idea/update/GitUpdateEnvironment.java @@ -45,7 +45,7 @@ public class GitUpdateEnvironment implements UpdateEnvironment { final GitUpdateProcess gitUpdateProcess = new GitUpdateProcess(myProject, progressIndicator, getRepositoriesFromRoots(repositoryManager, roots), updatedFiles, true, true); - boolean result = gitUpdateProcess.update(mySettings.getUpdateType()).isSuccess(); + boolean result = gitUpdateProcess.update(mySettings.getUpdateMethod()).isSuccess(); return new GitUpdateSession(result, gitUpdateProcess.getSkippedRoots()); } diff --git a/plugins/git4idea/src/git4idea/update/GitUpdateOptionsPanel.java b/plugins/git4idea/src/git4idea/update/GitUpdateOptionsPanel.java index ec03decba3e0..aa01fb3fa50f 100644 --- a/plugins/git4idea/src/git4idea/update/GitUpdateOptionsPanel.java +++ b/plugins/git4idea/src/git4idea/update/GitUpdateOptionsPanel.java @@ -39,7 +39,7 @@ public class GitUpdateOptionsPanel { public boolean isModified(GitVcsSettings settings) { UpdateMethod type = getUpdateType(); - return type != settings.getUpdateType() || updateSaveFilesPolicy() != settings.updateChangesPolicy(); + return type != settings.getUpdateMethod() || updateSaveFilesPolicy() != settings.updateChangesPolicy(); } /** @@ -71,7 +71,7 @@ public class GitUpdateOptionsPanel { * Save configuration to settings object */ public void applyTo(GitVcsSettings settings) { - settings.setUpdateType(getUpdateType()); + settings.setUpdateMethod(getUpdateType()); settings.setUpdateChangesPolicy(updateSaveFilesPolicy()); } @@ -79,7 +79,7 @@ public class GitUpdateOptionsPanel { * Update panel according to settings */ public void updateFrom(GitVcsSettings settings) { - switch (settings.getUpdateType()) { + switch (settings.getUpdateMethod()) { case REBASE: myForceRebaseRadioButton.setSelected(true); break; @@ -90,7 +90,7 @@ public class GitUpdateOptionsPanel { myBranchDefaultRadioButton.setSelected(true); break; default: - assert false : "Unknown value of update type: " + settings.getUpdateType(); + assert false : "Unknown value of update type: " + settings.getUpdateMethod(); } UpdatePolicyUtils.updatePolicyItem(settings.updateChangesPolicy(), myStashRadioButton, myShelveRadioButton); } diff --git a/plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.kt b/plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.kt index 8a85271ea246..70a8c4c67946 100644 --- a/plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.kt +++ b/plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.kt @@ -298,7 +298,7 @@ class GitPushOperationSingleRepoTest : GitPushOperationBaseTest() { } fun `test dont silently update if force push is rejected`() { - settings.updateType = UpdateMethod.REBASE + settings.updateMethod = UpdateMethod.REBASE settings.setAutoUpdateIfPushRejected(true) val remoteTipAndPushResult = forcePushWithReject(true) @@ -311,7 +311,7 @@ class GitPushOperationSingleRepoTest : GitPushOperationBaseTest() { fun `test dont silently update if force with lease push is rejected`() { assumeForceWithLeaseSupported() - settings.updateType = UpdateMethod.REBASE + settings.updateMethod = UpdateMethod.REBASE settings.setAutoUpdateIfPushRejected(true) val remoteTipAndPushResult = forcePushWithReject(false) @@ -448,7 +448,7 @@ class GitPushOperationSingleRepoTest : GitPushOperationBaseTest() { generateUnpushedMergedCommitProblem() settings.setAutoUpdateIfPushRejected(true) - settings.updateType = UpdateMethod.REBASE + settings.updateMethod = UpdateMethod.REBASE var rebaseOverMergeProblemDetected = false dialogManager.onMessage { @@ -462,7 +462,7 @@ class GitPushOperationSingleRepoTest : GitPushOperationBaseTest() { fun `test dont overwrite rebase setting when chose to merge due to unpushed merge commits`() { generateUnpushedMergedCommitProblem() - settings.updateType = UpdateMethod.REBASE + settings.updateMethod = UpdateMethod.REBASE var rebaseOverMergeProblemDetected = false dialogManager.onDialog(GitRejectedPushUpdateDialog::class.java, { @@ -472,12 +472,12 @@ class GitPushOperationSingleRepoTest : GitPushOperationBaseTest() { push("master", "origin/master") assertTrue(rebaseOverMergeProblemDetected) assertEquals("Update method was overwritten by temporary update-via-merge decision", - UpdateMethod.REBASE, settings.updateType) + UpdateMethod.REBASE, settings.updateMethod) } fun `test respect branch default setting for rejected push dialog`() { generateUpdateNeeded() - settings.updateType = UpdateMethod.BRANCH_DEFAULT + settings.updateMethod = UpdateMethod.BRANCH_DEFAULT git("config branch.master.rebase true") var defaultActionName = "" @@ -498,7 +498,7 @@ class GitPushOperationSingleRepoTest : GitPushOperationBaseTest() { fun `test respect branch default setting for silent update when rejected push`() { generateUpdateNeeded() - settings.updateType = UpdateMethod.BRANCH_DEFAULT + settings.updateMethod = UpdateMethod.BRANCH_DEFAULT git("config branch.master.rebase true") settings.setAutoUpdateIfPushRejected(true) @@ -510,7 +510,7 @@ class GitPushOperationSingleRepoTest : GitPushOperationBaseTest() { // => simply don't rewrite the setting if the same value is chosen, as was default value initially fun `test dont overwrite branch default setting when agree in rejected push dialog`() { generateUpdateNeeded() - settings.updateType = UpdateMethod.BRANCH_DEFAULT + settings.updateMethod = UpdateMethod.BRANCH_DEFAULT git("config branch.master.rebase true") dialogManager.onDialog(GitRejectedPushUpdateDialog::class.java, { @@ -518,7 +518,7 @@ class GitPushOperationSingleRepoTest : GitPushOperationBaseTest() { }) push("master", "origin/master") - assertEquals(UpdateMethod.BRANCH_DEFAULT, settings.updateType) + assertEquals(UpdateMethod.BRANCH_DEFAULT, settings.updateMethod) } private fun generateUpdateNeeded() { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/WorkCounter.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/WorkCounter.kt index 11c6df9f8baa..abd686492eaa 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/WorkCounter.kt +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/WorkCounter.kt @@ -17,7 +17,6 @@ package org.jetbrains.plugins.groovy.lang.psi.dataFlow -import com.intellij.codeInspection.dataFlow.WorkingTimeMeasurer import com.intellij.openapi.util.registry.Registry internal class WorkCounter { diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/WorkingTimeMeasurer.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/WorkingTimeMeasurer.java similarity index 56% rename from java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/WorkingTimeMeasurer.java rename to plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/WorkingTimeMeasurer.java index b0c4f1808779..bdb795995bb0 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/WorkingTimeMeasurer.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/WorkingTimeMeasurer.java @@ -1,19 +1,5 @@ -/* - * Copyright 2000-2012 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.codeInspection.dataFlow; +// Copyright 2000-2019 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.lang.psi.dataFlow; import org.jetbrains.annotations.Nullable; diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/uast/GroovyUastPlugin.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/uast/GroovyUastPlugin.kt index 4cf382ece532..11792ed9ee3f 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/uast/GroovyUastPlugin.kt +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/uast/GroovyUastPlugin.kt @@ -2,10 +2,7 @@ package org.jetbrains.plugins.groovy.lang.psi.uast import com.intellij.lang.Language -import com.intellij.psi.PsiAnnotation -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiElement -import com.intellij.psi.ResolveResult +import com.intellij.psi.* import com.intellij.psi.impl.source.tree.LeafPsiElement import com.intellij.psi.util.strictParents import org.jetbrains.plugins.groovy.GroovyLanguage @@ -19,6 +16,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod import org.jetbrains.uast.* +import org.jetbrains.uast.expressions.UInjectionHost /** * This is a very limited implementation of UastPlugin for Groovy, @@ -67,12 +65,16 @@ class GroovyUastPlugin : UastLanguagePlugin { } -class GrULiteral(val grElement: GrLiteral, val parentProvider: () -> UElement?) : ULiteralExpression { +class GrULiteral(val grElement: GrLiteral, val parentProvider: () -> UElement?) : ULiteralExpression, UInjectionHost { override val value: Any? get() = grElement.value override fun evaluate(): Any? = value override val uastParent: UElement? by lazy(parentProvider) override val psi: PsiElement? = grElement override val annotations: List = emptyList() //not implemented + override val isString: Boolean + get() = super.isString + override val psiLanguageInjectionHost: PsiLanguageInjectionHost + get() = grElement } class GrUNamedExpression(val grElement: GrAnnotationNameValuePair, val parentProvider: () -> UElement?) : UNamedExpression { diff --git a/plugins/java-i18n/intellij.java.i18n.iml b/plugins/java-i18n/intellij.java.i18n.iml index 7118b70b6283..81ff6d9c441c 100644 --- a/plugins/java-i18n/intellij.java.i18n.iml +++ b/plugins/java-i18n/intellij.java.i18n.iml @@ -22,5 +22,6 @@ + \ No newline at end of file diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/capitalization/TitleCapitalizationInspection.java b/plugins/java-i18n/src/com/intellij/codeInspection/capitalization/TitleCapitalizationInspection.java index 6ad7906fae8e..7a96010b8d1c 100644 --- a/plugins/java-i18n/src/com/intellij/codeInspection/capitalization/TitleCapitalizationInspection.java +++ b/plugins/java-i18n/src/com/intellij/codeInspection/capitalization/TitleCapitalizationInspection.java @@ -1,4 +1,4 @@ -// 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. +// Copyright 2000-2019 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.codeInspection.capitalization; import com.intellij.codeInsight.AnnotationUtil; @@ -80,7 +80,7 @@ public class TitleCapitalizationInspection extends AbstractBaseJavaLocalInspecti String titleValue, @NotNull ProblemsHolder holder, Nls.Capitalization capitalization) { - if (!isCapitalizationSatisfied(titleValue, capitalization)) { + if (!NlsCapitalizationUtil.isCapitalizationSatisfied(titleValue, capitalization)) { holder.registerProblem(e, "String '" + titleValue + "' is not properly capitalized. It should have " + StringUtil.toLowerCase(capitalization.toString()) + " capitalization", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new TitleCapitalizationFix(titleValue, capitalization)); @@ -141,38 +141,6 @@ public class TitleCapitalizationInspection extends AbstractBaseJavaLocalInspecti return null; } - public static boolean isCapitalizationSatisfied(String value, Nls.Capitalization capitalization) { - if (StringUtil.isEmpty(value) || capitalization == Nls.Capitalization.NotSpecified) { - return true; - } - value = value.replace("&", ""); - return capitalization == Nls.Capitalization.Title - ? StringUtil.wordsToBeginFromUpperCase(value).equals(value) - : checkSentenceCapitalization(value); - } - - private static boolean checkSentenceCapitalization(@NotNull String value) { - List words = StringUtil.split(value, " "); - if (words.size() == 0) return true; - if (Character.isLetter(words.get(0).charAt(0)) && !isCapitalizedWord(words.get(0))) return false; - if (words.size() == 1) return true; - int capitalized = 1; - for (int i = 1, size = words.size(); i < size; i++) { - String word = words.get(i); - if (isCapitalizedWord(word)) { - // check for abbreviations like SQL or I18n - if (word.length() == 1 || !Character.isLowerCase(word.charAt(1))) - continue; - capitalized++; - } - } - return capitalized / words.size() < 0.2; // allow reasonable amount of capitalized words - } - - private static boolean isCapitalizedWord(String word) { - return word.length() > 0 && Character.isLetter(word.charAt(0)) && Character.isUpperCase(word.charAt(0)); - } - private static class TitleCapitalizationFix implements LocalQuickFix { private final String myTitleValue; private final Nls.Capitalization myCapitalization; @@ -204,7 +172,8 @@ public class TitleCapitalizationInspection extends AbstractBaseJavaLocalInspecti } final String string = (String)value; final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); - final PsiExpression newExpression = factory.createExpressionFromText('"' + fixValue(string) + '"', element); + final PsiExpression newExpression = + factory.createExpressionFromText('"' + NlsCapitalizationUtil.fixValue(string, myCapitalization) + '"', element); literalExpression.replace(newExpression); } else if (element instanceof PsiMethodCallExpression) { @@ -222,7 +191,7 @@ public class TitleCapitalizationInspection extends AbstractBaseJavaLocalInspecti if (value == null) { return; } - property.setValue(fixValue(value)); + property.setValue(NlsCapitalizationUtil.fixValue(value, myCapitalization)); } else if (element instanceof PsiReferenceExpression) { final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)element; @@ -237,13 +206,6 @@ public class TitleCapitalizationInspection extends AbstractBaseJavaLocalInspecti } } - @NotNull - private String fixValue(String string) { - return myCapitalization == Nls.Capitalization.Title - ? StringUtil.wordsToBeginFromUpperCase(string) - : StringUtil.capitalize(StringUtil.wordsToBeginFromLowerCase(string)); - } - @NotNull @Override public String getFamilyName() { diff --git a/plugins/java-i18n/testSrc/com/intellij/codeInspection/CapitalizationTest.java b/plugins/java-i18n/testSrc/com/intellij/codeInspection/CapitalizationTest.java deleted file mode 100644 index 0cbf18c6ff1c..000000000000 --- a/plugins/java-i18n/testSrc/com/intellij/codeInspection/CapitalizationTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2000-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.codeInspection; - -import com.intellij.codeInspection.capitalization.TitleCapitalizationInspection; -import junit.framework.TestCase; -import org.jetbrains.annotations.Nls; - -public class CapitalizationTest extends TestCase { - - public void testCapitalization() { - assertTrue(TitleCapitalizationInspection.isCapitalizationSatisfied("Fix SQL issues", Nls.Capitalization.Sentence)); - assertTrue(TitleCapitalizationInspection.isCapitalizationSatisfied("Fix I18n issues", Nls.Capitalization.Sentence)); - assertTrue(TitleCapitalizationInspection.isCapitalizationSatisfied("Fix C issues", Nls.Capitalization.Sentence)); - assertTrue(TitleCapitalizationInspection.isCapitalizationSatisfied("@charset is invalid", Nls.Capitalization.Sentence)); - assertTrue(TitleCapitalizationInspection.isCapitalizationSatisfied("Add 'this' qualifier", Nls.Capitalization.Sentence)); - assertTrue(TitleCapitalizationInspection.isCapitalizationSatisfied("Add 'this' qualifier", Nls.Capitalization.Sentence)); - assertTrue(TitleCapitalizationInspection.isCapitalizationSatisfied("Please select the configuration file (usually named IntelliLang.xml) to import.", Nls.Capitalization.Sentence)); - assertFalse(TitleCapitalizationInspection.isCapitalizationSatisfied("Foo Bar", Nls.Capitalization.Sentence)); - assertTrue(TitleCapitalizationInspection.isCapitalizationSatisfied("Foo", Nls.Capitalization.Sentence)); - } -} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/buildtool/BuildViewMavenConsole.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/buildtool/BuildViewMavenConsole.java index fa58ab92576f..0de3eb9e8d0e 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/buildtool/BuildViewMavenConsole.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/buildtool/BuildViewMavenConsole.java @@ -89,7 +89,7 @@ public class BuildViewMavenConsole extends MavenConsole { ApplicationManager.getApplication().invokeLater(() -> { DefaultActionGroup actions = new DefaultActionGroup(); actions.addAll((myBuildView).getSwitchActions()); - actions.add(new ShowExecutionErrorsOnlyAction(myBuildView)); + actions.add(BuildTreeFilters.createFilteringActionsGroup(myBuildView)); JComponent consolePanel = createConsolePanel(myBuildView, actions); RunContentDescriptor descriptor = new RunContentDescriptor(myBuildView, processHandler, consolePanel, myTitle, MavenIcons.MavenLogo); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfiguration.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfiguration.java index 808606d9efac..aa357926e765 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfiguration.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfiguration.java @@ -1,9 +1,9 @@ // Copyright 2000-2019 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.idea.maven.execution; +import com.intellij.build.BuildTreeFilters; import com.intellij.build.BuildView; import com.intellij.build.DefaultBuildDescriptor; -import com.intellij.build.ShowExecutionErrorsOnlyAction; import com.intellij.debugger.impl.DebuggerManagerImpl; import com.intellij.debugger.settings.DebuggerSettings; import com.intellij.diagnostic.logging.LogConfigurationPanel; @@ -313,7 +313,7 @@ public class MavenRunConfiguration extends LocatableConfigurationBase implements final ConsoleView console = createConsoleViewAndAttachToProcess(executor, processHandler); AnAction[] actions = console instanceof BuildView ? - new AnAction[]{new ShowExecutionErrorsOnlyAction((BuildView)console)} : AnAction.EMPTY_ARRAY; + new AnAction[]{BuildTreeFilters.createFilteringActionsGroup((BuildView)console)} : AnAction.EMPTY_ARRAY; DefaultExecutionResult res = new DefaultExecutionResult(console, processHandler, actions); if (MavenResumeAction.isApplicable(getEnvironment().getProject(), getJavaParameters(), MavenRunConfiguration.this)) { MavenResumeAction resumeAction = new MavenResumeAction(res.getProcessHandler(), runner, getEnvironment()); diff --git a/python/testSrc/com/jetbrains/env/PyEnvTestCase.java b/python/testSrc/com/jetbrains/env/PyEnvTestCase.java index 1d169f5a1072..d1ddb541c644 100644 --- a/python/testSrc/com/jetbrains/env/PyEnvTestCase.java +++ b/python/testSrc/com/jetbrains/env/PyEnvTestCase.java @@ -356,7 +356,7 @@ public abstract class PyEnvTestCase { private final List myExceptions = new ArrayList<>(); @Override - public int show(final String message) { + public int show(@NotNull final String message) { myMessages.add(message); return 0; }