Merge branch 'master' of git.labs.intellij.net:idea/community

This commit is contained in:
Yann Cebron
2010-12-25 14:12:19 +01:00
8 changed files with 260 additions and 8 deletions
@@ -24,6 +24,7 @@ import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.libraries.scripting.ScriptingLibraryManager;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -38,7 +39,7 @@ public abstract class LangScriptingContextConfigurable implements Configurable,
public LangScriptingContextConfigurable(Project project, LangScriptingContextProvider provider) {
myLibManager = new ScriptingLibraryManager(project, provider.getLibraryType());
myPanel = useDedicatedLibraryUI(project) ? new ScriptingLibrariesPanel(provider, project, myLibManager) : new ScriptingLibrariesPanelStub();
myContextsConfigurable = new ScriptingContextsConfigurable(project, provider.getLibraryMappings(project));
myContextsConfigurable = new ScriptingContextsConfigurable(this, project, provider.getLibraryMappings(project));
}
private static boolean useDedicatedLibraryUI(Project project) {
@@ -88,4 +89,7 @@ public abstract class LangScriptingContextConfigurable implements Configurable,
public Configurable[] getConfigurables() {
return new Configurable[] {myContextsConfigurable};
}
@Nullable
public abstract String getUsageScopeHelpTopic();
}
@@ -16,6 +16,7 @@
package com.intellij.ide.scriptingContext.ui;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.scriptingContext.LangScriptingContextConfigurable;
import com.intellij.ide.scriptingContext.ScriptingLibraryMappings;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.libraries.scripting.ScriptingLibraryTable;
@@ -32,14 +33,16 @@ import javax.swing.*;
public class ScriptingContextsConfigurable extends LanguagePerFileConfigurable<ScriptingLibraryTable.LibraryModel> {
private final ScriptingLibraryMappings myScriptingLibraryMappings;
private final LangScriptingContextConfigurable myParent;
public ScriptingContextsConfigurable(final Project project, final ScriptingLibraryMappings mappings) {
public ScriptingContextsConfigurable(final LangScriptingContextConfigurable parent, final Project project, final ScriptingLibraryMappings mappings) {
super(project, ScriptingLibraryTable.LibraryModel.class, mappings,
IdeBundle.message("scripting.lib.usageScope.caption"),
IdeBundle.message("scripting.lib.usageScope.tableTitle"),
IdeBundle.message("scripting.lib.usageScope.override.question"),
IdeBundle.message("scripting.lib.usageScope.override.title"));
myScriptingLibraryMappings = mappings;
myParent = parent;
}
public void resetMappings() {
@@ -81,6 +84,6 @@ public class ScriptingContextsConfigurable extends LanguagePerFileConfigurable<S
@Override
public String getHelpTopic() {
return null;
return myParent.getUsageScopeHelpTopic();
}
}
@@ -1821,5 +1821,7 @@ simplifiable.annotation.problem.descriptor=Annotation <code>#ref</code> may be r
simplifiable.annotation.quickfix=Simplify annotation
overloaded.methods.with.same.number.parameters.option=Ignore overrides of library methods
string.concatenation.in.format.call.display.name=String concatenation argument in call to 'format()'
string.concatenation.in.format.call.problem.descriptor=Non-constant string concatenation argument in call to 'format()' #loc
string.concatenation.in.format.call.problem.descriptor=String concatenation argument in call to 'format()' #loc
string.concatenation.in.format.call.quickfix=Pass ''{0}'' as argument to ''format()''
string.concatenation.in.message.format.call.display.name=String concatenation argument in call to 'MessageFormat.format()'
string.concatenation.in.message.format.call.problem.descriptor=String concatenation argument in call to 'MessageFormat.format()'
@@ -564,6 +564,7 @@ public class InspectionGadgetsPlugin implements ApplicationComponent,
m_inspectionClasses.add(ReturnNullInspection.class);
m_inspectionClasses.add(StaticCallOnSubclassInspection.class);
m_inspectionClasses.add(StringConcatenationInFormatCallInspection.class);
m_inspectionClasses.add(StringConcatenationInMessageFormatCallInspection.class);
m_inspectionClasses.add(StaticFieldReferenceOnSubclassInspection.class);
m_inspectionClasses.add(StringEqualityInspection.class);
m_inspectionClasses.add(SubtractionInCompareToInspection.class);
@@ -86,7 +86,7 @@ public class StringConcatenationInFormatCallInspection extends BaseInspection {
if (rhs == null) {
return;
}
parent.addAfter(rhs, binaryExpression);
parent.add(rhs);
parent.addAfter(lhs, binaryExpression);
binaryExpression.delete();
}
@@ -0,0 +1,230 @@
/*
* Copyright 2010 Bas Leijdekkers
*
* 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.siyeh.ig.bugs;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class StringConcatenationInMessageFormatCallInspection
extends BaseInspection {
@Nls
@NotNull
@Override
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"string.concatenation.in.message.format.call.display.name");
}
@NotNull
@Override
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"string.concatenation.in.message.format.call.problem.descriptor");
}
@Override
protected InspectionGadgetsFix buildFix(Object... infos) {
final PsiReferenceExpression referenceExpression =
(PsiReferenceExpression) infos[0];
final String referenceName = referenceExpression.getReferenceName();
return new StringConcatenationInFormatCallFix(referenceName);
}
private static class StringConcatenationInFormatCallFix
extends InspectionGadgetsFix {
private final String variableName;
public StringConcatenationInFormatCallFix(String variableName) {
this.variableName = variableName;
}
@NotNull
public String getName() {
return InspectionGadgetsBundle.message(
"string.concatenation.in.format.call.quickfix", variableName);
}
@Override
protected void doFix(Project project, ProblemDescriptor descriptor)
throws IncorrectOperationException {
final PsiElement element = descriptor.getPsiElement();
if (!(element instanceof PsiBinaryExpression)) {
return;
}
final PsiBinaryExpression binaryExpression =
(PsiBinaryExpression) element;
final PsiElement parent = binaryExpression.getParent();
if (!(parent instanceof PsiExpressionList)) {
return;
}
final PsiExpressionList expressionList = (PsiExpressionList) parent;
final PsiExpression lhs = binaryExpression.getLOperand();
final PsiExpression rhs = binaryExpression.getROperand();
if (rhs == null) {
return;
}
final PsiExpression[] expressions = expressionList.getExpressions();
final int parameter = expressions.length - 1;
expressionList.add(rhs);
final Object constant =
ExpressionUtils.computeConstantExpression(lhs);
if (constant instanceof String) {
final PsiExpression newExpression =
addParameter(lhs, parameter);
if (newExpression == null) {
expressionList.addAfter(lhs, binaryExpression);
} else {
expressionList.addAfter(newExpression, binaryExpression);
}
} else {
expressionList.addAfter(lhs, binaryExpression);
}
binaryExpression.delete();
}
private static PsiExpression addParameter(PsiExpression expression,
int parameterNumber) {
if (expression instanceof PsiBinaryExpression) {
final PsiBinaryExpression binaryExpression =
(PsiBinaryExpression) expression;
final PsiExpression rhs = binaryExpression.getROperand();
if (rhs == null) {
return null;
}
final PsiExpression newExpression =
addParameter(rhs, parameterNumber);
if (newExpression == null) {
return null;
}
rhs.replace(newExpression);
return expression;
} else if (expression instanceof PsiLiteralExpression) {
final PsiLiteralExpression literalExpression =
(PsiLiteralExpression) expression;
final Object value = literalExpression.getValue();
if (!(value instanceof String)) {
return null;
}
final Project project = expression.getProject();
final PsiElementFactory factory =
JavaPsiFacade.getElementFactory(project);
return factory.createExpressionFromText("\"" + value + '{' +
parameterNumber + "}\"", null);
} else {
return null;
}
}
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new StringConcatenationInFormatCallVisitor();
}
private static class StringConcatenationInFormatCallVisitor
extends BaseInspectionVisitor {
@Override
public void visitMethodCallExpression(
PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
final PsiReferenceExpression methodExpression =
expression.getMethodExpression();
if (!isMessageFormatCall(methodExpression)) {
return;
}
final PsiExpressionList argumentList = expression.getArgumentList();
final PsiExpression[] arguments = argumentList.getExpressions();
if(arguments.length == 0){
return;
}
final PsiExpression firstArgument = arguments[0];
final PsiType type = firstArgument.getType();
if(type == null){
return;
}
final int formatArgumentIndex;
if("java.util.Locale".equals(type.getCanonicalText())
&& arguments.length > 1){
formatArgumentIndex = 1;
} else{
formatArgumentIndex = 0;
}
final PsiExpression formatArgument = arguments[formatArgumentIndex];
final PsiType formatArgumentType = formatArgument.getType();
if (formatArgumentType == null ||
!formatArgumentType.equalsToText("java.lang.String")) {
return;
}
if (!(formatArgument instanceof PsiBinaryExpression)) {
return;
}
if (PsiUtil.isConstantExpression(formatArgument)) {
return;
}
final PsiBinaryExpression binaryExpression =
(PsiBinaryExpression) formatArgument;
final PsiExpression lhs = binaryExpression.getLOperand();
final PsiType lhsType = lhs.getType();
if (lhsType == null || !lhsType.equalsToText("java.lang.String")) {
return;
}
final PsiExpression rhs = binaryExpression.getROperand();
if (!(rhs instanceof PsiReferenceExpression)) {
return;
}
registerError(formatArgument, rhs);
}
private static boolean isMessageFormatCall(
PsiReferenceExpression methodExpression) {
@NonNls final String referenceName =
methodExpression.getReferenceName();
if (!"format".equals(referenceName)) {
return false;
}
final PsiExpression qualifierExpression =
methodExpression.getQualifierExpression();
if (!(qualifierExpression instanceof PsiReferenceExpression)) {
return false;
}
final PsiReferenceExpression referenceExpression =
(PsiReferenceExpression) qualifierExpression;
final PsiElement target = referenceExpression.resolve();
if (!(target instanceof PsiClass)) {
return false;
}
final PsiClass aClass = (PsiClass) target;
return ClassUtils.isSubclass(aClass, "java.text.MessageFormat");
}
}
}
@@ -1,7 +1,7 @@
<html>
<body><table> <tr> <td valign="top">
<body>
<font face="verdana" size="-1">
This inspection reports non-constant string concatenations used as a Format string argument.
This inspection reports non-constant string concatenations used as a format string argument.
Often this is the result of mistakenly concatenating a string format argument by typing a '+'
when a ',' was meant.
This inspection checks calls to appropriate methods on
@@ -9,5 +9,7 @@ This inspection checks calls to appropriate methods on
<b><font color="#000080">java.lang.String</font></b>,
<b><font color="#000080">java.io.PrintWriter</font></b>,
or <b><font color="#000080">java.io.PrintStream</font></b>.
</font></td> </tr> <tr> <td height="20"> <font face="verdana" size="-2">New in 10.1, Powered by InspectionGadgets </font> </td> </tr> </table> </body>
</font>
<p><font face="verdana" size="-2">New in 10.1, Powered by InspectionGadgets </font>
</body>
</html>
@@ -0,0 +1,10 @@
<html>
<body>
<font face="verdana" size="-1">
This inspection reports non-constant string concatenations used as an argument to a call to
<b><font color="#000080">MessageFormat.format()</font></b>.
Often this is the result of mistakenly concatenating a string format argument by typing
a '+' when a ',' was meant.
</font><p>
<font face="verdana" size="-2">New in 10.1, Powered by InspectionGadgets </font></body>
</html>