summaryrefslogtreecommitdiff
path: root/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/NonThreadSafeLazyInitializationInspection.java
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/NonThreadSafeLazyInitializationInspection.java')
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/NonThreadSafeLazyInitializationInspection.java246
1 files changed, 0 insertions, 246 deletions
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/NonThreadSafeLazyInitializationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/NonThreadSafeLazyInitializationInspection.java
deleted file mode 100644
index 2e0bebac17b9..000000000000
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/NonThreadSafeLazyInitializationInspection.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright 2003-2007 Dave Griffith, 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.initialization;
-
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.search.searches.ReferencesSearch;
-import com.intellij.psi.tree.IElementType;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.Processor;
-import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspection;
-import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.InspectionGadgetsFix;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Collection;
-
-public class NonThreadSafeLazyInitializationInspection
- extends BaseInspection {
-
- @Override
- @NotNull
- public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "non.thread.safe.lazy.initialization.display.name");
- }
-
- @Override
- @NotNull
- public String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message(
- "non.thread.safe.lazy.initialization.problem.descriptor");
- }
-
- @Override
- public BaseInspectionVisitor buildVisitor() {
- return new UnsafeSafeLazyInitializationVisitor();
- }
-
- private static class UnsafeSafeLazyInitializationVisitor
- extends BaseInspectionVisitor {
-
- @Override
- public void visitAssignmentExpression(
- @NotNull PsiAssignmentExpression expression) {
- super.visitAssignmentExpression(expression);
- final PsiExpression lhs = expression.getLExpression();
- if (!(lhs instanceof PsiReferenceExpression)) {
- return;
- }
- final PsiReference reference = (PsiReference)lhs;
- final PsiElement referent = reference.resolve();
- if (!(referent instanceof PsiField)) {
- return;
- }
- final PsiField field = (PsiField)referent;
- if (!field.hasModifierProperty(PsiModifier.STATIC)) {
- return;
- }
- if (isInStaticInitializer(expression)) {
- return;
- }
- if (isInSynchronizedContext(expression)) {
- return;
- }
- if (!isLazy(expression, (PsiReferenceExpression)lhs)) {
- return;
- }
- boolean assignedOnce = isAssignedOnce(referent);
- boolean safeToDelete = isSafeToDeleteIfStatement(expression);
- registerError(lhs, assignedOnce && safeToDelete);
- }
-
- private static boolean isAssignedOnce(PsiElement referent) {
- final int[] writeCount = new int[1];
- return ReferencesSearch.search(referent).forEach(new Processor<PsiReference>() {
- @Override
- public boolean process(PsiReference reference) {
- PsiElement element = reference.getElement();
- if (!(element instanceof PsiExpression)) {
- return true;
- }
- if (!PsiUtil.isAccessedForWriting((PsiExpression)element)) {
- return true;
- }
- return ++writeCount[0] != 2;
- }
- });
- }
-
- private static boolean isSafeToDeleteIfStatement(PsiElement expression) {
- PsiIfStatement ifStatement = PsiTreeUtil.getParentOfType(expression, PsiIfStatement.class);
- if (ifStatement.getElseBranch() != null) {
- return false;
- }
- PsiStatement thenBranch = ifStatement.getThenBranch();
- if (thenBranch == null) return false;
- if (!(thenBranch instanceof PsiBlockStatement)) {
- return true;
- }
- return ((PsiBlockStatement)thenBranch).getCodeBlock().getStatements().length == 1;
- }
-
- private static boolean isLazy(PsiAssignmentExpression expression,
- PsiReferenceExpression lhs) {
- final PsiIfStatement ifStatement =
- PsiTreeUtil.getParentOfType(expression,
- PsiIfStatement.class);
- if (ifStatement == null) {
- return false;
- }
- final PsiExpression condition = ifStatement.getCondition();
- if (condition == null) {
- return false;
- }
- return isNullComparison(condition, lhs);
- }
-
- private static boolean isNullComparison(
- PsiExpression condition, PsiReferenceExpression reference) {
- if (!(condition instanceof PsiBinaryExpression)) {
- return false;
- }
- final PsiBinaryExpression comparison =
- (PsiBinaryExpression)condition;
- final IElementType tokenType = comparison.getOperationTokenType();
- if (!tokenType.equals(JavaTokenType.EQEQ)) {
- return false;
- }
- final PsiExpression lhs = comparison.getLOperand();
- final PsiExpression rhs = comparison.getROperand();
- if (rhs == null) {
- return false;
- }
- final String lhsText = lhs.getText();
- final String rhsText = rhs.getText();
- if (!PsiKeyword.NULL.equals(lhsText) &&
- !PsiKeyword.NULL.equals(rhsText)) {
- return false;
- }
- final String referenceText = reference.getText();
- return referenceText.equals(lhsText) ||
- referenceText.equals(rhsText);
- }
-
- private static boolean isInSynchronizedContext(PsiElement element) {
- final PsiSynchronizedStatement syncBlock =
- PsiTreeUtil.getParentOfType(element,
- PsiSynchronizedStatement.class);
- if (syncBlock != null) {
- return true;
- }
- final PsiMethod method =
- PsiTreeUtil.getParentOfType(element,
- PsiMethod.class);
- return method != null &&
- method.hasModifierProperty(PsiModifier.SYNCHRONIZED)
- && method.hasModifierProperty(PsiModifier.STATIC);
- }
-
- private static boolean isInStaticInitializer(PsiElement element) {
- final PsiClassInitializer initializer =
- PsiTreeUtil.getParentOfType(element,
- PsiClassInitializer.class);
- return initializer != null &&
- initializer.hasModifierProperty(PsiModifier.STATIC);
- }
- }
-
- @Override
- protected InspectionGadgetsFix buildFix(Object... infos) {
- boolean isApplicable = ((Boolean)infos[0]).booleanValue();
- return isApplicable ? new IntroduceHolderFix() : null;
- }
-
- private static class IntroduceHolderFix extends InspectionGadgetsFix {
- @Override
- protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
- PsiReferenceExpression expression = (PsiReferenceExpression)descriptor.getPsiElement();
- PsiElement resolved = expression.resolve();
- if (!(resolved instanceof PsiField)) return;
- PsiField field = (PsiField)resolved;
- String holderName = suggestHolderName(field);
- @NonNls String text = "private static class " + holderName
- + " {" +
- "private static final " + field.getType().getCanonicalText() + " " +
- field.getName() + " = " + ((PsiAssignmentExpression)expression.getParent()).getRExpression().getText() + ";"
- + "}";
- PsiElementFactory elementFactory = JavaPsiFacade.getInstance(field.getProject()).getElementFactory();
- PsiClass holder = elementFactory.createClassFromText(text, field).getInnerClasses()[0];
- PsiMethod method = PsiTreeUtil.getParentOfType(expression, PsiMethod.class);
- method.getParent().addBefore(holder, method);
-
- PsiIfStatement ifStatement = PsiTreeUtil.getParentOfType(expression, PsiIfStatement.class);
- ifStatement.delete();
-
- final PsiExpression holderReference = elementFactory.createExpressionFromText(holderName + "." + field.getName(), field);
- Collection<PsiReference> references = ReferencesSearch.search(field).findAll();
- for (PsiReference reference : references) {
- PsiElement element = reference.getElement();
- element.replace(holderReference);
- }
- field.delete();
- }
-
- @NonNls
- private static String suggestHolderName(PsiField field) {
- String string = field.getType().getDeepComponentType().getPresentableText();
- final int index = string.indexOf('<');
- if (index != -1) {
- string = string.substring(0, index);
- }
- return string + "Holder";
- }
-
- @Override
- @NotNull
- public String getName() {
- return "Introduce holder class";
- }
-
- @NotNull
- @Override
- public String getFamilyName() {
- return getName();
- }
- }
-} \ No newline at end of file