diff --git a/java/idea-ui/src/com/intellij/ide/actions/ShowStructureSettingsAction.java b/java/idea-ui/src/com/intellij/ide/actions/ShowStructureSettingsAction.java index ded07d482ed3..eeb8d1b95a49 100644 --- a/java/idea-ui/src/com/intellij/ide/actions/ShowStructureSettingsAction.java +++ b/java/idea-ui/src/com/intellij/ide/actions/ShowStructureSettingsAction.java @@ -56,7 +56,7 @@ public class ShowStructureSettingsAction extends AnAction implements DumbAware { protected JComponent createSouthPanel() { JComponent panel = super.createSouthPanel(); assert panel != null; - CustomLineBorder line = new CustomLineBorder(new JBColor(Gray._153, Gray._80), 1, 0, 0, 0); + CustomLineBorder line = new CustomLineBorder(new JBColor(Gray._153.withAlpha(128), Gray._100.withAlpha(128)), 1, 0, 0, 0); panel.setBorder(new CompoundBorder(line, new EmptyBorder(10, 5, 5, 5))); return panel; } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/DefaultLibraryRootsComponentDescriptor.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/DefaultLibraryRootsComponentDescriptor.java index 7285480686c0..eb87df2a47e7 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/DefaultLibraryRootsComponentDescriptor.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/DefaultLibraryRootsComponentDescriptor.java @@ -130,7 +130,8 @@ public class DefaultLibraryRootsComponentDescriptor extends LibraryRootsComponen public boolean isAccepted(@NotNull VirtualFile rootCandidate, @NotNull ProgressIndicator progressIndicator) { if (rootCandidate.isDirectory()) { for (VirtualFile file : rootCandidate.getChildren()) { - if (NATIVE_LIBRARY_EXTENSIONS.contains(file.getExtension())) { + String extension = file.getExtension(); + if (extension != null && NATIVE_LIBRARY_EXTENSIONS.contains(extension)) { return true; } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy index c748c22b4e88..1f4e40e3c8ca 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy @@ -1300,7 +1300,7 @@ class Foo {{ type '.' assert myFixture.lookupElementStrings == ['Util.bar', 'Util.CONSTANT', 'Util.foo'] - def p = LookupElementPresentation.renderElement(myFixture.lookupElements[1]) + def p = ApplicationManager.application.runReadAction ({ LookupElementPresentation.renderElement(myFixture.lookupElements[1]) } as Computable) assert p.itemText == 'Util.CONSTANT' assert p.tailText == ' (foo)' assert p.typeText == 'int' diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/event/EditorFactoryListener.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/event/EditorFactoryListener.java index b8bd41980b7c..1d8ddcc2930b 100644 --- a/platform/editor-ui-api/src/com/intellij/openapi/editor/event/EditorFactoryListener.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/event/EditorFactoryListener.java @@ -23,7 +23,13 @@ import java.util.EventListener; * @see {@link com.intellij.openapi.editor.EditorFactory#addEditorFactoryListener(com.intellij.openapi.editor.event.EditorFactoryListener, com.intellij.openapi.Disposable)} */ public interface EditorFactoryListener extends EventListener { + /** + * Called after {@link com.intellij.openapi.editor.Editor} instance has been created. + */ void editorCreated(@NotNull EditorFactoryEvent event); + /** + * Called before {@link com.intellij.openapi.editor.Editor} instance will be released. + */ void editorReleased(@NotNull EditorFactoryEvent event); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index 44cab6a0ac3e..b309d66d130c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -856,6 +856,17 @@ public class DocumentationManager extends DockablePopupManager[] flags, final Color background) { StringBuilder buf = new StringBuilder(); removeAll(); - final String[] lines = UIUtil.splitText(StringUtil.join(texts), getFontMetrics(BOLD_FONT), myWidthLimit, ','); - + setBackground(background); int index = 0; int curOffset = 0; - - myOneLineComponents = new OneLineComponent[lines.length]; + final ArrayList components = new ArrayList(); Map flagsMap = new TreeMap(TEXT_RANGE_COMPARATOR); - int added = 0; + String line = ""; for (int i = 0; i < texts.length; i++) { - String line = escapeString(texts[i]); - if (lines.length <= index) break; - String text = lines[index]; - final int paramCount = StringUtil.split(text, ", ").size(); + String paramText = escapeString(texts[i]); + if (paramText == null) break; + line += texts[i]; final EnumSet flag = flags[i]; if (flag.contains(ParameterInfoUIContextEx.Flag.HIGHLIGHT)) { - flagsMap.put(TextRange.create(curOffset, curOffset + line.trim().length()), ParameterInfoUIContextEx.Flag.HIGHLIGHT); + flagsMap.put(TextRange.create(curOffset, curOffset + paramText.trim().length()), ParameterInfoUIContextEx.Flag.HIGHLIGHT); } if (flag.contains(ParameterInfoUIContextEx.Flag.DISABLE)) { - flagsMap.put(TextRange.create(curOffset, curOffset + line.trim().length()), ParameterInfoUIContextEx.Flag.DISABLE); + flagsMap.put(TextRange.create(curOffset, curOffset + paramText.trim().length()), ParameterInfoUIContextEx.Flag.DISABLE); } if (flag.contains(ParameterInfoUIContextEx.Flag.STRIKEOUT)) { - flagsMap.put(TextRange.create(curOffset, curOffset + line.trim().length()), ParameterInfoUIContextEx.Flag.STRIKEOUT); + flagsMap.put(TextRange.create(curOffset, curOffset + paramText.trim().length()), ParameterInfoUIContextEx.Flag.STRIKEOUT); } - curOffset += line.length(); - if (i == paramCount + added - 1) { - myOneLineComponents[index] = new OneLineComponent(); - setBackground(background); - buf.append(myOneLineComponents[index].setup(escapeString(text), flagsMap, background)); - add(myOneLineComponents[index], new GridBagConstraints(0, index, 1, 1, 1, 0, GridBagConstraints.WEST, + curOffset += paramText.length(); + if (line.length() >= 50) { + final OneLineComponent component = new OneLineComponent(); + buf.append(component.setup(escapeString(line), flagsMap, background)); + add(component, new GridBagConstraints(0, index, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); index += 1; flagsMap.clear(); curOffset = 1; - added += paramCount; + line = ""; + components.add(component); } } + final OneLineComponent component = new OneLineComponent(); + buf.append(component.setup(escapeString(line), flagsMap, background)); + add(component, new GridBagConstraints(0, index, 1, 1, 1, 0, GridBagConstraints.WEST, + GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + components.add(component); + myOneLineComponents = components.toArray(new OneLineComponent[components.size()]); return buf.toString(); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java index ec0cef4e76d5..d0313e04cf9f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java @@ -203,14 +203,17 @@ public class EditorFactoryImpl extends EditorFactory implements ApplicationCompo @Override public void releaseEditor(@NotNull Editor editor) { try { - ((EditorImpl)editor).release(); + myEditorFactoryEventDispatcher.getMulticaster().editorReleased(new EditorFactoryEvent(this, editor)); } finally { - myEditors.remove(editor); - myEditorFactoryEventDispatcher.getMulticaster().editorReleased(new EditorFactoryEvent(this, editor)); - - if (LOG.isDebugEnabled()) { - LOG.debug("number of Editor's:" + myEditors.size()); + try { + ((EditorImpl)editor).release(); + } + finally { + myEditors.remove(editor); + if (LOG.isDebugEnabled()) { + LOG.debug("number of Editor's:" + myEditors.size()); + } } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/GlassPanel.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/GlassPanel.java index 96cc9e451185..c80a222ffd96 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/ex/GlassPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/GlassPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. @@ -17,7 +17,10 @@ package com.intellij.openapi.options.ex; import com.intellij.ide.ui.search.SearchUtil; +import com.intellij.openapi.ui.GraphicsConfig; +import com.intellij.ui.ColorUtil; import com.intellij.ui.components.JBTabbedPane; +import com.intellij.util.ui.GraphicsUtil; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.Nullable; @@ -27,6 +30,7 @@ import java.awt.geom.Area; import java.awt.geom.Rectangle2D; import java.awt.geom.RoundRectangle2D; import java.awt.image.Kernel; +import java.util.ArrayList; import java.util.HashSet; import java.util.Set; @@ -64,17 +68,19 @@ public class GlassPanel extends JComponent { final Point leftPoint = SwingUtilities.convertPoint(myPanel, new Point(visibleRect.x, visibleRect.y), surfaceComponent); Area innerPanel = new Area(new Rectangle2D.Double(leftPoint.x, leftPoint.y, visibleRect.width, visibleRect.height)); Area mask = new Area(screen); - + ArrayList components = new ArrayList(); for (JComponent lightComponent : myLightComponents) { - final Area area = getComponentArea(surfaceComponent, lightComponent); + final Area area = getComponentArea(surfaceComponent, lightComponent, 1); if (area == null) continue; + components.add(lightComponent); if (lightComponent instanceof JLabel) { final JLabel label = (JLabel)lightComponent; final Component labelFor = label.getLabelFor(); if (labelFor instanceof JComponent) { - final Area labelForArea = getComponentArea(surfaceComponent, (JComponent)labelFor); + final Area labelForArea = getComponentArea(surfaceComponent, (JComponent)labelFor, 1); if (labelForArea != null) { + components.add((JComponent)labelFor); area.add(labelForArea); } } @@ -86,19 +92,32 @@ public class GlassPanel extends JComponent { Graphics2D g2 = (Graphics2D)g; - Color shieldColor = new Color(0.0f, 0.0f, 0.0f, 0.15f); + Color shieldColor = new Color(0.0f, 0.0f, 0.0f, 0.20f); Color boundsColor = Color.gray; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor(shieldColor); g2.fill(mask); - g2.setColor(boundsColor); - g2.draw(mask); + g2.setColor(ColorUtil.toAlpha(Color.orange, 25)); + GraphicsConfig config = GraphicsUtil.setupAAPainting(g2); + for (int i = 2; i > 0; i--) { + g2.setStroke(new BasicStroke(i)); + Area arrr = new Area(); + for (JComponent component : components) { + Area area = getComponentArea(surfaceComponent, component, i-1); + if (area != null) { + arrr.add(area); + } + } + g2.draw(arrr); + } + + config.restore(); } } @Nullable - private Area getComponentArea(final JComponent surfaceComponent, final JComponent lightComponent) { + private Area getComponentArea(final JComponent surfaceComponent, final JComponent lightComponent, int offset) { if (!lightComponent.isShowing()) return null; final Point panelPoint = SwingUtilities.convertPoint(lightComponent, new Point(0, 0), surfaceComponent); @@ -115,12 +134,17 @@ public class GlassPanel extends JComponent { int hInset = isWithBorder ? 7 : isLabelFromTabbedPane ? 20 : 7; int vInset = isWithBorder ? 1 : isLabelFromTabbedPane ? 10 : 5; - final Area area = new Area(new RoundRectangle2D.Double(x - hInset + insetsToIgnore.left, - y - vInset + insetsToIgnore.top, - lightComponent.getWidth() + hInset * 2 - insetsToIgnore.right - insetsToIgnore.left, - lightComponent.getHeight() + vInset * 2 - insetsToIgnore.top - insetsToIgnore.bottom, - 6, 6)); - return area; + hInset += offset; + vInset += offset; + int xCoord = x - hInset + insetsToIgnore.left; + int yCoord = y - vInset + insetsToIgnore.top; + int width = lightComponent.getWidth() + hInset * 2 - insetsToIgnore.right - insetsToIgnore.left; + int height = lightComponent.getHeight() + vInset * 2 - insetsToIgnore.top - insetsToIgnore.bottom; + return new Area(new RoundRectangle2D.Double(xCoord, + yCoord, + width, + height, + Math.min(height, 30), Math.min(height, 30))); } protected static Kernel getBlurKernel(int blurSize) { diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java index 03ced8a33825..c38bf6ff2033 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java @@ -128,7 +128,7 @@ public class IdeSettingsDialog extends DialogWrapper implements DataProvider { @Override protected JComponent createSouthPanel() { final JComponent panel = super.createSouthPanel(); - CustomLineBorder line = new CustomLineBorder(new JBColor(Gray._153, Gray._80), 1, 0, 0, 0); + CustomLineBorder line = new CustomLineBorder(new JBColor(Gray._153.withAlpha(128), Gray._100.withAlpha(128)), 1, 0, 0, 0); panel.setBorder(new CompoundBorder(line, new EmptyBorder(8, 12, 8, 12))); return panel; } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java index 443e5ee5f40b..2b3aa5bdda1d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java @@ -1201,7 +1201,8 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat * @return default view for the specified configurable */ private JComponent createDefaultComponent(SearchableConfigurable searchable) { - Box box = Box.createVerticalBox(); + JPanel box = new JPanel(); + box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS)); try { box.add(new JLabel(OptionsBundle.message(searchable.getId() + ".settings.description"))); } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java index 18a953593275..aee9e889fdf1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java @@ -37,6 +37,7 @@ import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure; import com.intellij.util.ui.GraphicsUtil; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; +import com.intellij.util.ui.tree.WideSelectionTreeUI; import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; import org.jetbrains.annotations.NotNull; @@ -49,12 +50,14 @@ import javax.swing.event.TreeExpansionListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.plaf.TreeUI; -import javax.swing.plaf.basic.BasicTreeUI; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import java.awt.*; -import java.awt.event.*; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; import java.util.*; import java.util.List; @@ -403,6 +406,9 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl } else { myProjectIcon.setVisible(false); } + if (Registry.is("ide.new.settings.dialog")) { + result.setBackground(selected ? UIUtil.getTreeSelectionBackground() : UIUtil.getSidePanelColor()); + } return result; } @@ -727,7 +733,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl super.processMouseEvent(e); } - private class MyTreeUi extends BasicTreeUI { + private class MyTreeUi extends WideSelectionTreeUI { @Override public void toggleExpandState(final TreePath path) { 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 fa3d08cac414..c36863e250b3 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 @@ -82,6 +82,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd myFilter = filter; myRoot = new MyRoot(groups); myTree = new MyTree(); + myTree.putClientProperty(WideSelectionTreeUI.TREE_TABLE_TREE_KEY, Boolean.TRUE); myTree.setBackground(UIUtil.getSidePanelColor()); myTree.getInputMap().clear(); TreeUtil.installActions(myTree); diff --git a/platform/testFramework/src/com/intellij/testFramework/LoggedErrorProcessor.java b/platform/testFramework/src/com/intellij/testFramework/LoggedErrorProcessor.java index 1577c7d21744..eb7611e4ed9e 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LoggedErrorProcessor.java +++ b/platform/testFramework/src/com/intellij/testFramework/LoggedErrorProcessor.java @@ -15,7 +15,6 @@ */ package com.intellij.testFramework; -import com.intellij.openapi.util.text.StringUtil; import org.apache.log4j.Logger; import org.jetbrains.annotations.NotNull; @@ -45,10 +44,15 @@ public class LoggedErrorProcessor { public void processError(String message, Throwable t, String[] details, @NotNull Logger logger) { logger.info(message, t); + System.err.println("ERROR: " + message); + if (t != null) t.printStackTrace(System.err); if (details != null && details.length > 0) { - message += "\n Details:" + StringUtil.join(details, "\n "); + System.out.println("details: "); + for (String detail : details) { + System.out.println(detail); + } } - throw new RuntimeException(message, t); + throw new AssertionError(message); } } diff --git a/platform/util-rt/src/com/intellij/openapi/util/Conditions.java b/platform/util-rt/src/com/intellij/openapi/util/Conditions.java index 633802d3408b..48bb06ad8b8e 100644 --- a/platform/util-rt/src/com/intellij/openapi/util/Conditions.java +++ b/platform/util-rt/src/com/intellij/openapi/util/Conditions.java @@ -45,7 +45,7 @@ public class Conditions { public static Condition is(final T option) { return new Condition() { public boolean value(T t) { - return t == option; + return Comparing.equal(t, option); } }; } diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNewProject.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNewProject.java index 665cfd7a5dd3..0b75c4bc01c4 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNewProject.java +++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNewProject.java @@ -24,7 +24,7 @@ import org.jetbrains.annotations.Nullable; public class StudyNewProject extends ProjectSpecificAction { public StudyNewProject(@NotNull final String name, @Nullable final Runnable runnable) { - super(new GenerateProjectCallback(runnable), new StudyDirectoryProjectGenerator(), name); + super(new GenerateProjectCallback(runnable), new StudyDirectoryProjectGenerator(), name, true); } public StudyNewProject() { diff --git a/python/helpers/rest_formatter.py b/python/helpers/rest_formatter.py index e3575f8d147f..a1d176cd3f8f 100644 --- a/python/helpers/rest_formatter.py +++ b/python/helpers/rest_formatter.py @@ -1,4 +1,5 @@ import sys +import re from docutils.core import publish_string from docutils import nodes from docutils.nodes import Text @@ -54,6 +55,53 @@ class RestHTMLTranslator(_EpydocHTMLTranslator): self.body.append("") HTMLTranslator.depart_field_body(self, node) + def visit_reference(self, node): + atts = {} + if 'refuri' in node: + atts['href'] = node['refuri'] + if self.settings.cloak_email_addresses and atts['href'].startswith('mailto:'): + atts['href'] = self.cloak_mailto(atts['href']) + self.in_mailto = True + # atts['class'] += ' external' + else: + assert 'refid' in node, 'References must have "refuri" or "refid" attribute.' + atts['href'] = '#' + node['refid'] + atts['class'] += ' internal' + if not isinstance(node.parent, nodes.TextElement): + assert len(node) == 1 and isinstance(node[0], nodes.image) + atts['class'] += ' image-reference' + self.body.append(self.starttag(node, 'a', '', **atts)) + + def starttag(self, node, tagname, suffix='\n', **attributes): + attr_dicts = [attributes] + if isinstance(node, nodes.Node): + attr_dicts.append(node.attributes) + if isinstance(node, dict): + attr_dicts.append(node) + # Munge each attribute dictionary. Unfortunately, we need to + # iterate through attributes one at a time because some + # versions of docutils don't case-normalize attributes. + for attr_dict in attr_dicts: + for (key, val) in attr_dict.items(): + # Prefix all CSS classes with "rst-"; and prefix all + # names with "rst-" to avoid conflicts. + if key.lower() in ('class', 'id', 'name'): + attr_dict[key] = 'rst-%s' % val + elif key.lower() in ('classes', 'ids', 'names'): + attr_dict[key] = ['rst-%s' % cls for cls in val] + elif key.lower() == 'href': + if attr_dict[key][:1]=='#': + attr_dict[key] = '#rst-%s' % attr_dict[key][1:] + else: + pass + # For headings, use class="heading" + if re.match(r'^h\d+$', tagname): + attributes['class'] = ' '.join([attributes.get('class',''), + 'heading']).strip() + + return HTMLTranslator.starttag(self, node, tagname, suffix, + **attributes) + def visit_field_list(self, node): fields = {} diff --git a/python/ide/src/com/jetbrains/python/configuration/PyContentEntriesModuleConfigurable.java b/python/ide/src/com/jetbrains/python/configuration/PyContentEntriesModuleConfigurable.java index bcbebc3b2639..ca00208c3c88 100644 --- a/python/ide/src/com/jetbrains/python/configuration/PyContentEntriesModuleConfigurable.java +++ b/python/ide/src/com/jetbrains/python/configuration/PyContentEntriesModuleConfigurable.java @@ -1,60 +1,29 @@ package com.jetbrains.python.configuration; import com.intellij.facet.impl.DefaultFacetsProvider; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CustomShortcutSet; -import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.impl.ModuleConfigurationStateImpl; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.ContentEntry; -import com.intellij.openapi.roots.ContentFolder; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootManager; -import com.intellij.openapi.roots.impl.ContentEntryImpl; -import com.intellij.openapi.roots.impl.ContentFolderBaseImpl; -import com.intellij.openapi.roots.ui.configuration.*; -import com.intellij.openapi.roots.ui.configuration.actions.ContentEntryEditingAction; -import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.roots.ui.configuration.DefaultModulesProvider; +import com.intellij.openapi.roots.ui.configuration.FacetsProvider; import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.vfs.VfsUtilCore; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.pointers.VirtualFilePointer; -import com.intellij.openapi.vfs.pointers.VirtualFilePointerListener; -import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager; -import com.intellij.ui.JBColor; -import com.intellij.util.EventDispatcher; -import com.intellij.util.containers.MultiMap; -import com.jetbrains.python.templateLanguages.TemplatesService; -import icons.PythonIcons; +import com.jetbrains.python.module.PyContentEntriesEditor; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.java.JavaSourceRootType; -import org.jetbrains.jps.model.module.JpsModuleSourceRootType; import javax.swing.*; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.tree.TreeCellRenderer; import java.awt.*; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.util.ArrayList; -import java.util.List; public class PyContentEntriesModuleConfigurable extends SearchableConfigurable.Parent.Abstract { - private static final Color TEMPLATES_COLOR = JBColor.MAGENTA; - private final Module myModule; private final JPanel myTopPanel = new JPanel(new BorderLayout()); protected ModifiableRootModel myModifiableModel; - protected MyCommonContentEntriesEditor myEditor; + protected PyContentEntriesEditor myEditor; public PyContentEntriesModuleConfigurable(final Module module) { myModule = module; @@ -108,8 +77,8 @@ public class PyContentEntriesModuleConfigurable extends SearchableConfigurable.P myTopPanel.add(component, BorderLayout.CENTER); } - protected MyCommonContentEntriesEditor createEditor(@NotNull Module module, @NotNull ModuleConfigurationStateImpl state) { - return new MyCommonContentEntriesEditor(module, state, JavaSourceRootType.SOURCE); + protected PyContentEntriesEditor createEditor(@NotNull Module module, @NotNull ModuleConfigurationStateImpl state) { + return new PyContentEntriesEditor(module, state, JavaSourceRootType.SOURCE); } @Override @@ -171,314 +140,4 @@ public class PyContentEntriesModuleConfigurable extends SearchableConfigurable.P return "python.project.structure"; } - private static class MyContentEntryTreeEditor extends ContentEntryTreeEditor { - - private final ChangeListener myListener = new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - update(); - } - }; - - public MyContentEntryTreeEditor(Project project, List> handlers) { - super(project, handlers); - } - - @Override - public void setContentEntryEditor(ContentEntryEditor newEditor) { - MyCommonContentEntriesEditor.MyContentEntryEditor existingEditor = getContentEntryEditor(); - if (Comparing.equal(existingEditor, newEditor)) { - return; - } - if (existingEditor != null) { - existingEditor.removeListener(myListener); - } - if (newEditor != null) { - ((MyCommonContentEntriesEditor.MyContentEntryEditor)newEditor).addListener(myListener); - } - super.setContentEntryEditor(newEditor); - } - - @Override - public MyCommonContentEntriesEditor.MyContentEntryEditor getContentEntryEditor() { - return (MyCommonContentEntriesEditor.MyContentEntryEditor)super.getContentEntryEditor(); - } - - @Override - protected void createEditingActions() { - super.createEditingActions(); - - ContentEntryEditingAction a = new ContentEntryEditingAction(myTree) { - { - final Presentation templatePresentation = getTemplatePresentation(); - templatePresentation.setText("Templates"); - templatePresentation.setDescription("Template Folders"); - templatePresentation.setIcon(PythonIcons.Python.TemplateRoot); - } - - @Override - public boolean isSelected(AnActionEvent e) { - final VirtualFile[] selectedFiles = getSelectedFiles(); - return selectedFiles.length != 0 && getContentEntryEditor().hasTemplateRoot(selectedFiles[0]); - } - - @Override - public void setSelected(AnActionEvent e, boolean isSelected) { - final VirtualFile[] selectedFiles = getSelectedFiles(); - assert selectedFiles.length != 0; - - for (VirtualFile selectedFile : selectedFiles) { - boolean wasSelected = getContentEntryEditor().hasTemplateRoot(selectedFile); - if (isSelected) { - if (!wasSelected) { - getContentEntryEditor().addTemplateRoot(selectedFile); - } - } - else { - if (wasSelected) { - getContentEntryEditor().removeTemplateRoot(selectedFile); - } - } - } - } - }; - myEditingActionsGroup.add(a); - a.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.ALT_MASK)), myTree); - } - - @Override - protected TreeCellRenderer getContentEntryCellRenderer() { - return new ContentEntryTreeCellRenderer(this, getEditHandlers()) { - @Override - protected Icon updateIcon(final ContentEntry entry, final VirtualFile file, final Icon originalIcon) { - if (getContentEntryEditor().hasTemplateRoot(file)) { - return PythonIcons.Python.TemplateRoot; - } - return super.updateIcon(entry, file, originalIcon); - } - }; - } - } - - protected static class MyCommonContentEntriesEditor extends CommonContentEntriesEditor { - private final MultiMap myTemplateRoots = new MultiMap(); - private final Module myModule; - private Disposable myFilePointersDisposable; - - private final VirtualFilePointerListener DUMMY_LISTENER = new VirtualFilePointerListener() { - @Override - public void beforeValidityChanged(@NotNull VirtualFilePointer[] pointers) { - } - - @Override - public void validityChanged(@NotNull VirtualFilePointer[] pointers) { - } - }; - - public MyCommonContentEntriesEditor(Module module, - ModuleConfigurationStateImpl moduleConfigurationState, - JpsModuleSourceRootType... rootTypes) { - super(module.getName(), moduleConfigurationState, rootTypes); - myModule = module; - reset(); - } - - @Override - protected ContentEntryTreeEditor createContentEntryTreeEditor(Project project) { - return new MyContentEntryTreeEditor(project, getEditHandlers()); - } - - @Override - protected List addContentEntries(VirtualFile[] files) { - List entries = super.addContentEntries(files); - addContentEntryPanels(entries.toArray(new ContentEntry[entries.size()])); - return entries; - } - - @Override - public void reset() { - if (myFilePointersDisposable != null) { - Disposer.dispose(myFilePointersDisposable); - } - myTemplateRoots.clear(); - - myFilePointersDisposable = Disposer.newDisposable(); - final TemplatesService instance = TemplatesService.getInstance(myModule); - if (instance != null) { - final List folders = instance.getTemplateFolders(); - for (VirtualFile folder : folders) { - ContentEntry contentEntry = findContentEntryForFile(folder); - if (contentEntry != null) { - myTemplateRoots.putValue(contentEntry, VirtualFilePointerManager.getInstance().create(folder, myFilePointersDisposable, - DUMMY_LISTENER)); - } - } - } - - if (myRootTreeEditor != null) { - ContentEntryEditor editor = myRootTreeEditor.getContentEntryEditor(); - if(editor!=null) editor.update(); - myRootTreeEditor.update(); - } - } - - @Nullable - private ContentEntry findContentEntryForFile(VirtualFile virtualFile) { - for (ContentEntry contentEntry : getModel().getContentEntries()) { - final VirtualFile file = contentEntry.getFile(); - if (file != null && VfsUtilCore.isAncestor(file, virtualFile, false)) { - return contentEntry; - } - } - return null; - } - - @Override - public void disposeUIResources() { - super.disposeUIResources(); - if (myFilePointersDisposable != null) { - Disposer.dispose(myFilePointersDisposable); - } - } - - @Override - public void apply() throws ConfigurationException { - super.apply(); - List templateRoots = getCurrentState(); - TemplatesService.getInstance(myModule).setTemplateFolders(templateRoots.toArray(new VirtualFile[templateRoots.size()])); - } - - private List getCurrentState() { - List result = new ArrayList(); - for (ContentEntry entry : myTemplateRoots.keySet()) { - for (VirtualFilePointer filePointer : myTemplateRoots.get(entry)) { - result.add(filePointer.getFile()); - } - } - return result; - } - - @Override - public boolean isModified() { - if (super.isModified()) return true; - final TemplatesService templatesService = TemplatesService.getInstance(myModule); - if (templatesService != null) { - List original = templatesService.getTemplateFolders(); - List current = getCurrentState(); - - if (!Comparing.haveEqualElements(original, current)) return true; - - } - return false; - } - - @Override - protected MyContentEntryEditor createContentEntryEditor(String contentEntryUrl) { - return new MyContentEntryEditor(contentEntryUrl, getEditHandlers()); - } - - protected class MyContentEntryEditor extends ContentEntryEditor { - private final EventDispatcher myEventDispatcher = EventDispatcher.create(ChangeListener.class); - - public MyContentEntryEditor(String contentEntryUrl, List> handlers) { - super(contentEntryUrl, handlers); - } - - @Override - protected ModifiableRootModel getModel() { - return MyCommonContentEntriesEditor.this.getModel(); - } - - public void addListener(ChangeListener changeListener) { - myEventDispatcher.addListener(changeListener); - } - - public void removeListener(ChangeListener changeListener) { - myEventDispatcher.removeListener(changeListener); - } - - @Override - protected ContentRootPanel createContentRootPane() { - return new MyContentRootPanel(); - } - - @Override - public void deleteContentFolder(ContentEntry contentEntry, ContentFolder folder) { - if (folder instanceof TemplateRootFolder) { - final VirtualFile file = folder.getFile(); - if (file != null) { - removeTemplateRoot(file); - } - } - else { - super.deleteContentFolder(contentEntry, folder); - } - } - - public void addTemplateRoot(@NotNull final VirtualFile file) { - final VirtualFilePointer root = VirtualFilePointerManager.getInstance().create(file, myFilePointersDisposable, DUMMY_LISTENER); - myTemplateRoots.putValue(getContentEntry(), root); - myEventDispatcher.getMulticaster().stateChanged(new ChangeEvent(this)); - update(); - } - - public void removeTemplateRoot(@NotNull final VirtualFile file) { - final VirtualFilePointer root = getTemplateRoot(file); - if (root != null) { - myTemplateRoots.remove(getContentEntry(), root); - myEventDispatcher.getMulticaster().stateChanged(new ChangeEvent(this)); - update(); - } - } - - public boolean hasTemplateRoot(@NotNull final VirtualFile file) { - return getTemplateRoot(file) != null; - } - - @Nullable - public VirtualFilePointer getTemplateRoot(@NotNull final VirtualFile file) { - for (VirtualFilePointer filePointer : myTemplateRoots.get(getContentEntry())) { - if (Comparing.equal(filePointer.getFile(), file)) { - return filePointer; - } - } - return null; - } - - protected class MyContentRootPanel extends ContentRootPanel { - public MyContentRootPanel() { - super(MyContentEntryEditor.this, getEditHandlers()); - } - - @Override - @NotNull - protected ContentEntryImpl getContentEntry() { - //noinspection ConstantConditions - return (ContentEntryImpl)MyContentEntryEditor.this.getContentEntry(); - } - - @Override - protected void addFolderGroupComponents() { - super.addFolderGroupComponents(); - if (!myTemplateRoots.get(getContentEntry()).isEmpty()) { - final List folders = new ArrayList(myTemplateRoots.size()); - for (VirtualFilePointer root : myTemplateRoots.get(getContentEntry())) { - folders.add(new TemplateRootFolder(root, getContentEntry())); - } - final JComponent sourcesComponent = createFolderGroupComponent("Template Folders", - folders.toArray(new ContentFolder[folders.size()]), - TEMPLATES_COLOR, null); - this.add(sourcesComponent, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, - GridBagConstraints.HORIZONTAL, new Insets(0, 0, 10, 0), 0, 0)); - } - } - } - } - } - - private static class TemplateRootFolder extends ContentFolderBaseImpl { - protected TemplateRootFolder(@NotNull VirtualFilePointer filePointer, @NotNull ContentEntryImpl contentEntry) { - super(filePointer, contentEntry); - } - } } diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java index b923b3cf6526..af1d40876d50 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java @@ -61,6 +61,7 @@ import java.util.List; abstract public class AbstractProjectSettingsStep extends AbstractActionWithPanel implements DumbAware { protected final DirectoryProjectGenerator myProjectGenerator; private final NullableConsumer myCallback; + private final boolean myIsWelcomeScreen; private PythonSdkChooserCombo mySdkCombo; private boolean myInstallFramework; private TextFieldWithBrowseButton myLocationField; @@ -70,10 +71,13 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane private AnAction myCreateAction; private Sdk mySdk; - public AbstractProjectSettingsStep(DirectoryProjectGenerator projectGenerator, NullableConsumer callback) { + public AbstractProjectSettingsStep(DirectoryProjectGenerator projectGenerator, + NullableConsumer callback, + boolean isWelcomeScreen) { super(); myProjectGenerator = projectGenerator; myCallback = callback; + myIsWelcomeScreen = isWelcomeScreen; myProjectDirectory = FileUtil.findSequentNonexistentFile(new File(ProjectUtil.getBaseDir()), "untitled", ""); if (myProjectGenerator instanceof WebProjectTemplate) { ((WebProjectTemplate)myProjectGenerator).getPeer().addSettingsStateListener(new WebProjectGenerator.SettingsStateListener() { @@ -109,17 +113,12 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane @Override public JPanel createPanel() { final JPanel basePanel = createBasePanel(); - final JPanel mainPanel = new JPanel(new BorderLayout()) { - @Override - protected void paintComponent(Graphics g) { - myLocationField.requestFocus(); - } - }; + final JPanel mainPanel = new JPanel(new BorderLayout()); final JPanel scrollPanel = new JPanel(new BorderLayout()); final DirectoryProjectGenerator[] generators = Extensions.getExtensions(DirectoryProjectGenerator.EP_NAME); - final int height = generators.length == 0 ? 150 : 400; + final int height = generators.length == 0 && !myIsWelcomeScreen ? 150 : 400; mainPanel.setPreferredSize(new Dimension(mainPanel.getPreferredSize().width, height)); myErrorLabel = new JLabel(""); myErrorLabel.setForeground(JBColor.RED); diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/PluginSpecificProjectsStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/PluginSpecificProjectsStep.java index a0c5f6e52fbf..ca0f3608a5d9 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/PluginSpecificProjectsStep.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/PluginSpecificProjectsStep.java @@ -27,11 +27,11 @@ import java.util.List; public class PluginSpecificProjectsStep extends DefaultActionGroup implements DumbAware { public PluginSpecificProjectsStep(@NotNull final NullableConsumer callback, - @NotNull final List projectGenerators) { + @NotNull final List projectGenerators, boolean isWelcomeScreen) { super("Plugin-specific", true); getTemplatePresentation().setIcon(AllIcons.Nodes.PluginLogo); for (DirectoryProjectGenerator generator : projectGenerators) { - add(new ProjectSpecificAction(callback, generator)); + add(new ProjectSpecificAction(callback, generator, isWelcomeScreen)); } } } diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java index 85cf6d118d34..fbb65f0fbe9e 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java @@ -28,16 +28,16 @@ public class ProjectSpecificAction extends DefaultActionGroup implements DumbAwa private final ProjectSpecificSettingsStep mySettings; public ProjectSpecificAction(@NotNull final NullableConsumer callback, - @NotNull final DirectoryProjectGenerator projectGenerator) { - this(callback, projectGenerator, projectGenerator.getName()); + @NotNull final DirectoryProjectGenerator projectGenerator, boolean isWelcomeScreen) { + this(callback, projectGenerator, projectGenerator.getName(), isWelcomeScreen); } public ProjectSpecificAction(@NotNull final NullableConsumer callback, @NotNull final DirectoryProjectGenerator projectGenerator, - @NotNull final String name) { + @NotNull final String name, boolean isWelcomeScreen) { super(name, true); getTemplatePresentation().setIcon(projectGenerator.getLogo()); - mySettings = new ProjectSpecificSettingsStep(projectGenerator, callback); + mySettings = new ProjectSpecificSettingsStep(projectGenerator, callback, isWelcomeScreen); add(mySettings); } diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java index 5e60601399bb..b85a06e0daa6 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java @@ -31,8 +31,8 @@ import javax.swing.*; public class ProjectSpecificSettingsStep extends AbstractProjectSettingsStep implements DumbAware { public ProjectSpecificSettingsStep(@NotNull final DirectoryProjectGenerator projectGenerator, - @NotNull final NullableConsumer callback) { - super(projectGenerator, callback); + @NotNull final NullableConsumer callback, boolean isWelcomeScreen) { + super(projectGenerator, callback, isWelcomeScreen); } @Override diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java index b15c20606ded..0628c6d829c1 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java @@ -34,11 +34,15 @@ import java.util.List; public class PyCharmNewProjectStep extends DefaultActionGroup implements DumbAware { public PyCharmNewProjectStep(@NotNull final String name, @Nullable final Runnable runnable) { + this(name, runnable, false); + } + + public PyCharmNewProjectStep(@NotNull final String name, @Nullable final Runnable runnable, boolean isWelcomeScreen) { super(name, true); final NullableConsumer callback = new GenerateProjectCallback(runnable); - final ProjectSpecificAction action = new ProjectSpecificAction(callback, new PythonBaseProjectGenerator()); + final ProjectSpecificAction action = new ProjectSpecificAction(callback, new PythonBaseProjectGenerator(), isWelcomeScreen); add(action); final DirectoryProjectGenerator[] generators = Extensions.getExtensions(DirectoryProjectGenerator.EP_NAME); @@ -57,19 +61,17 @@ public class PyCharmNewProjectStep extends DefaultActionGroup implements DumbAwa List pluginSpecificGenerators = Lists.newArrayList(); for (DirectoryProjectGenerator generator : generators) { if (generator instanceof PythonProjectGenerator) - add(new ProjectSpecificAction(callback, generator)); + add(new ProjectSpecificAction(callback, generator, isWelcomeScreen)); else pluginSpecificGenerators.add(generator); } if (!pluginSpecificGenerators.isEmpty()) { - add(new PluginSpecificProjectsStep(callback, pluginSpecificGenerators)); + add(new PluginSpecificProjectsStep(callback, pluginSpecificGenerators, isWelcomeScreen)); } } public PyCharmNewProjectStep() { - this("Select Project Type", null); - + this("Select Project Type", null, true); } - } diff --git a/python/pluginSrc/com/jetbrains/python/module/PythonModuleConfigurationEditorProvider.java b/python/pluginSrc/com/jetbrains/python/module/PythonModuleConfigurationEditorProvider.java index 01203480eae4..50b79c717112 100644 --- a/python/pluginSrc/com/jetbrains/python/module/PythonModuleConfigurationEditorProvider.java +++ b/python/pluginSrc/com/jetbrains/python/module/PythonModuleConfigurationEditorProvider.java @@ -15,15 +15,16 @@ */ package com.jetbrains.python.module; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleConfigurationEditor; import com.intellij.openapi.module.ModuleType; +import com.intellij.openapi.roots.ui.configuration.DefaultModuleConfigurationEditorFactory; import com.intellij.openapi.roots.ui.configuration.ModuleConfigurationEditorProvider; import com.intellij.openapi.roots.ui.configuration.ModuleConfigurationState; -import com.intellij.openapi.roots.ui.configuration.DefaultModuleConfigurationEditorFactory; -import com.intellij.openapi.module.ModuleConfigurationEditor; -import com.intellij.openapi.module.Module; +import org.jetbrains.jps.model.java.JavaSourceRootType; -import java.util.List; import java.util.ArrayList; +import java.util.List; /** * @author yole @@ -34,7 +35,7 @@ public class PythonModuleConfigurationEditorProvider implements ModuleConfigurat if (!(ModuleType.get(module) instanceof PythonModuleType)) return ModuleConfigurationEditor.EMPTY; final DefaultModuleConfigurationEditorFactory editorFactory = DefaultModuleConfigurationEditorFactory.getInstance(); final List editors = new ArrayList(); - editors.add(editorFactory.createModuleContentRootsEditor(state)); + editors.add(new PyContentEntriesEditor(module, state, JavaSourceRootType.SOURCE)); editors.add(editorFactory.createClasspathEditor(state)); return editors.toArray(new ModuleConfigurationEditor[editors.size()]); } diff --git a/python/rest/gen/com/jetbrains/rest/lexer/_RestFlexLexer.java b/python/rest/gen/com/jetbrains/rest/lexer/_RestFlexLexer.java index 8fa7e54aa9ae..f79403df4acb 100644 --- a/python/rest/gen/com/jetbrains/rest/lexer/_RestFlexLexer.java +++ b/python/rest/gen/com/jetbrains/rest/lexer/_RestFlexLexer.java @@ -1,4 +1,4 @@ -/* The following code was generated by JFlex 1.4.3 on 4/26/14 12:40 PM */ +/* The following code was generated by JFlex 1.4.3 on 8/25/14 1:56 PM */ package com.jetbrains.rest.lexer; @@ -11,8 +11,8 @@ import com.jetbrains.rest.RestTokenTypes; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 4/26/14 12:40 PM from the specification file - * /Users/ignatov/src/ultimate/tools/lexer/../../community/python/rest/src/com/jetbrains/rest/lexer/rest.flex + * on 8/25/14 1:56 PM from the specification file + * /home/ktisha/IDEA/tools/lexer/../../community/python/rest/src/com/jetbrains/rest/lexer/rest.flex */ public class _RestFlexLexer implements FlexLexer, RestTokenTypes { /** initial size of the lookahead buffer */ @@ -1293,7 +1293,7 @@ public class _RestFlexLexer implements FlexLexer, RestTokenTypes { "\1\232\21\42\1\0\1\33\1\0\1\42\1\33\1\42"+ "\7\0\1\164\1\0\1\165\1\33\4\0\1\33\6\0"+ "\4\42\1\233\22\42\1\0\1\33\1\0\1\42\1\33"+ - "\1\42\12\0\1\33\4\0\1\33\6\0\27\56\1\0"+ + "\1\42\12\0\1\33\4\0\1\56\6\0\27\56\1\0"+ "\1\234\1\0\1\56\1\33\1\56\12\0\1\33\4\0"+ "\1\33\1\235\1\0\1\236\3\0\27\237\1\0\1\33"+ "\1\0\1\237\1\33\1\240\1\241\2\0\1\242\1\243"+ diff --git a/python/rest/src/com/jetbrains/rest/lexer/rest.flex b/python/rest/src/com/jetbrains/rest/lexer/rest.flex index ee0b33108d4e..354779fcc48a 100644 --- a/python/rest/src/com/jetbrains/rest/lexer/rest.flex +++ b/python/rest/src/com/jetbrains/rest/lexer/rest.flex @@ -170,7 +170,7 @@ ANY= .|\n {USUAL_TYPES}"::" { yybegin(IN_VALUE); return DIRECTIVE;} {HIGHLIGHT_TYPES}"::" { yybegin(IN_HIGHLIGHT); return CUSTOM_DIRECTIVE;} [0-9A-Za-z\-:]*"::" { yybegin(IN_VALUE); return CUSTOM_DIRECTIVE;} -"|"[0-9A-Za-z]*"|" { return SUBSTITUTION;} +"|"[0-9A-Za-z_]*"|" { return SUBSTITUTION;} [0-9A-Za-z_\[|.]* { yybegin(IN_COMMENT); return COMMENT;} {CRLF}{2} { yybegin(INIT); return COMMENT;} {SPACE}*{CRLF}+ { return WHITESPACE; } diff --git a/python/rest/src/com/jetbrains/rest/parsing/RestParser.java b/python/rest/src/com/jetbrains/rest/parsing/RestParser.java index 791d94d02a75..1df9fc1eca0d 100644 --- a/python/rest/src/com/jetbrains/rest/parsing/RestParser.java +++ b/python/rest/src/com/jetbrains/rest/parsing/RestParser.java @@ -95,7 +95,7 @@ public class RestParser implements PsiParser { listMarker.drop(); } - private void parseMarkup(PsiBuilder builder) { + private static void parseMarkup(PsiBuilder builder) { PsiBuilder.Marker marker = builder.mark(); IElementType type = builder.getTokenType(); if (type == RestTokenTypes.SUBSTITUTION) { @@ -131,19 +131,19 @@ public class RestParser implements PsiParser { } } - private void gotoNextWhiteSpaces(PsiBuilder builder) { + private static void gotoNextWhiteSpaces(PsiBuilder builder) { while(!"\n".equals(builder.getTokenText()) && !(builder.getTokenType() == RestTokenTypes.TITLE) && !builder.eof() && (builder.getTokenType() != null)) { builder.advanceLexer(); } } - private void skipBlankLines(PsiBuilder builder) { + private static void skipBlankLines(PsiBuilder builder) { while("\n".equals(builder.getTokenText()) && !builder.eof() && (builder.getTokenType() != null)) { builder.advanceLexer(); } } - private void parseDirective(PsiBuilder builder, String white, PsiBuilder.Marker marker) { + private static void parseDirective(PsiBuilder builder, String white, PsiBuilder.Marker marker) { gotoNextWhiteSpaces(builder); if (builder.getTokenType() != RestTokenTypes.WHITESPACE) { builder.advanceLexer(); @@ -157,7 +157,6 @@ public class RestParser implements PsiParser { } else { marker.done(RestElementTypes.DIRECTIVE_BLOCK); - return; } } } diff --git a/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java b/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java index 55bc1e4c5446..913ed65f1e53 100644 --- a/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java +++ b/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java @@ -34,6 +34,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.QualifiedName; import com.intellij.util.Function; import com.jetbrains.python.PyNames; import com.jetbrains.python.codeInsight.PyCodeInsightSettings; @@ -44,13 +45,16 @@ import com.jetbrains.python.debugger.PySignatureCacheManager; import com.jetbrains.python.debugger.PySignatureUtil; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyBuiltinCache; -import com.intellij.psi.util.QualifiedName; import com.jetbrains.python.psi.resolve.QualifiedNameFinder; -import com.jetbrains.python.psi.types.*; +import com.jetbrains.python.psi.types.PyClassType; +import com.jetbrains.python.psi.types.PyType; +import com.jetbrains.python.psi.types.PyTypeParser; +import com.jetbrains.python.psi.types.TypeEvalContext; import com.jetbrains.python.toolbox.ChainIterable; import com.jetbrains.python.toolbox.FP; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.HeadMethod; +import org.apache.commons.httpclient.params.HttpConnectionManagerParams; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -414,8 +418,10 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i return true; } HttpClient client = new HttpClient(); - client.setTimeout(5 * 1000); - client.setConnectionTimeout(5 * 1000); + HttpConnectionManagerParams params = client.getHttpConnectionManager().getParams(); + params.setSoTimeout(5 * 1000); + params.setConnectionTimeout(5 * 1000); + try { HeadMethod method = new HeadMethod(url); int rc = client.executeMethod(method); @@ -618,9 +624,7 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i if (checkReturn) { RaiseVisitor visitor = new RaiseVisitor(); PyStatementList statementList = element.getStatementList(); - if (statementList != null) { - statementList.accept(visitor); - } + statementList.accept(visitor); if (visitor.myHasReturn) { builder.append(prefix).append("return:").append(offset); if (PyCodeInsightSettings.getInstance().INSERT_TYPE_DOCSTUB) { diff --git a/python/src/com/jetbrains/python/inspections/PyStatementEffectInspection.java b/python/src/com/jetbrains/python/inspections/PyStatementEffectInspection.java index 0cc7a4abd140..a521ed76d92f 100644 --- a/python/src/com/jetbrains/python/inspections/PyStatementEffectInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyStatementEffectInspection.java @@ -72,9 +72,6 @@ public class PyStatementEffectInspection extends PyInspection { final PyTryPart tryPart = PsiTreeUtil.getParentOfType(node, PyTryPart.class); if (tryPart != null) { final PyStatementList statementList = tryPart.getStatementList(); - if (statementList == null) { - return; - } if (statementList.getStatements().length == 1 && statementList.getStatements()[0] == node) { return; } diff --git a/python/src/com/jetbrains/python/inspections/quickfix/StatementEffectFunctionCallQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/StatementEffectFunctionCallQuickFix.java index 95daf466172e..d852fbc55c83 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/StatementEffectFunctionCallQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/StatementEffectFunctionCallQuickFix.java @@ -18,14 +18,12 @@ package com.jetbrains.python.inspections.quickfix; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiComment; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiWhiteSpace; import com.jetbrains.python.PyBundle; import com.jetbrains.python.PyNames; -import com.jetbrains.python.psi.LanguageLevel; -import com.jetbrains.python.psi.PyElementGenerator; -import com.jetbrains.python.psi.PyExpression; -import com.jetbrains.python.psi.PyReferenceExpression; +import com.jetbrains.python.psi.*; import org.jetbrains.annotations.NotNull; /** @@ -77,14 +75,23 @@ public class StatementEffectFunctionCallQuickFix implements LocalQuickFix { RemoveUnnecessaryBackslashQuickFix.removeBackSlash(next); if (whiteSpace != null) whiteSpace.delete(); + String commentText = null; if (next != null) { - final String text = next.getText(); + final PsiElement lastChild = next.getLastChild(); + if (lastChild instanceof PsiComment) { + commentText = lastChild.getText(); + } + final String text = next instanceof PyExpressionStatement ? ((PyExpressionStatement)next).getExpression().getText() : next.getText(); + stringBuilder.append(text); if (text.endsWith(",") && PyNames.PRINT.equals(expressionText)) stringBuilder.append(" end=' '"); next.delete(); } stringBuilder.append(")"); + if (commentText != null) { + stringBuilder.append(commentText); + } expression.replace(elementGenerator.createFromText(LanguageLevel.forElement(expression), PyExpression.class, stringBuilder.toString())); } diff --git a/python/src/com/jetbrains/python/module/PyContentEntriesEditor.java b/python/src/com/jetbrains/python/module/PyContentEntriesEditor.java new file mode 100644 index 000000000000..8ea8b26c0b5f --- /dev/null +++ b/python/src/com/jetbrains/python/module/PyContentEntriesEditor.java @@ -0,0 +1,367 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jetbrains.python.module; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.actionSystem.Presentation; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ContentEntry; +import com.intellij.openapi.roots.ContentFolder; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.impl.ContentEntryImpl; +import com.intellij.openapi.roots.impl.ContentFolderBaseImpl; +import com.intellij.openapi.roots.ui.configuration.*; +import com.intellij.openapi.roots.ui.configuration.actions.ContentEntryEditingAction; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.pointers.VirtualFilePointer; +import com.intellij.openapi.vfs.pointers.VirtualFilePointerListener; +import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager; +import com.intellij.ui.JBColor; +import com.intellij.util.EventDispatcher; +import com.intellij.util.containers.MultiMap; +import com.jetbrains.python.templateLanguages.TemplatesService; +import icons.PythonIcons; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.model.module.JpsModuleSourceRootType; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.tree.TreeCellRenderer; +import java.awt.*; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.List; + +public class PyContentEntriesEditor extends CommonContentEntriesEditor { + private static final Color TEMPLATES_COLOR = JBColor.MAGENTA; + private final MultiMap myTemplateRoots = new MultiMap(); + private final Module myModule; + private Disposable myFilePointersDisposable; + + private final VirtualFilePointerListener DUMMY_LISTENER = new VirtualFilePointerListener() { + @Override + public void beforeValidityChanged(@NotNull VirtualFilePointer[] pointers) { + } + + @Override + public void validityChanged(@NotNull VirtualFilePointer[] pointers) { + } + }; + + public PyContentEntriesEditor(Module module, ModuleConfigurationState moduleConfigurationState, + JpsModuleSourceRootType... rootTypes) { + super(module.getName(), moduleConfigurationState, rootTypes); + myModule = module; + reset(); + } + + @Override + protected ContentEntryTreeEditor createContentEntryTreeEditor(Project project) { + return new MyContentEntryTreeEditor(project, getEditHandlers()); + } + + @Override + protected List addContentEntries(VirtualFile[] files) { + List entries = super.addContentEntries(files); + addContentEntryPanels(entries.toArray(new ContentEntry[entries.size()])); + return entries; + } + + @Override + public void reset() { + if (myFilePointersDisposable != null) { + Disposer.dispose(myFilePointersDisposable); + } + myTemplateRoots.clear(); + + myFilePointersDisposable = Disposer.newDisposable(); + final TemplatesService instance = TemplatesService.getInstance(myModule); + if (instance != null) { + final List folders = instance.getTemplateFolders(); + for (VirtualFile folder : folders) { + ContentEntry contentEntry = findContentEntryForFile(folder); + if (contentEntry != null) { + myTemplateRoots.putValue(contentEntry, VirtualFilePointerManager.getInstance().create(folder, myFilePointersDisposable, + DUMMY_LISTENER)); + } + } + } + + if (myRootTreeEditor != null) { + ContentEntryEditor editor = myRootTreeEditor.getContentEntryEditor(); + if(editor!=null) editor.update(); + myRootTreeEditor.update(); + } + } + + @Nullable + private ContentEntry findContentEntryForFile(VirtualFile virtualFile) { + for (ContentEntry contentEntry : getModel().getContentEntries()) { + final VirtualFile file = contentEntry.getFile(); + if (file != null && VfsUtilCore.isAncestor(file, virtualFile, false)) { + return contentEntry; + } + } + return null; + } + + @Override + public void disposeUIResources() { + super.disposeUIResources(); + if (myFilePointersDisposable != null) { + Disposer.dispose(myFilePointersDisposable); + } + } + + @Override + public void apply() throws ConfigurationException { + super.apply(); + List templateRoots = getCurrentState(); + TemplatesService.getInstance(myModule).setTemplateFolders(templateRoots.toArray(new VirtualFile[templateRoots.size()])); + } + + private List getCurrentState() { + List result = new ArrayList(); + for (ContentEntry entry : myTemplateRoots.keySet()) { + for (VirtualFilePointer filePointer : myTemplateRoots.get(entry)) { + result.add(filePointer.getFile()); + } + } + return result; + } + + @Override + public boolean isModified() { + if (super.isModified()) return true; + final TemplatesService templatesService = TemplatesService.getInstance(myModule); + if (templatesService != null) { + List original = templatesService.getTemplateFolders(); + List current = getCurrentState(); + + if (!Comparing.haveEqualElements(original, current)) return true; + + } + return false; + } + + @Override + protected MyContentEntryEditor createContentEntryEditor(String contentEntryUrl) { + return new MyContentEntryEditor(contentEntryUrl, getEditHandlers()); + } + + protected class MyContentEntryEditor extends ContentEntryEditor { + private final EventDispatcher myEventDispatcher = EventDispatcher.create(ChangeListener.class); + + public MyContentEntryEditor(String contentEntryUrl, List> handlers) { + super(contentEntryUrl, handlers); + } + + @Override + protected ModifiableRootModel getModel() { + return PyContentEntriesEditor.this.getModel(); + } + + public void addListener(ChangeListener changeListener) { + myEventDispatcher.addListener(changeListener); + } + + public void removeListener(ChangeListener changeListener) { + myEventDispatcher.removeListener(changeListener); + } + + @Override + protected ContentRootPanel createContentRootPane() { + return new MyContentRootPanel(); + } + + @Override + public void deleteContentFolder(ContentEntry contentEntry, ContentFolder folder) { + if (folder instanceof TemplateRootFolder) { + final VirtualFile file = folder.getFile(); + if (file != null) { + removeTemplateRoot(file); + } + } + else { + super.deleteContentFolder(contentEntry, folder); + } + } + + public void addTemplateRoot(@NotNull final VirtualFile file) { + final VirtualFilePointer root = VirtualFilePointerManager.getInstance().create(file, myFilePointersDisposable, DUMMY_LISTENER); + myTemplateRoots.putValue(getContentEntry(), root); + myEventDispatcher.getMulticaster().stateChanged(new ChangeEvent(this)); + update(); + } + + public void removeTemplateRoot(@NotNull final VirtualFile file) { + final VirtualFilePointer root = getTemplateRoot(file); + if (root != null) { + myTemplateRoots.remove(getContentEntry(), root); + myEventDispatcher.getMulticaster().stateChanged(new ChangeEvent(this)); + update(); + } + } + + public boolean hasTemplateRoot(@NotNull final VirtualFile file) { + return getTemplateRoot(file) != null; + } + + @Nullable + public VirtualFilePointer getTemplateRoot(@NotNull final VirtualFile file) { + for (VirtualFilePointer filePointer : myTemplateRoots.get(getContentEntry())) { + if (Comparing.equal(filePointer.getFile(), file)) { + return filePointer; + } + } + return null; + } + + protected class MyContentRootPanel extends ContentRootPanel { + public MyContentRootPanel() { + super(MyContentEntryEditor.this, getEditHandlers()); + } + + @Override + @NotNull + protected ContentEntryImpl getContentEntry() { + //noinspection ConstantConditions + return (ContentEntryImpl)MyContentEntryEditor.this.getContentEntry(); + } + + @Override + protected void addFolderGroupComponents() { + super.addFolderGroupComponents(); + if (!myTemplateRoots.get(getContentEntry()).isEmpty()) { + final List folders = new ArrayList(myTemplateRoots.size()); + for (VirtualFilePointer root : myTemplateRoots.get(getContentEntry())) { + folders.add(new TemplateRootFolder(root, getContentEntry())); + } + final JComponent sourcesComponent = createFolderGroupComponent("Template Folders", + folders.toArray(new ContentFolder[folders.size()]), + TEMPLATES_COLOR, null); + this.add(sourcesComponent, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, + GridBagConstraints.HORIZONTAL, new Insets(0, 0, 10, 0), 0, 0)); + } + } + } + } + + private static class MyContentEntryTreeEditor extends ContentEntryTreeEditor { + + private final ChangeListener myListener = new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + update(); + } + }; + + public MyContentEntryTreeEditor(Project project, List> handlers) { + super(project, handlers); + } + + @Override + public void setContentEntryEditor(ContentEntryEditor newEditor) { + PyContentEntriesEditor.MyContentEntryEditor existingEditor = getContentEntryEditor(); + if (Comparing.equal(existingEditor, newEditor)) { + return; + } + if (existingEditor != null) { + existingEditor.removeListener(myListener); + } + if (newEditor != null) { + ((PyContentEntriesEditor.MyContentEntryEditor)newEditor).addListener(myListener); + } + super.setContentEntryEditor(newEditor); + } + + @Override + public PyContentEntriesEditor.MyContentEntryEditor getContentEntryEditor() { + return (PyContentEntriesEditor.MyContentEntryEditor)super.getContentEntryEditor(); + } + + @Override + protected void createEditingActions() { + super.createEditingActions(); + + ContentEntryEditingAction a = new ContentEntryEditingAction(myTree) { + { + final Presentation templatePresentation = getTemplatePresentation(); + templatePresentation.setText("Templates"); + templatePresentation.setDescription("Template Folders"); + templatePresentation.setIcon(PythonIcons.Python.TemplateRoot); + } + + @Override + public boolean isSelected(AnActionEvent e) { + final VirtualFile[] selectedFiles = getSelectedFiles(); + return selectedFiles.length != 0 && getContentEntryEditor().hasTemplateRoot(selectedFiles[0]); + } + + @Override + public void setSelected(AnActionEvent e, boolean isSelected) { + final VirtualFile[] selectedFiles = getSelectedFiles(); + assert selectedFiles.length != 0; + + for (VirtualFile selectedFile : selectedFiles) { + boolean wasSelected = getContentEntryEditor().hasTemplateRoot(selectedFile); + if (isSelected) { + if (!wasSelected) { + getContentEntryEditor().addTemplateRoot(selectedFile); + } + } + else { + if (wasSelected) { + getContentEntryEditor().removeTemplateRoot(selectedFile); + } + } + } + } + }; + myEditingActionsGroup.add(a); + a.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.ALT_MASK)), myTree); + } + + @Override + protected TreeCellRenderer getContentEntryCellRenderer() { + return new ContentEntryTreeCellRenderer(this, getEditHandlers()) { + @Override + protected Icon updateIcon(final ContentEntry entry, final VirtualFile file, final Icon originalIcon) { + if (getContentEntryEditor().hasTemplateRoot(file)) { + return PythonIcons.Python.TemplateRoot; + } + return super.updateIcon(entry, file, originalIcon); + } + }; + } + } + private static class TemplateRootFolder extends ContentFolderBaseImpl { + protected TemplateRootFolder(@NotNull VirtualFilePointer filePointer, @NotNull ContentEntryImpl contentEntry) { + super(filePointer, contentEntry); + } + } + +} diff --git a/python/src/com/jetbrains/python/sdk/flavors/WinPythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/WinPythonSdkFlavor.java index 273f4b09a717..9d22af8c03bf 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/WinPythonSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/WinPythonSdkFlavor.java @@ -34,6 +34,7 @@ public class WinPythonSdkFlavor extends CPythonSdkFlavor { public static WinPythonSdkFlavor INSTANCE = new WinPythonSdkFlavor(); private static Map ourRegistryMap = ImmutableMap.of("HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore", "python.exe", + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Python\\PythonCore", "python.exe", "HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython", "ipy.exe"); private WinPythonSdkFlavor() { diff --git a/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java b/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java index f48af7ff0e73..9be15944f37e 100644 --- a/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java +++ b/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java @@ -295,7 +295,7 @@ public abstract class CompatibilityVisitor extends PyAnnotator { } } commonRegisterProblem(message, " not support this syntax. Raise with no arguments can only be used in an except block", - len, node, null); + len, node, null, false); // raise 1, 2, 3 len = 0; message = new StringBuilder(myCommonMessage); diff --git a/python/testData/highlighting/unsupportedFeaturesInPython3.py b/python/testData/highlighting/unsupportedFeaturesInPython3.py index fce5f970f8ef..5a4f399b3f62 100644 --- a/python/testData/highlighting/unsupportedFeaturesInPython3.py +++ b/python/testData/highlighting/unsupportedFeaturesInPython3.py @@ -18,7 +18,7 @@ try: import __builtin__ -raise +raise try: pass diff --git a/python/testData/inspections/ReplacePrintComment.py b/python/testData/inspections/ReplacePrintComment.py new file mode 100644 index 000000000000..1cf3778b69b1 --- /dev/null +++ b/python/testData/inspections/ReplacePrintComment.py @@ -0,0 +1 @@ +print '%s %s %s %s' % bar # <- doesn't work either \ No newline at end of file diff --git a/python/testData/inspections/ReplacePrintComment_after.py b/python/testData/inspections/ReplacePrintComment_after.py new file mode 100644 index 000000000000..416deb8fd16e --- /dev/null +++ b/python/testData/inspections/ReplacePrintComment_after.py @@ -0,0 +1 @@ +print('%s %s %s %s' % bar) # <- doesn't work either diff --git a/python/testData/inspections/ReplacePrintEnd.py b/python/testData/inspections/ReplacePrintEnd.py new file mode 100644 index 000000000000..afc37fbe2840 --- /dev/null +++ b/python/testData/inspections/ReplacePrintEnd.py @@ -0,0 +1 @@ +print var, \ No newline at end of file diff --git a/python/testData/inspections/ReplacePrintEnd_after.py b/python/testData/inspections/ReplacePrintEnd_after.py new file mode 100644 index 000000000000..bae6b0c068a7 --- /dev/null +++ b/python/testData/inspections/ReplacePrintEnd_after.py @@ -0,0 +1 @@ +print(var, end=' ') diff --git a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java index c36372d9ba64..68387a2c9c2f 100644 --- a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java +++ b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java @@ -251,6 +251,23 @@ public class PyQuickFixTest extends PyTestCase { PyBundle.message("QFIX.statement.effect.introduce.variable"), true, true); } + public void testReplacePrintEnd() { + runWithLanguageLevel(LanguageLevel.PYTHON34, new Runnable() { + @Override + public void run() { + doInspectionTest("ReplacePrintEnd.py", PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect"), true, true); + }}); + } + + public void testReplacePrintComment() { + runWithLanguageLevel(LanguageLevel.PYTHON34, new Runnable() { + @Override + public void run() { + doInspectionTest("ReplacePrintComment.py", PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect"), true, + true); + }}); + } + public void testUnresolvedWith() { // PY-2083 setLanguageLevel(LanguageLevel.PYTHON25); doInspectionTest("UnresolvedWith.py", PyUnresolvedReferencesInspection.class, diff --git a/xml/impl/src/com/intellij/ide/browsers/JavaScriptDebuggerStarter.java b/xml/impl/src/com/intellij/ide/browsers/JavaScriptDebuggerStarter.java index cbc8cb111557..71dbb0c0dd71 100644 --- a/xml/impl/src/com/intellij/ide/browsers/JavaScriptDebuggerStarter.java +++ b/xml/impl/src/com/intellij/ide/browsers/JavaScriptDebuggerStarter.java @@ -12,8 +12,7 @@ import org.jetbrains.annotations.Nullable; public interface JavaScriptDebuggerStarter { boolean isApplicable(@NotNull RunConfiguration runConfiguration); - // todo we must pass browser family, otherwise result could be unexpected (by default Chrome will be used, but user can prefer Firefox) - void start(@NotNull String url, @NotNull RC runConfiguration, @NotNull U userData); + void start(@NotNull String url, @NotNull RC runConfiguration, @NotNull U userData, @Nullable WebBrowser browser); final class Util { static final ExtensionPointName EP_NAME = ExtensionPointName.create("org.jetbrains.javaScriptDebuggerStarter"); @@ -31,11 +30,15 @@ public interface JavaScriptDebuggerStarter { } public static boolean start(@NotNull RC runConfiguration, @NotNull String url) { + return start(runConfiguration, url, null); + } + + public static boolean start(@NotNull RC runConfiguration, @NotNull String url, @Nullable WebBrowser browser) { JavaScriptDebuggerStarter starter = get(runConfiguration); if (starter == null) { return false; } - starter.start(url, runConfiguration, NULL_OBJECT); + starter.start(url, runConfiguration, NULL_OBJECT, browser); return true; } @@ -49,9 +52,13 @@ public interface JavaScriptDebuggerStarter { @NotNull String url, @Nullable WebBrowser browser, boolean startDebugger) { - if (!startDebugger || !start(runConfiguration, url)) { + if (!startDebugger || !start(runConfiguration, url, browser)) { BrowserLauncher.getInstance().browse(url, browser, runConfiguration.getProject()); } } + + public static boolean hasStarters() { + return EP_NAME.getExtensions().length > 0; + } } } diff --git a/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java b/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java index e6bd32729b13..b634fd2fc8b1 100644 --- a/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java +++ b/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java @@ -40,15 +40,15 @@ public final class OpenUrlHyperlinkInfo implements HyperlinkWithPopupMenuInfo { this(url, Conditions.alwaysTrue(), null); } - public OpenUrlHyperlinkInfo(@NotNull String url, @Nullable WebBrowser browser) { - this(url, null, browser); + public OpenUrlHyperlinkInfo(@NotNull String url, @Nullable final WebBrowser browser) { + this(url, browser == null ? Conditions.alwaysTrue() : Conditions.is(browser)); } public OpenUrlHyperlinkInfo(@NotNull String url, @NotNull Condition browserCondition) { this(url, browserCondition, null); } - private OpenUrlHyperlinkInfo(@NotNull String url, @Nullable Condition browserCondition, @Nullable WebBrowser browser) { + private OpenUrlHyperlinkInfo(@NotNull String url, @NotNull Condition browserCondition, @Nullable WebBrowser browser) { this.url = url; this.browserCondition = browserCondition; this.browser = browser; @@ -58,7 +58,7 @@ public final class OpenUrlHyperlinkInfo implements HyperlinkWithPopupMenuInfo { public ActionGroup getPopupMenuGroup(@NotNull MouseEvent event) { DefaultActionGroup group = new DefaultActionGroup(); for (final WebBrowser browser : WebBrowserManager.getInstance().getActiveBrowsers()) { - if (browserCondition == null ? (this.browser == null || browser.equals(this.browser)) : browserCondition.value(browser)) { + if (browserCondition.value(browser)) { group.add(new AnAction("Open in " + browser.getName(), "Open URL in " + browser.getName(), browser.getIcon()) { @Override public void actionPerformed(AnActionEvent e) { diff --git a/xml/impl/src/com/intellij/ide/browsers/StartBrowserPanel.java b/xml/impl/src/com/intellij/ide/browsers/StartBrowserPanel.java index 603746bb3c60..a0faad5a0eb5 100644 --- a/xml/impl/src/com/intellij/ide/browsers/StartBrowserPanel.java +++ b/xml/impl/src/com/intellij/ide/browsers/StartBrowserPanel.java @@ -59,7 +59,7 @@ public class StartBrowserPanel { private JPanel myRoot; public StartBrowserPanel() { - myStartJavaScriptDebuggerCheckBox.setVisible(JavaScriptDebuggerStarter.Util.EP_NAME.getExtensions().length > 0); + myStartJavaScriptDebuggerCheckBox.setVisible(JavaScriptDebuggerStarter.Util.hasStarters()); myRoot.addAncestorListener(new AncestorListenerAdapter() { @Override public void ancestorAdded(AncestorEvent event) {