From 97bdbeab2e8075b62b40c1fdca1176c3f5cc3189 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 22 Apr 2011 13:36:59 +0400 Subject: [PATCH 1/4] NPE --- .../com/siyeh/ig/junit/TestMethodWithoutAssertionInspection.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspection.java index 7d8d9caee181..a2c499174c3d 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspection.java @@ -189,6 +189,7 @@ public class TestMethodWithoutAssertionInspection extends BaseInspection { } private boolean containsAssertion(PsiElement element) { + if (element == null) return false; final ContainsAssertionVisitor visitor = new ContainsAssertionVisitor(); element.accept(visitor); From cc31ae255ef57010287a9ac6a7a6c57de27f04b4 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 22 Apr 2011 15:36:47 +0400 Subject: [PATCH 2/4] assertion for strange path --- .../fixtures/impl/CodeInsightTestFixtureImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java index e4f17f8db55a..ba22374ef556 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -199,6 +199,9 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig assert destFile.mkdirs() : destFile; } else { + if (!fromFile.exists()) { + fail("Cannot find source file: '"+sourceFilePath+"'. getTestDataPath()='"+getTestDataPath()+"'. getHomePath()='"+getHomePath()+"'."); + } try { FileUtil.copy(fromFile, destFile); } From 2af0bb0dee73afeff39838dc9c28c6de21e25a1e Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 22 Apr 2011 18:33:02 +0400 Subject: [PATCH 3/4] reduce number of PsiClasses held on stack --- .../searches/ClassInheritorsSearch.java | 68 +++++++++++++------ 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/java/openapi/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java b/java/openapi/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java index 1d8f2b849293..e78fa7be6b87 100644 --- a/java/openapi/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java +++ b/java/openapi/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java @@ -21,23 +21,22 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; -import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiSearchScopeUtil; import com.intellij.psi.search.SearchScope; -import com.intellij.util.Function; +import com.intellij.reference.SoftReference; import com.intellij.util.Processor; import com.intellij.util.Query; import com.intellij.util.QueryExecutor; import com.intellij.util.containers.Stack; -import gnu.trove.TObjectHashingStrategy; +import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.HashSet; +import java.lang.ref.Reference; import java.util.Set; /** @@ -154,9 +153,7 @@ public class ClassInheritorsSearch extends ExtensibleQueryFactory() { public String compute() { @@ -173,25 +170,26 @@ public class ClassInheritorsSearch extends ExtensibleQueryFactory currentBase = Ref.create(null); - final Stack stack = new Stack(); - final Set processed = new HashSet(); + final Stack, String>> stack = new Stack, String>>(); + // there are two sets for memory optimization: it's cheaper to hold FQN than PsiClass + final Set processedFqns = new THashSet(); // FQN of processed classes if the class has one + final Set processed = new THashSet(); // processed classes without FQN (e.g. anonymous) + final Processor processor = new Processor() { public boolean process(final PsiClass candidate) { ProgressManager.checkCanceled(); final Ref result = new Ref(); + final String[] fqn = new String[1]; ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { + fqn[0] = candidate.getQualifiedName(); if (parameters.isCheckInheritance() || parameters.isCheckDeep() && !(candidate instanceof PsiAnonymousClass)) { if (!candidate.isInheritor(currentBase.get(), false)) { result.set(true); @@ -213,27 +211,53 @@ public class ClassInheritorsSearch extends ExtensibleQueryFactory ref = fqn[0] == null ? createHardReference(candidate) : new SoftReference(candidate); + stack.push(Pair.create(ref, fqn[0])); } return true; } }; - stack.push(baseClass); - final GlobalSearchScope scope = GlobalSearchScope.allScope(baseClass.getProject()); + stack.push(Pair.create(createHardReference(baseClass), qname)); + final GlobalSearchScope projectScope = GlobalSearchScope.allScope(baseClass.getProject()); + final JavaPsiFacade facade = JavaPsiFacade.getInstance(projectScope.getProject()); while (!stack.isEmpty()) { ProgressManager.checkCanceled(); - final PsiClass psiClass = stack.pop(); - if (!processed.add(psiClass)) continue; + Pair, String> pair = stack.pop(); + PsiClass psiClass = pair.getFirst().get(); + final String fqn = pair.getSecond(); + if (psiClass == null) { + psiClass = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiClass compute() { + return facade.findClass(fqn, projectScope); + } + }); + if (psiClass == null) continue; + } + if (fqn == null) { + if (!processed.add(psiClass)) continue; + } + else { + if (!processedFqns.add(fqn)) continue; + } currentBase.set(psiClass); - if (!DirectClassInheritorsSearch.search(psiClass, scope, parameters.isIncludeAnonymous()).forEach(processor)) return false; + if (!DirectClassInheritorsSearch.search(psiClass, projectScope, parameters.isIncludeAnonymous()).forEach(processor)) return false; } return true; } - private static boolean isFinal(final PsiClass baseClass) { + private static Reference createHardReference(final PsiClass candidate) { + return new SoftReference(candidate){ + @Override + public PsiClass get() { + return candidate; + } + }; + } + + private static boolean isFinal(@NotNull final PsiClass baseClass) { return ApplicationManager.getApplication().runReadAction(new Computable() { public Boolean compute() { return Boolean.valueOf(baseClass.hasModifierProperty(PsiModifier.FINAL)); From cc2f0a54ced6b77814d4f421e4c1d9dcd5796c3b Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 22 Apr 2011 18:34:17 +0400 Subject: [PATCH 4/4] mem leaks --- .../quickFix/CreateClassOrPackageFix.java | 61 ++++++-------- .../CatchBodyVisitor.java | 50 +++++------ .../DefaultFileTemplateUsageInspection.java | 36 ++------ .../FileHeaderChecker.java | 82 ++++++++----------- .../MethodBodyChecker.java | 55 ++++++------- .../AdjustPackageNameFix.java | 32 ++++---- .../WrongPackageStatementInspection.java | 6 +- 7 files changed, 127 insertions(+), 195 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/quickFix/CreateClassOrPackageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/quickFix/CreateClassOrPackageFix.java index c07ed8ada65c..4198411c0251 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/quickFix/CreateClassOrPackageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/quickFix/CreateClassOrPackageFix.java @@ -18,9 +18,7 @@ package com.intellij.codeInsight.daemon.quickFix; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.daemon.impl.quickfix.CreateClassKind; import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils; -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.codeInspection.LocalQuickFix; -import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement; import com.intellij.ide.util.DirectoryChooserUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; @@ -44,10 +42,8 @@ import java.util.*; /** * @author peter */ -public class CreateClassOrPackageFix implements IntentionAction, LocalQuickFix { - +public class CreateClassOrPackageFix extends LocalQuickFixAndIntentionActionOnPsiElement { private final List myWritableDirectoryList; - private final PsiElement myContext; private final String myPresentation; @Nullable private final ClassKind myClassKind; @@ -92,17 +88,17 @@ public class CreateClassOrPackageFix implements IntentionAction, LocalQuickFix { return createFix(qualifiedName, context.getResolveScope(), context, null, kind, superClass, null); } - private CreateClassOrPackageFix(final List writableDirectoryList, - final PsiElement context, - final String presentation, - final String redPart, + private CreateClassOrPackageFix(@NotNull List writableDirectoryList, + @NotNull PsiElement context, + @NotNull String presentation, + @NotNull String redPart, @Nullable ClassKind kind, @Nullable String superClass, @Nullable final String templateName) { + super(context); myRedPart = redPart; myTemplateName = templateName; myWritableDirectoryList = writableDirectoryList; - myContext = context; myClassKind = kind; mySuperClass = superClass; myPresentation = presentation; @@ -111,13 +107,8 @@ public class CreateClassOrPackageFix implements IntentionAction, LocalQuickFix { @NotNull public String getText() { return QuickFixBundle.message( - myClassKind == ClassKind.INTERFACE ? "create.interface.text" : myClassKind != null ? "create.class.text" : "create.package.text", - myPresentation); - } - - @NotNull - public String getName() { - return getText(); + myClassKind == ClassKind.INTERFACE ? "create.interface.text" : myClassKind != null ? "create.class.text" : "create.package.text", + myPresentation); } @NotNull @@ -125,19 +116,28 @@ public class CreateClassOrPackageFix implements IntentionAction, LocalQuickFix { return getText(); } - public void applyFix(@NotNull final Project project, @NotNull ProblemDescriptor descriptor) { - final PsiFile file = descriptor.getPsiElement().getContainingFile(); + @Override + public void invoke(@NotNull final Project project, + @NotNull final PsiFile file, + @Nullable("is null when called from inspection") Editor editor, + @NotNull final PsiElement startElement, + @NotNull PsiElement endElement) { if (isAvailable(project, null, file)) { new WriteCommandAction(project) { protected void run(Result result) throws Throwable { - invoke(project, null, file); + final PsiDirectory directory = chooseDirectory(project, file); + if (directory == null) return; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + doCreate(directory, startElement); + } + }); } }.execute(); } } private static boolean checkCreateClassOrPackage(final boolean createJavaClass, final PsiDirectory directory, final String name) { - try { if (createJavaClass) { JavaDirectoryService.getInstance().checkCreateClass(directory, name); @@ -152,21 +152,6 @@ public class CreateClassOrPackageFix implements IntentionAction, LocalQuickFix { } } - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return true; - } - - public void invoke(@NotNull Project project, Editor editor, PsiFile file) { - - final PsiDirectory directory = chooseDirectory(project, file); - if (directory == null) return; - ApplicationManager.getApplication().runWriteAction(new Runnable() { - public void run() { - doCreate(directory); - } - }); - } - @Nullable private PsiDirectory chooseDirectory(final Project project, final PsiFile file) { PsiDirectory preferredDirectory = myWritableDirectoryList.isEmpty() ? null : myWritableDirectoryList.get(0); @@ -192,7 +177,7 @@ public class CreateClassOrPackageFix implements IntentionAction, LocalQuickFix { return preferredDirectory; } - private void doCreate(final PsiDirectory baseDirectory) { + private void doCreate(final PsiDirectory baseDirectory, PsiElement myContext) { final PsiManager manager = baseDirectory.getManager(); PsiDirectory directory = baseDirectory; String lastName; diff --git a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/CatchBodyVisitor.java b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/CatchBodyVisitor.java index 8a13f5ff8398..bbea38fa16a9 100644 --- a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/CatchBodyVisitor.java +++ b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/CatchBodyVisitor.java @@ -20,12 +20,12 @@ import com.intellij.codeInspection.*; import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.ide.fileTemplates.FileTemplateManager; import com.intellij.ide.fileTemplates.JavaTemplateUtil; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; @@ -108,41 +108,33 @@ class CatchBodyVisitor extends JavaRecursiveElementWalkingVisitor { Pair range = DefaultFileTemplateUsageInspection.getInteriorRange(catchBlock); final String description = InspectionsBundle.message("default.file.template.description"); ProblemDescriptor descriptor = myManager.createProblemDescriptor(range.first, range.second, description, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - myOnTheFly, createQuickFix(section)); + myOnTheFly, createQuickFix()); myProblemDescriptors.add(descriptor); } - private static LocalQuickFix[] createQuickFix(final PsiCatchSection section) { + private static LocalQuickFix[] createQuickFix() { FileTemplate template = FileTemplateManager.getInstance().getCodeTemplate(JavaTemplateUtil.TEMPLATE_CATCH_BODY); - final Runnable runnable = new Runnable() { - public void run() { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - public void run() { - final PsiParameter parameter = section.getParameter(); - if (parameter == null) return; - PsiCodeBlock catchBlock = section.getCatchBlock(); - if (catchBlock == null) return; - PsiType type = parameter.getType(); - if (!(type instanceof PsiClassType)) return; - final PsiJavaParserFacade elementFactory = JavaPsiFacade.getInstance(section.getProject()).getParserFacade(); - try { - PsiCatchSection sectionTemplate = elementFactory.createCatchSection((PsiClassType)type, parameter.getName(), parameter); - section.replace(sectionTemplate); - } - catch (IncorrectOperationException e) { - LOG.error(e); - } - } - }); - } - }; - ReplaceWithFileTemplateFix replaceWithFileTemplateFix = new ReplaceWithFileTemplateFix() { - public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - runnable.run(); + public void applyFix(@NotNull Project project, @NotNull final ProblemDescriptor descriptor) { + final PsiCatchSection section = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiCatchSection.class); + if (section == null) return; + final PsiParameter parameter = section.getParameter(); + if (parameter == null) return; + PsiCodeBlock catchBlock = section.getCatchBlock(); + if (catchBlock == null) return; + PsiType type = parameter.getType(); + if (!(type instanceof PsiClassType)) return; + final PsiJavaParserFacade elementFactory = JavaPsiFacade.getInstance(section.getProject()).getParserFacade(); + try { + PsiCatchSection sectionTemplate = elementFactory.createCatchSection((PsiClassType)type, parameter.getName(), parameter); + section.replace(sectionTemplate); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } } }; - LocalQuickFix editFileTemplateFix = DefaultFileTemplateUsageInspection.createEditFileTemplateFix(template, runnable); + LocalQuickFix editFileTemplateFix = DefaultFileTemplateUsageInspection.createEditFileTemplateFix(template, replaceWithFileTemplateFix); if (template.isDefault()) { return new LocalQuickFix[]{editFileTemplateFix}; } diff --git a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/DefaultFileTemplateUsageInspection.java b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/DefaultFileTemplateUsageInspection.java index 256265b2e5ea..6fb1f2fb1203 100644 --- a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/DefaultFileTemplateUsageInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/DefaultFileTemplateUsageInspection.java @@ -15,17 +15,14 @@ */ package com.intellij.codeInspection.defaultFileTemplateUsage; -import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.*; import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.ide.fileTemplates.FileTemplateManager; import com.intellij.ide.fileTemplates.impl.FileTemplateConfigurable; -import com.intellij.openapi.editor.Editor; import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.psi.*; -import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -85,7 +82,7 @@ public class DefaultFileTemplateUsageInspection extends BaseJavaLocalInspectionT break; } int end; - for (end=children.length-1; start start;end--) { PsiElement child = children[end]; if (child instanceof PsiWhiteSpace) continue; if (child instanceof PsiJavaToken && ((PsiJavaToken)child).getTokenType() == JavaTokenType.RBRACE) continue; @@ -122,15 +119,15 @@ public class DefaultFileTemplateUsageInspection extends BaseJavaLocalInspectionT return new InspectionOptions(this).getComponent(); } - public static LocalQuickFix createEditFileTemplateFix(final FileTemplate templateToEdit, final Runnable replaceTemplateFix) { + public static LocalQuickFix createEditFileTemplateFix(final FileTemplate templateToEdit, final ReplaceWithFileTemplateFix replaceTemplateFix) { return new MyLocalQuickFix(templateToEdit, replaceTemplateFix); } - private static class MyLocalQuickFix implements LocalQuickFix, IntentionAction { + private static class MyLocalQuickFix implements LocalQuickFix { private final FileTemplate myTemplateToEdit; - private final Runnable myReplaceTemplateFix; + private final ReplaceWithFileTemplateFix myReplaceTemplateFix; - public MyLocalQuickFix(FileTemplate templateToEdit, Runnable replaceTemplateFix) { + public MyLocalQuickFix(FileTemplate templateToEdit, ReplaceWithFileTemplateFix replaceTemplateFix) { myTemplateToEdit = templateToEdit; myReplaceTemplateFix = replaceTemplateFix; } @@ -146,22 +143,6 @@ public class DefaultFileTemplateUsageInspection extends BaseJavaLocalInspectionT } public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - invoke(project, null, null); - } - - @NotNull - @Override - public String getText() { - return getName(); - } - - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return true; - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { final FileTemplateConfigurable configurable = new FileTemplateConfigurable(); SwingUtilities.invokeLater(new Runnable(){ public void run() { @@ -170,14 +151,9 @@ public class DefaultFileTemplateUsageInspection extends BaseJavaLocalInspectionT }); boolean ok = ShowSettingsUtil.getInstance().editConfigurable(project, configurable); if (ok) { - myReplaceTemplateFix.run(); + myReplaceTemplateFix.applyFix(project, descriptor); FileTemplateManager.getInstance().saveAll(); } } - - @Override - public boolean startInWriteAction() { - return false; - } } } diff --git a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.java b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.java index 9096ae84e829..807eb6d2ff95 100644 --- a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.java +++ b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.java @@ -19,7 +19,6 @@ import com.intellij.codeInsight.CodeInsightUtil; import com.intellij.codeInspection.*; import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.ide.fileTemplates.FileTemplateManager; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; @@ -76,7 +75,7 @@ public class FileHeaderChecker { }); PsiDocComment element = docComment.get(); if (element == null) return null; - LocalQuickFix[] quickFix = createQuickFix(element, matcher, offsetToProperty); + LocalQuickFix[] quickFix = createQuickFix(matcher, offsetToProperty); final String description = InspectionsBundle.message("default.file.template.description"); return manager.createProblemDescriptor(element, description, onTheFly, quickFix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING); } @@ -98,55 +97,46 @@ public class FileHeaderChecker { return properties; } - private static LocalQuickFix[] createQuickFix(final PsiDocComment element, - final Matcher matcher, - final TIntObjectHashMap offsetToProperty) { + private static LocalQuickFix[] createQuickFix(final Matcher matcher, + final TIntObjectHashMap offsetToProperty) { final FileTemplate template = FileTemplateManager.getInstance().getPattern(FileTemplateManager.FILE_HEADER_TEMPLATE_NAME); - final Runnable runnable = new Runnable() { - public void run() { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - public void run() { - if (!element.isValid()) return; - if (!CodeInsightUtil.preparePsiElementsForWrite(element)) return; - String newText; - try { - newText = template.getText(computeProperties(matcher, offsetToProperty)); - } - catch (IOException e) { - LOG.error(e); - return; - } - try { - int offset = element.getTextRange().getStartOffset(); - PsiFile psiFile = element.getContainingFile(); - if (psiFile == null) return; - PsiDocumentManager documentManager = PsiDocumentManager.getInstance(psiFile.getProject()); - Document document = documentManager.getDocument(psiFile); - if (document == null) return; - - element.delete(); - documentManager.doPostponedOperationsAndUnblockDocument(document); - documentManager.commitDocument(document); - - document.insertString(offset, newText); - } - catch (IncorrectOperationException e) { - LOG.error(e); - } - catch (IllegalStateException e) { - LOG.error("Cannot create doc comment from text: '" + newText + "'", e); - } - } - }); - } - }; final ReplaceWithFileTemplateFix replaceTemplateFix = new ReplaceWithFileTemplateFix() { - public void applyFix(@NotNull final Project project, @NotNull ProblemDescriptor descriptor) { - runnable.run(); + public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) { + PsiElement element = descriptor.getPsiElement(); + if (element == null || !element.isValid()) return; + if (!CodeInsightUtil.preparePsiElementsForWrite(element)) return; + String newText; + try { + newText = template.getText(computeProperties(matcher, offsetToProperty)); + } + catch (IOException e) { + LOG.error(e); + return; + } + try { + int offset = element.getTextRange().getStartOffset(); + PsiFile psiFile = element.getContainingFile(); + if (psiFile == null) return; + PsiDocumentManager documentManager = PsiDocumentManager.getInstance(psiFile.getProject()); + Document document = documentManager.getDocument(psiFile); + if (document == null) return; + + element.delete(); + documentManager.doPostponedOperationsAndUnblockDocument(document); + documentManager.commitDocument(document); + + document.insertString(offset, newText); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + catch (IllegalStateException e) { + LOG.error("Cannot create doc comment from text: '" + newText + "'", e); + } } }; - final LocalQuickFix editFileTemplateFix = DefaultFileTemplateUsageInspection.createEditFileTemplateFix(template, runnable); + final LocalQuickFix editFileTemplateFix = DefaultFileTemplateUsageInspection.createEditFileTemplateFix(template, replaceTemplateFix); if (template.isDefault()) { return new LocalQuickFix[]{editFileTemplateFix}; } diff --git a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/MethodBodyChecker.java b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/MethodBodyChecker.java index 3d060bf487a2..1b97ed3a6912 100644 --- a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/MethodBodyChecker.java +++ b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/MethodBodyChecker.java @@ -23,7 +23,6 @@ import com.intellij.codeInspection.*; import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.ide.fileTemplates.FileTemplateManager; import com.intellij.ide.fileTemplates.JavaTemplateUtil; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; @@ -32,6 +31,7 @@ import com.intellij.openapi.util.UserDataHolderEx; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ConcurrentHashMap; import org.jetbrains.annotations.NotNull; @@ -169,40 +169,33 @@ public class MethodBodyChecker { return null; } - final Runnable runnable = new Runnable() { - public void run() { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - public void run() { - PsiType returnType = method.getReturnType(); - if (method.isConstructor() || returnType == null) return; - PsiCodeBlock body = method.getBody(); - if (body == null) return; - if (!CodeInsightUtil.preparePsiElementsForWrite(body)) return; - PsiClass aClass = method.getContainingClass(); - if (aClass == null) return; - List superSignatures = method.getHierarchicalMethodSignature().getSuperSignatures(); - try { - PsiMethod templateMethod = JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createMethod("x", returnType); - setupMethodBody(superSignatures, templateMethod, aClass, false); - final PsiCodeBlock templateBody = templateMethod.getBody(); - if (templateBody == null) return; - - PsiElement newBody = body.replace(templateBody); - CodeStyleManager.getInstance(aClass.getManager()).reformat(newBody); - } - catch (IncorrectOperationException e) { - LOG.error(e); - } - } - }); - } - }; final ReplaceWithFileTemplateFix replaceWithFileTemplateFix = new ReplaceWithFileTemplateFix() { public void applyFix(@NotNull final Project project, @NotNull ProblemDescriptor descriptor) { - runnable.run(); + PsiMethod method = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiMethod.class); + if (method == null) return; + PsiType returnType = method.getReturnType(); + if (method.isConstructor() || returnType == null) return; + PsiCodeBlock body = method.getBody(); + if (body == null) return; + if (!CodeInsightUtil.preparePsiElementsForWrite(body)) return; + PsiClass aClass = method.getContainingClass(); + if (aClass == null) return; + List superSignatures = method.getHierarchicalMethodSignature().getSuperSignatures(); + try { + PsiMethod templateMethod = JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createMethod("x", returnType); + setupMethodBody(superSignatures, templateMethod, aClass, false); + final PsiCodeBlock templateBody = templateMethod.getBody(); + if (templateBody == null) return; + + PsiElement newBody = body.replace(templateBody); + CodeStyleManager.getInstance(aClass.getManager()).reformat(newBody); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } } }; - LocalQuickFix editFileTemplateFix = DefaultFileTemplateUsageInspection.createEditFileTemplateFix(template, runnable); + LocalQuickFix editFileTemplateFix = DefaultFileTemplateUsageInspection.createEditFileTemplateFix(template, replaceWithFileTemplateFix); if (template != null && template.isDefault()) { return new LocalQuickFix[]{editFileTemplateFix}; } diff --git a/java/java-impl/src/com/intellij/codeInspection/wrongPackageStatement/AdjustPackageNameFix.java b/java/java-impl/src/com/intellij/codeInspection/wrongPackageStatement/AdjustPackageNameFix.java index 127df5de62d9..a488487ad091 100644 --- a/java/java-impl/src/com/intellij/codeInspection/wrongPackageStatement/AdjustPackageNameFix.java +++ b/java/java-impl/src/com/intellij/codeInspection/wrongPackageStatement/AdjustPackageNameFix.java @@ -27,19 +27,15 @@ import org.jetbrains.annotations.NotNull; public class AdjustPackageNameFix implements LocalQuickFix { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.wrongPackageStatement.AdjustPackageNameFix"); - private final PsiJavaFile myFile; - private final PsiPackageStatement myStatement; - private final PsiPackage myTargetPackage; + private final String myName; - public AdjustPackageNameFix(PsiJavaFile file, PsiPackageStatement statement, PsiPackage targetPackage) { - myFile = file; - myStatement = statement; - myTargetPackage = targetPackage; + public AdjustPackageNameFix(String targetPackage) { + myName = targetPackage; } @NotNull public String getName() { - return QuickFixBundle.message("adjust.package.text", myTargetPackage.getQualifiedName()); + return QuickFixBundle.message("adjust.package.text", myName); } @NotNull @@ -47,21 +43,21 @@ public class AdjustPackageNameFix implements LocalQuickFix { return QuickFixBundle.message("adjust.package.family"); } - public boolean isAvailable() { - return myFile != null - && myFile.isValid() - && myFile.getManager().isInProject(myFile) - && myTargetPackage != null - && myTargetPackage.isValid() - && (myStatement == null || myStatement.isValid()) - ; - } - public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) { + PsiElement element = descriptor.getPsiElement(); + if (element == null) return; + PsiFile myFile = element.getContainingFile(); if (!CodeInsightUtilBase.prepareFileForWrite(myFile)) return; + PsiDirectory directory = myFile.getContainingDirectory(); + if (directory == null) return; + PsiPackage myTargetPackage = JavaDirectoryService.getInstance().getPackage(directory); + if (myTargetPackage == null) return; + try { PsiElementFactory factory = JavaPsiFacade.getInstance(myFile.getProject()).getElementFactory(); + PsiPackageStatement myStatement = ((PsiJavaFile)myFile).getPackageStatement(); + if (myTargetPackage.getQualifiedName().length() == 0) { if (myStatement != null) { myStatement.delete(); diff --git a/java/java-impl/src/com/intellij/codeInspection/wrongPackageStatement/WrongPackageStatementInspection.java b/java/java-impl/src/com/intellij/codeInspection/wrongPackageStatement/WrongPackageStatementInspection.java index adcf3bfe8158..3bd236db3e0e 100644 --- a/java/java-impl/src/com/intellij/codeInspection/wrongPackageStatement/WrongPackageStatementInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/wrongPackageStatement/WrongPackageStatementInspection.java @@ -56,7 +56,7 @@ public class WrongPackageStatementInspection extends BaseJavaLocalInspectionTool String description = JavaErrorMessages.message("missing.package.statement", packageName); return new ProblemDescriptor[]{manager.createProblemDescriptor(classes[0].getNameIdentifier(), description, - new AdjustPackageNameFix(javaFile, null, dirPackage), + new AdjustPackageNameFix(packageName), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly)}; } if (packageStatement != null) { @@ -64,10 +64,10 @@ public class WrongPackageStatementInspection extends BaseJavaLocalInspectionTool PsiPackage classPackage = (PsiPackage)packageReference.resolve(); List availableFixes = new ArrayList(); if (classPackage == null) { - availableFixes.add(new AdjustPackageNameFix(javaFile, packageStatement, dirPackage)); + availableFixes.add(new AdjustPackageNameFix(packageName)); } else if (!Comparing.equal(dirPackage.getQualifiedName(), packageReference.getText(), true)) { - availableFixes.add(new AdjustPackageNameFix(javaFile, packageStatement, dirPackage)); + availableFixes.add(new AdjustPackageNameFix(packageName)); MoveToPackageFix moveToPackageFix = new MoveToPackageFix(classPackage.getQualifiedName()); if (moveToPackageFix.isAvailable(file)) { availableFixes.add(moveToPackageFix);