mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
+2
-1
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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'
|
||||
|
||||
+6
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+11
@@ -856,6 +856,17 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
}
|
||||
}
|
||||
}
|
||||
if (targetElement == null) {
|
||||
for (Language language : Language.getRegisteredLanguages()) {
|
||||
DocumentationProvider documentationProvider = LanguageDocumentation.INSTANCE.forLanguage(language);
|
||||
if (documentationProvider != null) {
|
||||
targetElement = documentationProvider.getDocumentationElementForLink(manager, refText, psiElement);
|
||||
if (targetElement != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (targetElement != null) {
|
||||
fetchDocInfo(getDefaultCollector(targetElement, null), component);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.intellij.lang.parameterInfo.ParameterInfoUIContextEx;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.ui.Gray;
|
||||
import com.intellij.ui.JBColor;
|
||||
@@ -296,47 +295,50 @@ public class ParameterInfoComponent extends JPanel {
|
||||
public String setup(final String[] texts, final EnumSet<ParameterInfoUIContextEx.Flag>[] 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<OneLineComponent> components = new ArrayList<OneLineComponent>();
|
||||
|
||||
Map<TextRange, ParameterInfoUIContextEx.Flag> flagsMap = new TreeMap<TextRange, ParameterInfoUIContextEx.Flag>(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<ParameterInfoUIContextEx.Flag> 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<JComponent> components = new ArrayList<JComponent>();
|
||||
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) {
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
+2
-1
@@ -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")));
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+1
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public class Conditions {
|
||||
public static <T> Condition<T> is(final T option) {
|
||||
return new Condition<T>() {
|
||||
public boolean value(T t) {
|
||||
return t == option;
|
||||
return Comparing.equal(t, option);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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("</a>")
|
||||
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 = {}
|
||||
|
||||
+6
-347
@@ -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<ModuleSourceRootEditHandler<?>> 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<ContentEntry, VirtualFilePointer> myTemplateRoots = new MultiMap<ContentEntry, VirtualFilePointer>();
|
||||
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<ContentEntry> addContentEntries(VirtualFile[] files) {
|
||||
List<ContentEntry> 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<VirtualFile> 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<VirtualFile> templateRoots = getCurrentState();
|
||||
TemplatesService.getInstance(myModule).setTemplateFolders(templateRoots.toArray(new VirtualFile[templateRoots.size()]));
|
||||
}
|
||||
|
||||
private List<VirtualFile> getCurrentState() {
|
||||
List<VirtualFile> result = new ArrayList<VirtualFile>();
|
||||
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<VirtualFile> original = templatesService.getTemplateFolders();
|
||||
List<VirtualFile> 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<ChangeListener> myEventDispatcher = EventDispatcher.create(ChangeListener.class);
|
||||
|
||||
public MyContentEntryEditor(String contentEntryUrl, List<ModuleSourceRootEditHandler<?>> 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<TemplateRootFolder> folders = new ArrayList<TemplateRootFolder>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-8
@@ -61,6 +61,7 @@ import java.util.List;
|
||||
abstract public class AbstractProjectSettingsStep extends AbstractActionWithPanel implements DumbAware {
|
||||
protected final DirectoryProjectGenerator myProjectGenerator;
|
||||
private final NullableConsumer<AbstractProjectSettingsStep> 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<AbstractProjectSettingsStep> callback) {
|
||||
public AbstractProjectSettingsStep(DirectoryProjectGenerator projectGenerator,
|
||||
NullableConsumer<AbstractProjectSettingsStep> 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);
|
||||
|
||||
+2
-2
@@ -27,11 +27,11 @@ import java.util.List;
|
||||
public class PluginSpecificProjectsStep extends DefaultActionGroup implements DumbAware {
|
||||
|
||||
public PluginSpecificProjectsStep(@NotNull final NullableConsumer<AbstractProjectSettingsStep> callback,
|
||||
@NotNull final List<DirectoryProjectGenerator> projectGenerators) {
|
||||
@NotNull final List<DirectoryProjectGenerator> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,16 +28,16 @@ public class ProjectSpecificAction extends DefaultActionGroup implements DumbAwa
|
||||
private final ProjectSpecificSettingsStep mySettings;
|
||||
|
||||
public ProjectSpecificAction(@NotNull final NullableConsumer<AbstractProjectSettingsStep> 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<AbstractProjectSettingsStep> 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);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -31,8 +31,8 @@ import javax.swing.*;
|
||||
public class ProjectSpecificSettingsStep extends AbstractProjectSettingsStep implements DumbAware {
|
||||
|
||||
public ProjectSpecificSettingsStep(@NotNull final DirectoryProjectGenerator projectGenerator,
|
||||
@NotNull final NullableConsumer<AbstractProjectSettingsStep> callback) {
|
||||
super(projectGenerator, callback);
|
||||
@NotNull final NullableConsumer<AbstractProjectSettingsStep> callback, boolean isWelcomeScreen) {
|
||||
super(projectGenerator, callback, isWelcomeScreen);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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<AbstractProjectSettingsStep> 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<DirectoryProjectGenerator> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-5
@@ -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<ModuleConfigurationEditor> editors = new ArrayList<ModuleConfigurationEditor>();
|
||||
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()]);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
* <a href="http://www.jflex.de/">JFlex</a> 1.4.3
|
||||
* on 4/26/14 12:40 PM from the specification file
|
||||
* <tt>/Users/ignatov/src/ultimate/tools/lexer/../../community/python/rest/src/com/jetbrains/rest/lexer/rest.flex</tt>
|
||||
* on 8/25/14 1:56 PM from the specification file
|
||||
* <tt>/home/ktisha/IDEA/tools/lexer/../../community/python/rest/src/com/jetbrains/rest/lexer/rest.flex</tt>
|
||||
*/
|
||||
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"+
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+12
-5
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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<ContentEntry, VirtualFilePointer> myTemplateRoots = new MultiMap<ContentEntry, VirtualFilePointer>();
|
||||
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<ContentEntry> addContentEntries(VirtualFile[] files) {
|
||||
List<ContentEntry> 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<VirtualFile> 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<VirtualFile> templateRoots = getCurrentState();
|
||||
TemplatesService.getInstance(myModule).setTemplateFolders(templateRoots.toArray(new VirtualFile[templateRoots.size()]));
|
||||
}
|
||||
|
||||
private List<VirtualFile> getCurrentState() {
|
||||
List<VirtualFile> result = new ArrayList<VirtualFile>();
|
||||
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<VirtualFile> original = templatesService.getTemplateFolders();
|
||||
List<VirtualFile> 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<ChangeListener> myEventDispatcher = EventDispatcher.create(ChangeListener.class);
|
||||
|
||||
public MyContentEntryEditor(String contentEntryUrl, List<ModuleSourceRootEditHandler<?>> 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<TemplateRootFolder> folders = new ArrayList<TemplateRootFolder>(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<ModuleSourceRootEditHandler<?>> 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,6 +34,7 @@ public class WinPythonSdkFlavor extends CPythonSdkFlavor {
|
||||
public static WinPythonSdkFlavor INSTANCE = new WinPythonSdkFlavor();
|
||||
private static Map<String, String> 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() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -18,7 +18,7 @@ try:
|
||||
|
||||
<error descr="Python version 3.0 does not have module __builtin__">import __builtin__</error>
|
||||
|
||||
<error descr="Python version 3.0 does not support this syntax. Raise with no arguments can only be used in an except block">raise</error>
|
||||
<warning descr="Python version 3.0 does not support this syntax. Raise with no arguments can only be used in an except block">raise</warning>
|
||||
|
||||
try:
|
||||
pass
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<warning descr="Statement seems to have no effect and can be replaced with function call to have effect">print</warning><error descr="End of statement expected"> </error><warning descr="Statement seems to have no effect">'%s %s %s %s' % bar</warning> # <- doesn't work either
|
||||
@@ -0,0 +1 @@
|
||||
print('%s %s %s %s' % bar) # <- doesn't work either
|
||||
@@ -0,0 +1 @@
|
||||
<warning descr="Statement seems to have no effect and can be replaced with function call to have effect">print</warning><error descr="End of statement expected"> </error><warning descr="Statement seems to have no effect">var,</warning>
|
||||
@@ -0,0 +1 @@
|
||||
print(var, end=' ')
|
||||
@@ -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,
|
||||
|
||||
@@ -12,8 +12,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public interface JavaScriptDebuggerStarter<RC extends RunConfiguration, U> {
|
||||
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<JavaScriptDebuggerStarter> EP_NAME = ExtensionPointName.create("org.jetbrains.javaScriptDebuggerStarter");
|
||||
@@ -31,11 +30,15 @@ public interface JavaScriptDebuggerStarter<RC extends RunConfiguration, U> {
|
||||
}
|
||||
|
||||
public static <RC extends RunConfiguration> boolean start(@NotNull RC runConfiguration, @NotNull String url) {
|
||||
return start(runConfiguration, url, null);
|
||||
}
|
||||
|
||||
public static <RC extends RunConfiguration> boolean start(@NotNull RC runConfiguration, @NotNull String url, @Nullable WebBrowser browser) {
|
||||
JavaScriptDebuggerStarter<RC, Object> 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<RC extends RunConfiguration, U> {
|
||||
@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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,15 +40,15 @@ public final class OpenUrlHyperlinkInfo implements HyperlinkWithPopupMenuInfo {
|
||||
this(url, Conditions.<WebBrowser>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.<WebBrowser>alwaysTrue() : Conditions.is(browser));
|
||||
}
|
||||
|
||||
public OpenUrlHyperlinkInfo(@NotNull String url, @NotNull Condition<WebBrowser> browserCondition) {
|
||||
this(url, browserCondition, null);
|
||||
}
|
||||
|
||||
private OpenUrlHyperlinkInfo(@NotNull String url, @Nullable Condition<WebBrowser> browserCondition, @Nullable WebBrowser browser) {
|
||||
private OpenUrlHyperlinkInfo(@NotNull String url, @NotNull Condition<WebBrowser> 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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user