From 810fe5236e63ceea48f2f54fbff96f7fe941ac66 Mon Sep 17 00:00:00 2001 From: fitermay Date: Thu, 28 Jul 2016 19:18:29 -0400 Subject: [PATCH 01/63] --do not pass empty format to getArrayItems --- .../debugger/containerview/NumericContainerViewTable.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/debugger/containerview/NumericContainerViewTable.java b/python/src/com/jetbrains/python/debugger/containerview/NumericContainerViewTable.java index 2a3c75df8aa0..9078a99f6fb2 100644 --- a/python/src/com/jetbrains/python/debugger/containerview/NumericContainerViewTable.java +++ b/python/src/com/jetbrains/python/debugger/containerview/NumericContainerViewTable.java @@ -227,7 +227,8 @@ public abstract class NumericContainerViewTable implements TableChunkDatasource myValue.isErrorOnEval(), myValue.isReturnedVal(), myValue.getParent(), myValue.getFrameAccessor()); - return myValue.getFrameAccessor().getArrayItems(slicedValue, rowOffset, colOffset, rows, cols, getFormat()); + final String format = getFormat().isEmpty() ? "%" : getFormat(); + return myValue.getFrameAccessor().getArrayItems(slicedValue, rowOffset, colOffset, rows, cols, format); } public abstract boolean isNumeric(); From 6493fa0a2d978cab16c9fe3960f1840347ca96f6 Mon Sep 17 00:00:00 2001 From: fitermay Date: Thu, 28 Jul 2016 19:26:45 -0400 Subject: [PATCH 02/63] --do not use PyDebuggerException for flow control (makes it very difficult to debug) --- .../python/debugger/pydev/ProtocolParser.java | 37 +++++-------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProtocolParser.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProtocolParser.java index 533e8c96bc36..a0d22151dfc0 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProtocolParser.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProtocolParser.java @@ -5,6 +5,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.jetbrains.python.debugger.*; import com.thoughtworks.xstream.io.naming.NoNameCoder; import com.thoughtworks.xstream.io.xml.XppReader; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.xmlpull.mxp1.MXParser; @@ -383,33 +384,14 @@ public class ProtocolParser { } private static String readString(final XppReader reader, final String name, final String fallback) throws PyDebuggerException { - final String value; - try { - value = read(reader, name); - } - catch (PyDebuggerException e) { - if (fallback != null) { - return fallback; - } - else { - throw e; - } - } - return decode(value); + final String value = read(reader, name, fallback == null); + return value == null ? fallback : value; } private static int readInt(final XppReader reader, final String name, final Integer fallback) throws PyDebuggerException { - final String value; - try { - value = read(reader, name); - } - catch (PyDebuggerException e) { - if (fallback != null) { - return fallback; - } - else { - throw e; - } + final String value = read(reader, name, fallback == null); + if (value == null) { + return fallback; } try { return Integer.parseInt(value); @@ -419,11 +401,12 @@ public class ProtocolParser { } } - private static String read(final XppReader reader, final String name) throws PyDebuggerException { + @Contract("_, _, true -> !null") + private static String read(final XppReader reader, final String name, boolean isRequired) throws PyDebuggerException { final String value = reader.getAttribute(name); - if (value == null) { + if (value == null && isRequired) { throw new PyDebuggerException("Attribute not found: " + name); } - return value; + return value == null ? null : decode(value); } } From 9e1240a0f2e8be3815b0f536a0d39aa68be8168f Mon Sep 17 00:00:00 2001 From: fitermay Date: Fri, 19 Aug 2016 00:07:17 -0400 Subject: [PATCH 03/63] Fix PY-20332: Fix code that causes constant revalidation during repaint --- .../python/debugger/array/JBTableWithRowHeaders.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/python/src/com/jetbrains/python/debugger/array/JBTableWithRowHeaders.java b/python/src/com/jetbrains/python/debugger/array/JBTableWithRowHeaders.java index b204cd569604..511d82fd4ca1 100644 --- a/python/src/com/jetbrains/python/debugger/array/JBTableWithRowHeaders.java +++ b/python/src/com/jetbrains/python/debugger/array/JBTableWithRowHeaders.java @@ -15,6 +15,7 @@ */ package com.jetbrains.python.debugger.array; +import com.google.common.base.Strings; import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.table.JBTable; import org.jetbrains.annotations.NotNull; @@ -87,7 +88,9 @@ public class JBTableWithRowHeaders extends JBTable { @Override protected void paintComponent(@NotNull Graphics g) { - getEmptyText().setText(""); + if (!Strings.isNullOrEmpty(getEmptyText().getText())) { + getEmptyText().setText(""); + } super.paintComponent(g); } @@ -105,7 +108,10 @@ public class JBTableWithRowHeaders extends JBTable { @Override public int getRowHeight(int row) { - setRowHeight(myMainTable.getRowHeight()); + int height = super.getRowHeight(); + if (height != myMainTable.getRowHeight()) { + setRowHeight(myMainTable.getRowHeight()); + } return super.getRowHeight(row); } From c7fc19c3a1487c3a161fa694a328f7a1b47b2dd8 Mon Sep 17 00:00:00 2001 From: fitermay Date: Fri, 19 Aug 2016 00:22:27 -0400 Subject: [PATCH 04/63] --Fix PY-20251: Remember the previous renderer state --- .../python/debugger/array/ArrayTableCellRenderer.java | 5 +++++ .../python/debugger/containerview/ColoredCellRenderer.java | 2 ++ .../debugger/containerview/NumericContainerViewTable.java | 3 +++ .../debugger/dataframe/DataFrameTableCellRenderer.java | 5 +++++ 4 files changed, 15 insertions(+) diff --git a/python/src/com/jetbrains/python/debugger/array/ArrayTableCellRenderer.java b/python/src/com/jetbrains/python/debugger/array/ArrayTableCellRenderer.java index 046af042c57f..379902756851 100644 --- a/python/src/com/jetbrains/python/debugger/array/ArrayTableCellRenderer.java +++ b/python/src/com/jetbrains/python/debugger/array/ArrayTableCellRenderer.java @@ -50,6 +50,11 @@ class ArrayTableCellRenderer extends DefaultTableCellRenderer implements Colored myColored = colored; } + @Override + public boolean getColored() { + return myColored; + } + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) { super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col); diff --git a/python/src/com/jetbrains/python/debugger/containerview/ColoredCellRenderer.java b/python/src/com/jetbrains/python/debugger/containerview/ColoredCellRenderer.java index c26de6c87141..9ce0471c3706 100644 --- a/python/src/com/jetbrains/python/debugger/containerview/ColoredCellRenderer.java +++ b/python/src/com/jetbrains/python/debugger/containerview/ColoredCellRenderer.java @@ -22,4 +22,6 @@ import javax.swing.table.TableCellRenderer; */ public interface ColoredCellRenderer extends TableCellRenderer { void setColored(boolean colored); + + boolean getColored(); } diff --git a/python/src/com/jetbrains/python/debugger/containerview/NumericContainerViewTable.java b/python/src/com/jetbrains/python/debugger/containerview/NumericContainerViewTable.java index 9078a99f6fb2..263b69daf670 100644 --- a/python/src/com/jetbrains/python/debugger/containerview/NumericContainerViewTable.java +++ b/python/src/com/jetbrains/python/debugger/containerview/NumericContainerViewTable.java @@ -82,12 +82,15 @@ public abstract class NumericContainerViewTable implements TableChunkDatasource myComponent.getSliceTextField().setText(chunk.getSlicePresentation()); myComponent.getFormatTextField().setText(chunk.getFormat()); myDialog.setTitle(getTitlePresentation(chunk.getSlicePresentation())); + boolean shouldSetColored = myTableCellRenderer == null || myTableCellRenderer.getColored(); myTableCellRenderer = createCellRenderer(Double.MIN_VALUE, Double.MIN_VALUE, chunk); if (!isNumeric()) { disableColor(); } else { myComponent.getColoredCheckbox().setEnabled(true); + myComponent.getColoredCheckbox().setSelected(shouldSetColored); + myTableCellRenderer.setColored(shouldSetColored); } if (!inPlace) { diff --git a/python/src/com/jetbrains/python/debugger/dataframe/DataFrameTableCellRenderer.java b/python/src/com/jetbrains/python/debugger/dataframe/DataFrameTableCellRenderer.java index 76946ce79e43..72eec940f578 100644 --- a/python/src/com/jetbrains/python/debugger/dataframe/DataFrameTableCellRenderer.java +++ b/python/src/com/jetbrains/python/debugger/dataframe/DataFrameTableCellRenderer.java @@ -41,6 +41,11 @@ class DataFrameTableCellRenderer extends DefaultTableCellRenderer implements Col myColored = colored; } + @Override + public boolean getColored() { + return myColored; + } + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) { super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col); From a7a51e1aee70f659ce01b0b243dd2c1566c1d2c3 Mon Sep 17 00:00:00 2001 From: fitermay Date: Fri, 19 Aug 2016 00:26:25 -0400 Subject: [PATCH 05/63] Fix PY-20468 --- .../debugger/containerview/PyViewNumericContainerAction.java | 1 + 1 file changed, 1 insertion(+) diff --git a/python/src/com/jetbrains/python/debugger/containerview/PyViewNumericContainerAction.java b/python/src/com/jetbrains/python/debugger/containerview/PyViewNumericContainerAction.java index 286757398595..17b354c99e67 100644 --- a/python/src/com/jetbrains/python/debugger/containerview/PyViewNumericContainerAction.java +++ b/python/src/com/jetbrains/python/debugger/containerview/PyViewNumericContainerAction.java @@ -72,6 +72,7 @@ public class PyViewNumericContainerAction extends XDebuggerTreeActionBase { @Override public void update(AnActionEvent e) { + e.getPresentation().setVisible(false); TreePath[] paths = getSelectedPaths(e.getDataContext()); if (paths != null) { if (paths.length > 1) { From 4484907fe92f3372a6c9bfa28307a9b50c8e021f Mon Sep 17 00:00:00 2001 From: fitermay Date: Sun, 28 Aug 2016 20:55:10 -0400 Subject: [PATCH 06/63] add support for parameter info in console --- .../_pydev_bundle/_pydev_calltip_util.py | 160 ++++++++++++++++ .../_pydev_bundle/_pydev_imports_tipper.py | 178 +++++++++--------- .../_pydev_bundle/pydev_console_utils.py | 168 ++++++++--------- .../python/psi/resolve/PyResolveContext.java | 19 +- .../python/PyParameterInfoHandler.java | 4 +- .../completion/PydevConsoleReference.java | 76 ++++++-- .../psi/impl/PyReferenceExpressionImpl.java | 4 +- 7 files changed, 406 insertions(+), 203 deletions(-) create mode 100644 python/helpers/pydev/_pydev_bundle/_pydev_calltip_util.py diff --git a/python/helpers/pydev/_pydev_bundle/_pydev_calltip_util.py b/python/helpers/pydev/_pydev_bundle/_pydev_calltip_util.py new file mode 100644 index 000000000000..8095e12f8fae --- /dev/null +++ b/python/helpers/pydev/_pydev_bundle/_pydev_calltip_util.py @@ -0,0 +1,160 @@ +''' +Id: "$Id$" +Copyright: Copyright (c) 2015 Bank of America Merrill Lynch, All Rights Reserved +Description: +Test: +''' +# noinspection PyBroadException +import types + +from _pydevd_bundle.pydevd_constants import IS_JYTHON, IS_PY3K + +try: + import inspect +except: + try: + from _pydev_imps import _pydev_inspect as inspect + except: + import traceback; + + traceback.print_exc() # Ok, no inspect available (search will not work)from _pydevd_bundle.pydevd_constants import IS_JYTHON, IS_PY3K + +from _pydev_bundle._pydev_imports_tipper import signature_from_docstring + + +def is_bound_method(obj): + if isinstance(obj, types.MethodType): + return getattr(obj, '__self__', getattr(obj, 'im_self', None)) is not None + else: + return False + + +def get_class_name(instance): + return getattr(getattr(instance, "__class__", None), "__name__", None) + + +def get_bound_class_name(obj): + my_self = getattr(obj, '__self__', getattr(obj, 'im_self', None)) + if my_self is None: + return None + return get_class_name(my_self) + + +def get_description(obj): + try: + ob_call = obj.__call__ + except: + ob_call = None + + if isinstance(obj, type) or type(obj).__name__ == 'classobj': + fob = getattr(obj, '__init__', lambda: None) + if not isinstance(fob, (types.FunctionType, types.MethodType)): + fob = obj + elif is_bound_method(ob_call): + fob = ob_call + else: + fob = obj + + argspec = "" + fn_name = None + fn_class = None + if isinstance(fob, (types.FunctionType, types.MethodType)): + spec_info = inspect.getfullargspec(fob) if IS_PY3K else inspect.getargspec(fob) + argspec = inspect.formatargspec(*spec_info) + fn_name = getattr(fob, '__name__', None) + if isinstance(obj, type) or type(obj).__name__ == 'classobj': + fn_name = "__init__" + fn_class = getattr(obj, "__name__", "UnknownClass") + elif is_bound_method(obj) or is_bound_method(ob_call): + fn_class = get_bound_class_name(obj) or "UnknownClass" + + else: + fn_name = getattr(fob, '__name__', None) + fn_self = getattr(fob, '__self__', None) + if fn_self is not None and not isinstance(fn_self, types.ModuleType): + fn_class = get_class_name(fn_self) + + doc_string = get_docstring(ob_call) if is_bound_method(ob_call) else get_docstring(obj) + return create_method_stub(fn_name, fn_class, argspec, doc_string) + + +def create_method_stub(fn_name, fn_class, argspec, doc_string): + if fn_name and argspec: + doc_string = "" if doc_string is None else doc_string + fn_stub = create_function_stub(fn_name, argspec, doc_string, indent=1 if fn_class else 0) + if fn_class: + expr = fn_class if fn_name == '__init__' else fn_class + '().' + fn_name + return create_class_stub(fn_class, fn_stub) + "\n" + expr + else: + expr = fn_name + return fn_stub + "\n" + expr + elif doc_string: + if fn_name: + restored_signature, _ = signature_from_docstring(doc_string, fn_name) + if restored_signature: + return create_method_stub(fn_name, fn_class, restored_signature, doc_string) + return create_function_stub('unknown', '(*args, **kwargs)', doc_string) + '\nunknown' + + else: + return '' + + +def get_docstring(obj): + if obj is not None: + try: + if IS_JYTHON: + # Jython + doc = obj.__doc__ + if doc is not None: + return doc + + from _pydev_bundle import _pydev_jy_imports_tipper + + is_method, infos = _pydev_jy_imports_tipper.ismethod(obj) + ret = '' + if is_method: + for info in infos: + ret += info.get_as_doc() + return ret + + else: + + doc = inspect.getdoc(obj) + if doc is not None: + return doc + except: + pass + else: + return '' + try: + # if no attempt succeeded, try to return repr()... + return repr(obj) + except: + try: + # otherwise the class + return str(obj.__class__) + except: + # if all fails, go to an empty string + return '' + + +def create_class_stub(class_name, contents): + return "class %s(object):\n%s" % (class_name, contents) + + +def create_function_stub(fn_name, fn_argspec, fn_docstring, indent=0): + def shift_right(string, prefix): + return ''.join(prefix + line for line in string.splitlines(True)) + + fn_docstring = shift_right(inspect.cleandoc(fn_docstring), " " * (indent + 1)) + ret = ''' +def %s%s: + """%s""" + pass +''' % (fn_name, fn_argspec, fn_docstring) + ret = ret[1:] # remove first /n + ret = ret.replace('\t', " ") + if indent: + prefix = " " * indent + ret = shift_right(ret, prefix) + return ret diff --git a/python/helpers/pydev/_pydev_bundle/_pydev_imports_tipper.py b/python/helpers/pydev/_pydev_bundle/_pydev_imports_tipper.py index c05c04e521b0..7ee92090f0e8 100644 --- a/python/helpers/pydev/_pydev_bundle/_pydev_imports_tipper.py +++ b/python/helpers/pydev/_pydev_bundle/_pydev_imports_tipper.py @@ -1,5 +1,5 @@ -import os.path import inspect +import os.path import sys from _pydev_bundle._pydev_tipper_common import do_find @@ -222,96 +222,7 @@ def generate_imports_tip_for_module(obj_to_complete, dirComps=None, getattr=geta args = '(%s)' % (r) except TypeError: #ok, let's see if we can get the arguments from the doc - args = '()' - try: - found = False - if len(doc) > 0: - if IS_IPY: - #Handle case where we have the situation below - #sort(self, object cmp, object key) - #sort(self, object cmp, object key, bool reverse) - #sort(self) - #sort(self, object cmp) - - #Or: sort(self: list, cmp: object, key: object) - #sort(self: list, cmp: object, key: object, reverse: bool) - #sort(self: list) - #sort(self: list, cmp: object) - if hasattr(obj, '__name__'): - name = obj.__name__+'(' - - - #Fix issue where it was appearing sort(aa)sort(bb)sort(cc) in the same line. - lines = doc.splitlines() - if len(lines) == 1: - c = doc.count(name) - if c > 1: - doc = ('\n'+name).join(doc.split(name)) - - - major = '' - for line in doc.splitlines(): - if line.startswith(name) and line.endswith(')'): - if len(line) > len(major): - major = line - if major: - args = major[major.index('('):] - found = True - - - if not found: - i = doc.find('->') - if i < 0: - i = doc.find('--') - if i < 0: - i = doc.find('\n') - if i < 0: - i = doc.find('\r') - - - if i > 0: - s = doc[0:i] - s = s.strip() - - #let's see if we have a docstring in the first line - if s[-1] == ')': - start = s.find('(') - if start >= 0: - end = s.find('[') - if end <= 0: - end = s.find(')') - if end <= 0: - end = len(s) - - args = s[start:end] - if not args[-1] == ')': - args = args + ')' - - - #now, get rid of unwanted chars - l = len(args) - 1 - r = [] - for i in xrange(len(args)): - if i == 0 or i == l: - r.append(args[i]) - else: - r.append(check_char(args[i])) - - args = ''.join(r) - - if IS_IPY: - if args.startswith('(self:'): - i = args.find(',') - if i >= 0: - args = '(self'+args[i:] - else: - args = '(self)' - i = args.find(')') - if i > 0: - args = args[:i+1] - - except: - pass + args, doc = signature_from_docstring(doc, getattr(obj, '__name__', None)) retType = TYPE_FUNCTION @@ -350,5 +261,90 @@ def generate_imports_tip_for_module(obj_to_complete, dirComps=None, getattr=geta return ret +def signature_from_docstring(doc, obj_name): + args = '()' + try: + found = False + if len(doc) > 0: + if IS_IPY: + # Handle case where we have the situation below + # sort(self, object cmp, object key) + # sort(self, object cmp, object key, bool reverse) + # sort(self) + # sort(self, object cmp) + # Or: sort(self: list, cmp: object, key: object) + # sort(self: list, cmp: object, key: object, reverse: bool) + # sort(self: list) + # sort(self: list, cmp: object) + if obj_name: + name = obj_name + '(' + # Fix issue where it was appearing sort(aa)sort(bb)sort(cc) in the same line. + lines = doc.splitlines() + if len(lines) == 1: + c = doc.count(name) + if c > 1: + doc = ('\n' + name).join(doc.split(name)) + + major = '' + for line in doc.splitlines(): + if line.startswith(name) and line.endswith(')'): + if len(line) > len(major): + major = line + if major: + args = major[major.index('('):] + found = True + + if not found: + i = doc.find('->') + if i < 0: + i = doc.find('--') + if i < 0: + i = doc.find('\n') + if i < 0: + i = doc.find('\r') + + if i > 0: + s = doc[0:i] + s = s.strip() + + # let's see if we have a docstring in the first line + if s[-1] == ')': + start = s.find('(') + if start >= 0: + end = s.find('[') + if end <= 0: + end = s.find(')') + if end <= 0: + end = len(s) + + args = s[start:end] + if not args[-1] == ')': + args = args + ')' + + # now, get rid of unwanted chars + l = len(args) - 1 + r = [] + for i in xrange(len(args)): + if i == 0 or i == l: + r.append(args[i]) + else: + r.append(check_char(args[i])) + + args = ''.join(r) + + if IS_IPY: + if args.startswith('(self:'): + i = args.find(',') + if i >= 0: + args = '(self' + args[i:] + else: + args = '(self)' + i = args.find(')') + if i > 0: + args = args[:i + 1] + + except: + pass + return args, doc diff --git a/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py b/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py index e9d0a6998a87..9d612005e9f3 100644 --- a/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py +++ b/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py @@ -1,17 +1,15 @@ -import os - from _pydev_bundle.pydev_imports import xmlrpclib, _queue, Exec -import sys -from _pydevd_bundle.pydevd_constants import IS_JYTHON +from _pydev_bundle._pydev_calltip_util import get_description from _pydev_imps._pydev_saved_modules import thread -from _pydevd_bundle import pydevd_xml from _pydevd_bundle import pydevd_vars +from _pydevd_bundle import pydevd_xml +from _pydevd_bundle.pydevd_constants import IS_JYTHON from _pydevd_bundle.pydevd_utils import * # @UnusedWildImport -import traceback -#======================================================================================================================= + +# ======================================================================================================================= # Null -#======================================================================================================================= +# ======================================================================================================================= class Null: """ Gotten from: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/68205 @@ -54,39 +52,39 @@ class Null: return 0 -#======================================================================================================================= +# ======================================================================================================================= # BaseStdIn -#======================================================================================================================= +# ======================================================================================================================= class BaseStdIn: def __init__(self, original_stdin=sys.stdin, *args, **kwargs): try: self.encoding = sys.stdin.encoding except: - #Not sure if it's available in all Python versions... + # Not sure if it's available in all Python versions... pass self.original_stdin = original_stdin def readline(self, *args, **kwargs): - #sys.stderr.write('Cannot readline out of the console evaluation\n') -- don't show anything - #This could happen if the user had done input('enter number).<-- upon entering this, that message would appear, - #which is not something we want. + # sys.stderr.write('Cannot readline out of the console evaluation\n') -- don't show anything + # This could happen if the user had done input('enter number).<-- upon entering this, that message would appear, + # which is not something we want. return '\n' def isatty(self): - return False #not really a file + return False # not really a file def write(self, *args, **kwargs): - pass #not available StdIn (but it can be expected to be in the stream interface) + pass # not available StdIn (but it can be expected to be in the stream interface) def flush(self, *args, **kwargs): - pass #not available StdIn (but it can be expected to be in the stream interface) + pass # not available StdIn (but it can be expected to be in the stream interface) def read(self, *args, **kwargs): - #in the interactive interpreter, a read and a readline are the same. + # in the interactive interpreter, a read and a readline are the same. return self.readline() def close(self, *args, **kwargs): - pass #expected in StdIn + pass # expected in StdIn def __getattr__(self, item): # it's called if the attribute wasn't found @@ -95,9 +93,9 @@ class BaseStdIn: raise AttributeError("%s has no attribute %s" % (self.original_stdin, item)) -#======================================================================================================================= +# ======================================================================================================================= # StdIn -#======================================================================================================================= +# ======================================================================================================================= class StdIn(BaseStdIn): ''' Object to be added to stdin (to emulate it as non-blocking while the next line arrives) @@ -110,16 +108,18 @@ class StdIn(BaseStdIn): self.host = host def readline(self, *args, **kwargs): - #Ok, callback into the client to get the new input + # Ok, callback into the client to get the new input try: server = xmlrpclib.Server('http://%s:%s' % (self.host, self.client_port)) requested_input = server.RequestInput() if not requested_input: - return '\n' #Yes, a readline must return something (otherwise we can get an EOFError on the input() call). + return '\n' # Yes, a readline must return something (otherwise we can get an EOFError on the input() call). return requested_input except: return '\n' + def close(self, *args, **kwargs): + pass # expected in StdIn #======================================================================================================================= # DebugConsoleStdIn @@ -155,9 +155,10 @@ class CodeFragment: if not code_fragment.is_single_line: self.is_single_line = False -#======================================================================================================================= + +# ======================================================================================================================= # BaseInterpreterInterface -#======================================================================================================================= +# ======================================================================================================================= class BaseInterpreterInterface: def __init__(self, mainThread): self.mainThread = mainThread @@ -206,15 +207,15 @@ class BaseInterpreterInterface: try: help = None if 'pydoc' in sys.modules: - pydoc = sys.modules['pydoc'] #Don't import it if it still is not there. + pydoc = sys.modules['pydoc'] # Don't import it if it still is not there. if hasattr(pydoc, 'help'): - #You never know how will the API be changed, so, let's code defensively here + # You never know how will the API be changed, so, let's code defensively here help = pydoc.help if not hasattr(help, 'input'): help = None except: - #Just ignore any error here + # Just ignore any error here pass more = False @@ -222,7 +223,7 @@ class BaseInterpreterInterface: sys.stdin = self.create_std_in(debugger, original_in) try: if help is not None: - #This will enable the help() function to work. + # This will enable the help() function to work. try: try: help.input = sys.stdin @@ -268,7 +269,6 @@ class BaseInterpreterInterface: return more - def do_add_exec(self, codeFragment): ''' Subclasses should override. @@ -277,7 +277,6 @@ class BaseInterpreterInterface: ''' raise NotImplementedError() - def get_namespace(self): ''' Subclasses should override. @@ -286,66 +285,48 @@ class BaseInterpreterInterface: ''' raise NotImplementedError() + def __resolve_reference__(self, text): + """ - def getDescription(self, text): - try: - obj = None - if '.' not in text: + :type text: str + """ + obj = None + if '.' not in text: + try: + obj = self.get_namespace()[text] + except KeyError: + pass + + if obj is None: try: - obj = self.get_namespace()[text] - except KeyError: - return '' - - else: - try: - splitted = text.split('.') - obj = self.get_namespace()[splitted[0]] - for t in splitted[1:]: - obj = getattr(obj, t) - except: - return '' - - if obj is not None: - try: - if sys.platform.startswith("java"): - #Jython - doc = obj.__doc__ - if doc is not None: - return doc - - from _pydev_bundle import _pydev_jy_imports_tipper - - is_method, infos = _pydev_jy_imports_tipper.ismethod(obj) - ret = '' - if is_method: - for info in infos: - ret += info.get_as_doc() - return ret - - else: - #Python and Iron Python - import inspect #@UnresolvedImport - - doc = inspect.getdoc(obj) - if doc is not None: - return doc + obj = self.get_namespace()['__builtins__'][text] except: pass - try: - #if no attempt succeeded, try to return repr()... - return repr(obj) - except: + if obj is None: try: - #otherwise the class - return str(obj.__class__) + obj = getattr(self.get_namespace()['__builtins__'], text, None) except: - #if all fails, go to an empty string - return '' - except: - traceback.print_exc() - return '' + pass + else: + try: + last_dot = text.rindex('.') + parent_context = text[0:last_dot] + res = pydevd_vars.eval_in_context(parent_context, self.get_namespace(), self.get_namespace()) + obj = getattr(res, text[last_dot + 1:]) + except: + pass + return obj + + def getDescription(self, text): + try: + obj = self.__resolve_reference__(text) + if obj is None: + return '' + return get_description(obj) + except: + return '' def do_exec_code(self, code, is_single_line): try: @@ -364,7 +345,6 @@ class BaseInterpreterInterface: def execLine(self, line): return self.do_exec_code(line, True) - def execMultipleLines(self, lines): if IS_JYTHON: for line in lines.split('\n'): @@ -372,9 +352,8 @@ class BaseInterpreterInterface: else: return self.do_exec_code(lines, False) - def interrupt(self): - self.buffer = None # Also clear the buffer when it's interrupted. + self.buffer = None # Also clear the buffer when it's interrupted. try: if self.interruptable: called = False @@ -412,10 +391,10 @@ class BaseInterpreterInterface: pass if not called: - if hasattr(thread, 'interrupt_main'): #Jython doesn't have it + if hasattr(thread, 'interrupt_main'): # Jython doesn't have it thread.interrupt_main() else: - self.mainThread._thread.interrupt() #Jython + self.mainThread._thread.interrupt() # Jython return True except: traceback.print_exc() @@ -495,11 +474,11 @@ class BaseInterpreterInterface: Used to show console with variables connection. Always return a frame where the locals map to our internal namespace. ''' - VIRTUAL_FRAME_ID = "1" # matches PyStackFrameConsole.java - VIRTUAL_CONSOLE_ID = "console_main" # matches PyThreadConsole.java + VIRTUAL_FRAME_ID = "1" # matches PyStackFrameConsole.java + VIRTUAL_CONSOLE_ID = "console_main" # matches PyThreadConsole.java if thread_id == VIRTUAL_CONSOLE_ID and frame_id == VIRTUAL_FRAME_ID: f = FakeFrame() - f.f_globals = {} #As globals=locals here, let's simply let it empty (and save a bit of network traffic). + f.f_globals = {} # As globals=locals here, let's simply let it empty (and save a bit of network traffic). f.f_locals = self.get_namespace() return f else: @@ -527,7 +506,7 @@ class BaseInterpreterInterface: except: # This happens on Jython embedded in host eclipse traceback.print_exc() - sys.stderr.write('pydevd is not available, cannot connect\n',) + sys.stderr.write('pydevd is not available, cannot connect\n', ) from _pydev_bundle import pydev_localhost threading.currentThread().__pydevd_id__ = "console_main" @@ -589,9 +568,10 @@ class BaseInterpreterInterface: # it to run in the main thread. self.exec_queue.put(do_enable_gui) -#======================================================================================================================= + +# ======================================================================================================================= # FakeFrame -#======================================================================================================================= +# ======================================================================================================================= class FakeFrame: ''' Used to show console with variables connection. diff --git a/python/psi-api/src/com/jetbrains/python/psi/resolve/PyResolveContext.java b/python/psi-api/src/com/jetbrains/python/psi/resolve/PyResolveContext.java index 860cef734a1d..3cd3c0809bdd 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/resolve/PyResolveContext.java +++ b/python/psi-api/src/com/jetbrains/python/psi/resolve/PyResolveContext.java @@ -24,17 +24,22 @@ import org.jetbrains.annotations.NotNull; public class PyResolveContext { private final boolean myAllowImplicits; private final boolean myAllowProperties; + private final boolean myAllowRemote; private final TypeEvalContext myTypeEvalContext; + private PyResolveContext(boolean allowImplicits, boolean allowProperties) { myAllowImplicits = allowImplicits; myAllowProperties = allowProperties; myTypeEvalContext = null; + myAllowRemote = false; } - private PyResolveContext(boolean allowImplicits, boolean allowProperties, TypeEvalContext typeEvalContext) { + + private PyResolveContext(boolean allowImplicits, boolean allowProperties, boolean allowRemote, TypeEvalContext typeEvalContext) { myAllowImplicits = allowImplicits; myAllowProperties = allowProperties; + myAllowRemote = allowRemote; myTypeEvalContext = typeEvalContext; } @@ -46,6 +51,10 @@ public class PyResolveContext { return myAllowProperties; } + public boolean allowRemote() { + return myAllowRemote; + } + private static final PyResolveContext ourDefaultContext = new PyResolveContext(true, true); private static final PyResolveContext ourNoImplicitsContext = new PyResolveContext(false, true); private static final PyResolveContext ourNoPropertiesContext = new PyResolveContext(false, false); @@ -63,11 +72,15 @@ public class PyResolveContext { } public PyResolveContext withTypeEvalContext(@NotNull TypeEvalContext context) { - return new PyResolveContext(myAllowImplicits, myAllowProperties, context); + return new PyResolveContext(myAllowImplicits, myAllowProperties, myAllowRemote, context); } public PyResolveContext withoutImplicits() { - return new PyResolveContext(false, myAllowProperties, myTypeEvalContext); + return new PyResolveContext(false, myAllowProperties, myAllowRemote, myTypeEvalContext); + } + + public PyResolveContext withRemote() { + return new PyResolveContext(myAllowImplicits, myAllowProperties, true, myTypeEvalContext); } public TypeEvalContext getTypeEvalContext() { diff --git a/python/src/com/jetbrains/python/PyParameterInfoHandler.java b/python/src/com/jetbrains/python/PyParameterInfoHandler.java index d704f26ae5ca..4307c6d6d0fa 100644 --- a/python/src/com/jetbrains/python/PyParameterInfoHandler.java +++ b/python/src/com/jetbrains/python/PyParameterInfoHandler.java @@ -65,7 +65,7 @@ public class PyParameterInfoHandler implements ParameterInfoHandler { + private final ConsoleCommunication myCommunication; private final String myPrefix; + private final boolean myAllowRemoteResolve; public PydevConsoleReference(final PyReferenceExpression expression, - final ConsoleCommunication communication, - final String prefix) { + final ConsoleCommunication communication, final String prefix, boolean allowRemoteResolve) { super(expression, true); myCommunication = communication; myPrefix = prefix; + myAllowRemoteResolve = allowRemoteResolve; } @NotNull public ResolveResult[] multiResolve(boolean incompleteCode) { - return ResolveResult.EMPTY_ARRAY; + if (!myAllowRemoteResolve) { + return RatedResolveResult.EMPTY_ARRAY; + } + PyExpression pyExpression = resolveFromStub(); + if (pyExpression == null) { + return RatedResolveResult.EMPTY_ARRAY; + } + + if (pyExpression instanceof PyReferenceExpression) { + final PsiReference redirectedRef = pyExpression.getReference(); + if (redirectedRef != null) { + PsiElement resolved = redirectedRef.resolve(); + if (resolved != null) { + return new ResolveResult[]{new RatedResolveResult(RatedResolveResult.RATE_HIGH, resolved)}; + } + } + } + + return RatedResolveResult.EMPTY_ARRAY; + + } + + public PyElement getDocumentationElement() { + return resolveFromStub(); + } + + + private PyExpression resolveFromStub() { + String qualifiedName = myElement.getText(); + if (qualifiedName == null) { + return null; + } + String description; + try { + + description = myCommunication.getDescription(qualifiedName); + if (Strings.isNullOrEmpty(description)) { + return null; + } + } + catch (Exception e) { + return null; + } + + PyElementGenerator generator = PyElementGenerator.getInstance(myElement.getProject()); + PyFile dummyFile = (PyFile)generator.createDummyFile(LanguageLevel.forElement(myElement), description); + Module module = ModuleUtilCore.findModuleForPsiElement(myElement); + if (module != null) { + dummyFile.putUserData(ModuleUtilCore.KEY_MODULE, module); + } + + List statements = dummyFile.getStatements(); + PyStatement pyStatement = statements.get(statements.size() - 1); + return pyStatement instanceof PyExpressionStatement ? ((PyExpressionStatement)pyStatement).getExpression() : null; } @NotNull @@ -71,8 +126,7 @@ public class PydevConsoleReference extends PsiPolyVariantReferenceBase Date: Sun, 28 Aug 2016 20:55:47 -0400 Subject: [PATCH 07/63] consider language level in console parser to currectly provide parameters for print(...) --- .../com/jetbrains/python/console/parsing/PyConsoleParser.java | 4 ++-- python/src/com/jetbrains/python/psi/PyFileElementType.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/src/com/jetbrains/python/console/parsing/PyConsoleParser.java b/python/src/com/jetbrains/python/console/parsing/PyConsoleParser.java index d0a6854bf634..b09bb3300c11 100644 --- a/python/src/com/jetbrains/python/console/parsing/PyConsoleParser.java +++ b/python/src/com/jetbrains/python/console/parsing/PyConsoleParser.java @@ -33,9 +33,9 @@ public class PyConsoleParser extends PyParser{ private PythonConsoleData myPythonConsoleData; private boolean myIPythonStartSymbol; - public PyConsoleParser(PythonConsoleData pythonConsoleData) { + public PyConsoleParser(PythonConsoleData pythonConsoleData, LanguageLevel languageLevel) { myPythonConsoleData = pythonConsoleData; - myLanguageLevel = LanguageLevel.getDefault(); + myLanguageLevel = languageLevel; } @NotNull diff --git a/python/src/com/jetbrains/python/psi/PyFileElementType.java b/python/src/com/jetbrains/python/psi/PyFileElementType.java index 6358424b5d55..11cd013273ee 100644 --- a/python/src/com/jetbrains/python/psi/PyFileElementType.java +++ b/python/src/com/jetbrains/python/psi/PyFileElementType.java @@ -106,7 +106,7 @@ public class PyFileElementType extends IStubFileElementType { final Project project = psi.getProject(); final PsiBuilderFactory factory = PsiBuilderFactory.getInstance(); final PsiBuilder builder = factory.createBuilder(project, node, lexer, getLanguage(), node.getChars()); - final PyParser parser = new PyConsoleParser(consoleData); + final PyParser parser = new PyConsoleParser(consoleData, getLanguageLevel(psi)); return parser.parse(this, builder).getFirstChildNode(); } From e1aa4eac1fa3d36c796567e0f4e40c4e42c66171 Mon Sep 17 00:00:00 2001 From: fitermay Date: Tue, 23 Aug 2016 19:39:55 -0400 Subject: [PATCH 08/63] bug fix: PyDevDocumentation provider should use best available parent reference expression to lookup documentation. --- .../console/PydevDocumentationProvider.java | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/python/src/com/jetbrains/python/console/PydevDocumentationProvider.java b/python/src/com/jetbrains/python/console/PydevDocumentationProvider.java index fc131a44771d..65905172a12a 100644 --- a/python/src/com/jetbrains/python/console/PydevDocumentationProvider.java +++ b/python/src/com/jetbrains/python/console/PydevDocumentationProvider.java @@ -16,13 +16,15 @@ package com.jetbrains.python.console; import com.intellij.lang.documentation.AbstractDocumentationProvider; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiManager; import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.python.console.completion.PydevConsoleElement; -import com.jetbrains.python.console.pydev.ConsoleCommunication; -import com.jetbrains.python.psi.PyExpression; +import com.jetbrains.python.console.completion.PydevConsoleReference; +import com.jetbrains.python.documentation.PyDocumentationBuilder; +import com.jetbrains.python.psi.PyElement; +import com.jetbrains.python.psi.PyReferenceExpression; +import com.jetbrains.python.psi.PyUtil; import org.jetbrains.annotations.Nullable; /** @@ -49,21 +51,21 @@ public class PydevDocumentationProvider extends AbstractDocumentationProvider { @Nullable public static String createDoc(final PsiElement element, final PsiElement originalElement) { - final PyExpression expression = PsiTreeUtil.getParentOfType(originalElement, PyExpression.class); + final PyReferenceExpression expression = PsiTreeUtil.getNonStrictParentOfType(originalElement, PyReferenceExpression.class); // Indicates that we are inside console, not a lookup element! if (expression == null){ return null; } - final ConsoleCommunication communication = PydevConsoleRunner.getConsoleCommunication(originalElement); - if (communication == null){ + PydevConsoleReference consoleRef = PyUtil.as(expression.getReference(), PydevConsoleReference.class); + if (consoleRef == null) { //shouldn't really happen! return null; } - try { - final String description = communication.getDescription(expression.getText()); - return StringUtil.isEmptyOrSpaces(description) ? null : description; - } - catch (Exception e) { + PyElement documentationElement = consoleRef.getDocumentationElement(); + if (documentationElement == null) { return null; } + + return new PyDocumentationBuilder(documentationElement, null).build(); + } } From 70db0e9bbff7bc6c1837626151f148c509e21c4a Mon Sep 17 00:00:00 2001 From: fitermay Date: Wed, 24 Aug 2016 21:45:52 -0400 Subject: [PATCH 09/63] --handle getDescription in debugger --- .../pydev/_pydevd_bundle/pydevd_comm.py | 38 +++++++++++++++ .../pydev/_pydevd_bundle/pydevd_console.py | 27 +++++++++-- .../pydevd_process_net_command.py | 13 +++-- .../debugger/pydev/AbstractCommand.java | 5 +- .../debugger/pydev/GetDescriptionCommand.java | 47 +++++++++++++++++++ .../debugger/pydev/MultiProcessDebugger.java | 5 ++ .../debugger/pydev/ProcessDebugger.java | 3 ++ .../python/debugger/pydev/RemoteDebugger.java | 7 +++ .../PythonDebugConsoleCommunication.java | 4 +- .../python/debugger/PyDebugProcess.java | 11 +++++ 10 files changed, 149 insertions(+), 11 deletions(-) create mode 100644 python/pydevSrc/com/jetbrains/python/debugger/pydev/GetDescriptionCommand.java diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py b/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py index 70566d248c16..1c3f2a3ee69a 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py +++ b/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py @@ -139,6 +139,7 @@ CMD_STEP_INTO_MY_CODE = 144 CMD_GET_CONCURRENCY_EVENT = 145 CMD_SHOW_RETURN_VALUES = 146 CMD_INPUT_REQUESTED = 147 +CMD_GET_DESCRIPTION = 148 CMD_VERSION = 501 CMD_RETURN = 502 @@ -193,6 +194,7 @@ ID_TO_MEANING = { '145': 'CMD_GET_CONCURRENCY_EVENT', '146': 'CMD_SHOW_RETURN_VALUES', '147': 'CMD_INPUT_REQUESTED', + '148': 'CMD_GET_DESCRIPTION', '501': 'CMD_VERSION', '502': 'CMD_RETURN', @@ -700,6 +702,12 @@ class NetCommandFactory: except Exception: return self.make_error_message(seq, get_exception_traceback_str()) + def make_get_description_message(self, seq, payload): + try: + return NetCommand(CMD_GET_DESCRIPTION, seq, payload) + except Exception: + return self.make_error_message(seq, get_exception_traceback_str()) + def make_get_frame_message(self, seq, payload): try: return NetCommand(CMD_GET_FRAME, seq, payload) @@ -1135,6 +1143,36 @@ class InternalGetCompletions(InternalThreadCommand): cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error evaluating expression " + exc) dbg.writer.add_command(cmd) + +# ======================================================================================================================= +# InternalGetDescription +# ======================================================================================================================= +class InternalGetDescription(InternalThreadCommand): + """ Fetch the variable description stub from the debug console + """ + + def __init__(self, seq, thread_id, frame_id, expression): + self.sequence = seq + self.thread_id = thread_id + self.frame_id = frame_id + self.expression = expression + + def do_it(self, dbg): + """ Get completions and write back to the client + """ + try: + frame = pydevd_vars.find_frame(self.thread_id, self.frame_id) + description = pydevd_console.get_description(frame, self.thread_id, self.frame_id, self.expression) + description = pydevd_vars.make_valid_xml_value(quote(description, '/>_= \t')) + description_xml = '' % description + cmd = dbg.cmd_factory.make_get_description_message(self.sequence, description_xml) + dbg.writer.add_command(cmd) + except: + exc = get_exception_traceback_str() + cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error in fetching description" + exc) + dbg.writer.add_command(cmd) + + #======================================================================================================================= # InternalGetBreakpointException #======================================================================================================================= diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_console.py b/python/helpers/pydev/_pydevd_bundle/pydevd_console.py index d35cdc9df39d..b48daae2703a 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevd_console.py +++ b/python/helpers/pydev/_pydevd_bundle/pydevd_console.py @@ -1,17 +1,17 @@ '''An helper file for the pydev debugger (REPL) console ''' -from code import InteractiveConsole import sys import traceback +from code import InteractiveConsole from _pydev_bundle import _pydev_completer -from _pydevd_bundle.pydevd_tracing import get_exception_traceback_str -from _pydevd_bundle.pydevd_vars import make_valid_xml_value -from _pydev_bundle.pydev_imports import Exec -from _pydevd_bundle.pydevd_io import IOBuf from _pydev_bundle.pydev_console_utils import BaseInterpreterInterface, BaseStdIn +from _pydev_bundle.pydev_imports import Exec from _pydev_bundle.pydev_override import overrides from _pydevd_bundle import pydevd_save_locals +from _pydevd_bundle.pydevd_io import IOBuf +from _pydevd_bundle.pydevd_tracing import get_exception_traceback_str +from _pydevd_bundle.pydevd_vars import make_valid_xml_value CONSOLE_OUTPUT = "output" CONSOLE_ERROR = "error" @@ -160,6 +160,12 @@ class DebugConsole(InteractiveConsole, BaseInterpreterInterface): except: self.showtraceback() + def get_namespace(self): + dbg_namespace = {} + dbg_namespace.update(self.frame.f_globals) + dbg_namespace.update(self.frame.f_locals) # locals later because it has precedence over the actual globals + return dbg_namespace + #======================================================================================================================= # InteractiveConsoleCache @@ -175,6 +181,7 @@ class InteractiveConsoleCache: def get_interactive_console(thread_id, frame_id, frame, console_message): """returns the global interactive console. interactive console should have been initialized by this time + :rtype: DebugConsole """ if InteractiveConsoleCache.thread_id == thread_id and InteractiveConsoleCache.frame_id == frame_id: return InteractiveConsoleCache.interactive_console_instance @@ -218,6 +225,16 @@ def execute_console_command(frame, thread_id, frame_id, line, buffer_output=True return console_message +def get_description(frame, thread_id, frame_id, expression): + console_message = ConsoleMessage() + interpreter = get_interactive_console(thread_id, frame_id, frame, console_message) + try: + interpreter.frame = frame + return interpreter.getDescription(expression) + finally: + interpreter.frame = None + + def get_completions(frame, act_tok): """ fetch all completions, create xml for the same return the completions xml diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_process_net_command.py b/python/helpers/pydev/_pydevd_bundle/pydevd_process_net_command.py index 2b7783cbe8ca..dec84ed73369 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevd_process_net_command.py +++ b/python/helpers/pydev/_pydevd_bundle/pydevd_process_net_command.py @@ -16,11 +16,10 @@ from _pydevd_bundle.pydevd_comm import CMD_RUN, CMD_VERSION, CMD_LIST_THREADS, C CMD_SET_PY_EXCEPTION, CMD_GET_FILE_CONTENTS, CMD_SET_PROPERTY_TRACE, CMD_ADD_EXCEPTION_BREAK, \ CMD_REMOVE_EXCEPTION_BREAK, CMD_LOAD_SOURCE, CMD_ADD_DJANGO_EXCEPTION_BREAK, CMD_REMOVE_DJANGO_EXCEPTION_BREAK, \ CMD_EVALUATE_CONSOLE_EXPRESSION, InternalEvaluateConsoleExpression, InternalConsoleGetCompletions, \ - CMD_RUN_CUSTOM_OPERATION, InternalRunCustomOperation, CMD_IGNORE_THROWN_EXCEPTION_AT, CMD_ENABLE_DONT_TRACE,\ - CMD_SHOW_RETURN_VALUES, ID_TO_MEANING + CMD_RUN_CUSTOM_OPERATION, InternalRunCustomOperation, CMD_IGNORE_THROWN_EXCEPTION_AT, CMD_ENABLE_DONT_TRACE, \ + CMD_SHOW_RETURN_VALUES, ID_TO_MEANING, CMD_GET_DESCRIPTION, InternalGetDescription from _pydevd_bundle.pydevd_constants import get_thread_id, IS_PY3K, DebugInfoHolder, dict_contains, dict_keys, dict_pop, \ STATE_RUN -import pydevd_file_utils def process_net_command(py_db, cmd_id, seq, text): @@ -229,6 +228,14 @@ def process_net_command(py_db, cmd_id, seq, text): except: traceback.print_exc() + elif cmd_id == CMD_GET_DESCRIPTION: + try: + + thread_id, frame_id, expression = text.split('\t', 2) + int_cmd = InternalGetDescription(seq, thread_id, frame_id, expression) + py_db.post_internal_command(int_cmd, thread_id) + except: + traceback.print_exc() elif cmd_id == CMD_GET_FRAME: thread_id, frame_id, scope = text.split('\t', 2) diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractCommand.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractCommand.java index 941e39343ba4..9090238a6a45 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractCommand.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractCommand.java @@ -30,7 +30,9 @@ public abstract class AbstractCommand { public static final int LOAD_SOURCE = 124; public static final int SMART_STEP_INTO = 128; public static final int EXIT = 129; - + public static final int GET_DESCRIPTION = 148; + + public static final int CALL_SIGNATURE_TRACE = 130; public static final int CMD_SET_PY_EXCEPTION = 131; @@ -52,6 +54,7 @@ public abstract class AbstractCommand { public static final int SHOW_RETURN_VALUES = 146; public static final int INPUT_REQUESTED = 147; + public static final int ERROR = 901; public static final int VERSION = 501; diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/GetDescriptionCommand.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/GetDescriptionCommand.java new file mode 100644 index 000000000000..ca216c7eb02e --- /dev/null +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/GetDescriptionCommand.java @@ -0,0 +1,47 @@ +package com.jetbrains.python.debugger.pydev; + +import com.jetbrains.python.debugger.PyDebugValue; +import com.jetbrains.python.debugger.PyDebuggerException; + +/** + * @author traff + */ +public class GetDescriptionCommand extends AbstractFrameCommand { + + private String myActionToken; + private String result = null; + + public GetDescriptionCommand(final RemoteDebugger debugger, String threadId, String frameId, final String myActionToken) { + super(debugger, GET_DESCRIPTION, threadId, frameId); + this.myActionToken = myActionToken; + } + + + @Override + public boolean isResponseExpected() { + return true; + } + + @Override + protected void processResponse(ProtocolFrame response) throws PyDebuggerException { + super.processResponse(response); + try { + PyDebugValue pyDebugValue = ProtocolParser.parseValue(response.getPayload(), getDebugger().getDebugProcess()); + result = pyDebugValue.getValue(); + } + catch (Exception e) { + throw new PyDebuggerException("cant obtain completions", e); + } + } + + + @Override + protected void buildPayload(Payload payload) { + super.buildPayload(payload); + payload.add(myActionToken); + } + + public String getResult() { + return result; + } +} diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/MultiProcessDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/MultiProcessDebugger.java index 042b455f3f1b..9b3231974b93 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/MultiProcessDebugger.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/MultiProcessDebugger.java @@ -518,6 +518,11 @@ public class MultiProcessDebugger implements ProcessDebugger { return debugger(threadId).getCompletions(threadId, frameId, prefix); } + @Override + public String getDescription(String threadId, String frameId, String cmd) { + return debugger(threadId).getDescription(threadId, frameId, cmd); + } + @Override public void addExceptionBreakpoint(ExceptionBreakpointCommandFactory factory) { for (RemoteDebugger d : allDebuggers()) { diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProcessDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProcessDebugger.java index 99c8908ab5c9..186dd53a569d 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProcessDebugger.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProcessDebugger.java @@ -87,6 +87,9 @@ public interface ProcessDebugger { List getCompletions(String threadId, String frameId, String prefix); + String getDescription(String threadId, String frameId, String cmd); + + void addExceptionBreakpoint(ExceptionBreakpointCommandFactory factory); void removeExceptionBreakpoint(ExceptionBreakpointCommandFactory factory); diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java index 457947dc9431..3149e42efa5e 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java @@ -761,6 +761,13 @@ public class RemoteDebugger implements ProcessDebugger { return command.getCompletions(); } + @Override + public String getDescription(String threadId, String frameId, String cmd) { + final GetDescriptionCommand command = new GetDescriptionCommand(this, threadId, frameId, cmd); + execute(command); + return command.getResult(); + } + @Override public void addExceptionBreakpoint(ExceptionBreakpointCommandFactory factory) { execute(factory.createAddCommand(this)); diff --git a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java index 78ecbf99578b..f0a16fcb3b69 100644 --- a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java +++ b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java @@ -55,8 +55,8 @@ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunicatio } @Override - public String getDescription(String text) { - return null; + public String getDescription(String refExpression) throws Exception { + return myDebugProcess.getDescription(refExpression); } @Override diff --git a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java index b252994c0e15..75023a3f24b6 100644 --- a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java +++ b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java @@ -902,6 +902,17 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr return Lists.newArrayList(); } + @NotNull + public String getDescription(String prefix) throws Exception { + if (isConnected()) { + dropFrameCaches(); + final PyStackFrame frame = currentFrame(); + return myDebugger.getDescription(frame.getThreadId(), frame.getFrameId(), prefix); + } + return ""; + } + + @Override public void startNotified(ProcessEvent event) { } From ecadbc0a4637b2b3596113f2b243add110777adb Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Tue, 30 Aug 2016 18:01:26 +0300 Subject: [PATCH 10/63] [groovy] fix unnecessary semicolon within traditional loops --- .../style/GrUnnecessarySemicolonInspection.java | 2 ++ .../style/GrUnnecessarySemicolonInspectionTest.groovy | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessarySemicolonInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessarySemicolonInspection.java index caa820acdcf2..51913e7c1ccb 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessarySemicolonInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessarySemicolonInspection.java @@ -25,6 +25,7 @@ import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.codeInspection.GroovySuppressableInspectionTool; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrTraditionalForClause; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import static com.intellij.psi.tree.TokenSet.andNot; @@ -79,6 +80,7 @@ public class GrUnnecessarySemicolonInspection extends GroovySuppressableInspecti } private static boolean isSemicolonUnnecessary(@NotNull PsiElement semicolon) { + if (semicolon.getParent() instanceof GrTraditionalForClause) return false; PsiElement next = PsiUtil.skipLeafSet(semicolon, true, FORWARD_SET); if (next == null) return true; if (next.getNode().getElementType() == mNLS) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessarySemicolonInspectionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessarySemicolonInspectionTest.groovy index a8a40e1bc168..2fd36afed0bc 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessarySemicolonInspectionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/style/GrUnnecessarySemicolonInspectionTest.groovy @@ -75,6 +75,10 @@ print(a); {->} doTest 'for (int i = 0; i < 10;) {}' } + void 'test traditional for without condition'() { + doTest 'for (int i = 0; ; i++) {}' + } + void 'test class members'() { doTest '''\ class A { From bcffe61fbc45b40568b5eb075bb21a7501b43e05 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Tue, 30 Aug 2016 18:17:51 +0300 Subject: [PATCH 11/63] type migration: migration to void: delete returns more accurately IDEA-159957 --- .../typeMigration/rules/VoidConversionRule.java | 9 ++++++--- .../siyeh/ig/fixes/DeleteUnnecessaryStatementFix.java | 4 ++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/VoidConversionRule.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/VoidConversionRule.java index 6385b079f450..748e49e02da6 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/VoidConversionRule.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/VoidConversionRule.java @@ -15,12 +15,14 @@ */ package com.intellij.refactoring.typeMigration.rules; +import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase; import com.intellij.refactoring.typeMigration.TypeEvaluator; import com.intellij.refactoring.typeMigration.TypeMigrationLabeler; import com.intellij.util.IncorrectOperationException; import com.siyeh.ig.controlflow.UnnecessaryReturnInspection; +import com.siyeh.ig.fixes.DeleteUnnecessaryStatementFix; import com.siyeh.ig.psiutils.SideEffectChecker; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -43,10 +45,11 @@ public class VoidConversionRule extends TypeConversionRule { @Override public PsiExpression replace(PsiExpression expression, @NotNull TypeEvaluator evaluator) throws IncorrectOperationException { final PsiElement parent = expression.getParent(); + final Project project = expression.getProject(); if (parent instanceof PsiReturnStatement) { - expression.delete(); - if (UnnecessaryReturnInspection.isReturnRedundant((PsiReturnStatement)parent, false, null)) { - parent.delete(); + final PsiReturnStatement replaced = (PsiReturnStatement)parent.replace(JavaPsiFacade.getElementFactory(project).createStatementFromText("return;", null)); + if (UnnecessaryReturnInspection.isReturnRedundant(replaced, false, null)) { + DeleteUnnecessaryStatementFix.deleteUnnecessaryStatement(replaced); } } return null; diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteUnnecessaryStatementFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteUnnecessaryStatementFix.java index deb46eccd664..f05aa239df8e 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteUnnecessaryStatementFix.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteUnnecessaryStatementFix.java @@ -56,6 +56,10 @@ public class DeleteUnnecessaryStatementFix extends InspectionGadgetsFix { if (statement == null) { return; } + deleteUnnecessaryStatement(statement); + } + + public static void deleteUnnecessaryStatement(PsiStatement statement) { final PsiElement parent = statement.getParent(); if (parent instanceof PsiIfStatement || parent instanceof PsiWhileStatement || From 7b7d49eabbb769bf2af29d838ebe9784bf130c3c Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Tue, 30 Aug 2016 18:18:17 +0300 Subject: [PATCH 12/63] Updater tests fixed. --- updater/testSrc/com/intellij/updater/PatchTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/updater/testSrc/com/intellij/updater/PatchTest.java b/updater/testSrc/com/intellij/updater/PatchTest.java index 6c8631edfb4d..b120c63db4de 100644 --- a/updater/testSrc/com/intellij/updater/PatchTest.java +++ b/updater/testSrc/com/intellij/updater/PatchTest.java @@ -35,7 +35,7 @@ public class PatchTest extends PatchTestCase { public void testDigestFiles() throws Exception { Patch patch = createPatch(); Map checkSums = patch.digestFiles(getDataDir(), Collections.emptyList(), false, TEST_UI); - assertEquals(9, checkSums.size()); + assertEquals(11, checkSums.size()); } @Test @@ -43,6 +43,7 @@ public class PatchTest extends PatchTestCase { Patch patch = createPatch(); assertThat(patch.getActions()).containsOnly( new CreateAction(patch, "newDir/newFile.txt"), + new CreateAction(patch, "newDir/"), new UpdateAction(patch, "Readme.txt", CHECKSUMS.README_TXT), new UpdateZipAction(patch, "lib/annotations.jar", Collections.singletonList("org/jetbrains/annotations/NewClass.class"), @@ -67,6 +68,7 @@ public class PatchTest extends PatchTestCase { assertThat(patch.getActions()).containsOnly( new CreateAction(patch, "newDir/newFile.txt"), + new CreateAction(patch, "newDir/"), new UpdateZipAction(patch, "lib/annotations.jar", Collections.singletonList("org/jetbrains/annotations/NewClass.class"), Collections.singletonList("org/jetbrains/annotations/Nullable.class"), From 42b10ded7a90ff574b4679fd562c5a5b459b082a Mon Sep 17 00:00:00 2001 From: irengrig Date: Tue, 30 Aug 2016 17:17:59 +0200 Subject: [PATCH 13/63] json schema resolve in json files: correctly create lookup scope; do not check by other schemes, if the file have associated schema --- .../schema/JsonSchemaDefinitionResolver.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/json/src/com/jetbrains/jsonSchema/extension/schema/JsonSchemaDefinitionResolver.java b/json/src/com/jetbrains/jsonSchema/extension/schema/JsonSchemaDefinitionResolver.java index 78c18d1aef00..444c78bd77b8 100644 --- a/json/src/com/jetbrains/jsonSchema/extension/schema/JsonSchemaDefinitionResolver.java +++ b/json/src/com/jetbrains/jsonSchema/extension/schema/JsonSchemaDefinitionResolver.java @@ -121,8 +121,7 @@ public class JsonSchemaDefinitionResolver { if (parSchema.getId() != null) { schemaFile = JsonSchemaService.Impl.getEx(myElement.getProject()).getSchemaFileById(parSchema.getId()); } - return resolveInSomeSchema(definitionAddress.substring(1) + PROPERTIES + propertyName, myElement.getProject(), parSchema.getId(), - schemaFile != null ? GlobalSearchScope.fileScope(myElement.getProject(), schemaFile) : null); + return resolveInSomeSchema(definitionAddress.substring(1) + PROPERTIES + propertyName, myElement.getProject(), parSchema.getId(), schemaFile); } else { String relative = splitter.getRelativePath(); if (StringUtil.isEmptyOrSpaces(relative)) { @@ -139,19 +138,20 @@ public class JsonSchemaDefinitionResolver { if (myRef == null) initializeName(); if (myRef == null) return null; - GlobalSearchScope filter = null; + VirtualFile filter = null; if (mySchemaId != null && myRef.startsWith("#/")) { - filter = GlobalSearchScope.fileScope(myElement.getContainingFile()); + filter = myElement.getContainingFile().getVirtualFile(); } else { final JsonSchemaServiceEx schemaServiceEx = JsonSchemaService.Impl.getEx(myElement.getProject()); final Collection> pairs = schemaServiceEx.getSchemaFilesByFile(myElement.getContainingFile().getVirtualFile()); if (pairs != null && ! pairs.isEmpty()) { for (Pair pair : pairs) { - final PsiElement element = resolveInSomeSchema(myRef, myElement.getProject(), pair.getSecond(), - GlobalSearchScope.fileScope(myElement.getProject(), pair.getFirst())); + final PsiElement element = resolveInSomeSchema(myRef, myElement.getProject(), pair.getSecond(), pair.getFirst()); if (element != null) return element; } + // if not in schema file + if (mySchemaId == null) return null; } } return resolveInSomeSchema(myRef, myElement.getProject(), mySchemaId, filter); @@ -161,10 +161,13 @@ public class JsonSchemaDefinitionResolver { private static PsiElement resolveInSomeSchema(@NotNull String referenceName, @NotNull final Project project, @Nullable final String schemaId, - final @Nullable GlobalSearchScope filter) { + final @Nullable VirtualFile filterFile) { final Ref> reference = new Ref<>(); final FileBasedIndex index = FileBasedIndex.getInstance(); + final GlobalSearchScope fileScope = filterFile == null ? null : GlobalSearchScope.fileScope(project, filterFile); + final GlobalSearchScope enlarged = fileScope != null && JsonSchemaResourcesRootsProvider.ourFiles.getValue().contains(filterFile) ? fileScope : + JsonSchemaResourcesRootsProvider.enlarge(project, fileScope == null ? GlobalSearchScope.allScope(project) : fileScope); index.processValues(JsonSchemaFileIndex.PROPERTIES_INDEX, referenceName, null, new FileBasedIndex.ValueProcessor() { @Override public boolean process(VirtualFile file, Integer value) { @@ -176,7 +179,7 @@ public class JsonSchemaDefinitionResolver { reference.set(Pair.create(file, value)); return false; } - }, JsonSchemaResourcesRootsProvider.enlarge(project, filter == null ? GlobalSearchScope.allScope(project) : filter)); + }, enlarged); if (!reference.isNull()) { final Pair pair = reference.get(); From 34248851b45af05bba44475061743e5cad2a8f30 Mon Sep 17 00:00:00 2001 From: irengrig Date: Tue, 30 Aug 2016 17:25:24 +0200 Subject: [PATCH 14/63] WEB-21827 Understand jsnext:main field in package.json --- .../jsonSchema/extension/schema/JsonSchemaFileIndex.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/json/src/com/jetbrains/jsonSchema/extension/schema/JsonSchemaFileIndex.java b/json/src/com/jetbrains/jsonSchema/extension/schema/JsonSchemaFileIndex.java index 296bf2d23f2a..d61dea1c9ca5 100644 --- a/json/src/com/jetbrains/jsonSchema/extension/schema/JsonSchemaFileIndex.java +++ b/json/src/com/jetbrains/jsonSchema/extension/schema/JsonSchemaFileIndex.java @@ -35,7 +35,7 @@ import java.util.Map; */ public class JsonSchemaFileIndex extends FileBasedIndexExtension { public static final ID PROPERTIES_INDEX = ID.create("json.schema.properties.index"); - public static final int VERSION = 4; + public static final int VERSION = 5; private IntInlineKeyDescriptor myKeyDescriptor = new IntInlineKeyDescriptor(); @NotNull From b2791e4f73bba2e3835690c407b20d5c6d67f589 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 30 Aug 2016 17:34:31 +0200 Subject: [PATCH 15/63] use green stubs in java PSI to decrease the amount of AST being reloaded after GC --- .../psi/impl/source/PsiAnonymousClassImpl.java | 5 ++--- .../com/intellij/psi/impl/source/PsiClassImpl.java | 4 ++-- .../psi/impl/source/PsiEnumConstantImpl.java | 4 ++-- .../com/intellij/psi/impl/source/PsiFieldImpl.java | 12 ++++++------ .../psi/impl/source/PsiImportStatementBaseImpl.java | 2 +- .../psi/impl/source/PsiImportStatementImpl.java | 2 +- .../intellij/psi/impl/source/PsiJavaFileImpl.java | 2 +- .../intellij/psi/impl/source/PsiJavaModuleImpl.java | 2 +- .../com/intellij/psi/impl/source/PsiMethodImpl.java | 11 ++++++----- .../intellij/psi/impl/source/PsiParameterImpl.java | 4 ++-- .../psi/impl/source/PsiParameterListImpl.java | 2 +- .../psi/impl/source/PsiReferenceListImpl.java | 2 +- .../source/tree/java/PsiLiteralExpressionImpl.java | 4 ++-- .../impl/source/tree/java/PsiNameValuePairImpl.java | 2 +- 14 files changed, 29 insertions(+), 29 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnonymousClassImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnonymousClassImpl.java index ca9663bdaf8d..d63e372a501f 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnonymousClassImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnonymousClassImpl.java @@ -20,7 +20,6 @@ import com.intellij.psi.*; import com.intellij.psi.impl.java.stubs.JavaStubElementTypes; import com.intellij.psi.impl.java.stubs.PsiClassStub; import com.intellij.psi.impl.source.tree.ChildRole; -import com.intellij.psi.impl.source.tree.SharedImplUtil; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.reference.SoftReference; import com.intellij.util.IncorrectOperationException; @@ -66,7 +65,7 @@ public class PsiAnonymousClassImpl extends PsiClassImpl implements PsiAnonymousC @Override @NotNull public PsiClassType getBaseClassType() { - final PsiClassStub stub = getStub(); + final PsiClassStub stub = getGreenStub(); if (stub == null) { myCachedBaseType = null; return getTypeByTree(); @@ -192,7 +191,7 @@ public class PsiAnonymousClassImpl extends PsiClassImpl implements PsiAnonymousC @Override public boolean isInQualifiedNew() { - final PsiClassStub stub = getStub(); + final PsiClassStub stub = getGreenStub(); if (stub != null) { return stub.isAnonymousInQualifiedNew(); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java index e016b4279670..ab28e1992311 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java @@ -242,7 +242,7 @@ public class PsiClassImpl extends JavaStubPsiElement> implements @Override @Nullable public PsiClass getContainingClass() { - final PsiClassStub stub = getStub(); + final PsiClassStub stub = getGreenStub(); if (stub != null) { StubElement parent = stub.getParentStub(); return parent instanceof PsiClassStub ? ((PsiClassStub)parent).getPsi() : null; @@ -540,7 +540,7 @@ public class PsiClassImpl extends JavaStubPsiElement> implements private static boolean isAnonymousOrLocal(PsiClass aClass) { if (aClass instanceof PsiAnonymousClass) return true; - final PsiClassStub stub = ((PsiClassImpl)aClass).getStub(); + final PsiClassStub stub = ((PsiClassImpl)aClass).getGreenStub(); if (stub != null) { final StubElement parentStub = stub.getParentStub(); return !(parentStub instanceof PsiClassStub || parentStub instanceof PsiFileStub); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiEnumConstantImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiEnumConstantImpl.java index 3ffb565ab5ca..47b3d271e948 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiEnumConstantImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiEnumConstantImpl.java @@ -174,7 +174,7 @@ public class PsiEnumConstantImpl extends JavaStubPsiElement implem @Override @NotNull public String getName() { - final PsiFieldStub stub = getStub(); + final PsiFieldStub stub = getGreenStub(); if (stub != null) { return stub.getName(); } @@ -194,7 +194,7 @@ public class PsiEnumConstantImpl extends JavaStubPsiElement implem @Override public boolean isDeprecated() { - final PsiFieldStub stub = getStub(); + final PsiFieldStub stub = getGreenStub(); if (stub != null) { return stub.isDeprecated(); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java index db17f1a9b9e5..3b0ad2efed61 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java @@ -104,7 +104,7 @@ public class PsiFieldImpl extends JavaStubPsiElement implements Ps @Override @NotNull public String getName() { - final PsiFieldStub stub = getStub(); + final PsiFieldStub stub = getGreenStub(); if (stub != null) { return stub.getName(); } @@ -185,7 +185,7 @@ public class PsiFieldImpl extends JavaStubPsiElement implements Ps private PsiField findFirstFieldInDeclaration() { if (getSelfModifierList() != null) return this; - final PsiFieldStub stub = getStub(); + final PsiFieldStub stub = getGreenStub(); if (stub != null) { final List siblings = stub.getParentStub().getChildrenStubs(); final int idx = siblings.indexOf(stub); @@ -226,7 +226,7 @@ public class PsiFieldImpl extends JavaStubPsiElement implements Ps // avoids stub-to-AST switch if possible, // returns the light generated initializer literal expression if stored in stubs, the regular initializer if wasn't public PsiExpression getDetachedInitializer() { - final PsiFieldStub stub = getStub(); + final PsiFieldStub stub = getGreenStub(); PsiExpression initializer; if (stub == null) { initializer = getInitializer(); @@ -251,7 +251,7 @@ public class PsiFieldImpl extends JavaStubPsiElement implements Ps @Override public boolean hasInitializer() { - PsiFieldStub stub = getStub(); + PsiFieldStub stub = getGreenStub(); if (stub != null) { return stub.getInitializerText() != null; } @@ -299,7 +299,7 @@ public class PsiFieldImpl extends JavaStubPsiElement implements Ps @Override public boolean isDeprecated() { - final PsiFieldStub stub = getStub(); + final PsiFieldStub stub = getGreenStub(); if (stub != null) { return stub.isDeprecated() || stub.hasDeprecatedAnnotation() && PsiImplUtil.isDeprecatedByAnnotation(this); } @@ -309,7 +309,7 @@ public class PsiFieldImpl extends JavaStubPsiElement implements Ps @Override public PsiDocComment getDocComment(){ - final PsiFieldStub stub = getStub(); + final PsiFieldStub stub = getGreenStub(); if (stub != null && !stub.hasDocComment()) return null; CompositeElement treeElement = getNode(); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportStatementBaseImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportStatementBaseImpl.java index c5af2ad5b312..ceb6ce7d9116 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportStatementBaseImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportStatementBaseImpl.java @@ -40,7 +40,7 @@ public abstract class PsiImportStatementBaseImpl extends JavaStubPsiElement imp @NotNull @Override public String getModuleName() { - PsiJavaModuleStub stub = getStub(); + PsiJavaModuleStub stub = getGreenStub(); if (stub != null) { return stub.getName(); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiMethodImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiMethodImpl.java index f565fc1541d4..e9e08148a1fa 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiMethodImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiMethodImpl.java @@ -20,6 +20,7 @@ import com.intellij.navigation.ItemPresentation; import com.intellij.navigation.ItemPresentationProviders; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.ui.Queryable; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Computable; import com.intellij.psi.*; import com.intellij.psi.impl.ElementPresentationUtil; @@ -136,7 +137,7 @@ public class PsiMethodImpl extends JavaStubPsiElement implements @NotNull public String getName() { final String name; - final PsiMethodStub stub = getStub(); + final PsiMethodStub stub = getGreenStub(); if (stub != null) { name = stub.getName(); } @@ -241,7 +242,7 @@ public class PsiMethodImpl extends JavaStubPsiElement implements @Override public boolean isDeprecated() { - final PsiMethodStub stub = getStub(); + final PsiMethodStub stub = getGreenStub(); if (stub != null) { return stub.isDeprecated() || stub.hasDeprecatedAnnotation() && PsiImplUtil.isDeprecatedByAnnotation(this); } @@ -251,7 +252,7 @@ public class PsiMethodImpl extends JavaStubPsiElement implements @Override public PsiDocComment getDocComment() { - final PsiMethodStub stub = getStub(); + final PsiMethodStub stub = getGreenStub(); if (stub != null && !stub.hasDocComment()) return null; return (PsiDocComment)getNode().findChildByRoleAsPsiElement(ChildRole.DOC_COMMENT); @@ -259,7 +260,7 @@ public class PsiMethodImpl extends JavaStubPsiElement implements @Override public boolean isConstructor() { - final PsiMethodStub stub = getStub(); + final PsiMethodStub stub = getGreenStub(); if (stub != null) { return stub.isConstructor(); } @@ -269,7 +270,7 @@ public class PsiMethodImpl extends JavaStubPsiElement implements @Override public boolean isVarArgs() { - final PsiMethodStub stub = getStub(); + final PsiMethodStub stub = getGreenStub(); if (stub != null) { return stub.isVarArgs(); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java index 5276b11f0efa..c9cc626e371b 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java @@ -113,7 +113,7 @@ public class PsiParameterImpl extends JavaStubPsiElement imple @Override @NotNull public final String getName() { - PsiParameterStub stub = getStub(); + PsiParameterStub stub = getGreenStub(); if (stub != null) { return stub.getName(); } @@ -269,7 +269,7 @@ public class PsiParameterImpl extends JavaStubPsiElement imple @Override public boolean isVarArgs() { - final PsiParameterStub stub = getStub(); + final PsiParameterStub stub = getGreenStub(); if (stub != null) { return stub.isParameterTypeEllipsis(); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterListImpl.java index 687c19f90dfe..c4ac677bacfa 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterListImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterListImpl.java @@ -59,7 +59,7 @@ public class PsiParameterListImpl extends JavaStubPsiElement Date: Tue, 30 Aug 2016 18:41:41 +0300 Subject: [PATCH 16/63] revert compiler-message to receive only one file --- .../jps/incremental/CompiledClass.java | 3 +- .../BaseInstrumentingBuilder.java | 3 +- .../NotNullInstrumentingBuilder.java | 4 +- .../incremental/messages/CompilerMessage.java | 56 +++---------------- 4 files changed, 14 insertions(+), 52 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompiledClass.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompiledClass.java index 6a57e2707ac7..5dacdb596078 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompiledClass.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompiledClass.java @@ -28,6 +28,7 @@ import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.Collections; +import java.util.List; /** * In-memory representation of JVM *.class file produced by a compiler. @@ -84,7 +85,7 @@ public class CompiledClass extends UserDataHolderBase{ } @NotNull - public Collection getSourceFilesPaths() { + public List getSourceFilesPaths() { return ContainerUtil.map(mySourceFiles, new Function() { @Override public String fun(File file) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/BaseInstrumentingBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/BaseInstrumentingBuilder.java index fffa64cb6ccb..f8c46abf3e57 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/BaseInstrumentingBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/BaseInstrumentingBuilder.java @@ -20,6 +20,7 @@ import com.intellij.compiler.instrumentation.InstrumentationClassFinder; import com.intellij.compiler.instrumentation.InstrumenterClassWriter; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Key; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.ModuleChunk; import org.jetbrains.jps.incremental.*; @@ -72,7 +73,7 @@ public abstract class BaseInstrumentingBuilder extends ClassProcessingBuilder { LOG.info(e); final String message = e.getMessage(); if (message != null) { - context.processMessage(new CompilerMessage(getPresentableName(), message, compiledClass.getSourceFilesPaths(), BuildMessage.Kind.ERROR)); + context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.ERROR, message, ContainerUtil.getFirstItem(compiledClass.getSourceFilesPaths()))); } else { context.processMessage(new CompilerMessage(getPresentableName(), e)); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/NotNullInstrumentingBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/NotNullInstrumentingBuilder.java index 5ae766ce0e59..a4e7873b373b 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/NotNullInstrumentingBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/NotNullInstrumentingBuilder.java @@ -93,9 +93,9 @@ public class NotNullInstrumentingBuilder extends BaseInstrumentingBuilder{ } }) + ": " + e.getMessage(); context.processMessage(new CompilerMessage(getPresentableName(), + BuildMessage.Kind.ERROR, msg, - compiledClass.getSourceFilesPaths(), - BuildMessage.Kind.ERROR)); + ContainerUtil.getFirstItem(compiledClass.getSourceFilesPaths()))); } return null; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CompilerMessage.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CompilerMessage.java index c627ab7df75a..a594a9bef12d 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CompilerMessage.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CompilerMessage.java @@ -16,16 +16,12 @@ package org.jetbrains.jps.incremental.messages; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.Function; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.PrintStream; -import java.util.Collection; -import java.util.Collections; /** * @author Eugene Zhuravlev @@ -37,28 +33,24 @@ public class CompilerMessage extends BuildMessage { private final long myProblemBeginOffset; private final long myProblemEndOffset; private final long myProblemLocationOffset; - private final Collection mySourcePaths; + private final String mySourcePath; private final long myLine; private final long myColumn; public CompilerMessage(@NotNull String compilerName, @NotNull Throwable internalError) { - this(compilerName, Kind.ERROR, getTextFromThrowable(internalError)); + this(compilerName, Kind.ERROR, getTextFromThrowable(internalError), null, -1L, -1L, -1L, -1L, -1L); } public CompilerMessage(@NotNull String compilerName, Kind kind, String messageText) { - this(compilerName, kind, messageText, (String)null, -1L, -1L, -1L, -1L, -1L); - } - - public CompilerMessage(@NotNull String compilerName, String messageText, Collection sourcePaths, Kind kind) { - this(compilerName, kind, messageText, sourcePaths, -1L, -1L, -1L, -1L, -1L); + this(compilerName, kind, messageText, null, -1L, -1L, -1L, -1L, -1L); } public CompilerMessage(@NotNull String compilerName, Kind kind, String messageText, String sourcePath) { - this(compilerName, messageText, sourcePath == null ? Collections.emptyList() : Collections.singleton(sourcePath), kind); + this(compilerName, kind, messageText, sourcePath, -1L, -1L, -1L, -1L, -1L); } public CompilerMessage(@NotNull String compilerName, Kind kind, String messageText, - @NotNull Collection sourcePaths, + @Nullable String sourcePath, long problemBeginOffset, long problemEndOffset, long problemLocationOffset, @@ -69,34 +61,11 @@ public class CompilerMessage extends BuildMessage { myProblemBeginOffset = problemBeginOffset; myProblemEndOffset = problemEndOffset; myProblemLocationOffset = problemLocationOffset; - mySourcePaths = ContainerUtil.map(sourcePaths, new Function() { - @Override - public String fun(String s) { - return s.replace(File.separatorChar, '/'); - } - }); + mySourcePath = sourcePath != null && !sourcePath.isEmpty()? sourcePath.replace(File.separatorChar, '/') : null; myLine = locationLine; myColumn = locationColumn; } - public CompilerMessage(@NotNull String compilerName, Kind kind, String messageText, - @Nullable String sourcePath, - long problemBeginOffset, - long problemEndOffset, - long problemLocationOffset, - long locationLine, - long locationColumn) { - this(compilerName, - kind, - messageText, - sourcePath == null ? Collections.emptyList() : Collections.singleton(sourcePath), - problemBeginOffset, - problemEndOffset, - problemLocationOffset, - locationLine, - locationColumn); - } - @NotNull public String getCompilerName() { return myCompilerName; @@ -104,7 +73,7 @@ public class CompilerMessage extends BuildMessage { @Nullable public String getSourcePath() { - return mySourcePaths.size() == 1 ? ContainerUtil.getFirstItem(mySourcePaths) : null; + return mySourcePath; } public long getLine() { @@ -130,16 +99,7 @@ public class CompilerMessage extends BuildMessage { public String toString() { final StringBuilder builder = new StringBuilder(); builder.append(getCompilerName()).append(":").append(getKind().name()).append(":").append(super.toString()); - String result; - if (mySourcePaths.isEmpty()) { - result = null; - } - else if (mySourcePaths.size() == 1) { - result = ContainerUtil.getFirstItem(mySourcePaths); - } else { - result = mySourcePaths.toString(); - } - final String path = result; + final String path = getSourcePath(); if (path != null) { builder.append("; file: ").append(path); final long line = getLine(); From 4ab133b8305099af332f37a8631188a259e2dac2 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Tue, 30 Aug 2016 18:52:55 +0300 Subject: [PATCH 17/63] [groovy] accept all strings as method identifiers (fix IDEA-160289 and main method is quotes) --- .../jetbrains/plugins/groovy/lang/lexer/TokenSets.java | 10 ++++++++-- .../GroovyAppLineMarkerContributor.java | 7 ++++--- .../GroovyTestLineMarkerContributor.java | 10 +++++----- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java index 4a2e422f1aea..6391a469680a 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -294,9 +294,15 @@ public abstract class TokenSets { GroovyElementTypes.DISJUNCTION_TYPE_ELEMENT); - public static final TokenSet TYPE_DEFINITIONS = TokenSet.create(GroovyElementTypes.CLASS_DEFINITION, + public static final TokenSet TYPE_DEFINITIONS = TokenSet.create(GroovyElementTypes.CLASS_DEFINITION, GroovyElementTypes.ENUM_DEFINITION, GroovyElementTypes.INTERFACE_DEFINITION, GroovyElementTypes.ANNOTATION_DEFINITION, GroovyElementTypes.TRAIT_DEFINITION); + + public static final TokenSet METHOD_IDENTIFIERS = TokenSet.create( + GroovyTokenTypes.mIDENT, + GroovyTokenTypes.mGSTRING_LITERAL, + GroovyTokenTypes.mSTRING_LITERAL + ); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/testIntegration/GroovyAppLineMarkerContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/testIntegration/GroovyAppLineMarkerContributor.java index ed94d7927773..fce119831f11 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/testIntegration/GroovyAppLineMarkerContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/testIntegration/GroovyAppLineMarkerContributor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,8 @@ package org.jetbrains.plugins.groovy.testIntegration; import com.intellij.execution.application.ApplicationRunLineMarkerProvider; import com.intellij.psi.PsiElement; -import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; + +import static org.jetbrains.plugins.groovy.lang.lexer.TokenSets.METHOD_IDENTIFIERS; /** * @author Dmitry Avdeev @@ -26,6 +27,6 @@ public class GroovyAppLineMarkerContributor extends ApplicationRunLineMarkerProv @Override protected boolean isIdentifier(PsiElement e) { - return e.getNode().getElementType() == GroovyTokenTypes.mIDENT; + return METHOD_IDENTIFIERS.contains(e.getNode().getElementType()); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/testIntegration/GroovyTestLineMarkerContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/testIntegration/GroovyTestLineMarkerContributor.java index ebf5269f6f16..7050beaedbf1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/testIntegration/GroovyTestLineMarkerContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/testIntegration/GroovyTestLineMarkerContributor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,17 +16,17 @@ package org.jetbrains.plugins.groovy.testIntegration; import com.intellij.psi.PsiElement; -import com.intellij.psi.tree.IElementType; import com.intellij.testIntegration.TestRunLineMarkerProvider; -import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; + +import static org.jetbrains.plugins.groovy.lang.lexer.TokenSets.METHOD_IDENTIFIERS; /** * @author Dmitry Avdeev */ public class GroovyTestLineMarkerContributor extends TestRunLineMarkerProvider { + @Override protected boolean isIdentifier(PsiElement e) { - IElementType type = e.getNode().getElementType(); - return type == GroovyTokenTypes.mIDENT || type == GroovyTokenTypes.mGSTRING_LITERAL; + return METHOD_IDENTIFIERS.contains(e.getNode().getElementType()); } } From 1e2ecd672c403b28d8fc59a8d6f1345e7472414d Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 30 Aug 2016 17:51:47 +0200 Subject: [PATCH 18/63] regexp: use getContext() instead of overly complicated PsiLanguageInjectionHost retrieval --- .../lang/regexp/RegExpLanguageHosts.java | 38 +++++-------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLanguageHosts.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLanguageHosts.java index 5b6e3305ba6d..493c0f76b24e 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLanguageHosts.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLanguageHosts.java @@ -15,11 +15,11 @@ */ package org.intellij.lang.regexp; -import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.ClassExtension; -import com.intellij.psi.*; -import com.intellij.psi.impl.source.resolve.FileContextUtil; +import com.intellij.psi.PsiComment; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import org.intellij.lang.regexp.psi.*; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -51,36 +51,19 @@ public final class RegExpLanguageHosts extends ClassExtension null") @Nullable private static RegExpLanguageHost findRegExpHost(@Nullable final PsiElement element) { - if (ApplicationManager.getApplication().isUnitTestMode() && myHost != null) { - return myHost; - } if (element == null) { return null; } - PsiLanguageInjectionHost injectionHost = InjectedLanguageManager.getInstance(element.getProject()).getInjectionHost(element); - final RegExpLanguageHost host = getRegExpHost(injectionHost); - if (host != null) { - return host; + if (ApplicationManager.getApplication().isUnitTestMode() && myHost != null) { + return myHost; } final PsiFile file = element.getContainingFile(); - final SmartPsiElementPointer pointer = file.getUserData(FileContextUtil.INJECTED_IN_ELEMENT); - if (pointer == null) { - return null; + final PsiElement context = file.getContext(); + if (context instanceof RegExpLanguageHost) { + return (RegExpLanguageHost)context; } - final PsiElement pointerElement = pointer.getElement(); - if (pointerElement == null) { - return null; - } - return getRegExpHost(pointerElement); - } - - @Nullable - private static RegExpLanguageHost getRegExpHost(@Nullable PsiElement languageInjectionHostElement) { - if (languageInjectionHostElement instanceof RegExpLanguageHost) { - return (RegExpLanguageHost)languageInjectionHostElement; - } - if (languageInjectionHostElement != null) { - return INSTANCE.forClass(languageInjectionHostElement.getClass()); + if (context != null) { + return INSTANCE.forClass(context.getClass()); } return null; } @@ -171,7 +154,6 @@ public final class RegExpLanguageHosts extends ClassExtension namedCharacterPattern = psiElement().withText("N"); + extend(CompletionType.BASIC, psiElement().afterLeaf(namedCharacterPattern), + new NamedCharacterCompletionProvider(true)); + extend(CompletionType.BASIC, psiElement().afterLeaf(psiElement(RegExpTT.LBRACE).afterLeaf(namedCharacterPattern)), + new NamedCharacterCompletionProvider(false)); } } diff --git a/RegExpSupport/src/org/intellij/lang/regexp/UnicodeCharacterNames.java b/RegExpSupport/src/org/intellij/lang/regexp/UnicodeCharacterNames.java index 57a465111d16..a84105ec40df 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/UnicodeCharacterNames.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/UnicodeCharacterNames.java @@ -33,14 +33,16 @@ public class UnicodeCharacterNames { try { final Class aClass = Class.forName("java.lang.CharacterName"); final Method initNamePool = ReflectionUtil.getDeclaredMethod(aClass, "initNamePool"); - final int[][] lookup2d = ReflectionUtil.getField(aClass, null, int[][].class, "lookup"); - if (initNamePool != null && lookup2d != null) { // jdk 8 - byte[] namePool = (byte[])initNamePool.invoke(null); + if (initNamePool != null) { // jdk 8 + byte[] namePool = (byte[])initNamePool.invoke(null); // initializes "lookup" field + final int[][] lookup2d = ReflectionUtil.getStaticFieldValue(aClass, int[][].class, "lookup"); + if (lookup2d == null) { + return; + } for (int[] indexes : lookup2d) { if (indexes != null) { for (int index : indexes) { if (index != 0) { - ; final String name = new String(namePool, index >>> 8, index & 0xff, AsciiUtil.ASCII_CHARSET); consumer.accept(name); } diff --git a/RegExpSupport/test/org/intellij/lang/regexp/RegExpCompletionTest.java b/RegExpSupport/test/org/intellij/lang/regexp/RegExpCompletionTest.java index 3ba88ab02baa..abdee64fbc05 100644 --- a/RegExpSupport/test/org/intellij/lang/regexp/RegExpCompletionTest.java +++ b/RegExpSupport/test/org/intellij/lang/regexp/RegExpCompletionTest.java @@ -15,9 +15,11 @@ */ package org.intellij.lang.regexp; +import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.openapi.application.PathManager; import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase; import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.ContainerUtil; import java.io.File; import java.util.ArrayList; @@ -57,6 +59,17 @@ public class RegExpCompletionTest extends CodeInsightFixtureTestCase { myFixture.checkResult("[[:^alpha:]"); } + public void testNamedCharacter() { + myFixture.configureByText(RegExpFileType.INSTANCE, "\\\\N{SMILE}"); + final LookupElement[] elements = myFixture.completeBasic(); + final List strings = ContainerUtil.map(elements, LookupElement::getLookupString); + assertEquals(Arrays.asList("SMILE", "SMILING FACE WITH SMILING EYES", "SMILING FACE WITH HEART-SHAPED EYES", + "SMILING CAT FACE WITH HEART-SHAPED EYES", "SMILING FACE WITH OPEN MOUTH AND SMILING EYES", + "SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES", "CAT FACE WITH WRY SMILE", + "GRINNING CAT FACE WITH SMILING EYES", "GRINNING FACE WITH SMILING EYES", + "KISSING FACE WITH SMILING EYES"), strings); + } + public void testBackSlashVariants() throws Throwable { List nameList = new ArrayList<>(Arrays.asList("d", "D", "s", "S", "w", "W", "b", "B", "A", "G", "Z", "z", "Q", "E", From 42764d22ffeaa8d2bd16cc8d52b0f9cc3a6df38b Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 30 Aug 2016 18:58:18 +0300 Subject: [PATCH 20/63] IDEA-70913 smart step into should not propose methods from both branches in conditional expressions --- .../actions/JavaSmartStepIntoHandler.java | 60 +++++++++++++++---- .../debugger/impl/DebuggerUtilsEx.java | 10 ++++ .../debugger/ui/breakpoints/Breakpoint.java | 11 +--- 3 files changed, 59 insertions(+), 22 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java index 707612ab4bce..883b0b8427c6 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java @@ -16,8 +16,13 @@ package com.intellij.debugger.actions; import com.intellij.debugger.SourcePosition; +import com.intellij.debugger.engine.DebuggerUtils; import com.intellij.debugger.engine.SuspendContextImpl; +import com.intellij.debugger.engine.evaluation.EvaluateException; +import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilderImpl; +import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator; import com.intellij.debugger.engine.events.DebuggerContextCommandImpl; +import com.intellij.debugger.impl.DebuggerContextImpl; import com.intellij.debugger.impl.DebuggerSession; import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.debugger.jdi.MethodBytecodeUtil; @@ -36,6 +41,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.util.DocumentUtil; import com.intellij.util.Range; +import com.intellij.util.ThreeState; import com.intellij.util.containers.OrderedSet; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; import com.sun.jdi.Location; @@ -68,7 +74,7 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler { @Override public void threadAction(@NotNull SuspendContextImpl suspendContext) { List targets = ApplicationManager.getApplication().runReadAction( - (Computable>)() -> findSmartStepTargets(position, suspendContext)); + (Computable>)() -> findSmartStepTargets(position, suspendContext, getDebuggerContext())); DebuggerUIUtil.invokeLater(() -> { if (targets.isEmpty()) { doStepInto(session, Registry.is("debugger.single.smart.step.force"), null); @@ -93,7 +99,9 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler { throw new IllegalStateException("Should not be used"); } - protected List findSmartStepTargets(final SourcePosition position, @Nullable SuspendContextImpl suspendContext) { + protected List findSmartStepTargets(final SourcePosition position, + @Nullable SuspendContextImpl suspendContext, + @NotNull DebuggerContextImpl debuggerContext) { final int line = position.getLine(); if (line < 0) { return Collections.emptyList(); // the document has been changed @@ -174,38 +182,64 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler { @Override public void visitField(PsiField field) { - TextRange range = field.getTextRange(); - if (lineRange.intersects(range)) { - //textRange.set(textRange.get().union(range)); + if (checkTextRange(field, false)) { super.visitField(field); } } @Override public void visitMethod(PsiMethod method) { - TextRange range = method.getTextRange(); - if (lineRange.intersects(range)) { - //textRange.set(textRange.get().union(range)); + if (checkTextRange(method, false)) { super.visitMethod(method); } } @Override public void visitStatement(PsiStatement statement) { - TextRange range = statement.getTextRange(); - if (lineRange.intersects(range)) { - textRange.set(textRange.get().union(range)); + if (checkTextRange(statement, true)) { super.visitStatement(statement); } } + @Override + public void visitConditionalExpression(PsiConditionalExpression expression) { + PsiExpression condition = expression.getCondition(); + condition.accept(this); + ThreeState conditionRes = ThreeState.UNSURE; + if (!DebuggerUtils.hasSideEffects(condition)) { + try { + ExpressionEvaluator evaluator = EvaluatorBuilderImpl.getInstance().build(condition, position); + conditionRes = ThreeState.fromBoolean(DebuggerUtilsEx.evaluateBoolean(evaluator, debuggerContext.createEvaluationContext())); + } + catch (EvaluateException e) { + LOG.info(e); + } + } + PsiExpression thenExpression = expression.getThenExpression(); + if (conditionRes != ThreeState.NO && thenExpression != null) { + thenExpression.accept(this); + } + PsiExpression elseExpression = expression.getElseExpression(); + if (conditionRes != ThreeState.YES && elseExpression != null) { + elseExpression.accept(this); + } + } + @Override public void visitExpression(PsiExpression expression) { + checkTextRange(expression, true); + super.visitExpression(expression); + } + + boolean checkTextRange(PsiElement expression, boolean expand) { TextRange range = expression.getTextRange(); if (lineRange.intersects(range)) { - textRange.set(textRange.get().union(range)); + if (expand) { + textRange.set(textRange.get().union(range)); + } + return true; } - super.visitExpression(expression); + return false; } public void visitExpressionList(PsiExpressionList expressionList) { diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java index 14a8a1994abd..6d34c7f0dc69 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java @@ -25,6 +25,8 @@ import com.intellij.debugger.SourcePosition; import com.intellij.debugger.engine.*; import com.intellij.debugger.engine.evaluation.*; import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilder; +import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator; +import com.intellij.debugger.engine.evaluation.expression.UnBoxingEvaluator; import com.intellij.debugger.engine.requests.RequestManagerImpl; import com.intellij.debugger.jdi.VirtualMachineProxyImpl; import com.intellij.debugger.requests.Requestor; @@ -865,6 +867,14 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils { return PsiParameter.EMPTY_ARRAY; } + public static boolean evaluateBoolean(ExpressionEvaluator evaluator, EvaluationContextImpl context) throws EvaluateException { + Object value = UnBoxingEvaluator.unbox(evaluator.evaluate(context), context); + if (!(value instanceof BooleanValue)) { + throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.boolean.expected")); + } + return ((BooleanValue)value).booleanValue(); + } + public static boolean intersects(@NotNull TextRange range, @NotNull PsiElement elem) { TextRange elemRange = elem.getTextRange(); return elemRange != null && elemRange.intersects(range); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java index cfee49e7c399..c76b62fb1f68 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java @@ -25,8 +25,8 @@ import com.intellij.debugger.engine.*; import com.intellij.debugger.engine.evaluation.*; import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilderImpl; import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator; -import com.intellij.debugger.engine.evaluation.expression.UnBoxingEvaluator; import com.intellij.debugger.engine.events.SuspendContextCommandImpl; +import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.debugger.jdi.StackFrameProxyImpl; import com.intellij.debugger.jdi.ThreadReferenceProxyImpl; import com.intellij.debugger.requests.ClassPrepareRequestor; @@ -371,13 +371,7 @@ public abstract class Breakpoint

implements return EvaluatorBuilderImpl.build(getCondition(), contextPsiElement, contextSourcePosition, project); } }); - Object value = UnBoxingEvaluator.unbox(evaluator.evaluate(context), context); - if (!(value instanceof BooleanValue)) { - throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.boolean.expected")); - } - if (!((BooleanValue)value).booleanValue()) { - return false; - } + return DebuggerUtilsEx.evaluateBoolean(evaluator, context); } catch (EvaluateException ex) { if (ex.getCause() instanceof VMDisconnectedException) { @@ -387,7 +381,6 @@ public abstract class Breakpoint

implements DebuggerBundle.message("error.failed.evaluating.breakpoint.condition", getCondition(), ex.getMessage()) ); } - return true; } protected String calculateEventClass(EvaluationContextImpl context, LocatableEvent event) throws EvaluateException { From 88614739d89f9e0253cbdcc8b318acc6d4a6e951 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Tue, 30 Aug 2016 19:04:12 +0300 Subject: [PATCH 21/63] IDEA-160442 Warn about excessive use of collectors --- ...SimplifyStreamApiCallChainsInspection.java | 131 ++++++++++++++++++ .../afterCollectorCounting.java | 10 ++ .../afterCollectorMapping.java | 10 ++ .../afterCollectorMaxBy.java | 10 ++ .../afterCollectorMinBy.java | 10 ++ .../afterCollectorReducing1.java | 10 ++ .../afterCollectorReducing2.java | 10 ++ .../afterCollectorReducing3.java | 10 ++ .../afterCollectorSummingInt.java | 10 ++ .../afterCollectorSummingLong.java | 10 ++ .../beforeCollectorCounting.java | 10 ++ .../beforeCollectorMapping.java | 10 ++ .../beforeCollectorMaxBy.java | 10 ++ .../beforeCollectorMinBy.java | 10 ++ .../beforeCollectorReducing1.java | 10 ++ .../beforeCollectorReducing3.java | 10 ++ .../beforeCollectorSummingInt.java | 10 ++ .../beforeCollectorSummingLong.java | 10 ++ 18 files changed, 301 insertions(+) create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/afterCollectorCounting.java create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/afterCollectorMapping.java create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/afterCollectorMaxBy.java create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/afterCollectorMinBy.java create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/afterCollectorReducing1.java create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/afterCollectorReducing2.java create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/afterCollectorReducing3.java create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/afterCollectorSummingInt.java create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/afterCollectorSummingLong.java create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorCounting.java create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorMapping.java create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorMaxBy.java create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorMinBy.java create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorReducing1.java create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorReducing3.java create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorSummingInt.java create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorSummingLong.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java index 823513cdef5d..5dfb5cfd8ae6 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java @@ -45,6 +45,16 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns private static final String EMPTY_SET_METHOD = "emptySet"; private static final String SINGLETON_LIST_METHOD = "singletonList"; private static final String SINGLETON_METHOD = "singleton"; + private static final String COLLECT_METHOD = "collect"; + + private static final String COUNTING_COLLECTOR = "counting"; + private static final String MIN_BY_COLLECTOR = "minBy"; + private static final String MAX_BY_COLLECTOR = "maxBy"; + private static final String MAPPING_COLLECTOR = "mapping"; + private static final String REDUCING_COLLECTOR = "reducing"; + private static final String SUMMING_INT_COLLECTOR = "summingInt"; + private static final String SUMMING_LONG_COLLECTOR = "summingLong"; + private static final String SUMMING_DOUBLE_COLLECTOR = "summingDouble"; @Override public boolean isEnabledByDefault() { @@ -95,6 +105,44 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns holder.registerProblem(methodCall, null, fix.getMessage(), fix); } } + else if (isCallOf(method, CommonClassNames.JAVA_UTIL_STREAM_STREAM, COLLECT_METHOD, 1)) { + PsiElement parameter = methodCall.getArgumentList().getExpressions()[0]; + if(parameter instanceof PsiMethodCallExpression) { + PsiMethodCallExpression collectorCall = (PsiMethodCallExpression)parameter; + PsiMethod collectorMethod = collectorCall.resolveMethod(); + ReplaceCollectorFix fix = null; + if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, COUNTING_COLLECTOR, 0)) { + fix = new ReplaceCollectorFix(COUNTING_COLLECTOR, "count()", false); + } else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, MIN_BY_COLLECTOR, 1)) { + fix = new ReplaceCollectorFix(MIN_BY_COLLECTOR, "min({1})", true); + } else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, MAX_BY_COLLECTOR, 1)) { + fix = new ReplaceCollectorFix(MAX_BY_COLLECTOR, "max({1})", true); + } else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, MAPPING_COLLECTOR, 2)) { + fix = new ReplaceCollectorFix(MAPPING_COLLECTOR, "map({1}).collect({2})", false); + } else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, REDUCING_COLLECTOR, 1)) { + fix = new ReplaceCollectorFix(REDUCING_COLLECTOR, "reduce({1})", true); + } else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, REDUCING_COLLECTOR, 2)) { + fix = new ReplaceCollectorFix(REDUCING_COLLECTOR, "reduce({1}, {2})", false); + } else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, REDUCING_COLLECTOR, 3)) { + fix = new ReplaceCollectorFix(REDUCING_COLLECTOR, "map({2}).reduce({1}, {3})", false); + } else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, SUMMING_INT_COLLECTOR, 1)) { + fix = new ReplaceCollectorFix(SUMMING_INT_COLLECTOR, "mapToInt({1}).sum()", false); + } else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, SUMMING_LONG_COLLECTOR, 1)) { + fix = new ReplaceCollectorFix(SUMMING_LONG_COLLECTOR, "mapToLong({1}).sum()", false); + } else if(isCallOf(collectorMethod, CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS, SUMMING_DOUBLE_COLLECTOR, 1)) { + fix = new ReplaceCollectorFix(SUMMING_DOUBLE_COLLECTOR, "mapToDouble({1}).sum()", false); + } + if (fix != null && + collectorCall.getArgumentList().getExpressions().length == collectorMethod.getParameterList().getParametersCount()) { + TextRange range = methodCall.getTextRange(); + PsiElement nameElement = methodCall.getMethodExpression().getReferenceNameElement(); + if(nameElement != null) { + range = new TextRange(nameElement.getTextOffset(), range.getEndOffset()); + } + holder.registerProblem(methodCall, range.shiftRight(-methodCall.getTextOffset()), fix.getMessage(), fix); + } + } + } else { final String name; if (isCallOf(method, CommonClassNames.JAVA_UTIL_STREAM_STREAM, FOR_EACH_METHOD, 1)) { @@ -390,4 +438,87 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns } } } + + private static class ReplaceCollectorFix implements LocalQuickFix { + private final String myCollector; + private final String myStreamSequence; + private final String myStreamSequenceStripped; + private final boolean myChangeSemantics; + + public ReplaceCollectorFix(String collector, String streamSequence, boolean changeSemantics) { + myCollector = collector; + myStreamSequence = streamSequence; + myStreamSequenceStripped = streamSequence.replaceAll("\\([^)]+\\)", "()"); + myChangeSemantics = changeSemantics; + } + + @Nls + @NotNull + @Override + public String getName() { + return getFamilyName(); + } + + @Nls + @NotNull + @Override + public String getFamilyName() { + return "Replace Stream.collect(" + myCollector + + "()) with Stream." + myStreamSequenceStripped + + (myChangeSemantics ? " (may change semantics when result is null)" : ""); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + PsiElement element = descriptor.getStartElement(); + if (element instanceof PsiMethodCallExpression) { + PsiMethodCallExpression collectCall = (PsiMethodCallExpression)element; + PsiExpression qualifierExpression = collectCall.getMethodExpression().getQualifierExpression(); + if (qualifierExpression != null) { + PsiElement parameter = collectCall.getArgumentList().getExpressions()[0]; + if (parameter instanceof PsiMethodCallExpression) { + PsiMethodCallExpression collectorCall = (PsiMethodCallExpression)parameter; + PsiExpression[] collectorArgs = collectorCall.getArgumentList().getExpressions(); + String result = myStreamSequence; + for(int i=0; i .count() change the result type from boxed to primitive + // In rare cases it's necessary to add cast to return back to boxed type + // example: + // List intList; List stringList; + // intList.remove(stringList.stream().collect(summingInt(String::length)) -- remove given element + // intList.remove(stringList.stream().mapToInt(String::length).sum()) -- remove element by index + if(expression instanceof PsiExpression) { + PsiType type = ((PsiExpression)expression).getType(); + if(type instanceof PsiPrimitiveType) { + PsiClassType boxedType = ((PsiPrimitiveType)type).getBoxedType(expression); + if(boxedType != null) { + PsiExpression castExpression = + factory.createExpressionFromText("(" + boxedType.getCanonicalText() + ") " + expression.getText(), expression); + PsiElement cast = expression.replace(castExpression); + if (cast instanceof PsiTypeCastExpression && RedundantCastUtil.isCastRedundant((PsiTypeCastExpression)cast)) { + RedundantCastUtil.removeCast((PsiTypeCastExpression)cast); + } + } + } + } + } + } + } + } + + @NotNull + String getMessage() { + return "Stream.collect(" + myCollector + + "()) can be replaced with Stream." + myStreamSequenceStripped + "()" + + (myChangeSemantics ? " (may change semantics when result is null)" : ""); + } + } + } diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorCounting.java b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorCounting.java new file mode 100644 index 000000000000..71e3b19347f8 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorCounting.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(counting()) with Stream.count()" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public long count(List data) { + return data.stream().filter(x -> x.startsWith("xyz")).count(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorMapping.java b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorMapping.java new file mode 100644 index 000000000000..5947f90e9c27 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorMapping.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(mapping()) with Stream.map().collect()" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public List sizes(List data) { + return data.stream().filter(x -> x.startsWith("xyz")).map(String::length).collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorMaxBy.java b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorMaxBy.java new file mode 100644 index 000000000000..d854a721537a --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorMaxBy.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(maxBy()) with Stream.max() (may change semantics when result is null)" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public String max(List data) { + return data.stream().filter(x -> x.startsWith("xyz")).max(String.CASE_INSENSITIVE_ORDER).orElse(""); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorMinBy.java b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorMinBy.java new file mode 100644 index 000000000000..c9feabac14e4 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorMinBy.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(minBy()) with Stream.min() (may change semantics when result is null)" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public Optional min(List data) { + return data.stream().filter(x -> x.startsWith("xyz")).min(String.CASE_INSENSITIVE_ORDER); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorReducing1.java b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorReducing1.java new file mode 100644 index 000000000000..37374e316f13 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorReducing1.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(reducing()) with Stream.reduce() (may change semantics when result is null)" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public Optional concat(List data) { + return data.stream().filter(x -> x.startsWith("xyz")).reduce(String::concat); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorReducing2.java b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorReducing2.java new file mode 100644 index 000000000000..a5a5a24b9580 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorReducing2.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(reducing()) with Stream.reduce()" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public String concat(List data) { + return data.stream().filter(x -> x.startsWith("xyz")).reduce("", String::concat); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorReducing3.java b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorReducing3.java new file mode 100644 index 000000000000..ab3b2ccea49c --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorReducing3.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(reducing()) with Stream.map().reduce()" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public int sum(List data) { + return data.stream().filter(x -> x.startsWith("xyz")).map(String::length).reduce(0, Integer::sum); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorSummingInt.java b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorSummingInt.java new file mode 100644 index 000000000000..249a0358d3e6 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorSummingInt.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(summingInt()) with Stream.mapToInt().sum()" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public void remove(List ints, List data) { + ints.remove((Integer) data.stream().mapToInt(String::length).sum()); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorSummingLong.java b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorSummingLong.java new file mode 100644 index 000000000000..6b86f89a7693 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterCollectorSummingLong.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(summingLong()) with Stream.mapToLong().sum()" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public void remove(List ints, List data) { + ints.remove(data.stream().mapToLong(String::length).sum()); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorCounting.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorCounting.java new file mode 100644 index 000000000000..b40342231759 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorCounting.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(counting()) with Stream.count()" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public long count(List data) { + return data.stream().filter(x -> x.startsWith("xyz")).collect(Collectors.counting()); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorMapping.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorMapping.java new file mode 100644 index 000000000000..a6642d790f95 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorMapping.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(mapping()) with Stream.map().collect()" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public List sizes(List data) { + return data.stream().filter(x -> x.startsWith("xyz")).collect(Collectors.mapping(String::length, Collectors.toList())); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorMaxBy.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorMaxBy.java new file mode 100644 index 000000000000..e6c59cd4caa1 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorMaxBy.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(maxBy()) with Stream.max() (may change semantics when result is null)" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public String max(List data) { + return data.stream().filter(x -> x.startsWith("xyz")).collect(Collectors.maxBy(String.CASE_INSENSITIVE_ORDER)).orElse(""); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorMinBy.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorMinBy.java new file mode 100644 index 000000000000..7be18c5687b9 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorMinBy.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(minBy()) with Stream.min() (may change semantics when result is null)" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public Optional min(List data) { + return data.stream().filter(x -> x.startsWith("xyz")).collect(Collectors.minBy(String.CASE_INSENSITIVE_ORDER)); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorReducing1.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorReducing1.java new file mode 100644 index 000000000000..a10971f7ee78 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorReducing1.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(reducing()) with Stream.reduce() (may change semantics when result is null)" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public Optional concat(List data) { + return data.stream().filter(x -> x.startsWith("xyz")).collect(Collectors.reducing(String::concat)); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorReducing3.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorReducing3.java new file mode 100644 index 000000000000..7ac6bff960d7 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorReducing3.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(reducing()) with Stream.map().reduce()" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public int sum(List data) { + return data.stream().filter(x -> x.startsWith("xyz")).collect(Collectors.reducing(0, String::length, Integer::sum)); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorSummingInt.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorSummingInt.java new file mode 100644 index 000000000000..0a0e77601350 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorSummingInt.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(summingInt()) with Stream.mapToInt().sum()" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public void remove(List ints, List data) { + ints.remove(data.stream().collect(Collectors.summingInt(String::length))); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorSummingLong.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorSummingLong.java new file mode 100644 index 000000000000..305cc7bc13d4 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorSummingLong.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(summingLong()) with Stream.mapToLong().sum()" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public void remove(List ints, List data) { + ints.remove(data.stream().collect(Collectors.summingLong(String::length))); + } +} \ No newline at end of file From 31f3a6da408eef66ad2c0faa5c13b33c99618b34 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Tue, 30 Aug 2016 19:09:18 +0300 Subject: [PATCH 22/63] IDEA-160442 Warn about excessive use of collectors (additional test file) --- .../streamApiCallChains/beforeCollectorReducing2.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorReducing2.java diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorReducing2.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorReducing2.java new file mode 100644 index 000000000000..0f0da24629f6 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeCollectorReducing2.java @@ -0,0 +1,10 @@ +// "Replace Stream.collect(reducing()) with Stream.reduce()" "true" + +import java.util.List; +import java.util.stream.Collectors; + +public class Main { + public String concat(List data) { + return data.stream().filter(x -> x.startsWith("xyz")).collect(Collectors.reducing("", String::concat)); + } +} \ No newline at end of file From 6d08c57fb7a378aacb05eb524bb906b03c4f9ec0 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Tue, 30 Aug 2016 19:05:44 +0300 Subject: [PATCH 23/63] [HintReporter] Logging added --- .../reporting/ReportMissingOrExcessiveInlineHint.kt | 9 ++++++++- .../platform-impl/src/com/intellij/reporting/Reporter.kt | 6 +++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/reporting/ReportMissingOrExcessiveInlineHint.kt b/java/java-impl/src/com/intellij/reporting/ReportMissingOrExcessiveInlineHint.kt index ccb63e96b143..544a739d08c6 100644 --- a/java/java-impl/src/com/intellij/reporting/ReportMissingOrExcessiveInlineHint.kt +++ b/java/java-impl/src/com/intellij/reporting/ReportMissingOrExcessiveInlineHint.kt @@ -23,6 +23,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.PathManager +import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Inlay import com.intellij.openapi.project.Project @@ -35,6 +36,10 @@ class ReportMissingOrExcessiveInlineHint : AnAction() { private val text = "Report Missing or Excessive Inline Hint" private val description = "Text line at caret will be anonymously reported to our servers" + companion object { + private val LOG = Logger.getInstance(ReportMissingOrExcessiveInlineHint::class.java) + } + init { val presentation = templatePresentation presentation.text = text @@ -85,12 +90,14 @@ class ReportMissingOrExcessiveInlineHint : AnAction() { } private fun trySendFileInBackground() { + LOG.debug("File: ${file.path} Length: ${file.length()}") if (!file.exists() || file.length() == 0L) return - ApplicationManager.getApplication().executeOnPooledThread { val text = file.readText() + LOG.debug("File text $text") if (StatsSender.send(text)) { file.delete() + LOG.debug("File deleted") } } } diff --git a/platform/platform-impl/src/com/intellij/reporting/Reporter.kt b/platform/platform-impl/src/com/intellij/reporting/Reporter.kt index 5da107a0da14..728f1bed7ca3 100644 --- a/platform/platform-impl/src/com/intellij/reporting/Reporter.kt +++ b/platform/platform-impl/src/com/intellij/reporting/Reporter.kt @@ -17,6 +17,7 @@ package com.intellij.reporting import com.google.gson.Gson import com.intellij.openapi.application.PermanentInstallationID +import com.intellij.openapi.diagnostic.Logger import org.apache.http.client.fluent.Request import org.apache.http.entity.ContentType @@ -32,7 +33,8 @@ private object Utils { object StatsSender { private val infoUrl = "https://www.jetbrains.com/config/features-service-status.json" - + private val LOG = Logger.getInstance(StatsSender::class.java) + private fun requestServerUrl(): String? { try { val response = Request.Get(infoUrl).execute().returnContent().asString() @@ -40,6 +42,7 @@ object StatsSender { if (info.isServiceAlive()) return info.url } catch (e: Exception) { + LOG.debug(e) } return null @@ -55,6 +58,7 @@ object StatsSender { } } catch (e: Exception) { + LOG.debug(e) } return false } From 8c45b1c5e6e24079a6678cffdb3d83c541b9c854 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 30 Aug 2016 19:35:43 +0300 Subject: [PATCH 24/63] [java] class and package name completion in module files --- .../completion/AllClassesGetter.java | 9 +- .../completion/JavaCompletionContributor.java | 8 +- .../completion/JavaCompletionUtil.java | 14 ++- .../completion/JavaModuleCompletion.java | 89 +++++++++++++++++-- .../completion/JavaNoVariantsDelegator.java | 6 +- .../lang/java/parser/ModuleParser.java | 16 +++- .../psi/parser-partial/modules/Provides7.txt | 21 +++++ .../completion/ModuleCompletionTest.kt | 17 +++- .../java/parser/partial/ModuleParserTest.java | 1 + 9 files changed, 154 insertions(+), 27 deletions(-) create mode 100644 java/java-tests/testData/psi/parser-partial/modules/Provides7.txt diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java index 8d244022701a..06a9ed709b4d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java @@ -126,13 +126,8 @@ public class AllClassesGetter { public static final InsertHandler INSERT_FQN = (context, item) -> { final String qName = item.getQualifiedName(); if (qName != null) { - int start = context.getTailOffset() - 1; - while (start >= 0) { - final char ch = context.getDocument().getCharsSequence().charAt(start); - if (!Character.isJavaIdentifierPart(ch) && ch != '.') break; - start--; - } - context.getDocument().replaceString(start + 1, context.getTailOffset(), qName); + int start = JavaCompletionUtil.findQualifiedNameStart(context); + context.getDocument().replaceString(start, context.getTailOffset(), qName); LOG.assertTrue(context.getTailOffset() >= 0); } }; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java index 3e7509751754..f8a321402aab 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java @@ -226,12 +226,8 @@ public class JavaCompletionContributor extends CompletionContributor { PrefixMatcher matcher = result.getPrefixMatcher(); PsiElement parent = position.getParent(); - if (JavaModuleCompletion.isModuleFile(position.getContainingFile())) { - JavaModuleCompletion.addVariants(position, element -> { - if (element.getLookupString().startsWith(result.getPrefixMatcher().getPrefix())) { - result.addElement(element); - } - }); + if (JavaModuleCompletion.isModuleFile(parameters.getOriginalFile())) { + JavaModuleCompletion.addVariants(position, result); result.stopHere(); return; } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index ca955ed337c0..725881849c26 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -935,4 +935,14 @@ public class JavaCompletionUtil { } return false; } -} + + public static int findQualifiedNameStart(@NotNull InsertionContext context) { + int start = context.getTailOffset() - 1; + while (start >= 0) { + char ch = context.getDocument().getCharsSequence().charAt(start); + if (!Character.isJavaIdentifierPart(ch) && ch != '.') break; + start--; + } + return start + 1; + } +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaModuleCompletion.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaModuleCompletion.java index d9414f11c9b4..2620e664e599 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaModuleCompletion.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaModuleCompletion.java @@ -19,21 +19,22 @@ import com.intellij.codeInsight.TailType; import com.intellij.codeInsight.completion.JavaKeywordCompletion.OverrideableSpace; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; -import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.module.impl.scopes.ModulesScope; import com.intellij.openapi.project.Project; import com.intellij.psi.*; -import com.intellij.psi.impl.file.impl.JavaFileManager; import com.intellij.psi.impl.java.stubs.index.JavaModuleNameIndex; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.ProjectScope; +import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; +import java.util.function.Predicate; + import static com.intellij.codeInsight.completion.JavaKeywordCompletion.createKeyword; class JavaModuleCompletion { @@ -41,7 +42,13 @@ class JavaModuleCompletion { return PsiUtil.isLanguageLevel9OrHigher(file) && PsiJavaModule.MODULE_INFO_FILE.equals(file.getName()); } - static void addVariants(@NotNull PsiElement position, @NotNull Consumer result) { + static void addVariants(@NotNull PsiElement position, @NotNull CompletionResultSet resultSet) { + Consumer result = element -> { + if (element.getLookupString().startsWith(resultSet.getPrefixMatcher().getPrefix())) { + resultSet.addElement(element); + } + }; + if (position instanceof PsiIdentifier) { PsiElement context = position.getParent(); if (context instanceof PsiErrorElement) context = context.getParent(); @@ -52,11 +59,14 @@ class JavaModuleCompletion { else if (context instanceof PsiJavaModule) { addModuleStatementKeywords(position, result); } + else if (context instanceof PsiProvidesStatement) { + addProvidesStatementKeywords(position, result); + } else if (context instanceof PsiJavaModuleReferenceElement) { addModuleReferences(context, result); } else if (context instanceof PsiJavaCodeReferenceElement) { - addCodeReferences(context, result); + addCodeReferences(context, result, resultSet); } } } @@ -74,6 +84,10 @@ class JavaModuleCompletion { result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.PROVIDES), TailType.HUMBLE_SPACE_BEFORE_WORD)); } + private static void addProvidesStatementKeywords(PsiElement position, Consumer result) { + result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.WITH), TailType.HUMBLE_SPACE_BEFORE_WORD)); + } + private static void addModuleReferences(PsiElement context, Consumer result) { PsiJavaModule host = PsiTreeUtil.getParentOfType(context, PsiJavaModule.class); if (host != null) { @@ -90,24 +104,81 @@ class JavaModuleCompletion { } } - private static void addCodeReferences(PsiElement context, Consumer result) { - PsiElement statement = PsiTreeUtil.skipParentsOfType(context, PsiJavaCodeReferenceElement.class); + private static void addCodeReferences(PsiElement context, Consumer result, CompletionResultSet resultSet) { + PsiElement statement = context.getParent(); if (statement instanceof PsiExportsStatement) { Module module = ModuleUtilCore.findModuleForPsiElement(context); - PsiPackage topPackage = ServiceManager.getService(context.getProject(), JavaFileManager.class).findPackage(""); + PsiPackage topPackage = JavaPsiFacade.getInstance(context.getProject()).findPackage(""); if (module != null && topPackage != null) { processPackage(topPackage, new ModulesScope(module), result); } } + else if (statement instanceof PsiUsesStatement) { + processClasses(context.getProject(), null, resultSet, SERVICE_FILTER, TailType.SEMICOLON); + } + else if (statement instanceof PsiProvidesStatement) { + PsiJavaCodeReferenceElement intRef = ((PsiProvidesStatement)statement).getInterfaceReference(); + if (context == intRef) { + processClasses(context.getProject(), null, resultSet, SERVICE_FILTER, TailType.HUMBLE_SPACE_BEFORE_WORD); + } + else if (context == ((PsiProvidesStatement)statement).getImplementationReference() && intRef != null) { + PsiElement service = intRef.resolve(); + Module module = ModuleUtilCore.findModuleForPsiElement(context); + if (service instanceof PsiClass && module != null) { + Predicate filter = psiClass -> !psiClass.hasModifierProperty(PsiModifier.ABSTRACT) && + InheritanceUtil.isInheritorOrSelf(psiClass, (PsiClass)service, true); + processClasses(context.getProject(), new ModulesScope(module), resultSet, filter, TailType.SEMICOLON); + } + } + } } private static void processPackage(PsiPackage pkg, ModulesScope scope, Consumer result) { String packageName = pkg.getQualifiedName(); - if (packageName.indexOf('.') > 0 && !PsiUtil.isPackageEmpty(pkg.getDirectories(scope), packageName)) { - result.consume(new OverrideableSpace(LookupElementBuilder.create(packageName), TailType.SEMICOLON)); + if (isQualified(packageName) && !PsiUtil.isPackageEmpty(pkg.getDirectories(scope), packageName)) { + result.consume(new OverrideableSpace(lookupElement(pkg), TailType.SEMICOLON)); } for (PsiPackage subPackage : pkg.getSubPackages(scope)) { processPackage(subPackage, scope, result); } } + + private static final Predicate SERVICE_FILTER = + psiClass -> !psiClass.isEnum() && psiClass.hasModifierProperty(PsiModifier.PUBLIC); + + private static void processClasses(Project project, + GlobalSearchScope scope, + CompletionResultSet resultSet, + Predicate filter, + TailType tail) { + GlobalSearchScope _scope = scope != null ? scope : ProjectScope.getAllScope(project); + AllClassesGetter.processJavaClasses(resultSet.getPrefixMatcher(), project, _scope, psiClass -> { + if (isQualified(psiClass.getQualifiedName()) && filter.test(psiClass)) { + resultSet.addElement(new OverrideableSpace(lookupElement(psiClass), tail)); + } + return true; + }); + } + + private static LookupElementBuilder lookupElement(PsiNamedElement e) { + LookupElementBuilder lookup = LookupElementBuilder.create(e).withInsertHandler(FQN_INSERT_HANDLER); + String fqn = e instanceof PsiClass ? ((PsiClass)e).getQualifiedName() : ((PsiQualifiedNamedElement)e).getQualifiedName(); + return fqn != null ? lookup.withPresentableText(fqn) : lookup; + } + + private static boolean isQualified(String name) { + return name != null && name.indexOf('.') > 0; + } + + private static final InsertHandler FQN_INSERT_HANDLER = new InsertHandler() { + @Override + public void handleInsert(InsertionContext context, LookupElement item) { + Object e = item.getObject(); + String fqn = e instanceof PsiClass ? ((PsiClass)e).getQualifiedName() : ((PsiQualifiedNamedElement)e).getQualifiedName(); + if (fqn != null) { + int start = JavaCompletionUtil.findQualifiedNameStart(context); + context.getDocument().replaceString(start, context.getTailOffset(), fqn); + } + } + }; } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java index 5b80538771b4..aa69cb91909b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,10 @@ import static com.intellij.patterns.PsiJavaPatterns.psiElement; public class JavaNoVariantsDelegator extends CompletionContributor { @Override public void fillCompletionVariants(@NotNull final CompletionParameters parameters, @NotNull final CompletionResultSet result) { + if (JavaModuleCompletion.isModuleFile(parameters.getOriginalFile())) { + return; + } + final JavaCompletionSession session = new JavaCompletionSession(result); ResultTracker tracker = new ResultTracker(result) { @Override diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ModuleParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ModuleParser.java index deb016b7d84a..9216f033cb5a 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ModuleParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ModuleParser.java @@ -21,13 +21,19 @@ import com.intellij.psi.JavaTokenType; import com.intellij.psi.PsiKeyword; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.tree.IElementType; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import java.util.Set; + import static com.intellij.lang.PsiBuilderUtil.expect; import static com.intellij.lang.java.parser.JavaParserUtil.error; import static com.intellij.lang.java.parser.JavaParserUtil.semicolon; public class ModuleParser { + private static final Set STATEMENT_KEYWORDS = + ContainerUtil.newHashSet(PsiKeyword.REQUIRES, PsiKeyword.EXPORTS, PsiKeyword.USES, PsiKeyword.PROVIDES); + public static void parseModule(@NotNull PsiBuilder builder) { PsiBuilder.Marker module = builder.mark(); mapAndAdvance(builder, JavaTokenType.MODULE_KEYWORD); @@ -225,7 +231,15 @@ public class ModuleParser { } } else if (!hasError) { - error(builder, JavaErrorMessages.message("expected.with")); + IElementType next = builder.getTokenType(); + if (next == JavaTokenType.IDENTIFIER && !STATEMENT_KEYWORDS.contains(builder.getTokenText())) { + PsiBuilder.Marker marker = builder.mark(); + builder.advanceLexer(); + marker.error(JavaErrorMessages.message("expected.with")); + } + else { + error(builder, JavaErrorMessages.message("expected.with")); + } hasError = true; } diff --git a/java/java-tests/testData/psi/parser-partial/modules/Provides7.txt b/java/java-tests/testData/psi/parser-partial/modules/Provides7.txt new file mode 100644 index 000000000000..df577c34d4d2 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/modules/Provides7.txt @@ -0,0 +1,21 @@ +PsiJavaFile:Provides7.java + PsiJavaModule:M + PsiKeyword:module('module') + PsiWhiteSpace(' ') + PsiJavaModuleReference + PsiIdentifier:M('M') + PsiWhiteSpace(' ') + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiProvidesStatement + PsiKeyword:provides('provides') + PsiWhiteSpace(' ') + PsiJavaCodeReferenceElement:Spi + PsiIdentifier:Spi('Spi') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiErrorElement:'with' expected + PsiIdentifier:_('_') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/ModuleCompletionTest.kt b/java/java-tests/testSrc/com/intellij/codeInsight/completion/ModuleCompletionTest.kt index 28dd8eb35089..9fcd9c2fc2a0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/ModuleCompletionTest.kt +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/ModuleCompletionTest.kt @@ -33,7 +33,22 @@ class ModuleCompletionTest : LightFixtureCompletionTestCase() { addFile("pkg/empty/package-info.java", "package pkg.empty;") addFile("pkg/main/C.java", "package pkg.main;\nclass C { }") addFile("pkg/other/C.groovy", "package pkg.other\nclass C { }") - variants("module M { exports pkg. }", "pkg.main", "pkg.other") + variants("module M { exports pkg. }", "main", "other") + complete("module M { exports pkg.o }", "module M { exports pkg.other; }") + } + + fun testUses() { + addFile("pkg/main/MySvc.java", "package pkg.main;\npublic class MySvc { }") + addFile("pkg/main/MySvcImpl.java", "package pkg.main;\nclass MySvcImpl extends MySvc { }") + complete("module M { uses MyS }", "module M { uses pkg.main.MySvc; }") + } + + fun testProvides() { + addFile("pkg/main/MySvc.java", "package pkg.main;\npublic class MySvc { }") + addFile("pkg/main/MySvcImpl.java", "package pkg.main;\nclass MySvcImpl extends MySvc { }") + complete("module M { provides MyS }", "module M { provides pkg.main.MySvc }") + complete("module M { provides pkg.main.MySvc }", "module M { provides pkg.main.MySvc with }") + complete("module M { provides pkg.main.MySvc with MSI }", "module M { provides pkg.main.MySvc with pkg.main.MySvcImpl; }") } // diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ModuleParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ModuleParserTest.java index 2c4ad310ede7..5141a5d897a1 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ModuleParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ModuleParserTest.java @@ -69,6 +69,7 @@ public class ModuleParserTest extends JavaParsingTestCase { public void testProvides4() { doParserTest("module M { provides Spi with ; }"); } public void testProvides5() { doParserTest("module M { provides Spi with Impl }"); } public void testProvides6() { doParserTest("module M { provides Spi with Impl; }"); } + public void testProvides7() { doParserTest("module M { provides Spi _ }"); } private void doParserTest(String text) { doParserTest(text, builder -> JavaParser.INSTANCE.getFileParser().parse(builder)); From 52ac0074cf76460a1490d2daa12a0ff70e932d75 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 30 Aug 2016 18:43:37 +0300 Subject: [PATCH 25/63] find implicit constructor call: check this constructor only (IDEA-CR-13272) --- .../ConstructorReferencesSearchHelper.java | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearchHelper.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearchHelper.java index c2a01117d72b..7ac842b28928 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearchHelper.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearchHelper.java @@ -63,9 +63,10 @@ class ConstructorReferencesSearchHelper { DumbService.getInstance(project).runReadActionInSmartMode(new Computable() { @Override public Void compute() { - constructorCanBeCalledImplicitly[0] = constructor.getParameterList().getParametersCount() == 0; + final PsiParameter[] parameters = constructor.getParameterList().getParameters(); + constructorCanBeCalledImplicitly[0] = parameters.length == 0; if (!constructorCanBeCalledImplicitly[0]) { - constructorCanBeCalledImplicitly[0] = hasDefaultConstructorWithVarargParameter(containingClass); + constructorCanBeCalledImplicitly[0] = parameters.length == 1 && parameters[0].isVarArgs(); } isEnum[0] = containingClass.isEnum(); isUnder18[0] = PsiUtil.getLanguageLevel(containingClass).isAtLeast(LanguageLevel.JDK_1_8); @@ -127,17 +128,6 @@ class ConstructorReferencesSearchHelper { return ClassInheritorsSearch.search(containingClass, searchScope, false).forEach(processor2); } - private static boolean hasDefaultConstructorWithVarargParameter(@NotNull PsiClass containingClass) { - final PsiMethod[] constructors = containingClass.getConstructors(); - for (PsiMethod ctr : constructors) { - final PsiParameter[] parameters = ctr.getParameterList().getParameters(); - if (parameters.length == 1 && parameters[0].isVarArgs()) { - return true; - } - } - return false; - } - private static boolean processEnumReferences(@NotNull final Processor processor, @NotNull final PsiMethod constructor, @NotNull final Project project, From 574fd386458d0d48e3b3b806154a3016e0dd2e0b Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 30 Aug 2016 19:25:00 +0300 Subject: [PATCH 26/63] code cleanup: allow to cleanup through inspection disabled in current profile, reuse intention's code --- .../actions/CleanupInspectionIntention.java | 85 ++++++------- .../ex/GlobalInspectionContextImpl.java | 113 +++++++++--------- .../ex/SequentialCleanupTask.java | 93 -------------- 3 files changed, 102 insertions(+), 189 deletions(-) delete mode 100644 platform/lang-impl/src/com/intellij/codeInspection/ex/SequentialCleanupTask.java diff --git a/platform/lang-impl/src/com/intellij/codeInspection/actions/CleanupInspectionIntention.java b/platform/lang-impl/src/com/intellij/codeInspection/actions/CleanupInspectionIntention.java index 813412589ea6..0a4e9104df61 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/actions/CleanupInspectionIntention.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/actions/CleanupInspectionIntention.java @@ -31,16 +31,16 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.progress.EmptyProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Computable; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.IncorrectOperationException; import com.intellij.util.SequentialModalProgressTask; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.List; /** @@ -74,39 +74,45 @@ public class CleanupInspectionIntention implements IntentionAction, HighPriority @Override public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException { - if (!FileModificationService.getInstance().preparePsiElementForWrite(file)) return; + final List descriptions = ProgressManager.getInstance().runProcess(() -> { InspectionManager inspectionManager = InspectionManager.getInstance(project); return InspectionEngine.runInspectionOnFile(file, myToolWrapper, inspectionManager.createNewGlobalContext(false)); }, new EmptyProgressIndicator()); - Collections.sort(descriptions, new Comparator() { - @Override - public int compare(final CommonProblemDescriptor o1, final CommonProblemDescriptor o2) { - final ProblemDescriptorBase d1 = (ProblemDescriptorBase)o1; - final ProblemDescriptorBase d2 = (ProblemDescriptorBase)o2; - final int offset2 = d2.getTextRange().getStartOffset(); - final int offset1 = d1.getTextRange().getStartOffset(); - return offset2 < offset1 ? -1 : offset1 == offset2 ? 0 : 1; - } + if (!descriptions.isEmpty() && !FileModificationService.getInstance().preparePsiElementForWrite(file)) return; + + final AbstractPerformFixesTask fixesTask = applyFixes(project, "Apply Fixes", descriptions, myQuickfixClass); + + if (!fixesTask.isApplicableFixFound()) { + HintManager.getInstance().showErrorHint(editor, "Unfortunately '" + myText + "' is currently not available for batch mode\n User interaction is required for each problem found"); + } + } + + public static AbstractPerformFixesTask applyFixes(@NotNull Project project, + @NotNull String presentationText, + @NotNull List descriptions, + @Nullable Class quickfixClass) { + Collections.sort(descriptions, (o1, o2) -> { + final ProblemDescriptorBase d1 = (ProblemDescriptorBase)o1; + final ProblemDescriptorBase d2 = (ProblemDescriptorBase)o2; + return -PsiUtilCore.compareElementsByPosition(d1.getPsiElement(), d2.getPsiElement()); }); - - final String templatePresentationText = "Apply Fixes"; + final SequentialModalProgressTask progressTask = - new SequentialModalProgressTask(project, templatePresentationText, true); - final boolean isBatch = BatchQuickFix.class.isAssignableFrom(myQuickfixClass); - final AbstractPerformFixesTask fixesTask = createTask(project, descriptions.toArray(new ProblemDescriptor[descriptions.size()]), progressTask, isBatch); + new SequentialModalProgressTask(project, presentationText, true); + final boolean isBatch = quickfixClass != null && BatchQuickFix.class.isAssignableFrom(quickfixClass); + final AbstractPerformFixesTask fixesTask = isBatch ? + new PerformBatchFixesTask(project, descriptions.toArray(ProblemDescriptor.EMPTY_ARRAY), progressTask, quickfixClass) : + new PerformFixesTask(project, descriptions.toArray(ProblemDescriptor.EMPTY_ARRAY), progressTask, quickfixClass); CommandProcessor.getInstance().executeCommand(project, () -> { CommandProcessor.getInstance().markCurrentCommandAsGlobal(project); progressTask.setMinIterationTime(200); progressTask.setTask(fixesTask); ProgressManager.getInstance().run(progressTask); - }, templatePresentationText, null); - - if (!fixesTask.isApplicableFixFound()) { - HintManager.getInstance().showErrorHint(editor, "Unfortunately '" + myText + "' is currently not available for batch mode\n User interaction is required for each problem found"); - } + }, presentationText, null); + return fixesTask; } @Override @@ -120,23 +126,16 @@ public class CleanupInspectionIntention implements IntentionAction, HighPriority return false; } - @NotNull - private AbstractPerformFixesTask createTask(@NotNull Project project, - ProblemDescriptor[] descriptions, - SequentialModalProgressTask progressTask, - boolean isBatch) { - return isBatch ? - new PerformBatchFixesTask(project, descriptions, progressTask) : - new PerformFixesTask(project, descriptions, progressTask); - } - - private abstract class AbstractPerformFixesTask extends PerformFixesModalTask { + private static abstract class AbstractPerformFixesTask extends PerformFixesModalTask { private boolean myApplicableFixFound = false; + protected final Class myQuickfixClass; public AbstractPerformFixesTask(@NotNull Project project, - @NotNull CommonProblemDescriptor[] descriptors, - @NotNull SequentialModalProgressTask task) { + @NotNull CommonProblemDescriptor[] descriptors, + @NotNull SequentialModalProgressTask task, + @Nullable Class quickfixClass) { super(project, descriptors, task); + myQuickfixClass = quickfixClass; } protected abstract void collectFix(QuickFix fix, ProblemDescriptor descriptor, Project project); @@ -146,7 +145,7 @@ public class CleanupInspectionIntention implements IntentionAction, HighPriority final QuickFix[] fixes = descriptor.getFixes(); if (fixes != null && fixes.length > 0) { for (final QuickFix fix : fixes) { - if (fix != null && fix.getClass().isAssignableFrom(myQuickfixClass)) { + if (fix != null && (myQuickfixClass == null || fix.getClass().isAssignableFrom(myQuickfixClass))) { final ProblemDescriptor problemDescriptor = (ProblemDescriptor)descriptor; final PsiElement element = problemDescriptor.getPsiElement(); if (element != null && element.isValid()) { @@ -164,14 +163,15 @@ public class CleanupInspectionIntention implements IntentionAction, HighPriority } } - private class PerformBatchFixesTask extends AbstractPerformFixesTask { + private static class PerformBatchFixesTask extends AbstractPerformFixesTask { private final List myBatchModeDescriptors = new ArrayList<>(); private boolean myApplied = false; public PerformBatchFixesTask(@NotNull Project project, @NotNull CommonProblemDescriptor[] descriptors, - @NotNull SequentialModalProgressTask task) { - super(project, descriptors, task); + @NotNull SequentialModalProgressTask task, + @NotNull Class quickfixClass) { + super(project, descriptors, task, quickfixClass); } @Override @@ -204,11 +204,12 @@ public class CleanupInspectionIntention implements IntentionAction, HighPriority } } - private class PerformFixesTask extends AbstractPerformFixesTask { + private static class PerformFixesTask extends AbstractPerformFixesTask { public PerformFixesTask(@NotNull Project project, @NotNull CommonProblemDescriptor[] descriptors, - @NotNull SequentialModalProgressTask task) { - super(project, descriptors, task); + @NotNull SequentialModalProgressTask task, + @Nullable Class quickFixClass) { + super(project, descriptors, task, quickFixClass); } @Override diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java index aa16bf133356..f5fba8dec473 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java @@ -20,10 +20,10 @@ import com.intellij.analysis.AnalysisScope; import com.intellij.analysis.AnalysisUIOptions; import com.intellij.analysis.PerformAnalysisInBackgroundOption; import com.intellij.codeInsight.FileModificationService; -import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.HighlightInfoProcessor; import com.intellij.codeInsight.daemon.impl.LocalInspectionsPass; import com.intellij.codeInspection.*; +import com.intellij.codeInspection.actions.CleanupInspectionIntention; import com.intellij.codeInspection.lang.GlobalInspectionContextExtension; import com.intellij.codeInspection.reference.RefElement; import com.intellij.codeInspection.reference.RefEntity; @@ -47,7 +47,6 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.application.TransactionGuard; import com.intellij.openapi.application.ex.ApplicationManagerEx; -import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.components.PathMacroManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; @@ -77,8 +76,9 @@ import com.intellij.psi.util.PsiUtilCore; import com.intellij.ui.GuiUtils; import com.intellij.ui.content.*; import com.intellij.util.*; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.*; import com.intellij.util.containers.HashMap; +import com.intellij.util.containers.HashSet; import com.intellij.util.ui.UIUtil; import gnu.trove.THashSet; import org.jdom.Element; @@ -92,6 +92,7 @@ import java.io.IOException; import java.io.OutputStreamWriter; import java.lang.reflect.Constructor; import java.util.*; +import java.util.Queue; import java.util.concurrent.*; public class GlobalInspectionContextImpl extends GlobalInspectionContextBase implements GlobalInspectionContext { @@ -889,8 +890,6 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator(); final List lTools = new ArrayList<>(); - final LinkedHashMap> results = new LinkedHashMap<>(); - final SearchScope searchScope = scope.toSearchScope(); final TextRange range; if (searchScope instanceof LocalSearchScope) { @@ -909,47 +908,66 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp assert tools != null; return tools.getTool().getTool() instanceof CleanupLocalInspectionTool; }); + List descriptors = new ArrayList<>(); + Set files = new HashSet<>(); boolean includeDoNotShow = includeDoNotShow(profile); - scope.accept(new PsiElementVisitor() { - private int myCount; - @Override - public void visitFile(PsiFile file) { - if (progressIndicator != null) { - progressIndicator.setFraction((double)++myCount / fileCount); - } - if (isBinary(file)) return; - for (final Tools tools : inspectionTools) { - final InspectionToolWrapper tool = tools.getEnabledTool(file, includeDoNotShow); - if (tool instanceof LocalInspectionToolWrapper) { - lTools.add((LocalInspectionToolWrapper)tool); - tool.initialize(GlobalInspectionContextImpl.this); + final RefManagerImpl refManager = (RefManagerImpl)getRefManager(); + refManager.inspectionReadActionStarted(); + try { + scope.accept(new PsiElementVisitor() { + private int myCount; + @Override + public void visitFile(PsiFile file) { + if (progressIndicator != null) { + progressIndicator.setFraction((double)++myCount / fileCount); } - } - - if (!lTools.isEmpty()) { - final LocalInspectionsPass pass = new LocalInspectionsPass(file, PsiDocumentManager.getInstance(getProject()).getDocument(file), range != null ? range.getStartOffset() : 0, - range != null ? range.getEndOffset() : file.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true, - HighlightInfoProcessor.getEmpty()); - Runnable runnable = () -> pass.doInspectInBatch(GlobalInspectionContextImpl.this, InspectionManager.getInstance(getProject()), lTools); - ApplicationManager.getApplication().runReadAction(runnable); - final List infos = pass.getInfos(); - if (searchScope instanceof LocalSearchScope) { - for (Iterator iterator = infos.iterator(); iterator.hasNext(); ) { - final HighlightInfo info = iterator.next(); - final TextRange infoRange = new TextRange(info.getStartOffset(), info.getEndOffset()); - if (!((LocalSearchScope)searchScope).containsRange(file, infoRange)) { - iterator.remove(); - } + if (isBinary(file)) return; + for (final Tools tools : inspectionTools) { + final InspectionToolWrapper tool = tools.getEnabledTool(file, includeDoNotShow); + if (tool instanceof LocalInspectionToolWrapper) { + lTools.add((LocalInspectionToolWrapper)tool); + tool.initialize(GlobalInspectionContextImpl.this); } } - if (!infos.isEmpty()) { - results.put(file, infos); + + if (!lTools.isEmpty()) { + final LocalInspectionsPass pass = new LocalInspectionsPass(file, PsiDocumentManager.getInstance(getProject()).getDocument(file), range != null ? range.getStartOffset() : 0, + range != null ? range.getEndOffset() : file.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true, + HighlightInfoProcessor.getEmpty()); + Runnable runnable = () -> pass.doInspectInBatch(GlobalInspectionContextImpl.this, InspectionManager.getInstance(getProject()), lTools); + ApplicationManager.getApplication().runReadAction(runnable); + + List localDescriptors = new ArrayList<>(); + for (LocalInspectionToolWrapper tool : lTools) { + for (CommonProblemDescriptor descriptor : getPresentation(tool).getProblemDescriptors()) { + if (descriptor instanceof ProblemDescriptor) { + localDescriptors.add((ProblemDescriptor)descriptor); + } + } + } + + if (searchScope instanceof LocalSearchScope) { + for (Iterator iterator = localDescriptors.iterator(); iterator.hasNext(); ) { + final ProblemDescriptor descriptor = iterator.next(); + final TextRange infoRange = descriptor instanceof ProblemDescriptorBase ? ((ProblemDescriptorBase)descriptor).getTextRange() : null; + if (infoRange != null && !((LocalSearchScope)searchScope).containsRange(file, infoRange)) { + iterator.remove(); + } + } + } + if (!localDescriptors.isEmpty()) { + descriptors.addAll(localDescriptors); + files.add(file); + } } } - } - }); + }); + } + finally { + refManager.inspectionReadActionFinished(); + } - if (results.isEmpty()) { + if (files.isEmpty()) { GuiUtils.invokeLaterIfNeeded(() -> { if (commandName != null) { NOTIFICATION_GROUP.createNotification(InspectionsBundle.message("inspection.no.problems.message", scope.getFileCount(), scope.getDisplayName()), MessageType.INFO).notify(getProject()); @@ -961,21 +979,8 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp return; } Runnable runnable = () -> { - if (!FileModificationService.getInstance().preparePsiElementsForWrite(results.keySet())) return; - - final String title = "Code Cleanup"; - final SequentialModalProgressTask progressTask = new SequentialModalProgressTask(getProject(), title, true); - progressTask.setMinIterationTime(200); - progressTask.setTask(new SequentialCleanupTask(getProject(), results, progressTask)); - CommandProcessor.getInstance().executeCommand(getProject(), () -> { - if (commandName != null) { - CommandProcessor.getInstance().markCurrentCommandAsGlobal(getProject()); - } - ProgressManager.getInstance().run(progressTask); - if (postRunnable != null) { - ApplicationManager.getApplication().invokeLater(postRunnable); - } - }, title, null); + if (!FileModificationService.getInstance().preparePsiElementsForWrite(files)) return; + CleanupInspectionIntention.applyFixes(getProject(), "Code Cleanup", descriptors, null); }; TransactionGuard.submitTransaction(getProject(), runnable); } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/SequentialCleanupTask.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/SequentialCleanupTask.java deleted file mode 100644 index f72eabaebb82..000000000000 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/SequentialCleanupTask.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.codeInspection.ex; - -import com.intellij.codeInsight.daemon.impl.HighlightInfo; -import com.intellij.openapi.actionSystem.ActionManager; -import com.intellij.openapi.application.AccessToken; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.WriteAction; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiFile; -import com.intellij.util.SequentialModalProgressTask; -import com.intellij.util.SequentialTask; - -import java.util.*; - -class SequentialCleanupTask implements SequentialTask { - private static final Logger LOG = Logger.getInstance(SequentialCleanupTask.class); - - private final Project myProject; - private final List> myResults = new ArrayList<>(); - private final SequentialModalProgressTask myProgressTask; - private int myCount = 0; - - public SequentialCleanupTask(Project project, LinkedHashMap> results, SequentialModalProgressTask task) { - myProject = project; - for (Map.Entry> entry : results.entrySet()) { - PsiFile file = entry.getKey(); - List infos = entry.getValue(); - // sort from bottom to top - Collections.sort(infos, (info1, info2) -> info2.getStartOffset() - info1.getStartOffset()); - for (HighlightInfo info : infos) { - myResults.add(Pair.create(file, info)); - } - } - myProgressTask = task; - } - - @Override - public void prepare() {} - - @Override - public boolean isDone() { - return myCount > myResults.size() - 1; - } - - @Override - public boolean iteration() { - final Pair pair = myResults.get(myCount++); - final ProgressIndicator indicator = myProgressTask.getIndicator(); - if (indicator != null) { - indicator.setFraction((double) myCount/myResults.size()); - indicator.setText("Processing " + pair.first.getName()); - } - for (final Pair actionRange : pair.second.quickFixActionRanges) { - final AccessToken token = WriteAction.start(); - try { - actionRange.getFirst().getAction().invoke(myProject, null, pair.first); - } - catch (ProcessCanceledException e) { - throw e; - } - catch (Exception e) { - LOG.error(e); - } - finally { - token.finish(); - } - } - return true; - } - - @Override - public void stop() {} -} From 47734322976b3ffb28169314c294796ae5a022c9 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 30 Aug 2016 21:04:26 +0300 Subject: [PATCH 27/63] unused declaration: preserve structure on file level as it shows problems (IDEA-160298) --- .../ex/InspectionRVContentProvider.java | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProvider.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProvider.java index 35f2ca182bb8..3251b80df54d 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProvider.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProvider.java @@ -20,6 +20,7 @@ */ package com.intellij.codeInspection.ex; +import com.intellij.codeInsight.daemon.impl.HighlightInfoType; import com.intellij.codeInspection.CommonProblemDescriptor; import com.intellij.codeInspection.QuickFix; import com.intellij.codeInspection.reference.RefDirectory; @@ -279,21 +280,25 @@ public abstract class InspectionRVContentProvider { continue; } } - for (RefElementNode parentNode : parentNodes) { - final List nodes = new ArrayList<>(); - TreeUtil.traverse(parentNode, new TreeUtil.Traverse() { - @Override - public boolean accept(final Object node) { - if (node instanceof ProblemDescriptionNode) { - nodes.add((ProblemDescriptionNode)node); + + //allow unused declaration to have structure at file level even when there are unused parameters + if (!HighlightInfoType.UNUSED_SYMBOL_SHORT_NAME.equals(toolWrapper.getShortName())) { + for (RefElementNode parentNode : parentNodes) { + final List nodes = new ArrayList<>(); + TreeUtil.traverse(parentNode, new TreeUtil.Traverse() { + @Override + public boolean accept(final Object node) { + if (node instanceof ProblemDescriptionNode) { + nodes.add((ProblemDescriptionNode)node); + } + return true; } - return true; + }); + if (nodes.isEmpty()) continue; + parentNode.removeAllChildren(); + for (ProblemDescriptionNode node : nodes) { + parentNode.add(node); } - }); - if (nodes.isEmpty()) continue; //FilteringInspectionTool == DeadCode - parentNode.removeAllChildren(); - for (ProblemDescriptionNode node : nodes) { - parentNode.add(node); } } for (RefElementNode node : parentNodes) { From 3f5632d044cd0d196e938ad219758eb6312d8d32 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Tue, 30 Aug 2016 20:43:47 +0200 Subject: [PATCH 28/63] Changed the wrong copyright note according to the review: https://github.com/JetBrains/intellij-community/pull/439/files#r76836768 --- python/helpers/pydev/_pydev_bundle/_pydev_calltip_util.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/python/helpers/pydev/_pydev_bundle/_pydev_calltip_util.py b/python/helpers/pydev/_pydev_bundle/_pydev_calltip_util.py index 8095e12f8fae..b846fb4e5586 100644 --- a/python/helpers/pydev/_pydev_bundle/_pydev_calltip_util.py +++ b/python/helpers/pydev/_pydev_bundle/_pydev_calltip_util.py @@ -1,8 +1,6 @@ ''' -Id: "$Id$" -Copyright: Copyright (c) 2015 Bank of America Merrill Lynch, All Rights Reserved -Description: -Test: +License: Apache 2.0 +Author: Yuli Fitterman ''' # noinspection PyBroadException import types From 42727211768547e126571cb9db45f3c5dc720569 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Tue, 30 Aug 2016 20:49:56 +0200 Subject: [PATCH 29/63] Rename the method as 'stub' has a different meaning --- .../python/console/completion/PydevConsoleReference.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/src/com/jetbrains/python/console/completion/PydevConsoleReference.java b/python/src/com/jetbrains/python/console/completion/PydevConsoleReference.java index e56f9df987fa..735e225fe044 100644 --- a/python/src/com/jetbrains/python/console/completion/PydevConsoleReference.java +++ b/python/src/com/jetbrains/python/console/completion/PydevConsoleReference.java @@ -64,7 +64,7 @@ public class PydevConsoleReference extends PsiPolyVariantReferenceBase Date: Tue, 30 Aug 2016 22:50:08 +0200 Subject: [PATCH 30/63] make an option to avoid Tool Window activation on start --- .../impl/ProjectViewToolWindowFactory.java | 6 +++--- .../intellij/openapi/wm/ToolWindowFactory.java | 18 +++++++++++++++++- .../openapi/wm/ToolWindowFactoryEx.java | 4 ++-- .../openapi/wm/impl/ToolWindowImpl.java | 6 ++---- .../openapi/wm/impl/WindowInfoImpl.java | 16 +++++++++++++--- 5 files changed, 37 insertions(+), 13 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewToolWindowFactory.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewToolWindowFactory.java index f4b3803a63d0..764228fc4ef5 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewToolWindowFactory.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewToolWindowFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,13 +22,13 @@ import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.wm.ToolWindow; -import com.intellij.openapi.wm.ToolWindowFactoryEx; +import com.intellij.openapi.wm.ToolWindowFactory; import org.jetbrains.annotations.NotNull; /** * @author yole */ -public class ProjectViewToolWindowFactory implements ToolWindowFactoryEx, DumbAware { +public class ProjectViewToolWindowFactory implements ToolWindowFactory, DumbAware { @Override public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) { ((ProjectViewImpl) ProjectView.getInstance(project)).setupImpl(toolWindow); diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java index cc198e18a140..7ae725e4ac62 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,8 +23,24 @@ import org.jetbrains.annotations.NotNull; * Performs lazy initialization of a toolwindow registered in plugin.xml. * * @author yole + * @author Konstantin Bulenkov * @see ToolWindowEP */ public interface ToolWindowFactory { void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow); + + /** + * Perform additional initialisation routine here + * @param window Tool Window + */ + default void init(ToolWindow window) {} + + /** + * Tool Window saves its state on project close and restore on when project opens + * In some cases, it is useful to postpone Tool Window activation until user explicitly activates it. + * Example: Tool Window initialisation takes huge amount of time and makes project loading slower. + * @return {@code true} if Tool Window should not be activated on start even if was opened previously. + * {@code false} otherwise. + */ + default boolean isDoNotActivateOnStart() {return false;} } diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactoryEx.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactoryEx.java index 2179adb0cefe..d5fbea89e151 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactoryEx.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactoryEx.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ package com.intellij.openapi.wm; /** * @author Dennis.Ushakov + * @deprecated use {@link ToolWindowFactory} */ public interface ToolWindowFactoryEx extends ToolWindowFactory { - void init(ToolWindow window); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java index c97831818eec..649fe18153ae 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -555,9 +555,7 @@ public final class ToolWindowImpl implements ToolWindowEx { public void setContentFactory(ToolWindowFactory contentFactory) { myContentFactory = contentFactory; - if (contentFactory instanceof ToolWindowFactoryEx) { - ((ToolWindowFactoryEx)contentFactory).init(this); - } + contentFactory.init(this); } public void ensureContentInitialized() { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java index ff006a1156e2..6de3fdc79d3f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -263,7 +263,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo myId = element.getAttributeValue(ID_ATTR); myWasRead = true; try { - myActive = Boolean.valueOf(element.getAttributeValue(ACTIVE_ATTR)).booleanValue(); + myActive = Boolean.valueOf(element.getAttributeValue(ACTIVE_ATTR)).booleanValue() && canActivateOnStart(myId); } catch (NumberFormatException ignored) { } @@ -283,7 +283,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo } catch (IllegalArgumentException ignored) { } - myVisible = Boolean.valueOf(element.getAttributeValue(VISIBLE_ATTR)).booleanValue(); + myVisible = Boolean.valueOf(element.getAttributeValue(VISIBLE_ATTR)).booleanValue() && canActivateOnStart(myId); if (element.getAttributeValue(SHOW_STRIPE_BUTTON) != null) { myShowStripeButton = Boolean.valueOf(element.getAttributeValue(SHOW_STRIPE_BUTTON)).booleanValue(); } @@ -319,6 +319,16 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo myContentUiType = ToolWindowContentUiType.getInstance(element.getAttributeValue(CONTENT_UI_ATTR)); } + private static boolean canActivateOnStart(String id) { + for (ToolWindowEP ep : ToolWindowEP.EP_NAME.getExtensions()) { + if (id.equals(ep.id)) { + ToolWindowFactory factory = ep.getToolWindowFactory(); + return !factory.isDoNotActivateOnStart(); + } + } + return true; + } + /** * Sets new anchor. */ From 2bf3aed68e31dac16b462e7fb6e002e35aa79b2d Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Wed, 31 Aug 2016 05:30:04 +0300 Subject: [PATCH 31/63] Intercept duplicate Languages at init and suggest disabling responsible plugin(s) This commit introduces ImplementationConflictException which is handled if logged as error. On handling, implementation classes are mapped to corresponding plugins. If there is at least one implementation class located in platform jars, the others have to be disabled. In other case, it is possible to leave one plugin (and thus its implementation) alive and try to restart. --- .../ImplementationConflictException.java | 44 ++++ .../src/com/intellij/lang/Language.java | 11 +- .../diagnostic/PluginConflictReporter.java | 66 +++++ .../errordialog/PluginConflictDialog.form | 40 +++ .../errordialog/PluginConflictDialog.java | 242 ++++++++++++++++++ .../src/com/intellij/idea/IdeaLogger.java | 6 + .../src/messages/DiagnosticBundle.properties | 5 + 7 files changed, 412 insertions(+), 2 deletions(-) create mode 100644 platform/core-api/src/com/intellij/diagnostic/ImplementationConflictException.java create mode 100644 platform/platform-impl/src/com/intellij/diagnostic/PluginConflictReporter.java create mode 100644 platform/platform-impl/src/com/intellij/diagnostic/errordialog/PluginConflictDialog.form create mode 100644 platform/platform-impl/src/com/intellij/diagnostic/errordialog/PluginConflictDialog.java diff --git a/platform/core-api/src/com/intellij/diagnostic/ImplementationConflictException.java b/platform/core-api/src/com/intellij/diagnostic/ImplementationConflictException.java new file mode 100644 index 000000000000..e9348739f3e4 --- /dev/null +++ b/platform/core-api/src/com/intellij/diagnostic/ImplementationConflictException.java @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.diagnostic; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class ImplementationConflictException extends RuntimeException { + + @NotNull + private final Collection> myConflictingClasses; + + public ImplementationConflictException(String message, Throwable cause, @NotNull Object ...implementationObjects) { + super(message, cause); + final List> classes = new ArrayList>(); + for (Object object : implementationObjects) { + classes.add(object.getClass()); + } + + myConflictingClasses = Collections.unmodifiableList(classes); + } + + @NotNull + public Collection> getConflictingClasses() { + return myConflictingClasses; + } +} diff --git a/platform/core-api/src/com/intellij/lang/Language.java b/platform/core-api/src/com/intellij/lang/Language.java index d941110520dc..829ef0973a54 100644 --- a/platform/core-api/src/com/intellij/lang/Language.java +++ b/platform/core-api/src/com/intellij/lang/Language.java @@ -15,6 +15,7 @@ */ package com.intellij.lang; +import com.intellij.diagnostic.ImplementationConflictException; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeRegistry; @@ -79,12 +80,18 @@ public abstract class Language extends UserDataHolderBase { Class langClass = getClass(); Language prev = ourRegisteredLanguages.put(langClass, this); if (prev != null) { - LOG.error("Language of '" + langClass + "' is already registered: " + prev); + LOG.error(new ImplementationConflictException("Language of '" + langClass + "' is already registered: " + prev, + null, + prev, + this)); return; } prev = ourRegisteredIDs.put(ID, this); if (prev != null) { - LOG.error("Language with ID '" + ID + "' is already registered: " + prev.getClass()); + LOG.error(new ImplementationConflictException("Language with ID '" + ID + "' is already registered: " + prev.getClass(), + null, + prev, + this)); } for (String mimeType : mimeTypes) { if (StringUtil.isEmpty(mimeType)) { diff --git a/platform/platform-impl/src/com/intellij/diagnostic/PluginConflictReporter.java b/platform/platform-impl/src/com/intellij/diagnostic/PluginConflictReporter.java new file mode 100644 index 000000000000..de6704382644 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/diagnostic/PluginConflictReporter.java @@ -0,0 +1,66 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.diagnostic; + +import com.intellij.diagnostic.errordialog.PluginConflictDialog; +import com.intellij.ide.plugins.cl.PluginClassLoader; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.extensions.PluginId; +import com.intellij.openapi.wm.WindowManager; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +public enum PluginConflictReporter { + INSTANCE; + + public void reportConflictByClasses(@NotNull Collection> conflictingClasses) { + final Set foundPlugins = new HashSet<>(); + boolean hasConflictWithPlatform = false; + + if (conflictingClasses.size() < 2) { + throw new IllegalArgumentException("The conflict should has been caused by at least two classes"); + } + + for (Class aClass : conflictingClasses) { + final ClassLoader classLoader = aClass.getClassLoader(); + if (classLoader instanceof PluginClassLoader) { + foundPlugins.add(((PluginClassLoader)classLoader).getPluginId()); + } + else { + hasConflictWithPlatform = true; + } + } + + if (foundPlugins.isEmpty()) { + Logger.getInstance(PluginConflictReporter.class).warn("The conflict has not come from PluginClassLoader"); + return; + } + + boolean finalHasConflictWithPlatform = hasConflictWithPlatform; + ApplicationManager.getApplication().invokeLater(() -> { + final JFrame frame = WindowManager.getInstance().findVisibleFrame(); + if (frame != null) { + new PluginConflictDialog(frame, new ArrayList<>(foundPlugins), finalHasConflictWithPlatform).show(); + } + }); + } +} diff --git a/platform/platform-impl/src/com/intellij/diagnostic/errordialog/PluginConflictDialog.form b/platform/platform-impl/src/com/intellij/diagnostic/errordialog/PluginConflictDialog.form new file mode 100644 index 000000000000..b9a7ed6e56c4 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/diagnostic/errordialog/PluginConflictDialog.form @@ -0,0 +1,40 @@ + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/errordialog/PluginConflictDialog.java b/platform/platform-impl/src/com/intellij/diagnostic/errordialog/PluginConflictDialog.java new file mode 100644 index 000000000000..011231a47a8b --- /dev/null +++ b/platform/platform-impl/src/com/intellij/diagnostic/errordialog/PluginConflictDialog.java @@ -0,0 +1,242 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.diagnostic.errordialog; + +import com.intellij.diagnostic.DiagnosticBundle; +import com.intellij.ide.plugins.IdeaPluginDescriptor; +import com.intellij.ide.plugins.PluginManager; +import com.intellij.ide.plugins.PluginManagerConfigurable; +import com.intellij.ide.plugins.PluginManagerCore; +import com.intellij.openapi.extensions.PluginId; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.components.JBLabel; +import com.intellij.ui.components.JBRadioButton; +import com.intellij.util.ui.JBEmptyBorder; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class PluginConflictDialog extends DialogWrapper { + public static final int WIDTH = 510; + + @NotNull + private final List myConflictingPlugins; + + private final boolean myIsConflictWithPlatform; + @Nullable + private final List myRadioButtons; + + private JPanel myContentPane; + + private JBLabel myTopMessageLabel; + + private JPanel myConflictingPluginsListPanel; + + private JBLabel myBottomMessageLabel; + + public PluginConflictDialog(@NotNull Component parent, + @NotNull List conflictingPlugins, + boolean isConflictWithPlatform) { + super(parent, false); + + myConflictingPlugins = conflictingPlugins; + myIsConflictWithPlatform = isConflictWithPlatform; + + if (myIsConflictWithPlatform) { + myRadioButtons = null; + } + else { + myRadioButtons = new ArrayList<>(); + } + + $$$setupUI$$$(); + setTitle(DiagnosticBundle.message("error.dialog.conflict.plugin.title")); + init(); + + myTopMessageLabel.setText(getTopMessageText(conflictingPlugins, isConflictWithPlatform)); + myBottomMessageLabel.setText(DiagnosticBundle.message("error.dialog.conflict.plugin.footer")); + + myTopMessageLabel.setPreferredSize(new Dimension(WIDTH, (int)myTopMessageLabel.getPreferredSize().getHeight())); + myContentPane.setPreferredSize(new Dimension(WIDTH, (int)myContentPane.getMinimumSize().getHeight())); + } + + private static String getTopMessageText(@NotNull List conflictingPlugins, boolean isConflictWithPlatform) { + final int pluginsNumber = conflictingPlugins.size(); + if (isConflictWithPlatform) { + return DiagnosticBundle.message("error.dialog.conflict.plugin.header.platform", pluginsNumber); + } + else { + final List names = conflictingPlugins.stream() + .map(PluginConflictDialog::getPluginNameOrId) + .map(s -> "" + s + "") + .collect(Collectors.toList()); + return DiagnosticBundle.message("error.dialog.conflict.plugin.header.each.other", + StringUtil.join(names.subList(0, pluginsNumber - 1), ", "), + names.get(pluginsNumber - 1)); + } + } + + private void $$$setupUI$$$() { + } + + @Nullable + @Override + protected JComponent createCenterPanel() { + return myContentPane; + } + + private void createUIComponents() { + final ButtonGroup buttonGroup = new ButtonGroup(); + + myConflictingPluginsListPanel = new JPanel(new GridLayout(0, 1)); + final List pluginDescriptions = myConflictingPlugins.stream() + .map(plugin -> getChooserPanelForPlugin(buttonGroup, plugin)) + .collect(Collectors.toList()); + + if (!myIsConflictWithPlatform) { + pluginDescriptions.add(0, getChooserPanelForPlugin(buttonGroup, null)); + } + + for (JPanel panel : pluginDescriptions) { + myConflictingPluginsListPanel.add(panel); + } + + setUpDefaultSelection(); + } + + @NotNull + private JPanel getChooserPanelForPlugin(@NotNull ButtonGroup buttonGroup, @Nullable PluginId plugin) { + final JPanel panel = new JPanel(new BorderLayout()); + if (!myIsConflictWithPlatform) { + assert myRadioButtons != null; + + final JBRadioButton radioButton = new JBRadioButton(); + myRadioButtons.add(radioButton); + buttonGroup.add(radioButton); + + panel.add(radioButton, BorderLayout.WEST); + panel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + radioButton.setSelected(true); + } + }); + } + + final JPanel descriptionPanel; + if (plugin != null) { + descriptionPanel = getPluginDescriptionPanel(plugin, !myIsConflictWithPlatform); + } + else { + descriptionPanel = getDisableAllPanel(); + } + descriptionPanel.setBorder(new JBEmptyBorder(10, myIsConflictWithPlatform ? 10 : 0, 10, 20)); + + panel.add(descriptionPanel, BorderLayout.CENTER); + return panel; + } + + private void setUpDefaultSelection() { + if (myIsConflictWithPlatform) { + return; + } + assert myRadioButtons != null && myRadioButtons.size() == myConflictingPlugins.size() + 1; + + for (int i = 0; i < myConflictingPlugins.size(); i++) { + final IdeaPluginDescriptor pluginDescriptor = PluginManager.getPlugin(myConflictingPlugins.get(i)); + if (pluginDescriptor != null + && (pluginDescriptor.isBundled() || StringUtil.equalsIgnoreCase(pluginDescriptor.getVendor(), "JetBrains"))) { + myRadioButtons.get(i).setSelected(true); + return; + } + } + myRadioButtons.get(myRadioButtons.size() - 1).setSelected(true); + } + + @NotNull + private static JPanel getPluginDescriptionPanel(@NotNull PluginId plugin, boolean addUseWord) { + final JPanel panel = new JPanel(new BorderLayout()); + + final IdeaPluginDescriptor pluginDescriptor = PluginManager.getPlugin(plugin); + if (pluginDescriptor == null) { + panel.add(new JBLabel(plugin.getIdString()), BorderLayout.CENTER); + return panel; + } + + final StringBuilder sb = new StringBuilder(""); + if (addUseWord) { + sb.append("Use "); + } + sb.append(pluginDescriptor.getName()); + if (pluginDescriptor.getVendor() != null) { + sb.append(" by ").append(pluginDescriptor.getVendor()); + } + sb.append(""); + panel.add(new JBLabel(sb.toString())); + return panel; + } + + @NotNull + private static String getPluginNameOrId(@NotNull PluginId pluginId) { + final IdeaPluginDescriptor pluginDescriptor = PluginManager.getPlugin(pluginId); + if (pluginDescriptor == null) { + return pluginId.getIdString(); + } + else { + return pluginDescriptor.getName(); + } + } + + @NotNull + private static JPanel getDisableAllPanel() { + final JPanel panel = new JPanel(new BorderLayout()); + panel.add(new JBLabel(DiagnosticBundle.message("error.dialog.conflict.plugin.disable.all"))); + return panel; + } + + @NotNull + @Override + protected Action getOKAction() { + return new DisableAction(); + } + + private class DisableAction extends DialogWrapperAction { + protected DisableAction() { + super(DiagnosticBundle.message("error.dialog.disable.plugin.action.disable")); + putValue(DEFAULT_ACTION, Boolean.TRUE); + } + + @Override + protected void doAction(ActionEvent e) { + for (int i = 0; i < myConflictingPlugins.size(); ++i) { + if (myRadioButtons == null || !myRadioButtons.get(i).isSelected()) { + PluginManagerCore.disablePlugin(myConflictingPlugins.get(i).getIdString()); + } + } + close(OK_EXIT_CODE); + PluginManagerConfigurable.shutdownOrRestartApp(""); + } + } +} diff --git a/platform/platform-impl/src/com/intellij/idea/IdeaLogger.java b/platform/platform-impl/src/com/intellij/idea/IdeaLogger.java index cbc22c5f149e..793f11e029f3 100644 --- a/platform/platform-impl/src/com/intellij/idea/IdeaLogger.java +++ b/platform/platform-impl/src/com/intellij/idea/IdeaLogger.java @@ -15,7 +15,9 @@ */ package com.intellij.idea; +import com.intellij.diagnostic.ImplementationConflictException; import com.intellij.diagnostic.LogMessageEx; +import com.intellij.diagnostic.PluginConflictReporter; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ex.ApplicationInfoEx; import com.intellij.openapi.application.impl.ApplicationImpl; @@ -123,6 +125,10 @@ public class IdeaLogger extends Log4jBasedLogger { } } + if (t instanceof ImplementationConflictException) { + PluginConflictReporter.INSTANCE.reportConflictByClasses(((ImplementationConflictException)t).getConflictingClasses()); + } + String detailString = StringUtil.join(details, "\n"); if (ourErrorsOccurred == null) { diff --git a/platform/platform-resources-en/src/messages/DiagnosticBundle.properties b/platform/platform-resources-en/src/messages/DiagnosticBundle.properties index e26b4ae549e3..e4c6d820b884 100644 --- a/platform/platform-resources-en/src/messages/DiagnosticBundle.properties +++ b/platform/platform-resources-en/src/messages/DiagnosticBundle.properties @@ -92,5 +92,10 @@ error.dialog.attachment.path.column.title=Path error.dialog.attachment.include.column.title=Include error.attachments.tab.title=Attachments error.dialog.filecontent.title=File content +error.dialog.conflict.plugin.title=Initialization Failure +error.dialog.conflict.plugin.header.platform=The following plugin{0,choice,1#|2#s} conflict{0,choice,1#s|2#} with IDE platform: +error.dialog.conflict.plugin.header.each.other=

The following plugins conflict with each other: {0} and {1}

+error.dialog.conflict.plugin.footer=It is highly recommended to resolve this conflict by disabling redundant plugins. +error.dialog.conflict.plugin.disable.all=Disable all diagnostic.error.report.include.attachment.warning=Report will include attachment: ''{0}''. diagnostic.error.report.include.attachments.warning=Report will include {0} attachments. From 1dc72618875c0b968db93767f5db44c9555eed29 Mon Sep 17 00:00:00 2001 From: fitermay Date: Wed, 31 Aug 2016 00:08:08 -0400 Subject: [PATCH 32/63] tab completions --- .../python/console/PydevConsoleRunner.java | 93 ++++++++++++++----- 1 file changed, 69 insertions(+), 24 deletions(-) diff --git a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java index 4fb4aefbf63b..ae7fc0841767 100644 --- a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java +++ b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java @@ -19,6 +19,7 @@ import com.google.common.base.CharMatcher; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.collect.Collections2; +import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.execution.ExecutionException; import com.intellij.execution.ExecutionHelper; import com.intellij.execution.Executor; @@ -40,11 +41,13 @@ import com.intellij.ide.errorTreeView.NewErrorTreeViewPanel; import com.intellij.internal.statistic.UsageTrigger; import com.intellij.lang.ASTNode; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.ex.ActionUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Caret; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.actionSystem.EditorAction; import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler; @@ -61,10 +64,7 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.Couple; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; @@ -164,7 +164,7 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory environmentVariables, @NotNull - PyConsoleOptions.PyConsoleSettings settingsProvider, + PyConsoleOptions.PyConsoleSettings settingsProvider, String... statementsToExecute) { super(project, consoleType.getTitle(), workingDir); mySdk = sdk; @@ -316,6 +316,7 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory ProgressManager.getInstance().run(new Task.Backgroundable(getProject(), "Connecting to Console", false) { - @Override - public void run(@NotNull final ProgressIndicator indicator) { - indicator.setText("Connecting to console..."); - try { - initAndRun(myStatementsToExecute); + UIUtil + .invokeLaterIfNeeded(() -> ProgressManager.getInstance().run(new Task.Backgroundable(getProject(), "Connecting to Console", false) { + @Override + public void run(@NotNull final ProgressIndicator indicator) { + indicator.setText("Connecting to console..."); + try { + initAndRun(myStatementsToExecute); + } + catch (final Exception e) { + LOG.warn("Error running console", e); + UIUtil.invokeAndWaitIfNeeded(new Runnable() { + @Override + public void run() { + showErrorsInConsole(e); + } + }); + } } - catch (final Exception e) { - LOG.warn("Error running console", e); - UIUtil.invokeAndWaitIfNeeded(new Runnable() { - @Override - public void run() { - showErrorsInConsole(e); - } - }); - } - } - })); + })); } private void showErrorsInConsole(Exception e) { @@ -564,7 +566,8 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory %d) on IDE side, " + - "port %d (=> %d) on pydevconsole.py side", myPorts[1], remotePorts.second, myPorts[0], remotePorts.first)); + "port %d (=> %d) on pydevconsole.py side", myPorts[1], remotePorts.second, myPorts[0], + remotePorts.first)); } myPydevConsoleCommunication = new PydevRemoteConsoleCommunication(getProject(), myPorts[0], remoteProcess, myPorts[1]); @@ -575,7 +578,8 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory Date: Wed, 31 Aug 2016 10:30:15 +0200 Subject: [PATCH 33/63] IDEA-160367 Settings Repository: login dialog should get focus when appears --- .../intellij/openapi/application/actions.kt | 15 +++++++++--- plugins/settings-repository/src/authForm.kt | 23 +++++++++---------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/application/actions.kt b/platform/platform-impl/src/com/intellij/openapi/application/actions.kt index 820f04dee7da..2188fe08777f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/actions.kt +++ b/platform/platform-impl/src/com/intellij/openapi/application/actions.kt @@ -38,12 +38,21 @@ inline fun runBatchUpdate(messageBus: MessageBus, runnable: () -> T): T { /** * @exclude Internal use only */ -fun invokeAndWaitIfNeed(runnable: () -> Unit) { +fun invokeAndWaitIfNeed(runnable: () -> T): T { val app = ApplicationManager.getApplication() if (app == null) { - if (SwingUtilities.isEventDispatchThread()) runnable() else SwingUtilities.invokeAndWait(runnable) + if (SwingUtilities.isEventDispatchThread()) { + return runnable() + } + else { + var result: T? = null + SwingUtilities.invokeAndWait { result = runnable() } + return result as T + } } else { - app.invokeAndWait(runnable, ModalityState.defaultModalityState()) + var result: T? = null + app.invokeAndWait({ result = runnable() }, ModalityState.defaultModalityState()) + return result as T } } \ No newline at end of file diff --git a/plugins/settings-repository/src/authForm.kt b/plugins/settings-repository/src/authForm.kt index 1e63bc57179a..5f9e85368785 100644 --- a/plugins/settings-repository/src/authForm.kt +++ b/plugins/settings-repository/src/authForm.kt @@ -21,13 +21,12 @@ import com.intellij.layout.* import com.intellij.layout.CCFlags.* import com.intellij.layout.LCFlags.* import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.invokeAndWaitIfNeed import com.intellij.openapi.ui.dialog -import com.intellij.openapi.util.Computable import com.intellij.ui.DocumentAdapter import com.intellij.util.PathUtilRt import com.intellij.util.nullize import com.intellij.util.trimMiddle -import com.intellij.util.ui.UIUtil import javax.swing.JPasswordField import javax.swing.JTextField import javax.swing.event.DocumentEvent @@ -38,16 +37,16 @@ fun showAuthenticationForm(credentials: Credentials?, uri: String, host: String? } val isGitHub = host == "github.com" - val note = if (sshKeyFile == null) icsMessage(if (isGitHub) "login.github.note" else "login.other.git.provider.note") else null - var username = credentials?.userName - if (username == null && isGitHub && path != null && sshKeyFile == null) { - val firstSlashIndex = path.indexOf('/', 1) - username = path.substring(1, if (firstSlashIndex == -1) path.length else firstSlashIndex) - } + val note = if (sshKeyFile == null) icsMessage(if (isGitHub) "login.github.note" else "login.other.git.provider.note") else null + var username = credentials?.userName + if (username == null && isGitHub && path != null && sshKeyFile == null) { + val firstSlashIndex = path.indexOf('/', 1) + username = path.substring(1, if (firstSlashIndex == -1) path.length else firstSlashIndex) + } - val message = if (sshKeyFile == null) icsMessage("log.in.to", uri.trimMiddle(50)) else icsMessage("enter.your.password.for.ssh.key", PathUtilRt.getFileName(sshKeyFile)) + val message = if (sshKeyFile == null) icsMessage("log.in.to", uri.trimMiddle(50)) else icsMessage("enter.your.password.for.ssh.key", PathUtilRt.getFileName(sshKeyFile)) - return UIUtil.invokeAndWaitIfNeeded(Computable { + return invokeAndWaitIfNeed { val userField = JTextField(username) val passwordField = JPasswordField(credentials?.password.toString()) @@ -69,7 +68,7 @@ fun showAuthenticationForm(credentials: Credentials?, uri: String, host: String? title = "Settings Repository", resizable = false, centerPanel = centerPanel, - preferedFocusComponent = userField, + preferedFocusComponent = if (userField.parent == null) passwordField else userField, okActionEnabled = false) passwordField.document.addDocumentListener(object : DocumentAdapter() { @@ -87,5 +86,5 @@ fun showAuthenticationForm(credentials: Credentials?, uri: String, host: String? else { null } - }) + } } \ No newline at end of file From 44cb0f2dc6e31736748e60dbdb056408e7664e77 Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 31 Aug 2016 11:26:59 +0300 Subject: [PATCH 34/63] build scripts: added descriptions of python plugins --- .../jetbrains/intellij/build/CommunityRepositoryModules.groovy | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy b/build/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy index 56199beed166..47a6c04b73fb 100644 --- a/build/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy +++ b/build/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy @@ -178,6 +178,7 @@ class CommunityRepositoryModules { plugin("course-creator"), plugin("course-creator-python"), plugin("ipnb"), - plugin("IntelliLang-python") + plugin("IntelliLang-python"), + plugin("python-rest") ] } \ No newline at end of file From 8a4c8e1c6349db5c63e715705373df8a5c77282e Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 31 Aug 2016 11:28:19 +0300 Subject: [PATCH 35/63] build scripts: compile all modules required to build searchable options --- .../org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy | 2 +- .../intellij/build/impl/DistributionJARsBuilder.groovy | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy b/build/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy index 81592affda5e..2a01f0f6ed23 100644 --- a/build/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy +++ b/build/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy @@ -84,7 +84,7 @@ class BuildTasksImpl extends BuildTasks { @Override void buildSearchableOptions(String targetModuleName, List modulesToIndex, List pathsToLicenses) { - buildSearchableOptions(new File(buildContext.projectBuilder.moduleOutput(buildContext.findModule(targetModuleName))), modulesToIndex, pathsToLicenses) + buildSearchableOptions(new File(buildContext.projectBuilder.moduleOutput(buildContext.findRequiredModule(targetModuleName))), modulesToIndex, pathsToLicenses) } //todo[nik] do we need 'cp' and 'jvmArgs' parameters? diff --git a/build/groovy/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.groovy b/build/groovy/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.groovy index 9df697b418b8..b7608e18ff81 100644 --- a/build/groovy/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.groovy +++ b/build/groovy/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.groovy @@ -146,7 +146,8 @@ class DistributionJARsBuilder { List getPlatformModules() { (platform.moduleJars.values() as List) + - ["java-runtime" /*required to build searchable options index*/, "updater"] + ["java-runtime", "platform-main", /*required to build searchable options index*/ + "updater", buildContext.productProperties.productLayout.mainModule] } From 6299da1ec85e5e7e6bea680ef944d782d97bd76f Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 31 Aug 2016 11:28:58 +0300 Subject: [PATCH 36/63] build scripts: 'icon-robots.txt' files excluded from jars --- .../jetbrains/intellij/build/impl/DistributionJARsBuilder.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/build/groovy/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.groovy b/build/groovy/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.groovy index b7608e18ff81..f0930d64183d 100644 --- a/build/groovy/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.groovy +++ b/build/groovy/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.groovy @@ -79,6 +79,7 @@ class DistributionJARsBuilder { exclude(name: "tips/**") exclude(name: "tips") exclude(name: "search/**") + exclude(name: "**/icon-robots.txt") } def productLayout = buildContext.productProperties.productLayout From 008f5dbd578c8ea5c9fc77c27e738f1acc92457a Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 31 Aug 2016 11:49:25 +0300 Subject: [PATCH 37/63] create project from sources: ignore *.java files under node_modules directory (IDEA-150380) --- .../projectWizard/importSources/JavaSourceRootDetector.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetector.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetector.java index f0259c79d5cb..800a82d71a05 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetector.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetector.java @@ -33,6 +33,10 @@ public abstract class JavaSourceRootDetector extends ProjectStructureDetector { @Override public DirectoryProcessingResult detectRoots(@NotNull File dir, @NotNull File[] children, @NotNull File base, @NotNull List result) { + if (dir.getName().equals("node_modules")) { + return DirectoryProcessingResult.SKIP_CHILDREN; + } + final String fileExtension = getFileExtension(); for (File child : children) { if (child.isFile() && FileUtilRt.extensionEquals(child.getName(), fileExtension)) { From d1f94e413696b5298932a49fc2247397b458946b Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 31 Aug 2016 08:51:21 +0200 Subject: [PATCH 38/63] cleanup some synonymous module content scopes, add javadoc to Module --- .../com/intellij/openapi/module/Module.java | 35 ++++++++++++++----- .../xml/ModuleContentRootSearchScope.java | 35 ++++--------------- 2 files changed, 32 insertions(+), 38 deletions(-) diff --git a/platform/core-api/src/com/intellij/openapi/module/Module.java b/platform/core-api/src/com/intellij/openapi/module/Module.java index 36c9bef94dc9..155d71eb9bdd 100644 --- a/platform/core-api/src/com/intellij/openapi/module/Module.java +++ b/platform/core-api/src/com/intellij/openapi/module/Module.java @@ -102,41 +102,58 @@ public interface Module extends ComponentManager, AreaInstance, Disposable { String getOptionValue(@NotNull String key); /** - * Returns module scope including sources and tests, excluding libraries and dependencies. - * - * @return scope including sources and tests, excluding libraries and dependencies. + * @return module scope including source and tests, excluding libraries and dependencies. */ @NotNull GlobalSearchScope getModuleScope(); + /** + * @param includeTests whether to include test source + * @return module scope including source and, optionally, tests, excluding libraries and dependencies. + */ @NotNull GlobalSearchScope getModuleScope(boolean includeTests); /** - * Returns module scope including sources, tests, and libraries, excluding dependencies. - * - * @return scope including sources, tests, and libraries, excluding dependencies. + * @return module scope including source, tests, and libraries, excluding dependencies. */ @NotNull GlobalSearchScope getModuleWithLibrariesScope(); /** - * Returns module scope including sources, tests, and dependencies, excluding libraries. - * - * @return scope including sources, tests, and dependencies, excluding libraries. + * @return module scope including source, tests, and dependencies, excluding libraries. */ @NotNull GlobalSearchScope getModuleWithDependenciesScope(); + /** + * @return a scope that includes everything in module content roots, without any dependencies or libraries + */ @NotNull GlobalSearchScope getModuleContentScope(); + + /** + * @return a scope that includes everything under the content roots of this module and its dependencies, with test source + */ @NotNull GlobalSearchScope getModuleContentWithDependenciesScope(); + /** + * @param includeTests whether test source and test dependencies should be included + * @return a scope including module source and dependencies with libraries + */ @NotNull GlobalSearchScope getModuleWithDependenciesAndLibrariesScope(boolean includeTests); + + /** + * @return a scope including everything under the content roots of this module and all modules that depend on it, directly or indirectly (via exported dependencies), excluding test source and resources + */ @NotNull GlobalSearchScope getModuleWithDependentsScope(); + + /** + * @return same as {@link #getModuleWithDependentsScope()}, but with test source/resources included + */ @NotNull GlobalSearchScope getModuleTestsWithDependentsScope(); @NotNull diff --git a/xml/dom-openapi/src/com/intellij/util/xml/ModuleContentRootSearchScope.java b/xml/dom-openapi/src/com/intellij/util/xml/ModuleContentRootSearchScope.java index 2b54b14d8564..8d5b065a699e 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/ModuleContentRootSearchScope.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/ModuleContentRootSearchScope.java @@ -15,39 +15,16 @@ */ package com.intellij.util.xml; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.module.Module; -import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.NotNull; +import com.intellij.psi.search.DelegatingGlobalSearchScope; -public class ModuleContentRootSearchScope extends GlobalSearchScope { - private final ModuleRootManager myRootManager; - private final Module myModule; +/** + * @deprecated use {@link Module#getModuleContentScope()} + */ +public class ModuleContentRootSearchScope extends DelegatingGlobalSearchScope { public ModuleContentRootSearchScope(final Module module) { - super(module.getProject()); - myRootManager = ModuleRootManager.getInstance(module); - myModule = module; + super(module.getModuleContentScope()); } - @Override - public boolean contains(@NotNull final VirtualFile file) { - return myRootManager.getFileIndex().isInContent(file); - } - - @Override - public int compare(@NotNull final VirtualFile file1, @NotNull final VirtualFile file2) { - return 0; - } - - @Override - public boolean isSearchInModuleContent(@NotNull final Module aModule) { - return aModule == myModule; - } - - @Override - public boolean isSearchInLibraries() { - return false; - } } From e2cb17e31785c88a4f1ac9a4fea031e1b7109cef Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 31 Aug 2016 10:37:45 +0200 Subject: [PATCH 39/63] don't complete java constructors where arrays are expected, render them more class-like (IDEA-CR-13383, IDEA-93584) --- .../JavaClassNameInsertHandler.java | 15 ++++----- .../completion/JavaCompletionUtil.java | 11 ++----- .../JavaConstructorCallElement.java | 33 +++++++++++++++---- .../completion/MemberLookupHelper.java | 11 ++++--- 4 files changed, 43 insertions(+), 27 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java index dcd1e597ae48..4026930f4e6f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java @@ -16,7 +16,6 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.AutoPopupController; -import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.ExpectedTypesProvider; import com.intellij.codeInsight.lookup.Lookup; import com.intellij.codeInsight.lookup.LookupElement; @@ -34,6 +33,7 @@ import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.javadoc.PsiDocTag; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import static com.intellij.psi.codeStyle.JavaCodeStyleSettings.*; @@ -159,18 +159,17 @@ class JavaClassNameInsertHandler implements InsertHandler info.getType() instanceof PsiArrayType); + } + private static boolean insertingAnnotation(InsertionContext context, LookupElement item) { final Object obj = item.getObject(); if (!(obj instanceof PsiClass) || !((PsiClass)obj).isAnnotationType()) return false; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index 725881849c26..b69f87c23522 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -528,10 +528,7 @@ public class JavaCompletionUtil { .accepts(reference), JavaClassNameInsertHandler.JAVA_CLASS_INSERT_HANDLER, Conditions.alwaysTrue()); - if (JavaClassNameCompletionContributor.AFTER_NEW.accepts(reference)) { - return JBIterable.from(classItems).flatMap(i -> JavaConstructorCallElement.wrap(i, reference.getElement())); - } - return classItems; + return JBIterable.from(classItems).flatMap(i -> JavaConstructorCallElement.wrap(i, reference.getElement())); } } @@ -544,11 +541,7 @@ public class JavaCompletionUtil { if (completion instanceof PsiClass) { JavaPsiClassReferenceElement classItem = JavaClassNameCompletionContributor.createClassLookupItem((PsiClass)completion, true).setSubstitutor(substitutor); - if (JavaClassNameCompletionContributor.AFTER_NEW.accepts(reference)) { - return JavaConstructorCallElement.wrap(classItem, reference.getElement()); - } - - return Collections.singletonList(classItem); + return JavaConstructorCallElement.wrap(classItem, reference.getElement()); } if (completion instanceof PsiMethod) { JavaMethodCallElement item = new JavaMethodCallElement((PsiMethod)completion).setQualifierSubstitutor(substitutor); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaConstructorCallElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaConstructorCallElement.java index f9e5fa120837..29bbd8b9b80a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaConstructorCallElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaConstructorCallElement.java @@ -20,7 +20,11 @@ import com.intellij.codeInsight.lookup.LookupElementDecorator; import com.intellij.codeInsight.lookup.LookupElementPresentation; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; +import com.intellij.psi.util.CachedValueProvider; +import com.intellij.psi.util.CachedValuesManager; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.containers.JBIterable; import org.jetbrains.annotations.NotNull; @@ -42,6 +46,10 @@ public class JavaConstructorCallElement extends JavaMethodCallElement { myType = type.get(); setQualifierSubstitutor(myType.resolveGenerics().getSubstitutor()); + markClassItemWrapped(classItem); + } + + private void markClassItemWrapped(@NotNull LookupElement classItem) { LookupElement delegate = classItem; while (true) { delegate.putUserData(WRAPPING_CONSTRUCTOR_CALL, this); @@ -65,19 +73,24 @@ public class JavaConstructorCallElement extends JavaMethodCallElement { @Override public void renderElement(LookupElementPresentation presentation) { myClassItem.renderElement(presentation); - String itemText = presentation.getItemText(); - super.renderElement(presentation); - presentation.setItemText(itemText); + String tailText = StringUtil.notNullize(presentation.getTailText()); + int genericsEnd = tailText.lastIndexOf('>') + 1; + + presentation.clearTail(); + presentation.appendTailText(tailText.substring(0, genericsEnd), false); + presentation.appendTailText(MemberLookupHelper.getMethodParameterString(getObject(), getSubstitutor()), false); + presentation.appendTailText(tailText.substring(genericsEnd), true); } - static List wrap(JavaPsiClassReferenceElement classItem, PsiElement position) { + static List wrap(@NotNull JavaPsiClassReferenceElement classItem, @NotNull PsiElement position) { PsiClass psiClass = classItem.getObject(); return wrap(classItem, psiClass, position, () -> JavaPsiFacade.getElementFactory(psiClass.getProject()).createType(psiClass, PsiSubstitutor.EMPTY)); } - static List wrap(LookupElement classItem, PsiClass psiClass, PsiElement position, Supplier type) { - if (Registry.is("java.completion.show.constructors") && JavaClassNameCompletionContributor.AFTER_NEW.accepts(position)) { + static List wrap(@NotNull LookupElement classItem, @NotNull PsiClass psiClass, + @NotNull PsiElement position, @NotNull Supplier type) { + if (Registry.is("java.completion.show.constructors") && isConstructorCallPlace(position)) { PsiMethod[] constructors = psiClass.getConstructors(); if (constructors.length > 0) { return JBIterable.of(constructors). @@ -89,6 +102,14 @@ public class JavaConstructorCallElement extends JavaMethodCallElement { return Collections.singletonList(classItem); } + private static boolean isConstructorCallPlace(@NotNull PsiElement position) { + return CachedValuesManager.getCachedValue(position, () -> { + boolean result = JavaClassNameCompletionContributor.AFTER_NEW.accepts(position) && + !JavaClassNameInsertHandler.isArrayTypeExpected(PsiTreeUtil.getParentOfType(position, PsiNewExpression.class)); + return CachedValueProvider.Result.create(result, position); + }); + } + static boolean isWrapped(LookupElement element) { return element.getUserData(WRAPPING_CONSTRUCTOR_CALL) != null; } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/MemberLookupHelper.java b/java/java-impl/src/com/intellij/codeInsight/completion/MemberLookupHelper.java index 6589f4a815e3..cd338c747c86 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/MemberLookupHelper.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/MemberLookupHelper.java @@ -20,6 +20,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.PsiFormatUtil; import com.intellij.psi.util.PsiFormatUtilBase; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; @@ -78,9 +79,7 @@ public class MemberLookupHelper { final String params = myMergedOverloads ? "(...)" : myMember instanceof PsiMethod - ? PsiFormatUtil.formatMethod((PsiMethod)myMember, substitutor, - PsiFormatUtilBase.SHOW_PARAMETERS, - PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_TYPE) + ? getMethodParameterString((PsiMethod)myMember, substitutor) : ""; presentation.clearTail(); presentation.appendTailText(params, false); @@ -96,5 +95,9 @@ public class MemberLookupHelper { } } - + @NotNull + static String getMethodParameterString(@NotNull PsiMethod method, @NotNull PsiSubstitutor substitutor) { + return PsiFormatUtil.formatMethod(method, substitutor, + PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_TYPE); + } } From 877358aea3bb24a8b7c862cf51555c31258ff16f Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 31 Aug 2016 11:30:14 +0200 Subject: [PATCH 40/63] java completion method call arg template: don't move to the next variable unless it's smart completion, cancel when implementing anonymous class, don't invoke when completing with smart enter --- .../completion/ConstructorInsertHandler.java | 7 +++++- .../completion/JavaMethodCallElement.java | 23 ++++++++++++++++--- .../JavaTemplateCompletionProcessor.java | 11 ++++++++- .../codeInsight/template/TemplateManager.java | 6 +++++ .../template/impl/TemplateManagerImpl.java | 10 ++++++++ 5 files changed, 52 insertions(+), 5 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java index b0dc386a4a57..d31afee0a899 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java @@ -7,7 +7,10 @@ import com.intellij.codeInsight.generation.OverrideImplementExploreUtil; import com.intellij.codeInsight.generation.OverrideImplementUtil; import com.intellij.codeInsight.generation.PsiGenerationInfo; import com.intellij.codeInsight.intention.impl.TypeExpression; -import com.intellij.codeInsight.lookup.*; +import com.intellij.codeInsight.lookup.Lookup; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupElementDecorator; +import com.intellij.codeInsight.lookup.PsiTypeLookupItem; import com.intellij.codeInsight.template.*; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.openapi.application.ApplicationManager; @@ -260,6 +263,8 @@ public class ConstructorInsertHandler implements InsertHandler { + TemplateManager.getInstance(project).finishTemplate(editor); + PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument()); final PsiAnonymousClass aClass = PsiTreeUtil.findElementOfClassAtOffset(file, editor.getCaretModel().getOffset(), PsiAnonymousClass.class, false); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java index 9a6925cf58fd..2c7275accd5e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java @@ -22,10 +22,15 @@ import com.intellij.codeInsight.template.Template; import com.intellij.codeInsight.template.TemplateManager; import com.intellij.codeInsight.template.impl.ConstantNode; import com.intellij.codeInsight.template.impl.MacroCallNode; +import com.intellij.codeInsight.template.impl.TemplateManagerImpl; +import com.intellij.codeInsight.template.impl.TemplateState; import com.intellij.codeInsight.template.macro.CompleteMacro; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.ClassConditionKey; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.java.LanguageLevel; @@ -170,7 +175,7 @@ public class JavaMethodCallElement extends LookupItem implements Type } } - if (hasParams && Registry.is("java.completion.argument.live.template")) { + if (hasParams && context.getCompletionChar() != Lookup.COMPLETE_STATEMENT_SELECT_CHAR && Registry.is("java.completion.argument.live.template")) { startArgumentLiveTemplate(context, method); } } @@ -187,7 +192,8 @@ public class JavaMethodCallElement extends LookupItem implements Type qualifyMethodCall(file, startOffset, document); } - private static void startArgumentLiveTemplate(InsertionContext context, PsiMethod method) { + public static final Key ARGUMENT_TEMPLATE_ACTIVE = Key.create("ARGUMENT_TEMPLATE_ACTIVE"); + private void startArgumentLiveTemplate(InsertionContext context, PsiMethod method) { TemplateManager manager = TemplateManager.getInstance(method.getProject()); Template template = manager.createTemplate("", ""); PsiParameter[] parameters = method.getParameterList().getParameters(); @@ -199,7 +205,18 @@ public class JavaMethodCallElement extends LookupItem implements Type template.addVariable(name, new MacroCallNode(new CompleteMacro()), new ConstantNode(name), true); } - manager.startTemplate(context.getEditor(), template); + Editor editor = context.getEditor(); + manager.startTemplate(editor, template); + + TemplateState templateState = TemplateManagerImpl.getTemplateState(editor); + if (templateState == null) return; + + editor.putUserData(ARGUMENT_TEMPLATE_ACTIVE, this); + Disposer.register(templateState, () -> { + if (editor.getUserData(ARGUMENT_TEMPLATE_ACTIVE) == this) { + editor.putUserData(ARGUMENT_TEMPLATE_ACTIVE, null); + } + }); } private boolean shouldInsertTypeParameters() { diff --git a/java/java-impl/src/com/intellij/codeInsight/template/macro/JavaTemplateCompletionProcessor.java b/java/java-impl/src/com/intellij/codeInsight/template/macro/JavaTemplateCompletionProcessor.java index 75d4d7ec2cde..06491b964227 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/macro/JavaTemplateCompletionProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/macro/JavaTemplateCompletionProcessor.java @@ -16,10 +16,13 @@ package com.intellij.codeInsight.template.macro; import com.intellij.codeInsight.completion.JavaCompletionUtil; +import com.intellij.codeInsight.completion.JavaMethodCallElement; +import com.intellij.codeInsight.completion.SmartCompletionDecorator; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.template.ExpressionContext; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.ClassConditionKey; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiPackage; import java.util.List; @@ -34,6 +37,12 @@ public class JavaTemplateCompletionProcessor implements TemplateCompletionProces if (elements != null && elements.size() == 1 && elements.get(0) instanceof PsiPackage) { return false; } + + Editor editor = context.getEditor(); + if (editor != null && editor.getUserData(JavaMethodCallElement.ARGUMENT_TEMPLATE_ACTIVE) != null) { + return item.as(ClassConditionKey.create(SmartCompletionDecorator.class)) != null; + } + return true; } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateManager.java b/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateManager.java index b4d905848c2c..ffe46825d84b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateManager.java @@ -56,4 +56,10 @@ public abstract class TemplateManager { @Nullable public abstract Template getActiveTemplate(@NotNull Editor editor); + + /** + * Finished a live template in the given editor, if it's present + * @return whether a live template was present + */ + public abstract boolean finishTemplate(@NotNull Editor editor); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.java index 64d7fe640fd5..6f5e4f455133 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.java @@ -521,6 +521,16 @@ public class TemplateManagerImpl extends TemplateManager implements Disposable { return templateState != null ? templateState.getTemplate() : null; } + @Override + public boolean finishTemplate(@NotNull Editor editor) { + TemplateState state = getTemplateState(editor); + if (state != null) { + state.gotoEnd(); + return true; + } + return false; + } + public static boolean isApplicable(PsiFile file, int offset, TemplateImpl template) { return isApplicable(template, getApplicableContextTypes(file, offset)); } From 950322165f5ae3ffcb9c7704c83984b9fe970a1c Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 31 Aug 2016 12:43:54 +0300 Subject: [PATCH 41/63] IDEA-70913 smart step into should not propose methods from both branches in conditional expressions - support if statement --- .../actions/JavaSmartStepIntoHandler.java | 40 +++++++++++++------ .../debugger/engine/DebuggerUtils.java | 7 +++- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java index 883b0b8427c6..0d46f2fba155 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java @@ -201,28 +201,42 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler { } } + @Override + public void visitIfStatement(PsiIfStatement statement) { + visitConditional(statement.getCondition(), statement.getThenBranch(), statement.getElseBranch()); + } + @Override public void visitConditionalExpression(PsiConditionalExpression expression) { - PsiExpression condition = expression.getCondition(); - condition.accept(this); - ThreeState conditionRes = ThreeState.UNSURE; - if (!DebuggerUtils.hasSideEffects(condition)) { + visitConditional(expression.getCondition(), expression.getThenExpression(), expression.getElseExpression()); + } + + private void visitConditional(@Nullable PsiElement condition, + @Nullable PsiElement thenBranch, + @Nullable PsiElement elseBranch) { + if (condition != null) { + condition.accept(this); + } + ThreeState conditionRes = evaluateCondition(condition); + if (conditionRes != ThreeState.NO && thenBranch != null) { + thenBranch.accept(this); + } + if (conditionRes != ThreeState.YES && elseBranch != null) { + elseBranch.accept(this); + } + } + + private ThreeState evaluateCondition(@Nullable PsiElement condition) { + if (condition != null && !DebuggerUtils.hasSideEffects(condition)) { try { ExpressionEvaluator evaluator = EvaluatorBuilderImpl.getInstance().build(condition, position); - conditionRes = ThreeState.fromBoolean(DebuggerUtilsEx.evaluateBoolean(evaluator, debuggerContext.createEvaluationContext())); + return ThreeState.fromBoolean(DebuggerUtilsEx.evaluateBoolean(evaluator, debuggerContext.createEvaluationContext())); } catch (EvaluateException e) { LOG.info(e); } } - PsiExpression thenExpression = expression.getThenExpression(); - if (conditionRes != ThreeState.NO && thenExpression != null) { - thenExpression.accept(this); - } - PsiExpression elseExpression = expression.getElseExpression(); - if (conditionRes != ThreeState.YES && elseExpression != null) { - elseExpression.accept(this); - } + return ThreeState.UNSURE; } @Override diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java b/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java index 2f382f0ca80f..f81fee187349 100644 --- a/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java +++ b/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java @@ -423,11 +423,14 @@ public abstract class DebuggerUtils { } } - public static boolean hasSideEffects(PsiElement element) { + public static boolean hasSideEffects(@Nullable PsiElement element) { return hasSideEffectsOrReferencesMissingVars(element, null); } - public static boolean hasSideEffectsOrReferencesMissingVars(PsiElement element, @Nullable final Set visibleLocalVariables) { + public static boolean hasSideEffectsOrReferencesMissingVars(@Nullable PsiElement element, @Nullable final Set visibleLocalVariables) { + if (element == null) { + return false; + } final Ref rv = new Ref<>(Boolean.FALSE); element.accept(new JavaRecursiveElementWalkingVisitor() { @Override From 9a0b394f0be12159137f1c7f9b99e6492decc2e5 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 31 Aug 2016 13:12:16 +0300 Subject: [PATCH 42/63] IDEA-160474 File Templates: 'Enable Live Templates' checkbox is cleared on restart --- .../ide/fileTemplates/impl/FileTemplateSettings.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateSettings.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateSettings.java index 3a93d1a617f5..b6e96738bded 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateSettings.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateSettings.java @@ -52,7 +52,7 @@ public class FileTemplateSettings extends FileTemplatesLoader implements Persist @Nullable @Override public Element getState() { - Element element = null; + Element element = new Element("fileTemplateSettings"); for (FTManager manager : getAllManagers()) { Element templatesGroup = null; for (FileTemplateBase template : manager.getAllTemplates(true)) { @@ -75,9 +75,6 @@ public class FileTemplateSettings extends FileTemplatesLoader implements Persist if (templatesGroup == null) { templatesGroup = new Element(getXmlElementGroupName(manager)); - if (element == null) { - element = new Element("fileTemplateSettings"); - } element.addContent(templatesGroup); } templatesGroup.addContent(templateElement); From 674b735b95b1d9ec2a55aab18685caac0f133fd9 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Wed, 31 Aug 2016 13:15:51 +0300 Subject: [PATCH 43/63] git: annotations - remove duplicated `getCurrentRevision` request --- .../src/git4idea/annotate/GitAnnotationProvider.java | 5 +++-- .../git4idea/src/git4idea/annotate/GitFileAnnotation.java | 7 +++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java b/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java index 2eb5b138dd8b..e3ea1dc6003c 100644 --- a/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java +++ b/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java @@ -129,12 +129,13 @@ public class GitAnnotationProvider implements AnnotationProviderEx { assert vcs != null; VcsRevisionNumber actualRevision = revision != null ? revision : vcs.getDiffProvider().getCurrentRevision(file); + if (actualRevision != null) { Object annotatedData = myCache.get(repositoryFilePath, GitVcs.getKey(), actualRevision); - if (annotatedData instanceof CachedData) return restoreFromCache(file, revision, (CachedData)annotatedData); + if (annotatedData instanceof CachedData) return restoreFromCache(file, actualRevision, (CachedData)annotatedData); } - GitFileAnnotation fileAnnotation = doAnnotate(repositoryFilePath, revision, file); + GitFileAnnotation fileAnnotation = doAnnotate(repositoryFilePath, actualRevision, file); if (actualRevision != null) { myCache.put(repositoryFilePath, GitVcs.getKey(), actualRevision, cacheData(fileAnnotation)); diff --git a/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java b/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java index 8ca02c145245..93bb1f47168f 100644 --- a/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java +++ b/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java @@ -73,16 +73,15 @@ public class GitFileAnnotation extends FileAnnotation { } }; - public GitFileAnnotation(@NotNull final Project project, + public GitFileAnnotation(@NotNull Project project, @NotNull VirtualFile file, - @Nullable final VcsRevisionNumber revision, + @Nullable VcsRevisionNumber revision, @NotNull List lines) { super(project); myProject = project; myFile = file; myVcs = ObjectUtils.assertNotNull(GitVcs.getInstance(myProject)); - myBaseRevision = revision == null ? (myVcs.getDiffProvider().getCurrentRevision(file)) : revision; - + myBaseRevision = revision; myLines = lines; } From 99317a5de7ff8495e03b2ea4856edda545826607 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Wed, 31 Aug 2016 13:28:53 +0300 Subject: [PATCH 44/63] IDEA-58417 vcs: enable "annotate previous revision" action for locally modified files it was broken in a7c864a --- .../openapi/vcs/actions/AnnotateCurrentRevisionAction.java | 2 ++ .../openapi/vcs/actions/AnnotatePreviousRevisionAction.java | 2 ++ .../intellij/openapi/vcs/actions/AnnotateRevisionAction.java | 3 +-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateCurrentRevisionAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateCurrentRevisionAction.java index 0103ef58d28f..65bff2ce30fc 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateCurrentRevisionAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateCurrentRevisionAction.java @@ -30,6 +30,8 @@ class AnnotateCurrentRevisionAction extends AnnotateRevisionAction { @Override protected VcsFileRevision getRevision(int lineNumber) { assert myProvider != null; + + if (lineNumber < 0 || lineNumber >= myAnnotation.getLineCount()) return null; return myProvider.getRevision(lineNumber); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotatePreviousRevisionAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotatePreviousRevisionAction.java index dba8837c48da..248be76a3a2e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotatePreviousRevisionAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotatePreviousRevisionAction.java @@ -31,10 +31,12 @@ class AnnotatePreviousRevisionAction extends AnnotateRevisionAction { @Override protected VcsFileRevision getRevision(int lineNumber) { assert myProvider != null; + if (lineNumber == UpToDateLineNumberProvider.ABSENT_LINE_NUMBER) { return myProvider.getLastRevision(); } else { + if (lineNumber < 0 || lineNumber >= myAnnotation.getLineCount()) return null; return myProvider.getPreviousRevision(lineNumber); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionAction.java index c51fb9d2e9d3..7bf3ce4c9f00 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionAction.java @@ -23,7 +23,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; abstract class AnnotateRevisionAction extends AnnotateRevisionActionBase implements DumbAware, UpToDateLineNumberListener { - @NotNull private final FileAnnotation myAnnotation; + @NotNull protected final FileAnnotation myAnnotation; @NotNull private final AbstractVcs myVcs; private int currentLine; @@ -83,7 +83,6 @@ abstract class AnnotateRevisionAction extends AnnotateRevisionActionBase impleme @Nullable @Override protected VcsFileRevision getFileRevision(@NotNull AnActionEvent e) { - if (currentLine < 0 || currentLine >= myAnnotation.getLineCount()) return null; return getRevision(currentLine); } From 354fb0656363c11d38a1988b28c3766fde8fc61b Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 31 Aug 2016 13:53:25 +0300 Subject: [PATCH 45/63] junit: check return type of junit 3 tests --- .../impl/src/com/intellij/execution/junit/JUnitUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java b/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java index 399c004e1e14..e6baf6ba00a5 100644 --- a/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java +++ b/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java @@ -112,7 +112,7 @@ public class JUnitUtil { if (psiMethod.hasModifierProperty(PsiModifier.STATIC) && SUITE_METHOD_NAME.equals(psiMethod.getName())) return false; if (!psiMethod.getName().startsWith("test")) return false; PsiClass testCaseClass = getTestCaseClassOrNull(location); - return testCaseClass != null && psiMethod.getContainingClass().isInheritor(testCaseClass, true); + return testCaseClass != null && psiMethod.getContainingClass().isInheritor(testCaseClass, true) && PsiType.VOID.equals(psiMethod.getReturnType()); } public static boolean isTestCaseInheritor(final PsiClass aClass) { From 3e2d4eac6e5eedfa8a3d6324e9d2586bdda2e49c Mon Sep 17 00:00:00 2001 From: Pavel Dolgov Date: Wed, 31 Aug 2016 14:29:40 +0300 Subject: [PATCH 46/63] Javafx: Reduced search scope when looking for FXML controller class (simplified, because the effective scope is applied anyway) (IDEA-160386) --- .../src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java index 4cf4e9310146..290a395fcdfc 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java @@ -1198,7 +1198,7 @@ public class JavaFxPsiUtil { if (type != null && type.equalsToText(JavaFxCommonNames.JAVAFX_FXML_FXMLLOADER)) { final PsiElement parent = expression.getParent(); if (parent instanceof PsiLocalVariable) { - ReferencesSearch.search(parent, parent.getUseScope()).forEach(processor); + ReferencesSearch.search(parent).forEach(processor); final PsiClass controller = injectedController.get(); if (controller != null) { return false; From 3b4a68c6f9ad3920644d410397d558cf4847ad80 Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 31 Aug 2016 11:31:09 +0300 Subject: [PATCH 47/63] pycharm build scripts rewritten --- .../WindowsDistributionCustomizer.groovy | 2 +- .../pycharm/PyCharmCommunityBuilder.groovy | 43 ++ .../pycharm/PyCharmCommunityProperties.groovy | 116 +++++ .../PyCharmMacDistributionCustomizer.groovy | 54 +++ .../pycharm/PyCharmPropertiesBase.groovy | 73 ++++ ...yCharmWindowsDistributionCustomizer.groovy | 54 +++ python/build/paths.nsi | 6 - python/build/plugin-list.txt | 8 - .../pycharm64_community_launcher.properties | 11 - python/build/pycharm_community_build.gant | 409 +----------------- .../pycharm_community_launcher.properties | 11 - python/build/python-community-build.iml | 6 +- .../resources/{PC_instCom.ico => install.ico} | Bin python/build/resources/pycharm_inst.ico | Bin 26694 -> 0 bytes python/build/resources/pycharm_uninst.ico | Bin 26694 -> 0 bytes .../{PC_uninstCom.ico => uninstall.ico} | Bin python/build/strings.nsi | 16 - .../pycharm/edu/PyCharmEduProperties.groovy | 69 +-- .../build/pycharm_edu_build.gant | 1 + .../build/python-edu-build.iml | 1 + 20 files changed, 369 insertions(+), 511 deletions(-) create mode 100644 python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmCommunityBuilder.groovy create mode 100644 python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmCommunityProperties.groovy create mode 100644 python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmMacDistributionCustomizer.groovy create mode 100644 python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmPropertiesBase.groovy create mode 100644 python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmWindowsDistributionCustomizer.groovy delete mode 100644 python/build/paths.nsi delete mode 100644 python/build/pycharm64_community_launcher.properties delete mode 100644 python/build/pycharm_community_launcher.properties rename python/build/resources/{PC_instCom.ico => install.ico} (100%) delete mode 100644 python/build/resources/pycharm_inst.ico delete mode 100644 python/build/resources/pycharm_uninst.ico rename python/build/resources/{PC_uninstCom.ico => uninstall.ico} (100%) delete mode 100644 python/build/strings.nsi diff --git a/build/groovy/org/jetbrains/intellij/build/WindowsDistributionCustomizer.groovy b/build/groovy/org/jetbrains/intellij/build/WindowsDistributionCustomizer.groovy index 8302320628e9..d7316081fb6e 100644 --- a/build/groovy/org/jetbrains/intellij/build/WindowsDistributionCustomizer.groovy +++ b/build/groovy/org/jetbrains/intellij/build/WindowsDistributionCustomizer.groovy @@ -78,7 +78,7 @@ abstract class WindowsDistributionCustomizer { /** * The returned name will be used to create links on Desktop */ - String fullNameIncludingEditionAndVendor(ApplicationInfoProperties applicationInfo) { applicationInfo.shortCompanyName + " " + applicationInfo.productName } + String fullNameIncludingEditionAndVendor(ApplicationInfoProperties applicationInfo) { applicationInfo.shortCompanyName + " " + fullNameIncludingEdition(applicationInfo) } String uninstallFeedbackPageUrl(ApplicationInfoProperties applicationInfo) { return null diff --git a/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmCommunityBuilder.groovy b/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmCommunityBuilder.groovy new file mode 100644 index 000000000000..f8deb6206539 --- /dev/null +++ b/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmCommunityBuilder.groovy @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.intellij.build.pycharm + +import org.codehaus.gant.GantBinding +import org.jetbrains.intellij.build.BuildContext +import org.jetbrains.intellij.build.BuildTasks +import org.jetbrains.intellij.build.JetBrainsBuildTools + +/** + * @author nik + */ +class PyCharmCommunityBuilder { + private final GantBinding binding + private final String home + + PyCharmCommunityBuilder(String home, GantBinding binding) { + this.home = home + this.binding = binding + } + + def build() { + def buildContext = BuildContext.createContext(binding.ant, binding.projectBuilder, binding.project, binding.global, + "$home/community", home, "$home/out/pycharmCE", new PyCharmCommunityProperties(home), + JetBrainsBuildTools.create("$home/build/lib/jet-sign.jar")) + def buildTasks = BuildTasks.create(buildContext) + buildTasks.compileModulesAndBuildDistributions() + buildTasks.zipProjectSources() + } +} \ No newline at end of file diff --git a/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmCommunityProperties.groovy b/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmCommunityProperties.groovy new file mode 100644 index 000000000000..1e9b0aa55cc6 --- /dev/null +++ b/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmCommunityProperties.groovy @@ -0,0 +1,116 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.intellij.build.pycharm + +import org.jetbrains.intellij.build.* + +/** + * @author nik + */ +class PyCharmCommunityProperties extends PyCharmPropertiesBase { + PyCharmCommunityProperties(String home) { + super(home) + productCode = "PC" + platformPrefix = "PyCharmCore" + applicationInfoModule = "python-community-ide-resources" + brandingResourcePaths = ["$home/community/python/resources"] + + productLayout.platformApiModules = CommunityRepositoryModules.PLATFORM_API_MODULES + ["dom-openapi"] + productLayout.platformImplementationModules = CommunityRepositoryModules.PLATFORM_IMPLEMENTATION_MODULES + [ + "dom-impl", "python-community", "python-community-ide-resources", + "python-ide-community", "python-community-configure", "python-openapi", "python-psi-api", "platform-main" + ] + productLayout.bundledPluginModules = new File("$home/community/python/build/plugin-list.txt").readLines() + productLayout.mainModule = "main_pycharm_ce" + } + + @Override + void copyAdditionalFiles(BuildContext context, String targetDirectory) { + super.copyAdditionalFiles(context, targetDirectory) + context.ant.copy(todir: "$targetDirectory/license") { + fileset(file: "$context.paths.communityHome/LICENSE.txt") + fileset(file: "$context.paths.communityHome/NOTICE.txt") + } + } + + @Override + String systemSelector(ApplicationInfoProperties applicationInfo) { + "PyCharmCE${applicationInfo.majorVersion}.${applicationInfo.minorVersionMainPart}" + } + + @Override + String baseArtifactName(ApplicationInfoProperties applicationInfo, String buildNumber) { + "pycharmPC-$buildNumber" + } + + @Override + WindowsDistributionCustomizer createWindowsCustomizer(String projectHome) { + return new PyCharmWindowsDistributionCustomizer() { + { + buildZipWithBundledOracleJre = true + installerImagesPath = "$projectHome/community/python/build/resources" + fileAssociations = [".py"] + } + + @Override + String fullNameIncludingEdition(ApplicationInfoProperties applicationInfo) { + "PyCharm Community Edition" + } + + @Override + void copyAdditionalFiles(BuildContext context, String targetDirectory) { + super.copyAdditionalFiles(context, targetDirectory) + context.ant.copy(file: "$context.paths.projectHome/python/help/pycharmhelp.jar", todir: "$targetDirectory/help", failonerror: false) + } + } + } + + @Override + LinuxDistributionCustomizer createLinuxCustomizer(String projectHome) { + return new LinuxDistributionCustomizer() { + { + iconPngPath = "$projectHome/community/python/resources/PyCharmCore128.png" + } + @Override + String rootDirectoryName(ApplicationInfoProperties applicationInfo, String buildNumber) { + "pycharm-community-${applicationInfo.isEAP ? buildNumber : applicationInfo.fullVersion}" + } + + @Override + void copyAdditionalFiles(BuildContext context, String targetDirectory) { + context.ant.copy(file: "$context.paths.projectHome/python/help/pycharmhelp.jar", todir: "$targetDirectory/help", failonerror: false) + } + } + } + + @Override + MacDistributionCustomizer createMacCustomizer(String projectHome) { + return new PyCharmMacDistributionCustomizer() { + { + icnsPath = "$projectHome/community/python/resources/PyCharmCore.icns" + bundleIdentifier = "com.jetbrains.pycharm" + helpId = "PY" + dmgImagePath = "$projectHome/community/python/build/DMG_background.png" + } + + @Override + String rootDirectoryName(ApplicationInfoProperties applicationInfo, String buildNumber) { + String suffix = applicationInfo.isEAP ? " ${applicationInfo.majorVersion}.${applicationInfo.minorVersion} EAP" : "" + "PyCharm CE${suffix}.app" + } + } + } +} \ No newline at end of file diff --git a/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmMacDistributionCustomizer.groovy b/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmMacDistributionCustomizer.groovy new file mode 100644 index 000000000000..57a8b3a0c1f9 --- /dev/null +++ b/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmMacDistributionCustomizer.groovy @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.intellij.build.pycharm + +import org.jetbrains.intellij.build.ApplicationInfoProperties +import org.jetbrains.intellij.build.BuildContext +import org.jetbrains.intellij.build.MacDistributionCustomizer + +/** + * @author nik + */ +class PyCharmMacDistributionCustomizer extends MacDistributionCustomizer { + @Override + void copyAdditionalFiles(BuildContext context, String targetDirectory) { + context.ant.copy(todir: "$targetDirectory/skeletons") { + fileset(dir: "$context.paths.projectHome/community/python/skeletons") { + include(name: "skeletons-mac*.zip") + } + } + } + + @Override + Map customIdeaProperties(ApplicationInfoProperties applicationInfo) { + ["ide.mac.useNativeClipboard": "false"] + } +} diff --git a/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmPropertiesBase.groovy b/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmPropertiesBase.groovy new file mode 100644 index 000000000000..934febae1d72 --- /dev/null +++ b/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmPropertiesBase.groovy @@ -0,0 +1,73 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.intellij.build.pycharm + +import org.jetbrains.intellij.build.ApplicationInfoProperties +import org.jetbrains.intellij.build.BuildContext +import org.jetbrains.intellij.build.BuildTasks +import org.jetbrains.intellij.build.MacDistributionCustomizer +import org.jetbrains.intellij.build.ProductProperties +import org.jetbrains.intellij.build.WindowsDistributionCustomizer + +/** + * @author nik + */ +abstract class PyCharmPropertiesBase extends ProductProperties { + PyCharmPropertiesBase(String home) { + baseFileName = "pycharm" + additionalIDEPropertiesFilePaths = ["$home/build/conf/ideaJNC.properties"] + reassignAltClickToMultipleCarets = true + productLayout.mainJarName = "pycharm.jar" + productLayout.additionalPlatformJars.put("pycharm-pydev.jar", "python-pydev") + additionalDirectoriesWithLicenses = ["$home/python/license"] + } + + @Override + void copyAdditionalFiles(BuildContext context, String targetDirectory) { + def tasks = BuildTasks.create(context) + tasks.zipSourcesOfModules(["python-pydev"], "$targetDirectory/lib/src/pycharm-pydev-src.zip") + tasks.zipSourcesOfModules(["python-openapi", "python-psi-api"], "$targetDirectory/lib/src/pycharm-openapi-src.zip") + + context.ant.copy(todir: "$targetDirectory/helpers") { + fileset(dir: "$context.paths.projectHome/community/python/helpers") + } + context.ant.copy(todir: "$targetDirectory/help") { + fileset(dir: "$context.paths.projectHome/python/help") { + include(name: "*.pdf") + } + } + } + + @Override + String environmentVariableBaseName(ApplicationInfoProperties applicationInfo) { + "PYCHARM" + } +} \ No newline at end of file diff --git a/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmWindowsDistributionCustomizer.groovy b/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmWindowsDistributionCustomizer.groovy new file mode 100644 index 000000000000..8a229400c594 --- /dev/null +++ b/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmWindowsDistributionCustomizer.groovy @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.intellij.build.pycharm + +import org.jetbrains.intellij.build.ApplicationInfoProperties +import org.jetbrains.intellij.build.BuildContext +import org.jetbrains.intellij.build.WindowsDistributionCustomizer + +/** + * @author nik + */ +class PyCharmWindowsDistributionCustomizer extends WindowsDistributionCustomizer { + @Override + void copyAdditionalFiles(BuildContext context, String targetDirectory) { + context.ant.copy(todir: "$targetDirectory/skeletons") { + fileset(dir: "$context.paths.projectHome/community/python/skeletons") { + include(name: "skeletons-win*.zip") + } + } + } + + @Override + String rootDirectoryName(ApplicationInfoProperties applicationInfo, String buildNumber) { + "" + } +} diff --git a/python/build/paths.nsi b/python/build/paths.nsi deleted file mode 100644 index 3f8b0a427865..000000000000 --- a/python/build/paths.nsi +++ /dev/null @@ -1,6 +0,0 @@ -; Installer images -!define IMAGES_LOCATION "${COMMUNITY_DIR}\python\build\resources" -;!define LICENSE_FILE "${BASE_DIR}\python\license\PyCharm_Preview_License" -!define PRODUCT_PROPERTIES_FILE "${BASE_DIR}\out\pycharmCE\layout\bin\idea.properties" -!define PRODUCT_VM_OPTIONS_NAME pycharm*.exe.vmoptions -!define PRODUCT_VM_OPTIONS_FILE "${BASE_DIR}\out\pycharmCE\win\bin\${PRODUCT_VM_OPTIONS_NAME}" diff --git a/python/build/plugin-list.txt b/python/build/plugin-list.txt index 5da4136c5bea..85dc46bf17d1 100644 --- a/python/build/plugin-list.txt +++ b/python/build/plugin-list.txt @@ -1,21 +1,13 @@ -cvsIntegration -cvs-core cvs-plugin -javacvs-src -smartcvs-src svn4idea git4idea remote-servers-git hg4idea -tasks tasks-core -tasks-api -jira github terminal IntelliLang IntelliLang-xml -IntelliLang-js IntelliLang-python rest python-rest diff --git a/python/build/pycharm64_community_launcher.properties b/python/build/pycharm64_community_launcher.properties deleted file mode 100644 index 3453c65d52e6..000000000000 --- a/python/build/pycharm64_community_launcher.properties +++ /dev/null @@ -1,11 +0,0 @@ -IDS_JDK_ENV_VAR=PYCHARM_JDK_64 -IDS_JDK_ONLY=true -IDS_APP_TITLE=__IDE-NAME__ Launcher -IDS_VM_OPTIONS_PATH=%USERPROFILE%\\.__PRODUCT_PATHS_SELECTOR__ -IDS_VM_OPTION_ERRORFILE=-XX:ErrorFile=%USERPROFILE%\\java_error_in___product_uc___%p.log -IDS_VM_OPTION_HEAPDUMPPATH=-XX:HeapDumpPath=%USERPROFILE%\\java_error_in___product_uc__.hprof -IDC_WINLAUNCHER=__IDE-NAME___LAUNCHER -IDS_PROPS_ENV_VAR=__IDE-NAME___PROPERTIES -IDS_VM_OPTIONS_ENV_VAR=__IDE-NAME__64_VM_OPTIONS -IDS_ERROR_LAUNCHING_APP=Error launching __IDE-NAME__ -IDS_VM_OPTIONS=-Didea.platform.prefix=PyCharmCore -Didea.paths.selector=__PRODUCT_PATHS_SELECTOR__ diff --git a/python/build/pycharm_community_build.gant b/python/build/pycharm_community_build.gant index 6213ba96fcb2..78b902fd3467 100644 --- a/python/build/pycharm_community_build.gant +++ b/python/build/pycharm_community_build.gant @@ -1,403 +1,12 @@ -import org.jetbrains.jps.LayoutInfo +import org.jetbrains.intellij.build.impl.BuildUtils +import org.jetbrains.jps.gant.JpsGantTool +import org.jetbrains.jps.idea.IdeaProjectLoader -import static org.jetbrains.jps.idea.IdeaProjectLoader.guessHome +includeTool << JpsGantTool -setProperty("home", guessHome(this as Script)) - -includeTargets << new File("${guessHome(this as Script)}/build/scripts/utils.gant") -includeTargets << new File("${guessHome(this)}/build/scripts/libLicenses.gant") - -requireProperty("buildNumber", requireProperty("build.number", snapshot)) - -setProperty("ch", home) -setProperty("pythonCommunityHome", "$home/python") - -// load ApplicationInfo.xml properties -ant.xmlproperty(file: "$pythonCommunityHome/python-community-ide-resources/resources/idea/PyCharmCoreApplicationInfo.xml", collapseAttributes: "true") - -setProperty("system_selector", "PyCharmCE${versionSelector()}") -setProperty("dryRun", false) -setProperty("jdk16", guessJdk()) - -//modules to compile -setProperty("pluginFilter", new File("$pythonCommunityHome/build/plugin-list.txt").readLines()) - -private List pycharmPlatformApiModules() { - return [platformApiModules, "dom-openapi"].flatten() -} - - -private List pycharmImplementationModules() { //modules to put into pycharm.jar - return [platformImplementationModules, "dom-impl", "python-community", "python-community-ide-resources", - "python-ide-community", "python-community-configure", "python-openapi", "python-psi-api", "platform-main"].flatten() -} - -private List modules() { - return [ - "python-pydev", "colorSchemes", pycharmPlatformApiModules(), pycharmImplementationModules(), pluginFilter - ].flatten() -} - -private List approvedJars() { - def normalizedHome = ch.replace('\\', '/') - def normalizedPythonHome = pythonCommunityHome.replace('\\', '/') - return ["$normalizedHome/lib/", "$normalizedPythonHome/lib/", "$normalizedHome/xml/relaxng/lib/"] -} - -class Paths { - final sandbox - final distAll - final distWin - final distMac - final distUnix - final artifacts - final ideaSystem - final ideaConfig - - def Paths(String home) { - sandbox = "$home/out/pycharmCE" - - distAll = "$sandbox/layout" - distWin = "$sandbox/win" - distMac = "$sandbox/mac" - distUnix = "$sandbox/unix" - artifacts = "$sandbox/artifacts" - - ideaSystem = "$sandbox/system" - ideaConfig = "$sandbox/config" - } -} - -setProperty("paths", new Paths(home)) -setProperty("buildName", "PC-$buildNumber") - -target('default': "Build artifacts") { - - loadProject() - - projectBuilder.stage("Cleaning up sandbox folder") - - projectBuilder.targetFolder = "${paths.sandbox}/classes" - projectBuilder.dryRun = dryRun - - if (!dryRun) { - forceDelete(paths.sandbox) - ant.mkdir(dir: paths.sandbox) - } - - ant.tstamp() { - format(property: "todayYear", pattern: "yyyy") - } - - ant.patternset(id: "resources.included") { - include(name: "**/*.properties") - include(name: "fileTemplates/**/*") - include(name: "inspectionDescriptions/**/*") - include(name: "intentionDescriptions/**/*") - include(name: "tips/**/*") - include(name: "search/**/*") - } - - ant.patternset(id: "resources.excluded") { - exclude(name: "**/*.properties") - exclude(name: "fileTemplates/**/*") - exclude(name: "fileTemplates") - exclude(name: "inspectionDescriptions/**/*") - exclude(name: "inspectionDescriptions") - exclude(name: "intentionDescriptions/**/*") - exclude(name: "intentionDescriptions") - exclude(name: "tips/**/*") - exclude(name: "tips") - } - - zipSources(home, paths.artifacts) - - def usedJars = buildModulesAndCollectUsedJars(modules(), approvedJars(), ["/ant/"]) - - layoutCommunity("${paths.sandbox}/classes/production", usedJars) - - /* - buildNSIS([paths.distAll, paths.distWin], - "$home/python/build/strings.nsi", "$home/python/build/paths.nsi", - "pycharm", false, true, system_selector) - */ - - /* - signMacZip("pycharm") - buildDmg("pycharm", "${home}/python/build/DMG_background.png") - */ -} - -public layoutCommunity(String classesPath, Set usedJars) { - setProperty("pluginFilter", new File("$pythonCommunityHome/build/plugin-list.txt").readLines()) - - if (usedJars == null) { - usedJars = collectUsedJars(modules(), approvedJars(), ["/ant/"], null) - } - - def appInfo = appInfoFile(classesPath) - def paths = new Paths(home) - buildSearchableOptions("${projectBuilder.moduleOutput(findModule("platform-resources"))}/search", [], { - projectBuilder.moduleRuntimeClasspath(findModule("main_pycharm_ce"), false).each { - ant.pathelement(location: it) - } - }, "-Didea.platform.prefix=PyCharmCore -Didea.no.jre.check=true") - - if (!dryRun) { - wireBuildDate("PC-${buildNumber}", appInfo) - } - - Map args = [ - buildNumber: "PC-${buildNumber}", - system_selector: system_selector, - ide_jvm_args: "-Didea.platform.prefix=PyCharmCore -Didea.no.jre.check=true"] - - LayoutInfo layoutInfo = layoutFull(args, paths.distAll, usedJars) - generateLicensesTable("$paths.artifacts/third-party-libraries.txt", layoutInfo.usedModules); - - layoutWin(args, paths.distWin) - layoutUnix(args, paths.distUnix) - layoutMac(args, paths.distMac) - - ant.echo(message: "PC-${buildNumber}", file: "${paths.distAll}/build.txt") - - def launcher = "${paths.distWin}/bin/pycharm.exe" - def launcher64 = "${paths.distWin}/bin/pycharm64.exe" - List resourcePaths = ["$ch/community-resources/src", - "$ch/platform/icons/src", - "$pythonCommunityHome/python-community-ide-resources/resources", - "$pythonCommunityHome/resources"] - buildWinLauncher("$ch", "$ch/bin/WinLauncher/WinLauncher.exe", launcher, - appInfo, "$pythonCommunityHome/build/pycharm_community_launcher.properties", system_selector, resourcePaths) - buildWinLauncher("$ch", "$ch/bin/WinLauncher/WinLauncher64.exe", launcher64, - appInfo, "$pythonCommunityHome/build/pycharm64_community_launcher.properties", system_selector, resourcePaths) - - List pathsDist = new File("${home}/out/pycharm/jdk.win/jre").exists() ? [paths.distAll, paths.distWin, "${home}/out/pycharm/jdk.win"] : [paths.distAll, paths.distWin] - buildWinZip("${paths.artifacts}/pycharmPC-${buildNumber}.zip", pathsDist) - - //win oracle jdk - if (new File("${home}/out/pycharm/jdk.oracle.win/jre").exists()) { - buildWinZip("${paths.artifacts}/pycharmPC-${buildNumber}-oracle-win.zip", [paths.distAll, paths.distWin, "${home}/out/pycharm/jdk.oracle.win"]) - } - - String tarRoot = isEap() ? "pycharm-community-$buildNumber" : "pycharm-community-${p("component.version.major")}.${p("component.version.minor")}" - buildTarGz(tarRoot, "$paths.artifacts/pycharmPC-${buildNumber}-no-jdk.tar", [paths.distAll, paths.distUnix]) - requireProperty("jdk.linux", "false") - if (p("jdk.linux") != "false") { - buildTarGz(tarRoot, "$paths.artifacts/pycharmPC-${buildNumber}.tar", [paths.distAll, paths.distUnix, "${home}/out/pycharm/jdk.linux"], ["jre/jre/bin/*"]) - } - - String macAppRoot = isEap() ? "PyCharm CE ${p("component.version.major")}.${p("component.version.minor")} EAP.app/Contents" : "PyCharm CE.app/Contents" - buildMacZip(macAppRoot, "${paths.artifacts}/pycharmPC-${buildNumber}.mac.zip", [paths.distAll], paths.distMac) -} - -private layoutPlugins(layouts) { - dir("plugins") { - layouts.layoutPlugin("rest") - layouts.layoutPlugin("python-rest") - layouts.layoutPlugin("ipnb") { - fileset(dir: "$pythonCommunityHome/ipnb/lib") - } - } - - layouts.layoutCommunityPlugins(ch) -} - -private String appInfoFile(String classesPath) { - return "$classesPath/python-community-ide-resources/idea/PyCharmCoreApplicationInfo.xml" -} - -private layoutFull(Map args, String target, Set usedJars) { - def openapiModules = pycharmPlatformApiModules() - def superLayouts = includeFile("$ch/build/scripts/layouts.gant") - - reassignAltClickToMultipleCarets("$ch") - - def result = layout(target) { - dir("lib") { - jar("util.jar") { - module("util") - module("util-rt") - } - - jar("openapi.jar") { - openapiModules.each { module it } - } - - jar("annotations.jar") { - module("annotations-common") - module("annotations") - } - jar("extensions.jar") { module("extensions") } - - jar(([name: "pycharm.jar", duplicate: "preserve"])) { - pycharmImplementationModules().each { - module(it) { - exclude(name: "**/tips/**") - } - } - } - - jar("pycharm-pydev.jar") { - module("python-pydev") - } - - jar("bootstrap.jar") { module("bootstrap") } - jar("resources.jar") { - module("platform-resources") - module("colorSchemes") - } - - jar("forms_rt.jar") { - module("forms_rt") - } - - //noinspection GroovyAssignabilityCheck - jar([name: "resources_en.jar", duplicate: "preserve"]) { - // custom resources should go first - module("python-community-ide-resources") { - ant.patternset { - include(name: "**/tips/**") - } - } - module("platform-resources-en") { - ant.patternset { - exclude(name: "tips/images/switcher.png") - exclude(name: "tips/images/navigateToFilePath.gif") - } - } - } - - jar("icons.jar") { module("icons") } - jar("boot.jar") { module("boot") } - - usedJars.each { - fileset(file: it) - } - - fileset(dir: "$ch/build/kotlinc/lib") { - include(name: "kotlin-runtime.jar") - include(name: "kotlin-reflect.jar") - } - - dir("libpty") { - fileset(dir: "$ch/lib/libpty") { - exclude(name: "*.txt") - } - } - - dir("ext") { - fileset(dir: "$ch/lib") { - include(name: "cglib*.jar") - } - } - - dir("src") { - fileset(dir: "$ch/lib/src") { - include(name: "trove4j_changes.txt") - include(name: "trove4j_src.jar") - } - - jar("pycharm-pydev-src.zip") { - fileset(dir: "$pythonCommunityHome/pydevSrc") - } - jar("pycharm-openapi-src.zip") { - fileset(dir: "$pythonCommunityHome/openapi/src") - fileset(dir: "$pythonCommunityHome/psi-api/src") - } - } - } - - dir("help") { - fileset(dir: "$home/python/help") { - include(name: "*.pdf") - } - } - - dir("helpers") { - fileset(dir: "$pythonCommunityHome/helpers") - } - - dir("license") { - fileset(dir: "$ch/license") - fileset(dir: "$ch") { - include(name: "LICENSE.txt") - include(name: "NOTICE.txt") - } - } - - layoutPlugins(superLayouts) - - dir("bin") { - fileset(dir: "$ch/bin") { - exclude(name: "appletviewer.policy") - include(name: "*.*") - } - } - } - patchPropertiesFile(target, args + [appendices: ["$home/build/conf/ideaJNC.properties"]]) - return result -} - -private layoutWin(Map args, String target) { - layout(target) { - dir("bin") { - fileset(dir: "$ch/bin/win") { - exclude(name: "breakgen*") - } - } - - dir("skeletons") { - fileset(dir: "$pythonCommunityHome/skeletons") { - include(name: "skeletons-win*.zip") - } - } - } - - winScripts(target, ch, "pycharm.bat", args) - winVMOptions(target, null, "pycharm.exe", "pycharm64.exe") - ant.copy(file: "$home/python/help/pycharmhelp.jar", todir: "$target/help", failonerror: false) -} - -private layoutUnix(Map args, String target) { - layout(target) { - dir("bin") { - fileset(dir: "$ch/bin/linux") { - exclude(name: "libbreakgen*") - } - } - } - - ant.copy(file: "$pythonCommunityHome/resources/PyCharmCore128.png", tofile: "$target/bin/pycharm.png") - - unixScripts(target, ch, "pycharm.sh", args) - unixVMOptions(target, "pycharm") - - ant.copy(file: "$home/python/help/pycharmhelp.jar", todir: "$target/help", failonerror: false) -} - -private layoutMac(Map _args, String target) { - layout(target) { - dir("bin") { - fileset(dir: "$home/bin") { - include(name: "*.jnilib") - } - } - - dir("skeletons") { - fileset(dir: "$pythonCommunityHome/skeletons") { - include(name: "skeletons-mac*.zip") - } - } - } - - Map args = new HashMap(_args) - args.icns = "$pythonCommunityHome/resources/PyCharmCore.icns" - args.bundleIdentifier = "com.jetbrains.pycharm" - args.platform_prefix = "PyCharmCore" - args.help_id = "PY" - args."idea.properties.path" = "${paths.distAll}/bin/idea.properties" - args."idea.properties" = ["idea.no.jre.check": true, "ide.mac.useNativeClipboard": "false"]; - args.executable = "pycharm" - layoutMacApp(target, ch, args) +target("default": "Default") { + String home = new File(IdeaProjectLoader.guessHome(this)).parentFile.absolutePath + BuildUtils.addToClassPath("$home/build/groovy", ant) + BuildUtils.addToClassPath("$home/community/python/build/groovy", ant) + Class.forName("org.jetbrains.intellij.build.pycharm.PyCharmCommunityBuilder").constructors[0].newInstance(home, binding).build() } diff --git a/python/build/pycharm_community_launcher.properties b/python/build/pycharm_community_launcher.properties deleted file mode 100644 index 83de195036d8..000000000000 --- a/python/build/pycharm_community_launcher.properties +++ /dev/null @@ -1,11 +0,0 @@ -IDS_JDK_ENV_VAR=PYCHARM_JDK -IDS_JDK_ONLY=false -IDS_APP_TITLE=__IDE-NAME__ Launcher -IDS_VM_OPTIONS_PATH=%USERPROFILE%\\.__PRODUCT_PATHS_SELECTOR__ -IDS_VM_OPTION_ERRORFILE=-XX:ErrorFile=%USERPROFILE%\\java_error_in___product_uc___%p.log -IDS_VM_OPTION_HEAPDUMPPATH=-XX:HeapDumpPath=%USERPROFILE%\\java_error_in___product_uc__.hprof -IDC_WINLAUNCHER=__IDE-NAME___LAUNCHER -IDS_PROPS_ENV_VAR=__IDE-NAME___PROPERTIES -IDS_VM_OPTIONS_ENV_VAR=__IDE-NAME___VM_OPTIONS -IDS_ERROR_LAUNCHING_APP=Error launching __IDE-NAME__ -IDS_VM_OPTIONS=-Didea.platform.prefix=PyCharmCore -Didea.paths.selector=__PRODUCT_PATHS_SELECTOR__ diff --git a/python/build/python-community-build.iml b/python/build/python-community-build.iml index 8665f6c2b0e4..1ecb47b47e83 100644 --- a/python/build/python-community-build.iml +++ b/python/build/python-community-build.iml @@ -2,10 +2,14 @@ - + + + + + \ No newline at end of file diff --git a/python/build/resources/PC_instCom.ico b/python/build/resources/install.ico similarity index 100% rename from python/build/resources/PC_instCom.ico rename to python/build/resources/install.ico diff --git a/python/build/resources/pycharm_inst.ico b/python/build/resources/pycharm_inst.ico deleted file mode 100644 index 6c75bcdbc441a8fc609fbecc14eafffb3416a872..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26694 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 K5K9ot5dS}z9PGdV diff --git a/python/build/resources/pycharm_uninst.ico b/python/build/resources/pycharm_uninst.ico deleted file mode 100644 index a5b9ad86ae949f22d25d7373d7275c326eedf23c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26694 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 diff --git a/python/build/resources/PC_uninstCom.ico b/python/build/resources/uninstall.ico similarity index 100% rename from python/build/resources/PC_uninstCom.ico rename to python/build/resources/uninstall.ico diff --git a/python/build/strings.nsi b/python/build/strings.nsi deleted file mode 100644 index c3f32aa21191..000000000000 --- a/python/build/strings.nsi +++ /dev/null @@ -1,16 +0,0 @@ -!define MANUFACTURER "JetBrains" -!define MUI_PRODUCT "PyCharm Community Edition" -!define PRODUCT_FULL_NAME "JetBrains PyCharm Community Edition" -!define PRODUCT_EXE_FILE "pycharm.exe" -!define PRODUCT_EXE_FILE_64 "pycharm64.exe" -!define PRODUCT_ICON_FILE "PC_instCom.ico" -!define PRODUCT_UNINST_ICON_FILE "PC_uninstCom.ico" -!define PRODUCT_LOGO_FILE "logo.bmp" -!define PRODUCT_HEADER_FILE "headerlogo.bmp" -!define ASSOCIATION ".py" -!define UNINSTALL_WEB_PAGE "feedback_web_page" - -; if SHOULD_SET_DEFAULT_INSTDIR != 0 then default installation directory will be directory where highest-numbered RubyMine build has been installed -; set to 1 for release build -!define SHOULD_SET_DEFAULT_INSTDIR "0" - diff --git a/python/educational-python/build/groovy/org/jetbrains/intellij/build/pycharm/edu/PyCharmEduProperties.groovy b/python/educational-python/build/groovy/org/jetbrains/intellij/build/pycharm/edu/PyCharmEduProperties.groovy index 22d7ae924ab7..6720888d2c20 100644 --- a/python/educational-python/build/groovy/org/jetbrains/intellij/build/pycharm/edu/PyCharmEduProperties.groovy +++ b/python/educational-python/build/groovy/org/jetbrains/intellij/build/pycharm/edu/PyCharmEduProperties.groovy @@ -1,55 +1,33 @@ package org.jetbrains.intellij.build.pycharm.edu -import org.jetbrains.intellij.build.ApplicationInfoProperties -import org.jetbrains.intellij.build.BuildContext -import org.jetbrains.intellij.build.BuildTasks -import org.jetbrains.intellij.build.CommunityLibraryLicenses -import org.jetbrains.intellij.build.CommunityRepositoryModules -import org.jetbrains.intellij.build.LinuxDistributionCustomizer -import org.jetbrains.intellij.build.MacDistributionCustomizer -import org.jetbrains.intellij.build.ProductProperties -import org.jetbrains.intellij.build.WindowsDistributionCustomizer +import org.jetbrains.intellij.build.* +import org.jetbrains.intellij.build.pycharm.PyCharmMacDistributionCustomizer +import org.jetbrains.intellij.build.pycharm.PyCharmPropertiesBase +import org.jetbrains.intellij.build.pycharm.PyCharmWindowsDistributionCustomizer /** * @author nik */ -class PyCharmEduProperties extends ProductProperties { +class PyCharmEduProperties extends PyCharmPropertiesBase { PyCharmEduProperties(String home) { - baseFileName = "pycharm" + super(home) productCode = "PE" platformPrefix = "PyCharmEdu" applicationInfoModule = "educational-python" brandingResourcePaths = ["$home/community/python/educational-python/resources"] - additionalIDEPropertiesFilePaths = ["$home/build/conf/ideaJNC.properties"] - reassignAltClickToMultipleCarets = true - productLayout.mainJarName = "pycharm.jar" productLayout.mainModule = "main_pycharm_edu" productLayout.platformApiModules = CommunityRepositoryModules.PLATFORM_API_MODULES + ["dom-openapi"] productLayout.platformImplementationModules = CommunityRepositoryModules.PLATFORM_IMPLEMENTATION_MODULES + [ "dom-impl", "python-community", "python-community-ide-resources", "python-ide-community", "python-community-configure", "educational-python", "python-openapi", "python-psi-api", "platform-main" ] - productLayout.additionalPlatformJars.put("pycharm-pydev.jar", "python-pydev") productLayout.bundledPluginModules = new File("$home/community/python/educational-python/build/plugin-list.txt").readLines() - - allLibraryLicenses = CommunityLibraryLicenses.LICENSES_LIST } @Override void copyAdditionalFiles(BuildContext context, String targetDirectory) { - def tasks = BuildTasks.create(context) - tasks.zipSourcesOfModules(["python-pydev"], "$targetDirectory/lib/src/pycharm-pydev-src.zip") - tasks.zipSourcesOfModules(["python-openapi", "python-psi-api"], "$targetDirectory/lib/src/pycharm-openapi-src.zip") - - context.ant.copy(todir: "$targetDirectory/helpers") { - fileset(dir: "$context.paths.projectHome/community/python/helpers") - } - context.ant.copy(todir: "$targetDirectory/help") { - fileset(dir: "$context.paths.projectHome/python/help") { - include(name: "*.pdf") - } - } + super.copyAdditionalFiles(context, targetDirectory) context.ant.copy(todir: "$targetDirectory/license") { fileset(file: "$context.paths.communityHome/LICENSE.txt") fileset(file: "$context.paths.communityHome/NOTICE.txt") @@ -66,14 +44,9 @@ class PyCharmEduProperties extends ProductProperties { "pycharmEDU-$buildNumber" } - @Override - String environmentVariableBaseName(ApplicationInfoProperties applicationInfo) { - "PYCHARM" - } - @Override WindowsDistributionCustomizer createWindowsCustomizer(String projectHome) { - return new WindowsDistributionCustomizer() { + return new PyCharmWindowsDistributionCustomizer() { { buildZipWithBundledOracleJre = true installerImagesPath = "$projectHome/community/python/educational-python/build/resources" @@ -84,17 +57,13 @@ class PyCharmEduProperties extends ProductProperties { } @Override - String rootDirectoryName(ApplicationInfoProperties applicationInfo, String buildNumber) { - "" + String fullNameIncludingEdition(ApplicationInfoProperties applicationInfo) { + "PyCharm Edu" } @Override void copyAdditionalFiles(BuildContext context, String targetDirectory) { - context.ant.copy(todir: "$targetDirectory/skeletons") { - fileset(dir: "$context.paths.projectHome/community/python/skeletons") { - include(name: "skeletons-win*.zip") - } - } + super.copyAdditionalFiles(context, targetDirectory) context.ant.copy(file: "$context.paths.projectHome/python/help/pycharm-eduhelp.jar", todir: "$targetDirectory/help", failonerror: false) } } @@ -121,27 +90,13 @@ class PyCharmEduProperties extends ProductProperties { @Override MacDistributionCustomizer createMacCustomizer(String projectHome) { - return new MacDistributionCustomizer() { + return new PyCharmMacDistributionCustomizer() { { icnsPath = "$projectHome/community/python/educational-python/resources/PyCharmEdu.icns" bundleIdentifier = "com.jetbrains.pycharm" helpId = "PE" dmgImagePath = "$projectHome/community/python/educational-python/build/DMG_background.png" } - - @Override - void copyAdditionalFiles(BuildContext context, String targetDirectory) { - context.ant.copy(todir: "$targetDirectory/skeletons") { - fileset(dir: "$context.paths.projectHome/community/python/skeletons") { - include(name: "skeletons-mac*.zip") - } - } - } - - @Override - Map customIdeaProperties(ApplicationInfoProperties applicationInfo) { - ["ide.mac.useNativeClipboard": "false"] - } } } } \ No newline at end of file diff --git a/python/educational-python/build/pycharm_edu_build.gant b/python/educational-python/build/pycharm_edu_build.gant index e18e98c60dfe..09c69eaf4e30 100644 --- a/python/educational-python/build/pycharm_edu_build.gant +++ b/python/educational-python/build/pycharm_edu_build.gant @@ -7,6 +7,7 @@ includeTool << JpsGantTool target("default": "Default") { String home = new File(IdeaProjectLoader.guessHome(this)).parentFile.absolutePath BuildUtils.addToClassPath("$home/build/groovy", ant) + BuildUtils.addToClassPath("$home/community/python/build/groovy", ant) BuildUtils.addToClassPath("$home/community/python/educational-python/build/groovy", ant) Class.forName("org.jetbrains.intellij.build.pycharm.edu.PyCharmEduBuilder").constructors[0].newInstance(home, binding).build() } diff --git a/python/educational-python/build/python-edu-build.iml b/python/educational-python/build/python-edu-build.iml index 1ecb47b47e83..275262d81506 100644 --- a/python/educational-python/build/python-edu-build.iml +++ b/python/educational-python/build/python-edu-build.iml @@ -11,5 +11,6 @@ + \ No newline at end of file From acf88797696dbea90b083a85ae49d1887f6c0808 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 31 Aug 2016 15:35:28 +0300 Subject: [PATCH 48/63] severities: ensure valid severities order after editing (IDEA-160567) --- .../codeInsight/daemon/impl/SeverityRegistrar.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java index dd6801d6a931..97637deb51f8 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java @@ -159,6 +159,11 @@ public class SeverityRegistrar implements Comparator { read.add(severity); } } + myOrderMap = ensureAllStandardIncluded(read, knownSeverities); + severitiesChanged(); + } + + private OrderMap ensureAllStandardIncluded(List read, final List knownSeverities) { OrderMap orderMap = fromList(read); if (orderMap.isEmpty()) { orderMap = fromList(knownSeverities); @@ -182,8 +187,7 @@ public class SeverityRegistrar implements Comparator { } orderMap = fromList(list); } - myOrderMap = orderMap; - severitiesChanged(); + return orderMap; } public void writeExternal(Element element) { @@ -345,7 +349,7 @@ public class SeverityRegistrar implements Comparator { } public void setOrder(@NotNull List orderList) { - myOrderMap = fromList(orderList); + myOrderMap = ensureAllStandardIncluded(orderList, getDefaultOrder()); myReadOrder = null; severitiesChanged(); } From 8f56a856aed84dfac9fcd09c8b6355bf4faecadf Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 31 Aug 2016 15:43:30 +0300 Subject: [PATCH 49/63] inspection settings: myProfilePanelHolder should be preferred component to focus --- .../codeInspection/ui/header/InspectionToolsConfigurable.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java index 7cfc0ee621fa..3f0e5c0341f8 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java @@ -667,9 +667,7 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable @Override public JComponent getPreferredFocusedComponent() { - final InspectionProfileImpl inspectionProfile = myProfiles.getProfilesComboBox().getSelectedProfile(); - SingleInspectionProfilePanel panel = getProfilePanel(inspectionProfile); - return panel == null ? null : panel.getPreferredFocusedComponent(); + return myProfilePanelHolder; } private void showProfile(InspectionProfileImpl profile) { From 575878c57aefd6d0523c3c9766adcfdd32b3c0af Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 31 Aug 2016 15:58:13 +0300 Subject: [PATCH 50/63] Cleanup (formatting) --- .../src/com/intellij/lang/Language.java | 38 ++++++++----------- .../components/impl/ComponentManagerImpl.java | 15 ++++---- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/platform/core-api/src/com/intellij/lang/Language.java b/platform/core-api/src/com/intellij/lang/Language.java index 829ef0973a54..9dbe2bccff2f 100644 --- a/platform/core-api/src/com/intellij/lang/Language.java +++ b/platform/core-api/src/com/intellij/lang/Language.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,6 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,12 +33,10 @@ import java.util.concurrent.ConcurrentMap; /** * The base class for all programming language support implementations. Specific language implementations should inherit from this class - * and its register instance wrapped with {@link com.intellij.openapi.fileTypes.LanguageFileType} instance through - * FileTypeManager.getInstance().registerFileType + * and its register instance wrapped with {@link LanguageFileType} instance via {@code FileTypeManager.getInstance().registerFileType()}. * There should be exactly one instance of each Language. - * It is usually created when creating {@link com.intellij.openapi.fileTypes.LanguageFileType} and can be retrieved later - * with {@link #findInstance(Class)}. - * For the list of standard languages, see {@link com.intellij.lang.StdLanguages}. + * It is usually created when creating {@link LanguageFileType} and can be retrieved later with {@link #findInstance(Class)}. + * For the list of standard languages, see {@code com.intellij.lang.StdLanguages}. */ public abstract class Language extends UserDataHolderBase { private static final Logger LOG = Logger.getInstance("#com.intellij.lang.Language"); @@ -47,14 +44,15 @@ public abstract class Language extends UserDataHolderBase { private static final Map, Language> ourRegisteredLanguages = ContainerUtil.newConcurrentMap(); private static final ConcurrentMap> ourRegisteredMimeTypes = ContainerUtil.newConcurrentMap(); private static final Map ourRegisteredIDs = ContainerUtil.newConcurrentMap(); + private final Language myBaseLanguage; private final String myID; private final String[] myMimeTypes; private final List myDialects = ContainerUtil.createLockFreeCopyOnWriteList(); + public static final Language ANY = new Language("") { @Override public String toString() { - //noinspection HardCodedStringLiteral return "Language: ANY"; } @@ -65,34 +63,31 @@ public abstract class Language extends UserDataHolderBase { } }; - protected Language(@NotNull @NonNls String ID) { + protected Language(@NotNull String ID) { this(ID, ArrayUtil.EMPTY_STRING_ARRAY); } - protected Language(@NotNull @NonNls final String ID, @NotNull @NonNls final String... mimeTypes) { + protected Language(@NotNull String ID, @NotNull String... mimeTypes) { this(null, ID, mimeTypes); } - protected Language(@Nullable Language baseLanguage, @NotNull @NonNls final String ID, @NotNull @NonNls final String... mimeTypes) { + protected Language(@Nullable Language baseLanguage, @NotNull String ID, @NotNull String... mimeTypes) { myBaseLanguage = baseLanguage; myID = ID; myMimeTypes = mimeTypes; + Class langClass = getClass(); Language prev = ourRegisteredLanguages.put(langClass, this); if (prev != null) { - LOG.error(new ImplementationConflictException("Language of '" + langClass + "' is already registered: " + prev, - null, - prev, - this)); + LOG.error(new ImplementationConflictException("Language of '" + langClass + "' is already registered: " + prev, null, prev, this)); return; } + prev = ourRegisteredIDs.put(ID, this); if (prev != null) { - LOG.error(new ImplementationConflictException("Language with ID '" + ID + "' is already registered: " + prev.getClass(), - null, - prev, - this)); + LOG.error(new ImplementationConflictException("Language with ID '" + ID + "' is already registered: " + prev.getClass(), null, prev, this)); } + for (String mimeType : mimeTypes) { if (StringUtil.isEmpty(mimeType)) { continue; @@ -103,6 +98,7 @@ public abstract class Language extends UserDataHolderBase { } languagesByMimeType.add(this); } + if (baseLanguage != null) { baseLanguage.myDialects.add(this); } @@ -136,10 +132,8 @@ public abstract class Language extends UserDataHolderBase { return result == null ? Collections.emptyList() : Collections.unmodifiableCollection(result); } - @Override public String toString() { - //noinspection HardCodedStringLiteral return "Language: " + myID; } @@ -235,4 +229,4 @@ public abstract class Language extends UserDataHolderBase { myBaseLanguage = null; myMimeTypes = null; } -} +} \ No newline at end of file diff --git a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java index fcf71fd24fc1..2221418c116c 100644 --- a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java @@ -383,11 +383,10 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements private void registerComponents(@NotNull ComponentConfig config) { ClassLoader loader = config.getClassLoader(); try { - final Class interfaceClass = Class.forName(config.getInterfaceClass(), true, loader); - final Class implementationClass = Comparing.equal(config.getInterfaceClass(), config.getImplementationClass()) - ? - interfaceClass - : StringUtil.isEmpty(config.getImplementationClass()) ? null : Class.forName(config.getImplementationClass(), true, loader); + Class interfaceClass = Class.forName(config.getInterfaceClass(), true, loader); + Class implementationClass = Comparing.equal(config.getInterfaceClass(), config.getImplementationClass()) ? interfaceClass : + StringUtil.isEmpty(config.getImplementationClass()) ? null : + Class.forName(config.getImplementationClass(), true, loader); MutablePicoContainer picoContainer = getPicoContainer(); if (config.options != null && Boolean.parseBoolean(config.options.get("overrides"))) { ComponentAdapter oldAdapter = picoContainer.getComponentAdapterOfType(interfaceClass); @@ -398,8 +397,8 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements } // implementationClass == null means we want to unregister this component if (implementationClass != null) { - picoContainer.registerComponent(new ComponentConfigComponentAdapter(interfaceClass, implementationClass, config.getPluginId(), - config.options != null && Boolean.parseBoolean(config.options.get("workspace")))); + boolean ws = config.options != null && Boolean.parseBoolean(config.options.get("workspace")); + picoContainer.registerComponent(new ComponentConfigComponentAdapter(interfaceClass, implementationClass, config.getPluginId(), ws)); } } catch (Throwable t) { @@ -522,4 +521,4 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements return "ComponentConfigAdapter[" + getComponentKey() + "]: implementation=" + getComponentImplementation() + ", plugin=" + myPluginId; } } -} +} \ No newline at end of file From e701a2585c910f15bd1392687dd059b24521f306 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Tue, 30 Aug 2016 20:33:57 +0300 Subject: [PATCH 51/63] Add ability to set default suspend policy for breakpoint type --- .../com/intellij/xdebugger/breakpoints/XBreakpointType.java | 5 +++++ .../xdebugger/impl/breakpoints/BreakpointState.java | 5 +++-- .../xdebugger/impl/breakpoints/LineBreakpointState.java | 6 ++++-- .../xdebugger/impl/breakpoints/XBreakpointManagerImpl.java | 5 +++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java index a41635140e74..22fc25df8021 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java @@ -49,6 +49,7 @@ import java.util.List; */ public abstract class XBreakpointType, P extends XBreakpointProperties> { public static final ExtensionPointName EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.xdebugger.breakpointType"); + public static final SuspendPolicy DEFAULT_SUSPEND_POLICY = SuspendPolicy.ALL; private final @NonNls @NotNull String myId; private final @Nls @NotNull String myTitle; private final boolean mySuspendThreadSupported; @@ -84,6 +85,10 @@ public abstract class XBreakpointType, P extends XBreak return mySuspendThreadSupported; } + public SuspendPolicy getDefaultSuspendPolicy() { + return DEFAULT_SUSPEND_POLICY; + } + public enum StandardPanels {SUSPEND_POLICY, ACTIONS, DEPENDENCY} public EnumSet getVisibleStandardPanels() { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java index 8631b8fc901b..fa2547de63e5 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java @@ -37,7 +37,7 @@ public class BreakpointState, P extends XBreakpointProp private String myTypeId; private boolean myEnabled; private Element myPropertiesElement; - private SuspendPolicy mySuspendPolicy = SuspendPolicy.ALL; + private SuspendPolicy mySuspendPolicy = XBreakpointType.DEFAULT_SUSPEND_POLICY; private boolean myLogMessage; private LogExpression myLogExpression; private Condition myCondition; @@ -53,10 +53,11 @@ public class BreakpointState, P extends XBreakpointProp public BreakpointState() { } - public BreakpointState(final boolean enabled, final String typeId, final long timeStamp) { + public BreakpointState(final boolean enabled, final String typeId, final long timeStamp, final SuspendPolicy suspendPolicy) { myEnabled = enabled; myTypeId = typeId; myTimeStamp = timeStamp; + mySuspendPolicy = suspendPolicy; } @Attribute("enabled") diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/LineBreakpointState.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/LineBreakpointState.java index c843d9ef53c1..534db7761a79 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/LineBreakpointState.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/LineBreakpointState.java @@ -16,6 +16,7 @@ package com.intellij.xdebugger.impl.breakpoints; import com.intellij.util.xmlb.annotations.Tag; +import com.intellij.xdebugger.breakpoints.SuspendPolicy; import com.intellij.xdebugger.breakpoints.XBreakpointProperties; import com.intellij.xdebugger.breakpoints.XLineBreakpoint; import com.intellij.xdebugger.breakpoints.XLineBreakpointType; @@ -33,8 +34,9 @@ public class LineBreakpointState

extends Breakp public LineBreakpointState() { } - public LineBreakpointState(final boolean enabled, final String typeId, final String fileUrl, final int line, boolean temporary, final long timeStamp) { - super(enabled, typeId, timeStamp); + public LineBreakpointState(final boolean enabled, final String typeId, final String fileUrl, final int line, boolean temporary, + final long timeStamp, final SuspendPolicy suspendPolicy) { + super(enabled, typeId, timeStamp, suspendPolicy); myFileUrl = fileUrl; myLine = line; myTemporary = temporary; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java index 0c9f0bdd806c..f6038c693eb2 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java @@ -121,7 +121,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta boolean defaultBreakpoint) { BreakpointState state = new BreakpointState<>(enabled, type.getId(), - defaultBreakpoint ? 0 : myTime++); + defaultBreakpoint ? 0 : myTime++, type.getDefaultSuspendPolicy()); getBreakpointDefaults(type).applyDefaults(state); state.setGroup(myDefaultGroup); return new XBreakpointBase,T, BreakpointState>(type, this, properties, state); @@ -217,7 +217,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta boolean temporary) { ApplicationManager.getApplication().assertWriteAccessAllowed(); LineBreakpointState state = new LineBreakpointState<>(true, type.getId(), fileUrl, line, temporary, - myTime++); + myTime++, type.getDefaultSuspendPolicy()); getBreakpointDefaults(type).applyDefaults(state); state.setGroup(myDefaultGroup); XLineBreakpointImpl breakpoint = new XLineBreakpointImpl<>(type, this, properties, @@ -508,6 +508,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta private static BreakpointState createBreakpointDefaults(@NotNull XBreakpointType type) { BreakpointState state = new BreakpointState(); state.setTypeId(type.getId()); + state.setSuspendPolicy(type.getDefaultSuspendPolicy()); return state; } From b16449a3e88802464366a6498fecda3972c87063 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Tue, 30 Aug 2016 20:35:28 +0300 Subject: [PATCH 52/63] Set default suspend policy to "Thread" for Python line breakpoints (PY-20196) --- .../com/jetbrains/python/debugger/PyLineBreakpointType.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/python/src/com/jetbrains/python/debugger/PyLineBreakpointType.java b/python/src/com/jetbrains/python/debugger/PyLineBreakpointType.java index 38a041d1edab..52b52557b736 100644 --- a/python/src/com/jetbrains/python/debugger/PyLineBreakpointType.java +++ b/python/src/com/jetbrains/python/debugger/PyLineBreakpointType.java @@ -28,6 +28,7 @@ import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.xdebugger.XDebuggerUtil; +import com.intellij.xdebugger.breakpoints.SuspendPolicy; import com.intellij.xdebugger.breakpoints.XLineBreakpointTypeBase; import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.PythonFileType; @@ -99,6 +100,11 @@ public class PyLineBreakpointType extends XLineBreakpointTypeBase { return true; } + @Override + public SuspendPolicy getDefaultSuspendPolicy() { + return SuspendPolicy.THREAD; + } + private static boolean isPythonScratch(@NotNull Project project, @NotNull VirtualFile file) { return ScratchUtil.isScratch(file) && LanguageUtil.getLanguageForPsi(project, file) == PythonLanguage.INSTANCE; } From 22da925422f369d04485ed4d6639582636c4c06f Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Wed, 31 Aug 2016 12:25:25 +0300 Subject: [PATCH 53/63] Updates after the review IDEA-CR-13415 --- .../com/intellij/xdebugger/breakpoints/XBreakpointType.java | 3 +-- .../intellij/xdebugger/impl/breakpoints/BreakpointState.java | 2 +- .../xdebugger/impl/breakpoints/ui/XSuspendPolicyPanel.java | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java index 22fc25df8021..d9005fd5a4e3 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java @@ -49,7 +49,6 @@ import java.util.List; */ public abstract class XBreakpointType, P extends XBreakpointProperties> { public static final ExtensionPointName EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.xdebugger.breakpointType"); - public static final SuspendPolicy DEFAULT_SUSPEND_POLICY = SuspendPolicy.ALL; private final @NonNls @NotNull String myId; private final @Nls @NotNull String myTitle; private final boolean mySuspendThreadSupported; @@ -86,7 +85,7 @@ public abstract class XBreakpointType, P extends XBreak } public SuspendPolicy getDefaultSuspendPolicy() { - return DEFAULT_SUSPEND_POLICY; + return SuspendPolicy.ALL; } public enum StandardPanels {SUSPEND_POLICY, ACTIONS, DEPENDENCY} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java index fa2547de63e5..8dd934a48c94 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java @@ -37,7 +37,7 @@ public class BreakpointState, P extends XBreakpointProp private String myTypeId; private boolean myEnabled; private Element myPropertiesElement; - private SuspendPolicy mySuspendPolicy = XBreakpointType.DEFAULT_SUSPEND_POLICY; + private SuspendPolicy mySuspendPolicy = SuspendPolicy.ALL; private boolean myLogMessage; private LogExpression myLogExpression; private Condition myCondition; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XSuspendPolicyPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XSuspendPolicyPanel.java index 947693068e21..2d2f918a01b6 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XSuspendPolicyPanel.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XSuspendPolicyPanel.java @@ -169,7 +169,7 @@ public class XSuspendPolicyPanel extends XBreakpointPropertiesSubPanel { return mySuspendAll.isSelected() ? SuspendPolicy.ALL : SuspendPolicy.THREAD; } else { - return SuspendPolicy.ALL; + return myBreakpoint.getType().getDefaultSuspendPolicy(); } } From 24171ee9037c8bb62eac886e6785c8538adf29c8 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Wed, 31 Aug 2016 15:29:06 +0200 Subject: [PATCH 54/63] scheme-based copyright manager --- .../ProjectInspectionProfileManager.kt | 10 +- .../src/SchemeManagerImpl.kt | 8 +- .../configurationStore/scheme-impl.kt | 30 ++ .../src/com/intellij/jdom.kt | 2 + plugins/copyright/copyright.iml | 1 + plugins/copyright/src/CopyrightManager.kt | 277 +++++++++++++++++ plugins/copyright/src/META-INF/plugin.xml | 92 +++--- .../idea/copyright/CopyrightManager.java | 292 ------------------ .../actions/AbstractFileProcessor.java | 47 +-- .../actions/GenerateCopyrightAction.java | 3 +- .../actions/UpdateCopyrightAction.java | 2 +- .../actions/UpdateCopyrightProcessor.java | 19 +- .../copyright/pattern/VelocityHelper.java | 4 +- .../psi/AbstractUpdateCopyright.java | 4 +- .../copyright/psi/UpdatePsiFileCopyright.java | 4 +- .../copyright/ui/CopyrightConfigurable.java | 8 +- .../copyright/ui/CopyrightProfilesPanel.java | 33 +- .../copyright/ui/ProjectSettingsPanel.java | 27 +- .../copyright/ui/TemplateCommentPanel.java | 11 +- .../idea/copyright/util/NewFileTracker.java | 14 +- 20 files changed, 417 insertions(+), 471 deletions(-) create mode 100644 plugins/copyright/src/CopyrightManager.kt delete mode 100644 plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java diff --git a/platform/analysis-impl/src/com/intellij/profile/codeInspection/ProjectInspectionProfileManager.kt b/platform/analysis-impl/src/com/intellij/profile/codeInspection/ProjectInspectionProfileManager.kt index a0ea74611b0d..dcd1697edf70 100644 --- a/platform/analysis-impl/src/com/intellij/profile/codeInspection/ProjectInspectionProfileManager.kt +++ b/platform/analysis-impl/src/com/intellij/profile/codeInspection/ProjectInspectionProfileManager.kt @@ -21,6 +21,7 @@ import com.intellij.codeInspection.ex.InspectionToolRegistrar import com.intellij.configurationStore.SchemeDataHolder import com.intellij.configurationStore.SchemeManagerIprProvider import com.intellij.configurationStore.digest +import com.intellij.configurationStore.wrapState import com.intellij.openapi.Disposable import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.PersistentStateComponent @@ -32,7 +33,6 @@ import com.intellij.openapi.project.ProjectManager import com.intellij.openapi.project.ProjectManagerListener import com.intellij.openapi.startup.StartupActivity import com.intellij.openapi.util.Disposer -import com.intellij.openapi.util.JDOMUtil import com.intellij.openapi.util.text.StringUtil import com.intellij.packageDependencies.DependencyValidationManager import com.intellij.profile.Profile @@ -264,13 +264,7 @@ class ProjectInspectionProfileManager(val project: Project, severityRegistrar.writeExternal(result) - if (JDOMUtil.isEmpty(result)) { - result.name = "state" - return result - } - else { - return Element("state").addContent(result) - } + return wrapState(result) } override fun getScopesManager() = scopeManager diff --git a/platform/configuration-store-impl/src/SchemeManagerImpl.kt b/platform/configuration-store-impl/src/SchemeManagerImpl.kt index 50634e5b4433..3b759da23c11 100644 --- a/platform/configuration-store-impl/src/SchemeManagerImpl.kt +++ b/platform/configuration-store-impl/src/SchemeManagerImpl.kt @@ -370,12 +370,16 @@ class SchemeManagerImpl(val fileSpec: String, override fun updateDigest(scheme: MUTABLE_SCHEME) { try { - externalInfo.digest = (processor.writeScheme(scheme) as Element).digest() + updateDigest(processor.writeScheme(scheme) as Element) } catch (e: WriteExternalException) { LOG.error("Cannot update digest", e) } } + + override fun updateDigest(data: Element) { + externalInfo.digest = data.digest() + } } private fun loadScheme(fileName: String, input: InputStream, schemes: MutableList, filesToDelete: MutableSet? = null): MUTABLE_SCHEME? { @@ -438,7 +442,7 @@ class SchemeManagerImpl(val fileSpec: String, XmlPullParser.START_TAG -> { if (!isUseOldFileNameSanitize || parser.name != "component") { var name: String? = null - if (isUseOldFileNameSanitize && parser.name == "profile") { + if (isUseOldFileNameSanitize && (parser.name == "profile" || parser.name == "copyright")) { eventType = parser.next() findName@ while (eventType != XmlPullParser.END_DOCUMENT) { when (eventType) { diff --git a/platform/projectModel-impl/src/com/intellij/configurationStore/scheme-impl.kt b/platform/projectModel-impl/src/com/intellij/configurationStore/scheme-impl.kt index a00f58e52583..eda2ab4802b8 100644 --- a/platform/projectModel-impl/src/com/intellij/configurationStore/scheme-impl.kt +++ b/platform/projectModel-impl/src/com/intellij/configurationStore/scheme-impl.kt @@ -15,8 +15,11 @@ */ package com.intellij.configurationStore +import com.intellij.openapi.options.ExternalizableSchemeAdapter import com.intellij.openapi.options.Scheme import com.intellij.openapi.options.SchemeProcessor +import com.intellij.openapi.options.SchemeState +import com.intellij.util.isEmpty import org.jdom.Element import java.io.OutputStream import java.security.MessageDigest @@ -29,6 +32,8 @@ interface SchemeDataHolder { fun read(): Element fun updateDigest(scheme: MUTABLE_SCHEME) + + fun updateDigest(data: Element) } interface SerializableScheme { @@ -84,4 +89,29 @@ fun Element.digest(): ByteArray { val digest = MessageDigest.getInstance("SHA-1") serializeElementToBinary(this, DigestOutputStream(digest)) return digest.digest() +} + +abstract class SchemeWrapper(name: String) : ExternalizableSchemeAdapter(), SerializableScheme { + protected abstract val lazyScheme: Lazy + + val scheme: T + get() = lazyScheme.value + + val schemeState: SchemeState + get() = if (lazyScheme.isInitialized()) SchemeState.POSSIBLY_CHANGED else SchemeState.UNCHANGED + + init { + this.name = name + } +} + +fun wrapState(element: Element): Element { + if (element.isEmpty()) { + element.name = "state" + return element + } + + val wrapper = Element("state") + wrapper.addContent(element) + return wrapper } \ No newline at end of file diff --git a/platform/projectModel-impl/src/com/intellij/jdom.kt b/platform/projectModel-impl/src/com/intellij/jdom.kt index ef460e6902cd..f1e45ae5c543 100644 --- a/platform/projectModel-impl/src/com/intellij/jdom.kt +++ b/platform/projectModel-impl/src/com/intellij/jdom.kt @@ -82,6 +82,8 @@ fun Element.element(name: String): Element { return element } +fun Element.attribute(name: String, value: String?): Element = setAttribute(name, value) + fun Element.remove(name: String, transform: (child: Element) -> T): List { val result = SmartList() val groupIterator = getContent(ElementFilter(name)).iterator() diff --git a/plugins/copyright/copyright.iml b/plugins/copyright/copyright.iml index 126c6110fa43..e9b97f5b12bf 100644 --- a/plugins/copyright/copyright.iml +++ b/plugins/copyright/copyright.iml @@ -14,5 +14,6 @@ + \ No newline at end of file diff --git a/plugins/copyright/src/CopyrightManager.kt b/plugins/copyright/src/CopyrightManager.kt new file mode 100644 index 000000000000..b9605666c44c --- /dev/null +++ b/plugins/copyright/src/CopyrightManager.kt @@ -0,0 +1,277 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.copyright + +import com.intellij.configurationStore.LazySchemeProcessor +import com.intellij.configurationStore.SchemeDataHolder +import com.intellij.configurationStore.SchemeWrapper +import com.intellij.configurationStore.wrapState +import com.intellij.openapi.Disposable +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.ModalityState +import com.intellij.openapi.components.PersistentStateComponent +import com.intellij.openapi.components.State +import com.intellij.openapi.components.Storage +import com.intellij.openapi.components.service +import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.editor.EditorFactory +import com.intellij.openapi.editor.event.DocumentAdapter +import com.intellij.openapi.editor.event.DocumentEvent +import com.intellij.openapi.fileEditor.FileDocumentManager +import com.intellij.openapi.options.SchemeManagerFactory +import com.intellij.openapi.project.Project +import com.intellij.openapi.roots.ProjectRootManager +import com.intellij.openapi.startup.StartupActivity +import com.intellij.openapi.util.Disposer +import com.intellij.openapi.util.InvalidDataException +import com.intellij.openapi.util.WriteExternalException +import com.intellij.openapi.util.text.StringUtil +import com.intellij.packageDependencies.DependencyValidationManager +import com.intellij.project.isDirectoryBased +import com.intellij.psi.PsiFile +import com.intellij.psi.PsiManager +import com.intellij.util.attribute +import com.intellij.util.element +import com.maddyhome.idea.copyright.CopyrightProfile +import com.maddyhome.idea.copyright.actions.UpdateCopyrightProcessor +import com.maddyhome.idea.copyright.options.LanguageOptions +import com.maddyhome.idea.copyright.options.Options +import com.maddyhome.idea.copyright.util.FileTypeUtil +import com.maddyhome.idea.copyright.util.NewFileTracker +import org.jdom.Element +import java.util.* +import java.util.concurrent.atomic.AtomicReference +import java.util.function.Function + +private const val DEFAULT = "default" +private const val MODULE2COPYRIGHT = "module2copyright" +private const val COPYRIGHT = "copyright" +private const val ELEMENT = "element" +private const val MODULE = "module" + +private val LOG = Logger.getInstance(CopyrightManager::class.java) + +@State(name = "CopyrightManager", storages = arrayOf(Storage(value = "copyright/profiles_settings.xml", exclusive = true))) +class CopyrightManager(private val project: Project, schemeManagerFactory: SchemeManagerFactory) : PersistentStateComponent { + companion object { + @JvmStatic + fun getInstance(project: Project) = project.service() + } + + var defaultCopyright: CopyrightProfile? = null + val scopeToCopyright = LinkedHashMap() + val options = Options() + + val schemeManager = schemeManagerFactory.create("copyright", object : LazySchemeProcessor, SchemeWrapper>() { + override fun createScheme(dataHolder: SchemeDataHolder>, + name: String, + attributeProvider: Function): SchemeWrapper { + return LazySchemeWrapper(name, dataHolder, schemeWriter) + } + + override fun getState(scheme: SchemeWrapper) = scheme.schemeState + + override fun isSchemeFile(name: CharSequence) = !StringUtil.equals(name, "profiles_settings.xml") + }, isUseOldFileNameSanitize = true) + + init { + val app = ApplicationManager.getApplication() + if (project.isDirectoryBased || !app.isUnitTestMode) { + schemeManager.loadSchemes() + } + } + + fun mapCopyright(scopeName: String, copyrightProfileName: String) { + scopeToCopyright.put(scopeName, copyrightProfileName) + } + + fun unmapCopyright(scopeName: String) { + scopeToCopyright.remove(scopeName) + } + + fun hasAnyCopyrights(): Boolean { + return defaultCopyright != null || !scopeToCopyright.isEmpty() + } + + override fun getState(): Element? { + val state = Element("settings") + try { + if (!scopeToCopyright.isEmpty()) { + val map = Element(MODULE2COPYRIGHT) + for ((scopeName, profileName) in scopeToCopyright) { + map.element(ELEMENT) + .attribute(MODULE, scopeName) + .attribute(COPYRIGHT, profileName) + } + state.addContent(map) + } + + options.writeExternal(state) + } + catch (e: WriteExternalException) { + LOG.error(e) + return null + } + + if (defaultCopyright != null) { + state.setAttribute(DEFAULT, defaultCopyright!!.name) + } + + return wrapState(state) + } + + override fun loadState(state: Element) { + val moduleToCopyright = state.getChild(MODULE2COPYRIGHT) + if (moduleToCopyright != null) { + for (element in moduleToCopyright.getChildren(ELEMENT)) { + scopeToCopyright.put(element.getAttributeValue(MODULE), element.getAttributeValue(COPYRIGHT)) + } + } + + try { + defaultCopyright = schemeManager.findSchemeByName(state.getAttributeValue(DEFAULT).orEmpty())?.scheme + options.readExternal(state) + } + catch (e: InvalidDataException) { + LOG.error(e) + } + } + + fun addCopyright(profile: CopyrightProfile) { + schemeManager.addScheme(InitializedSchemeWrapper(profile, schemeWriter)) + } + + fun getCopyrights(): Collection = schemeManager.allSchemes.map { it.scheme } + + fun clearMappings() { + scopeToCopyright.clear() + } + + fun removeCopyright(copyrightProfile: CopyrightProfile) { + schemeManager.removeScheme(copyrightProfile.name) + + val it = scopeToCopyright.keys.iterator() + while (it.hasNext()) { + if (scopeToCopyright.get(it.next()) == copyrightProfile.name) { + it.remove() + } + } + } + + fun replaceCopyright(name: String, profile: CopyrightProfile) { + if (defaultCopyright?.name == name) { + defaultCopyright = profile + } + + val existingScheme = schemeManager.findSchemeByName(name) + if (existingScheme == null) { + addCopyright(profile) + } + else { + existingScheme.scheme.copyFrom(profile) + } + } + + fun getCopyrightOptions(file: PsiFile): CopyrightProfile? { + val virtualFile = file.virtualFile + if (virtualFile == null || options.getOptions(virtualFile.fileType.name).getFileTypeOverride() == LanguageOptions.NO_COPYRIGHT) { + return null + } + + val validationManager = DependencyValidationManager.getInstance(project) + for (scopeName in scopeToCopyright.keys) { + val packageSet = validationManager.getScope(scopeName)?.value ?: continue + if (packageSet.contains(file, validationManager)) { + scopeToCopyright.get(scopeName)?.let { schemeManager.findSchemeByName(it) }?.let { return it.scheme } + } + } + return defaultCopyright + } +} + +private class CopyrightManagerPostStartupActivity : StartupActivity { + val newFileTracker = NewFileTracker() + + override fun runActivity(project: Project) { + Disposer.register(project, Disposable { newFileTracker.clear() }) + + EditorFactory.getInstance().eventMulticaster.addDocumentListener(object : DocumentAdapter() { + override fun documentChanged(e: DocumentEvent) { + val virtualFile = FileDocumentManager.getInstance().getFile(e.document) ?: return + val module = ProjectRootManager.getInstance(project).fileIndex.getModuleForFile(virtualFile) ?: return + if (!newFileTracker.poll(virtualFile) || + !FileTypeUtil.getInstance().isSupportedFile(virtualFile) || + PsiManager.getInstance(project).findFile(virtualFile) == null) { + return + } + + ApplicationManager.getApplication().invokeLater(Runnable { + if (!virtualFile.isValid) { + return@Runnable + } + + val file = PsiManager.getInstance(project).findFile(virtualFile) + if (file != null && file.isWritable) { + CopyrightManager.getInstance(project).getCopyrightOptions(file)?.let { + UpdateCopyrightProcessor(project, module, file).run() + } + } + }, ModalityState.NON_MODAL, project.disposed) + } + }, project) + } +} + +private fun wrapScheme(element: Element): Element { + val wrapper = Element("component") + .attribute("name", "CopyrightManager") + wrapper.addContent(element) + return wrapper +} + +private val schemeWriter = { scheme: CopyrightProfile -> + val element = Element("copyright") + scheme.writeExternal(element) + wrapScheme(element) +} + +private class InitializedSchemeWrapper(scheme: CopyrightProfile, private val writer: (scheme: CopyrightProfile) -> Element) : SchemeWrapper(scheme.name) { + override val lazyScheme = lazyOf(scheme) + + override fun writeScheme() = writer(scheme) +} + +private class LazySchemeWrapper(name: String, + dataHolder: SchemeDataHolder>, + private val writer: (scheme: CopyrightProfile) -> Element, + private val subStateTagName: String = "copyright") : SchemeWrapper(name) { + private val dataHolder = AtomicReference(dataHolder) + + override val lazyScheme = lazy { + val scheme = CopyrightProfile() + @Suppress("NAME_SHADOWING") + val dataHolder = this.dataHolder.getAndSet(null) + val element = dataHolder.read().getChild(subStateTagName) + scheme.readExternal(element) + dataHolder.updateDigest(writer(scheme)) + scheme + } + + override fun writeScheme(): Element { + val dataHolder = dataHolder.get() + return if (dataHolder == null) writer(scheme) else dataHolder.read() + } +} \ No newline at end of file diff --git a/plugins/copyright/src/META-INF/plugin.xml b/plugins/copyright/src/META-INF/plugin.xml index 87b49a360163..0a583be018b5 100644 --- a/plugins/copyright/src/META-INF/plugin.xml +++ b/plugins/copyright/src/META-INF/plugin.xml @@ -1,56 +1,50 @@ - - - - Copyright - com.intellij.copyright - - Copyright Notice. This plugin is used to ensure files in a project or module have - a consistent copyright notice. - - 8.1 - JetBrains - com.intellij.modules.java + Copyright + com.intellij.copyright + + Copyright Notice. This plugin is used to ensure files in a project or module have a consistent copyright notice. + + 8.1 + JetBrains + com.intellij.modules.java - - - - - - + + + + + + - - - com.maddyhome.idea.copyright.CopyrightManager - - - + + - - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java b/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java deleted file mode 100644 index be5cebfb2d87..000000000000 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright 2000-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.maddyhome.idea.copyright; - -import com.intellij.openapi.Disposable; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.components.*; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.EditorFactory; -import com.intellij.openapi.editor.event.DocumentAdapter; -import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.editor.event.DocumentListener; -import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.ProjectRootManager; -import com.intellij.openapi.startup.StartupManager; -import com.intellij.openapi.util.*; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.packageDependencies.DependencyValidationManager; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiManager; -import com.intellij.psi.search.scope.packageSet.NamedScope; -import com.intellij.psi.search.scope.packageSet.PackageSet; -import com.maddyhome.idea.copyright.actions.UpdateCopyrightProcessor; -import com.maddyhome.idea.copyright.options.LanguageOptions; -import com.maddyhome.idea.copyright.options.Options; -import com.maddyhome.idea.copyright.util.FileTypeUtil; -import com.maddyhome.idea.copyright.util.NewFileTracker; -import org.jdom.Element; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; - -@State(name = "CopyrightManager", storages = @Storage(value = "copyright", stateSplitter = CopyrightManager.CopyrightStateSplitter.class)) -public class CopyrightManager extends AbstractProjectComponent implements PersistentStateComponent { - private static final Logger LOG = Logger.getInstance("#" + CopyrightManager.class.getName()); - @Nullable - private CopyrightProfile myDefaultCopyright = null; - private final LinkedHashMap myModuleToCopyrights = new LinkedHashMap<>(); - private final Map myCopyrights = new TreeMap<>(); - private final Options myOptions = new Options(); - - public CopyrightManager(@NotNull Project project, - @NotNull final EditorFactory editorFactory, - @NotNull final Application application, - @NotNull final FileDocumentManager fileDocumentManager, - @NotNull final FileTypeUtil fileTypeUtil, - @NotNull final ProjectRootManager projectRootManager, - @NotNull final PsiManager psiManager, - @NotNull StartupManager startupManager) { - super(project); - if (!myProject.isDefault()) { - final NewFileTracker newFileTracker = NewFileTracker.getInstance(); - Disposer.register(myProject, new Disposable() { - @Override - public void dispose() { - newFileTracker.clear(); - } - }); - startupManager.runWhenProjectIsInitialized(() -> { - DocumentListener listener = new DocumentAdapter() { - @Override - public void documentChanged(DocumentEvent e) { - final Document document = e.getDocument(); - final VirtualFile virtualFile = fileDocumentManager.getFile(document); - if (virtualFile == null) return; - final Module module = projectRootManager.getFileIndex().getModuleForFile(virtualFile); - if (module == null) return; - if (!newFileTracker.poll(virtualFile)) return; - if (!fileTypeUtil.isSupportedFile(virtualFile)) return; - if (psiManager.findFile(virtualFile) == null) return; - application.invokeLater(() -> { - if (!virtualFile.isValid()) return; - final PsiFile file = psiManager.findFile(virtualFile); - if (file != null && file.isWritable()) { - final CopyrightProfile opts = getCopyrightOptions(file); - if (opts != null) { - new UpdateCopyrightProcessor(myProject, module, file).run(); - } - } - }, ModalityState.NON_MODAL, myProject.getDisposed()); - } - }; - editorFactory.getEventMulticaster().addDocumentListener(listener, myProject); - }); - } - } - - @NonNls - static final String COPYRIGHT = "copyright"; - @NonNls - private static final String MODULE2COPYRIGHT = "module2copyright"; - @NonNls - private static final String ELEMENT = "element"; - @NonNls - private static final String MODULE = "module"; - @NonNls - private static final String DEFAULT = "default"; - - public static CopyrightManager getInstance(Project project) { - return project.getComponent(CopyrightManager.class); - } - - @Override - @NonNls - @NotNull - public String getComponentName() { - return "CopyrightManager"; - } - - @Override - public Element getState() { - Element state = new Element("settings"); - - try { - if (!myCopyrights.isEmpty()) { - for (CopyrightProfile copyright : myCopyrights.values()) { - Element copyrightElement = new Element(COPYRIGHT); - copyright.serializeInto(copyrightElement, true); - if (!JDOMUtil.isEmpty(copyrightElement)) { - state.addContent(copyrightElement); - } - } - } - - if (!myModuleToCopyrights.isEmpty()) { - final Element map = new Element(MODULE2COPYRIGHT); - for (String moduleName : myModuleToCopyrights.keySet()) { - final Element setting = new Element(ELEMENT); - setting.setAttribute(MODULE, moduleName); - setting.setAttribute(COPYRIGHT, myModuleToCopyrights.get(moduleName)); - map.addContent(setting); - } - state.addContent(map); - } - - myOptions.writeExternal(state); - } - catch (WriteExternalException e) { - LOG.error(e); - return null; - } - - if (myDefaultCopyright != null) { - state.setAttribute(DEFAULT, myDefaultCopyright.getName()); - } - - return state; - } - - @Override - public void loadState(Element state) { - clearCopyrights(); - - final Element moduleToCopyright = state.getChild(MODULE2COPYRIGHT); - if (moduleToCopyright != null) { - for (Element element : moduleToCopyright.getChildren(ELEMENT)) { - myModuleToCopyrights.put(element.getAttributeValue(MODULE), element.getAttributeValue(COPYRIGHT)); - } - } - - try { - for (Element element : state.getChildren(COPYRIGHT)) { - final CopyrightProfile copyrightProfile = new CopyrightProfile(); - copyrightProfile.readExternal(element); - myCopyrights.put(copyrightProfile.getName(), copyrightProfile); - } - myDefaultCopyright = myCopyrights.get(StringUtil.notNullize(state.getAttributeValue(DEFAULT))); - myOptions.readExternal(state); - } - catch (InvalidDataException e) { - LOG.error(e); - } - } - - public Map getCopyrightsMapping() { - return myModuleToCopyrights; - } - - public void setDefaultCopyright(@Nullable CopyrightProfile copyright) { - myDefaultCopyright = copyright; - } - - @Nullable - public CopyrightProfile getDefaultCopyright() { - return myDefaultCopyright; - } - - public void addCopyright(CopyrightProfile copyrightProfile) { - myCopyrights.put(copyrightProfile.getName(), copyrightProfile); - } - - public void removeCopyright(CopyrightProfile copyrightProfile) { - myCopyrights.values().remove(copyrightProfile); - for (Iterator it = myModuleToCopyrights.keySet().iterator(); it.hasNext();) { - final String profileName = myModuleToCopyrights.get(it.next()); - if (profileName.equals(copyrightProfile.getName())) { - it.remove(); - } - } - } - - public void clearCopyrights() { - myDefaultCopyright = null; - myCopyrights.clear(); - myModuleToCopyrights.clear(); - } - - public void mapCopyright(String scopeName, String copyrightProfileName) { - myModuleToCopyrights.put(scopeName, copyrightProfileName); - } - - public void unmapCopyright(String scopeName) { - myModuleToCopyrights.remove(scopeName); - } - - public Collection getCopyrights() { - return myCopyrights.values(); - } - - public boolean hasAnyCopyrights() { - return myDefaultCopyright != null || !myModuleToCopyrights.isEmpty(); - } - - @Nullable - public CopyrightProfile getCopyrightOptions(@NotNull PsiFile file) { - final VirtualFile virtualFile = file.getVirtualFile(); - if (virtualFile == null || myOptions.getOptions(virtualFile.getFileType().getName()).getFileTypeOverride() == LanguageOptions.NO_COPYRIGHT) return null; - final DependencyValidationManager validationManager = DependencyValidationManager.getInstance(myProject); - for (String scopeName : myModuleToCopyrights.keySet()) { - final NamedScope namedScope = validationManager.getScope(scopeName); - if (namedScope != null) { - final PackageSet packageSet = namedScope.getValue(); - if (packageSet != null) { - if (packageSet.contains(file, validationManager)) { - final CopyrightProfile profile = myCopyrights.get(myModuleToCopyrights.get(scopeName)); - if (profile != null) { - return profile; - } - } - } - } - } - return myDefaultCopyright != null ? myDefaultCopyright : null; - } - - public Options getOptions() { - return myOptions; - } - - public void replaceCopyright(String displayName, CopyrightProfile copyrightProfile) { - if (myDefaultCopyright != null && Comparing.strEqual(myDefaultCopyright.getName(), displayName)) { - myDefaultCopyright = copyrightProfile; - } - myCopyrights.remove(displayName); - addCopyright(copyrightProfile); - } - - static final class CopyrightStateSplitter extends MainConfigurationStateSplitter { - @NotNull - @Override - protected String getComponentStateFileName() { - return "profiles_settings"; - } - - @NotNull - @Override - protected String getSubStateTagName() { - return COPYRIGHT; - } - } -} diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/AbstractFileProcessor.java b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/AbstractFileProcessor.java index fe6870b349f4..7b020a0e6597 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/AbstractFileProcessor.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/AbstractFileProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package com.maddyhome.idea.copyright.actions; import com.intellij.codeInsight.FileModificationService; +import com.intellij.copyright.CopyrightManager; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; @@ -30,13 +31,12 @@ import com.intellij.openapi.roots.ContentIterator; import com.intellij.openapi.roots.ModuleFileIndex; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.vfs.ReadonlyStatusHandler; -import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.util.IncorrectOperationException; -import com.maddyhome.idea.copyright.CopyrightManager; import com.maddyhome.idea.copyright.CopyrightProfile; import com.maddyhome.idea.copyright.util.FileTypeUtil; import org.jetbrains.annotations.NotNull; @@ -51,39 +51,11 @@ public abstract class AbstractFileProcessor { private PsiDirectory directory = null; private PsiFile file = null; private PsiFile[] files = null; - private boolean subdirs = false; private final String message; private final String title; protected abstract Runnable preprocessFile(PsiFile file, boolean allowReplacement) throws IncorrectOperationException; - protected AbstractFileProcessor(Project project, String title, String message) { - myProject = project; - myModule = null; - directory = null; - subdirs = true; - this.title = title; - this.message = message; - } - - protected AbstractFileProcessor(Project project, Module module, String title, String message) { - myProject = project; - myModule = module; - directory = null; - subdirs = true; - this.title = title; - this.message = message; - } - - protected AbstractFileProcessor(Project project, PsiDirectory dir, boolean subdirs, String title, String message) { - myProject = project; - myModule = null; - directory = dir; - this.subdirs = subdirs; - this.message = message; - this.title = title; - } - protected AbstractFileProcessor(Project project, PsiFile file, String title, String message) { myProject = project; myModule = null; @@ -92,7 +64,7 @@ public abstract class AbstractFileProcessor { this.title = title; } - protected AbstractFileProcessor(Project project, PsiFile[] files, String title, String message, Runnable runnable) { + protected AbstractFileProcessor(Project project, PsiFile[] files, String title, String message) { myProject = project; myModule = null; this.files = files; @@ -102,7 +74,7 @@ public abstract class AbstractFileProcessor { public void run() { if (directory != null) { - process(directory, subdirs); + process(directory, false); } else if (files != null) { process(files); @@ -275,7 +247,7 @@ public abstract class AbstractFileProcessor { for (PsiFile psiFile : files) { vFiles.add(psiFile.getVirtualFile()); } - if (!ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(VfsUtil.toVirtualFileArray(vFiles)) + if (!ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(VfsUtilCore.toVirtualFileArray(vFiles)) .hasReadonlyFiles()) { if (!files.isEmpty()) { final Runnable[] resultRunnable = new Runnable[1]; @@ -296,15 +268,12 @@ public abstract class AbstractFileProcessor { if (opts != null && FileTypeUtil.isSupportedFile(local)) { files.add(local); } - } if (subdirs) { - PsiDirectory[] dirs = directory.getSubdirectories(); - for (PsiDirectory dir : dirs) { - findFiles(files, dir, subdirs); + for (PsiDirectory dir : directory.getSubdirectories()) { + findFiles(files, dir, true); } - } } diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/GenerateCopyrightAction.java b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/GenerateCopyrightAction.java index 2a1b9c9df186..c077ccb6b7b1 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/GenerateCopyrightAction.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/GenerateCopyrightAction.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.maddyhome.idea.copyright.actions; +import com.intellij.copyright.CopyrightManager; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.module.Module; @@ -24,7 +24,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; -import com.maddyhome.idea.copyright.CopyrightManager; import com.maddyhome.idea.copyright.ui.CopyrightProjectConfigurable; import com.maddyhome.idea.copyright.util.FileTypeUtil; import org.jetbrains.annotations.Nullable; diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/UpdateCopyrightAction.java b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/UpdateCopyrightAction.java index 7d096633ab1d..b219fc4c28a6 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/UpdateCopyrightAction.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/UpdateCopyrightAction.java @@ -20,6 +20,7 @@ import com.intellij.analysis.AnalysisScope; import com.intellij.analysis.BaseAnalysisAction; import com.intellij.analysis.BaseAnalysisActionDialog; import com.intellij.codeInsight.FileModificationService; +import com.intellij.copyright.CopyrightManager; import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.command.CommandProcessor; @@ -37,7 +38,6 @@ import com.intellij.psi.*; import com.intellij.ui.TitledSeparator; import com.intellij.util.SequentialModalProgressTask; import com.intellij.util.SequentialTask; -import com.maddyhome.idea.copyright.CopyrightManager; import com.maddyhome.idea.copyright.pattern.FileUtil; import com.maddyhome.idea.copyright.util.FileTypeUtil; import org.jetbrains.annotations.NotNull; diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/UpdateCopyrightProcessor.java b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/UpdateCopyrightProcessor.java index e2fc2cdfb9db..c11ea431faea 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/UpdateCopyrightProcessor.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/UpdateCopyrightProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.maddyhome.idea.copyright.actions; +import com.intellij.copyright.CopyrightManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.progress.ProgressIndicator; @@ -24,10 +25,8 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.EmptyRunnable; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; -import com.maddyhome.idea.copyright.CopyrightManager; import com.maddyhome.idea.copyright.CopyrightProfile; import com.maddyhome.idea.copyright.psi.UpdateCopyright; import com.maddyhome.idea.copyright.psi.UpdateCopyrightFactory; @@ -39,18 +38,6 @@ public class UpdateCopyrightProcessor extends AbstractFileProcessor public static final String TITLE = "Update Copyright"; public static final String MESSAGE = "Updating copyrights..."; - public UpdateCopyrightProcessor(Project project, Module module) - { - super(project, module, TITLE, MESSAGE); - setup(project, module); - } - - public UpdateCopyrightProcessor(Project project, Module module, PsiDirectory dir, boolean subdirs) - { - super(project, dir, subdirs, TITLE, MESSAGE); - setup(project, module); - } - public UpdateCopyrightProcessor(Project project, Module module, PsiFile file) { super(project, file, TITLE, MESSAGE); @@ -59,7 +46,7 @@ public class UpdateCopyrightProcessor extends AbstractFileProcessor public UpdateCopyrightProcessor(Project project, Module module, PsiFile[] files) { - super(project, files, TITLE, MESSAGE, null); + super(project, files, TITLE, MESSAGE); setup(project, module); } diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/pattern/VelocityHelper.java b/plugins/copyright/src/com/maddyhome/idea/copyright/pattern/VelocityHelper.java index d3c5e74a945d..94fe8871cfd9 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/pattern/VelocityHelper.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/pattern/VelocityHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.maddyhome.idea.copyright.pattern; +import com.intellij.copyright.CopyrightManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; @@ -23,7 +24,6 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiUtilCore; -import com.maddyhome.idea.copyright.CopyrightManager; import org.apache.commons.collections.ExtendedProperties; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/psi/AbstractUpdateCopyright.java b/plugins/copyright/src/com/maddyhome/idea/copyright/psi/AbstractUpdateCopyright.java index ad21b02c514a..a67b2ff727d3 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/psi/AbstractUpdateCopyright.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/psi/AbstractUpdateCopyright.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,13 +16,13 @@ package com.maddyhome.idea.copyright.psi; +import com.intellij.copyright.CopyrightManager; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiManager; -import com.maddyhome.idea.copyright.CopyrightManager; import com.maddyhome.idea.copyright.CopyrightProfile; import com.maddyhome.idea.copyright.options.LanguageOptions; import com.maddyhome.idea.copyright.pattern.EntityUtil; diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java b/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java index 02ee5ccb1502..77827b278585 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.maddyhome.idea.copyright.psi; +import com.intellij.copyright.CopyrightManager; import com.intellij.lang.Commenter; import com.intellij.lang.LanguageCommenters; import com.intellij.openapi.command.WriteCommandAction; @@ -31,7 +32,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.IncorrectOperationException; -import com.maddyhome.idea.copyright.CopyrightManager; import com.maddyhome.idea.copyright.CopyrightProfile; import com.maddyhome.idea.copyright.options.LanguageOptions; import com.maddyhome.idea.copyright.util.FileTypeUtil; diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/CopyrightConfigurable.java b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/CopyrightConfigurable.java index d14dcdaf88fa..ae0938cc4fd0 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/CopyrightConfigurable.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/CopyrightConfigurable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.maddyhome.idea.copyright.ui; +import com.intellij.copyright.CopyrightManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.SpellCheckingEditorCustomizationProvider; import com.intellij.openapi.fileTypes.FileTypes; @@ -28,12 +29,12 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.*; import com.intellij.util.DocumentUtil; import com.intellij.util.containers.ContainerUtil; -import com.maddyhome.idea.copyright.CopyrightManager; import com.maddyhome.idea.copyright.CopyrightProfile; import com.maddyhome.idea.copyright.pattern.EntityUtil; import com.maddyhome.idea.copyright.pattern.VelocityHelper; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -59,7 +60,7 @@ public class CopyrightConfigurable extends NamedConfigurable { private JTextField myAllowReplaceTextField; private JPanel myEditorPanel; - public CopyrightConfigurable(Project project, CopyrightProfile copyrightProfile, Runnable updater) { + public CopyrightConfigurable(@NotNull Project project, CopyrightProfile copyrightProfile, Runnable updater) { super(true, updater); myProject = project; myCopyrightProfile = copyrightProfile; @@ -130,6 +131,7 @@ public class CopyrightConfigurable extends NamedConfigurable { catch (PatternSyntaxException e) { throw new ConfigurationException("Keyword pattern syntax is incorrect: " + e.getMessage()); } + myCopyrightProfile.setKeyword(keyword); myCopyrightProfile.setAllowReplaceKeyword(myAllowReplaceTextField.getText().trim()); CopyrightManager.getInstance(myProject).replaceCopyright(myDisplayName, myCopyrightProfile); diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/CopyrightProfilesPanel.java b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/CopyrightProfilesPanel.java index 57bc6e9260b3..17b6d6753f5e 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/CopyrightProfilesPanel.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/CopyrightProfilesPanel.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.maddyhome.idea.copyright.ui; +import com.intellij.copyright.CopyrightManager; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonShortcuts; @@ -37,14 +37,10 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.PopupStep; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.vfs.VfsUtilCore; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.Consumer; import com.intellij.util.IconUtil; import com.intellij.util.PlatformIcons; import com.intellij.util.containers.HashMap; -import com.maddyhome.idea.copyright.CopyrightManager; import com.maddyhome.idea.copyright.CopyrightProfile; import com.maddyhome.idea.copyright.options.ExternalOptionHelper; import org.jetbrains.annotations.Nls; @@ -90,15 +86,11 @@ public class CopyrightProfilesPanel extends MasterDetailsComponent implements Se @Override protected void processRemovedItems() { Map profiles = getAllProfiles(); - final List deleted = new ArrayList<>(); - for (CopyrightProfile profile : myManager.getCopyrights()) { + for (CopyrightProfile profile : new ArrayList<>(myManager.getCopyrights())) { if (!profiles.containsValue(profile)) { - deleted.add(profile); + myManager.removeCopyright(profile); } } - for (CopyrightProfile profile : deleted) { - myManager.removeCopyright(profile); - } } @Override @@ -174,10 +166,10 @@ public class CopyrightProfilesPanel extends MasterDetailsComponent implements Se @Override public void actionPerformed(AnActionEvent event) { - final String name = askForProfileName("Create Copyright Profile", ""); - if (name == null) return; - final CopyrightProfile copyrightProfile = new CopyrightProfile(name); - addProfileNode(copyrightProfile); + String name = askForProfileName("Create Copyright Profile", ""); + if (name != null) { + addProfileNode(new CopyrightProfile(name)); + } } }); result.add(new MyDeleteAction()); @@ -188,9 +180,12 @@ public class CopyrightProfilesPanel extends MasterDetailsComponent implements Se @Override public void actionPerformed(AnActionEvent event) { - final String profileName = askForProfileName("Copy Copyright Profile", ""); - if (profileName == null) return; - final CopyrightProfile clone = new CopyrightProfile(); + String profileName = askForProfileName("Copy Copyright Profile", ""); + if (profileName == null) { + return; + } + + CopyrightProfile clone = new CopyrightProfile(); clone.copyFrom((CopyrightProfile)getSelectedObject()); clone.setName(profileName); addProfileNode(clone); @@ -268,7 +263,7 @@ public class CopyrightProfilesPanel extends MasterDetailsComponent implements Se }); } - private void addProfileNode(CopyrightProfile copyrightProfile) { + private void addProfileNode(@NotNull CopyrightProfile copyrightProfile) { final CopyrightConfigurable copyrightConfigurable = new CopyrightConfigurable(myProject, copyrightProfile, TREE_UPDATER); copyrightConfigurable.setModified(true); final MyNode node = new MyNode(copyrightConfigurable); diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/ProjectSettingsPanel.java b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/ProjectSettingsPanel.java index 541922f92269..e26f64eacc20 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/ProjectSettingsPanel.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/ProjectSettingsPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,15 +15,16 @@ */ package com.maddyhome.idea.copyright.ui; +import com.intellij.copyright.CopyrightManager; import com.intellij.ide.DataManager; import com.intellij.ide.util.scopeChooser.PackageSetChooserCombo; import com.intellij.ide.util.scopeChooser.ScopeChooserConfigurable; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.options.ex.Settings; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.LabeledComponent; import com.intellij.openapi.util.Comparing; -import com.intellij.packageDependencies.DefaultScopesProvider; import com.intellij.packageDependencies.DependencyValidationManager; import com.intellij.psi.search.scope.packageSet.CustomScopesProviderEx; import com.intellij.psi.search.scope.packageSet.NamedScope; @@ -34,9 +35,7 @@ import com.intellij.ui.ListCellRendererWrapper; import com.intellij.ui.ToolbarDecorator; import com.intellij.ui.components.editors.JBComboBoxTableCellEditorComponent; import com.intellij.ui.table.TableView; -import com.intellij.util.Function; import com.intellij.util.ui.*; -import com.maddyhome.idea.copyright.CopyrightManager; import com.maddyhome.idea.copyright.CopyrightProfile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -58,7 +57,7 @@ public class ProjectSettingsPanel { private final TableView myScopeMappingTable; private final ListTableModel myScopeMappingModel; - private final JComboBox myProfilesComboBox = new JComboBox(); + private final JComboBox myProfilesComboBox = new ComboBox(); private final HyperlinkLabel myScopesLink = new HyperlinkLabel(); @@ -135,7 +134,7 @@ public class ProjectSettingsPanel { ElementProducer producer = new ElementProducer() { @Override public ScopeSetting createElement() { - return new ScopeSetting(DefaultScopesProvider.getAllScope(), myProfilesModel.getAllProfiles().values().iterator().next()); + return new ScopeSetting(CustomScopesProviderEx.getAllScope(), myProfilesModel.getAllProfiles().values().iterator().next()); } @Override @@ -158,7 +157,7 @@ public class ProjectSettingsPanel { if (defaultCopyright == null) return true; if (!defaultCopyright.equals(selected)) return true; } - final Map map = myManager.getCopyrightsMapping(); + final Map map = myManager.getScopeToCopyright(); if (map.size() != myScopeMappingModel.getItems().size()) return true; final Iterator iterator = map.keySet().iterator(); for (ScopeSetting setting : myScopeMappingModel.getItems()) { @@ -174,22 +173,17 @@ public class ProjectSettingsPanel { } public void apply() { - Collection profiles = new ArrayList<>(myManager.getCopyrights()); - myManager.clearCopyrights(); - for (CopyrightProfile profile : profiles) { - myManager.addCopyright(profile); - } - final List settingList = myScopeMappingModel.getItems(); - for (ScopeSetting scopeSetting : settingList) { + myManager.setDefaultCopyright((CopyrightProfile)myProfilesComboBox.getSelectedItem()); + myManager.clearMappings(); + for (ScopeSetting scopeSetting : myScopeMappingModel.getItems()) { myManager.mapCopyright(scopeSetting.getScope().getName(), scopeSetting.getProfileName()); } - myManager.setDefaultCopyright((CopyrightProfile)myProfilesComboBox.getSelectedItem()); } public void reset() { myProfilesComboBox.setSelectedItem(myManager.getDefaultCopyright()); final List mappings = new ArrayList<>(); - final Map copyrights = myManager.getCopyrightsMapping(); + final Map copyrights = myManager.getScopeToCopyright(); final DependencyValidationManager manager = DependencyValidationManager.getInstance(myProject); final Set scopes2Unmap = new HashSet<>(); for (final String scopeName : copyrights.keySet()) { @@ -207,7 +201,6 @@ public class ProjectSettingsPanel { myScopeMappingModel.setItems(mappings); } - private class ScopeSetting { private NamedScope myScope; private CopyrightProfile myProfile; diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/TemplateCommentPanel.java b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/TemplateCommentPanel.java index 515afd30f3f0..ba2231a3ab8b 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/TemplateCommentPanel.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/TemplateCommentPanel.java @@ -16,6 +16,7 @@ package com.maddyhome.idea.copyright.ui; +import com.intellij.copyright.CopyrightManager; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorFontType; import com.intellij.openapi.fileTypes.FileType; @@ -27,7 +28,6 @@ import com.intellij.openapi.project.Project; import com.intellij.ui.DocumentAdapter; import com.intellij.uiDesigner.core.GridConstraints; import com.intellij.util.ui.UIUtil; -import com.maddyhome.idea.copyright.CopyrightManager; import com.maddyhome.idea.copyright.CopyrightProfile; import com.maddyhome.idea.copyright.options.LanguageOptions; import com.maddyhome.idea.copyright.options.Options; @@ -82,10 +82,7 @@ public class TemplateCommentPanel implements SearchableConfigurable { private void updateBox() { boolean enable = true; - if (!cbSeparatorBefore.isSelected()) { - enable = false; - } - else if (!cbSeparatorAfter.isSelected()) { + if (!cbSeparatorBefore.isSelected() || !cbSeparatorAfter.isSelected()) { enable = false; } else { @@ -336,8 +333,8 @@ public class TemplateCommentPanel implements SearchableConfigurable { mySeparatorCharLabel.setEnabled(true); updateBox(); } else { - UIUtil.setEnabled(myCommentTypePanel, enable, true); - UIUtil.setEnabled(myBorderPanel, enable, true); + UIUtil.setEnabled(myCommentTypePanel, false, true); + UIUtil.setEnabled(myBorderPanel, false, true); } } diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/util/NewFileTracker.java b/plugins/copyright/src/com/maddyhome/idea/copyright/util/NewFileTracker.java index ad68be5d10b6..84a91150c35a 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/util/NewFileTracker.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/util/NewFileTracker.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,17 +24,14 @@ import java.util.Collections; import java.util.Set; public class NewFileTracker { - public static NewFileTracker getInstance() { - return instance; - } + private final Set newFiles = Collections.synchronizedSet(new THashSet()); public boolean poll(@NotNull VirtualFile file) { return newFiles.remove(file); } - private NewFileTracker() { - final VirtualFileManager virtualFileManager = VirtualFileManager.getInstance(); - virtualFileManager.addVirtualFileListener(new VirtualFileAdapter() { + public NewFileTracker() { + VirtualFileManager.getInstance().addVirtualFileListener(new VirtualFileAdapter() { @Override public void fileCreated(@NotNull VirtualFileEvent event) { if (event.isFromRefresh()) return; @@ -49,9 +46,6 @@ public class NewFileTracker { }); } - private final Set newFiles = Collections.synchronizedSet(new THashSet()); - private static final NewFileTracker instance = new NewFileTracker(); - public void clear() { newFiles.clear(); } From 677cd104433dd81f745afa5a6f581c0480f355e4 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 31 Aug 2016 16:33:30 +0300 Subject: [PATCH 55/63] severities: do not create array of the same length; ensure errors are not copied when the length changes (IDEA-160495) --- .../codeInsight/daemon/impl/TrafficLightRenderer.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java index 9153a80dd67d..4ec77f5e5b8c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java @@ -115,12 +115,8 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable { private void refresh() { int maxIndex = mySeverityRegistrar.getSeverityMaxIndex(); - if (errorCount != null && maxIndex == errorCount.length) return; - int[] newErrors = new int[maxIndex+1]; - if (errorCount != null) { - System.arraycopy(errorCount, 0, newErrors, 0, Math.min(errorCount.length, newErrors.length)); - } - errorCount = newErrors; + if (errorCount != null && maxIndex + 1 == errorCount.length) return; + errorCount = new int[maxIndex + 1]; } static void setOrRefreshErrorStripeRenderer(@NotNull EditorMarkupModel editorMarkupModel, @@ -334,7 +330,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable { Icon icon = AllIcons.General.InspectionsOK; for (int i = status.errorCount.length - 1; i >= 0; i--) { - if (status.errorCount[i] != 0) { + if (status.errorCount[i] > 0) { icon = SeverityRegistrar.getSeverityRegistrar(project).getRendererIconByIndex(i); break; } From 897432908ce5707e5735584584024bbc63dcfcaf Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 31 Aug 2016 16:36:03 +0300 Subject: [PATCH 56/63] remove conflicting mnemonics from settings (IDEA-160537) --- .../src/messages/InspectionsBundle.properties | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/platform/platform-resources-en/src/messages/InspectionsBundle.properties b/platform/platform-resources-en/src/messages/InspectionsBundle.properties index ca0f3b785cd1..bd39fea46863 100644 --- a/platform/platform-resources-en/src/messages/InspectionsBundle.properties +++ b/platform/platform-resources-en/src/messages/InspectionsBundle.properties @@ -317,13 +317,13 @@ inspection.javadoc.html.not.required.label.text=Additional Not Required Html Att inspection.javadoc.html.not.required.dialog.title=Edit Additional Not Required Html Attributes inspection.required.attributes.display.name=Missing required attribute -inspection.unused.symbol.check.localvars=&Local variables (Editor only) -inspection.unused.symbol.check.fields=&Fields: -inspection.unused.symbol.check.methods=&Methods: -inspection.unused.symbol.check.accessors=&Getters/setters -inspection.unused.symbol.check.classes=&Classes: -inspection.unused.symbol.check.inner.classes=&Inner classes: -inspection.unused.symbol.check.parameters=&Parameters in +inspection.unused.symbol.check.localvars=Local variables (Editor only) +inspection.unused.symbol.check.fields=Fields: +inspection.unused.symbol.check.methods=Methods: +inspection.unused.symbol.check.accessors=Getters/setters +inspection.unused.symbol.check.classes=Classes: +inspection.unused.symbol.check.inner.classes=Inner classes: +inspection.unused.symbol.check.parameters=Parameters in inspection.results.for.profile.toolwindow.title=''{0}'' Profile on {1} inspection.results.for.inspection.toolwindow.title=''{0}'' Inspection on {1} From 2a0ea218f3d145c0d884ef50eabed365d084ceb0 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Wed, 31 Aug 2016 15:46:10 +0200 Subject: [PATCH 57/63] =?UTF-8?q?scheme-based=20copyright=20manager=20?= =?UTF-8?q?=E2=80=94=20lazy=20default=20profile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectInspectionProfileManager.kt | 34 +++++++------- .../configurationStore/scheme-impl.kt | 6 +++ plugins/copyright/src/CopyrightManager.kt | 45 +++++++++---------- .../copyright/ui/ProjectSettingsPanel.java | 8 ++-- 4 files changed, 46 insertions(+), 47 deletions(-) diff --git a/platform/analysis-impl/src/com/intellij/profile/codeInspection/ProjectInspectionProfileManager.kt b/platform/analysis-impl/src/com/intellij/profile/codeInspection/ProjectInspectionProfileManager.kt index dcd1697edf70..cf06a8f296f8 100644 --- a/platform/analysis-impl/src/com/intellij/profile/codeInspection/ProjectInspectionProfileManager.kt +++ b/platform/analysis-impl/src/com/intellij/profile/codeInspection/ProjectInspectionProfileManager.kt @@ -209,6 +209,23 @@ class ProjectInspectionProfileManager(val project: Project, } } + @Synchronized override fun getState(): Element? { + val result = Element("settings") + + schemeManagerIprProvider?.writeState(result) + + val state = this.state + state.projectProfile = schemeManager.currentSchemeName + XmlSerializer.serializeInto(state, result, skipDefaultsSerializationFilter) + if (!result.children.isEmpty()) { + result.addContent(Element("version").setAttribute("value", VERSION)) + } + + severityRegistrar.writeExternal(result) + + return wrapState(result) + } + @Synchronized override fun loadState(state: Element) { val data = state.getChild("settings") @@ -250,23 +267,6 @@ class ProjectInspectionProfileManager(val project: Project, } } - @Synchronized override fun getState(): Element? { - val result = Element("settings") - - schemeManagerIprProvider?.writeState(result) - - val state = this.state - state.projectProfile = schemeManager.currentSchemeName - XmlSerializer.serializeInto(state, result, skipDefaultsSerializationFilter) - if (!result.children.isEmpty()) { - result.addContent(Element("version").setAttribute("value", VERSION)) - } - - severityRegistrar.writeExternal(result) - - return wrapState(result) - } - override fun getScopesManager() = scopeManager @Synchronized override fun getProfiles(): Collection { diff --git a/platform/projectModel-impl/src/com/intellij/configurationStore/scheme-impl.kt b/platform/projectModel-impl/src/com/intellij/configurationStore/scheme-impl.kt index eda2ab4802b8..abf0dd809862 100644 --- a/platform/projectModel-impl/src/com/intellij/configurationStore/scheme-impl.kt +++ b/platform/projectModel-impl/src/com/intellij/configurationStore/scheme-impl.kt @@ -105,6 +105,12 @@ abstract class SchemeWrapper(name: String) : ExternalizableSchem } } +class InitializedSchemeWrapper(scheme: T, private val writer: (scheme: T) -> Element) : SchemeWrapper(scheme.name) { + override val lazyScheme = lazyOf(scheme) + + override fun writeScheme() = writer(scheme) +} + fun wrapState(element: Element): Element { if (element.isEmpty()) { element.name = "state" diff --git a/plugins/copyright/src/CopyrightManager.kt b/plugins/copyright/src/CopyrightManager.kt index b9605666c44c..df933e30f966 100644 --- a/plugins/copyright/src/CopyrightManager.kt +++ b/plugins/copyright/src/CopyrightManager.kt @@ -15,10 +15,7 @@ */ package com.intellij.copyright -import com.intellij.configurationStore.LazySchemeProcessor -import com.intellij.configurationStore.SchemeDataHolder -import com.intellij.configurationStore.SchemeWrapper -import com.intellij.configurationStore.wrapState +import com.intellij.configurationStore.* import com.intellij.openapi.Disposable import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ModalityState @@ -71,7 +68,14 @@ class CopyrightManager(private val project: Project, schemeManagerFactory: Schem fun getInstance(project: Project) = project.service() } - var defaultCopyright: CopyrightProfile? = null + private var defaultCopyrightName: String? = null + + var defaultCopyright: CopyrightProfile? + get() = defaultCopyrightName?.let { schemeManager.findSchemeByName(it)?.scheme } + set(value) { + defaultCopyrightName = value?.name + } + val scopeToCopyright = LinkedHashMap() val options = Options() @@ -103,11 +107,11 @@ class CopyrightManager(private val project: Project, schemeManagerFactory: Schem } fun hasAnyCopyrights(): Boolean { - return defaultCopyright != null || !scopeToCopyright.isEmpty() + return defaultCopyrightName != null || !scopeToCopyright.isEmpty() } override fun getState(): Element? { - val state = Element("settings") + val result = Element("settings") try { if (!scopeToCopyright.isEmpty()) { val map = Element(MODULE2COPYRIGHT) @@ -116,25 +120,26 @@ class CopyrightManager(private val project: Project, schemeManagerFactory: Schem .attribute(MODULE, scopeName) .attribute(COPYRIGHT, profileName) } - state.addContent(map) + result.addContent(map) } - options.writeExternal(state) + options.writeExternal(result) } catch (e: WriteExternalException) { LOG.error(e) return null } - if (defaultCopyright != null) { - state.setAttribute(DEFAULT, defaultCopyright!!.name) + defaultCopyrightName?.let { + result.setAttribute(DEFAULT, it) } - return wrapState(state) + return wrapState(result) } override fun loadState(state: Element) { - val moduleToCopyright = state.getChild(MODULE2COPYRIGHT) + val data = state.getChild("settings") + val moduleToCopyright = data.getChild(MODULE2COPYRIGHT) if (moduleToCopyright != null) { for (element in moduleToCopyright.getChildren(ELEMENT)) { scopeToCopyright.put(element.getAttributeValue(MODULE), element.getAttributeValue(COPYRIGHT)) @@ -142,8 +147,8 @@ class CopyrightManager(private val project: Project, schemeManagerFactory: Schem } try { - defaultCopyright = schemeManager.findSchemeByName(state.getAttributeValue(DEFAULT).orEmpty())?.scheme - options.readExternal(state) + defaultCopyrightName = data.getAttributeValue(DEFAULT) + options.readExternal(data) } catch (e: InvalidDataException) { LOG.error(e) @@ -172,10 +177,6 @@ class CopyrightManager(private val project: Project, schemeManagerFactory: Schem } fun replaceCopyright(name: String, profile: CopyrightProfile) { - if (defaultCopyright?.name == name) { - defaultCopyright = profile - } - val existingScheme = schemeManager.findSchemeByName(name) if (existingScheme == null) { addCopyright(profile) @@ -248,12 +249,6 @@ private val schemeWriter = { scheme: CopyrightProfile -> wrapScheme(element) } -private class InitializedSchemeWrapper(scheme: CopyrightProfile, private val writer: (scheme: CopyrightProfile) -> Element) : SchemeWrapper(scheme.name) { - override val lazyScheme = lazyOf(scheme) - - override fun writeScheme() = writer(scheme) -} - private class LazySchemeWrapper(name: String, dataHolder: SchemeDataHolder>, private val writer: (scheme: CopyrightProfile) -> Element, diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/ProjectSettingsPanel.java b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/ProjectSettingsPanel.java index e26f64eacc20..98aac77dd502 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/ProjectSettingsPanel.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/ProjectSettingsPanel.java @@ -150,12 +150,10 @@ public class ProjectSettingsPanel { } public boolean isModified() { - final CopyrightProfile defaultCopyright = myManager.getDefaultCopyright(); + CopyrightProfile defaultCopyright = myManager.getDefaultCopyright(); final Object selected = myProfilesComboBox.getSelectedItem(); - if (defaultCopyright != selected) { - if (selected == null) return true; - if (defaultCopyright == null) return true; - if (!defaultCopyright.equals(selected)) return true; + if (defaultCopyright != selected && (selected == null || defaultCopyright == null || !defaultCopyright.equals(selected))) { + return true; } final Map map = myManager.getScopeToCopyright(); if (map.size() != myScopeMappingModel.getItems().size()) return true; From 4a31e2f3c3925f3606ee2a505a15a9d6ef3a70bb Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 31 Aug 2016 16:55:58 +0300 Subject: [PATCH 58/63] IDEA-160474 File Templates: 'Enable Live Templates' checkbox is cleared on restart: fix test --- .../ide/fileTemplates/impl/LightFileTemplatesTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/ide/fileTemplates/impl/LightFileTemplatesTest.java b/platform/platform-tests/testSrc/com/intellij/ide/fileTemplates/impl/LightFileTemplatesTest.java index f925c43f6fcb..f628f6e7a365 100644 --- a/platform/platform-tests/testSrc/com/intellij/ide/fileTemplates/impl/LightFileTemplatesTest.java +++ b/platform/platform-tests/testSrc/com/intellij/ide/fileTemplates/impl/LightFileTemplatesTest.java @@ -182,12 +182,12 @@ public class LightFileTemplatesTest extends LightPlatformTestCase { FileTemplateBase template = (FileTemplateBase)myTemplateManager.getTemplate("templateWithLiveTemplate.txt"); assertTrue(template.isLiveTemplateEnabledByDefault()); FileTemplateSettings settings = ServiceManager.getService(ExportableFileTemplateSettings.class); - assertNull(settings.getState()); + assertEquals(0, settings.getState().getContentSize()); template.setLiveTemplateEnabled(false); Element state = settings.getState(); assertNotNull(state); template.setLiveTemplateEnabled(true); - assertNull(settings.getState()); + assertEquals(0, settings.getState().getContentSize()); } private FileTemplateManagerImpl myTemplateManager; From acb8b0843bfac5bcfca4aac1c2ba17bace5e5268 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Wed, 31 Aug 2016 16:23:12 +0200 Subject: [PATCH 59/63] =?UTF-8?q?scheme-based=20copyright=20manager=20?= =?UTF-8?q?=E2=80=94=20ipr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/copyright/src/CopyrightManager.kt | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/plugins/copyright/src/CopyrightManager.kt b/plugins/copyright/src/CopyrightManager.kt index df933e30f966..046b415dc40d 100644 --- a/plugins/copyright/src/CopyrightManager.kt +++ b/plugins/copyright/src/CopyrightManager.kt @@ -79,6 +79,8 @@ class CopyrightManager(private val project: Project, schemeManagerFactory: Schem val scopeToCopyright = LinkedHashMap() val options = Options() + private val schemeManagerIprProvider = if (project.isDirectoryBased) null else SchemeManagerIprProvider() + val schemeManager = schemeManagerFactory.create("copyright", object : LazySchemeProcessor, SchemeWrapper>() { override fun createScheme(dataHolder: SchemeDataHolder>, name: String, @@ -89,7 +91,7 @@ class CopyrightManager(private val project: Project, schemeManagerFactory: Schem override fun getState(scheme: SchemeWrapper) = scheme.schemeState override fun isSchemeFile(name: CharSequence) = !StringUtil.equals(name, "profiles_settings.xml") - }, isUseOldFileNameSanitize = true) + }, isUseOldFileNameSanitize = true, streamProvider = schemeManagerIprProvider) init { val app = ApplicationManager.getApplication() @@ -113,6 +115,8 @@ class CopyrightManager(private val project: Project, schemeManagerFactory: Schem override fun getState(): Element? { val result = Element("settings") try { + schemeManagerIprProvider?.writeState(result) + if (!scopeToCopyright.isEmpty()) { val map = Element(MODULE2COPYRIGHT) for ((scopeName, profileName) in scopeToCopyright) { @@ -138,7 +142,17 @@ class CopyrightManager(private val project: Project, schemeManagerFactory: Schem } override fun loadState(state: Element) { - val data = state.getChild("settings") + val data: Element? = state.getChild("settings") + + schemeManagerIprProvider?.let { + it.load(data) + schemeManager.reload() + } + + if (data == null) { + return + } + val moduleToCopyright = data.getChild(MODULE2COPYRIGHT) if (moduleToCopyright != null) { for (element in moduleToCopyright.getChildren(ELEMENT)) { From 7dab2a75d85504d7ff06867e1ddffac21d2ec459 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Wed, 31 Aug 2016 17:08:48 +0300 Subject: [PATCH 60/63] IDEA-135620 Typing with a lot of carets (hundreds) is extremely slow some 'cheap' improvements --- .../src/com/intellij/openapi/editor/impl/CaretImpl.java | 5 ++--- .../com/intellij/openapi/editor/impl/FoldingModelImpl.java | 6 ++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java index 84c4f7db2045..874685d1ac0a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java @@ -493,7 +493,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret, Dumpable { } } - myEditor.getFoldingModel().flushCaretPosition(); + myEditor.getFoldingModel().flushCaretPosition(this); VerticalInfo oldInfo = myCaretInfo; LogicalPosition oldCaretPosition = myLogicalCaret; @@ -682,7 +682,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret, Dumpable { updateVisualLineInfo(); - myEditor.getFoldingModel().flushCaretPosition(); + myEditor.getFoldingModel().flushCaretPosition(this); setLastColumnNumber(myLogicalCaret.column); myDesiredSelectionStartColumn = myDesiredSelectionEndColumn = -1; @@ -872,7 +872,6 @@ public class CaretImpl extends UserDataHolderBase implements Caret, Dumpable { } } - updateVisualLineInfo(); updateSelectionOnDocumentChange(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java index df72e3819091..6a482d6c16f4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java @@ -523,10 +523,8 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedInternalDocu return myFoldTextAttributes; } - public void flushCaretPosition() { - for (Caret caret : myEditor.getCaretModel().getAllCarets()) { - caret.putUserData(SAVED_CARET_POSITION, null); - } + void flushCaretPosition(@NotNull Caret caret) { + caret.putUserData(SAVED_CARET_POSITION, null); } void onBulkDocumentUpdateStarted() { From 53477d978c4f1a4112c48dd0522172acf62b76e0 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 31 Aug 2016 17:38:08 +0300 Subject: [PATCH 61/63] unused declaration: collect fixes from description only if problem node is selected (IDEA-160300) --- .../DummyEntryPointsPresentation.java | 4 ++-- .../UnusedDeclarationPresentation.java | 22 ++++++++++++++++--- .../ex/InspectionRVContentProviderImpl.java | 2 +- .../ui/DefaultInspectionToolPresentation.java | 4 ++-- .../ui/InspectionToolPresentation.java | 2 +- 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java index c53f363a470b..0aac8ceb56c6 100644 --- a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java +++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java @@ -15,7 +15,6 @@ */ package com.intellij.codeInspection.deadCode; -import com.intellij.codeInspection.CommonProblemDescriptor; import com.intellij.codeInspection.GlobalJavaInspectionContext; import com.intellij.codeInspection.InspectionsBundle; import com.intellij.codeInspection.ex.*; @@ -24,6 +23,7 @@ import com.intellij.codeInspection.reference.RefEntity; import com.intellij.codeInspection.reference.RefJavaElement; import com.intellij.codeInspection.ui.InspectionNode; import com.intellij.codeInspection.ui.InspectionResultsView; +import com.intellij.codeInspection.ui.InspectionTree; import com.intellij.codeInspection.ui.InspectionTreeNode; import com.intellij.codeInspection.util.RefFilter; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -43,7 +43,7 @@ public class DummyEntryPointsPresentation extends UnusedDeclarationPresentation } @Override - public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, CommonProblemDescriptor[] allowedDescriptors) { + public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, InspectionTree tree) { if (myQuickFixActions == null) { myQuickFixActions = new QuickFixAction[]{new MoveEntriesToSuspicious(getToolWrapper())}; } diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java index 341b24194be4..11482cb727c3 100644 --- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java +++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java @@ -67,6 +67,7 @@ import javax.swing.text.html.HTML; import javax.swing.text.html.HTMLDocument; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.StyleSheet; +import javax.swing.tree.TreePath; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; @@ -182,7 +183,7 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta } @Override - public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, CommonProblemDescriptor[] allowedDescriptors) { + public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, InspectionTree tree) { boolean showFixes = false; for (RefEntity element : refElements) { if (!getIgnoredRefElements().contains(element) && element.isValid()) { @@ -192,8 +193,23 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta } if (showFixes) { - final QuickFixAction[] fixes = super.getQuickFixes(refElements, allowedDescriptors); - return fixes != null ? ArrayUtil.mergeArrays(fixes, myQuickFixActions) : myQuickFixActions; + final TreePath[] paths = tree.getSelectionPaths(); + if (paths != null) { + int count = 0; + for (TreePath path : paths) { + final Object component = path.getLastPathComponent(); + if (component instanceof ProblemDescriptionNode) { + count++; + } + } + if (count > 0) { + final QuickFixAction[] fixes = super.getQuickFixes(refElements, tree); + if (fixes != null) { + return count == paths.length ? fixes : ArrayUtil.mergeArrays(fixes, myQuickFixActions); + } + } + } + return myQuickFixActions; } return QuickFixAction.EMPTY; } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProviderImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProviderImpl.java index 57635c5a0c5f..01a27855fce9 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProviderImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProviderImpl.java @@ -81,7 +81,7 @@ public class InspectionRVContentProviderImpl extends InspectionRVContentProvider public QuickFixAction[] getQuickFixes(@NotNull final InspectionToolWrapper toolWrapper, @NotNull final InspectionTree tree) { final RefEntity[] refEntities = tree.getSelectedElements(); InspectionToolPresentation presentation = tree.getContext().getPresentation(toolWrapper); - return refEntities.length == 0 ? null : presentation.getQuickFixes(refEntities, tree.getSelectedDescriptors()); + return refEntities.length == 0 ? null : presentation.getQuickFixes(refEntities, tree); } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java index 1eea4e076c80..7111ed4853f5 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java @@ -618,8 +618,8 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro @Override @Nullable - public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, CommonProblemDescriptor[] allowedDescriptors) { - return extractActiveFixes(refElements, getProblemElements(), allowedDescriptors); + public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, InspectionTree tree) { + return extractActiveFixes(refElements, getProblemElements(), tree != null ? tree.getSelectedDescriptors() : null); } @Override diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionToolPresentation.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionToolPresentation.java index d77a3d7d34e6..be718f0fb4c6 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionToolPresentation.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionToolPresentation.java @@ -80,7 +80,7 @@ public interface InspectionToolPresentation extends ProblemDescriptionsProcessor @NotNull Set getModuleProblems(); @Nullable - QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, @Nullable CommonProblemDescriptor[] descriptors); + QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, @Nullable InspectionTree tree); @NotNull Map getProblemElements(); @NotNull From b06d96a4907d947369761376b3095dde84cd3ced Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 31 Aug 2016 18:02:26 +0300 Subject: [PATCH 62/63] build scripts: automatically set 'idea.jars.nocopy' property for products without java support (such products don't use *.jar libraries so don't need to avoid locking of jar files) --- .../org/jetbrains/intellij/build/BuildContext.groovy | 6 ++++++ .../intellij/build/impl/BuildContextImpl.groovy | 12 +++++++++++- .../intellij/build/impl/BuildTasksImpl.groovy | 8 ++++++++ .../build/pycharm/PyCharmPropertiesBase.groovy | 1 - 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/build/groovy/org/jetbrains/intellij/build/BuildContext.groovy b/build/groovy/org/jetbrains/intellij/build/BuildContext.groovy index aababf51b22b..121e52b0b0c4 100644 --- a/build/groovy/org/jetbrains/intellij/build/BuildContext.groovy +++ b/build/groovy/org/jetbrains/intellij/build/BuildContext.groovy @@ -65,6 +65,12 @@ abstract class BuildContext { abstract boolean includeBreakGenLibraries() + /** + * If the method returns {@code false} 'idea.jars.nocopy' property will be set to {@code true} in idea.properties by default. Otherwise it + * won't be set and the IDE will copy library *.jar files to avoid their locking when running under Windows. + */ + abstract boolean shouldIDECopyJarsByDefault() + abstract void patchInspectScript(String path) abstract String getAdditionalJvmArguments() diff --git a/build/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy b/build/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy index b741ca5fdbbe..5fe53ef1e029 100644 --- a/build/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy +++ b/build/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy @@ -259,8 +259,18 @@ class BuildContextImpl extends BuildContext { @Override boolean includeBreakGenLibraries() { + return isJavaSupportedInProduct() + } + + @Override + boolean shouldIDECopyJarsByDefault() { + return isJavaSupportedInProduct() + } + + private boolean isJavaSupportedInProduct() { def productLayout = productProperties.productLayout - return productLayout.mainJarName == null || //todo[nik] remove this condition later + return productLayout.mainJarName == null || + //todo[nik] remove this condition later; currently build scripts for IDEA don't fully migrated to the new scheme productLayout.includedPlatformModules.contains("execution-impl") } diff --git a/build/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy b/build/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy index 2a01f0f6ed23..6d03a54eca40 100644 --- a/build/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy +++ b/build/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy @@ -143,6 +143,14 @@ class BuildTasksImpl extends BuildTasks { File originalFile = new File("$buildContext.paths.communityHome/bin/idea.properties") String text = originalFile.text + if (!buildContext.shouldIDECopyJarsByDefault()) { + text += """ +#--------------------------------------------------------------------- +# IDE can copy library .jar files to prevent their locking. Set this property to 'false' to enable copying. +#--------------------------------------------------------------------- +idea.jars.nocopy=true +""" + } buildContext.productProperties.additionalIDEPropertiesFilePaths.each { text += "\n" + new File(it).text } diff --git a/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmPropertiesBase.groovy b/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmPropertiesBase.groovy index 934febae1d72..9d7c7c31957e 100644 --- a/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmPropertiesBase.groovy +++ b/python/build/groovy/org/jetbrains/intellij/build/pycharm/PyCharmPropertiesBase.groovy @@ -43,7 +43,6 @@ import org.jetbrains.intellij.build.WindowsDistributionCustomizer abstract class PyCharmPropertiesBase extends ProductProperties { PyCharmPropertiesBase(String home) { baseFileName = "pycharm" - additionalIDEPropertiesFilePaths = ["$home/build/conf/ideaJNC.properties"] reassignAltClickToMultipleCarets = true productLayout.mainJarName = "pycharm.jar" productLayout.additionalPlatformJars.put("pycharm-pydev.jar", "python-pydev") From b7f5ceba06cbf783a7223440fbc009709bae7435 Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Wed, 31 Aug 2016 18:04:10 +0300 Subject: [PATCH 63/63] util: extract StringUtil.findStartingLineSeparator --- .../openapi/util/text/StringUtil.java | 21 ++++++++++++++---- .../intellij/util/text/StringUtilTest.java | 22 +++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index 60a758a6ae6d..ba678c929ff9 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -3147,10 +3147,23 @@ public class StringUtil extends StringUtilRt { public static LineSeparator detectSeparators(@NotNull CharSequence text) { int index = indexOfAny(text, "\n\r"); if (index == -1) return null; - if (startsWith(text, index, "\r\n")) return LineSeparator.CRLF; - if (text.charAt(index) == '\r') return LineSeparator.CR; - if (text.charAt(index) == '\n') return LineSeparator.LF; - throw new IllegalStateException(); + LineSeparator lineSeparator = findStartingLineSeparator(text, index); + if (lineSeparator == null) { + throw new AssertionError(); + } + return lineSeparator; + } + + @Nullable + public static LineSeparator findStartingLineSeparator(@NotNull CharSequence text, int startIndex) { + if (startIndex < 0 || startIndex >= text.length()) { + return null; + } + char ch = text.charAt(startIndex); + if (ch == '\r') { + return startIndex + 1 < text.length() && text.charAt(startIndex + 1) == '\n' ? LineSeparator.CRLF : LineSeparator.CR; + } + return ch == '\n' ? LineSeparator.LF : null; } @NotNull diff --git a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java index 569734335156..b8791aea3bf8 100644 --- a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java +++ b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java @@ -373,6 +373,28 @@ public class StringUtilTest { assertEquals(LineSeparator.CRLF, StringUtil.detectSeparators("asd\r\nads\n")); } + @Test + public void testFindStartingLineSeparator() { + assertEquals(null, StringUtil.findStartingLineSeparator("", -1)); + assertEquals(null, StringUtil.findStartingLineSeparator("", 0)); + assertEquals(null, StringUtil.findStartingLineSeparator("", 1)); + assertEquals(null, StringUtil.findStartingLineSeparator("\nHello", -1)); + assertEquals(null, StringUtil.findStartingLineSeparator("\nHello", 1)); + assertEquals(null, StringUtil.findStartingLineSeparator("\nH\rel\nlo", 6)); + + assertEquals(LineSeparator.LF, StringUtil.findStartingLineSeparator("\nHello", 0)); + assertEquals(LineSeparator.LF, StringUtil.findStartingLineSeparator("\nH\rel\nlo", 5)); + assertEquals(LineSeparator.LF, StringUtil.findStartingLineSeparator("Hello\n", 5)); + + assertEquals(LineSeparator.CR, StringUtil.findStartingLineSeparator("\rH\r\nello", 0)); + assertEquals(LineSeparator.CR, StringUtil.findStartingLineSeparator("Hello\r", 5)); + assertEquals(LineSeparator.CR, StringUtil.findStartingLineSeparator("Hello\b\r", 6)); + + assertEquals(LineSeparator.CRLF, StringUtil.findStartingLineSeparator("\rH\r\nello", 2)); + assertEquals(LineSeparator.CRLF, StringUtil.findStartingLineSeparator("\r\nH\r\nello", 0)); + assertEquals(LineSeparator.CRLF, StringUtil.findStartingLineSeparator("\r\nH\r\nello\r\n", 9)); + } + @Test public void testFormatFileSize() { assertEquals("0B", StringUtil.formatFileSize(0));