From eab4410c639c32c0761d6740a4407c17b12e7957 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Mon, 12 Nov 2018 23:00:44 +0200 Subject: [PATCH 1/9] optimizations: Init sb1 with capacity, use .append(char), reduce sb2 into string --- .../advancedExpressionFolding/Range.java | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/com/intellij/advancedExpressionFolding/Range.java b/src/com/intellij/advancedExpressionFolding/Range.java index 0f82fbff..9034c6da 100644 --- a/src/com/intellij/advancedExpressionFolding/Range.java +++ b/src/com/intellij/advancedExpressionFolding/Range.java @@ -105,20 +105,13 @@ public boolean supportsFoldRegions(@NotNull Document document, @Override public FoldingDescriptor[] buildFoldRegions(@NotNull PsiElement element, @NotNull Document document, @Nullable Expression parent) { FoldingGroup group = FoldingGroup.newGroup(getClass().getName()); - StringBuilder sb1 = new StringBuilder().append(" ").append(separator).append(" "); - if (isStartInclusive()) { - sb1.append("["); - } else { - sb1.append("("); - } - String p1 = sb1.toString(); - StringBuilder sb2 = new StringBuilder(); - if (isEndInclusive()) { - sb2.append("]"); - } else { - sb2.append(")"); - } - String p2 = sb2.toString(); + String p1 = new StringBuilder(separator.length() + 3) + .append(' ') + .append(separator) + .append(' ') + .append(isStartInclusive() ? '[' : '(') + .toString(); + String p2 = isEndInclusive() ? "]" : ")"; ArrayList descriptors = new ArrayList<>(); descriptors.add(new FoldingDescriptor(element.getNode(), TextRange.create(getOperand().getTextRange().getEndOffset(), From b81f93368733c1c10938578feaaf397609058018 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Mon, 12 Nov 2018 23:01:39 +0200 Subject: [PATCH 2/9] optimizations: InterpolatedString: set initial capacity for sI, use append(char) --- .../advancedExpressionFolding/InterpolatedString.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/com/intellij/advancedExpressionFolding/InterpolatedString.java b/src/com/intellij/advancedExpressionFolding/InterpolatedString.java index 4d2d6163..fef5c481 100644 --- a/src/com/intellij/advancedExpressionFolding/InterpolatedString.java +++ b/src/com/intellij/advancedExpressionFolding/InterpolatedString.java @@ -102,12 +102,12 @@ public String getPlaceholderText() { ? operands.get(i + 1).getTextRange().getStartOffset() + 1 : operands.get(i + 1).getTextRange().getStartOffset(); int fI = i; - StringBuilder sI = new StringBuilder().append(buf[0]); + StringBuilder sI = new StringBuilder(buf[0].length() + 2).append(buf[0]); if (!(operands.get(fI + 1) instanceof CharSequenceLiteral)) { - sI.append("$"); + sI.append('$'); } if (!(operands.get(fI + 1) instanceof Variable) && !(operands.get(fI + 1) instanceof CharSequenceLiteral)) { - sI.append("{"); + sI.append('{'); buf[0] = "}"; } else { buf[0] = ""; From 45fe4e7512bbc5f452e5cc5f3fa78f196913a51c Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Mon, 12 Nov 2018 23:05:02 +0200 Subject: [PATCH 3/9] optimizations: Expression: set initial capacity for sb, use append(char) instead of append(Object) --- src/com/intellij/advancedExpressionFolding/Expression.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/intellij/advancedExpressionFolding/Expression.java b/src/com/intellij/advancedExpressionFolding/Expression.java index 956d85ff..dbc7800d 100644 --- a/src/com/intellij/advancedExpressionFolding/Expression.java +++ b/src/com/intellij/advancedExpressionFolding/Expression.java @@ -151,13 +151,13 @@ protected static String subscript(String str) { } private static String map(String str, Map subscriptMapping) { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(str.length()); for (int i = 0; i < str.length(); i++) { Character c = subscriptMapping.get(str.charAt(i)); if (c == null) { return null; } else if (!c.equals('❤')) { - sb.append(c); + sb.append((char) c); } } return sb.toString(); From 44f0b19f21a2a81981ed9e183777fc433ecdb257 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Tue, 13 Nov 2018 22:25:16 +0200 Subject: [PATCH 4/9] optimizations: AdvancedExpressionFoldingBuilder: 1. Precompile regexp GENERICS_PATTERN. 2 Use Collections.addAll(list, array) without creation of ArrayList by Arrays.asList() --- .../AdvancedExpressionFoldingBuilder.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java b/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java index 66abd2ad..67dfc5a0 100644 --- a/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java +++ b/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java @@ -24,8 +24,8 @@ import java.util.stream.Stream; public class AdvancedExpressionFoldingBuilder extends FoldingBuilderEx { - private static final FoldingDescriptor[] NO_DESCRIPTORS = new FoldingDescriptor[0]; + private static final Pattern GENERICS_PATTERN = Pattern.compile("<[^<>]*>"); private static Set supportedMethods = new HashSet() { { @@ -1297,12 +1297,10 @@ private static Variable getVariableExpression(PsiElement element, boolean copy) @NotNull private static String eraseGenerics(@NotNull String signature) { - String re = "<[^<>]*>"; - Pattern p = Pattern.compile(re); - Matcher m = p.matcher(signature); + Matcher m = GENERICS_PATTERN.matcher(signature); while (m.find()) { signature = m.replaceAll(""); - m = p.matcher(signature); + m = GENERICS_PATTERN.matcher(signature); } return signature; } @@ -1928,8 +1926,8 @@ public FoldingDescriptor[] buildFoldRegions(@NotNull PsiElement element, @NotNul try { @Nullable Expression expression = getNonSyntheticExpression(element, document); if (expression != null && expression.supportsFoldRegions(document, null)) { - allDescriptors = new ArrayList<>(); FoldingDescriptor[] descriptors = expression.buildFoldRegions(expression.getElement(), document, null); + allDescriptors = new ArrayList<>(); Collections.addAll(allDescriptors, descriptors); } if (expression == null || expression.isNested()) { @@ -1939,12 +1937,11 @@ public FoldingDescriptor[] buildFoldRegions(@NotNull PsiElement element, @NotNul if (allDescriptors == null) { allDescriptors = new ArrayList<>(); } - allDescriptors.addAll(Arrays.asList(descriptors)); + Collections.addAll(allDescriptors, descriptors); } } } - } catch (IndexNotReadyException e) { - // ignore + } catch (IndexNotReadyException ignore) { } return allDescriptors != null ? allDescriptors.toArray(NO_DESCRIPTORS) : NO_DESCRIPTORS; } @@ -1971,4 +1968,5 @@ public boolean isCollapsedByDefault(@NotNull ASTNode astNode) { } return false; } + } From 017e08ce60a0c4e1ead7138b99c7feaa7fa91422 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Wed, 14 Nov 2018 21:18:13 +0200 Subject: [PATCH 5/9] Extract AdvancedExpressionFoldingBuilder.guessPropertyName() into PropertyUtil and add a test for it --- .../AdvancedExpressionFoldingBuilder.java | 25 ++-------------- .../PropertyUtil.java | 29 +++++++++++++++++++ .../PropertyUtilTest.java | 20 +++++++++++++ 3 files changed, 51 insertions(+), 23 deletions(-) create mode 100644 src/com/intellij/advancedExpressionFolding/PropertyUtil.java create mode 100644 test/com/intellij/advancedExpressionFolding/PropertyUtilTest.java diff --git a/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java b/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java index 67dfc5a0..2d24566d 100644 --- a/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java +++ b/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java @@ -23,6 +23,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import static com.intellij.advancedExpressionFolding.PropertyUtil.guessPropertyName; + public class AdvancedExpressionFoldingBuilder extends FoldingBuilderEx { private static final FoldingDescriptor[] NO_DESCRIPTORS = new FoldingDescriptor[0]; private static final Pattern GENERICS_PATTERN = Pattern.compile("<[^<>]*>"); @@ -1826,29 +1828,6 @@ private static String charAt(@NotNull Document document, int position) { return document.getText(TextRange.create(position, position + 1)); } - @NotNull - private static String guessPropertyName(@NotNull String text) { - StringBuilder sb = new StringBuilder(); - if (text.startsWith("get")) { - sb.append(text.substring(3)); - } else if (text.startsWith("set")) { - sb.append(text.substring(3)); - } else if (text.startsWith("is")) { - sb.append(text.substring(2)); - } else { - sb.append(text); - } - for (int i = 0; i < sb.length(); i++) { - if (Character.isUpperCase(sb.charAt(i)) && - (i == sb.length() - 1 || Character.isUpperCase(sb.charAt(i + 1)) || i == 0)) { - sb.setCharAt(i, Character.toLowerCase(sb.charAt(i))); - } else if (Character.isLowerCase(sb.charAt(i))) { - break; - } - } - return sb.toString(); - } - @Nullable private static NumberLiteral getSlicePosition(@NotNull PsiElement parent, @NotNull Expression qualifierExpression, @NotNull PsiBinaryExpression a2b, @NotNull Document document) { diff --git a/src/com/intellij/advancedExpressionFolding/PropertyUtil.java b/src/com/intellij/advancedExpressionFolding/PropertyUtil.java new file mode 100644 index 00000000..a5443860 --- /dev/null +++ b/src/com/intellij/advancedExpressionFolding/PropertyUtil.java @@ -0,0 +1,29 @@ +package com.intellij.advancedExpressionFolding; + +import org.jetbrains.annotations.NotNull; + +public class PropertyUtil { + + @NotNull + public static String guessPropertyName(@NotNull String text) { + StringBuilder sb = new StringBuilder(); + if (text.startsWith("get")) { + sb.append(text.substring(3)); + } else if (text.startsWith("set")) { + sb.append(text.substring(3)); + } else if (text.startsWith("is")) { + sb.append(text.substring(2)); + } else { + sb.append(text); + } + for (int i = 0; i < sb.length(); i++) { + if (Character.isUpperCase(sb.charAt(i)) && + (i == sb.length() - 1 || Character.isUpperCase(sb.charAt(i + 1)) || i == 0)) { + sb.setCharAt(i, Character.toLowerCase(sb.charAt(i))); + } else if (Character.isLowerCase(sb.charAt(i))) { + break; + } + } + return sb.toString(); + } +} diff --git a/test/com/intellij/advancedExpressionFolding/PropertyUtilTest.java b/test/com/intellij/advancedExpressionFolding/PropertyUtilTest.java new file mode 100644 index 00000000..2617f58a --- /dev/null +++ b/test/com/intellij/advancedExpressionFolding/PropertyUtilTest.java @@ -0,0 +1,20 @@ +package com.intellij.advancedExpressionFolding; + +import org.junit.Test; + +import static com.intellij.advancedExpressionFolding.PropertyUtil.guessPropertyName; +import static org.junit.Assert.*; + +public class PropertyUtilTest { + @Test + public void testGuessPropertyName() { + assertEquals("", guessPropertyName("")); + assertEquals("length", guessPropertyName("length")); + assertEquals("name", guessPropertyName("getName")); + assertEquals("name", guessPropertyName("setName")); + assertEquals("enabled", guessPropertyName("isEnabled")); + assertEquals("enabledByDefault", guessPropertyName("isEnabledByDefault")); + assertEquals("html", guessPropertyName("getHTML")); + assertEquals("htmlText", guessPropertyName("isHTMLText")); + } +} \ No newline at end of file From 34d27c91a2ff709415f84b937d127a9d9cd7f6af Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Fri, 16 Nov 2018 13:37:03 +0200 Subject: [PATCH 6/9] AdvancedExpressionFoldingBuilder.getExpression() simplify --- .../AdvancedExpressionFoldingBuilder.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java b/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java index 2d24566d..04e9a4f7 100644 --- a/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java +++ b/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java @@ -339,15 +339,9 @@ private static boolean isReferenceToReference(@Nullable PsiReferenceExpression r @Contract("_, _, true -> !null") private static Expression getExpression(@NotNull PsiElement element, @NotNull Document document, boolean synthetic) { - if (synthetic) { - return CachedValuesManager.getCachedValue(element, - () -> CachedValueProvider.Result.create(buildExpression(element, document, true), - PsiModificationTracker.MODIFICATION_COUNT)); - } else { - return CachedValuesManager.getCachedValue(element, - () -> CachedValueProvider.Result.create(buildExpression(element, document, false), - PsiModificationTracker.MODIFICATION_COUNT)); - } + return CachedValuesManager.getCachedValue(element, + () -> CachedValueProvider.Result.create(buildExpression(element, document, synthetic), + PsiModificationTracker.MODIFICATION_COUNT)); } @SuppressWarnings("WeakerAccess") From e9ceb2ad04a8aab69620fedcc2de181ffc5af307 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Fri, 15 Jan 2021 13:42:17 +0200 Subject: [PATCH 7/9] PropertyUtil: optimize --- .../PropertyUtil.java | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/com/intellij/advancedExpressionFolding/PropertyUtil.java b/src/com/intellij/advancedExpressionFolding/PropertyUtil.java index a5443860..185f3abd 100644 --- a/src/com/intellij/advancedExpressionFolding/PropertyUtil.java +++ b/src/com/intellij/advancedExpressionFolding/PropertyUtil.java @@ -2,25 +2,29 @@ import org.jetbrains.annotations.NotNull; +import static java.lang.Character.isLowerCase; +import static java.lang.Character.isUpperCase; +import static java.lang.Character.toLowerCase; + public class PropertyUtil { @NotNull public static String guessPropertyName(@NotNull String text) { - StringBuilder sb = new StringBuilder(); - if (text.startsWith("get")) { - sb.append(text.substring(3)); - } else if (text.startsWith("set")) { - sb.append(text.substring(3)); + StringBuilder sb = new StringBuilder(text.length()); + int startPos; + if (text.startsWith("get") || text.startsWith("set")) { + startPos = 3; } else if (text.startsWith("is")) { - sb.append(text.substring(2)); + startPos = 2; } else { - sb.append(text); + startPos = 0; } + sb.append(text, startPos, text.length()); for (int i = 0; i < sb.length(); i++) { - if (Character.isUpperCase(sb.charAt(i)) && - (i == sb.length() - 1 || Character.isUpperCase(sb.charAt(i + 1)) || i == 0)) { - sb.setCharAt(i, Character.toLowerCase(sb.charAt(i))); - } else if (Character.isLowerCase(sb.charAt(i))) { + if (isUpperCase(sb.charAt(i)) && + (i == sb.length() - 1 || isUpperCase(sb.charAt(i + 1)) || i == 0)) { + sb.setCharAt(i, toLowerCase(sb.charAt(i))); + } else if (isLowerCase(sb.charAt(i))) { break; } } From 90af70b50f5568e1391b66ddc548058edfd9c2ed Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sat, 16 Jan 2021 12:34:42 +0200 Subject: [PATCH 8/9] AdvancedExpressionFoldingBuilder.charAt(): return char instead of string --- .../AdvancedExpressionFoldingBuilder.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java b/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java index 04e9a4f7..a977d4c5 100644 --- a/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java +++ b/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java @@ -24,6 +24,7 @@ import java.util.stream.Stream; import static com.intellij.advancedExpressionFolding.PropertyUtil.guessPropertyName; +import static java.lang.Character.isWhitespace; public class AdvancedExpressionFoldingBuilder extends FoldingBuilderEx { private static final FoldingDescriptor[] NO_DESCRIPTORS = new FoldingDescriptor[0]; @@ -1791,10 +1792,10 @@ static int findDot(@NotNull Document document, int position, int i, boolean incl position < document.getText().length()) { position += i; offset += i; - if (charAt(document, position).equals(".")) { + if (charAt(document, position) == '.') { break; } - if (!charAt(document, position).matches("\\s")) { + if (!isWhitespace(charAt(document, position))) { return Integer.MAX_VALUE; } } @@ -1803,14 +1804,14 @@ static int findDot(@NotNull Document document, int position, int i, boolean incl do { position += i; offsetWithNewLine += i; - if (i < 0 && charAt(document, position).equals("\n")) { + if (i < 0 && charAt(document, position) == '\n') { offset = offsetWithNewLine; - } else if (i > 0 && charAt(document, position).matches("\\s")) { + } else if (i > 0 && isWhitespace(charAt(document, position))) { offset = offsetWithNewLine; } } while (Math.abs(offsetWithNewLine) < 100 && position > 0 && position < document.getText().length() && - charAt(document, position).matches("\\s")); + isWhitespace(charAt(document, position))); } if (Math.abs(offset) >= 100) { return Integer.MAX_VALUE; @@ -1818,8 +1819,8 @@ static int findDot(@NotNull Document document, int position, int i, boolean incl return offset; } - private static String charAt(@NotNull Document document, int position) { - return document.getText(TextRange.create(position, position + 1)); + private static char charAt(@NotNull Document document, int position) { + return document.getText(TextRange.create(position, position + 1)).charAt(0); } @Nullable From de83e0889af52dcf65d3dd872c811463fd9b5edf Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sat, 16 Jan 2021 12:35:58 +0200 Subject: [PATCH 9/9] AdvancedExpressionFoldingBuilder: use list.isEmpty() --- .../AdvancedExpressionFoldingBuilder.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java b/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java index a977d4c5..80a138c7 100644 --- a/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java +++ b/src/com/intellij/advancedExpressionFolding/AdvancedExpressionFoldingBuilder.java @@ -733,7 +733,7 @@ && startsWith(((PsiMethodCallExpression) qualifier).getMethodExpression().getRef && ((PsiReferenceExpression) e).isReferenceTo(r.resolve()) || e instanceof PsiMethodCallExpression && ((PsiMethodCallExpression) e).getMethodExpression().isReferenceTo(r.resolve()) ).toList(); - if (references.size() > 0) { + if (!references.isEmpty()) { return new ElvisExpression(element, element.getTextRange(), getAnyExpression(element.getThenExpression(), document), getAnyExpression(element.getElseExpression(), document), @@ -804,7 +804,7 @@ private static boolean calculateIfFinal(@NotNull PsiVariable element) { && ((PsiPostfixExpression) e).getOperand() instanceof PsiReferenceExpression && ((PsiReferenceExpression) ((PsiPostfixExpression) e).getOperand()).isReferenceTo(element) ).toList(); - if (references.size() == 0) { + if (references.isEmpty()) { isFinal = true; } } @@ -1218,7 +1218,7 @@ private static Expression getNewExpression(PsiNewExpression element, @NotNull Do break; } } - if (flag && arguments.size() > 0) { + if (flag && !arguments.isEmpty()) { if (settings.getState().isGetExpressionsCollapse()) return new SetLiteral(element, element.getTextRange(), TextRange.create(anonymousClass.getLBrace().getTextRange().getStartOffset(),