Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
小 白蛋
Intellij Community
Commits
f73a5572
Commit
f73a5572
authored
7 years ago
by
Tagir Valeev
Browse files
Options
Download
Email Patches
Plain Diff
Fix IDEA-177647 Convert String to StringBuilder intention produces wrong code
parent
7878a20a
Branches unavailable
Tags unavailable
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/stringConcatInLoop/afterConcatChar.java
+16
-0
...Analyzer/quickFix/stringConcatInLoop/afterConcatChar.java
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/stringConcatInLoop/beforeConcatChar.java
+14
-0
...nalyzer/quickFix/stringConcatInLoop/beforeConcatChar.java
plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConcatenationInLoopsInspection.java
+26
-9
.../ig/performance/StringConcatenationInLoopsInspection.java
with
56 additions
and
9 deletions
+56
-9
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/stringConcatInLoop/afterConcatChar.java
0 → 100644
+
16
-
0
View file @
f73a5572
// "Convert variable 'str1' from String to StringBuilder" "true"
public
class
IntentionBug
{
public
static
void
main
(
String
[]
args
)
{
/*1*/
/*2*/
StringBuilder
str1
=
new
StringBuilder
();
for
(
char
i
=
'a'
;
i
<
'd'
;
i
++)
{
str1
.
append
(
i
).
append
((
char
)
(
i
+
1
));
str1
.
append
(
i
).
append
((
char
)
(
i
+
1
));
str1
.
append
(
1
).
append
(
2
).
append
(
3
);
str1
.
append
(
1
+
2
+
3
);
}
System
.
out
.
println
(
str1
);
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/stringConcatInLoop/beforeConcatChar.java
0 → 100644
+
14
-
0
View file @
f73a5572
// "Convert variable 'str1' from String to StringBuilder" "true"
public
class
IntentionBug
{
public
static
void
main
(
String
[]
args
)
{
String
str1
=
""
;
for
(
char
i
=
'a'
;
i
<
'd'
;
i
++)
{
str1
=
str1
<
caret
>+
i
+
(
char
)
(
i
+
1
);
str1
=
/*1*/
str1
/*2*/
+
i
+
(
char
)
(
i
+
1
);
str1
=
str1
+
1
+
2
+
3
;
str1
=
str1
+(
1
+
2
+
3
);
}
System
.
out
.
println
(
str1
);
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConcatenationInLoopsInspection.java
+
26
-
9
View file @
f73a5572
...
...
@@ -46,6 +46,7 @@ import java.util.ArrayList;
import
java.util.Collection
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.function.Predicate
;
import
java.util.regex.Pattern
;
public
class
StringConcatenationInLoopsInspection
extends
BaseInspection
{
...
...
@@ -335,12 +336,20 @@ public class StringConcatenationInLoopsInspection extends BaseInspection {
PsiVariable
builderVariable
,
PsiElement
scope
,
CommentTracker
ct
)
{
replaceAll
(
variable
,
builderVariable
,
scope
,
ct
,
ref
->
false
);
}
void
replaceAll
(
PsiVariable
variable
,
PsiVariable
builderVariable
,
PsiElement
scope
,
CommentTracker
ct
,
Predicate
<
PsiReferenceExpression
>
skip
)
{
Query
<
PsiReference
>
query
=
scope
==
null
?
ReferencesSearch
.
search
(
variable
)
:
ReferencesSearch
.
search
(
variable
,
new
LocalSearchScope
(
scope
));
Collection
<
PsiReference
>
refs
=
query
.
findAll
();
for
(
PsiReference
ref
:
refs
)
{
PsiElement
target
=
ref
.
getElement
();
if
(
target
instanceof
PsiReferenceExpression
&&
target
.
isValid
())
{
if
(
target
instanceof
PsiReferenceExpression
&&
target
.
isValid
()
&&
!
skip
.
test
((
PsiReferenceExpression
)
target
)
)
{
replace
(
variable
,
builderVariable
,
(
PsiReferenceExpression
)
target
,
ct
);
}
}
...
...
@@ -461,6 +470,7 @@ public class StringConcatenationInLoopsInspection extends BaseInspection {
PsiAssignmentExpression
assignment
,
CommentTracker
ct
)
{
PsiExpression
rValue
=
PsiUtil
.
skipParenthesizedExprDown
(
assignment
.
getRExpression
());
String
builderName
=
Objects
.
requireNonNull
(
builderVariable
.
getName
());
if
(
assignment
.
getOperationTokenType
().
equals
(
JavaTokenType
.
EQ
))
{
if
(
rValue
instanceof
PsiPolyadicExpression
&&
((
PsiPolyadicExpression
)
rValue
).
getOperationTokenType
().
equals
(
JavaTokenType
.
PLUS
))
{
...
...
@@ -470,13 +480,20 @@ public class StringConcatenationInLoopsInspection extends BaseInspection {
// s = s + ...;
if
(
ExpressionUtils
.
isReferenceTo
(
operands
[
0
],
variable
))
{
StreamEx
.
iterate
(
operands
[
1
],
Objects:
:
nonNull
,
PsiElement:
:
getNextSibling
).
forEach
(
ct:
:
markUnchanged
);
String
text
=
rValue
.
getText
().
substring
(
operands
[
1
].
getStartOffsetInParent
());
PsiExpression
added
=
JavaPsiFacade
.
getElementFactory
(
variable
.
getProject
()).
createExpressionFromText
(
text
,
assignment
);
replaceAll
(
variable
,
builderVariable
,
added
,
ct
);
replaceAll
(
variable
,
builderVariable
,
rValue
,
ct
,
operands
[
0
]::
equals
);
StringBuilder
replacement
=
ChangeToAppendUtil
.
buildAppendExpression
(
added
,
false
,
new
StringBuilder
(
builder
Variable
.
get
Name
()
));
ChangeToAppendUtil
.
buildAppendExpression
(
rValue
,
false
,
new
StringBuilder
(
builderName
));
if
(
replacement
!=
null
)
{
ct
.
replace
(
assignment
,
replacement
.
toString
());
PsiMethodCallExpression
append
=
(
PsiMethodCallExpression
)
ct
.
replace
(
assignment
,
replacement
.
toString
());
while
(
true
)
{
PsiMethodCallExpression
qualifierCall
=
MethodCallUtils
.
getQualifierMethodCall
(
append
);
if
(
qualifierCall
==
null
)
break
;
append
=
qualifierCall
;
}
PsiExpression
qualifier
=
append
.
getMethodExpression
().
getQualifierExpression
();
if
(
qualifier
!=
null
)
{
append
.
replace
(
qualifier
);
}
}
return
;
}
...
...
@@ -485,7 +502,7 @@ public class StringConcatenationInLoopsInspection extends BaseInspection {
if
(
ExpressionUtils
.
isReferenceTo
(
lastOp
,
variable
))
{
ct
.
delete
(
concat
.
getTokenBeforeOperand
(
lastOp
),
lastOp
);
replaceAll
(
variable
,
builderVariable
,
rValue
,
ct
);
ct
.
replace
(
assignment
,
builder
Variable
.
get
Name
()
+
".insert(0,"
+
ct
.
text
(
rValue
)
+
")"
);
ct
.
replace
(
assignment
,
builderName
+
".insert(0,"
+
ct
.
text
(
rValue
)
+
")"
);
return
;
}
}
...
...
@@ -500,14 +517,14 @@ public class StringConcatenationInLoopsInspection extends BaseInspection {
String
replacement
=
""
;
if
(
rValue
!=
null
)
{
StringBuilder
sb
=
ChangeToAppendUtil
.
buildAppendExpression
(
ct
.
markUnchanged
(
rValue
),
false
,
new
StringBuilder
(
builder
Variable
.
get
Name
()
));
ChangeToAppendUtil
.
buildAppendExpression
(
ct
.
markUnchanged
(
rValue
),
false
,
new
StringBuilder
(
builderName
));
if
(
sb
!=
null
)
{
replacement
=
sb
.
toString
();
}
}
ct
.
replace
(
assignment
,
replacement
);
}
else
if
(
assignment
.
getOperationTokenType
().
equals
(
JavaTokenType
.
EQ
))
{
ct
.
replace
(
assignment
,
builder
Variable
.
get
Name
()
+
"="
+
generateNewStringBuilder
(
rValue
,
ct
));
ct
.
replace
(
assignment
,
builderName
+
"="
+
generateNewStringBuilder
(
rValue
,
ct
));
}
}
}
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Projects
Groups
Snippets
Help