Merge remote-tracking branch 'origin/master'

This commit is contained in:
Vladimir.Orlov
2016-11-02 10:11:18 +03:00
35 changed files with 557 additions and 183 deletions
@@ -450,8 +450,4 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
return 31 * mySearchType.hashCode() + mySearchFileType.hashCode();
}
}
private static class RawSearchResult {
}
}
@@ -20,8 +20,10 @@ import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.lang.java.lexer.JavaLexer;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
@@ -87,7 +89,7 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
private static boolean isSupportedCodeLocation(PsiMethodCallExpression call) {
PsiElement cur = call;
PsiElement parent = cur.getParent();
while(parent instanceof PsiExpression) {
while(parent instanceof PsiExpression || parent instanceof PsiExpressionList) {
// TODO: support in single expression lambdas
if(parent instanceof PsiLambdaExpression) {
return false;
@@ -133,9 +135,10 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
if(InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_UTIL_STREAM_BASE_STREAM)) {
PsiExpression qualifier = call.getMethodExpression().getQualifierExpression();
if(qualifier != null) {
Operation op = Operation.createIntermediate(name, args, outVar, getStreamElementType(qualifier.getType()));
PsiType elementType = getStreamElementType(qualifier.getType());
Operation op = Operation.createIntermediate(name, args, outVar, elementType);
if (op != null) return op;
op = TerminalOperation.createTerminal(name, args, callType, className, call.getParent() instanceof PsiExpressionStatement);
op = TerminalOperation.createTerminal(name, args, elementType, callType, call.getParent() instanceof PsiExpressionStatement);
if (op != null) return op;
}
}
@@ -232,11 +235,12 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
}
}
catch (Exception ex) {
String text = terminalCall.getText();
if(temporaryStreamPlaceholder.isPhysical()) {
// Just in case if something went wrong: at least try to restore the original stream code
temporaryStreamPlaceholder.replace(factory.createExpressionFromText(terminalCall.getText(), temporaryStreamPlaceholder));
temporaryStreamPlaceholder.replace(factory.createExpressionFromText(text, temporaryStreamPlaceholder));
}
throw ex;
throw new RuntimeException("Error converting Stream to loop: "+text, ex);
}
}
@@ -380,9 +384,9 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
}
private boolean isUsed(String varName) {
if(myUsedNames.contains(varName)) return true;
// TODO: cleaner solution
return !varName.equals(JavaCodeStyleManager.getInstance(myStatement.getProject()).suggestUniqueVariableName(varName, myStatement, true));
return myUsedNames.contains(varName) || JavaLexer.isKeyword(varName, LanguageLevel.HIGHEST) ||
// TODO: cleaner solution
!varName.equals(JavaCodeStyleManager.getInstance(myStatement.getProject()).suggestUniqueVariableName(varName, myStatement, true));
}
public String declare(String desiredName, String type, String initializer) {
@@ -63,7 +63,7 @@ abstract class TerminalOperation extends Operation {
}
@Nullable
static TerminalOperation createTerminal(String name, PsiExpression[] args, PsiType callType, String className, boolean isVoid) {
static TerminalOperation createTerminal(String name, PsiExpression[] args, PsiType elementType, PsiType resultType, boolean isVoid) {
if(isVoid) {
if ((name.equals("forEach") || name.equals("forEachOrdered")) && args.length == 1) {
FunctionHelper fn = FunctionHelper.create(args[0], 1, true);
@@ -75,23 +75,22 @@ abstract class TerminalOperation extends Operation {
return new AccumulatedTerminalOperation("count", "long", "0", "{acc}++;");
}
if(name.equals("sum") && args.length == 0) {
return new AccumulatedTerminalOperation("sum", callType.getCanonicalText(), "0", "{acc}+={item};");
return new AccumulatedTerminalOperation("sum", resultType.getCanonicalText(), "0", "{acc}+={item};");
}
if(name.equals("average") && args.length == 0) {
if(className.equals(CommonClassNames.JAVA_UTIL_STREAM_DOUBLE_STREAM)) {
if(elementType.equals(PsiType.DOUBLE)) {
return new AverageTerminalOperation(true);
}
else if(className.equals(CommonClassNames.JAVA_UTIL_STREAM_INT_STREAM) ||
className.equals(CommonClassNames.JAVA_UTIL_STREAM_LONG_STREAM)) {
else if(elementType.equals(PsiType.INT) || elementType.equals(PsiType.LONG)) {
return new AverageTerminalOperation(false);
}
}
if(name.equals("summaryStatistics") && args.length == 0) {
return new AccumulatedTerminalOperation("stat", callType.getCanonicalText(), "new " + callType.getCanonicalText() + "()",
return new AccumulatedTerminalOperation("stat", resultType.getCanonicalText(), "new " + resultType.getCanonicalText() + "()",
"{acc}.accept({item});");
}
if((name.equals("findFirst") || name.equals("findAny")) && args.length == 0) {
return new FindTerminalOperation(callType.getCanonicalText());
return new FindTerminalOperation(resultType.getCanonicalText());
}
if((name.equals("anyMatch") || name.equals("allMatch") || name.equals("noneMatch")) && args.length == 1) {
FunctionHelper fn = FunctionHelper.create(args[0], 1, true);
@@ -101,11 +100,11 @@ abstract class TerminalOperation extends Operation {
if(args.length == 2 || args.length == 3) {
FunctionHelper fn = FunctionHelper.create(args[1], 2, true);
if(fn != null) {
return new ReduceTerminalOperation(args[0], fn, callType.getCanonicalText());
return new ReduceTerminalOperation(args[0], fn, resultType.getCanonicalText());
}
}
if(args.length == 1) {
PsiType optionalElementType = getOptionalElementType(callType);
PsiType optionalElementType = getOptionalElementType(resultType);
FunctionHelper fn = FunctionHelper.create(args[0], 2, true);
if(fn != null && optionalElementType != null) {
return new ReduceToOptionalTerminalOperation(fn, optionalElementType.getCanonicalText());
@@ -113,8 +112,8 @@ abstract class TerminalOperation extends Operation {
}
}
if(name.equals("toArray") && args.length < 2) {
if(!(callType instanceof PsiArrayType)) return null;
PsiType componentType = ((PsiArrayType)callType).getComponentType();
if(!(resultType instanceof PsiArrayType)) return null;
PsiType componentType = ((PsiArrayType)resultType).getComponentType();
if (componentType instanceof PsiPrimitiveType) {
if(args.length == 0) return new ToPrimitiveArrayTerminalOperation(componentType.getCanonicalText());
}
@@ -130,7 +129,7 @@ abstract class TerminalOperation extends Operation {
if(!(type instanceof PsiArrayType)) return null;
arr = "new "+type.getCanonicalText().replaceFirst("\\[]", "[0]");
}
return new AccumulatedTerminalOperation("list", CommonClassNames.JAVA_UTIL_LIST + "<" + componentType.getCanonicalText() + ">",
return new AccumulatedTerminalOperation("list", CommonClassNames.JAVA_UTIL_LIST + "<" + elementType.getCanonicalText() + ">",
"new "+ CommonClassNames.JAVA_UTIL_ARRAY_LIST+"<>()", "{acc}.add({item});",
"{acc}.toArray("+arr+")");
}
@@ -144,25 +143,25 @@ abstract class TerminalOperation extends Operation {
PsiClass collectorClass = collector.getContainingClass();
if(collectorClass != null && CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS.equals(collectorClass.getQualifiedName())) {
if(collector.getName().equals("toList") && collectorArgs.length == 0) {
return AccumulatedTerminalOperation.toCollection(callType, CommonClassNames.JAVA_UTIL_ARRAY_LIST, "list");
return AccumulatedTerminalOperation.toCollection(resultType, CommonClassNames.JAVA_UTIL_ARRAY_LIST, "list");
}
if(collector.getName().equals("toSet") && collectorArgs.length == 0) {
return AccumulatedTerminalOperation.toCollection(callType, CommonClassNames.JAVA_UTIL_HASH_SET, "set");
return AccumulatedTerminalOperation.toCollection(resultType, CommonClassNames.JAVA_UTIL_HASH_SET, "set");
}
if(collector.getName().equals("toCollection") && collectorArgs.length == 1) {
FunctionHelper fn = FunctionHelper.create(collectorArgs[0], 0, true);
if(fn != null) {
return new ToCollectionTerminalOperation(fn, callType);
return new ToCollectionTerminalOperation(fn, resultType);
}
}
if(collector.getName().equals("reducing") && collectorArgs.length == 2) {
FunctionHelper fn = FunctionHelper.create(collectorArgs[1], 2, true);
if(fn != null) {
return new ReduceTerminalOperation(collectorArgs[0], fn, callType.getCanonicalText());
return new ReduceTerminalOperation(collectorArgs[0], fn, resultType.getCanonicalText());
}
}
if(collector.getName().equals("reducing") && collectorArgs.length == 1) {
PsiType optionalElementType = getOptionalElementType(callType);
PsiType optionalElementType = getOptionalElementType(resultType);
FunctionHelper fn = FunctionHelper.create(collectorArgs[0], 2, true);
if(fn != null && optionalElementType != null) {
return new ReduceToOptionalTerminalOperation(fn, optionalElementType.getCanonicalText());
@@ -355,7 +354,14 @@ abstract class TerminalOperation extends Operation {
@Override
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
myFn.transform(context, inVar.getName());
String expression = myNegatePredicate ? BoolUtils.getNegatedExpressionText(myFn.getExpression()) : myFn.getText();
String expression;
if (myNegatePredicate) {
PsiLambdaExpression lambda = (PsiLambdaExpression)context.createExpression("(" + inVar.getDeclaration() + ")->" + myFn.getText());
expression = BoolUtils.getNegatedExpressionText((PsiExpression)lambda.getBody());
}
else {
expression = myFn.getText();
}
return "if(" + expression + ") {\n" +
context.assignAndBreak(myName, PsiType.BOOLEAN.getCanonicalText(), String.valueOf(!myDefaultValue), String.valueOf(myDefaultValue)) +
"}\n";
@@ -0,0 +1,19 @@
// "Replace Stream API chain with loop" "true"
import java.util.Arrays;
import java.util.List;
public class Main {
private static boolean test(List<String> list) {
for (String s : list) {
if (s.trim() != s.toLowerCase()) {
return false;
}
}
return true;
}
public static void main(String[] args) {
System.out.println(test(Arrays.asList("a", "b", "c")));
}
}
@@ -0,0 +1,22 @@
// "Replace Stream API chain with loop" "true"
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class Main {
private static test(List<String> packages) {
Optional<String> found = Optional.empty();
for (String s : packages) {
if (s.startsWith("xyz")) {
found = Optional.of(s);
break;
}
}
return found.filter(pkg -> pkg.endsWith("abc")).isPresent();
}
public static void main(String[] args) {
System.out.println(test(Arrays.asList("xyzabc", "xyz123", "123abc", "123")));
}
}
@@ -0,0 +1,18 @@
// "Replace Stream API chain with loop" "true"
import java.util.*;
import java.util.stream.*;
public class Main {
private static void test(List<String> test) {
StringBuilder sb = new StringBuilder();
for (String s : test) {
sb.append(s);
}
System.out.println("x"+ sb.toString() +"y");
}
public static void main(String[] args) {
System.out.println(test(Arrays.asList("a", "b", "c")));
}
}
@@ -7,7 +7,7 @@ import java.util.List;
public class Main {
private static List<?>[] test(int[] numbers) {
List<List<?>> list = new ArrayList<>();
List<List<Integer>> list = new ArrayList<>();
for (int number : numbers) {
Integer n = number;
List<Integer> integers = Collections.singletonList(n);
@@ -6,7 +6,7 @@ import java.util.List;
public class Main {
private static Object[] test(int[] numbers) {
List<Object> list = new ArrayList<>();
List<Integer> list = new ArrayList<>();
for (int number : numbers) {
Integer integer = number;
list.add(integer);
@@ -0,0 +1,21 @@
// "Replace Stream API chain with loop" "true"
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class Main {
private static Number[] test(Object[] objects) {
List<Object> list = new ArrayList<>();
for (Object object : objects) {
if (Number.class.isInstance(object)) {
list.add(object);
}
}
return list.toArray(new Number[0]);
}
public static void main(String[] args) {
System.out.println(Arrays.asList(test(new Object[]{1, 2, 3, "string", 4})));
}
}
@@ -0,0 +1,14 @@
// "Replace Stream API chain with loop" "true"
import java.util.Arrays;
import java.util.List;
public class Main {
private static boolean test(List<String> list) {
return list.stream().al<caret>lMatch(s -> s.trim() == s.toLowerCase());
}
public static void main(String[] args) {
System.out.println(test(Arrays.asList("a", "b", "c")));
}
}
@@ -0,0 +1,14 @@
// "Replace Stream API chain with loop" "true"
import java.util.Arrays;
import java.util.List;
public class Main {
private static test(List<String> packages) {
return packages.stream().filter(pkg -> pkg.startsWith("xyz")).fin<caret>dAny().filter(pkg -> pkg.endsWith("abc")).isPresent();
}
public static void main(String[] args) {
System.out.println(test(Arrays.asList("xyzabc", "xyz123", "123abc", "123")));
}
}
@@ -0,0 +1,14 @@
// "Replace Stream API chain with loop" "true"
import java.util.*;
import java.util.stream.*;
public class Main {
private static void test(List<String> test) {
System.out.println("x"+test.stream().c<caret>ollect(Collectors.joining())+"y");
}
public static void main(String[] args) {
System.out.println(test(Arrays.asList("a", "b", "c")));
}
}
@@ -0,0 +1,13 @@
// "Replace Stream API chain with loop" "true"
import java.util.stream.Stream;
public class Main {
private static Number[] test(Object[] objects) {
return Stream.of(objects).filter(Number.class::isInstance).toArr<caret>ay(Number[]::new);
}
public static void main(String[] args) {
System.out.println(Arrays.asList(test(new Object[]{1, 2, 3, "string", 4})));
}
}
@@ -17,4 +17,11 @@ package com.intellij.codeInsight.hints
class InlayInfo(val text: String, val offset: Int)
class MethodInfo(val fullyQualifiedName: String, val paramNames: List<String>)
open class MethodInfo(val fullyQualifiedName: String, val paramNames: List<String>) {
open fun getMethodName(): String {
val start = fullyQualifiedName.lastIndexOf('.') + 1
return fullyQualifiedName.substring(start)
}
}
@@ -40,34 +40,30 @@ import com.intellij.psi.util.PsiTreeUtil
private fun String.capitalize() = StringUtil.capitalizeWords(this, true)
class ShowParameterHintsSettings : AnAction() {
class ShowSettingsWithAddedPattern : AnAction() {
init {
val presentation = templatePresentation
presentation.text = CodeInsightBundle.message("inlay.hints.show.settings").capitalize()
presentation.description = CodeInsightBundle.message("inlay.hints.show.settings.description")
templatePresentation.description = CodeInsightBundle.message("inlay.hints.show.settings.description")
}
override fun update(e: AnActionEvent) {
val file = CommonDataKeys.PSI_FILE.getData(e.dataContext) ?: return
val editor = CommonDataKeys.EDITOR.getData(e.dataContext) ?: return
val info = getMethodInfoAtOffset(editor, file) ?: return
val name = info.getMethodName()
e.presentation.text = CodeInsightBundle.message("inlay.hints.show.settings", name)
}
override fun actionPerformed(e: AnActionEvent) {
val project = CommonDataKeys.PROJECT.getData(e.dataContext) ?: return
val file = CommonDataKeys.PSI_FILE.getData(e.dataContext) ?: return
val hintExtension = InlayParameterHintsExtension.forLanguage(file.language) ?: return
val dialog = ParameterNameHintsConfigurable(project, hintExtension.defaultBlackList, file.language)
dialog.show()
}
}
class BlacklistCurrentMethodAction : AnAction() {
init {
val presentation = templatePresentation
presentation.text = CodeInsightBundle.message("inlay.hints.blacklist.method").capitalize()
presentation.description = CodeInsightBundle.message("inlay.hints.blacklist.method.description")
}
override fun actionPerformed(e: AnActionEvent) {
val editor = CommonDataKeys.EDITOR.getData(e.dataContext) ?: return
val file = CommonDataKeys.PSI_FILE.getData(e.dataContext) ?: return
val hintExtension = InlayParameterHintsExtension.forLanguage(file.language) ?: return
val info = getMethodInfoAtOffset(editor, file) ?: return
val dialog = ParameterNameHintsConfigurable(project, hintExtension.defaultBlackList, file.language, info.toPattern())
addMethodAtCaretToBlackList(editor, file)
dialog.show()
}
}
@@ -160,18 +156,19 @@ private fun refreshAllOpenEditors() {
}
}
private fun addMethodAtCaretToBlackList(editor: Editor, file: PsiFile) {
private fun getMethodInfoAtOffset(editor: Editor, file: PsiFile): MethodInfo? {
val offset = editor.caretModel.offset
val element = file.findElementAt(offset)
val hintsProvider = InlayParameterHintsExtension.forLanguage(file.language) ?: return
val method = PsiTreeUtil.findFirstParent(element, { e -> hintsProvider.getMethodInfo(e) != null }) ?: return
val info = hintsProvider.getMethodInfo(method) ?: return
val pattern = info.fullyQualifiedName + '(' + info.paramNames.joinToString(",") + ')'
ParameterNameHintsSettings.getInstance().addIgnorePattern(file.language, pattern)
val hintsProvider = InlayParameterHintsExtension.forLanguage(file.language) ?: return null
val method = PsiTreeUtil.findFirstParent(element, { e -> hintsProvider.getMethodInfo(e) != null }) ?: return null
return hintsProvider.getMethodInfo(method)
}
private fun addMethodAtCaretToBlackList(editor: Editor, file: PsiFile) {
val info = getMethodInfoAtOffset(editor, file) ?: return
ParameterNameHintsSettings.getInstance().addIgnorePattern(file.language, info.toPattern())
refreshAllOpenEditors()
}
@@ -189,3 +186,5 @@ fun isPossibleHintNearOffset(file: PsiFile, offset: Int): Boolean {
return false
}
fun MethodInfo.toPattern() = this.fullyQualifiedName + '(' + this.paramNames.joinToString(",") + ')'
@@ -17,37 +17,49 @@ package com.intellij.codeInsight.hints.settings;
import com.intellij.codeInsight.hints.filtering.MatcherConstructor;
import com.intellij.lang.Language;
import com.intellij.openapi.components.ServiceManager;
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.fileTypes.PlainTextLanguage;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.EditorTextFieldProvider;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class ParameterNameHintsConfigurable extends DialogWrapper {
public JPanel myConfigurable;
private EditorTextField myEditorTextField;
private final Project myProject;
private final Set<String> myDefaultBlackList;
private final Language myLanguage;
private final String myNewPreselectedItem;
private final Project myProject;
public ParameterNameHintsConfigurable(@NotNull Project project,
public ParameterNameHintsConfigurable(@NotNull Project project,
@NotNull Set<String> defaultBlackList,
@NotNull Language language) {
this(project, defaultBlackList, language, null);
}
public ParameterNameHintsConfigurable(@NotNull Project project,
@NotNull Set<String> defaultBlackList,
@NotNull Language language,
@Nullable String newPreselectedPattern) {
super(project);
myProject = project;
myDefaultBlackList = defaultBlackList;
myLanguage = language;
myDefaultBlackList = defaultBlackList;
myNewPreselectedItem = newPreselectedPattern;
setTitle("Configure Parameter Name Hints Blacklist");
init();
}
@@ -84,18 +96,11 @@ public class ParameterNameHintsConfigurable extends DialogWrapper {
return myConfigurable;
}
public JPanel myConfigurable;
private EditorTextField myEditorTextField;
private void createUIComponents() {
EditorTextFieldProvider service = ServiceManager.getService(myProject, EditorTextFieldProvider.class);
myEditorTextField = service.getEditorField(PlainTextLanguage.INSTANCE, myProject, ContainerUtil.emptyIterable());
Diff diff = ParameterNameHintsSettings.getInstance().getBlackListDiff(myLanguage);
Set<String> blacklist = diff.applyOn(myDefaultBlackList);
String text = StringUtil.join(blacklist, "\n");
myEditorTextField.setText(text);
myEditorTextField = createEditor(blacklist, myNewPreselectedItem);
myEditorTextField.addDocumentListener(new DocumentAdapter() {
@Override
public void documentChanged(DocumentEvent e) {
@@ -103,7 +108,40 @@ public class ParameterNameHintsConfigurable extends DialogWrapper {
}
});
}
private EditorTextField createEditor(@NotNull Set<String> blacklist, @Nullable String newPreselectedItem) {
String text = StringUtil.join(blacklist, "\n");
final TextRange range;
if (newPreselectedItem != null) {
text += "\n";
final int startOffset = text.length();
text += newPreselectedItem;
range = new TextRange(startOffset, text.length());
}
else {
range = null;
}
return createEditorField(text, range);
}
@NotNull
private EditorTextField createEditorField(@NotNull String text, @Nullable TextRange rangeToSelect) {
Document document = EditorFactory.getInstance().createDocument(text);
EditorTextField field = new EditorTextField(document, myProject, FileTypes.PLAIN_TEXT, false, false);
field.setPreferredSize(new Dimension(200, 350));
field.addSettingsProvider(editor -> {
editor.setVerticalScrollbarVisible(true);
editor.setHorizontalScrollbarVisible(true);
editor.getSettings().setAdditionalLinesCount(2);
if (rangeToSelect != null) {
editor.getCaretModel().moveToOffset(rangeToSelect.getStartOffset());
editor.getScrollingModel().scrollVertically(document.getTextLength() - 1);
editor.getSelectionModel().setSelection(rangeToSelect.getStartOffset(), rangeToSelect.getEndOffset());
}
});
return field;
}
}
@@ -445,7 +445,26 @@ public class SearchReplaceComponent extends EditorHeaderComponent implements Dat
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
NEW_LINE_KEYSTROKE,
WHEN_FOCUSED);
wrapper.setContent(textArea);
textComponent.registerKeyboardAction(e -> {
if (isMultiline(textComponent)) {
if (textComponent.isEditable() && textComponent.isEnabled()) {
textComponent.replaceSelection("\t");
}
else {
UIManager.getLookAndFeel().provideErrorFeedback(textComponent);
}
}
else {
textComponent.transferFocus();
}
}, KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), WHEN_FOCUSED);
textComponent.registerKeyboardAction(e -> {
textComponent.transferFocusBackward();
}, KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK), WHEN_FOCUSED);
wrapper.setContent(textArea);
UIUtil.addUndoRedoActions(textComponent);
Utils.setSmallerFont(textComponent);
@@ -491,6 +510,10 @@ public class SearchReplaceComponent extends EditorHeaderComponent implements Dat
area.setRows(Math.max(2, Math.min(3, StringUtil.countChars(area.getText(), '\n') + 1)));
}
private static boolean isMultiline(@NotNull JTextComponent component) {
return component.getText().contains("\n");
}
private void installCloseOnEscapeAction(@NotNull JTextComponent c) {
ActionListener action = new ActionListener() {
@@ -50,6 +50,7 @@ import javax.swing.event.DocumentEvent;
import javax.swing.text.DefaultEditorKit;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.RoundRectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
@@ -181,6 +182,9 @@ public class SearchTextArea extends NonOpaquePanel implements PropertyChangeList
myInfoLabel.setText(info);
}
private static Color enabledBorderColor = new JBColor(Gray._196, Gray._100);
private static Color disabledBorderColor = Gray._83;
@Override
public void paint(Graphics graphics) {
Graphics2D g = (Graphics2D)graphics.create();
@@ -191,18 +195,25 @@ public class SearchTextArea extends NonOpaquePanel implements PropertyChangeList
if (r.height % 2 == 1) r.height--;
int arcSize = Math.min(25, r.height-1);
boolean hasFocus = myTextArea.hasFocus();
g.setColor(myTextArea.isEnabled() ? Gray._196 : Gray._83);
Color borderColor = myTextArea.isEnabled() ? enabledBorderColor : disabledBorderColor;
if (SystemInfo.isMac && (UIUtil.isUnderIntelliJLaF() || UIUtil.isUnderAquaLookAndFeel())) {
g.setColor(borderColor);
MacIntelliJTextFieldUI.paintAquaSearchFocusRing(g, r, myTextArea);
}
else {
JBInsets.removeFrom(r, new Insets(3, 3, 3, 3));
if (hasFocus) {
JBInsets.removeFrom(r, new JBInsets(3, 3, 3, 3));
if (hasFocus && (UIUtil.isUnderIntelliJLaF() || UIUtil.isUnderDarcula())) {
DarculaUIUtil.paintSearchFocusRing(g, r, myTextArea, arcSize+6);
}
else {
g.drawRoundRect(r.x, r.y, r.width, r.height, arcSize, arcSize);
Shape shape = UIUtil.isUnderWindowsLookAndFeel()
? new Rectangle(r.x, r.y, r.width, r.height)
: new RoundRectangle2D.Double(r.x, r.y, r.width, r.height, arcSize, arcSize);
g.setColor(borderColor);
g.setColor(myTextArea.getBackground());
g.fill(shape);
g.setColor(borderColor);
g.draw(shape);
}
}
}
@@ -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.
@@ -15,6 +15,7 @@
*/
package com.intellij.ide.actions;
import com.intellij.codeInsight.hint.HintUtil;
import com.intellij.codeInsight.navigation.NavigationUtil;
import com.intellij.navigation.GotoRelatedItem;
import com.intellij.openapi.actionSystem.AnAction;
@@ -22,12 +23,16 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.ui.IdeBorderFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import java.util.List;
/**
@@ -43,17 +48,28 @@ public class GotoRelatedSymbolAction extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
PsiElement element = getContextElement(e.getDataContext());
final DataContext dataContext = e.getDataContext();
final PsiElement element = getContextElement(dataContext);
if (element == null) return;
List<GotoRelatedItem> items = NavigationUtil.collectRelatedItems(element, e.getDataContext());
if (items.isEmpty()) return;
List<GotoRelatedItem> items = NavigationUtil.collectRelatedItems(element, dataContext);
if (items.isEmpty()) {
final JComponent label = HintUtil.createErrorLabel("No related symbols");
label.setBorder(IdeBorderFactory.createEmptyBorder(2, 7, 2, 7));
JBPopupFactory.getInstance().createBalloonBuilder(label)
.setFadeoutTime(3000)
.setFillColor(HintUtil.ERROR_COLOR)
.createBalloon()
.show(JBPopupFactory.getInstance().guessBestPopupLocation(dataContext), Balloon.Position.above);
return;
}
if (items.size() == 1 && items.get(0).getElement() != null) {
items.get(0).navigate();
return;
}
NavigationUtil.getRelatedItemsPopup(items, "Choose Target").showInBestPositionFor(e.getDataContext());
NavigationUtil.getRelatedItemsPopup(items, "Choose Target").showInBestPositionFor(dataContext);
}
@TestOnly
@@ -220,7 +220,7 @@ public class MacIntelliJTextFieldUI extends TextFieldWithPopupHandlerUI {
g.setStroke(new BasicStroke(.5f));
g.draw(getShape(r, 4, false));
if (true || c.hasFocus()) {
if (c.hasFocus()) {
Color graphiteColor = new Color(0x6f6f72);
Color blueColor = ColorUtil.brighter(new Color(0x006de2), 3);
g.setColor(ColorUtil.withAlpha(IntelliJLaf.isGraphite() ? graphiteColor : blueColor, .3));
@@ -0,0 +1,137 @@
/*
* 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.ui.popup;
import com.intellij.util.ReflectionUtil;
import javax.swing.JWindow;
import java.awt.Window;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.util.ArrayDeque;
/**
* @author Sergey Malenkov
*/
final class HeavyWeightPopupCache implements ComponentListener {
/**
* Returns a cached window or creates a new one if cache is empty.
*
* @param owner the window from which a popup is displayed
* @return a window for the specified owner
*/
public static Window create(Window owner) {
if (owner != null) {
HeavyWeightPopupCache cache = getCache(owner);
if (cache != null) {
Window popup = cache.poll();
if (popup != null) return popup;
}
}
Window popup = new JWindow(owner);
popup.setType(Window.Type.POPUP);
return popup;
}
/**
* Caches a window if possible.
*
* @param popup the popup window that is not needed
*/
public static void dispose(Window popup) {
if (popup != null) {
hide(popup);
Window owner = popup.getOwner();
if (owner == null || !owner.isDisplayable()) {
popup.dispose();
}
else {
HeavyWeightPopupCache cache = getCache(owner);
if (cache == null) {
cache = new HeavyWeightPopupCache();
owner.addComponentListener(cache);
}
cache.push(popup);
}
}
}
private static HeavyWeightPopupCache getCache(Window owner) {
for (ComponentListener listener : owner.getComponentListeners()) {
if (listener instanceof HeavyWeightPopupCache) {
return (HeavyWeightPopupCache)listener;
}
}
return null;
}
private static Window poll(ArrayDeque<Window> windows) {
return windows.poll();
}
private static void push(ArrayDeque<Window> windows, Window popup) {
windows.push(popup);
}
private static void hide(ArrayDeque<Window> windows) {
for (Window window : windows) hide(window);
}
/**
* Disables showing a child window with its parent.
*
* @param window the popup window that is not needed
*/
private static void hide(Window window) {
// HACK: do not allow to show a hidden popup on showing its parent
ReflectionUtil.setField(Window.class, window, boolean.class, "showWithParent", false);
}
private final ArrayDeque<Window> myWindows = new ArrayDeque<>();
private Window poll() {
return poll(myWindows);
}
private void push(Window popup) {
push(myWindows, popup);
}
private void hide() {
hide(myWindows);
}
@Override
public void componentResized(ComponentEvent event) {
}
@Override
public void componentMoved(ComponentEvent event) {
}
@Override
public void componentShown(ComponentEvent event) {
}
@Override
public void componentHidden(ComponentEvent event) {
Object source = event.getSource();
if (source instanceof Window) {
HeavyWeightPopupCache cache = getCache((Window)source);
if (cache != null) cache.hide();
}
}
}
@@ -20,13 +20,13 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayDeque;
import java.awt.event.HierarchyListener;
/**
* @author Sergey Malenkov
*/
public class MovablePopup {
private static final Object CACHE = new Object();
private final HierarchyListener myListener = event -> setVisible(false);
private final Component myOwner;
private final Component myContent;
private Rectangle myViewBounds;
@@ -161,11 +161,7 @@ public class MovablePopup {
Window owner = UIUtil.getWindow(myOwner);
if (owner != null) {
if (myHeavyWeight) {
Window view = pop(owner);
if (view == null) {
view = new JWindow(owner);
view.setType(Window.Type.POPUP);
}
Window view = HeavyWeightPopupCache.create(owner);
setAlwaysOnTop(view, myAlwaysOnTop);
setWindowFocusable(view, myWindowFocusable);
setWindowShadow(view, myWindowShadow);
@@ -193,6 +189,7 @@ public class MovablePopup {
myView.setBounds(myViewBounds);
myView.setVisible(true);
myViewBounds = null;
myOwner.addHierarchyListener(myListener);
}
}
}
@@ -206,6 +203,7 @@ public class MovablePopup {
private void disposeAndUpdate(boolean update) {
if (myView != null) {
myOwner.removeHierarchyListener(myListener);
boolean visible = myView.isVisible();
myView.setVisible(false);
Container container = myContent.getParent();
@@ -214,10 +212,7 @@ public class MovablePopup {
}
if (myView instanceof Window) {
myViewBounds = myView.getBounds();
Window window = (Window)myView;
if (!push(UIUtil.getWindow(myOwner), window)) {
window.dispose();
}
HeavyWeightPopupCache.dispose((Window)myView);
}
else {
Container parent = myView.getParent();
@@ -270,35 +265,4 @@ public class MovablePopup {
}
return null;
}
private static Window pop(Window owner) {
JRootPane root = getRootPane(owner);
if (root != null) {
synchronized (CACHE) {
@SuppressWarnings("unchecked")
ArrayDeque<Window> cache = (ArrayDeque<Window>)root.getClientProperty(CACHE);
if (cache != null && !cache.isEmpty()) {
return cache.pop();
}
}
}
return null;
}
private static boolean push(Window owner, Window window) {
JRootPane root = getRootPane(owner);
if (root != null) {
synchronized (CACHE) {
@SuppressWarnings("unchecked")
ArrayDeque<Window> cache = (ArrayDeque<Window>)root.getClientProperty(CACHE);
if (cache == null) {
cache = new ArrayDeque<>();
root.putClientProperty(CACHE, cache);
}
cache.push(window);
return true;
}
}
return false;
}
}
@@ -528,8 +528,8 @@ highlight.imported.members.chooser.title=Choose Imported Members to Highlight
javadoc.resolved.value=Resolved value\:
javadoc.error.resolving.url=Couldn''t resolve URL <i>{0}</i> <p>Configuring paths to API docs in <a href="open://Project Settings">project settings</a> might help
inlay.hints.show.settings=Show parameter name hints settings...
inlay.hints.show.settings.description=Show dialog with parameter name hints settings
inlay.hints.show.settings=Add Method ''{0}'' to Blacklist...
inlay.hints.show.settings.description=Open parameter name hints settings
inlay.hints.blacklist.method=Do not show hints for current method
inlay.hints.blacklist.method.description=Adds current method to parameter name hints blacklist
inlay.hints.intention.family.name=Parameter Name Hints
@@ -300,8 +300,7 @@
</group>
<group id="ParameterNameHints" popup="true">
<action id="BlacklistCurrentMethodAction" class="com.intellij.codeInsight.hints.BlacklistCurrentMethodAction"/>
<action id="ShowParameterHintsSettings" class="com.intellij.codeInsight.hints.ShowParameterHintsSettings"/>
<action id="ShowSettingsWithAddedPattern" class="com.intellij.codeInsight.hints.ShowSettingsWithAddedPattern"/>
</group>
<action id="ToggleInlineHintsAction" class="com.intellij.codeInsight.hints.ToggleInlineHintsAction">
@@ -747,7 +747,7 @@ database.scrollable.result.sets.description=Enables scrollable result sets, if J
database.scrollable.result.sets=true
database.src_storage.enabled.description=Enables database sources storage
database.src_storage.enabled.restartRequired=true
database.src_storage.enabled=false
database.src_storage.enabled=true
git.status.write=true
git.blocking.read=true
@@ -298,22 +298,26 @@ public final class IconLoader {
LOG.error(icon); // # 22481
return EMPTY_ICON;
}
final int scale = UIUtil.isRetina() ? 2 : 1;
@SuppressWarnings("UndesirableClassUsage")
BufferedImage image = new BufferedImage(scale*icon.getIconWidth(), scale*icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
final Graphics2D graphics = image.createGraphics();
if (icon instanceof CachedImageIcon) {
disabledIcon = ((CachedImageIcon)icon).asDisabledIcon();
} else {
final int scale = UIUtil.isRetina() ? 2 : 1;
@SuppressWarnings("UndesirableClassUsage")
BufferedImage image = new BufferedImage(scale * icon.getIconWidth(), scale * icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
final Graphics2D graphics = image.createGraphics();
graphics.setColor(UIUtil.TRANSPARENT_COLOR);
graphics.fillRect(0, 0, icon.getIconWidth(), icon.getIconHeight());
graphics.scale(scale, scale);
icon.paintIcon(LabelHolder.ourFakeComponent, graphics, 0, 0);
graphics.setColor(UIUtil.TRANSPARENT_COLOR);
graphics.fillRect(0, 0, icon.getIconWidth(), icon.getIconHeight());
graphics.scale(scale, scale);
icon.paintIcon(LabelHolder.ourFakeComponent, graphics, 0, 0);
graphics.dispose();
graphics.dispose();
Image img = ImageUtil.filter(image, UIUtil.getGrayFilter());
if (UIUtil.isRetina()) img = RetinaImage.createFrom(img);
Image img = ImageUtil.filter(image, UIUtil.getGrayFilter());
if (UIUtil.isRetina()) img = RetinaImage.createFrom(img);
disabledIcon = new JBImageIcon(img);
disabledIcon = new JBImageIcon(img);
}
ourIcon2DisabledIcon.put(icon, disabledIcon);
}
return disabledIcon;
@@ -376,24 +380,36 @@ public final class IconLoader {
private volatile boolean dark;
private volatile int numberOfPatchers = ourPatchers.size();
private volatile ImageFilter filter;
private ImageFilter[] myFilters;
private final MyScaledIconsCache myScaledIconsCache = new MyScaledIconsCache();
public CachedImageIcon(@NotNull URL url) {
private CachedImageIcon(@NotNull URL url, @NotNull ImageFilter[] filters) {
myUrl = url;
dark = USE_DARK_ICONS;
filter = IMAGE_FILTER;
myFilters = filters;
}
@NotNull
public CachedImageIcon(@NotNull URL url) {
this(url, new ImageFilter[] {IMAGE_FILTER});
}
private void setGlobalFilter(ImageFilter globalFilter) {
myFilters[0] = globalFilter;
}
private ImageFilter getGlobalFilter() {
return myFilters[0];
}
@NotNull
private synchronized ImageIcon getRealIcon() {
if (isLoaderDisabled() && (myRealIcon == null || dark != USE_DARK_ICONS || needUpdateJBUIScale() || filter != IMAGE_FILTER || numberOfPatchers != ourPatchers.size())) return EMPTY_ICON;
if (isLoaderDisabled() && (myRealIcon == null || dark != USE_DARK_ICONS || needUpdateJBUIScale() || getGlobalFilter() != IMAGE_FILTER || numberOfPatchers != ourPatchers.size())) return EMPTY_ICON;
if (!isValid()) {
myRealIcon = null;
dark = USE_DARK_ICONS;
updateJBUIScale();
filter = IMAGE_FILTER;
setGlobalFilter(IMAGE_FILTER);
myScaledIconsCache.clear();
if (numberOfPatchers != ourPatchers.size()) {
numberOfPatchers = ourPatchers.size();
@@ -420,7 +436,7 @@ public final class IconLoader {
if (icon != null) return (ImageIcon)icon;
}
Image image = ImageLoader.loadFromUrl(myUrl, true, filter);
Image image = ImageLoader.loadFromUrl(myUrl, true, myFilters);
icon = checkIcon(image, myUrl);
if (icon != null) {
@@ -437,7 +453,7 @@ public final class IconLoader {
}
private boolean isValid() {
return dark == USE_DARK_ICONS && !needUpdateJBUIScale() && filter == IMAGE_FILTER && numberOfPatchers == ourPatchers.size();
return dark == USE_DARK_ICONS && !needUpdateJBUIScale() && getGlobalFilter() == IMAGE_FILTER && numberOfPatchers == ourPatchers.size();
}
@Override
@@ -475,6 +491,10 @@ public final class IconLoader {
return (icon != null) ? icon : this;
}
private Icon asDisabledIcon() {
return new CachedImageIcon(myUrl, new ImageFilter[] {getGlobalFilter(), UIUtil.getGrayFilter()});
}
private class MyScaledIconsCache {
// Map {false -> image}, {true -> image@2x}
private Map<Boolean, SoftReference<Image>> origImagesCache = Collections.synchronizedMap(new HashMap<Boolean, SoftReference<Image>>(2));
@@ -493,7 +513,7 @@ public final class IconLoader {
Image img = SoftReference.dereference(origImagesCache.get(retina));
if (img == null) {
img = ImageLoader.loadFromUrl(myUrl, UIUtil.isUnderDarcula(), retina, filter);
img = ImageLoader.loadFromUrl(myUrl, UIUtil.isUnderDarcula(), retina, myFilters);
origImagesCache.put(retina, new SoftReference<Image>(img));
}
return img;
@@ -2472,7 +2472,7 @@ public class StringUtil extends StringUtilRt {
* Escape property name or key in property file. Unicode characters are escaped as well.
*
* @param input an input to escape
* @param isKey if true, the rules for key escaping are applied. All spaces are escaped in that case.
* @param isKey if true, the rules for key escaping are applied. The leading space is escaped in that case.
* @return an escaped string
*/
@NotNull
@@ -2483,7 +2483,7 @@ public class StringUtil extends StringUtilRt {
final char ch = input.charAt(i);
switch (ch) {
case ' ':
if (isKey) {
if (isKey && i == 0) {
// only the leading space has to be escaped
escaped.append('\\');
}
@@ -195,6 +195,14 @@ public class ImageLoader implements Serializable {
return new ImageConverterChain();
}
public ImageConverterChain withFilter(final ImageFilter[] filters) {
ImageConverterChain chain = this;
for (ImageFilter filter : filters) {
chain = chain.withFilter(filter);
}
return chain;
}
public ImageConverterChain withFilter(final ImageFilter filter) {
return with(new ImageConverter() {
@Override
@@ -253,11 +261,16 @@ public class ImageLoader implements Serializable {
@Nullable
public static Image loadFromUrl(@NotNull URL url, boolean allowFloatScaling) {
return loadFromUrl(url, allowFloatScaling, null);
return loadFromUrl(url, allowFloatScaling, (ImageFilter)null);
}
@Nullable
public static Image loadFromUrl(@NotNull URL url, boolean allowFloatScaling, ImageFilter filter) {
return loadFromUrl(url, allowFloatScaling, new ImageFilter[] {filter});
}
@Nullable
public static Image loadFromUrl(@NotNull URL url, boolean allowFloatScaling, ImageFilter[] filters) {
final float scaleFactor = calcScaleFactor(allowFloatScaling);
// We can't check all 3rd party plugins and convince the authors to add @2x icons.
@@ -271,7 +284,7 @@ public class ImageLoader implements Serializable {
return ImageDescList.create(url.toString(), null, UIUtil.isUnderDarcula(), loadRetinaImages, allowFloatScaling).load(
ImageConverterChain.create().
withFilter(filter).
withFilter(filters).
withRetina().
with(new ImageConverter() {
public Image convert(Image source, ImageDesc desc) {
@@ -309,13 +322,18 @@ public class ImageLoader implements Serializable {
@Nullable
public static Image loadFromUrl(URL url, boolean dark, boolean retina) {
return loadFromUrl(url, dark, retina, null);
return loadFromUrl(url, dark, retina, (ImageFilter[])null);
}
@Nullable
public static Image loadFromUrl(URL url, boolean dark, boolean retina, ImageFilter filter) {
return loadFromUrl(url, dark, retina, new ImageFilter[] {filter});
}
@Nullable
public static Image loadFromUrl(URL url, boolean dark, boolean retina, ImageFilter[] filters) {
return ImageDescList.create(url.toString(), null, dark, retina, true).
load(ImageConverterChain.create().withFilter(filter).withRetina());
load(ImageConverterChain.create().withFilter(filters).withRetina());
}
@Nullable
@@ -39,7 +39,7 @@ public class FontUtil {
if (start == -1) return input;
Font font = null;
StringBuilder result = new StringBuilder();
StringBuilder result = new StringBuilder(input.substring(0, start));
for (int i = start; i < input.length(); i++) {
char c = input.charAt(i);
if (baseFont.canDisplay(c)) {
@@ -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,6 +15,7 @@
*/
package org.jetbrains.idea.devkit.dom.impl;
import com.intellij.codeInsight.completion.CompletionConfidenceEP;
import com.intellij.codeInsight.completion.CompletionContributorEP;
import com.intellij.codeInspection.dataFlow.StringExpressionHelper;
import com.intellij.icons.AllIcons;
@@ -47,6 +48,7 @@ import javax.swing.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
class LanguageResolvingUtil {
private static final String ANY_LANGUAGE_DEFAULT_ID = Language.ANY.getID();
@@ -209,6 +211,11 @@ class LanguageResolvingUtil {
return new LanguageDefinition(anyLanguageId, languageClass, AllIcons.FileTypes.Any_type, "<any language>");
}
private static final Set<String> EP_WITH_ANY_LANGUAGE_ID = ContainerUtil.immutableSet(
CompletionContributorEP.class.getName(),
CompletionConfidenceEP.class.getName()
);
private static String calculateAnyLanguageId(ConvertContext context) {
final Extension extension = context.getInvocationElement().getParentOfType(Extension.class, true);
if (extension == null) {
@@ -220,7 +227,7 @@ class LanguageResolvingUtil {
}
final GenericAttributeValue<PsiClass> epBeanClass = extensionPoint.getBeanClass();
if (CompletionContributorEP.class.getName().equals(epBeanClass.getStringValue())) {
if (EP_WITH_ANY_LANGUAGE_ID.contains(epBeanClass.getStringValue())) {
return "any";
}
@@ -178,9 +178,6 @@ public abstract class GroovyPsiElementFactory implements JVMElementFactory {
@NotNull
public abstract GrVariableDeclaration createVariableDeclaration(@Nullable String[] modifiers, @Nullable String initializer, @Nullable PsiType type, String... identifiers);
@NotNull
public abstract GrVariableDeclaration createVariableDeclarationFromText(@NotNull String text, @Nullable PsiElement context);
@NotNull
public abstract GrEnumConstant createEnumConstantFromText(@NotNull String text);
@@ -296,13 +296,6 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory {
return statement;
}
@NotNull
@Override
public GrVariableDeclaration createVariableDeclarationFromText(@NotNull String text, @Nullable PsiElement context) {
final GroovyFile file = createGroovyFileChecked(text, false, context);
return ((GrVariableDeclaration)file.getTopStatements()[0]);
}
@NotNull
@Override
public GrEnumConstant createEnumConstantFromText(@NotNull String text) {
@@ -41,6 +41,7 @@ class GroovyClosurePattern : GroovyExpressionPattern<GrClosableBlock, GroovyClos
}
else -> return false
}
context?.put(closureCallKey, call)
val method = call.resolveMethod() ?: return false
return methodPattern.accepts(method)
@@ -15,17 +15,21 @@
*/
package org.jetbrains.plugins.groovy.lang.psi.patterns
import com.intellij.openapi.util.Key
import com.intellij.patterns.PatternCondition
import com.intellij.util.ProcessingContext
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression
val closureCallKey = Key.create<GrCall>("groovy.pattern.closure.call")
inline fun <reified T : GrExpression> groovyExpression() = GroovyExpressionPattern.Capture(T::class.java)
fun groovyList() = groovyExpression<GrListOrMap>().with(object : PatternCondition<GrListOrMap>("isList") {
override fun accepts(t: GrListOrMap, context: ProcessingContext?) = !t.isMap
})
fun psiMethod(containingClass: String, name: String) = GroovyPatterns.psiMethod().withName(name).definedInClass(containingClass)
fun psiMethod(containingClass: String, vararg name: String) = GroovyPatterns.psiMethod().withName(*name).definedInClass(containingClass)
fun groovyClosure() = GroovyClosurePattern()
@@ -106,8 +106,7 @@ public class GrStubFileElementType extends IStubFileElementType<GrFileStub> {
public GrFileStub deserialize(@NotNull final StubInputStream dataStream, final StubElement parentStub) throws IOException {
StringRef name = dataStream.readName();
boolean isScript = dataStream.readBoolean();
String[] annotations = GrStubUtils.readStringArray(dataStream);
return new GrFileStub(name, isScript, annotations);
return new GrFileStub(name, isScript, GrStubUtils.readStringArray(dataStream));
}
@Override