diff --git a/java/compiler/impl/src/com/intellij/compiler/make/ChangedConstantsDependencyProcessor.java b/java/compiler/impl/src/com/intellij/compiler/make/ChangedConstantsDependencyProcessor.java index fde5ee1fe91e..e4102a9899f5 100644 --- a/java/compiler/impl/src/com/intellij/compiler/make/ChangedConstantsDependencyProcessor.java +++ b/java/compiler/impl/src/com/intellij/compiler/make/ChangedConstantsDependencyProcessor.java @@ -27,6 +27,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.search.*; @@ -88,7 +89,7 @@ class ChangedConstantsDependencyProcessor { } } catch (CacheCorruptedException e) { - _ex[0] = e; + _ex[0] = e; } catch (ProcessCanceledException e) { // supressed deliberately @@ -100,7 +101,7 @@ class ChangedConstantsDependencyProcessor { } } - private void processFieldRemoved(FieldInfo info, PsiClass aClass) throws CacheCorruptedException { + private void processFieldRemoved(FieldInfo info, final PsiClass aClass) throws CacheCorruptedException { if (info.isPrivate()) { return; // optimization: don't need to search, cause may be used only in this class } @@ -118,41 +119,54 @@ class ChangedConstantsDependencyProcessor { } final PsiSearchHelper psiSearchHelper = PsiManager.getInstance(myProject).getSearchHelper(); + final Ref exRef = new Ref(null); final long analysisStart = System.currentTimeMillis(); - boolean skipResolve = mySkipExpressionResolve; - - PsiIdentifier[] identifiers = findIdentifiers(psiSearchHelper, myDependencyCache.resolve(info.getName()), searchScope, UsageSearchContext.IN_CODE); - for (PsiIdentifier identifier : identifiers) { - PsiElement parent = identifier.getParent(); - if (parent instanceof PsiReferenceExpression) { - PsiReferenceExpression refExpr = (PsiReferenceExpression)parent; - PsiReference reference = refExpr.getReference(); - skipResolve = skipResolve || (System.currentTimeMillis() - analysisStart) > ANALYSIS_DURATION_THRESHOLD_MILLIS; - if (skipResolve || reference == null || reference.resolve() == null) { - PsiClass ownerClass = getOwnerClass(refExpr); - if (ownerClass != null && !ownerClass.equals(aClass)) { - int qualifiedName = myDependencyCache.getSymbolTable().getId(ownerClass.getQualifiedName()); - // should force marking of the class no matter was it compiled or not - // This will ensure the class was recompiled _after_ all the constants get their new values - if (myDependencyCache.markClass(qualifiedName, true)) { - if (LOG.isDebugEnabled()) { - LOG.debug("Mark dependent class " + myDependencyCache.resolve(qualifiedName) + - "; reason: some constants were removed from " + myDependencyCache.resolve(myQName)); + + processIdentifiers(psiSearchHelper, new PsiElementProcessor() { + private boolean skipResolve = mySkipExpressionResolve; + @Override + public boolean execute(PsiIdentifier identifier) { + try { + final PsiElement parent = identifier.getParent(); + if (parent instanceof PsiReferenceExpression) { + PsiReferenceExpression refExpr = (PsiReferenceExpression)parent; + PsiReference reference = refExpr.getReference(); + skipResolve = skipResolve || (System.currentTimeMillis() - analysisStart) > ANALYSIS_DURATION_THRESHOLD_MILLIS; + if (skipResolve || reference == null || reference.resolve() == null) { + final PsiClass ownerClass = getOwnerClass(refExpr); + if (ownerClass != null && !ownerClass.equals(aClass)) { + final String _qName = ownerClass.getQualifiedName(); + if (_qName != null) { + int qualifiedName = myDependencyCache.getSymbolTable().getId(_qName); + // should force marking of the class no matter was it compiled or not + // This will ensure the class was recompiled _after_ all the constants get their new values + if (myDependencyCache.markClass(qualifiedName, true)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Mark dependent class " + myDependencyCache.resolve(qualifiedName) + "; reason: some constants were removed from " + myDependencyCache.resolve(myQName)); + } + } + } + else { + LOG.warn("Class with null qualified name was not expected here: " + ownerClass); + } } } } + return true; + } + catch (CacheCorruptedException e) { + exRef.set(e); + return false; } } + }, myDependencyCache.resolve(info.getName()), searchScope, UsageSearchContext.IN_CODE); + + final CacheCorruptedException cacheCorruptedException = exRef.get(); + if (cacheCorruptedException != null) { + throw cacheCorruptedException; } } - @NotNull - private static PsiIdentifier[] findIdentifiers(PsiSearchHelper helper, @NotNull String identifier, @NotNull SearchScope searchScope, short searchContext) { - PsiElementProcessor.CollectElements processor = new PsiElementProcessor.CollectElements(); - processIdentifiers(helper, processor, identifier, searchScope, searchContext); - return processor.toArray(PsiIdentifier.EMPTY_ARRAY); - } - private static boolean processIdentifiers(PsiSearchHelper helper, @NotNull final PsiElementProcessor processor, @NotNull final String identifier, @@ -196,7 +210,7 @@ class ChangedConstantsDependencyProcessor { if (myDependencyCache.markClass(qualifiedName, true)) { if (LOG.isDebugEnabled()) { LOG.debug("Marked dependent class " + myDependencyCache.resolve(qualifiedName) + "; reason: constants changed in " + - myDependencyCache.resolve(myQName)); + myDependencyCache.resolve(myQName)); } } } diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.java index 5be9eb25f1a3..fab2d0833a6b 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.java @@ -17,6 +17,7 @@ package com.intellij.packaging.impl.artifacts; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ui.configuration.ModulesAlphaComparator; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.io.FileUtil; @@ -32,6 +33,7 @@ import javax.swing.event.DocumentEvent; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.Arrays; /** * @author nik @@ -74,7 +76,8 @@ public class JarArtifactFromModulesDialog extends DialogWrapper { updateManifestDirField(); myManifestDirField.addBrowseFolderListener(null, null, project, ManifestFileUtil.createDescriptorForManifestDirectory()); - final Module[] modules = context.getModulesProvider().getModules(); + final Module[] modules = context.getModulesProvider().getModules().clone(); + Arrays.sort(modules, ModulesAlphaComparator.INSTANCE); if (modules.length > 1) { myModuleComboBox.addItem(null); } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesAlphaComparator.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesAlphaComparator.java index b3bb01f50a50..9bef5a71428a 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesAlphaComparator.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesAlphaComparator.java @@ -25,6 +25,8 @@ import java.util.Comparator; * @author 2003 */ public class ModulesAlphaComparator implements Comparator{ + public static ModulesAlphaComparator INSTANCE = new ModulesAlphaComparator(); + public int compare(Module module1, Module module2) { final String name1 = module1.getName(); final String name2 = module2.getName(); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java index daf020a0615e..d36cabf4eb0d 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java @@ -73,10 +73,8 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change private final ProjectConfigurable myProjectConfigurable; private final List myModuleEditors = new ArrayList(); private final Comparator myModuleEditorComparator = new Comparator() { - final ModulesAlphaComparator myModulesComparator = new ModulesAlphaComparator(); - public int compare(ModuleEditor editor1, ModuleEditor editor2) { - return myModulesComparator.compare(editor1.getModule(), editor2.getModule()); + return ModulesAlphaComparator.INSTANCE.compare(editor1.getModule(), editor2.getModule()); } @SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"}) diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java index dfbaa0d5ce4d..a7a23e18f039 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java @@ -489,7 +489,8 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { Messages.showMessageDialog(ClasspathPanelImpl.this, ProjectBundle.message("message.no.module.dependency.candidates"), getTitle(), Messages.getInformationIcon()); return null; } - return new ModuleChooser(chooseItems, ProjectBundle.message("classpath.chooser.title.add.module.dependency")); + return new ModuleChooser(chooseItems, ProjectBundle.message("classpath.chooser.title.add.module.dependency"), + ProjectBundle.message("classpath.chooser.description.add.module.dependency")); } } ); @@ -669,8 +670,8 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { } private class ModuleChooser extends ChooseModulesDialog implements ClasspathElementChooser { - public ModuleChooser(final List items, final String title) { - super(ClasspathPanelImpl.this, items, title); + public ModuleChooser(final List items, final String title, String description) { + super(ClasspathPanelImpl.this, items, title, description); } public void doChoose() { diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ChooseModulesDialog.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ChooseModulesDialog.java index e876f5588a5f..013628bc233a 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ChooseModulesDialog.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ChooseModulesDialog.java @@ -25,6 +25,7 @@ package com.intellij.openapi.roots.ui.configuration.libraryEditor; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.ide.util.ChooseElementsDialog; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -36,6 +37,10 @@ public class ChooseModulesDialog extends ChooseElementsDialog { super(parent, items, title, null, true); } + public ChooseModulesDialog(Component parent, List items, String title, @Nullable String description) { + super(parent, items, title, description, true); + } + public ChooseModulesDialog(final Project project, final List items, final String title, final String description) { super(project, items, title, description, true); } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/DefaultInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/DefaultInsertHandler.java index 6949e1cc1bb1..f8d6812dde2a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/DefaultInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/DefaultInsertHandler.java @@ -210,7 +210,6 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone case '<': case '>': case '\"': - case '[': return TailType.createSimpleTailType(completionChar); } final TailType attr = item.getTailType(); return attr == TailType.UNKNOWN ? TailType.NONE : attr; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaAwareCompletionData.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaAwareCompletionData.java index ae8c9070c875..4fa3bb4f4eb8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaAwareCompletionData.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaAwareCompletionData.java @@ -87,13 +87,15 @@ public class JavaAwareCompletionData extends CompletionData{ ret.setInsertHandler(new InsertHandler() { @Override public void handleInsert(InsertionContext context, LookupElement item) { + if (context.shouldAddCompletionChar()) { + return; + } TailType type = analyzeItem(item.getObject(), context.getFile().findElementAt(context.getStartOffset())); if (type == TailType.NONE) { type = tailType; } //new DefaultInsertHandler().handleInsert(context, item); if (type != TailType.NONE) { - context.setAddCompletionChar(false); type.processTail(context.getEditor(), context.getTailOffset()); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java index 6f6d83d35ced..769476ab91d4 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java @@ -41,28 +41,31 @@ public class JavaCharFilter extends CharFilter { public Result acceptChar(char c, final int prefixLength, final Lookup lookup) { if (!lookup.isCompletion()) return null; + if (!(lookup.getPsiFile() instanceof PsiJavaFile)) { + return null; + } + + LookupElement item = lookup.getCurrentItem(); + if (item == null) return null; + if (c == '!') { - if (lookup.getPsiFile() instanceof PsiJavaFile) { - final LookupElement item = lookup.getCurrentItem(); - if (item == null) return null; - - final Object o = item.getObject(); - if (o instanceof PsiVariable) { - if (PsiType.BOOLEAN.isAssignableFrom(((PsiVariable)o).getType())) return Result.SELECT_ITEM_AND_FINISH_LOOKUP; - } - if (o instanceof PsiMethod) { - final PsiType type = ((PsiMethod)o).getReturnType(); - if (type != null && PsiType.BOOLEAN.isAssignableFrom(type)) return Result.SELECT_ITEM_AND_FINISH_LOOKUP; - } - - return null; + final Object o = item.getObject(); + if (o instanceof PsiVariable) { + if (PsiType.BOOLEAN.isAssignableFrom(((PsiVariable)o).getType())) return Result.SELECT_ITEM_AND_FINISH_LOOKUP; } + if (o instanceof PsiMethod) { + final PsiType type = ((PsiMethod)o).getReturnType(); + if (type != null && PsiType.BOOLEAN.isAssignableFrom(type)) return Result.SELECT_ITEM_AND_FINISH_LOOKUP; + } + + return null; } if (c == '.' && isWithinLiteral(lookup)) return Result.ADD_TO_PREFIX; + if (c == '[') return CharFilter.Result.SELECT_ITEM_AND_FINISH_LOOKUP; + if (c == '<' && item.getObject() instanceof PsiClass) return Result.SELECT_ITEM_AND_FINISH_LOOKUP; if (c == '#' && PsiTreeUtil.getParentOfType(lookup.getPsiElement(), PsiDocComment.class) != null) { - final LookupElement item = lookup.getCurrentItem(); - if (item != null && item.getObject() instanceof PsiClass) { + if (item.getObject() instanceof PsiClass) { return Result.SELECT_ITEM_AND_FINISH_LOOKUP; } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java index cc3d3fd2178f..c299e311aa80 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java @@ -17,6 +17,7 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.ExpectedTypesProvider; +import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.lang.LangBundle; import com.intellij.lang.StdLanguages; import com.intellij.openapi.actionSystem.IdeActions; @@ -58,45 +59,10 @@ public class JavaClassNameCompletionContributor extends CompletionContributor { final CompletionResultSet result = JavaCompletionSorting.addJavaSorting(parameters, _result); - final PsiElement insertedElement = parameters.getPosition(); - - final ElementFilter filter = - or(JavaSmartCompletionContributor.AFTER_THROW_NEW, - JavaCompletionContributor.INSIDE_METHOD_THROWS_CLAUSE, - JavaCompletionContributor.IN_CATCH_TYPE).accepts(insertedElement) ? new AssignableFromFilter(CommonClassNames.JAVA_LANG_THROWABLE) : - IN_TYPE_PARAMETER.accepts(insertedElement) ? new ExcludeDeclaredFilter(new ClassFilter(PsiTypeParameter.class)) : - TrueFilter.INSTANCE; - - - final boolean inJavaContext = parameters.getPosition() instanceof PsiIdentifier; - if (AFTER_NEW.accepts(insertedElement)) { - final PsiExpression expr = PsiTreeUtil.getContextOfType(insertedElement, PsiExpression.class, true); - for (final ExpectedTypeInfo info : ExpectedTypesProvider.getExpectedTypes(expr, true)) { - final PsiType type = info.getType(); - final PsiClass psiClass = PsiUtil.resolveClassInType(type); - if (psiClass != null) { - result.addElement(createClassLookupItem(psiClass, inJavaContext)); - } - final PsiType defaultType = info.getDefaultType(); - if (!defaultType.equals(type)) { - final PsiClass defClass = PsiUtil.resolveClassInType(defaultType); - if (defClass != null) { - result.addElement(createClassLookupItem(defClass, inJavaContext)); - } - } - } - } - - final boolean lookingForAnnotations = PsiJavaPatterns.psiElement().afterLeaf("@").accepts(insertedElement); - - AllClassesGetter.processJavaClasses(parameters, result.getPrefixMatcher(), parameters.getInvocationCount() <= 1, new Consumer() { + addAllClasses(parameters, result, new Consumer() { @Override - public void consume(PsiClass psiClass) { - if (lookingForAnnotations && !psiClass.isAnnotationType()) return; - - if (filter.isAcceptable(psiClass, insertedElement)) { - result.addElement(createClassLookupItem(psiClass, inJavaContext)); - } + public void consume(LookupElement element) { + _result.addElement(element); } }); } @@ -104,6 +70,51 @@ public class JavaClassNameCompletionContributor extends CompletionContributor { } + public static void addAllClasses(CompletionParameters parameters, final CompletionResultSet result, @NotNull final Consumer consumer) { + final PsiElement insertedElement = parameters.getPosition(); + + final ElementFilter filter = + or(JavaSmartCompletionContributor.AFTER_THROW_NEW, + JavaCompletionContributor.INSIDE_METHOD_THROWS_CLAUSE, + JavaCompletionContributor.IN_CATCH_TYPE).accepts(insertedElement) ? new AssignableFromFilter(CommonClassNames.JAVA_LANG_THROWABLE) : + IN_TYPE_PARAMETER.accepts(insertedElement) ? new ExcludeDeclaredFilter(new ClassFilter(PsiTypeParameter.class)) : + TrueFilter.INSTANCE; + + + final boolean inJavaContext = parameters.getPosition() instanceof PsiIdentifier; + if (AFTER_NEW.accepts(insertedElement)) { + final PsiExpression expr = PsiTreeUtil.getContextOfType(insertedElement, PsiExpression.class, true); + for (final ExpectedTypeInfo info : ExpectedTypesProvider.getExpectedTypes(expr, true)) { + final PsiType type = info.getType(); + final PsiClass psiClass = PsiUtil.resolveClassInType(type); + if (psiClass != null) { + consumer.consume(createClassLookupItem(psiClass, inJavaContext)); + } + final PsiType defaultType = info.getDefaultType(); + if (!defaultType.equals(type)) { + final PsiClass defClass = PsiUtil.resolveClassInType(defaultType); + if (defClass != null) { + consumer.consume(createClassLookupItem(defClass, inJavaContext)); + } + } + } + } + + final boolean lookingForAnnotations = PsiJavaPatterns.psiElement().afterLeaf("@").accepts(insertedElement); + + AllClassesGetter + .processJavaClasses(parameters, result.getPrefixMatcher(), parameters.getInvocationCount() <= 1, new Consumer() { + @Override + public void consume(PsiClass psiClass) { + if (lookingForAnnotations && !psiClass.isAnnotationType()) return; + + if (filter.isAcceptable(psiClass, insertedElement)) { + consumer.consume(createClassLookupItem(psiClass, inJavaContext)); + } + } + }); + } + public static JavaPsiClassReferenceElement createClassLookupItem(final PsiClass psiClass, final boolean inJavaContext) { return AllClassesGetter.createLookupItem(psiClass, inJavaContext ? JavaClassNameInsertHandler.JAVA_CLASS_INSERT_HANDLER : AllClassesGetter.TRY_SHORTENING); } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java index c42019456461..4c7c656b3b08 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java @@ -44,10 +44,6 @@ class JavaClassNameInsertHandler implements InsertHandler() { - @Override - public void consume(LookupElement lookupElement) { - if (!inheritors.alreadyProcessed(lookupElement)) { - result.addElement(lookupElement); - } + JavaClassNameCompletionContributor.addAllClasses(parameters, result, new Consumer() { + @Override + public void consume(LookupElement element) { + if (!inheritors.alreadyProcessed(element)) { + result.addElement(element); } - }); + } + }); } } @@ -315,6 +318,8 @@ public class JavaCompletionContributor extends CompletionContributor { return false; } + if (NameUtil.useMinusculeHumpMatcher) return true; + final String s = result.getPrefixMatcher().getPrefix(); if (StringUtil.isEmpty(s) || !Character.isUpperCase(s.charAt(0))) return false; return true; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java index 77ce85355add..3499436a3504 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java @@ -116,6 +116,7 @@ public class JavaCompletionSorting { @Override public Comparable weigh(@NotNull LookupElement element) { final Object o = element.getObject(); + if (o instanceof PsiKeyword) return -3; if (!(o instanceof PsiMember)) return 0; if (((PsiMember)o).hasModifierProperty(PsiModifier.STATIC)) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index a61ec6508300..5bfaa05fdb5b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -842,8 +842,9 @@ public class JavaCompletionUtil { final boolean hasTail = tailType != TailType.NONE && tailType != TailType.UNKNOWN; final boolean smart = completionChar == Lookup.COMPLETE_STATEMENT_SELECT_CHAR; - final boolean addCompletionChar = context.shouldAddCompletionChar(); - context.setAddCompletionChar(false); + if (completionChar == '(' || completionChar == '.' || completionChar == ',' || completionChar == ';') { + context.setAddCompletionChar(false); + } final boolean needRightParenth = forceClosingParenthesis || !smart && (CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET || hasTail); if (hasTail) { @@ -863,7 +864,7 @@ public class JavaCompletionUtil { AutoPopupController.getInstance(file.getProject()).autoPopupParameterInfo(editor, overloadsMatter ? null : (PsiElement)item.getObject()); } - if (smart || needRightParenth && addCompletionChar) { + if (smart || needRightParenth) { TailType toInsert = tailType; LookupItem lookupItem = item.as(LookupItem.CLASS_CONDITION_KEY); if (lookupItem == null || lookupItem.getAttribute(LookupItem.TAIL_TYPE_ATTR) != TailType.UNKNOWN) { @@ -877,7 +878,7 @@ public class JavaCompletionUtil { } toInsert.processTail(editor, context.getTailOffset()); - if (context.getCompletionChar() == '.') { + if (completionChar == '.') { AutoPopupController.getInstance(file.getProject()).autoPopupMemberLookup(context.getEditor(), null); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java index e75b14747528..eaa74241a230 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java @@ -123,6 +123,7 @@ public class JavaMethodCallElement extends LookupItem implements Type final PsiType type = method.getReturnType(); if (context.getCompletionChar() == '!' && type != null && PsiType.BOOLEAN.isAssignableFrom(type)) { + context.setAddCompletionChar(false); context.commitDocument(); final int offset = context.getOffset(refStart); final PsiMethodCallExpression methodCall = PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiMethodCallExpression.class, false); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/SmartCompletionDecorator.java b/java/java-impl/src/com/intellij/codeInsight/completion/SmartCompletionDecorator.java index ef32d2520c77..9bd06caa047a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/SmartCompletionDecorator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/SmartCompletionDecorator.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.TailType; +import com.intellij.codeInsight.lookup.Lookup; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupItem; import com.intellij.codeInsight.lookup.TailTypeDecorator; @@ -52,10 +53,12 @@ public class SmartCompletionDecorator extends TailTypeDecorator { } protected TailType computeTailType(InsertionContext context) { - final TailType defType = LookupItem.getDefaultTailType(context.getCompletionChar()); - if (defType != null) { - context.setAddCompletionChar(false); - return defType; + if (context.getCompletionChar() == Lookup.COMPLETE_STATEMENT_SELECT_CHAR) { + return TailType.SMART_COMPLETION; + } + + if (LookupItem.getDefaultTailType(context.getCompletionChar()) != null) { + return null; } LookupElement delegate = getDelegate(); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaHighlightInfoTypes.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaHighlightInfoTypes.java new file mode 100644 index 000000000000..969fb93946c0 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaHighlightInfoTypes.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * 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.intellij.codeInsight.daemon.impl; + +import com.intellij.codeInsight.daemon.HighlightDisplayKey; +import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection; +import com.intellij.lang.annotation.HighlightSeverity; +import com.intellij.openapi.editor.SyntaxHighlighterColors; +import com.intellij.openapi.editor.colors.CodeInsightColors; + +/** + * @author anna + * Date: 01-Feb-2008 + */ +public interface JavaHighlightInfoTypes extends HighlightInfoType { + HighlightInfoType UNUSED_IMPORT = new HighlightInfoType.HighlightInfoTypeSeverityByKey( + HighlightDisplayKey.findOrRegister(UnusedImportLocalInspection.SHORT_NAME, UnusedImportLocalInspection.DISPLAY_NAME), + CodeInsightColors.NOT_USED_ELEMENT_ATTRIBUTES); + + HighlightInfoType JAVA_KEYWORD = new HighlightInfoType.HighlightInfoTypeImpl( + HighlightSeverity.INFORMATION, SyntaxHighlighterColors.KEYWORD); +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaHightlightInfoTypes.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaHightlightInfoTypes.java deleted file mode 100644 index 45c6431e64ad..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaHightlightInfoTypes.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * 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. - */ - -/* - * User: anna - * Date: 01-Feb-2008 - */ -package com.intellij.codeInsight.daemon.impl; - -import com.intellij.codeInsight.daemon.HighlightDisplayKey; -import com.intellij.codeInspection.javaDoc.JavaDocReferenceInspection; -import com.intellij.codeInspection.uncheckedWarnings.UncheckedWarningLocalInspection; -import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection; -import com.intellij.openapi.editor.colors.CodeInsightColors; - -public class JavaHightlightInfoTypes { - - public static final HighlightInfoType UNUSED_IMPORT = new HighlightInfoType.HighlightInfoTypeSeverityByKey( - HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME) == null ? - HighlightDisplayKey.register(UnusedImportLocalInspection.SHORT_NAME, UnusedImportLocalInspection.DISPLAY_NAME) : HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME), CodeInsightColors.NOT_USED_ELEMENT_ATTRIBUTES); - public static final HighlightInfoType JAVADOC_WRONG_REF = new HighlightInfoType.HighlightInfoTypeSeverityByKey(HighlightDisplayKey.find( - JavaDocReferenceInspection.SHORT_NAME) == null ? - HighlightDisplayKey.register(JavaDocReferenceInspection.SHORT_NAME, JavaDocReferenceInspection.DISPLAY_NAME) : HighlightDisplayKey.find(JavaDocReferenceInspection.SHORT_NAME), CodeInsightColors.WRONG_REFERENCES_ATTRIBUTES); - public static final HighlightInfoType UNCHECKED_WARNING = new HighlightInfoType.HighlightInfoTypeSeverityByKeyAttrBySeverity(HighlightDisplayKey.find( - UncheckedWarningLocalInspection.SHORT_NAME) == null ? - HighlightDisplayKey.register(UncheckedWarningLocalInspection.SHORT_NAME, UncheckedWarningLocalInspection.DISPLAY_NAME, UncheckedWarningLocalInspection.ID) : HighlightDisplayKey.find(UncheckedWarningLocalInspection.SHORT_NAME)); - - private JavaHightlightInfoTypes() { - } -} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java index 961244c467c6..f55cd69e0f69 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java @@ -674,7 +674,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { } private HighlightInfo registerRedundantImport(PsiImportStatementBase importStatement, HighlightDisplayKey unusedImportKey) { - HighlightInfo info = HighlightInfo.createHighlightInfo(JavaHightlightInfoTypes.UNUSED_IMPORT, importStatement, InspectionsBundle.message("unused.import.statement")); + HighlightInfo info = HighlightInfo.createHighlightInfo(JavaHighlightInfoTypes.UNUSED_IMPORT, importStatement, InspectionsBundle.message("unused.import.statement")); QuickFixAction.registerQuickFixAction(info, new OptimizeImportsFix(), unusedImportKey); QuickFixAction.registerQuickFixAction(info, new EnableOptimizeImportsOnTheFlyFix(), unusedImportKey); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index d81969add235..5d5401bbbac2 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -33,6 +33,7 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.search.searches.SuperMethodsSearch; import com.intellij.psi.util.*; +import com.intellij.util.ArrayUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.HashSet; import gnu.trove.THashMap; @@ -115,11 +116,14 @@ public class GenericsHighlightUtil { if (!typeParameterListOwner.hasTypeParameters()) { return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, referenceElements[0], "Diamond operator is not applicable for non-parameterized types"); } - inferenceResult = ((PsiDiamondType)referenceElements[0].getType()).resolveInferredTypes(); - final String errorMessage = inferenceResult.getErrorMessage(); + final PsiType expectedType = detectExpectedType(referenceParameterList); + if (!(expectedType instanceof PsiClassType && ((PsiClassType)expectedType).isRaw())) { + inferenceResult = ((PsiDiamondType)referenceElements[0].getType()).resolveInferredTypes(); + final String errorMessage = inferenceResult.getErrorMessage(); if (errorMessage != null) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, referenceElements[0], errorMessage); + return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, referenceElements[0], errorMessage); } + } } } @@ -175,6 +179,42 @@ public class GenericsHighlightUtil { return null; } + private static PsiType detectExpectedType(PsiReferenceParameterList referenceParameterList) { + final PsiNewExpression newExpression = PsiTreeUtil.getParentOfType(referenceParameterList, PsiNewExpression.class); + LOG.assertTrue(newExpression != null); + final PsiElement parent = newExpression.getParent(); + PsiType expectedType = null; + if (parent instanceof PsiVariable && newExpression.equals(((PsiVariable)parent).getInitializer())) { + expectedType = ((PsiVariable)parent).getType(); + } + else if (parent instanceof PsiAssignmentExpression && newExpression.equals(((PsiAssignmentExpression)parent).getRExpression())) { + expectedType = ((PsiAssignmentExpression)parent).getLExpression().getType(); + } + else if (parent instanceof PsiReturnStatement) { + PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class); + if (method != null) { + expectedType = method.getReturnType(); + } + } + else if (parent instanceof PsiExpressionList) { + final PsiElement pParent = parent.getParent(); + if (pParent instanceof PsiCallExpression && parent.equals(((PsiCallExpression)pParent).getArgumentList())) { + final PsiMethod method = ((PsiCallExpression)pParent).resolveMethod(); + if (method != null) { + final PsiExpression[] expressions = ((PsiCallExpression)pParent).getArgumentList().getExpressions(); + final int idx = ArrayUtil.find(expressions, newExpression); + if (idx > -1) { + final PsiParameterList parameterList = method.getParameterList(); + if (idx < parameterList.getParametersCount()) { + expectedType = parameterList.getParameters()[idx].getType(); + } + } + } + } + } + return expectedType; + } + @Nullable private static HighlightInfo checkTypeParameterWithinItsBound(final PsiTypeParameter classParameter, final PsiSubstitutor substitutor, diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 7ca8e460bdac..5770530e592f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -533,7 +533,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalVoidType(keyword)); if (PsiTreeUtil.getParentOfType(keyword, PsiDocTagValue.class) != null) { - myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.JAVA_KEYWORD, keyword, null)); + myHolder.add(HighlightInfo.createHighlightInfo(JavaHighlightInfoTypes.JAVA_KEYWORD, keyword, null)); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java index 04543c0dc731..c446d083b469 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java @@ -91,6 +91,7 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction { } private static String formatTypesList(ParameterInfoImpl[] infos, PsiElement context) { + if (infos == null) return null; String result = ""; try { for (ParameterInfoImpl info : infos) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GeneralizeCatchFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GeneralizeCatchFix.java index 33953721c035..78300d1bcf5b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GeneralizeCatchFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GeneralizeCatchFix.java @@ -40,7 +40,7 @@ public class GeneralizeCatchFix implements IntentionAction { @NotNull public String getText() { return QuickFixBundle.message("generalize.catch.text", - HighlightUtil.formatType(myCatchParameter.getType()), + HighlightUtil.formatType(myCatchParameter == null ? null : myCatchParameter.getType()), HighlightUtil.formatType(myUnhandledException)); } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java index 3b9f9633b698..06b80346c053 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java @@ -30,6 +30,7 @@ import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.search.PsiElementProcessorAdapter; import com.intellij.psi.search.searches.OverridingMethodsSearch; import com.intellij.psi.util.PsiFormatUtil; +import com.intellij.psi.util.PsiFormatUtilBase; import com.intellij.psi.util.PsiUtil; import com.intellij.util.VisibilityUtil; import com.intellij.util.IncorrectOperationException; @@ -54,6 +55,7 @@ public class ModifierFix extends IntentionAndQuickFixAction { myShouldHave = shouldHave; myShowContainingClass = showContainingClass; } + public ModifierFix(@NotNull PsiModifierListOwner owner, @Modifier @NotNull String modifier, boolean shouldHave, boolean showContainingClass) { this(owner.getModifierList(), modifier, shouldHave, showContainingClass); if (owner instanceof PsiVariable) { @@ -64,12 +66,12 @@ public class ModifierFix extends IntentionAndQuickFixAction { @NotNull public String getName() { String name = null; - PsiElement parent = myVariable == null ? myModifierList.getParent() : myVariable; + PsiElement parent = myVariable == null ? myModifierList == null ? null : myModifierList.getParent() : myVariable; if (parent instanceof PsiClass) { name = ((PsiClass)parent).getName(); } else { - int options = PsiFormatUtil.SHOW_NAME | (myShowContainingClass ? PsiFormatUtil.SHOW_CONTAINING_CLASS : 0); + int options = PsiFormatUtilBase.SHOW_NAME | (myShowContainingClass ? PsiFormatUtilBase.SHOW_CONTAINING_CLASS : 0); if (parent instanceof PsiMethod) { name = PsiFormatUtil.formatMethod((PsiMethod)parent, PsiSubstitutor.EMPTY, options, 0); } @@ -79,8 +81,9 @@ public class ModifierFix extends IntentionAndQuickFixAction { else if (parent instanceof PsiClassInitializer) { PsiClass containingClass = ((PsiClassInitializer)parent).getContainingClass(); String className = containingClass instanceof PsiAnonymousClass - ? QuickFixBundle.message("anonymous.class.presentation", ((PsiAnonymousClass)containingClass).getBaseClassType().getPresentableText()) - : containingClass.getName(); + ? QuickFixBundle.message("anonymous.class.presentation", + ((PsiAnonymousClass)containingClass).getBaseClassType().getPresentableText()) + : containingClass != null ? containingClass.getName() : "unknown"; name = QuickFixBundle.message("class.initializer.presentation", className); } } @@ -99,7 +102,7 @@ public class ModifierFix extends IntentionAndQuickFixAction { return myModifierList != null && myModifierList.isValid() && myModifierList.getManager().isInProject(myModifierList) && - myModifierList.hasModifierProperty(myModifier) != myShouldHave && + myModifierList.hasExplicitModifier(myModifier) != myShouldHave && (myVariable == null || myVariable.isValid()); } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceAddAllArrayToCollectionFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceAddAllArrayToCollectionFix.java index 96804cdc70dc..009754d48537 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceAddAllArrayToCollectionFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceAddAllArrayToCollectionFix.java @@ -101,15 +101,13 @@ public class ReplaceAddAllArrayToCollectionFix implements IntentionAction { @NonNls private String getCollectionsMethodCall() { final PsiExpression qualifierExpression = myMethodCall.getMethodExpression().getQualifierExpression(); + PsiExpression[] expressions = myMethodCall.getArgumentList().getExpressions(); return "java.util.Collections.addAll(" + (qualifierExpression != null ? qualifierExpression.getText() : "this") + - ", " + - myMethodCall.getArgumentList().getExpressions()[0] - .getText() + - ")"; + ", " + (expressions.length == 0 ? "" : expressions[0].getText()) + ")"; } public boolean startInWriteAction() { return true; } -} \ No newline at end of file +} diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java index cc5d211ae100..cc2a3d8a1a9d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java @@ -35,6 +35,7 @@ import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiShortNamesCache; import com.intellij.psi.util.PsiFormatUtil; +import com.intellij.psi.util.PsiFormatUtilBase; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.proximity.PsiProximityComparator; import com.intellij.ui.popup.list.ListPopupImpl; @@ -62,8 +63,10 @@ public class StaticImportMethodFix implements IntentionAction { @NotNull public String getText() { String text = QuickFixBundle.message("static.import.method.text"); - if (candidates.size() == 1) { - text += " '" + PsiFormatUtil.formatMethod(candidates.get(0), PsiSubstitutor.EMPTY, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_CONTAINING_CLASS | PsiFormatUtil.SHOW_FQ_NAME, 0)+"'"; + if (candidates != null && candidates.size() == 1) { + text += " '" + PsiFormatUtil.formatMethod(candidates.get(0), PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_NAME | + PsiFormatUtilBase.SHOW_CONTAINING_CLASS | + PsiFormatUtilBase.SHOW_FQ_NAME, 0)+"'"; } else { text += "..."; @@ -243,7 +246,7 @@ public class StaticImportMethodFix implements IntentionAction { final PopupListElementRenderer rightArrow = new PopupListElementRenderer(this); @Override protected ListCellRenderer getListElementRenderer() { - return new MethodCellRenderer(true, PsiFormatUtil.SHOW_NAME){ + return new MethodCellRenderer(true, PsiFormatUtilBase.SHOW_NAME){ @Override protected DefaultListCellRenderer getRightCellRenderer() { final DefaultListCellRenderer moduleRenderer = super.getRightCellRenderer(); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java index 56b34711ed8b..ddc5e9fb58db 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java @@ -70,7 +70,6 @@ public class VariableAccessFromInnerClassFix implements IntentionAction { case COPY_TO_FINAL: return QuickFixBundle.message("make.final.copy.to.temp", myVariable.getName()); default: - LOG.error("invalid type "+myFixType); return ""; } Collection vars = getVariablesToFix(); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/WrapExpressionFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/WrapExpressionFix.java index d4c85df105fb..ff3112b69525 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/WrapExpressionFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/WrapExpressionFix.java @@ -56,13 +56,13 @@ public class WrapExpressionFix implements IntentionAction { @NotNull public String getText() { - final PsiMethod wrapper = myExpression.isValid() ? findWrapper(myExpression.getType(), myExpectedType, myPrimitiveExpected) : null; - final String methodPresentation = wrapper != null ? (wrapper.getContainingClass().getName() + "." + wrapper.getName()) : ""; + final PsiMethod wrapper = myExpression.isValid() && myExpectedType != null ? findWrapper(myExpression.getType(), myExpectedType, myPrimitiveExpected) : null; + final String methodPresentation = wrapper != null ? wrapper.getContainingClass().getName() + "." + wrapper.getName() : ""; return QuickFixBundle.message("wrap.expression.using.static.accessor.text", methodPresentation); } @Nullable - private static PsiMethod findWrapper(PsiType type, PsiClassType expectedType, boolean primitiveExpected) { + private static PsiMethod findWrapper(PsiType type, @NotNull PsiClassType expectedType, boolean primitiveExpected) { PsiClass aClass = expectedType.resolve(); if (aClass != null) { PsiType expectedReturnType = expectedType; diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaBackspaceHandler.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaBackspaceHandler.java index 44e4985af417..2f1c8991a779 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaBackspaceHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaBackspaceHandler.java @@ -22,6 +22,7 @@ import com.intellij.psi.JavaTokenType; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiJavaFile; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.PsiUtil; public class JavaBackspaceHandler extends BackspaceHandlerDelegate { @@ -43,30 +44,33 @@ public class JavaBackspaceHandler extends BackspaceHandlerDelegate { char c1 = chars.charAt(offset); if (c == '<' && myToDeleteGt) { if (c1 != '>') return true; - handleLTDeletion(editor, offset); + handleLTDeletion(editor, offset, JavaTokenType.LT, JavaTokenType.GT, JavaTypedHandler.INVALID_INSIDE_REFERENCE); return true; } return false; } - private static void handleLTDeletion(final Editor editor, final int offset) { + public static void handleLTDeletion(final Editor editor, + final int offset, + final IElementType lt, + final IElementType gt, final TokenSet invalidInsideReference) { HighlighterIterator iterator = ((EditorEx)editor).getHighlighter().createIterator(offset); - while (iterator.getStart() > 0 && !JavaTypedHandlerUtil.isTokenInvalidInsideReference(iterator.getTokenType())) { + while (iterator.getStart() > 0 && !invalidInsideReference.contains(iterator.getTokenType())) { iterator.retreat(); } - if (JavaTypedHandlerUtil.isTokenInvalidInsideReference(iterator.getTokenType())) iterator.advance(); + if (invalidInsideReference.contains(iterator.getTokenType())) iterator.advance(); int balance = 0; while (!iterator.atEnd() && balance >= 0) { final IElementType tokenType = iterator.getTokenType(); - if (tokenType == JavaTokenType.LT) { + if (tokenType == lt) { balance++; } - else if (tokenType == JavaTokenType.GT) { + else if (tokenType == gt) { balance--; } - else if (JavaTypedHandlerUtil.isTokenInvalidInsideReference(tokenType)) { + else if (invalidInsideReference.contains(tokenType)) { break; } diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaTypedHandler.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaTypedHandler.java index a99e67f228c3..6237cfd6dbd4 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaTypedHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaTypedHandler.java @@ -34,6 +34,7 @@ import com.intellij.psi.filters.position.SuperParentFilter; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.jsp.JspFile; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.Nullable; @@ -42,6 +43,7 @@ import org.jetbrains.annotations.Nullable; * @author yole */ public class JavaTypedHandler extends TypedHandlerDelegate { + static final TokenSet INVALID_INSIDE_REFERENCE = TokenSet.create(JavaTokenType.SEMICOLON, JavaTokenType.LBRACE, JavaTokenType.RBRACE); private boolean myJavaLTTyped; public Result checkAutoPopup(final char charTyped, final Project project, final Editor editor, final PsiFile file) { @@ -106,7 +108,7 @@ public class JavaTypedHandler extends TypedHandlerDelegate { if (file instanceof PsiJavaFile && !(file instanceof JspFile) && CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET && PsiUtil.isLanguageLevel5OrHigher(file)) { - if (handleJavaGT(editor)) return Result.STOP; + if (handleJavaGT(editor, JavaTokenType.LT, JavaTokenType.GT, INVALID_INSIDE_REFERENCE)) return Result.STOP; } } @@ -144,7 +146,7 @@ public class JavaTypedHandler extends TypedHandlerDelegate { public Result charTyped(final char c, final Project project, final Editor editor, final PsiFile file) { if (myJavaLTTyped) { myJavaLTTyped = false; - handleAfterJavaLT(editor); + handleAfterJavaLT(editor, JavaTokenType.LT, JavaTokenType.GT, INVALID_INSIDE_REFERENCE); return Result.STOP; } return Result.CONTINUE; @@ -170,7 +172,10 @@ public class JavaTypedHandler extends TypedHandlerDelegate { } //need custom handler, since brace matcher cannot be used - private static boolean handleJavaGT(final Editor editor) { + public static boolean handleJavaGT(final Editor editor, + final IElementType lt, + final IElementType gt, + final TokenSet invalidInsideReference) { if (!CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET) return false; int offset = editor.getCaretModel().getOffset(); @@ -178,24 +183,23 @@ public class JavaTypedHandler extends TypedHandlerDelegate { if (offset == editor.getDocument().getTextLength()) return false; HighlighterIterator iterator = ((EditorEx) editor).getHighlighter().createIterator(offset); - if (iterator.getTokenType() != JavaTokenType.GT) return false; - while (!iterator.atEnd() && !JavaTypedHandlerUtil.isTokenInvalidInsideReference(iterator.getTokenType())) { + if (iterator.getTokenType() != gt) return false; + while (!iterator.atEnd() && !invalidInsideReference.contains(iterator.getTokenType())) { iterator.advance(); } - if (iterator.atEnd()) return false; - if (JavaTypedHandlerUtil.isTokenInvalidInsideReference(iterator.getTokenType())) iterator.retreat(); + if (!iterator.atEnd() && invalidInsideReference.contains(iterator.getTokenType())) iterator.retreat(); int balance = 0; while (!iterator.atEnd() && balance >= 0) { final IElementType tokenType = iterator.getTokenType(); - if (tokenType == JavaTokenType.LT) { + if (tokenType == lt) { balance--; } - else if (tokenType == JavaTokenType.GT) { + else if (tokenType == gt) { balance++; } - else if (JavaTypedHandlerUtil.isTokenInvalidInsideReference(tokenType)) { + else if (invalidInsideReference.contains(tokenType)) { break; } @@ -212,27 +216,30 @@ public class JavaTypedHandler extends TypedHandlerDelegate { } //need custom handler, since brace matcher cannot be used - private static void handleAfterJavaLT(final Editor editor) { + public static void handleAfterJavaLT(final Editor editor, + final IElementType lt, + final IElementType gt, + final TokenSet invalidInsideReference) { if (!CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET) return; int offset = editor.getCaretModel().getOffset(); HighlighterIterator iterator = ((EditorEx) editor).getHighlighter().createIterator(offset); - while (iterator.getStart() > 0 && !JavaTypedHandlerUtil.isTokenInvalidInsideReference(iterator.getTokenType())) { + while (iterator.getStart() > 0 && !invalidInsideReference.contains(iterator.getTokenType())) { iterator.retreat(); } - if (JavaTypedHandlerUtil.isTokenInvalidInsideReference(iterator.getTokenType())) iterator.advance(); + if (invalidInsideReference.contains(iterator.getTokenType())) iterator.advance(); int balance = 0; while (!iterator.atEnd() && balance >= 0) { final IElementType tokenType = iterator.getTokenType(); - if (tokenType == JavaTokenType.LT) { + if (tokenType == lt) { balance++; } - else if (tokenType == JavaTokenType.GT) { + else if (tokenType == gt) { balance--; } - else if (JavaTypedHandlerUtil.isTokenInvalidInsideReference(tokenType)) { + else if (invalidInsideReference.contains(tokenType)) { break; } @@ -262,7 +269,11 @@ public class JavaTypedHandler extends TypedHandlerDelegate { if (iterator.getStart() > 0) iterator.retreat(); final IElementType tokenType = iterator.getTokenType(); if (tokenType == JavaTokenType.DOT) return true; - if (tokenType == JavaTokenType.IDENTIFIER && iterator.getEnd() == offset) { + return isClassLikeIdentifier(offset, editor, iterator, JavaTokenType.IDENTIFIER); + } + + public static boolean isClassLikeIdentifier(int offset, Editor editor, HighlighterIterator iterator, final IElementType idType) { + if (iterator.getTokenType() == idType && iterator.getEnd() == offset) { final CharSequence chars = editor.getDocument().getCharsSequence(); final char startChar = chars.charAt(iterator.getStart()); if (!Character.isUpperCase(startChar)) return false; diff --git a/java/java-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java b/java/java-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java index 6cf445dd6a69..45f39ce69bb8 100644 --- a/java/java-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java @@ -18,6 +18,7 @@ package com.intellij.codeInspection; import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.codeInsight.daemon.GroupNames; import com.intellij.codeInsight.intention.HighPriorityAction; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; @@ -26,6 +27,8 @@ import com.intellij.psi.util.TypeConversionUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; +import java.util.List; + /** * User: anna * Date: 1/28/11 @@ -76,13 +79,13 @@ public class ExplicitTypeCanBeDiamondInspection extends BaseJavaLocalInspectionT if (typeElements.length == 1 && typeElements[0].getType() instanceof PsiDiamondType) return; final PsiDiamondType.DiamondInferenceResult inferenceResult = PsiDiamondType.resolveInferredTypes(expression); if (inferenceResult.getErrorMessage() == null) { - final PsiType[] types = inferenceResult.getTypes(); + final List types = inferenceResult.getInferredTypes(); final PsiType[] typeArguments = parameterList.getTypeArguments(); - if (types.length == typeArguments.length) { + if (types.size() == typeArguments.length) { for (int i = 0, typeArgumentsLength = typeArguments.length; i < typeArgumentsLength; i++) { PsiType typeArgument = typeArguments[i]; - if (types[i] instanceof PsiWildcardType) { - final PsiWildcardType wildcardType = (PsiWildcardType)types[i]; + if (types.get(i) instanceof PsiWildcardType) { + final PsiWildcardType wildcardType = (PsiWildcardType)types.get(i); final PsiType bound = wildcardType.getBound(); if (bound != null) { if (wildcardType.isExtends()) { @@ -92,7 +95,7 @@ public class ExplicitTypeCanBeDiamondInspection extends BaseJavaLocalInspectionT } } } - if (!typeArgument.equals(types[i])) { + if (!typeArgument.equals(types.get(i))) { return; } } @@ -109,6 +112,7 @@ public class ExplicitTypeCanBeDiamondInspection extends BaseJavaLocalInspectionT } private static class ReplaceWithDiamondFix implements LocalQuickFix, HighPriorityAction { + public static final Logger LOG = Logger.getInstance("#" + ReplaceWithDiamondFix.class.getName()); @NotNull @Override public String getName() { @@ -126,8 +130,13 @@ public class ExplicitTypeCanBeDiamondInspection extends BaseJavaLocalInspectionT final PsiElement psiElement = descriptor.getPsiElement(); if (psiElement instanceof PsiReferenceParameterList) { if (!CodeInsightUtilBase.prepareFileForWrite(psiElement.getContainingFile())) return; - final PsiTypeElement[] parameterElements = ((PsiReferenceParameterList)psiElement).getTypeParameterElements(); - psiElement.deleteChildRange(parameterElements[0], parameterElements[parameterElements.length - 1]); + final PsiNewExpression expression = + (PsiNewExpression)JavaPsiFacade.getElementFactory(project).createExpressionFromText("new a<>()", psiElement); + final PsiJavaCodeReferenceElement classReference = expression.getClassReference(); + LOG.assertTrue(classReference != null); + final PsiReferenceParameterList parameterList = classReference.getParameterList(); + LOG.assertTrue(parameterList != null); + psiElement.replace(parameterList); } } } diff --git a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocReferenceInspection.java b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocReferenceInspection.java index af46d0c795d8..77b76a3b4f26 100644 --- a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocReferenceInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocReferenceInspection.java @@ -48,12 +48,10 @@ import java.util.*; public class JavaDocReferenceInspection extends BaseLocalInspectionTool { @NonNls public static final String SHORT_NAME = "JavadocReference"; - public static final String DISPLAY_NAME = InspectionsBundle.message("inspection.javadoc.ref.display.name"); - private static ProblemDescriptor createDescriptor(@NotNull PsiElement element, String template, InspectionManager manager, boolean onTheFly) { - return manager.createProblemDescriptor(element, template, onTheFly, (LocalQuickFix [])null, ProblemHighlightType.LIKE_UNKNOWN_SYMBOL); + return manager.createProblemDescriptor(element, template, onTheFly, null, ProblemHighlightType.LIKE_UNKNOWN_SYMBOL); } @Nullable @@ -66,9 +64,14 @@ public class JavaDocReferenceInspection extends BaseLocalInspectionTool { return checkMember(field, manager, isOnTheFly); } + @Nullable + public ProblemDescriptor[] checkClass(@NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) { + return checkMember(aClass, manager, isOnTheFly); + } + @Nullable private ProblemDescriptor[] checkMember(final PsiDocCommentOwner docCommentOwner, final InspectionManager manager, final boolean isOnTheFly) { - ArrayList problems = new ArrayList(); + final ArrayList problems = new ArrayList(); final PsiDocComment docComment = docCommentOwner.getDocComment(); if (docComment == null) return null; @@ -77,26 +80,20 @@ public class JavaDocReferenceInspection extends BaseLocalInspectionTool { for (PsiJavaCodeReferenceElement reference : references) { final List classesToImport = new ImportClassFix(reference).getClassesToImport(); final PsiElement referenceNameElement = reference.getReferenceNameElement(); - problems.add(manager.createProblemDescriptor(referenceNameElement != null ? referenceNameElement : reference, cannotResolveSymbolMessage("" + reference.getText() + ""), - !isOnTheFly || classesToImport.isEmpty() ? null : new AddImportFix(classesToImport), ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, - isOnTheFly)); + problems.add(manager.createProblemDescriptor(referenceNameElement != null ? referenceNameElement : reference, + cannotResolveSymbolMessage("" + reference.getText() + ""), + !isOnTheFly || classesToImport.isEmpty() ? null : new AddImportFix(classesToImport), + ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, isOnTheFly)); } - return problems.isEmpty() - ? null - : problems.toArray(new ProblemDescriptor[problems.size()]); + return problems.isEmpty() ? null : problems.toArray(new ProblemDescriptor[problems.size()]); } - @Nullable - public ProblemDescriptor[] checkClass(@NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) { - return checkMember(aClass, manager, isOnTheFly); - } - - private PsiElementVisitor getVisitor(final Set references, final PsiElement context, final ArrayList problems, - final InspectionManager manager, final boolean onTheFly) { + final InspectionManager manager, + final boolean onTheFly) { return new JavaElementVisitor() { @Override public void visitReferenceExpression(PsiReferenceExpression expression) { visitElement(expression); @@ -137,58 +134,56 @@ public class JavaDocReferenceInspection extends BaseLocalInspectionTool { }; } - public static void visitRefInDocTag(final PsiDocTag tag, final JavadocManager manager, final PsiElement context, ArrayList problems, - InspectionManager inspectionManager, - boolean onTheFly) { + public static void visitRefInDocTag(final PsiDocTag tag, + final JavadocManager manager, + final PsiElement context, + final ArrayList problems, + final InspectionManager inspectionManager, + final boolean onTheFly) { final String tagName = tag.getName(); - PsiDocTagValue value = tag.getValueElement(); + final PsiDocTagValue value = tag.getValueElement(); if (value == null) return; final JavadocTagInfo info = manager.getTagInfo(tagName); if (info != null && !info.isValidInContext(context)) return; - String message = info == null || !info.isInline() ? null : info.checkTagValue(value); + final String message = info == null || !info.isInline() ? null : info.checkTagValue(value); if (message != null){ problems.add(createDescriptor(value, message, inspectionManager, onTheFly)); } + final PsiReference reference = value.getReference(); - if (reference != null) { - PsiElement element = reference.resolve(); - if (element == null) { - final int textOffset = value.getTextOffset(); + if (reference == null) return; + final PsiElement element = reference.resolve(); + if (element != null) return; + final int textOffset = value.getTextOffset(); + if (textOffset == value.getTextRange().getEndOffset()) return; + final PsiDocTagValue valueElement = tag.getValueElement(); + if (valueElement == null) return; - if (textOffset != value.getTextRange().getEndOffset()) { - final PsiDocTagValue valueElement = tag.getValueElement(); - if (valueElement != null) { - final CharSequence paramName = - value.getContainingFile().getViewProvider().getContents().subSequence(textOffset, value.getTextRange().getEndOffset()); - @NonNls String params = "" + paramName + ""; - - final List fixes = new ArrayList(); - if (onTheFly && "param".equals(tagName)) { - final PsiDocCommentOwner commentOwner = PsiTreeUtil.getParentOfType(tag, PsiDocCommentOwner.class); - if (commentOwner instanceof PsiMethod) { - final PsiMethod method = (PsiMethod)commentOwner; - final PsiParameter[] parameters = method.getParameterList().getParameters(); - final PsiDocTag[] tags = tag.getContainingComment().getTags(); - final Set unboundParams = new HashSet(); - for (PsiParameter parameter : parameters) { - if (!JavaDocLocalInspection.isFound(tags, parameter)) { - unboundParams.add(parameter.getName()); - } - } - if (!unboundParams.isEmpty()) { - fixes.add(new RenameReferenceQuickFix(unboundParams)); - } - } - } - fixes.add(new RemoveTagFix(tagName, paramName, tag)); - - problems.add(inspectionManager.createProblemDescriptor(valueElement, reference.getRangeInElement(), cannotResolveSymbolMessage(params), - ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, onTheFly, - fixes.toArray(new LocalQuickFix[fixes.size()]))); + final CharSequence paramName = value.getContainingFile().getViewProvider().getContents().subSequence(textOffset, value.getTextRange().getEndOffset()); + final String params = "" + paramName + ""; + final List fixes = new ArrayList(); + if (onTheFly && "param".equals(tagName)) { + final PsiDocCommentOwner commentOwner = PsiTreeUtil.getParentOfType(tag, PsiDocCommentOwner.class); + if (commentOwner instanceof PsiMethod) { + final PsiMethod method = (PsiMethod)commentOwner; + final PsiParameter[] parameters = method.getParameterList().getParameters(); + final PsiDocTag[] tags = tag.getContainingComment().getTags(); + final Set unboundParams = new HashSet(); + for (PsiParameter parameter : parameters) { + if (!JavaDocLocalInspection.isFound(tags, parameter)) { + unboundParams.add(parameter.getName()); } } + if (!unboundParams.isEmpty()) { + fixes.add(new RenameReferenceQuickFix(unboundParams)); + } } } + fixes.add(new RemoveTagFix(tagName, paramName, tag)); + + problems.add(inspectionManager.createProblemDescriptor(valueElement, reference.getRangeInElement(), cannotResolveSymbolMessage(params), + ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, onTheFly, + fixes.toArray(new LocalQuickFix[fixes.size()]))); } private static String cannotResolveSymbolMessage(String params) { @@ -197,7 +192,7 @@ public class JavaDocReferenceInspection extends BaseLocalInspectionTool { @NotNull public String getDisplayName() { - return DISPLAY_NAME; + return InspectionsBundle.message("inspection.javadoc.ref.display.name"); } @NotNull diff --git a/java/java-impl/src/com/intellij/psi/controlFlow/LocalsControlFlowPolicy.java b/java/java-impl/src/com/intellij/psi/controlFlow/LocalsControlFlowPolicy.java index 8c951540a383..6b036bc933d1 100644 --- a/java/java-impl/src/com/intellij/psi/controlFlow/LocalsControlFlowPolicy.java +++ b/java/java-impl/src/com/intellij/psi/controlFlow/LocalsControlFlowPolicy.java @@ -16,6 +16,7 @@ package com.intellij.psi.controlFlow; import com.intellij.psi.*; +import org.jetbrains.annotations.Nullable; public class LocalsControlFlowPolicy implements ControlFlowPolicy { private final PsiElement myCodeFragment; @@ -36,6 +37,7 @@ public class LocalsControlFlowPolicy implements ControlFlowPolicy { } } + @Nullable private PsiVariable checkCodeFragment(PsiElement refElement) { PsiElement codeFragement; if (refElement instanceof PsiParameter @@ -45,6 +47,7 @@ public class LocalsControlFlowPolicy implements ControlFlowPolicy { else{ codeFragement = ControlFlowUtil.findCodeFragment(refElement); } + if (codeFragement == null) return null; if (myCodeFragment.getContainingFile() == codeFragement.getContainingFile() && //In order for jsp includes to work !myCodeFragment.equals(codeFragement)) return null; return (PsiVariable)refElement; diff --git a/java/java-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java b/java/java-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java index b528198bb493..e4416a428200 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java @@ -15,8 +15,8 @@ */ package com.intellij.psi.impl.source.javadoc; +import com.google.common.collect.Lists; import com.intellij.lang.ASTNode; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.impl.source.Constants; @@ -29,9 +29,9 @@ import com.intellij.psi.javadoc.PsiDocTagValue; import com.intellij.psi.scope.ElementClassFilter; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.scope.processor.FilterScopeProcessor; +import com.intellij.psi.util.MethodSignature; +import com.intellij.psi.util.MethodSignatureUtil; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtil; -import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.CharTable; import com.intellij.util.IncorrectOperationException; @@ -85,8 +85,6 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo @Nullable private PsiReference getReferenceInScope(PsiElement scope, PsiElement element) { final String name = element.getText(); - - final String[] signature = getSignature(); if (signature == null) { @@ -97,49 +95,44 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo } } - final PsiMethod[] methods = getAllMethods(scope, this); - - nextMethod: - for (PsiMethod method : methods) { - if (!method.getName().equals(name)) continue; - - if (signature == null) { - return new MyReference(method); - } - else { - final PsiParameter[] parameters = method.getParameterList().getParameters(); - if (parameters.length != signature.length) continue; - for (int j = 0; j < parameters.length; j++) { - PsiParameter parameter = parameters[j]; - PsiType type1 = TypeConversionUtil.erasure(parameter.getType()); - String type2 = signature[j]; - if (!Comparing.strEqual(type1.getPresentableText(), type2) && !Comparing.strEqual(type1.getCanonicalText(), type2)) { - String shortName = ""; - PsiClass psiClass = PsiUtil.resolveClassInType(type1); - while (psiClass != null) { - shortName = psiClass.getName() + (shortName.length() > 0 ? "." + shortName : ""); - psiClass = PsiTreeUtil.getParentOfType(psiClass, PsiClass.class); - } - if (!Comparing.strEqual(shortName, type2)) { - continue nextMethod; - } - } + final MethodSignature methodSignature; + if (signature != null) { + final List types = Lists.newArrayListWithCapacity(signature.length); + final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(element.getProject()).getElementFactory(); + for (String s : signature) { + try { + types.add(elementFactory.createTypeFromText(s, scope)); + } + catch (IncorrectOperationException e) { + types.add(PsiType.NULL); } - - return new MyReference(method) { - @NotNull - public PsiElement[] getVariants() { - final List lst = new ArrayList(); - for (PsiMethod method : methods) { - if (name.equals(method.getName())) { - lst.add(method); - } - } - return lst.toArray(new PsiMethod[lst.size()]); - } - }; } + methodSignature = MethodSignatureUtil.createMethodSignature(name, types.toArray(new PsiType[types.size()]), + PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); } + else { + methodSignature = MethodSignatureUtil.createMethodSignature(name, PsiType.EMPTY_ARRAY, + PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); + } + + final PsiMethod[] methods = getAllMethods(scope, this); + for (PsiMethod method : methods) { + if (!method.getName().equals(name) || + !MethodSignatureUtil.areSignaturesErasureEqual(methodSignature, method.getSignature(PsiSubstitutor.EMPTY))) continue; + return new MyReference(method) { + @NotNull + public PsiElement[] getVariants() { + final List lst = new ArrayList(); + for (PsiMethod method : methods) { + if (name.equals(method.getName())) { + lst.add(method); + } + } + return lst.toArray(new PsiMethod[lst.size()]); + } + }; + } + return null; } @@ -157,34 +150,30 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo public int getTextOffset() { final PsiElement element = getNameElement(); - - if (element != null) { - return element.getTextRange().getStartOffset(); - } - - return getTextRange().getEndOffset(); + return element != null ? element.getTextRange().getStartOffset() : getTextRange().getEndOffset(); } + @Nullable public PsiElement getNameElement() { final ASTNode sharp = findChildByType(DOC_TAG_VALUE_SHARP_TOKEN); - if (sharp == null) return null; - return SourceTreeToPsiMap.treeElementToPsi(sharp).getNextSibling(); + return sharp != null ? SourceTreeToPsiMap.treeToPsiNotNull(sharp).getNextSibling() : null; } - + @Nullable public String[] getSignature() { - PsiElement element = getNameElement().getNextSibling(); + PsiElement element = getNameElement(); + if (element == null) return null; + element = element.getNextSibling(); while (element != null && !(element instanceof PsiDocTagValue)) { element = element.getNextSibling(); } - if (element == null) return null; List types = new ArrayList(); for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) { if (child.getNode().getElementType() == DOC_TYPE_HOLDER) { - final String[] typeStrings = child.getText().split("[, ]"); //avoid param types list parsing hmm mathod(paramType1, paramType2, ...) -> typeElement1, identifier2, ... + final String[] typeStrings = child.getText().split("[, ]"); //avoid param types list parsing hmm method(paramType1, paramType2, ...) -> typeElement1, identifier2, ... if (typeStrings != null) { for (String type : typeStrings) { if (type.length() > 0) { @@ -224,14 +213,14 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo } public class MyReference implements PsiJavaReference { - private final PsiElement myReferencee; + private final PsiElement myReferredElement; - public MyReference(PsiElement referencee) { - myReferencee = referencee; + public MyReference(PsiElement referredElement) { + myReferredElement = referredElement; } public PsiElement resolve() { - return myReferencee; + return myReferredElement; } public void processVariants(PsiScopeProcessor processor) { @@ -244,12 +233,14 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo @NotNull public JavaResolveResult advancedResolve(boolean incompleteCode) { - return myReferencee == null ? JavaResolveResult.EMPTY : new CandidateInfo(myReferencee, PsiSubstitutor.EMPTY); + return myReferredElement == null ? JavaResolveResult.EMPTY + : new CandidateInfo(myReferredElement, PsiSubstitutor.EMPTY); } @NotNull public JavaResolveResult[] multiResolve(boolean incompleteCode) { - return myReferencee == null ? JavaResolveResult.EMPTY_ARRAY : new JavaResolveResult[]{new CandidateInfo(myReferencee, PsiSubstitutor.EMPTY)}; + return myReferredElement == null ? JavaResolveResult.EMPTY_ARRAY + : new JavaResolveResult[]{new CandidateInfo(myReferredElement, PsiSubstitutor.EMPTY)}; } @NotNull @@ -269,21 +260,26 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo @NotNull public String getCanonicalText() { - return getNameElement().getText(); + final PsiElement nameElement = getNameElement(); + assert nameElement != null; + return nameElement.getText(); } public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { - final PsiElement element = getNameElement(); - final ASTNode treeElement = SourceTreeToPsiMap.psiElementToTree(element); + final PsiElement nameElement = getNameElement(); + assert nameElement != null; + final ASTNode treeElement = SourceTreeToPsiMap.psiToTreeNotNull(nameElement); final CharTable charTableByTree = SharedImplUtil.findCharTableByTree(treeElement); - LeafElement newToken = Factory.createSingleLeafElement(DOC_TAG_VALUE_TOKEN, newElementName, charTableByTree, getManager()); - ((CompositeElement)treeElement.getTreeParent()).replaceChildInternal(SourceTreeToPsiMap.psiElementToTree(element), newToken); - return SourceTreeToPsiMap.treeElementToPsi(newToken); + final LeafElement newToken = Factory.createSingleLeafElement(DOC_TAG_VALUE_TOKEN, newElementName, charTableByTree, getManager()); + ((CompositeElement)treeElement.getTreeParent()).replaceChildInternal(SourceTreeToPsiMap.psiToTreeNotNull(nameElement), newToken); + return SourceTreeToPsiMap.treeToPsiNotNull(newToken); } public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException { if (isReferenceTo(element)) return PsiDocMethodOrFieldRef.this; - final String name = getNameElement().getText(); + final PsiElement nameElement = getNameElement(); + assert nameElement != null; + final String name = nameElement.getText(); final String newName; final PsiMethod method; @@ -305,15 +301,16 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo throw new IncorrectOperationException(); } - - if (getFirstChild().getNode().getElementType() == ElementType.DOC_REFERENCE_HOLDER) { - PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement) getFirstChild().getFirstChild(); + final PsiElement child = getFirstChild(); + if (containingClass != null && child != null && child.getNode().getElementType() == ElementType.DOC_REFERENCE_HOLDER) { + final PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement) child.getFirstChild(); + assert referenceElement != null; referenceElement.bindToElement(containingClass); } else { - if (!PsiTreeUtil.isAncestor(containingClass, PsiDocMethodOrFieldRef.this, true)) { - final PsiReferenceExpression ref = - JavaPsiFacade.getInstance(containingClass.getProject()).getElementFactory().createReferenceExpression(containingClass); + if (containingClass != null && !PsiTreeUtil.isAncestor(containingClass, PsiDocMethodOrFieldRef.this, true)) { + final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(containingClass.getProject()).getElementFactory(); + final PsiReferenceExpression ref = elementFactory.createReferenceExpression(containingClass); addAfter(ref, null); } } @@ -352,10 +349,11 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo } public PsiElement bindToText(PsiClass containingClass, StringBuffer newText) { - PsiComment comment = - JavaPsiFacade.getInstance(containingClass.getProject()).getElementFactory().createCommentFromText(newText.toString(), null); + PsiElementFactory elementFactory = JavaPsiFacade.getInstance(containingClass.getProject()).getElementFactory(); + PsiComment comment = elementFactory.createCommentFromText(newText.toString(), null); PsiElement tag = PsiTreeUtil.getChildOfType(comment, PsiDocTag.class); PsiElement ref = PsiTreeUtil.getChildOfType(tag, PsiDocMethodOrFieldRef.class); + assert ref != null : newText; return replace(ref); } @@ -366,20 +364,20 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo public TextRange getRangeInElement() { final ASTNode sharp = findChildByType(DOC_TAG_VALUE_SHARP_TOKEN); if (sharp == null) return new TextRange(0, getTextLength()); - final PsiElement nextSibling = SourceTreeToPsiMap.treeElementToPsi(sharp).getNextSibling(); - if(nextSibling != null){ + final PsiElement nextSibling = SourceTreeToPsiMap.treeToPsiNotNull(sharp).getNextSibling(); + if (nextSibling != null) { final int startOffset = nextSibling.getTextRange().getStartOffset() - getTextRange().getStartOffset(); int endOffset = nextSibling.getTextRange().getEndOffset() - getTextRange().getStartOffset(); final PsiElement nextParSibling = nextSibling.getNextSibling(); - if(nextParSibling != null && "(".equals(nextParSibling.getText())){ - endOffset ++; + if (nextParSibling != null && "(".equals(nextParSibling.getText())) { + endOffset++; PsiElement nextElement = nextParSibling.getNextSibling(); - if(nextElement != null && SourceTreeToPsiMap.psiElementToTree(nextElement).getElementType() == DOC_TAG_VALUE_TOKEN){ + if (nextElement != null && SourceTreeToPsiMap.psiToTreeNotNull(nextElement).getElementType() == DOC_TAG_VALUE_TOKEN) { endOffset += nextElement.getTextLength(); nextElement = nextElement.getNextSibling(); } - if(nextElement != null && ")".equals(nextElement.getText())){ - endOffset ++; + if (nextElement != null && ")".equals(nextElement.getText())) { + endOffset++; } } return new TextRange(startOffset, endOffset); diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodDialog.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodDialog.java index c5637ed8a6ce..a935d6046c5a 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodDialog.java @@ -373,8 +373,11 @@ public class ExtractMethodDialog extends AbstractExtractDialog { buffer.append("static "); } if (myTypeParameterList != null) { - buffer.append(myTypeParameterList.getText()); - buffer.append(" "); + final String typeParamsText = myTypeParameterList.getText(); + if (!typeParamsText.isEmpty()) { + buffer.append(typeParamsText); + buffer.append(" "); + } } if (isChainedConstructor()) { diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java index f203196b8d56..f99ae678c7c5 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java @@ -28,6 +28,7 @@ import com.intellij.codeInsight.AnnotationUtil; import com.intellij.codeInsight.ChangeContextUtil; import com.intellij.codeInsight.TestUtil; import com.intellij.codeInsight.highlighting.HighlightManager; +import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.ide.util.DirectoryChooserUtil; import com.intellij.ide.util.PackageUtil; import com.intellij.openapi.application.ApplicationManager; @@ -552,15 +553,18 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase public void pass(final ElementToWorkOn elementToWorkOn) { if (elementToWorkOn == null) return; + final boolean hasRunTemplate = LookupManager.getActiveLookup(editor) == null; if (elementToWorkOn.getExpression() == null) { final PsiLocalVariable localVariable = elementToWorkOn.getLocalVariable(); - final boolean result = invokeImpl(project, localVariable, editor); + final boolean result = invokeImpl(project, localVariable, editor) && hasRunTemplate; if (result) { editor.getSelectionModel().removeSelection(); } } - else if (invokeImpl(project, elementToWorkOn.getExpression(), editor)) { - editor.getSelectionModel().removeSelection(); + else { + if (invokeImpl(project, elementToWorkOn.getExpression(), editor) && hasRunTemplate) { + editor.getSelectionModel().removeSelection(); + } } } }; diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java index c61a82d31b32..8fcb8390d532 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java @@ -397,7 +397,7 @@ class IntroduceConstantDialog extends DialogWrapper { errorString = RefactoringBundle.message("no.field.name.specified"); } else if (!JavaPsiFacade.getInstance(myProject).getNameHelper().isIdentifier(fieldName)) { errorString = RefactoringMessageUtil.getIncorrectIdentifierMessage(fieldName); - } else if (!myParentClass.getLanguage().equals(newClass.getLanguage())) { + } else if (newClass != null && !myParentClass.getLanguage().equals(newClass.getLanguage())) { errorString = RefactoringBundle.message("move.to.different.language", UsageViewUtil.getType(myParentClass), myParentClass.getQualifiedName(), newClass.getQualifiedName()); } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/InplaceIntroduceParameterPopup.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/InplaceIntroduceParameterPopup.java index 895aa80e2892..32494482c0b3 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/InplaceIntroduceParameterPopup.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/InplaceIntroduceParameterPopup.java @@ -17,6 +17,8 @@ package com.intellij.refactoring.introduceParameter; import com.intellij.codeInsight.highlighting.HighlightManager; import com.intellij.codeInsight.intention.impl.TypeExpression; +import com.intellij.codeInsight.template.impl.TemplateManagerImpl; +import com.intellij.codeInsight.template.impl.TemplateState; import com.intellij.ide.IdeTooltipManager; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; @@ -33,17 +35,17 @@ import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.*; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.refactoring.JavaRefactoringSettings; -import com.intellij.refactoring.RefactoringBundle; -import com.intellij.refactoring.introduceVariable.OccurrencesChooser; import com.intellij.refactoring.introduceVariable.VariableInplaceIntroducer; import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer; -import com.intellij.refactoring.ui.NameSuggestionsGenerator; +import com.intellij.refactoring.ui.TypeSelectorManager; import com.intellij.refactoring.ui.TypeSelectorManagerImpl; -import com.intellij.ui.NonFocusableCheckBox; +import com.intellij.ui.TitlePanel; import com.intellij.ui.awt.RelativePoint; import com.intellij.usageView.UsageInfo; import gnu.trove.TIntArrayList; @@ -61,30 +63,30 @@ import java.util.List; * Date: 2/25/11 */ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI { - private JCheckBox myDelegateCb; private Balloon myBalloon; private final Project myProject; private final Editor myEditor; private final TypeSelectorManagerImpl myTypeSelectorManager; - private final NameSuggestionsGenerator myNameSuggestionsGenerator; - private final PsiExpression myExpr; + private PsiExpression myExpr; private final PsiLocalVariable myLocalVar; private final PsiMethod myMethod; private final PsiMethod myMethodToSearchFor; private final PsiExpression[] myOccurrences; private final boolean myMustBeFinal; - private final RangeMarker myExprMarker; - private final List myOccurrenceMarkers; + private RangeMarker myExprMarker; + private List myOccurrenceMarkers; private final JPanel myWholePanel; + private int myParameterIndex = -1; + private String myParameterName; + private final String myExprText; InplaceIntroduceParameterPopup(final Project project, final Editor editor, final List classMemberRefs, final TypeSelectorManagerImpl typeSelectorManager, - final NameSuggestionsGenerator nameSuggestionsGenerator, final PsiExpression expr, final PsiLocalVariable localVar, final PsiMethod method, @@ -96,7 +98,6 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI { myProject = project; myEditor = editor; myTypeSelectorManager = typeSelectorManager; - myNameSuggestionsGenerator = nameSuggestionsGenerator; myExpr = expr; myLocalVar = localVar; myMethod = method; @@ -104,14 +105,23 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI { myOccurrences = occurrences; myMustBeFinal = mustBeFinal; myExprMarker = expr != null ? myEditor.getDocument().createRangeMarker(myExpr.getTextRange()) : null; - myOccurrenceMarkers = new ArrayList(); + myExprText = myExpr != null ? myExpr.getText() : null; myWholePanel = new JPanel(new GridBagLayout()); - myWholePanel.setBorder(BorderFactory.createTitledBorder(IntroduceParameterHandler.REFACTORING_NAME)); - myDelegateCb = new NonFocusableCheckBox(RefactoringBundle.message("delegation.panel.delegate.via.overloading.method")); + myWholePanel.setBorder(null); final GridBagConstraints gc = - new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 0), 0, 0); - myWholePanel.add(myDelegateCb, gc); + new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0); + + final TitlePanel titlePanel = new TitlePanel(); + titlePanel.setBorder(null); + titlePanel.setText(IntroduceParameterHandler.REFACTORING_NAME); + myWholePanel.add(titlePanel, gc); + + gc.insets = new Insets(5, 5, 5, 0); + if (myOccurrences.length > 1 && !myIsInvokedOnDeclaration) { + gc.gridy++; + createOccurrencesCb(gc, myWholePanel, myOccurrences.length); + } final JavaRefactoringSettings settings = JavaRefactoringSettings.getInstance(); createLocalVariablePanel(gc, myWholePanel, settings); createRemoveParamsPanel(gc, myWholePanel); @@ -119,52 +129,75 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI { gc.gridy++; myWholePanel.add(createReplaceFieldsWithGettersPanel(), gc); } + gc.gridy++; + createDelegateCb(gc, myWholePanel); } void inplaceIntroduceParameter() { - final LinkedHashMap occurrencesMap = - new LinkedHashMap(); + startIntroduceTemplate(false); + } - for (PsiExpression occurrence : myOccurrences) { - myOccurrenceMarkers.add(myEditor.getDocument().createRangeMarker(occurrence.getTextRange())); - } - - OccurrencesChooser.fillChoices(myExpr, myOccurrences, occurrencesMap); - new OccurrencesChooser(myEditor).showChooser(new IntroduceParameterPass(), occurrencesMap); + private void startIntroduceTemplate(final boolean replaceAllOccurrences) { + CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { + public void run() { + myTypeSelectorManager.setAllOccurences(replaceAllOccurrences); + final PsiType defaultType = myTypeSelectorManager.getTypeSelector().getSelectedType(); + final String propName = myLocalVar != null ? JavaCodeStyleManager + .getInstance(myProject).variableNameToPropertyName(myLocalVar.getName(), VariableKind.LOCAL_VARIABLE) : null; + final String[] names = IntroduceParameterHandler.createNameSuggestionGenerator(myExpr, propName, myProject) + .getSuggestedNameInfo(defaultType).names; + final PsiParameter parameter = createParameterToStartTemplateOn(names, defaultType); + if (parameter != null) { + myParameterIndex = myMethod.getParameterList().getParameterIndex(parameter); + myEditor.getCaretModel().moveToOffset(parameter.getTextOffset()); + showBalloon(); + final LinkedHashSet nameSuggestions = new LinkedHashSet(); + nameSuggestions.add(parameter.getName()); + nameSuggestions.addAll(Arrays.asList(names)); + final VariableInplaceRenamer renamer = new ParameterInplaceIntroducer(parameter); + renamer.performInplaceRename(false, nameSuggestions); + } + } + }, IntroduceParameterHandler.REFACTORING_NAME, null); } @Override - protected void updateControls(JCheckBox[] removeParamsCb) { + protected TypeSelectorManager getTypeSelectionManager() { + return myTypeSelectorManager; + } + + private PsiParameter getParameter() { + return myMethod.getParameterList().getParameters()[myParameterIndex]; + } + + public List getOccurrenceMarkers() { + if (myOccurrenceMarkers == null) { + myOccurrenceMarkers = new ArrayList(); + for (PsiExpression occurrence : myOccurrences) { + myOccurrenceMarkers.add(myEditor.getDocument().createRangeMarker(occurrence.getTextRange())); + } + } + return myOccurrenceMarkers; } private class ParameterInplaceIntroducer extends VariableInplaceIntroducer { - private String myParameterName; + private SmartTypePointer myParameterTypePointer; private SmartTypePointer myDefaultParameterTypePointer; - private final PsiParameter myParameter; - private int myParameterIndex; - private PsiExpression myExpression; - private final OccurrencesChooser.ReplaceChoice myReplaceChoice; private boolean myFinal; - private final String myExprText; - public ParameterInplaceIntroducer(PsiParameter parameter, - OccurrencesChooser.ReplaceChoice replaceChoice) { + public ParameterInplaceIntroducer(PsiParameter parameter) { super(myProject, new TypeExpression(myProject, myTypeSelectorManager.getTypesForAll()), myEditor, parameter, myMustBeFinal, - myTypeSelectorManager.getTypesForAll().length > 1, myExprMarker, myOccurrenceMarkers); - myParameter = parameter; - myReplaceChoice = replaceChoice; - myExprText = myExpr != null ? myExpr.getText() : null; - myParameterIndex = myMethod.getParameterList().getParameterIndex(myParameter); + myTypeSelectorManager.getTypesForAll().length > 1, myExprMarker, getOccurrenceMarkers()); myDefaultParameterTypePointer = SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(parameter.getType()); } @Override protected PsiVariable getVariable() { - return myMethod.getParameterList().getParameters()[myParameterIndex]; + return getParameter(); } @Override @@ -184,8 +217,13 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI { @Override protected void collectAdditionalElementsToRename(boolean processTextOccurrences, List> stringUsages) { - for (PsiExpression expression : myOccurrences) { - stringUsages.add(Pair.create(expression, new TextRange(0, expression.getTextLength()))); + if (isReplaceAllOccurences()) { + for (PsiExpression expression : myOccurrences) { + stringUsages.add(Pair.create(expression, new TextRange(0, expression.getTextLength()))); + } + } + else if (myExpr != null) { + stringUsages.add(Pair.create(myExpr, new TextRange(0, myExpr.getTextLength()))); } } @@ -202,9 +240,16 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI { @NotNull HighlightManager highlightManager) { final TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES); - for (RangeMarker marker : myOccurrenceMarkers) { - final int startOffset = marker.getStartOffset(); - highlightManager.addOccurrenceHighlight(editor, startOffset, startOffset + myParameter.getName().length(), attributes, 0, highlighters, null); + final int variableNameLength = getVariable().getName().length(); + if (isReplaceAllOccurences()) { + for (RangeMarker marker : getOccurrenceMarkers()) { + final int startOffset = marker.getStartOffset(); + highlightManager.addOccurrenceHighlight(editor, startOffset, startOffset + variableNameLength, attributes, 0, highlighters, null); + } + } + else if (myExpr != null) { + final int startOffset = myExprMarker.getStartOffset(); + highlightManager.addOccurrenceHighlight(editor, startOffset, startOffset + variableNameLength, attributes, 0, highlighters, null); } super.addHighlights(ranges, editor, highlighters, highlightManager); } @@ -222,7 +267,7 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI { if (success) { boolean isDeleteLocalVariable = false; - PsiExpression parameterInitializer = myExpression; + PsiExpression parameterInitializer = myExpr; if (myLocalVar != null) { if (isUseInitializer()) { parameterInitializer = myLocalVar.getInitializer(); @@ -233,10 +278,10 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI { final IntroduceParameterProcessor processor = new IntroduceParameterProcessor(myProject, myMethod, - myMethodToSearchFor, parameterInitializer, myExpression, + myMethodToSearchFor, parameterInitializer, myExpr, myLocalVar, isDeleteLocalVariable, myParameterName, - myReplaceChoice == OccurrencesChooser.ReplaceChoice.ALL, - getReplaceFieldsWithGetters(), myMustBeFinal || myFinal, myDelegateCb.isSelected(), + isReplaceAllOccurences(), + getReplaceFieldsWithGetters(), myMustBeFinal || myFinal, isGenerateDelegate(), myParameterTypePointer.getType(), parametersToRemove); processor.setPrepareSuccessfulSwingThreadCallback(new Runnable() { @@ -263,40 +308,54 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI { } - @Override public void finish() { super.finish(); myBalloon.hide(); - final PsiParameter psiParameter = myMethod.getParameterList().getParameters()[myParameterIndex]; - myParameterName = psiParameter.getName(); + final PsiParameter psiParameter = (PsiParameter)getVariable(); + LOG.assertTrue(psiParameter != null); myFinal = psiParameter.hasModifierProperty(PsiModifier.FINAL); myParameterTypePointer = SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(psiParameter.getType()); PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + myParameterName = psiParameter.getName(); ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { final PsiFile containingFile = myMethod.getContainingFile(); final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject); - myExpression = restoreExpression(containingFile, elementFactory, myExprMarker); - for (RangeMarker marker : myOccurrenceMarkers) { - if (myExprMarker != null && marker.getStartOffset() == myExprMarker.getStartOffset()) continue; - restoreExpression(containingFile, elementFactory, marker); + myExpr = restoreExpression(containingFile, psiParameter, elementFactory, myExprMarker); + if (myExpr != null) { + myExprMarker = myEditor.getDocument().createRangeMarker(myExpr.getTextRange()); } + final List occurrenceMarkers = getOccurrenceMarkers(); + for (int i = 0, occurrenceMarkersSize = occurrenceMarkers.size(); i < occurrenceMarkersSize; i++) { + RangeMarker marker = occurrenceMarkers.get(i); + if (myExprMarker != null && marker.getStartOffset() == myExprMarker.getStartOffset()) { + myOccurrences[i] = myExpr; + continue; + } + final PsiExpression psiExpression = restoreExpression(containingFile, psiParameter, elementFactory, marker); + if (psiExpression != null) { + myOccurrences[i] = psiExpression; + } + } + myOccurrenceMarkers = null; if (psiParameter.isValid()) { psiParameter.delete(); } } }); - } @Nullable - private PsiExpression restoreExpression(PsiFile containingFile, PsiElementFactory elementFactory, RangeMarker marker) { + private PsiExpression restoreExpression(PsiFile containingFile, + PsiParameter psiParameter, + PsiElementFactory elementFactory, + RangeMarker marker) { if (myExprText == null) return null; - if (myParameter == null || !myParameter.isValid()) return null; + if (psiParameter == null || !psiParameter.isValid()) return null; final PsiElement refVariableElement = containingFile.findElementAt(marker.getStartOffset()); final PsiExpression expression = PsiTreeUtil.getParentOfType(refVariableElement, PsiReferenceExpression.class); - if (expression instanceof PsiReferenceExpression && ((PsiReferenceExpression)expression).resolve() == myParameter) { + if (expression instanceof PsiReferenceExpression && ((PsiReferenceExpression)expression).resolve() == psiParameter) { return (PsiExpression)expression.replace(elementFactory.createExpressionFromText(myExprText, myMethod)); } return null; @@ -313,56 +372,48 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI { return createFinals == null ? CodeStyleSettingsManager.getSettings(myProject).GENERATE_FINAL_PARAMETERS : createFinals.booleanValue(); } - private class IntroduceParameterPass extends Pass { - - @Override - public void pass(final OccurrencesChooser.ReplaceChoice replaceChoice) { - CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { - public void run() { - myTypeSelectorManager.setAllOccurences(replaceChoice != OccurrencesChooser.ReplaceChoice.NO); - final PsiType defaultType = myTypeSelectorManager.getTypeSelector().getSelectedType(); - final String[] names = myNameSuggestionsGenerator.getSuggestedNameInfo(defaultType).names; - final PsiParameter parameter = createParameterToStartTemplateOn(names, defaultType); - if (parameter != null) { - myEditor.getCaretModel().moveToOffset(parameter.getTextOffset()); - showSettingsPopup(); - final VariableInplaceRenamer renamer = - new ParameterInplaceIntroducer(parameter, replaceChoice); - renamer.performInplaceRename(false, new LinkedHashSet(Arrays.asList(names))); - } - } - }, IntroduceParameterHandler.REFACTORING_NAME, null); - } - - private PsiParameter createParameterToStartTemplateOn(final String[] names, - final PsiType defaultType) { - final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myMethod.getProject()); - return ApplicationManager.getApplication().runWriteAction(new Computable() { - @Override - public PsiParameter compute() { - final PsiParameter psiParameter = (PsiParameter)myMethod.getParameterList() - .addAfter(elementFactory.createParameter(names[0], defaultType), - JavaIntroduceParameterMethodUsagesProcessor.getAnchorParameter(myMethod)); - PsiUtil.setModifierProperty(psiParameter, PsiModifier.FINAL, hasFinalModifier()); - return psiParameter; - } - }); - } - - private void showSettingsPopup() { - BalloonBuilder balloonBuilder = JBPopupFactory.getInstance().createBalloonBuilder(myWholePanel); - balloonBuilder.setFadeoutTime(0); - balloonBuilder.setFillColor(IdeTooltipManager.GRAPHITE_COLOR); - balloonBuilder.setAnimationCycle(0); - balloonBuilder.setHideOnClickOutside(false); - balloonBuilder.setHideOnKeyOutside(false); - balloonBuilder.setHideOnAction(false); - balloonBuilder.setCloseButtonEnabled(true); - final RelativePoint target = JBPopupFactory.getInstance().guessBestPopupLocation(myEditor); - final Point screenPoint = target.getScreenPoint(); - myBalloon = balloonBuilder.createBalloon(); - myBalloon - .show(new RelativePoint(new Point(screenPoint.x, screenPoint.y - myEditor.getLineHeight())), Balloon.Position.above); + @Override + protected void updateControls(JCheckBox[] removeParamsCb) { + super.updateControls(removeParamsCb); + if (myParameterIndex < 0) return; + final TemplateState templateState = TemplateManagerImpl.getTemplateState(myEditor); + if (templateState != null) { + templateState.gotoEnd(true); + startIntroduceTemplate(isReplaceAllOccurences()); } } + + + private PsiParameter createParameterToStartTemplateOn(final String[] names, + final PsiType defaultType) { + final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myMethod.getProject()); + return ApplicationManager.getApplication().runWriteAction(new Computable() { + @Override + public PsiParameter compute() { + final String name = myParameterName != null ? myParameterName : names[0]; + final PsiParameter anchor = JavaIntroduceParameterMethodUsagesProcessor.getAnchorParameter(myMethod); + final PsiParameter psiParameter = (PsiParameter)myMethod.getParameterList() + .addAfter(elementFactory.createParameter(name, defaultType), anchor); + PsiUtil.setModifierProperty(psiParameter, PsiModifier.FINAL, hasFinalModifier()); + return psiParameter; + } + }); + } + + private void showBalloon() { + final BalloonBuilder balloonBuilder = JBPopupFactory.getInstance().createBalloonBuilder(myWholePanel); + balloonBuilder.setFadeoutTime(0) + .setFillColor(IdeTooltipManager.GRAPHITE_COLOR) + .setAnimationCycle(0) + .setHideOnClickOutside(false) + .setHideOnKeyOutside(false) + .setHideOnAction(false) + .setCloseButtonEnabled(true); + + final RelativePoint target = JBPopupFactory.getInstance().guessBestPopupLocation(myEditor); + final Point screenPoint = target.getScreenPoint(); + myBalloon = balloonBuilder.createBalloon(); + myBalloon + .show(new RelativePoint(new Point(screenPoint.x, screenPoint.y - myEditor.getLineHeight())), Balloon.Position.above); + } } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterDialog.java index 8876e3826590..828e93793032 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterDialog.java @@ -40,8 +40,6 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; import java.util.List; public class IntroduceParameterDialog extends RefactoringDialog { @@ -60,8 +58,7 @@ public class IntroduceParameterDialog extends RefactoringDialog { // private JComponent myParameterNameField = null; private NameSuggestionsField myParameterNameField; - private JCheckBox myCbReplaceAllOccurences = null; - private JCheckBox myCbGenerateDelegate = null; + private final NameSuggestionsGenerator myNameSuggestionsGenerator; private final TypeSelectorManager myTypeSelectorManager; @@ -106,13 +103,7 @@ public class IntroduceParameterDialog extends RefactoringDialog { return myCbDeclareFinal != null && myCbDeclareFinal.isSelected(); } - private boolean isReplaceAllOccurences() { - return myPanel.myIsInvokedOnDeclaration || myCbReplaceAllOccurences != null && myCbReplaceAllOccurences.isSelected(); - } - private boolean isGenerateDelegate() { - return myCbGenerateDelegate != null && myCbGenerateDelegate.isSelected(); - } private String getParameterName() { return myParameterNameField.getEnteredName().trim(); @@ -196,11 +187,7 @@ public class IntroduceParameterDialog extends RefactoringDialog { gbConstraints.gridwidth = 2; if (myOccurenceNumber > 1 && !myPanel.myIsInvokedOnDeclaration) { gbConstraints.gridy++; - myCbReplaceAllOccurences = new NonFocusableCheckBox(); - myCbReplaceAllOccurences.setText(RefactoringBundle.message("replace.all.occurences", myOccurenceNumber)); - - panel.add(myCbReplaceAllOccurences, gbConstraints); - myCbReplaceAllOccurences.setSelected(false); + myPanel.createOccurrencesCb(gbConstraints, panel, myOccurenceNumber); } JavaRefactoringSettings settings = JavaRefactoringSettings.getInstance(); @@ -218,31 +205,19 @@ public class IntroduceParameterDialog extends RefactoringDialog { myCbDeclareFinal.setEnabled(false); } - if(myCbReplaceAllOccurences != null) { + if(myPanel.myCbReplaceAllOccurences != null) { gbConstraints.insets = new Insets(0, 16, 4, 8); } myPanel.createLocalVariablePanel(gbConstraints, panel, settings); - + myPanel.createRemoveParamsPanel(gbConstraints, panel); gbConstraints.insets = new Insets(4, 0, 4, 8); gbConstraints.gridy++; - myCbGenerateDelegate = new NonFocusableCheckBox(RefactoringBundle.message("delegation.panel.delegate.via.overloading.method")); - panel.add(myCbGenerateDelegate, gbConstraints); + myPanel.createDelegateCb(gbConstraints, panel); - final JCheckBox[] removeParamsCb = myPanel.createRemoveParamsPanel(gbConstraints, panel); - if (myCbReplaceAllOccurences != null) { - myCbReplaceAllOccurences.addItemListener( - new ItemListener() { - public void itemStateChanged(ItemEvent e) { - myPanel.updateControls(removeParamsCb); - } - } - ); - } return panel; } - protected JComponent createCenterPanel() { if(Util.anyFieldsWithGettersPresent(myClassMembersList)) { return myPanel.createReplaceFieldsWithGettersPanel(); @@ -276,8 +251,8 @@ public class IntroduceParameterDialog extends RefactoringDialog { myProject, myMethodToReplaceIn, myMethodToSearchFor, parameterInitializer, myExpression, myLocalVar, isDeleteLocalVariable, - getParameterName(), isReplaceAllOccurences(), - myPanel.getReplaceFieldsWithGetters(), isDeclareFinal(), isGenerateDelegate(), getSelectedType(), myPanel.getParametersToRemove()); + getParameterName(), myPanel.isReplaceAllOccurences(), + myPanel.getReplaceFieldsWithGetters(), isDeclareFinal(), myPanel.isGenerateDelegate(), getSelectedType(), myPanel.getParametersToRemove()); invokeRefactoring(processor); myParameterNameField.requestFocusInWindow(); } @@ -299,29 +274,10 @@ public class IntroduceParameterDialog extends RefactoringDialog { super(project, onLocalVariable, onExpression, methodToReplaceIn, parametersToRemove); } + @Override - protected void updateControls(JCheckBox[] removeParamsCb) { - if (myCbReplaceAllOccurences != null) { - for (JCheckBox box : removeParamsCb) { - if (box != null) { - box.setEnabled(myCbReplaceAllOccurences.isSelected()); - } - } - myTypeSelectorManager.setAllOccurences(myCbReplaceAllOccurences.isSelected()); - if (myCbReplaceAllOccurences.isSelected()) { - if (myCbDeleteLocalVariable != null) { - myCbDeleteLocalVariable.makeSelectable(); - } - } - else { - if (myCbDeleteLocalVariable != null) { - myCbDeleteLocalVariable.makeUnselectable(false); - } - } - } - else { - myTypeSelectorManager.setAllOccurences(myIsInvokedOnDeclaration); - } + protected TypeSelectorManager getTypeSelectionManager() { + return myTypeSelectorManager; } } } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java index 64e08642e02d..ab68e187b33f 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java @@ -26,14 +26,20 @@ package com.intellij.refactoring.introduceParameter; import com.intellij.codeInsight.CodeInsightUtil; import com.intellij.codeInsight.completion.JavaCompletionUtil; -import com.intellij.ide.util.SuperMethodWarningUtil; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.editor.colors.EditorColors; +import com.intellij.openapi.editor.colors.EditorColorsManager; +import com.intellij.openapi.editor.markup.*; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.*; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Pass; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.SuggestedNameInfo; @@ -41,17 +47,28 @@ import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.*; import com.intellij.refactoring.introduceField.ElementToWorkOn; +import com.intellij.refactoring.ui.MethodCellRenderer; import com.intellij.refactoring.ui.NameSuggestionsGenerator; import com.intellij.refactoring.ui.TypeSelectorManagerImpl; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.refactoring.util.occurences.ExpressionOccurenceManager; +import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.ScrollPaneFactory; +import com.intellij.ui.components.JBList; import com.intellij.usageView.UsageInfo; import gnu.trove.TIntArrayList; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; import java.util.*; import java.util.List; @@ -60,6 +77,7 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase implements R private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.introduceParameter.IntroduceParameterHandler"); static final String REFACTORING_NAME = RefactoringBundle.message("introduce.parameter.title"); private Project myProject; + private JBPopup myEnclosingMethodsPopup; public void invoke(@NotNull final Project project, final Editor editor, PsiFile file, DataContext dataContext) { PsiDocumentManager.getInstance(project).commitAllDocuments(); @@ -86,7 +104,7 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase implements R return invoke(editor, project, null, localVariable, true); } - private boolean invoke(Editor editor, Project project, final PsiExpression expr, + private boolean invoke(final Editor editor, final Project project, final PsiExpression expr, PsiLocalVariable localVar, boolean invokedOnDeclaration) { LOG.assertTrue(!PsiDocumentManager.getInstance(project).hasUncommitedDocuments()); PsiMethod method; @@ -131,103 +149,124 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase implements R return false; } - method = chooseEnclosingMethod(method); - if (method == null) return false; - - final PsiMethod methodToSearchFor = SuperMethodWarningUtil.checkSuperMethod(method, RefactoringBundle.message("to.refactor")); - if (methodToSearchFor == null) return false; - if (!CommonRefactoringUtil.checkReadOnlyStatus(project, methodToSearchFor)) return false; - - PsiExpression[] occurences; - if (expr != null) { - occurences = new ExpressionOccurenceManager(expr, method, null).findExpressionOccurrences(); + final List validEnclosingMethods = getEnclosingMethods(method); + if (validEnclosingMethods.isEmpty()) { + return false; } - else { // local variable - occurences = CodeInsightUtil.findReferenceExpressions(method, localVar); - } - PsiExpression expressionToRemoveParamFrom = expr; - if (expr == null) { - expressionToRemoveParamFrom = localVar.getInitializer(); - } - TIntArrayList parametersToRemove = expressionToRemoveParamFrom == null ? new TIntArrayList() : Util.findParametersToRemove(method, expressionToRemoveParamFrom, occurences); - - boolean mustBeFinal = false; - if (localVar != null) { - for(PsiExpression occurrence: occurences) { - if (PsiTreeUtil.getParentOfType(occurrence, PsiClass.class, PsiMethod.class) != method) { - mustBeFinal = true; - break; - } + final Introducer introducer = new Introducer(project, expr, localVar, editor); + final boolean unitTestMode = ApplicationManager.getApplication().isUnitTestMode(); + if (validEnclosingMethods.size() == 1 || unitTestMode) { + if (validEnclosingMethods.get(0).findDeepestSuperMethod() == null || unitTestMode) { + introducer.introduceParameter(method, method); + return true; } } - List localVars = new ArrayList(); - List classMemberRefs = new ArrayList(); - List params = new ArrayList(); + chooseMethodToIntroduceParameter(editor, validEnclosingMethods, introducer); - - if (expr != null) { - Util.analyzeExpression(expr, localVars, classMemberRefs, params); - } - - if (expr instanceof PsiReferenceExpression) { - PsiElement resolved = ((PsiReferenceExpression) expr).resolve(); - if (resolved instanceof PsiLocalVariable) { - localVar = (PsiLocalVariable) resolved; - } - } - - - if (ApplicationManager.getApplication().isUnitTestMode()) { - @NonNls String parameterName = "anObject"; - boolean replaceAllOccurences = true; - boolean isDeleteLocalVariable = true; - PsiExpression initializer = localVar != null && expr == null ? localVar.getInitializer() : expr; - new IntroduceParameterProcessor(myProject, method, methodToSearchFor, initializer, expr, localVar, isDeleteLocalVariable, parameterName, - replaceAllOccurences, IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, mustBeFinal, - false, null, - parametersToRemove).run(); - } - else { - final String propName = localVar != null ? JavaCodeStyleManager.getInstance(myProject).variableNameToPropertyName(localVar.getName(), VariableKind.LOCAL_VARIABLE) : null; - final PsiType initializerType = IntroduceParameterProcessor.getInitializerType(null, expr, localVar); - - TypeSelectorManagerImpl typeSelectorManager = expr != null - ? new TypeSelectorManagerImpl(project, initializerType, expr, occurences) - : new TypeSelectorManagerImpl(project, initializerType, occurences); - - NameSuggestionsGenerator nameSuggestionsGenerator = new NameSuggestionsGenerator() { - public SuggestedNameInfo getSuggestedNameInfo(PsiType type) { - final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(myProject); - final SuggestedNameInfo info = codeStyleManager.suggestVariableName(VariableKind.PARAMETER, propName, expr, type); - final String[] strings = JavaCompletionUtil.completeVariableNameForRefactoring(codeStyleManager, type, VariableKind.LOCAL_VARIABLE, info); - return new SuggestedNameInfo.Delegate(strings, info); - } - - }; - boolean isInplaceAvailableOnDataContext = editor != null && editor.getSettings().isVariableInplaceRenameEnabled() - && method == methodToSearchFor - && method.hasModifierProperty(PsiModifier.PRIVATE); - - if (!isInplaceAvailableOnDataContext) { - if (editor != null) { - RefactoringUtil.highlightAllOccurences(myProject, occurences, editor); - } - new IntroduceParameterDialog(myProject, classMemberRefs, occurences.length, localVar, expr, nameSuggestionsGenerator, - typeSelectorManager, methodToSearchFor, method, parametersToRemove, mustBeFinal).show(); - if (editor != null) { - editor.getSelectionModel().removeSelection(); - } - } else { - new InplaceIntroduceParameterPopup(project, editor, classMemberRefs, - typeSelectorManager, nameSuggestionsGenerator, - expr, localVar, method, methodToSearchFor, occurences, parametersToRemove, - mustBeFinal).inplaceIntroduceParameter(); - } - } return true; } + private void chooseMethodToIntroduceParameter(final Editor editor, + final List validEnclosingMethods, + final Introducer introducer) { + final JPanel panel = new JPanel(new BorderLayout()); + final JCheckBox superMethod = new JCheckBox("Choose base method", true); + superMethod.setMnemonic('b'); + panel.add(superMethod, BorderLayout.SOUTH); + final JBList list = new JBList(validEnclosingMethods.toArray()); + list.setCellRenderer(new MethodCellRenderer()); + list.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + list.setSelectedIndex(0); + final List highlighters = new ArrayList(); + final TextAttributes attributes = + EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES); + list.addListSelectionListener(new ListSelectionListener() { + public void valueChanged(final ListSelectionEvent e) { + final PsiMethod selectedMethod = (PsiMethod)list.getSelectedValue(); + if (selectedMethod == null) return; + dropHighlighters(highlighters); + updateView(selectedMethod, editor, attributes, highlighters, superMethod); + } + }); + updateView(validEnclosingMethods.get(0), editor, attributes, highlighters, superMethod); + final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(list); + scrollPane.setBorder(null); + panel.add(scrollPane, BorderLayout.CENTER); + + final List> + keyboardActions = Collections.singletonList(Pair.create(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + final PsiMethod methodToSearchIn = (PsiMethod)list.getSelectedValue(); + if (myEnclosingMethodsPopup != null && myEnclosingMethodsPopup.isVisible()) { + myEnclosingMethodsPopup.cancel(); + } + + final PsiMethod methodToSearchFor = superMethod.isEnabled() && superMethod.isSelected() + ? methodToSearchIn.findDeepestSuperMethod() : methodToSearchIn; + Runnable runnable = new Runnable() { + public void run() { + introducer.introduceParameter(methodToSearchIn, methodToSearchFor); + } + }; + IdeFocusManager.findInstance().doWhenFocusSettlesDown(runnable); + } + }, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0))); + myEnclosingMethodsPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(panel, list) + .setTitle("Introduce parameter to method") + .setMovable(false) + .setResizable(false) + .setRequestFocus(true) + .setKeyboardActions(keyboardActions).addListener(new JBPopupAdapter() { + @Override + public void onClosed(LightweightWindowEvent event) { + dropHighlighters(highlighters); + } + }).createPopup(); + myEnclosingMethodsPopup.showInBestPositionFor(editor); + } + + private static void updateView(PsiMethod selectedMethod, + Editor editor, + TextAttributes attributes, + List highlighters, + JCheckBox superMethod) { + final MarkupModel markupModel = editor.getMarkupModel(); + final PsiIdentifier nameIdentifier = selectedMethod.getNameIdentifier(); + if (nameIdentifier != null) { + final TextRange textRange = nameIdentifier.getTextRange(); + final RangeHighlighter rangeHighlighter = markupModel.addRangeHighlighter( + textRange.getStartOffset(), textRange.getEndOffset(), HighlighterLayer.SELECTION - 1, + attributes, + HighlighterTargetArea.EXACT_RANGE); + highlighters.add(rangeHighlighter); + } + superMethod.setEnabled(selectedMethod.findDeepestSuperMethod() != null); + } + + private static void dropHighlighters(List highlighters) { + for (RangeHighlighter highlighter : highlighters) { + highlighter.dispose(); + } + highlighters.clear(); + } + + protected static NameSuggestionsGenerator createNameSuggestionGenerator(final PsiExpression expr, + final String propName, + final Project project) { + return new NameSuggestionsGenerator() { + public SuggestedNameInfo getSuggestedNameInfo(PsiType type) { + final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project); + final SuggestedNameInfo info = codeStyleManager.suggestVariableName(VariableKind.PARAMETER, propName, expr, type); + final String[] strings = JavaCompletionUtil + .completeVariableNameForRefactoring(codeStyleManager, type, VariableKind.LOCAL_VARIABLE, info); + return new SuggestedNameInfo.Delegate(strings, info); + } + + }; + } + private static void showErrorMessage(Project project, String message, Editor editor) { CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INTRODUCE_PARAMETER); } @@ -238,7 +277,7 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase implements R /* do nothing */ } - private static List getEnclosingMethods(PsiMethod nearest) { + public static List getEnclosingMethods(PsiMethod nearest) { List enclosingMethods = new ArrayList(); enclosingMethods.add(nearest); PsiMethod method = nearest; @@ -285,4 +324,110 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase implements R private static boolean isLibraryInterfaceMethod(final PsiMethod method) { return method.hasModifierProperty(PsiModifier.ABSTRACT) && !method.getManager().isInProject(method); } + + private static class Introducer { + + private final Project myProject; + + private final PsiExpression myExpr; + private PsiLocalVariable myLocalVar; + private final Editor myEditor; + + public Introducer(Project project, + PsiExpression expr, + PsiLocalVariable localVar, + Editor editor) { + myProject = project; + myExpr = expr; + myLocalVar = localVar; + myEditor = editor; + } + + public void introduceParameter(PsiMethod method, PsiMethod methodToSearchFor) { + if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, methodToSearchFor)) return; + + PsiExpression[] occurences; + if (myExpr != null) { + occurences = new ExpressionOccurenceManager(myExpr, method, null).findExpressionOccurrences(); + } + else { // local variable + occurences = CodeInsightUtil.findReferenceExpressions(method, myLocalVar); + } + PsiExpression expressionToRemoveParamFrom = myExpr; + if (myExpr == null) { + expressionToRemoveParamFrom = myLocalVar.getInitializer(); + } + TIntArrayList parametersToRemove = expressionToRemoveParamFrom == null ? new TIntArrayList() : Util + .findParametersToRemove(method, expressionToRemoveParamFrom, occurences); + + boolean mustBeFinal = false; + if (myLocalVar != null) { + for(PsiExpression occurrence: occurences) { + if (PsiTreeUtil.getParentOfType(occurrence, PsiClass.class, PsiMethod.class) != method) { + mustBeFinal = true; + break; + } + } + } + + List localVars = new ArrayList(); + List classMemberRefs = new ArrayList(); + List params = new ArrayList(); + + + if (myExpr != null) { + Util.analyzeExpression(myExpr, localVars, classMemberRefs, params); + } + + if (myExpr instanceof PsiReferenceExpression) { + PsiElement resolved = ((PsiReferenceExpression)myExpr).resolve(); + if (resolved instanceof PsiLocalVariable) { + myLocalVar = (PsiLocalVariable) resolved; + } + } + + + if (ApplicationManager.getApplication().isUnitTestMode()) { + @NonNls String parameterName = "anObject"; + boolean replaceAllOccurences = true; + boolean isDeleteLocalVariable = true; + PsiExpression initializer = myLocalVar != null && myExpr == null ? myLocalVar.getInitializer() : myExpr; + new IntroduceParameterProcessor(myProject, method, methodToSearchFor, initializer, myExpr, myLocalVar, isDeleteLocalVariable, parameterName, + replaceAllOccurences, IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, mustBeFinal, + false, null, + parametersToRemove).run(); + } + else { + final String propName = myLocalVar != null ? JavaCodeStyleManager + .getInstance(myProject).variableNameToPropertyName(myLocalVar.getName(), VariableKind.LOCAL_VARIABLE) : null; + final PsiType initializerType = IntroduceParameterProcessor.getInitializerType(null, myExpr, myLocalVar); + + TypeSelectorManagerImpl typeSelectorManager = myExpr != null + ? new TypeSelectorManagerImpl(myProject, initializerType, myExpr, occurences) + : new TypeSelectorManagerImpl(myProject, initializerType, occurences); + + NameSuggestionsGenerator nameSuggestionsGenerator = createNameSuggestionGenerator(myExpr, propName, myProject); + boolean isInplaceAvailableOnDataContext = myEditor != null && myEditor.getSettings().isVariableInplaceRenameEnabled(); + + if (!isInplaceAvailableOnDataContext) { + if (myEditor != null) { + RefactoringUtil.highlightAllOccurences(myProject, occurences, myEditor); + } + new IntroduceParameterDialog(myProject, classMemberRefs, occurences.length, myLocalVar, myExpr, nameSuggestionsGenerator, + typeSelectorManager, methodToSearchFor, method, parametersToRemove, mustBeFinal).show(); + if (myEditor != null) { + myEditor.getSelectionModel().removeSelection(); + } + } + else { + new InplaceIntroduceParameterPopup(myProject, myEditor, classMemberRefs, + typeSelectorManager, + myExpr, myLocalVar, method, methodToSearchFor, occurences, parametersToRemove, + mustBeFinal).inplaceIntroduceParameter(); + } + } + } + } + + } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterSettingsUI.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterSettingsUI.java index a82a481b7f12..21fee109fade 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterSettingsUI.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterSettingsUI.java @@ -24,6 +24,7 @@ import com.intellij.refactoring.IntroduceParameterRefactoring; import com.intellij.refactoring.JavaRefactoringSettings; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.ui.RefactoringDialog; +import com.intellij.refactoring.ui.TypeSelectorManager; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.NonFocusableCheckBox; import com.intellij.ui.StateRestoringCheckBox; @@ -34,6 +35,8 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; /** * User: anna @@ -53,6 +56,9 @@ public abstract class IntroduceParameterSettingsUI { protected final boolean[] myParametersToRemoveChecked; protected final boolean myIsLocalVariable; + protected JCheckBox myCbReplaceAllOccurences = null; + private JCheckBox myCbGenerateDelegate = null; + public IntroduceParameterSettingsUI(Project project, PsiLocalVariable onLocalVariable, PsiExpression onExpression, @@ -97,6 +103,14 @@ public abstract class IntroduceParameterSettingsUI { return IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE; } + public boolean isReplaceAllOccurences() { + return myIsInvokedOnDeclaration || myCbReplaceAllOccurences != null && myCbReplaceAllOccurences.isSelected(); + } + + public boolean isGenerateDelegate() { + return myCbGenerateDelegate != null && myCbGenerateDelegate.isSelected(); + } + protected JPanel createReplaceFieldsWithGettersPanel() { JPanel radioButtonPanel = new JPanel(new GridBagLayout()); @@ -169,9 +183,33 @@ public abstract class IntroduceParameterSettingsUI { return parameters; } - protected abstract void updateControls(JCheckBox[] removeParamsCb); + protected void updateControls(JCheckBox[] removeParamsCb) { + if (myCbReplaceAllOccurences != null) { + for (JCheckBox box : removeParamsCb) { + if (box != null) { + box.setEnabled(myCbReplaceAllOccurences.isSelected()); + } + } + getTypeSelectionManager().setAllOccurences(myCbReplaceAllOccurences.isSelected()); + if (myCbReplaceAllOccurences.isSelected()) { + if (myCbDeleteLocalVariable != null) { + myCbDeleteLocalVariable.makeSelectable(); + } + } + else { + if (myCbDeleteLocalVariable != null) { + myCbDeleteLocalVariable.makeUnselectable(false); + } + } + } + else { + getTypeSelectionManager().setAllOccurences(myIsInvokedOnDeclaration); + } + } - protected JCheckBox[] createRemoveParamsPanel(GridBagConstraints gbConstraints, JPanel panel) { + protected abstract TypeSelectorManager getTypeSelectionManager(); + + protected void createRemoveParamsPanel(GridBagConstraints gbConstraints, JPanel panel) { final JCheckBox[] removeParamsCb = new JCheckBox[myParametersToRemove.length]; for (int i = 0; i < myParametersToRemove.length; i++) { PsiParameter parameter = myParametersToRemove[i]; @@ -192,7 +230,15 @@ public abstract class IntroduceParameterSettingsUI { } updateControls(removeParamsCb); - return removeParamsCb; + if (myCbReplaceAllOccurences != null) { + myCbReplaceAllOccurences.addItemListener( + new ItemListener() { + public void itemStateChanged(ItemEvent e) { + updateControls(removeParamsCb); + } + } + ); + } } protected void createLocalVariablePanel(GridBagConstraints gbConstraints, JPanel panel, JavaRefactoringSettings settings) { @@ -216,4 +262,18 @@ public abstract class IntroduceParameterSettingsUI { } } } + + + protected void createDelegateCb(GridBagConstraints gbConstraints, JPanel panel) { + myCbGenerateDelegate = new NonFocusableCheckBox(RefactoringBundle.message("delegation.panel.delegate.via.overloading.method")); + panel.add(myCbGenerateDelegate, gbConstraints); + } + + protected void createOccurrencesCb(GridBagConstraints gbConstraints, JPanel panel, final int occurenceNumber) { + myCbReplaceAllOccurences = new NonFocusableCheckBox(); + myCbReplaceAllOccurences.setText(RefactoringBundle.message("replace.all.occurences", occurenceNumber)); + + panel.add(myCbReplaceAllOccurences, gbConstraints); + myCbReplaceAllOccurences.setSelected(false); + } } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java index efd4672e9f5e..1ca50aad8094 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java @@ -110,7 +110,7 @@ public class OldReferenceResolver { final JavaResolveResult adv = oldRef.advancedResolve(false); final PsiElement scope = getClassContainingResolve(adv); final PsiClass clss = PsiTreeUtil.getParentOfType(oldExpr, PsiClass.class); - if (clss != null && scope != null && PsiTreeUtil.isAncestor(clss, scope, false)) { + if (clss != null && scope != null ) { final PsiElement subj = adv.getElement(); @@ -118,7 +118,6 @@ public class OldReferenceResolver { // Parameters if (subj instanceof PsiParameter) { PsiParameterList parameterList = myMethodToReplaceIn.getParameterList(); - PsiParameter[] parameters = parameterList.getParameters(); if (subj.getParent() != parameterList) return; int index = parameterList.getParameterIndex((PsiParameter)subj); @@ -133,7 +132,7 @@ public class OldReferenceResolver { } } // "naked" field and methods (should become qualified) - else if ((subj instanceof PsiField || subj instanceof PsiMethod) && oldRef.getQualifierExpression() == null) { + else if ((subj instanceof PsiField || subj instanceof PsiMethod) && oldRef.getQualifierExpression() == null && PsiTreeUtil.isAncestor(clss, scope, false)) { boolean isStatic = subj instanceof PsiField && ((PsiField)subj).hasModifierProperty(PsiModifier.STATIC) || subj instanceof PsiMethod && ((PsiMethod)subj).hasModifierProperty(PsiModifier.STATIC); @@ -151,7 +150,7 @@ public class OldReferenceResolver { } } - if (subj instanceof PsiField) { + if (subj instanceof PsiField && PsiTreeUtil.isAncestor(clss, scope, false)) { // probably replacing field with a getter if (myReplaceFieldsWithGetters != IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE) { if (myReplaceFieldsWithGetters == IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL || diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassHandler.java index 8840f1fc3c24..7d843351b0ad 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassHandler.java @@ -28,6 +28,10 @@ import org.jetbrains.annotations.Nullable; public interface MoveClassHandler { ExtensionPointName EP_NAME = new ExtensionPointName("com.intellij.refactoring.moveClassHandler"); + void prepareMove(@NotNull PsiClass aClass); + + void finishMoveClass(@NotNull PsiClass aClass); + /** * @return null if it cannot move aClass */ diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesHandlerBase.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesHandlerBase.java index 005ab5c7b057..32cf4cb8c812 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesHandlerBase.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesHandlerBase.java @@ -22,6 +22,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.vfs.VirtualFile; @@ -31,10 +32,9 @@ import com.intellij.psi.impl.source.jsp.jspJava.JspClass; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.JavaRefactoringSettings; import com.intellij.refactoring.RefactoringBundle; -import com.intellij.refactoring.move.MoveHandlerDelegate; import com.intellij.refactoring.move.MoveCallback; +import com.intellij.refactoring.move.MoveHandlerDelegate; import com.intellij.refactoring.util.CommonRefactoringUtil; -import com.intellij.openapi.project.Project; import com.intellij.refactoring.util.RadioUpDownListener; import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.util.IncorrectOperationException; @@ -70,8 +70,8 @@ public class MoveClassesOrPackagesHandlerBase extends MoveHandlerDelegate { public static boolean invalid4Move(PsiElement element) { PsiFile parentFile; - if (element instanceof PsiJavaFile) { - final PsiClass[] classes = ((PsiJavaFile)element).getClasses(); + if (element instanceof PsiClassOwner) { + final PsiClass[] classes = ((PsiClassOwner)element).getClasses(); if (classes.length == 0) return true; for (PsiClass aClass : classes) { if (aClass instanceof JspClass) return true; @@ -81,8 +81,9 @@ public class MoveClassesOrPackagesHandlerBase extends MoveHandlerDelegate { else { if (element instanceof JspClass) return true; if (!(element instanceof PsiClass)) return true; - if (!(element.getParent() instanceof PsiFile)) return true; - parentFile = (PsiFile)element.getParent(); + if (element instanceof PsiAnonymousClass) return true; + if (((PsiClass)element).getContainingClass() != null) return true; + parentFile = element.getContainingFile(); } if (CollectHighlightsUtil.isOutsideSourceRootJavaFile(parentFile)) return true; return false; @@ -313,12 +314,10 @@ public class MoveClassesOrPackagesHandlerBase extends MoveHandlerDelegate { public boolean tryToMove(final PsiElement element, final Project project, final DataContext dataContext, final PsiReference reference, final Editor editor) { if (isPackageOrDirectory(element)) return false; - if (CollectHighlightsUtil.isOutsideSourceRootJavaFile(element.getContainingFile())) return false; if (isReferenceInAnonymousClass(reference)) return false; - if (element instanceof PsiClass && !(element instanceof PsiAnonymousClass) && element.getParent() instanceof PsiFile) { - MoveClassesOrPackagesImpl.doMove(project, new PsiElement[]{element}, - LangDataKeys.TARGET_PSI_ELEMENT.getData(dataContext), null); + if (!invalid4Move(element)) { + MoveClassesOrPackagesImpl.doMove(project, new PsiElement[]{element}, LangDataKeys.TARGET_PSI_ELEMENT.getData(dataContext), null); return true; } return false; diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesProcessor.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesProcessor.java index d0349e634db4..002445ca5a20 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesProcessor.java @@ -15,7 +15,6 @@ */ package com.intellij.refactoring.move.moveClassesOrPackages; -import com.intellij.codeInsight.ChangeContextUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; @@ -80,8 +79,8 @@ public class MoveClassesOrPackagesProcessor extends BaseRefactoringProcessor { super(project); final Set toMove = new LinkedHashSet(); for (PsiElement element : elements) { - if (element instanceof PsiJavaFile) { - Collections.addAll(toMove, ((PsiJavaFile)element).getClasses()); + if (element instanceof PsiClassOwner) { + Collections.addAll(toMove, ((PsiClassOwner)element).getClasses()); } else { toMove.add(element); } @@ -448,7 +447,7 @@ public class MoveClassesOrPackagesProcessor extends BaseRefactoringProcessor { element = newElement; } else if (element instanceof PsiClass) { - ChangeContextUtil.encodeContextInfo(element, true); + MoveClassesOrPackagesUtil.prepareMoveClass((PsiClass)element); final PsiClass newElement = MoveClassesOrPackagesUtil.doMoveClass((PsiClass)element, myMoveDestination.getTargetDirectory(element.getContainingFile())); oldToNewElementsMapping.put(element, newElement); element = newElement; @@ -461,7 +460,7 @@ public class MoveClassesOrPackagesProcessor extends BaseRefactoringProcessor { for (PsiElement element : myElementsToMove) { if (element instanceof PsiClass) { - ChangeContextUtil.decodeContextInfo(element, null, null); + MoveClassesOrPackagesUtil.finishMoveClass((PsiClass)element); } } diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesUtil.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesUtil.java index 90494fe0d2f0..931917201cb6 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesUtil.java @@ -207,6 +207,18 @@ public class MoveClassesOrPackagesUtil { } } + public static void prepareMoveClass(PsiClass aClass) { + for (MoveClassHandler handler : MoveClassHandler.EP_NAME.getExtensions()) { + handler.prepareMove(aClass); + } + } + + public static void finishMoveClass(PsiClass aClass) { + for (MoveClassHandler handler : MoveClassHandler.EP_NAME.getExtensions()) { + handler.finishMoveClass(aClass); + } + } + // Does not process non-code usages! public static PsiClass doMoveClass(PsiClass aClass, PsiDirectory moveDestination) throws IncorrectOperationException { PsiClass newClass; diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveJavaClassHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveJavaClassHandler.java index 585544210885..d5153e6e8f46 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveJavaClassHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveJavaClassHandler.java @@ -15,6 +15,7 @@ */ package com.intellij.refactoring.move.moveClassesOrPackages; +import com.intellij.codeInsight.ChangeContextUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.psi.*; @@ -32,6 +33,20 @@ import java.util.Set; public class MoveJavaClassHandler implements MoveClassHandler { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.move.moveClassesOrPackages.MoveJavaClassHandler"); + @Override + public void finishMoveClass(@NotNull PsiClass aClass) { + if (aClass.getContainingFile() instanceof PsiJavaFile) { + ChangeContextUtil.decodeContextInfo(aClass, null, null); + } + } + + @Override + public void prepareMove(@NotNull PsiClass aClass) { + if (aClass.getContainingFile() instanceof PsiJavaFile) { + ChangeContextUtil.encodeContextInfo(aClass, true); + } + } + public PsiClass doMoveClass(@NotNull final PsiClass aClass, @NotNull PsiDirectory moveDestination) throws IncorrectOperationException { PsiFile file = aClass.getContainingFile(); final PsiPackage newPackage = JavaDirectoryService.getInstance().getPackage(moveDestination); diff --git a/java/java-impl/src/com/intellij/refactoring/typeCook/deductive/resolver/BindingFactory.java b/java/java-impl/src/com/intellij/refactoring/typeCook/deductive/resolver/BindingFactory.java index b2ca2440fb44..922869ef2622 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeCook/deductive/resolver/BindingFactory.java +++ b/java/java-impl/src/com/intellij/refactoring/typeCook/deductive/resolver/BindingFactory.java @@ -203,8 +203,10 @@ public class BindingFactory { return null; } - b3.myBindings.put(i, type); - b3.myCyclic = type instanceof PsiTypeVariable; + if (type != PsiType.NULL) { + b3.myBindings.put(i, type); + b3.myCyclic = type instanceof PsiTypeVariable; + } } break; @@ -216,8 +218,10 @@ public class BindingFactory { return null; } - b3.myBindings.put(i, type); - b3.myCyclic = type instanceof PsiTypeVariable; + if (type != PsiType.NULL) { + b3.myBindings.put(i, type); + b3.myCyclic = type instanceof PsiTypeVariable; + } } break; @@ -234,12 +238,11 @@ public class BindingFactory { return null; } - if (type == null) { - return null; + if (type != PsiType.NULL) { + b3.myBindings.put(i, type); + b3.myCyclic = type instanceof PsiTypeVariable; } - b3.myBindings.put(i, type); - b3.myCyclic = type instanceof PsiTypeVariable; } } } diff --git a/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java b/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java index ca2ac72bb928..a605ca4a8125 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java @@ -53,7 +53,7 @@ public class InlineUtil { initializer = RefactoringUtil.convertInitializerToNormalExpression(initializer, varType); ChangeContextUtil.encodeContextInfo(initializer, false); - PsiExpression expr = (PsiExpression)ref.replace(initializer); + PsiExpression expr = (PsiExpression)replaceDiamondWithInferredTypesIfNeeded(initializer, ref); PsiType exprType = expr.getType(); if (exprType != null && (!varType.equals(exprType) && varType instanceof PsiPrimitiveType || !TypeConversionUtil.isAssignable(varType, exprType))) { @@ -315,6 +315,46 @@ public class InlineUtil { }); } + private static PsiElement replaceDiamondWithInferredTypesIfNeeded(PsiExpression initializer, PsiElement ref) { + if (initializer instanceof PsiNewExpression) { + final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)initializer).getClassOrAnonymousClassReference(); + if (classReference != null) { + final PsiReferenceParameterList parameterList = classReference.getParameterList(); + if (parameterList != null) { + final PsiTypeElement[] typeParameterElements = parameterList.getTypeParameterElements(); + if (typeParameterElements.length == 1) { + final PsiType type = typeParameterElements[0].getType(); + if (type instanceof PsiDiamondType) { + final PsiDiamondType.DiamondInferenceResult inferenceResult = ((PsiDiamondType)type).resolveInferredTypes(); + if (inferenceResult.getErrorMessage() == null) { + final PsiElement copy = ref.copy(); + final PsiElement parent = ref.replace(initializer); + final PsiDiamondType.DiamondInferenceResult result = PsiDiamondType.resolveInferredTypes((PsiNewExpression)initializer, parent); + ref = parent.replace(copy); + if (!result.equals(inferenceResult)) { + final String inferredTypeText = StringUtil.join(inferenceResult.getTypes(), + new Function() { + @Override + public String fun(PsiType psiType) { + return psiType.getCanonicalText(); + } + }, ", "); + final PsiExpressionList argumentList = ((PsiNewExpression)initializer).getArgumentList(); + if (argumentList != null) { + final PsiExpression expression = JavaPsiFacade.getElementFactory(initializer.getProject()) + .createExpressionFromText("new " + classReference.getReferenceName() + "<" + inferredTypeText + ">" + argumentList.getText(), initializer); + return ref.replace(expression); + } + } + } + } + } + } + } + } + return ref.replace(initializer); + } + public enum TailCallType { None, Simple, Return } diff --git a/java/java-tests/testData/codeInsight/completion/normal/ClassAngleBracket.java b/java/java-tests/testData/codeInsight/completion/normal/ClassAngleBracket.java new file mode 100644 index 000000000000..89fff3a6c574 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ClassAngleBracket.java @@ -0,0 +1,6 @@ +class AbcdClass {} +class AbcdeClass {} + +class Foo { + Abcd +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/ClassAngleBracket_after.java b/java/java-tests/testData/codeInsight/completion/normal/ClassAngleBracket_after.java new file mode 100644 index 000000000000..ab3dc849b411 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ClassAngleBracket_after.java @@ -0,0 +1,6 @@ +class AbcdClass {} +class AbcdeClass {} + +class Foo { + AbcdClass<> +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/ClassSquareBracket.java b/java/java-tests/testData/codeInsight/completion/normal/ClassSquareBracket.java new file mode 100644 index 000000000000..89fff3a6c574 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ClassSquareBracket.java @@ -0,0 +1,6 @@ +class AbcdClass {} +class AbcdeClass {} + +class Foo { + Abcd +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/ClassSquareBracket_after.java b/java/java-tests/testData/codeInsight/completion/normal/ClassSquareBracket_after.java new file mode 100644 index 000000000000..03944aa60a36 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ClassSquareBracket_after.java @@ -0,0 +1,6 @@ +class AbcdClass {} +class AbcdeClass {} + +class Foo { + AbcdClass[] +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/MethodSquareBracket.java b/java/java-tests/testData/codeInsight/completion/normal/MethodSquareBracket.java new file mode 100644 index 000000000000..810337061123 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/MethodSquareBracket.java @@ -0,0 +1,9 @@ +class Foo { + int[] aaaa(int x){} + int[] aaab(){} + + + { + aaa + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/MethodSquareBracket_after.java b/java/java-tests/testData/codeInsight/completion/normal/MethodSquareBracket_after.java new file mode 100644 index 000000000000..e563262eb2a6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/MethodSquareBracket_after.java @@ -0,0 +1,9 @@ +class Foo { + int[] aaaa(int x){} + int[] aaab(){} + + + { + aaaa()[] + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/PrimitiveSquareBracket.java b/java/java-tests/testData/codeInsight/completion/normal/PrimitiveSquareBracket.java new file mode 100644 index 000000000000..31513c1ce7b9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/PrimitiveSquareBracket.java @@ -0,0 +1,5 @@ +class Foo { + d + + class doz {} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/PrimitiveSquareBracket_after.java b/java/java-tests/testData/codeInsight/completion/normal/PrimitiveSquareBracket_after.java new file mode 100644 index 000000000000..0be62feb89b1 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/PrimitiveSquareBracket_after.java @@ -0,0 +1,5 @@ +class Foo { + double[] + + class doz {} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/SpaceAfterLookupString_after.java b/java/java-tests/testData/codeInsight/completion/normal/SpaceAfterLookupString_after.java index 61c3e21af605..13d4c7a2afe0 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/SpaceAfterLookupString_after.java +++ b/java/java-tests/testData/codeInsight/completion/normal/SpaceAfterLookupString_after.java @@ -3,7 +3,7 @@ class Foo { { String abc; String abcdef; - abc d + abc d } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/VariableSquareBracket.java b/java/java-tests/testData/codeInsight/completion/normal/VariableSquareBracket.java new file mode 100644 index 000000000000..ebff9d951901 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/VariableSquareBracket.java @@ -0,0 +1,7 @@ +class Foo { + { + int[] aaaa; + int[] aaab; + aa + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/VariableSquareBracket_after.java b/java/java-tests/testData/codeInsight/completion/normal/VariableSquareBracket_after.java new file mode 100644 index 000000000000..84538649bbe4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/VariableSquareBracket_after.java @@ -0,0 +1,7 @@ +class Foo { + { + int[] aaaa; + int[] aaab; + aaaa[] + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/PreferModifiers.java b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferModifiers.java new file mode 100644 index 000000000000..c3348c249c2f --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferModifiers.java @@ -0,0 +1,9 @@ +public class Test { + + p + + class paaa {} + + static class paab {} + +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java index 1258a5350bf8..b7398235bd51 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java @@ -3,6 +3,7 @@ import java.util.List; class Test { List queue = new ArrayList<>(); + ArrayList l = new ArrayList<>(8); } class DD { @@ -73,3 +74,24 @@ class NonParameterized { new NonParameterized<>(); } } + + +interface I { + T m(); +} + +class FI1 { + I i1 = new I<>() { + @Override + public String m() { + return null; + } + }; + + I i2 = new I<>() { + @Override + public Object m() { + return null; + } + }; +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See0.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See0.java new file mode 100644 index 000000000000..5b7edc9ba85d --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See0.java @@ -0,0 +1,15 @@ +package pkg; + +/** + * @see #method(pkg.B0.C[]) + * @see #method(B0.C[]) + * @see #method(B0.C...) + */ +class A0 { + public void method(B0.C[] c) { } +} + +class B0 { + class C { + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See1.java new file mode 100644 index 000000000000..24d1dae563da --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See1.java @@ -0,0 +1,16 @@ +package pkg; + +/** + * @see #method(B1.C) + * @see #method(B1.C[][]) + * @see #method(B1.C..) + * @see #method(B1.C[) + */ +class A1 { + public void method(B1.C[] c) { } +} + +class B1 { + class C { + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See2.java new file mode 100644 index 000000000000..e3d607e09b70 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See2.java @@ -0,0 +1,13 @@ +package pkg; + +import java.util.List; + +/** + * @see #method(java.util.List) + * @see #method(java.util.List) + * @see #method(java.util.List) + * @see #method(java.util.List) + */ +class A2 { + public void method(List list) { } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/before33.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/before33.java new file mode 100644 index 000000000000..a032ae65d80c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/before33.java @@ -0,0 +1,12 @@ +// "Make 'e' not final" "false" + +class C { + static { + try { + throw new Exception(); + } + catch (RuntimeException | IOException e) { + e = null; + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/before34.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/before34.java new file mode 100644 index 000000000000..4aca069684c6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/before34.java @@ -0,0 +1,9 @@ +// "Make 'r' not final" "false" + +class C { + void m() throws Exception { + try (AutoCloseable r = null) { + r = null; + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/before35.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/before35.java new file mode 100644 index 000000000000..1bee6da0d391 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/before35.java @@ -0,0 +1,16 @@ +// "Make 'e' final" "false" + +class C { + static { + try { + throw new Exception(); + } + catch (RuntimeException | IOException e) { + new Runnable() { + public void run() { + System.out.println(e); + } + }.run(); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/before36.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/before36.java new file mode 100644 index 000000000000..04c4cdd30653 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier/before36.java @@ -0,0 +1,13 @@ +// "Make 'r' final" "false" + +class C { + void m() throws Exception { + try (AutoCloseable r = null) { + new Runnable() { + public void run() { + System.out.println(r); + } + }.run(); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/inlineLocal/NewExpressionWithDiamond.java b/java/java-tests/testData/refactoring/inlineLocal/NewExpressionWithDiamond.java new file mode 100644 index 000000000000..b5630a408bbd --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineLocal/NewExpressionWithDiamond.java @@ -0,0 +1,9 @@ +import java.util.*; + +class Test { + + void foo(){ + Map map = new HashMap<>(); + System.out.println(map); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/inlineLocal/NewExpressionWithDiamond.java.after b/java/java-tests/testData/refactoring/inlineLocal/NewExpressionWithDiamond.java.after new file mode 100644 index 000000000000..2b1d4fde39fe --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineLocal/NewExpressionWithDiamond.java.after @@ -0,0 +1,8 @@ +import java.util.*; + +class Test { + + void foo(){ + System.out.println(new HashMap()); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/inlineLocal/NewExpressionWithPreservedDiamond.java b/java/java-tests/testData/refactoring/inlineLocal/NewExpressionWithPreservedDiamond.java new file mode 100644 index 000000000000..786d23a2e7f7 --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineLocal/NewExpressionWithPreservedDiamond.java @@ -0,0 +1,9 @@ +import java.util.*; + +class Test { + + void foo(){ + Map map = new HashMap<>(); + Map map1 = map; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/inlineLocal/NewExpressionWithPreservedDiamond.java.after b/java/java-tests/testData/refactoring/inlineLocal/NewExpressionWithPreservedDiamond.java.after new file mode 100644 index 000000000000..eb76943ecdac --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineLocal/NewExpressionWithPreservedDiamond.java.after @@ -0,0 +1,8 @@ +import java.util.*; + +class Test { + + void foo(){ + Map map1 = new HashMap<>(); + } +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaTypedHandlerUtil.java b/java/java-tests/testData/refactoring/introduceParameter/afterEnclosingWithParamDeletion.java similarity index 54% rename from java/java-impl/src/com/intellij/codeInsight/editorActions/JavaTypedHandlerUtil.java rename to java/java-tests/testData/refactoring/introduceParameter/afterEnclosingWithParamDeletion.java index a64ab058d973..1216026ab11f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaTypedHandlerUtil.java +++ b/java/java-tests/testData/refactoring/introduceParameter/afterEnclosingWithParamDeletion.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,18 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.codeInsight.editorActions; - -import com.intellij.psi.tree.IElementType; -import com.intellij.psi.JavaTokenType; - -public class JavaTypedHandlerUtil { - private JavaTypedHandlerUtil() { +class AAAA { + void foo() { + sampleEnclosing("A" + ""); } - public static boolean isTokenInvalidInsideReference(final IElementType tokenType) { - return tokenType == JavaTokenType.SEMICOLON || - tokenType == JavaTokenType.LBRACE || - tokenType == JavaTokenType.RBRACE; + private void sampleEnclosing(final String anObject) { + new AAAA() { + void bar() { + System.out.println(anObject); + } + }.bar(); } } diff --git a/java/java-tests/testData/refactoring/introduceParameter/beforeEnclosingWithParamDeletion.java b/java/java-tests/testData/refactoring/introduceParameter/beforeEnclosingWithParamDeletion.java new file mode 100644 index 000000000000..231920153098 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceParameter/beforeEnclosingWithParamDeletion.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * 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. + */ +class AAAA { + void foo() { + sampleEnclosing("A"); + } + + private void sampleEnclosing(final String s) { + new AAAA() { + void bar() { + System.out.println(s + ""); + } + }.bar(); + } +} diff --git a/java/java-tests/testData/refactoring/typeCook/t152/after/Test.1.items b/java/java-tests/testData/refactoring/typeCook/t152/after/Test.1.items new file mode 100644 index 000000000000..a8f3261e48c0 --- /dev/null +++ b/java/java-tests/testData/refactoring/typeCook/t152/after/Test.1.items @@ -0,0 +1,2 @@ +java.util.ArrayList\nPsiField:l +java.util.ArrayList\nnew diff --git a/java/java-tests/testData/refactoring/typeCook/t152/after/Test.items b/java/java-tests/testData/refactoring/typeCook/t152/after/Test.items new file mode 100644 index 000000000000..a8f3261e48c0 --- /dev/null +++ b/java/java-tests/testData/refactoring/typeCook/t152/after/Test.items @@ -0,0 +1,2 @@ +java.util.ArrayList\nPsiField:l +java.util.ArrayList\nnew diff --git a/java/java-tests/testData/refactoring/typeCook/t152/after/test.java b/java/java-tests/testData/refactoring/typeCook/t152/after/test.java new file mode 100644 index 000000000000..41aa81d718e7 --- /dev/null +++ b/java/java-tests/testData/refactoring/typeCook/t152/after/test.java @@ -0,0 +1,6 @@ +import java.util.ArrayList; + +class Test +{ + ArrayList l = new ArrayList<>(8); +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/typeCook/t152/before/test.java b/java/java-tests/testData/refactoring/typeCook/t152/before/test.java new file mode 100644 index 000000000000..41aa81d718e7 --- /dev/null +++ b/java/java-tests/testData/refactoring/typeCook/t152/before/test.java @@ -0,0 +1,6 @@ +import java.util.ArrayList; + +class Test +{ + ArrayList l = new ArrayList<>(8); +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy index 5701157ce85b..6ab60c1f970d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy @@ -17,14 +17,20 @@ package com.intellij.codeInsight.completion import com.intellij.codeInsight.lookup.Lookup import com.intellij.codeInsight.lookup.LookupManager +import com.intellij.ide.DataManager import com.intellij.ide.ui.UISettings import com.intellij.openapi.actionSystem.IdeActions import com.intellij.openapi.command.CommandProcessor +import com.intellij.openapi.command.WriteCommandAction +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.editor.EditorFactory +import com.intellij.openapi.editor.actionSystem.EditorActionManager import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.extensions.LoadingOrder import com.intellij.openapi.progress.ProgressManager +import com.intellij.psi.PsiFile -/** + /** * @author peter */ class JavaAutoPopupTest extends CompletionAutoPopupTestCase { @@ -572,4 +578,40 @@ public interface Test { assert !lookup } + public void testTypingInAnotherEditor() { + myFixture.configureByText("a.java", "") + type 'c' + assert lookup + + Editor another = null + def wca = new WriteCommandAction.Simple(getProject(), new PsiFile[0]) { + @Override + protected void run() { + EditorActionManager.instance.getTypedAction().handler.execute(another, (char) 'x', DataManager.instance.dataContext) + } + } + + try { + edt { + lookup.hide() + def file = myFixture.addFileToProject("b.java", "") + another = EditorFactory.instance.createEditor(file.viewProvider.document, project) + wca.execute() + assert 'x' == another.document.text + } + joinAlarm() + joinCompletion() + def l1 = LookupManager.getActiveLookup(another) + if (l1) { + assert false : l1.items + } + type 'l' + assert lookup + } + finally { + edt { EditorFactory.instance.releaseEditor(another) } + } + + } + } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.java index 6324ba539edf..521469010051 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.java @@ -95,11 +95,11 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase { } public void testClassStaticMembersInVoidContext() throws Throwable { - checkPreferredItems(0, "booleanMethod", "voidMethod", "AN_OBJECT", "BOOLEAN", "Inner"); + checkPreferredItems(0, "booleanMethod", "voidMethod", "AN_OBJECT", "BOOLEAN", "class"); } public void testClassStaticMembersInBooleanContext() throws Throwable { - checkPreferredItems(0, "booleanMethod", "voidMethod", "BOOLEAN", "AN_OBJECT", "Inner"); + checkPreferredItems(0, "booleanMethod", "voidMethod", "BOOLEAN", "AN_OBJECT", "class"); } public void testDispreferDeclared() throws Throwable { @@ -213,4 +213,8 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase { checkPreferredItems(0, "return", "rLocal", "rParam", "rMethod"); } + public void testPreferModifiers() { + checkPreferredItems(0, "private", "protected", "public", "paaa", "paab"); + } + } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index 753a551e8ec0..5ba19599a8cc 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -569,13 +569,7 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase { configureByFile(getTestName(false) + ".java"); final int parametersCount = ((PsiMethod)getLookup().getCurrentItem().getObject()).getParameterList().getParametersCount(); assertEquals(0, parametersCount); - new WriteCommandAction.Simple(getProject(), new PsiFile[0]) { - @Override - protected void run() throws Throwable { - getLookup().finishLookup(Lookup.NORMAL_SELECT_CHAR); - } - }.execute().throwException(); - + type '\n' checkResult() } @@ -834,6 +828,13 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase { public void testCommaAfterVariable() throws Throwable { doTest(',') } + public void testClassAngleBracket() throws Throwable { doTest('<') } + + public void testClassSquareBracket() throws Throwable { doTest('[') } + public void testPrimitiveSquareBracket() throws Throwable { doTest('[') } + public void testVariableSquareBracket() throws Throwable { doTest('[') } + public void testMethodSquareBracket() throws Throwable { doTest('[') } + public void testSuperProtectedMethod() throws Throwable { myFixture.addClass """package foo; public class Bar { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java index 6b2196793939..3d9e95cfcdcd 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java @@ -79,21 +79,21 @@ public class AdvHighlightingTest extends DaemonAnalyzerTestCase { public void testImportDefaultPackage2() throws Exception { doTest(BASE_PATH+"/importDefaultPackage/x/ImportOnDemandUsage.java", BASE_PATH+"/importDefaultPackage", false, false); } public void testScopeBased() throws Exception { - NamedScope xscope = new NamedScope("xxx", new PatternPackageSet("x..*", PatternPackageSet.SCOPE_SOURCE, null)); - NamedScope utilscope = new NamedScope("util", new PatternPackageSet("java.util.*", PatternPackageSet.SCOPE_LIBRARY, null)); + NamedScope xScope = new NamedScope("xxx", new PatternPackageSet("x..*", PatternPackageSet.SCOPE_SOURCE, null)); + NamedScope utilScope = new NamedScope("util", new PatternPackageSet("java.util.*", PatternPackageSet.SCOPE_LIBRARY, null)); NamedScopeManager scopeManager = NamedScopeManager.getInstance(getProject()); - scopeManager.addScope(xscope); - scopeManager.addScope(utilscope); + scopeManager.addScope(xScope); + scopeManager.addScope(utilScope); EditorColorsManager manager = EditorColorsManager.getInstance(); EditorColorsScheme scheme = (EditorColorsScheme)manager.getGlobalScheme().clone(); manager.addColorsScheme(scheme); EditorColorsManager.getInstance().setGlobalScheme(scheme); - TextAttributesKey xKey = ColorAndFontOptions.getScopeTextAttributeKey(xscope.getName()); + TextAttributesKey xKey = ColorAndFontOptions.getScopeTextAttributeKey(xScope.getName()); TextAttributes xAttributes = new TextAttributes(Color.cyan, Color.darkGray, Color.blue, EffectType.BOXED, Font.ITALIC); scheme.setAttributes(xKey, xAttributes); - TextAttributesKey utilKey = ColorAndFontOptions.getScopeTextAttributeKey(utilscope.getName()); + TextAttributesKey utilKey = ColorAndFontOptions.getScopeTextAttributeKey(utilScope.getName()); TextAttributes utilAttributes = new TextAttributes(Color.gray, Color.magenta, Color.orange, EffectType.STRIKEOUT, Font.BOLD); scheme.setAttributes(utilKey, utilAttributes); @@ -105,21 +105,21 @@ public class AdvHighlightingTest extends DaemonAnalyzerTestCase { } } public void testSharedScopeBased() throws Exception { - NamedScope xscope = new NamedScope("xxx", new PatternPackageSet("x..*", PatternPackageSet.SCOPE_ANY, null)); - NamedScope utilscope = new NamedScope("util", new PatternPackageSet("java.util.*", PatternPackageSet.SCOPE_LIBRARY, null)); + NamedScope xScope = new NamedScope("xxx", new PatternPackageSet("x..*", PatternPackageSet.SCOPE_ANY, null)); + NamedScope utilScope = new NamedScope("util", new PatternPackageSet("java.util.*", PatternPackageSet.SCOPE_LIBRARY, null)); NamedScopesHolder scopeManager = DependencyValidationManager.getInstance(getProject()); - scopeManager.addScope(xscope); - scopeManager.addScope(utilscope); + scopeManager.addScope(xScope); + scopeManager.addScope(utilScope); EditorColorsManager manager = EditorColorsManager.getInstance(); EditorColorsScheme scheme = (EditorColorsScheme)manager.getGlobalScheme().clone(); manager.addColorsScheme(scheme); EditorColorsManager.getInstance().setGlobalScheme(scheme); - TextAttributesKey xKey = ColorAndFontOptions.getScopeTextAttributeKey(xscope.getName()); + TextAttributesKey xKey = ColorAndFontOptions.getScopeTextAttributeKey(xScope.getName()); TextAttributes xAttributes = new TextAttributes(Color.cyan, Color.darkGray, Color.blue, null, Font.ITALIC); scheme.setAttributes(xKey, xAttributes); - TextAttributesKey utilKey = ColorAndFontOptions.getScopeTextAttributeKey(utilscope.getName()); + TextAttributesKey utilKey = ColorAndFontOptions.getScopeTextAttributeKey(utilScope.getName()); TextAttributes utilAttributes = new TextAttributes(Color.gray, Color.magenta, Color.orange, EffectType.STRIKEOUT, Font.BOLD); scheme.setAttributes(utilKey, utilAttributes); @@ -158,6 +158,7 @@ public class AdvHighlightingTest extends DaemonAnalyzerTestCase { } }); + assert root != null; configureByExistingFile(root.findFileByRelativePath("moduleJava5/com/Java5.java")); Collection infos = highlightErrors(); assertEmpty(infos); @@ -168,6 +169,7 @@ public class AdvHighlightingTest extends DaemonAnalyzerTestCase { VirtualFile root = LocalFileSystem.getInstance().findFileByIoFile(new File(path)); loadAllModulesUnder(root); + assert root != null; configureByExistingFile(root.findFileByRelativePath("client/src/BugTest.java")); Collection infos = highlightErrors(); assertEmpty(infos); @@ -178,12 +180,18 @@ public class AdvHighlightingTest extends DaemonAnalyzerTestCase { VirtualFile root = LocalFileSystem.getInstance().findFileByIoFile(new File(path)); loadAllModulesUnder(root); + assert root != null; configureByExistingFile(root.findFileByRelativePath("src/ppp/SomeClass.java")); PsiField field = ((PsiJavaFile)myFile).getClasses()[0].findFieldByName("f", false); + assert field != null; PsiClass aClass = ((PsiClassType)field.getType()).resolve(); + assert aClass != null; assertEquals("ppp.BadClass", aClass.getQualifiedName()); //lies in source - assertEquals(myFile.getVirtualFile().getParent(), aClass.getContainingFile().getVirtualFile().getParent()); + final VirtualFile vFile1 = myFile.getVirtualFile(); + final VirtualFile vFile2 = aClass.getContainingFile().getVirtualFile(); + assert vFile1 != null; + assert vFile2 != null; + assertEquals(vFile1.getParent(), vFile2.getParent()); } - } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java index 765ac83ce899..5dc0bd3c99dd 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java @@ -4,8 +4,6 @@ import com.intellij.JavaTestUtil; import com.intellij.codeInspection.LocalInspectionTool; import com.intellij.codeInspection.javaDoc.JavaDocLocalInspection; import com.intellij.codeInspection.javaDoc.JavaDocReferenceInspection; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.pom.java.LanguageLevel; @@ -47,9 +45,7 @@ public class JavadocHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } - public void testInlineTagAsDescription() throws Exception { - doTest(); - } + public void testInlineTagAsDescription() throws Exception { doTest(); } public void testParam0() throws Exception { doTestWithLangLevel(LanguageLevel.HIGHEST); } public void testParam1() throws Exception { doTest(); } @@ -62,8 +58,8 @@ public class JavadocHighlightingTest extends LightDaemonAnalyzerTestCase { public void testSee3() throws Exception { doTest(); } public void testSee4() throws Exception { doTest(); } public void testSee5() throws Exception { doTest(); } - public void testSee6() throws Exception {doTest();} - public void testSeeConstants() throws Exception { doTest();} + public void testSee6() throws Exception { doTest(); } + public void testSeeConstants() throws Exception { doTest(); } public void testReturn0() throws Exception { doTest(); } public void testException0() throws Exception { doTest(); } public void testException1() throws Exception { doTest(); } @@ -73,7 +69,7 @@ public class JavadocHighlightingTest extends LightDaemonAnalyzerTestCase { public void testMultipleThrows() throws Exception { doTest(); } public void testInheritJavaDoc() throws Exception {doTestWithLangLevel(LanguageLevel.JDK_1_3);} public void testLink0() throws Exception { doTest(); } - public void testLinkFromInnerClassToSelfMethod() throws Exception {doTest();} + public void testLinkFromInnerClassToSelfMethod() throws Exception { doTest(); } public void testValueBadReference() throws Exception { doTestWithLangLevel(LanguageLevel.HIGHEST); } public void testValueGoodReference() throws Exception { doTestWithLangLevel(LanguageLevel.HIGHEST); } @@ -83,20 +79,18 @@ public class JavadocHighlightingTest extends LightDaemonAnalyzerTestCase { public void testValueNotOnStaticField() throws Exception { doTestWithLangLevel(LanguageLevel.HIGHEST); } public void testValueOnNotInitializedField() throws Exception { doTestWithLangLevel(LanguageLevel.HIGHEST); } - public void testUnknownInlineTag() throws Exception {doTest();} - public void testUnknownTags() throws Exception {doTest();} + public void testUnknownInlineTag() throws Exception { doTest(); } + public void testUnknownTags() throws Exception { doTest(); } - public void testBadCharacters() throws Exception {doTest();} + public void testBadCharacters() throws Exception { doTest(); } - public void testVararg() throws Exception {doTest();} + public void testVararg() throws Exception { doTest(); } - public void testInnerClassReferenceInSignature() throws Exception {doTest();} + public void testInnerClassReferenceInSignature() throws Exception { doTest(); } - public void testBadReference() throws Exception{ - doTest(); - } + public void testBadReference() throws Exception { doTest(); } - public void testMissingReturnDescription() throws Exception {doTest();} + public void testMissingReturnDescription() throws Exception { doTest(); } private void doTestWithLangLevel(final LanguageLevel langLevel) throws Exception { LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(langLevel); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocResolveTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocResolveTest.java new file mode 100644 index 000000000000..6b2be0270645 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocResolveTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * 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.intellij.codeInsight.daemon; + +import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.codeInspection.javaDoc.JavaDocLocalInspection; +import com.intellij.codeInspection.javaDoc.JavaDocReferenceInspection; + +public class JavadocResolveTest extends DaemonAnalyzerTestCase { + private static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/javaDoc/resolve"; + + @Override + protected LocalInspectionTool[] configureLocalInspectionTools() { + return new LocalInspectionTool[]{new JavaDocLocalInspection(), new JavaDocReferenceInspection()}; + } + + public void testSee0() throws Exception { doTest(); } + public void testSee1() throws Exception { doTest(); } + public void testSee2() throws Exception { doTest(); } + + private void doTest() throws Exception { + doTest(BASE_PATH + "/pkg/" + getTestName(false) + ".java", BASE_PATH, false, false); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ModifierTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ModifierTest.java index 0100ec65de47..c0eaeb8c1352 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ModifierTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ModifierTest.java @@ -8,4 +8,3 @@ public class ModifierTest extends LightQuickFixTestCase { return "/codeInsight/daemonCodeAnalyzer/quickFix/modifier"; } } - diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Simplify2DiamondInspectionsTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Simplify2DiamondInspectionsTest.java index 8667fdfcd617..76136b5fb8ef 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Simplify2DiamondInspectionsTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Simplify2DiamondInspectionsTest.java @@ -17,17 +17,6 @@ package com.intellij.codeInsight.daemon.quickFix; import com.intellij.codeInspection.ExplicitTypeCanBeDiamondInspection; import com.intellij.codeInspection.LocalInspectionTool; -import com.intellij.codeInspection.accessStaticViaInstance.AccessStaticViaInstance; -import com.intellij.codeInspection.deprecation.DeprecationInspection; -import com.intellij.codeInspection.ex.GlobalInspectionToolWrapper; -import com.intellij.codeInspection.javaDoc.JavaDocReferenceInspection; -import com.intellij.codeInspection.sillyAssignment.SillyAssignmentInspection; -import com.intellij.codeInspection.uncheckedWarnings.UncheckedWarningLocalInspection; -import com.intellij.codeInspection.unneededThrows.RedundantThrowsDeclaration; -import com.intellij.codeInspection.unusedParameters.UnusedParametersInspection; -import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; //todo test3 should be checked if it compiles - as now javac infers Object instead of String?! diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterTest.java index c193eeae4d9e..30481aacf6ca 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterTest.java @@ -28,6 +28,8 @@ import gnu.trove.TIntArrayList; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; +import java.util.List; + @TestDataPath("$CONTENT_ROOT/testData") public class IntroduceParameterTest extends LightCodeInsightTestCase { @Override @@ -270,6 +272,12 @@ public class IntroduceParameterTest extends LightCodeInsightTestCase { checkResultByFile("/refactoring/introduceParameter/after" + getTestName(false) + ".java"); } + public void testEnclosingWithParamDeletion() throws Exception { + configureByFile("/refactoring/introduceParameter/before" + getTestName(false) + ".java"); + perform(true, 0, "anObject", false, true, true, false, 1); + checkResultByFile("/refactoring/introduceParameter/after" + getTestName(false) + ".java"); + } + private static boolean perform(boolean replaceAllOccurences, int replaceFieldsWithGetters, @NonNls String parameterName, @@ -277,6 +285,18 @@ public class IntroduceParameterTest extends LightCodeInsightTestCase { boolean declareFinal, final boolean removeUnusedParameters, final boolean generateDelegate) { + return perform(replaceAllOccurences, replaceFieldsWithGetters, parameterName, searchForSuper, declareFinal, removeUnusedParameters, + generateDelegate, 0); + } + + private static boolean perform(boolean replaceAllOccurences, + int replaceFieldsWithGetters, + @NonNls String parameterName, + boolean searchForSuper, + boolean declareFinal, + final boolean removeUnusedParameters, + final boolean generateDelegate, + int enclosingLevel) { int startOffset = myEditor.getSelectionModel().getSelectionStart(); int endOffset = myEditor.getSelectionModel().getSelectionEnd(); @@ -294,6 +314,10 @@ public class IntroduceParameterTest extends LightCodeInsightTestCase { PsiMethod method = Util.getContainingMethod(context); if (method == null) return false; + final List methods = IntroduceParameterHandler.getEnclosingMethods(method); + assertTrue(methods.size() > enclosingLevel); + method = methods.get(enclosingLevel); + final PsiMethod methodToSearchFor; if (searchForSuper) { methodToSearchFor = method.findDeepestSuperMethod(); diff --git a/java/java-tests/testSrc/com/intellij/refactoring/TypeCookTest.java b/java/java-tests/testSrc/com/intellij/refactoring/TypeCookTest.java index 9fea974ce682..a27d64bdceb8 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/TypeCookTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/TypeCookTest.java @@ -648,6 +648,10 @@ public class TypeCookTest extends MultiFileTestCase { start(); } + public void testT152() throws Exception { + start(); + } + public void start() throws Exception { start(false); } diff --git a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLocalTest.java b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLocalTest.java index adf2b4571e95..c0e4cb1784b3 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLocalTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLocalTest.java @@ -70,6 +70,14 @@ public class InlineLocalTest extends LightCodeInsightTestCase { doTest(false); } + public void testNewExpressionWithDiamond() throws Exception { + doTest(false); + } + + public void testNewExpressionWithPreservedDiamond() throws Exception { + doTest(false); + } + public void testAugmentedAssignment() throws Exception { String exception = null; try { diff --git a/java/openapi/src/com/intellij/psi/PsiDiamondType.java b/java/openapi/src/com/intellij/psi/PsiDiamondType.java index 5b1488918a12..0abeb3a0134f 100644 --- a/java/openapi/src/com/intellij/psi/PsiDiamondType.java +++ b/java/openapi/src/com/intellij/psi/PsiDiamondType.java @@ -18,11 +18,13 @@ package com.intellij.psi; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; +import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -97,6 +99,11 @@ public class PsiDiamondType extends PsiType { } public static DiamondInferenceResult resolveInferredTypes(PsiNewExpression newExpression) { + return resolveInferredTypes(newExpression, newExpression); + } + + public static DiamondInferenceResult resolveInferredTypes(PsiNewExpression newExpression, + PsiElement context) { final PsiClass psiClass = findClass(newExpression); if (psiClass == null) return DiamondInferenceResult.NULL_RESULT; final PsiExpressionList argumentList = newExpression.getArgumentList(); @@ -107,12 +114,12 @@ public class PsiDiamondType extends PsiType { if (staticFactory == null) { return DiamondInferenceResult.NULL_RESULT; } - final PsiSubstitutor inferredSubstitutor = inferTypeParametersForStaticFactory(staticFactory, newExpression); + final PsiSubstitutor inferredSubstitutor = inferTypeParametersForStaticFactory(staticFactory, newExpression, context); final PsiTypeParameter[] parameters = staticFactory.getTypeParameters(); final PsiTypeParameter[] classParameters = psiClass.getTypeParameters(); final PsiJavaCodeReferenceElement classOrAnonymousClassReference = newExpression.getClassOrAnonymousClassReference(); LOG.assertTrue(classOrAnonymousClassReference != null); - final DiamondInferenceResult result = new DiamondInferenceResult(classOrAnonymousClassReference.getReferenceName() + "<>"); + final DiamondInferenceResult result = new DiamondInferenceResult(classOrAnonymousClassReference.getReferenceName() + "<>", newExpression.getProject()); for (PsiTypeParameter parameter : parameters) { for (PsiTypeParameter classParameter : classParameters) { if (Comparing.strEqual(classParameter.getName(), parameter.getName())) { @@ -187,9 +194,10 @@ public class PsiDiamondType extends PsiType { } else { buf.append("(").append(StringUtil.join(constructor.getParameterList().getParameters(), new Function() { + int myIdx = 0; @Override public String fun(PsiParameter psiParameter) { - return psiParameter.getType().getCanonicalText() + " " + psiParameter.getName(); + return psiParameter.getType().getCanonicalText() + " p" + myIdx++; } }, ",")).append(")"); } @@ -209,14 +217,15 @@ public class PsiDiamondType extends PsiType { private static PsiSubstitutor inferTypeParametersForStaticFactory(@NotNull PsiMethod staticFactoryMethod, - PsiNewExpression expression) { + PsiNewExpression expression, + PsiElement parent) { final JavaPsiFacade facade = JavaPsiFacade.getInstance(staticFactoryMethod.getProject()); final PsiResolveHelper resolveHelper = facade.getResolveHelper(); final PsiParameter[] parameters = staticFactoryMethod.getParameterList().getParameters(); final PsiExpressionList argumentList = expression.getArgumentList(); final PsiExpression[] expressions = argumentList.getExpressions(); return resolveHelper - .inferTypeArguments(staticFactoryMethod.getTypeParameters(), parameters, expressions, PsiSubstitutor.EMPTY, expression, false); + .inferTypeArguments(staticFactoryMethod.getTypeParameters(), parameters, expressions, PsiSubstitutor.EMPTY, parent, false); } public static class DiamondInferenceResult { @@ -236,19 +245,36 @@ public class PsiDiamondType extends PsiType { private String myErrorMessage; private String myNewExpressionPresentableText; + private Project myProject; public DiamondInferenceResult() { } - public DiamondInferenceResult(String expressionPresentableText) { + public DiamondInferenceResult(String expressionPresentableText, Project project) { myNewExpressionPresentableText = expressionPresentableText; + myProject = project; } public PsiType[] getTypes() { if (myErrorMessage != null) { return NULL_TYPES; } - return myInferredTypes.toArray(new PsiType[myInferredTypes.size()]); + final PsiType[] result = new PsiType[myInferredTypes.size()]; + for (int i = 0, myInferredTypesSize = myInferredTypes.size(); i < myInferredTypesSize; i++) { + PsiType inferredType = myInferredTypes.get(i); + if (inferredType instanceof PsiWildcardType) { + final PsiType bound = ((PsiWildcardType)inferredType).getBound(); + result[i] = bound != null ? bound : PsiType.getJavaLangObject(PsiManager.getInstance(myProject), GlobalSearchScope.allScope(myProject)); + } + else { + result[i] = inferredType; + } + } + return result; + } + + public List getInferredTypes() { + return myInferredTypes; } public String getErrorMessage() { @@ -300,6 +326,26 @@ public class PsiDiamondType extends PsiType { } }); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + DiamondInferenceResult that = (DiamondInferenceResult)o; + + if (myErrorMessage != null ? !myErrorMessage.equals(that.myErrorMessage) : that.myErrorMessage != null) return false; + if (!myInferredTypes.equals(that.myInferredTypes)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myInferredTypes.hashCode(); + result = 31 * result + (myErrorMessage != null ? myErrorMessage.hashCode() : 0); + return result; + } } public static boolean hasDefaultConstructor(@NotNull final PsiClass psiClass) { diff --git a/java/openapi/src/com/intellij/psi/util/MethodSignature.java b/java/openapi/src/com/intellij/psi/util/MethodSignature.java index 8700d3ba3285..0e7496398166 100644 --- a/java/openapi/src/com/intellij/psi/util/MethodSignature.java +++ b/java/openapi/src/com/intellij/psi/util/MethodSignature.java @@ -23,16 +23,23 @@ import org.jetbrains.annotations.NotNull; /** * @author cdr */ - public interface MethodSignature { MethodSignature[] EMPTY_ARRAY = new MethodSignature[0]; - @NotNull PsiSubstitutor getSubstitutor(); - @NotNull String getName(); - /** - * already substituted - */ - @NotNull PsiType[] getParameterTypes(); - @NotNull PsiTypeParameter[] getTypeParameters(); - boolean isRaw(); + @NotNull + PsiSubstitutor getSubstitutor(); + + @NotNull + String getName(); + + /** + * @return array of parameter types (already substituted) + */ + @NotNull + PsiType[] getParameterTypes(); + + @NotNull + PsiTypeParameter[] getTypeParameters(); + + boolean isRaw(); } diff --git a/java/openapi/src/com/intellij/psi/util/MethodSignatureUtil.java b/java/openapi/src/com/intellij/psi/util/MethodSignatureUtil.java index 73318fb601a5..5a70a6862181 100644 --- a/java/openapi/src/com/intellij/psi/util/MethodSignatureUtil.java +++ b/java/openapi/src/com/intellij/psi/util/MethodSignatureUtil.java @@ -29,6 +29,8 @@ import java.util.Set; public class MethodSignatureUtil { + private MethodSignatureUtil() { } + public static final TObjectHashingStrategy METHOD_BASED_HASHING_STRATEGY = new TObjectHashingStrategy() { public int computeHashCode(final MethodSignatureBackedByPsiMethod signature) { @@ -40,9 +42,6 @@ public class MethodSignatureUtil { } }; - private MethodSignatureUtil() { - } - public static MethodSignature createMethodSignature(@NonNls @NotNull String name, @Nullable PsiParameterList parameterTypes, @Nullable PsiTypeParameterList typeParameterList, @@ -154,10 +153,12 @@ public class MethodSignatureUtil { return null; } + @Nullable public static PsiMethod findMethodBySignature(final PsiClass aClass, PsiMethod pattenMethod, boolean checkBases) { return findMethodBySignature(aClass, pattenMethod.getSignature(PsiSubstitutor.EMPTY), checkBases); } + @Nullable public static PsiMethod findMethodBySignature(final PsiClass aClass, MethodSignature methodSignature, boolean checkBases) { List> pairs = aClass.findMethodsAndTheirSubstitutorsByName(methodSignature.getName(), checkBases); for (Pair pair : pairs) { @@ -181,13 +182,17 @@ public class MethodSignatureUtil { return null; } + @Nullable public static PsiMethod findMethodBySuperMethod(final PsiClass aClass, PsiMethod method, final boolean checkBases) { List> pairs = aClass.findMethodsAndTheirSubstitutorsByName(method.getName(), checkBases); for (Pair pair : pairs) { PsiMethod candidate = pair.first; PsiSubstitutor substitutor = pair.second; MethodSignature candidateSignature = candidate.getSignature(substitutor); - PsiSubstitutor superSubstitutor = TypeConversionUtil.getClassSubstitutor(method.getContainingClass(), candidate.getContainingClass(), substitutor); + final PsiClass methodClass = method.getContainingClass(); + final PsiClass candidateClass = candidate.getContainingClass(); + if (methodClass == null || candidateClass == null) continue; + PsiSubstitutor superSubstitutor = TypeConversionUtil.getClassSubstitutor(methodClass, candidateClass, substitutor); if (superSubstitutor == null) continue; MethodSignature superSignature = method.getSignature(superSubstitutor); if (isSubsignature(superSignature, candidateSignature)) return candidate; @@ -206,41 +211,47 @@ public class MethodSignatureUtil { } public static boolean areParametersErasureEqual(PsiMethod method1, PsiMethod method2) { - return METHOD_PARAMETERS_ERASURE_EQUALITY.equals(method1.getSignature(PsiSubstitutor.EMPTY), - method2.getSignature(PsiSubstitutor.EMPTY)); + return areSignaturesErasureEqual(method1.getSignature(PsiSubstitutor.EMPTY), method2.getSignature(PsiSubstitutor.EMPTY)); + } + + public static boolean areSignaturesErasureEqual(MethodSignature signature1, MethodSignature signature2) { + return METHOD_PARAMETERS_ERASURE_EQUALITY.equals(signature1, signature2); } /** - * @param methodSignature - * @param superMethodSignature + * @param methodSignature method signature + * @param superMethodSignature super method signature * @return null if signatures do not match */ + @Nullable public static PsiSubstitutor getSuperMethodSignatureSubstitutor(MethodSignature methodSignature, MethodSignature superMethodSignature) { PsiSubstitutor result = getSuperMethodSignatureSubstitutorImpl(methodSignature, superMethodSignature); if (result == null) return null; - PsiTypeParameter[] methoTypeParameters = methodSignature.getTypeParameters(); + PsiTypeParameter[] methodTypeParameters = methodSignature.getTypeParameters(); PsiTypeParameter[] superTypeParameters = superMethodSignature.getTypeParameters(); PsiSubstitutor methodSubstitutor = methodSignature.getSubstitutor(); //check bounds - for (int i = 0; i < methoTypeParameters.length; i++) { - PsiTypeParameter methoTypeParameter = methoTypeParameters[i]; + for (int i = 0; i < methodTypeParameters.length; i++) { + PsiTypeParameter methodTypeParameter = methodTypeParameters[i]; PsiTypeParameter superTypeParameter = superTypeParameters[i]; - final Set methoSupers = new HashSet(); - for (PsiClassType methoSuper : methoTypeParameter.getSuperTypes()) { - methoSupers.add(methodSubstitutor.substitute(methoSuper)); + final Set methodSupers = new HashSet(); + for (PsiClassType methodSuper : methodTypeParameter.getSuperTypes()) { + methodSupers.add(methodSubstitutor.substitute(methodSuper)); } final Set superSupers = new HashSet(); for (PsiClassType superSuper : superTypeParameter.getSuperTypes()) { - superSupers.add(methodSubstitutor.substitute(PsiUtil.captureToplevelWildcards(result.substitute(superSuper), methoTypeParameter))); + superSupers.add(methodSubstitutor.substitute(PsiUtil.captureToplevelWildcards(result.substitute(superSuper), methodTypeParameter))); } - if (!methoSupers.equals(superSupers)) return null; + if (!methodSupers.equals(superSupers)) return null; } + return result; } + @Nullable private static PsiSubstitutor getSuperMethodSignatureSubstitutorImpl(MethodSignature methodSignature, MethodSignature superSignature) { // normalize generic method declarations: correlate type parameters // todo: correlate type params by name? @@ -336,5 +347,4 @@ public class MethodSignatureUtil { } return true; } - } diff --git a/java/testFramework/src/com/intellij/codeInsight/completion/CompletionAutoPopupTestCase.groovy b/java/testFramework/src/com/intellij/codeInsight/completion/CompletionAutoPopupTestCase.groovy index 42b0ce7f8a65..7ddc6eb88ff5 100644 --- a/java/testFramework/src/com/intellij/codeInsight/completion/CompletionAutoPopupTestCase.groovy +++ b/java/testFramework/src/com/intellij/codeInsight/completion/CompletionAutoPopupTestCase.groovy @@ -65,6 +65,7 @@ abstract class CompletionAutoPopupTestCase extends LightCodeInsightFixtureTestCa } Thread.sleep(10) } + printThreadDump() fail("Too long completion") } diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java index 121ad9908699..d03a74e5c619 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java @@ -133,12 +133,12 @@ public abstract class LightQuickFixTestCase extends LightDaemonAnalyzerTestCase texts.add(intentionAction.getText()); } Collection infos = quickFix.doHighlighting(); - fail("Action with text '" + text + "' is not available in test " + testFullPath+"\nAvailable actions: "+texts+"\n"+actions+"\nErrors:"+infos); + fail("Action with text '" + text + "' is not available in test " + testFullPath+"\nAvailable actions ("+texts.size()+"): "+texts+"\n"+actions+"\nInfos:"+infos); } } else { if (!actionShouldBeAvailable) { - fail("Action '" + text + "' is available in test " + testFullPath); + fail("Action '" + text + "' is available (but must not) in test " + testFullPath); } quickFix.invoke(action); UIUtil.dispatchAllInvocationEvents(); diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/InsertionContext.java b/platform/lang-api/src/com/intellij/codeInsight/completion/InsertionContext.java index d5c1627795b2..1a793de71178 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/InsertionContext.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/InsertionContext.java @@ -36,17 +36,18 @@ public class InsertionContext { private final PsiFile myFile; private final Editor myEditor; private Runnable myLaterRunnable; - private boolean myAddCompletionChar = true; + private boolean myAddCompletionChar; public InsertionContext(final OffsetMap offsetMap, final char completionChar, final LookupElement[] elements, @NotNull final PsiFile file, - @NotNull final Editor editor) { + @NotNull final Editor editor, final boolean addCompletionChar) { myOffsetMap = offsetMap; myCompletionChar = completionChar; myElements = elements; myFile = file; myEditor = editor; setTailOffset(editor.getCaretModel().getOffset()); + myAddCompletionChar = addCompletionChar; } public void setTailOffset(final int offset) { diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/HighlightDisplayKey.java b/platform/lang-api/src/com/intellij/codeInsight/daemon/HighlightDisplayKey.java index 3ccad92eb7c5..9f7d7212ce2c 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/daemon/HighlightDisplayKey.java +++ b/platform/lang-api/src/com/intellij/codeInsight/daemon/HighlightDisplayKey.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.codeInsight.daemon; import com.intellij.openapi.diagnostic.Logger; @@ -36,11 +35,12 @@ public class HighlightDisplayKey { private final String myName; private final String myID; - public static HighlightDisplayKey find(@NonNls @NotNull String name){ + public static HighlightDisplayKey find(@NonNls @NotNull final String name) { return ourNameToKeyMap.get(name); } - public static HighlightDisplayKey findById(@NonNls @NotNull String id){ + @Nullable + public static HighlightDisplayKey findById(@NonNls @NotNull final String id) { HighlightDisplayKey key = ourIdToKeyMap.get(id); if (key != null) return key; key = ourNameToKeyMap.get(id); @@ -49,7 +49,7 @@ public class HighlightDisplayKey { } @Nullable - public static HighlightDisplayKey register(@NonNls @NotNull String name) { + public static HighlightDisplayKey register(@NonNls @NotNull final String name) { if (find(name) != null) { LOG.info("Key with name \'" + name + "\' already registered"); return null; @@ -58,7 +58,14 @@ public class HighlightDisplayKey { } @Nullable - public static HighlightDisplayKey register(@NonNls @NotNull String name, @NotNull String displayName, @NotNull @NonNls String id){ + public static HighlightDisplayKey register(@NonNls @NotNull final String name, @NotNull final String displayName) { + return register(name, displayName, name); + } + + @Nullable + public static HighlightDisplayKey register(@NonNls @NotNull final String name, + @NotNull final String displayName, + @NotNull @NonNls final String id) { if (find(name) != null) { LOG.info("Key with name \'" + name + "\' already registered"); return null; @@ -69,19 +76,49 @@ public class HighlightDisplayKey { } @Nullable - public static HighlightDisplayKey register(@NonNls @NotNull String name, @NotNull String displayName) { - return register(name, displayName, name); + public static HighlightDisplayKey register(@NonNls @NotNull final String name, + @NonNls @NotNull final String displayName, + @NonNls @NotNull final String id, + @NonNls @Nullable final String alternativeID) { + final HighlightDisplayKey key = register(name, displayName, id); + if (alternativeID != null) { + ourKeyToAlternativeIDMap.put(key, alternativeID); + } + return key; } - public static String getDisplayNameByKey(@Nullable HighlightDisplayKey key){ + @NotNull + public static HighlightDisplayKey findOrRegister(@NonNls @NotNull String name, @NotNull final String displayName) { + return findOrRegister(name, displayName, null); + } + + @NotNull + public static HighlightDisplayKey findOrRegister(@NonNls @NotNull final String name, + @NotNull final String displayName, + @NonNls @Nullable final String id) { + HighlightDisplayKey key = find(name); + if (key == null) { + key = register(name, displayName, id != null ? id : name); + assert key != null : name; + } + return key; + } + + @Nullable + public static String getDisplayNameByKey(@Nullable HighlightDisplayKey key) { return key == null ? null : ourKeyToDisplayNameMap.get(key); } - private HighlightDisplayKey(@NotNull String name) { + public static String getAlternativeID(@NotNull HighlightDisplayKey key) { + return ourKeyToAlternativeIDMap.get(key); + } + + + private HighlightDisplayKey(@NonNls @NotNull final String name) { this(name, name); } - public HighlightDisplayKey(@NonNls @NotNull final String name, @NotNull @NonNls final String ID) { + public HighlightDisplayKey(@NonNls @NotNull final String name, @NonNls @NotNull final String ID) { myName = name; myID = ID; ourNameToKeyMap.put(myName, this); @@ -97,16 +134,4 @@ public class HighlightDisplayKey { public String getID(){ return myID; } - - public static HighlightDisplayKey register(@NotNull String shortName, @NotNull String displayName, @NotNull String id, String alternativeID) { - final HighlightDisplayKey key = register(shortName, displayName, id); - if (alternativeID != null) { - ourKeyToAlternativeIDMap.put(key, alternativeID); - } - return key; - } - - public static String getAlternativeID(@NotNull HighlightDisplayKey key) { - return ourKeyToAlternativeIDMap.get(key); - } } diff --git a/platform/lang-api/src/com/intellij/codeInsight/intention/impl/BaseIntentionAction.java b/platform/lang-api/src/com/intellij/codeInsight/intention/impl/BaseIntentionAction.java index 98c1d0e23d12..31c89570a388 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/intention/impl/BaseIntentionAction.java +++ b/platform/lang-api/src/com/intellij/codeInsight/intention/impl/BaseIntentionAction.java @@ -37,4 +37,9 @@ public abstract class BaseIntentionAction implements IntentionAction { public boolean startInWriteAction() { return true; } + + @Override + public String toString() { + return getText(); + } } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettingsManager.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettingsManager.java index 3bb3dc2d6adf..1633629ecd9c 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettingsManager.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettingsManager.java @@ -131,13 +131,12 @@ public class CommonCodeStyleSettingsManager implements JDOMExternalizable { final String languageId = commonSettingsElement.getAttributeValue(LANGUAGE_ATTR); if (languageId != null && languageId.length() > 0) { Language target = Language.findLanguageByID(languageId); - if (target == null) { - target = new Language(languageId) {}; + if (target != null) { + final CommonCodeStyleSettings defaultSettings = LanguageCodeStyleSettingsProvider.getDefaultCommonSettings(target); + final CommonCodeStyleSettings settings = defaultSettings != null ? defaultSettings : new CommonCodeStyleSettings(target); + settings.readExternal(commonSettingsElement); + registerCommonSettings(target, settings); } - final CommonCodeStyleSettings defaultSettings = LanguageCodeStyleSettingsProvider.getDefaultCommonSettings(target); - final CommonCodeStyleSettings settings = defaultSettings != null ? defaultSettings : new CommonCodeStyleSettings(target); - settings.readExternal(commonSettingsElement); - registerCommonSettings(target, settings); } } } diff --git a/platform/lang-api/src/com/intellij/psi/stubs/SerializationManagerImpl.java b/platform/lang-api/src/com/intellij/psi/stubs/SerializationManagerImpl.java index eb627af84818..528c752ebfe6 100644 --- a/platform/lang-api/src/com/intellij/psi/stubs/SerializationManagerImpl.java +++ b/platform/lang-api/src/com/intellij/psi/stubs/SerializationManagerImpl.java @@ -20,6 +20,7 @@ import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.diagnostic.LogUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.util.ShutDownTracker; import com.intellij.openapi.util.io.FileUtil; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IStubFileElementType; @@ -51,6 +52,7 @@ public class SerializationManagerImpl extends SerializationManager implements Ap private final AtomicBoolean myNameStorageCrashed = new AtomicBoolean(false); private final File myFile = new File(PathManager.getIndexRoot(), "rep.names"); private boolean mySerializersLoaded = false; + private final AtomicBoolean myShutdownPerformed = new AtomicBoolean(false); public SerializationManagerImpl() { myFile.getParentFile().mkdirs(); @@ -63,7 +65,14 @@ public class SerializationManagerImpl extends SerializationManager implements Ap repairNameStorage(); // need this in order for myNameStorage not to be null myNameStorageCrashed.set(true); } - registerSerializer(PsiFileStubImpl.TYPE); + finally { + registerSerializer(PsiFileStubImpl.TYPE); + ShutDownTracker.getInstance().registerShutdownTask(new Runnable() { + public void run() { + performShutdown(); + } + }); + } } public boolean isNameStorageCorrupted() { @@ -230,8 +239,17 @@ public class SerializationManagerImpl extends SerializationManager implements Ap } public void disposeComponent() { + performShutdown(); + } + + private void performShutdown() { + if (!myShutdownPerformed.compareAndSet(false, true)) { + return; // already shut down + } + LOG.info("START StubSerializationManager SHUTDOWN"); try { myNameStorage.close(); + LOG.info("END StubSerializationManager SHUTDOWN"); } catch (IOException e) { LOG.error(e); diff --git a/platform/lang-impl/src/com/intellij/application/options/CodeCompletion.form b/platform/lang-impl/src/com/intellij/application/options/CodeCompletion.form index bfc550c6a6aa..9fcf3638ef97 100644 --- a/platform/lang-impl/src/com/intellij/application/options/CodeCompletion.form +++ b/platform/lang-impl/src/com/intellij/application/options/CodeCompletion.form @@ -133,7 +133,7 @@ - + diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index bc2278885174..5e2ea8902ae3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -18,12 +18,12 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.CodeInsightActionHandler; import com.intellij.codeInsight.CodeInsightSettings; -import com.intellij.codeInsight.TailType; import com.intellij.codeInsight.completion.impl.CompletionServiceImpl; import com.intellij.codeInsight.editorActions.CompletionAutoPopupHandler; import com.intellij.codeInsight.lookup.*; import com.intellij.codeInsight.lookup.impl.LookupImpl; import com.intellij.featureStatistics.FeatureUsageTracker; +import com.intellij.ide.DataManager; import com.intellij.injected.editor.EditorWindow; import com.intellij.lang.Language; import com.intellij.lang.injection.InjectedLanguageManager; @@ -37,6 +37,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.editor.actionSystem.EditorActionManager; import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.fileEditor.FileDocumentManager; @@ -219,7 +220,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { @NotNull private LookupImpl obtainLookup(Editor editor) { LookupImpl existing = (LookupImpl)LookupManager.getActiveLookup(editor); - if (existing != null && existing.isCompletion() && !existing.isHintMode()) { + if (existing != null && existing.isCompletion()) { existing.markReused(); if (!autopopup) { existing.setFocused(true); @@ -545,7 +546,9 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { final Editor editor = indicator.getEditor(); final PsiFile file = indicator.getParameters().getOriginalFile(); - final InsertionContext context = new InsertionContext(indicator.getOffsetMap(), completionChar, items.toArray(new LookupElement[items.size()]), file, editor); + final InsertionContext context = new InsertionContext(indicator.getOffsetMap(), completionChar, items.toArray(new LookupElement[items.size()]), file, editor, + completionChar != Lookup.AUTO_INSERT_SELECT_CHAR && completionChar != Lookup.REPLACE_SELECT_CHAR && + completionChar != Lookup.NORMAL_SELECT_CHAR && completionChar != Lookup.COMPLETE_STATEMENT_SELECT_CHAR); ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { final int idEndOffset = indicator.getIdentifierEndOffset(); @@ -563,10 +566,10 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { final int tailOffset = context.getTailOffset(); if (tailOffset >= 0) { - if (context.shouldAddCompletionChar() && - completionChar != Lookup.AUTO_INSERT_SELECT_CHAR && completionChar != Lookup.REPLACE_SELECT_CHAR && - completionChar != Lookup.NORMAL_SELECT_CHAR && completionChar != Lookup.COMPLETE_STATEMENT_SELECT_CHAR) { - TailType.insertChar(editor, tailOffset, completionChar); + if (context.shouldAddCompletionChar()) { + editor.getCaretModel().moveToOffset(tailOffset); + EditorActionManager.getInstance().getTypedAction().getHandler().execute(editor, completionChar, DataManager.getInstance() + .getDataContext(editor.getContentComponent())); } } else { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionPhase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionPhase.java index 4f10c015cddf..50a2418fe7bf 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionPhase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionPhase.java @@ -16,20 +16,25 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.completion.impl.CompletionServiceImpl; +import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationAdapter; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.CaretModel; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.SelectionModel; +import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.event.*; +import com.intellij.openapi.fileEditor.FileEditorManagerAdapter; +import com.intellij.openapi.fileEditor.FileEditorManagerEvent; +import com.intellij.openapi.fileEditor.FileEditorManagerListener; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.ui.HintListener; import com.intellij.ui.LightweightHint; +import com.intellij.util.messages.MessageBusConnection; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.util.EventObject; /** @@ -204,8 +209,88 @@ public abstract class CompletionPhase implements Disposable { } } public static class EmptyAutoPopup extends CompletionPhase { + public final Editor editor; + private final Project project; + private final EditorMouseAdapter mouseListener; + private final CaretListener caretListener; + private final DocumentAdapter documentListener; + private final PropertyChangeListener lookupListener; + private boolean changeGuard = false; + public EmptyAutoPopup(CompletionProgressIndicator indicator) { super(indicator); + this.editor = indicator.getEditor(); + this.project = indicator.getProject(); + MessageBusConnection connection = project.getMessageBus().connect(this); + connection.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerAdapter() { + @Override + public void selectionChanged(FileEditorManagerEvent event) { + stopAutoPopup(); + } + }); + + mouseListener = new EditorMouseAdapter() { + @Override + public void mouseClicked(EditorMouseEvent e) { + stopAutoPopup(); + } + }; + + caretListener = new CaretListener() { + @Override + public void caretPositionChanged(CaretEvent e) { + if (!changeGuard) { + stopAutoPopup(); + } + } + }; + editor.getSelectionModel().addSelectionListener(new SelectionListener() { + @Override + public void selectionChanged(SelectionEvent e) { + stopAutoPopup(); + } + }); + documentListener = new DocumentAdapter() { + @Override + public void documentChanged(DocumentEvent e) { + if (!changeGuard) { + stopAutoPopup(); + } + } + }; + lookupListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + stopAutoPopup(); + } + }; + + editor.addEditorMouseListener(mouseListener); + editor.getCaretModel().addCaretListener(caretListener); + editor.getDocument().addDocumentListener(documentListener); + LookupManager.getInstance(project).addPropertyChangeListener(lookupListener); + } + + @Override + public void dispose() { + editor.removeEditorMouseListener(mouseListener); + editor.getCaretModel().removeCaretListener(caretListener); + editor.getDocument().removeDocumentListener(documentListener); + LookupManager.getInstance(project).removePropertyChangeListener(lookupListener); + } + + public void handleTyping(char c) { + changeGuard = true; + try { + EditorModificationUtil.typeInStringAtCaretHonorBlockSelection(editor, String.valueOf(c), true); + } + finally { + changeGuard = false; + } + } + + private static void stopAutoPopup() { + CompletionServiceImpl.setCompletionPhase(NoCompletion); } @Override diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java index fd4f81c6cf2a..b3990a318c77 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java @@ -23,6 +23,7 @@ import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.lookup.*; import com.intellij.codeInsight.lookup.impl.LookupImpl; import com.intellij.lang.Language; +import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.CommandProcessor; @@ -38,7 +39,6 @@ import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.patterns.ElementPattern; import com.intellij.psi.PsiReference; @@ -151,12 +151,13 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement ((CompletionPhase.BgCalculation)phase).focusLookupWhenDone = true; } } else { - /* - myLookup.setAdvertisementText("Press " + + myLookup.addAdvertisement("Press " + CompletionContributor.getActionShortcut(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM_REPLACE) + " to choose the first suggestion"); - */ } + myLookup.addAdvertisement(CompletionContributor.getActionShortcut(IdeActions.ACTION_LOOKUP_DOWN) + " and " + + CompletionContributor.getActionShortcut(IdeActions.ACTION_LOOKUP_UP) + + " will move caret down and up"); } ProgressManager.checkCanceled(); @@ -329,22 +330,13 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } } - if (isAutopopupCompletion() && showHintAutopopup()) { - myLookup.setHintMode(true); - } - else { - myLookup.show(); - } + myLookup.show(); } myLookup.refreshUi(); hideAutopopupIfMeaningless(); updateFocus(); } - public static boolean showHintAutopopup() { - return "true".equals(Registry.stringValue("hint.autopopup")) && !ApplicationManager.getApplication().isUnitTestMode(); - } - final boolean isInsideIdentifier() { return getIdentifierEndOffset() != getSelectionEndOffset(); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionUtil.java index bf8f691202e8..967be3f5a7a2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionUtil.java @@ -175,7 +175,8 @@ public class CompletionUtil { private static InsertionContext newContext(InsertionContext oldContext, LookupElement forElement) { final Editor editor = oldContext.getEditor(); - return new InsertionContext(new OffsetMap(editor.getDocument()), Lookup.AUTO_INSERT_SELECT_CHAR, new LookupElement[]{forElement}, oldContext.getFile(), editor); + return new InsertionContext(new OffsetMap(editor.getDocument()), Lookup.AUTO_INSERT_SELECT_CHAR, new LookupElement[]{forElement}, oldContext.getFile(), editor, + oldContext.shouldAddCompletionChar()); } public static InsertionContext newContext(InsertionContext oldContext, LookupElement forElement, int startOffset, int tailOffset) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/TemplateInsertHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/TemplateInsertHandler.java index 977adac61580..d763a7c574c0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/TemplateInsertHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/TemplateInsertHandler.java @@ -85,7 +85,7 @@ public abstract class TemplateInsertHandler implements InsertHandler { final PsiFile psiFile = context.getFile(); InsertionContext newContext = - new InsertionContext(offsetMap, context.getCompletionChar(), LookupElement.EMPTY_ARRAY, psiFile, editor); + new InsertionContext(offsetMap, context.getCompletionChar(), LookupElement.EMPTY_ARRAY, psiFile, editor, context.shouldAddCompletionChar()); populateInsertMap(psiFile, offsetMap); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoComposite.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoComposite.java index 0e219704aeb2..822255428fff 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoComposite.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoComposite.java @@ -19,13 +19,18 @@ */ package com.intellij.codeInsight.daemon.impl; +import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; public class HighlightInfoComposite extends HighlightInfo { @NonNls private static final String HTML_HEADER = ""; @@ -35,21 +40,24 @@ public class HighlightInfoComposite extends HighlightInfo { @NonNls private static final String LINE_BREAK = "\n
"; public HighlightInfoComposite(@NotNull List infos) { - super(infos.get(0).type, infos.get(0).startOffset, infos.get(0).endOffset, createCompositeDescription(infos), - createCompositeTooltip(infos)); + super(infos.get(0).type, infos.get(0).startOffset, infos.get(0).endOffset, createCompositeDescription(infos), createCompositeTooltip(infos)); text = infos.get(0).text; highlighter = infos.get(0).highlighter; group = infos.get(0).group; - quickFixActionMarkers = ContainerUtil.createEmptyCOWList(); - quickFixActionRanges = ContainerUtil.createEmptyCOWList(); + List> markers = null; + List> ranges = null; for (HighlightInfo info : infos) { if (info.quickFixActionMarkers != null) { - quickFixActionMarkers.addAll(info.quickFixActionMarkers); + if (markers == null) markers = new ArrayList>(); + markers.addAll(info.quickFixActionMarkers); } if (info.quickFixActionRanges != null) { - quickFixActionRanges.addAll(info.quickFixActionRanges); + if (ranges == null) ranges = new ArrayList>(); + ranges.addAll(info.quickFixActionRanges); } } + quickFixActionMarkers = markers == null ? ContainerUtil.>createEmptyCOWList() : new CopyOnWriteArrayList>(markers); + quickFixActionRanges = ranges == null ? ContainerUtil.>createEmptyCOWList() : new CopyOnWriteArrayList>(ranges); } @Nullable diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java index ca4781c001ff..295a460f0ab1 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.codeInsight.daemon.impl; import com.intellij.codeHighlighting.HighlightDisplayLevel; @@ -22,7 +21,6 @@ import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.InspectionsBundle; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.SyntaxHighlighterColors; import com.intellij.openapi.editor.colors.CodeInsightColors; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.util.Comparing; @@ -42,34 +40,36 @@ public interface HighlightInfoType { @NonNls String UNUSED_SYMBOL_ID = "UnusedDeclaration"; @NonNls String DEPRECATION_SHORT_NAME = "Deprecation"; - @NonNls String DEPRECATION_ID = "deprecation"; @NonNls String DEPRECATION_DISPLAY_NAME = InspectionsBundle.message("inspection.deprecated.display.name"); + @NonNls String DEPRECATION_ID = "deprecation"; + + HighlightInfoType ERROR = new HighlightInfoTypeImpl(HighlightSeverity.ERROR, CodeInsightColors.ERRORS_ATTRIBUTES); + HighlightInfoType WARNING = new HighlightInfoTypeImpl(HighlightSeverity.WARNING, CodeInsightColors.WARNINGS_ATTRIBUTES); + /** @deprecated use {@link #WEAK_WARNING} instead */ + HighlightInfoType INFO = new HighlightInfoTypeImpl(HighlightSeverity.INFO, CodeInsightColors.INFO_ATTRIBUTES); + HighlightInfoType WEAK_WARNING = new HighlightInfoTypeImpl(HighlightSeverity.WEAK_WARNING, CodeInsightColors.WEAK_WARNING_ATTRIBUTES); + HighlightInfoType INFORMATION = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.INFORMATION_ATTRIBUTES); HighlightInfoType WRONG_REF = new HighlightInfoTypeImpl(HighlightSeverity.ERROR, CodeInsightColors.WRONG_REFERENCES_ATTRIBUTES); - HighlightInfoType ERROR = new HighlightInfoTypeImpl(HighlightSeverity.ERROR, CodeInsightColors.ERRORS_ATTRIBUTES); - HighlightInfoType GENERIC_WARNINGS_OR_ERRORS_FROM_SERVER = new HighlightInfoTypeImpl(HighlightSeverity.GENERIC_SERVER_ERROR_OR_WARNING, CodeInsightColors.GENERIC_SERVER_ERROR_OR_WARNING); + HighlightInfoType GENERIC_WARNINGS_OR_ERRORS_FROM_SERVER = new HighlightInfoTypeImpl( + HighlightSeverity.GENERIC_SERVER_ERROR_OR_WARNING, CodeInsightColors.GENERIC_SERVER_ERROR_OR_WARNING); HighlightInfoType DUPLICATE_FROM_SERVER = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.DUPLICATE_FROM_SERVER); - HighlightInfoType UNUSED_SYMBOL = new HighlightInfoTypeSeverityByKey(HighlightDisplayKey.find(UNUSED_SYMBOL_SHORT_NAME) == null ? - HighlightDisplayKey.register(UNUSED_SYMBOL_SHORT_NAME, - UNUSED_SYMBOL_DISPLAY_NAME, - UNUSED_SYMBOL_ID) : HighlightDisplayKey.find(UNUSED_SYMBOL_SHORT_NAME), - CodeInsightColors.NOT_USED_ELEMENT_ATTRIBUTES); - + HighlightInfoType UNUSED_SYMBOL = new HighlightInfoTypeSeverityByKey( + HighlightDisplayKey.findOrRegister(UNUSED_SYMBOL_SHORT_NAME, UNUSED_SYMBOL_DISPLAY_NAME, UNUSED_SYMBOL_ID), + CodeInsightColors.NOT_USED_ELEMENT_ATTRIBUTES); HighlightInfoType DEPRECATED = new HighlightInfoTypeSeverityByKey( - HighlightDisplayKey.find(DEPRECATION_SHORT_NAME) == null ? HighlightDisplayKey - .register(DEPRECATION_SHORT_NAME, DEPRECATION_DISPLAY_NAME, DEPRECATION_ID) : HighlightDisplayKey.find(DEPRECATION_SHORT_NAME), + HighlightDisplayKey.findOrRegister(DEPRECATION_SHORT_NAME, DEPRECATION_DISPLAY_NAME, DEPRECATION_ID), CodeInsightColors.DEPRECATED_ATTRIBUTES); HighlightInfoType LOCAL_VARIABLE = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.LOCAL_VARIABLE_ATTRIBUTES); HighlightInfoType INSTANCE_FIELD = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.INSTANCE_FIELD_ATTRIBUTES); HighlightInfoType STATIC_FIELD = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.STATIC_FIELD_ATTRIBUTES); HighlightInfoType PARAMETER = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.PARAMETER_ATTRIBUTES); - // t.o.d.o attributes depend on the t.o.d.o text - HighlightInfoType TODO = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, null); + HighlightInfoType TODO = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, null); // t.o.d.o attributes depend on the t.o.d.o text HighlightInfoType METHOD_CALL = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.METHOD_CALL_ATTRIBUTES); HighlightInfoType METHOD_DECLARATION = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.METHOD_DECLARATION_ATTRIBUTES); HighlightInfoType CONSTRUCTOR_CALL = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.CONSTRUCTOR_CALL_ATTRIBUTES); @@ -84,21 +84,11 @@ public interface HighlightInfoType { HighlightInfoType REASSIGNED_LOCAL_VARIABLE = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES); HighlightInfoType REASSIGNED_PARAMETER = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.REASSIGNED_PARAMETER_ATTRIBUTES); HighlightInfoType IMPLICIT_ANONYMOUS_CLASS_PARAMETER = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.IMPLICIT_ANONYMOUS_CLASS_PARAMETER_ATTRIBUTES); + HighlightInfoType UNHANDLED_EXCEPTION = new HighlightInfoTypeImpl(HighlightSeverity.ERROR, CodeInsightColors.ERRORS_ATTRIBUTES); - HighlightInfoType WARNING = new HighlightInfoTypeImpl(HighlightSeverity.WARNING, CodeInsightColors.WARNINGS_ATTRIBUTES); - /** - * use #WEAK_WARNING instead - */ - @Deprecated - HighlightInfoType INFO = new HighlightInfoTypeImpl(HighlightSeverity.INFO, CodeInsightColors.INFO_ATTRIBUTES); - HighlightInfoType WEAK_WARNING = new HighlightInfoTypeImpl(HighlightSeverity.WEAK_WARNING, CodeInsightColors.WEAK_WARNING_ATTRIBUTES); - HighlightInfoType INFORMATION = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.INFORMATION_ATTRIBUTES); HighlightSeverity INJECTED_FRAGMENT_SEVERITY = new HighlightSeverity("INJECTED_FRAGMENT_SEVERITY", HighlightSeverity.INFORMATION.myVal-1); HighlightInfoType INJECTED_LANGUAGE_FRAGMENT = new HighlightInfoTypeImpl(INJECTED_FRAGMENT_SEVERITY, CodeInsightColors.INFORMATION_ATTRIBUTES); - HighlightInfoType UNHANDLED_EXCEPTION = new HighlightInfoTypeImpl(HighlightSeverity.ERROR, CodeInsightColors.ERRORS_ATTRIBUTES); - HighlightInfoType JAVA_KEYWORD = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, SyntaxHighlighterColors.KEYWORD); - @NotNull HighlightSeverity getSeverity(PsiElement psiElement); @@ -199,8 +189,7 @@ public interface HighlightInfoType { } class HighlightInfoTypeSeverityByKeyAttrBySeverity implements HighlightInfoType { - static final Logger LOG = Logger.getInstance( - "#com.intellij.codeInsight.daemon.impl.HighlightInfoType.HighlightInfoTypeSeverityByKeyAttrBySeverity"); + static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.HighlightInfoType.HighlightInfoTypeSeverityByKeyAttrBySeverity"); private final HighlightDisplayKey mySeverityKey; @@ -210,9 +199,10 @@ public interface HighlightInfoType { @NotNull public HighlightSeverity getSeverity(final PsiElement psiElement) { - HighlightDisplayLevel level = psiElement != null ? InspectionProjectProfileManager.getInstance(psiElement.getProject()).getInspectionProfile().getErrorLevel(mySeverityKey, - psiElement) : ((InspectionProfile)InspectionProfileManager.getInstance().getRootProfile()).getErrorLevel(mySeverityKey, - psiElement); + InspectionProfile profile = psiElement == null + ? (InspectionProfile)InspectionProfileManager.getInstance().getRootProfile() + : InspectionProjectProfileManager.getInstance(psiElement.getProject()).getInspectionProfile(); + HighlightDisplayLevel level = profile.getErrorLevel(mySeverityKey, psiElement); LOG.assertTrue(level != HighlightDisplayLevel.DO_NOT_SHOW); return level.getSeverity(); } @@ -224,14 +214,16 @@ public interface HighlightInfoType { ? infoType.getAttributesKey() : severity == HighlightSeverity.ERROR ? CodeInsightColors.ERRORS_ATTRIBUTES - : severity == HighlightSeverity.WARNING ? CodeInsightColors.WARNINGS_ATTRIBUTES - : severity == HighlightSeverity.WEAK_WARNING ? CodeInsightColors.WEAK_WARNING_ATTRIBUTES : CodeInsightColors.INFO_ATTRIBUTES; + : severity == HighlightSeverity.WARNING + ? CodeInsightColors.WARNINGS_ATTRIBUTES + : severity == HighlightSeverity.WEAK_WARNING + ? CodeInsightColors.WEAK_WARNING_ATTRIBUTES + : CodeInsightColors.INFO_ATTRIBUTES; } @SuppressWarnings({"HardCodedStringLiteral"}) public String toString() { return "HighlightInfoTypeSeverityByKeyAttrBySeverity[severity=" + mySeverityKey + "]"; - } } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java index 498d6a9326be..7e9c84af6981 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java @@ -255,7 +255,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass indicator.checkCanceled(); myInfos = new ArrayList(); - addHighlightsFromResults(myInfos); + addHighlightsFromResults(myInfos, indicator); } private void visitPriorityElementsAndInit(@NotNull List tools, @@ -389,7 +389,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass public Collection getHighlights() { List highlights = new ArrayList(); - addHighlightsFromResults(highlights); + addHighlightsFromResults(highlights, new DaemonProgressIndicator()); return highlights; } @@ -397,13 +397,12 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass private HighlightInfo highlightInfoFromDescriptor(@NotNull ProblemDescriptor problemDescriptor, @NotNull HighlightInfoType highlightInfoType, @NotNull String message, - String toolTip) { + String toolTip, PsiElement psiElement) { TextRange textRange = ((ProblemDescriptorImpl)problemDescriptor).getTextRange(); - PsiElement element = problemDescriptor.getPsiElement(); - if (textRange == null || element == null) return null; - boolean isFileLevel = element instanceof PsiFile && textRange.equals(element.getTextRange()); + if (textRange == null || psiElement == null) return null; + boolean isFileLevel = psiElement instanceof PsiFile && textRange.equals(psiElement.getTextRange()); - final HighlightSeverity severity = highlightInfoType.getSeverity(element); + final HighlightSeverity severity = highlightInfoType.getSeverity(psiElement); TextAttributes attributes = mySeverityRegistrar.getTextAttributesBySeverity(severity); return new HighlightInfo(attributes, highlightInfoType, textRange.getStartOffset(), textRange.getEndOffset(), message, toolTip, @@ -435,8 +434,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), file).getSeverity(); infos.clear(); - createHighlightsForDescriptor(infos, emptyActionRegistered, ilManager, file, thisDocument, tool, severity, descriptor, psiElement, - psiElement.getText()); + createHighlightsForDescriptor(infos, emptyActionRegistered, ilManager, file, thisDocument, tool, severity, descriptor, psiElement); for (HighlightInfo info : infos) { final EditorColorsScheme colorsScheme = getColorsScheme(); UpdateHighlightersUtil.addHighlighterToEditorIncrementally(myProject, myDocument, myFile, myStartOffset, myEndOffset, @@ -516,29 +514,26 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, myStartOffset, myEndOffset, myInfos, getColorsScheme(), getId()); } - private void addHighlightsFromResults(final List outInfos) { + private void addHighlightsFromResults(@NotNull List outInfos, @NotNull ProgressIndicator indicator) { InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile(); PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject); InjectedLanguageManager ilManager = InjectedLanguageManager.getInstance(myProject); Set emptyActionRegistered = new THashSet(); for (Map.Entry> entry : result.entrySet()) { + indicator.checkCanceled(); PsiFile file = entry.getKey(); Document documentRange = documentManager.getDocument(file); if (documentRange == null) continue; List resultList = entry.getValue(); - Map text = new THashMap(resultList.size()); for (InspectionResult inspectionResult : resultList) { + indicator.checkCanceled(); LocalInspectionTool tool = inspectionResult.tool; HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), file).getSeverity(); for (ProblemDescriptor descriptor : inspectionResult.foundProblems) { + indicator.checkCanceled(); PsiElement element = descriptor.getPsiElement(); - String psiText = element == null ? null : text.get(element); - if (psiText == null && element != null) { - psiText = element.getText(); - //text.put(element, psiText); - } - createHighlightsForDescriptor(outInfos, emptyActionRegistered, ilManager, file, documentRange, tool, severity, descriptor, element, psiText); + createHighlightsForDescriptor(outInfos, emptyActionRegistered, ilManager, file, documentRange, tool, severity, descriptor, element); } } } @@ -551,7 +546,8 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass Document documentRange, LocalInspectionTool tool, HighlightSeverity severity, - ProblemDescriptor descriptor, PsiElement element, String psiText) { + ProblemDescriptor descriptor, + PsiElement element) { if (element == null) return; if (myIgnoreSuppressed && InspectionManagerEx.inspectionResultSuppressed(element, tool)) return; HighlightInfoType level = highlightTypeFromDescriptor(descriptor, severity); @@ -603,7 +599,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass tooltip = "" + XmlStringUtil.escapeString(message) + link + ""; } } - HighlightInfo highlightInfo = highlightInfoFromDescriptor(descriptor, type, plainMessage, tooltip); + HighlightInfo highlightInfo = highlightInfoFromDescriptor(descriptor, type, plainMessage, tooltip,element); if (highlightInfo != null) { registerQuickFixes(tool, descriptor, highlightInfo, emptyActionRegistered); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ShowIntentionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ShowIntentionsPass.java index 1ee2b413a854..49bc17d515d0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ShowIntentionsPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ShowIntentionsPass.java @@ -122,11 +122,10 @@ public class ShowIntentionsPass extends TextEditorHighlightingPass { public void doCollectInformation(ProgressIndicator progress) { if (!ApplicationManager.getApplication().isUnitTestMode() && !myEditor.getContentComponent().hasFocus()) return; TemplateState state = TemplateManagerImpl.getTemplateState(myEditor); - if (state == null || state.isFinished()) { - DaemonCodeAnalyzerImpl codeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(myProject); - getIntentionActionsToShow(); - updateActions(codeAnalyzer); - } + if (state != null && !state.isFinished()) return; + DaemonCodeAnalyzerImpl codeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(myProject); + getIntentionActionsToShow(); + updateActions(codeAnalyzer); } public void doApplyInformationToEditor() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QuickFixAction.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QuickFixAction.java index 00f9650e32cf..441ad5dbea5f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QuickFixAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QuickFixAction.java @@ -114,13 +114,13 @@ public final class QuickFixAction { return result; } - private static void addAvailableActionsForGroups(HighlightInfo info, + private static void addAvailableActionsForGroups(@NotNull HighlightInfo info, Editor editor, - PsiFile file, - List outList, + @NotNull PsiFile file, + @NotNull List outList, int group, int offset) { - if (info == null || info.quickFixActionMarkers == null) return; + if (info.quickFixActionMarkers == null) return; if (group != -1 && group != info.group) return; for (Pair pair : info.quickFixActionMarkers) { HighlightInfo.IntentionActionDescriptor actionInGroup = pair.first; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/quickFix/CreateFileFix.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/quickFix/CreateFileFix.java index a1a6705b91b1..29b9586001da 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/quickFix/CreateFileFix.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/quickFix/CreateFileFix.java @@ -109,7 +109,7 @@ public class CreateFileFix implements IntentionAction, LocalQuickFix { long current = System.currentTimeMillis(); if (ApplicationManager.getApplication().isUnitTestMode() || current - myIsAvailableTimeStamp > REFRESH_INTERVAL) { - myIsAvailable = myDirectory.getVirtualFile().findChild(myNewFileName) == null; + myIsAvailable &= myDirectory.getVirtualFile().findChild(myNewFileName) == null; myIsAvailableTimeStamp = current; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java index a8dedbe9deb3..3070505ae37c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java @@ -19,37 +19,22 @@ import com.intellij.codeInsight.AutoPopupController; import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.completion.CodeCompletionHandlerBase; import com.intellij.codeInsight.completion.CompletionPhase; -import com.intellij.codeInsight.completion.CompletionProgressIndicator; import com.intellij.codeInsight.completion.CompletionType; import com.intellij.codeInsight.completion.impl.CompletionServiceImpl; -import com.intellij.codeInsight.lookup.Lookup; -import com.intellij.codeInsight.lookup.LookupAdapter; -import com.intellij.codeInsight.lookup.LookupEvent; import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.EditorModificationUtil; -import com.intellij.openapi.editor.event.*; import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.fileEditor.FileEditorManagerAdapter; -import com.intellij.openapi.fileEditor.FileEditorManagerEvent; -import com.intellij.openapi.fileEditor.FileEditorManagerListener; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Key; import com.intellij.psi.PsiFile; -import com.intellij.util.messages.MessageBusConnection; -import org.jetbrains.annotations.Nullable; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; /** * @author peter */ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { - private static final Key STATE_KEY = Key.create("AutopopupSTATE_KEY"); public static volatile boolean ourTestingAutopopup = false; @Override @@ -58,15 +43,9 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { Editor editor, PsiFile file, FileType fileType) { - final AutoPopupState state = getAutoPopupState(editor); - if (state != null && LookupManager.getActiveLookup(editor) == null) { - state.changeGuard = true; - try { - EditorModificationUtil.typeInStringAtCaretHonorBlockSelection(editor, String.valueOf(c), true); - } - finally { - state.changeGuard = false; - } + CompletionPhase phase = CompletionServiceImpl.getCompletionPhase(); + if (phase instanceof CompletionPhase.EmptyAutoPopup) { + ((CompletionPhase.EmptyAutoPopup)phase).handleTyping(c); return Result.STOP; } @@ -77,30 +56,29 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { public Result checkAutoPopup(char charTyped, final Project project, final Editor editor, final PsiFile file) { if (!CodeInsightSettings.getInstance().AUTO_POPUP_COMPLETION_LOOKUP) return Result.CONTINUE; - if (!Character.isLetter(charTyped) && charTyped != '_') { - finishAutopopupCompletion(editor, false); + if (LookupManager.getActiveLookup(editor) != null) { return Result.CONTINUE; } - if (getAutoPopupState(editor) != null || LookupManager.getActiveLookup(editor) != null) { + CompletionPhase oldPhase = CompletionServiceImpl.getCompletionPhase(); + if (oldPhase instanceof CompletionPhase.EmptyAutoPopup && ((CompletionPhase.EmptyAutoPopup)oldPhase).editor != editor) { + CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion); + } + + if (!Character.isLetter(charTyped) && charTyped != '_') { + if (CompletionServiceImpl.isPhase(CompletionPhase.EmptyAutoPopup.class)) { + CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion); + } return Result.CONTINUE; } if (!CompletionServiceImpl.isPhase(CompletionPhase.AutoPopupAlarm.class, CompletionPhase.NoCompletion.getClass())) { + if ("peter".equals(System.getProperty("user.name")) && ApplicationManagerEx.getApplicationEx().isInternal()) { + System.out.println(CompletionServiceImpl.getCompletionPhase() + " at " + System.currentTimeMillis()); + } return Result.CONTINUE; } - - /* - if (!CompletionProgressIndicator.showHintAutopopup()) { - final CharSequence text = editor.getDocument().getCharsSequence(); - final int offset = editor.getSelectionModel().hasSelection() ? editor.getSelectionModel().getSelectionEnd() : editor.getCaretModel().getOffset(); - if (text.length() > offset && Character.isUnicodeIdentifierPart(text.charAt(offset))) { - return Result.CONTINUE; - } - } - */ - final boolean isMainEditor = FileEditorManager.getInstance(project).getSelectedTextEditor() == editor; final CompletionPhase.AutoPopupAlarm phase = new CompletionPhase.AutoPopupAlarm(); @@ -125,132 +103,6 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { public static void invokeAutoPopupCompletion(Project project, final Editor editor) { new CodeCompletionHandlerBase(CompletionType.BASIC, false, true).invokeCompletion(project, editor, 0, false); - - final AutoPopupState state = new AutoPopupState(project, editor); - editor.putUserData(STATE_KEY, state); - - final Lookup lookup = LookupManager.getActiveLookup(editor); - if (lookup != null) { - lookup.addLookupListener(new LookupAdapter() { - @Override - public void itemSelected(LookupEvent event) { - final AutoPopupState state = getAutoPopupState(editor); - if (state != null) { - state.stopAutoPopup(); - } - } - - @Override - public void lookupCanceled(LookupEvent event) { - final AutoPopupState state = getAutoPopupState(editor); - if (event.isCanceledExplicitly() && state != null) { - state.stopAutoPopup(); - } - } - }); - } } - @Nullable - private static AutoPopupState getAutoPopupState(Editor editor) { - return editor.getUserData(STATE_KEY); - } - - private static void finishAutopopupCompletion(Editor editor, boolean neglectLookup) { - final AutoPopupState state = getAutoPopupState(editor); - if (state == null || state.changeGuard) { - return; - } - - if (!neglectLookup && LookupManager.getActiveLookup(editor) != null) { //the events during visible lookup period are handled separately - return; - } - - final CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCompletionService().getCurrentCompletion(); - if (CompletionServiceImpl.isPhase(CompletionPhase.AutoPopupAlarm.class, CompletionPhase.EmptyAutoPopup.class, CompletionPhase.PossiblyDisturbingAutoPopup.class)) { - CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion); - assert currentCompletion == null; - } else { - if (currentCompletion != null) { - currentCompletion.closeAndFinish(true); - } - CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass()); - } - - state.stopAutoPopup(); - } - - - private static class AutoPopupState { - final Editor editor; - final Project project; - final MessageBusConnection connection; - final EditorMouseAdapter mouseListener; - final CaretListener caretListener; - final DocumentAdapter documentListener; - final PropertyChangeListener lookupListener; - boolean changeGuard = false; - - private AutoPopupState(final Project project, final Editor editor) { - this.editor = editor; - this.project = project; - connection = project.getMessageBus().connect(); - connection.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerAdapter() { - @Override - public void selectionChanged(FileEditorManagerEvent event) { - finishAutopopupCompletion(editor, false); - } - }); - - mouseListener = new EditorMouseAdapter() { - @Override - public void mouseClicked(EditorMouseEvent e) { - finishAutopopupCompletion(editor, false); - } - }; - - caretListener = new CaretListener() { - @Override - public void caretPositionChanged(CaretEvent e) { - finishAutopopupCompletion(editor, false); - } - }; - editor.getSelectionModel().addSelectionListener(new SelectionListener() { - @Override - public void selectionChanged(SelectionEvent e) { - finishAutopopupCompletion(editor, false); - } - }); - documentListener = new DocumentAdapter() { - @Override - public void documentChanged(DocumentEvent e) { - finishAutopopupCompletion(editor, false); - } - }; - lookupListener = new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getNewValue() != null) { - finishAutopopupCompletion(editor, true); - } - } - }; - - editor.addEditorMouseListener(mouseListener); - editor.getCaretModel().addCaretListener(caretListener); - editor.getDocument().addDocumentListener(documentListener); - LookupManager.getInstance(project).addPropertyChangeListener(lookupListener); - } - - void stopAutoPopup() { - connection.disconnect(); - editor.removeEditorMouseListener(mouseListener); - editor.getCaretModel().removeCaretListener(caretListener); - editor.getDocument().removeDocumentListener(documentListener); - LookupManager.getInstance(project).removePropertyChangeListener(lookupListener); - - editor.putUserData(STATE_KEY, null); - } - - } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java index 233e06b81695..f0904702d7f0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java @@ -26,7 +26,6 @@ import com.intellij.lang.ASTNode; import com.intellij.lang.Language; import com.intellij.lang.LanguageParserDefinitions; import com.intellij.lang.ParserDefinition; -import com.intellij.lexer.Lexer; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ApplicationManager; @@ -49,7 +48,6 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; -import com.intellij.psi.templateLanguages.TemplateLanguage; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.PsiUtilBase; @@ -332,15 +330,8 @@ public class TypedHandler implements TypedActionHandler { HighlighterIterator iterator = ((EditorEx) editor).getHighlighter().createIterator(offset); if (iterator.atEnd()) return false; - Language language = iterator.getTokenType().getLanguage(); - final ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(language); - if (definition != null && !(language instanceof TemplateLanguage)) { - final Lexer lexer = definition.createLexer(editor.getProject()); - lexer.start(Character.toString(charTyped)); - final IElementType tokenType = lexer.getTokenType(); - if (tokenType != iterator.getTokenType()) { - return false; - } + if (iterator.getEnd() - iterator.getStart() != 1 || editor.getDocument().getCharsSequence().charAt(iterator.getStart()) != charTyped) { + return false; } BraceMatcher braceMatcher = BraceMatchingUtil.getBraceMatcher(fileType, iterator); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/Advertiser.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/Advertiser.java new file mode 100644 index 000000000000..b25adc97b8e3 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/Advertiser.java @@ -0,0 +1,132 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * 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.intellij.codeInsight.lookup.impl; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; +import com.intellij.util.ui.Animator; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * @author peter + */ +public class Advertiser implements Disposable { + private static final int ourScrollingResolution = 15; + private final List myTexts = new CopyOnWriteArrayList(); + private final JPanel myComponent = new JPanel() { + + @Override + public Dimension getPreferredSize() { + List texts = getTexts(); + if (texts.isEmpty()) return new Dimension(0, 0); + + FontMetrics fm = getFontMetrics(adFont()); + int w = 0; + for (String text : texts) { + w = Math.max(w, fm.stringWidth(text)); + } + + Insets insets = getBorder().getBorderInsets(this); + return new Dimension(w + insets.left + insets.right, fm.getHeight() + insets.top + insets.bottom); + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + + List texts = getTexts(); + if (texts.isEmpty()) return; + + Font font = adFont(); + FontMetrics metrics = g.getFontMetrics(font); + g.setFont(font); + + int height = getHeight(); + int y = (height - metrics.getHeight()) / 2 + metrics.getAscent() - (myScrollingOffset * height / ourScrollingResolution); + int x = getBorder().getBorderInsets(this).left; + + if (myCurrentItem >= 0) { + g.drawString(texts.get(myCurrentItem), x, y); + } + if (myScrollingOffset != 0) { + g.drawString(texts.get((myCurrentItem + 1) % texts.size()), x, y + height); + } + } + }; + private int myCurrentItem = 0; + private int myScrollingOffset = 0; + + public Advertiser(Disposable parentDisposable) { + Disposer.register(parentDisposable, this); + int interCycleGap = 4000; + Animator animator = new Animator("completion ad", ourScrollingResolution, 800, true, interCycleGap, -1) { + @Override + public void paintNow(float frame, float totalFrames, float cycle) { + int adCount = getTexts().size(); + if (adCount <= 1) { + myCurrentItem = myScrollingOffset = 0; + myComponent.repaint(); + return; + } + + myScrollingOffset = ((int)frame + 1) % ourScrollingResolution; + if (myScrollingOffset == 0) { + myCurrentItem = (myCurrentItem + 1) % adCount; + } + myComponent.paintImmediately(0, 0, myComponent.getWidth(), myComponent.getHeight()); + } + }; + animator.resume(); + Disposer.register(this, animator); + } + + private synchronized List getTexts() { + return new ArrayList(myTexts); + } + + public synchronized void clearAdvertisements() { + myTexts.clear(); + } + + private static Font adFont() { + Font font = UIUtil.getLabelFont(); + return font.deriveFont((float)(font.getSize() - 2)); + } + + public synchronized void addAdvertisement(@NotNull String text) { + myTexts.add(text); + if (myTexts.size() == 2) { + if (!myComponent.isShowing()) { + myCurrentItem = -1; + } + } + } + + public JComponent getAdComponent() { + return myComponent; + } + + @Override + public void dispose() { + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/EndHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/EndHandler.java index 8c443306c5f5..419d88935ad3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/EndHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/EndHandler.java @@ -31,7 +31,7 @@ public class EndHandler extends EditorActionHandler { public void execute(Editor editor, DataContext dataContext){ LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor); - if (lookup == null || !lookup.isFocused() || lookup.isHintMode()) { + if (lookup == null || !lookup.isFocused()) { myOriginalHandler.execute(editor, dataContext); return; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/HomeHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/HomeHandler.java index badc854bea87..a8699b9454c8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/HomeHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/HomeHandler.java @@ -31,7 +31,7 @@ public class HomeHandler extends EditorActionHandler { public void execute(Editor editor, DataContext dataContext){ LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor); - if (lookup == null || !lookup.isFocused() || lookup.isHintMode()) { + if (lookup == null || !lookup.isFocused()) { myOriginalHandler.execute(editor, dataContext); return; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.java index 1530694e87f1..76fa7b940f9e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.java @@ -98,16 +98,8 @@ public abstract class LookupActionHandler extends EditorActionHandler { public void actionPerformed(AnActionEvent e) { LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(PlatformDataKeys.EDITOR.getData(e.getDataContext())); assert lookup != null; - if (!CompletionProgressIndicator.showHintAutopopup()) { - lookup.hide(); - ActionManager.getInstance().getAction(IdeActions.ACTION_EDITOR_MOVE_CARET_UP).actionPerformed(e); - return; - } - - - lookup.setHintMode(false); - lookup.refreshUi(); - UpHandler.executeUp(lookup); + lookup.hide(); + ActionManager.getInstance().getAction(IdeActions.ACTION_EDITOR_MOVE_CARET_UP).actionPerformed(e); } @Override @@ -123,15 +115,8 @@ public abstract class LookupActionHandler extends EditorActionHandler { public void actionPerformed(AnActionEvent e) { LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(PlatformDataKeys.EDITOR.getData(e.getDataContext())); assert lookup != null; - if (!CompletionProgressIndicator.showHintAutopopup()) { - lookup.hide(); - ActionManager.getInstance().getAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN).actionPerformed(e); - return; - } - - lookup.setHintMode(false); - lookup.refreshUi(); - DownHandler.executeDown(lookup); + lookup.hide(); + ActionManager.getInstance().getAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN).actionPerformed(e); } @Override diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index 63f067a96829..33b214f78711 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -22,7 +22,6 @@ import com.intellij.codeInsight.completion.PrefixMatcher; import com.intellij.codeInsight.completion.impl.CamelHumpMatcher; import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.hint.HintManagerImpl; -import com.intellij.codeInsight.hint.HintUtil; import com.intellij.codeInsight.lookup.*; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.ide.ui.UISettings; @@ -35,10 +34,7 @@ import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; -import com.intellij.openapi.editor.colors.EditorColorsManager; -import com.intellij.openapi.editor.colors.EditorFontType; import com.intellij.openapi.editor.event.*; -import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; @@ -51,7 +47,10 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.DebugUtil; -import com.intellij.ui.*; +import com.intellij.ui.LightweightHint; +import com.intellij.ui.ListScrollingUtil; +import com.intellij.ui.ScreenUtil; +import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.components.JBList; import com.intellij.ui.plaf.beg.BegPopupMenuBorder; @@ -60,7 +59,6 @@ import com.intellij.util.CollectConsumer; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.AsyncProcessIcon; -import com.intellij.util.ui.GridBag; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; @@ -69,7 +67,6 @@ import javax.swing.*; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.border.LineBorder; -import javax.swing.border.MatteBorder; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; @@ -115,7 +112,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { private final AsyncProcessIcon myProcessIcon = new AsyncProcessIcon("Completion progress"); private final JPanel myIconPanel = new JPanel(new BorderLayout()); private volatile boolean myCalculating; - private final JLabel myAdComponent; + private final Advertiser myAdComponent; private volatile String myAdText; private volatile int myLookupTextWidth = 50; private boolean myReused; @@ -125,8 +122,6 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { private Alarm myHintAlarm = new Alarm(); private JLabel mySortingLabel; private final JScrollPane myScrollPane; - private boolean myHintMode; - private MyLightweightHint myAutopopupHint; public LookupImpl(Project project, Editor editor, @NotNull LookupArranger arranger){ super(new JPanel(new BorderLayout())); @@ -150,8 +145,10 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { getComponent().add(myScrollPane, BorderLayout.NORTH); myScrollPane.setBorder(null); - myAdComponent = HintUtil.createAdComponent(null, new EmptyBorder(1, 2, 1, 2 + relevanceSortIcon.getIconWidth())); - getComponent().add(myAdComponent, BorderLayout.SOUTH); + myAdComponent = new Advertiser(this); + JComponent adComponent = myAdComponent.getAdComponent(); + adComponent.setBorder(new EmptyBorder(0, 1, 1, 2 + relevanceSortIcon.getIconWidth())); + getComponent().add(adComponent, BorderLayout.SOUTH); getComponent().setBorder(new BegPopupMenuBorder()); myIconPanel.setBackground(Color.LIGHT_GRAY); @@ -297,6 +294,9 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { public void setAdvertisementText(@Nullable String text) { myAdText = text; + if (StringUtil.isNotEmpty(text)) { + addAdvertisement(text); + } } public String getAdvertisementText() { @@ -386,12 +386,10 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { updateListHeight(listModel); - myAdComponent.setText(myAdText); - if (!model.isEmpty()) { - myList.setFixedCellWidth(Math.max(myLookupTextWidth + myCellRenderer.getIconIndent(), myAdComponent.getPreferredSize().width)); + myList.setFixedCellWidth(Math.max(myLookupTextWidth + myCellRenderer.getIconIndent(), myAdComponent.getAdComponent().getPreferredSize().width)); - if (isFocused() && (!isExactPrefixItem(model.iterator().next()) || mySelectionTouched) && !isHintMode()) { + if (isFocused() && (!isExactPrefixItem(model.iterator().next()) || mySelectionTouched)) { restoreSelection(oldSelected, hasPreselected, oldInvariant); } else { @@ -481,22 +479,6 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { model.addElement(item); } - public void setHintMode(final boolean hintMode) { - if (!hintMode) { - hideAutopopupHint(); - markSelectionTouched(); - setFocused(true); - if (!myShown) { - show(); - } - } - myHintMode = hintMode; - } - - public boolean isHintMode() { - return myHintMode; - } - private static LookupElementPresentation renderItemApproximately(LookupElement item) { final LookupElementPresentation p = new LookupElementPresentation(); item.renderElement(p); @@ -790,9 +772,6 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { setFocused(true); markSelectionTouched(); - final Point point = e.getPoint(); - final int i = myList.locationToIndex(point); - if (e.getClickCount() == 2){ CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { public void run() { @@ -1072,19 +1051,22 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { } private void doHide(final boolean fireCanceled, final boolean explicitly) { - assert !myDisposed : disposeTrace; - myHidden = true; + if (myDisposed) { + LOG.error(disposeTrace); + } else { + myHidden = true; - try { - super.hide(); + try { + super.hide(); - Disposer.dispose(this); + Disposer.dispose(this); + + assert myDisposed; + } + catch (Throwable e) { + LOG.error(e); + } } - catch (Throwable e) { - LOG.error(e); - } - - assert myDisposed; if (fireCanceled) { fireLookupCanceled(explicitly); @@ -1102,15 +1084,16 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { public void dispose() { assert ApplicationManager.getApplication().isDispatchThread(); assert myHidden; - assert !myDisposed : disposeTrace; + if (myDisposed) { + LOG.error(disposeTrace); + return; + } Disposer.dispose(myProcessIcon); Disposer.dispose(myHintAlarm); myDisposed = true; disposeTrace = DebugUtil.currentStackTrace(); - - hideAutopopupHint(); } private int doSelectMostPreferableItem(List items) { @@ -1139,156 +1122,21 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { updateList(); - final Editor editor = myEditor; if (isVisible()) { LOG.assertTrue(!ApplicationManager.getApplication().isUnitTestMode()); - if (editor.getComponent().getRootPane() == null) { + if (myEditor.getComponent().getRootPane() == null) { LOG.error("Null root pane"); } updateScrollbarVisibility(); - HintManagerImpl.adjustEditorHintPosition(this, editor, calculatePosition(getComponent())); + HintManagerImpl.adjustEditorHintPosition(this, myEditor, calculatePosition(getComponent())); layoutStatusIcons(); if (reused) { ensureSelectionVisible(); } } - else if (myHintMode) { - final int itemTextPadding = 2; - - final JPanel hintComponent = createAutopopupHintComponent(itemTextPadding); - Point bestPoint = calculatePosition(hintComponent); - bestPoint.x += myCellRenderer.getIconIndent() - itemTextPadding; - Point editorPoint = SwingUtilities.convertPoint( - editor.getComponent().getRootPane().getLayeredPane(), - bestPoint, - editor.getContentComponent() - ); - - final HintHint hintHint = new HintHint(editor, editorPoint); - - final HintManagerImpl hintManager = HintManagerImpl.getInstanceImpl(); - if (myAutopopupHint == null) { - final JPanel panel = new JPanel(new BorderLayout()); - panel.add(hintComponent); - myAutopopupHint = new MyLightweightHint(panel); - myAutopopupHint.setForceShowAsPopup(true); - hintManager.showEditorHint(myAutopopupHint, editor, new Point(bestPoint), - HintManagerImpl.HIDE_BY_ESCAPE | HintManagerImpl.UPDATE_BY_SCROLLING, 0, false, hintHint); - } else { - final JComponent panel = myAutopopupHint.getComponent(); - panel.remove(0); - panel.add(hintComponent); - HintManagerImpl.adjustEditorHintPosition(myAutopopupHint, editor, bestPoint); - } - } - } - - private JPanel createAutopopupHintComponent(int itemTextPadding) { - int maxAutopopupItems = 7; - JPanel pane = new JPanel(new GridBagLayout()); - pane.setBackground(HintUtil.INFORMATION_COLOR); - - final Font editorFont = EditorColorsManager.getInstance().getGlobalScheme().getFont(EditorFontType.PLAIN); - final String ctrlSpace = KeymapUtil.getFirstKeyboardShortcutText( - ActionManager.getInstance().getAction(IdeActions.ACTION_CODE_COMPLETION)); - final String ctrlDown = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("EditorLookupDown")); - final String tab = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM_REPLACE)); - final String enter = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM)); - - final List items = getItems(); - GridBag gb = new GridBag().setDefaultFill(GridBagConstraints.HORIZONTAL).setDefaultWeightX(1); - for (int i = 0; i < Math.min(maxAutopopupItems, items.size()); i++) { - final LookupElement element = items.get(i); - final LookupElementPresentation presentation = new LookupElementPresentation(); - element.renderElement(presentation); - - { - final GridBagLayout gridBagLayout = new GridBagLayout(); - final JPanel row = new JPanel(gridBagLayout); - row.setOpaque(false); - - GridBag rgb = new GridBag().setDefaultAnchor(GridBagConstraints.BASELINE); - - final SimpleColoredComponent nameLabel = new SimpleColoredComponent(); - nameLabel.setIpad(new Insets(0, 0, 0, 0)); - nameLabel.setFont(editorFont); - final int style = presentation.isItemTextBold() ? Font.BOLD : Font.PLAIN; - myCellRenderer.renderItemName(element, LookupCellRenderer.FOREGROUND_COLOR, false, style, - StringUtil.notNullize(presentation.getItemText()), nameLabel); - nameLabel.setOpaque(false); - row.add(nameLabel, rgb.next()); - - final JLabel tailLabel = normalizedLabel(presentation.getTailText(), editorFont); - tailLabel.setForeground(LookupCellRenderer.getTailTextColor(false, presentation, tailLabel.getForeground())); - row.add(tailLabel, rgb.next()); - - String keys = i == 0 ? " [" + tab + (isFocused() ? ", " + enter : "") + "]" : i == 1 ? " [" + ctrlDown + "]" : ""; - JLabel adLabel = new JLabel(keys); - adLabel.setFont(adLabel.getFont().deriveFont(Font.BOLD, editorFont.getSize())); - row.add(adLabel, rgb.next().weightx(1).fillCellHorizontally()); - - row.add(normalizedLabel(" " + StringUtil.notNullize(presentation.getTypeText()) + " ", editorFont), rgb.next()); - - if (i == 1) { - row.setBorder(BorderFactory.createCompoundBorder(new EmptyBorder(5, 0, 0, 0), - BorderFactory.createCompoundBorder(new MatteBorder(1, 0, 0, 0, Color.lightGray), - new EmptyBorder(5, itemTextPadding, 0, 0)))); - } - else { - row.setBorder(new EmptyBorder(0, itemTextPadding, 0, 0)); - } - - - row.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - setCurrentItem(element); - CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { - public void run() { - finishLookup(NORMAL_SELECT_CHAR); - } - }, "", null); - } - }); - - pane.add(row, gb.nextLine()); - } - - } - - if (items.size() > maxAutopopupItems) { - final JPanel lastLine = new JPanel(new BorderLayout()); - lastLine.setBorder(new EmptyBorder(4, 0, 2, 0)); - lastLine.setOpaque(false); - - JLabel moreLabel = new JLabel(" " + (items.size() - maxAutopopupItems) + " more"); - moreLabel.setFont(moreLabel.getFont().deriveFont(Font.ITALIC, editorFont.getSize())); - lastLine.add(moreLabel, BorderLayout.WEST); - - JLabel keyLabel = new JLabel(" [" + ctrlSpace + "]"); - keyLabel.setFont(keyLabel.getFont().deriveFont(Font.BOLD, editorFont.getSize())); - lastLine.add(keyLabel); - - pane.add(lastLine, gb.nextLine().padx(5).pady(2).coverColumn()); - } - - return pane; - } - - private static JLabel normalizedLabel(String text, Font font) { - JLabel label = new JLabel(text); - label.setFont(label.getFont().deriveFont(Font.PLAIN, font.getSize())); - return label; - } - - private void hideAutopopupHint() { - if (myAutopopupHint != null) { - myAutopopupHint.justHide(); - myPositionedAbove = null; - } } private void layoutStatusIcons() { @@ -1300,7 +1148,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { final Dimension sortSize = mySortingLabel.getPreferredSize(); final Point sbLocation = SwingUtilities.convertPoint(myScrollPane.getVerticalScrollBar(), 0, 0, layeredPane); - final int sortHeight = (StringUtil.isNotEmpty(myAdText) ? myAdComponent : mySortingLabel).getPreferredSize().height; + final int sortHeight = (StringUtil.isNotEmpty(myAdText) ? myAdComponent.getAdComponent() : mySortingLabel).getPreferredSize().height; mySortingLabel.setBounds(sbLocation.x, layeredPane.getHeight() - sortHeight, sortSize.width, sortHeight); } @@ -1319,10 +1167,14 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { public void markReused() { myReused = true; myModel.clearItems(); - setAdvertisementText(null); + myAdComponent.clearAdvertisements(); myPreselectedItem = null; } + public void addAdvertisement(@NotNull String text) { + myAdComponent.addAdvertisement(text); + } + public boolean isLookupDisposed() { return myDisposed; } @@ -1389,24 +1241,4 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { return myModel.getRelevanceStrings(); } - private class MyLightweightHint extends LightweightHint { - private boolean myHidden; - - public MyLightweightHint(JPanel panel) { - super(panel); - } - - @Override - public void hide() { - if (myHidden) return; - - hideLookup(true); - justHide(); - } - - private void justHide() { - myHidden = true; - super.hide(); - } - } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/TypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/TypedHandler.java index 4dcab26920a2..370c39f68bc3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/TypedHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/TypedHandler.java @@ -82,6 +82,7 @@ public class TypedHandler implements TypedActionHandler { if (result == CharFilter.Result.SELECT_ITEM_AND_FINISH_LOOKUP && lookup.isFocused()) { LookupElement item = lookup.getCurrentItem(); if (item != null){ + inside = false; FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EDITING_COMPLETION_FINISH_BY_DOT_ETC); lookup.finishLookup(charTyped); return; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/actions/ChooseItemReplaceAction.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/actions/ChooseItemReplaceAction.java index 6ce7bbbec8a7..77bb54608f9b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/actions/ChooseItemReplaceAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/actions/ChooseItemReplaceAction.java @@ -46,7 +46,7 @@ public class ChooseItemReplaceAction extends EditorAction { FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EDITING_COMPLETION_REPLACE); LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor); assert lookup != null; - lookup.finishLookup(lookup.isHintMode() ? Lookup.NORMAL_SELECT_CHAR : Lookup.REPLACE_SELECT_CHAR); + lookup.finishLookup(Lookup.REPLACE_SELECT_CHAR); } @Override diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java index 7457d7e91936..7916e843bebd 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java @@ -520,7 +520,7 @@ public class TemplateState implements Disposable { PsiDocumentManager.getInstance(myProject).commitAllDocuments(); final OffsetMap offsetMap = new OffsetMap(myDocument); - final InsertionContext context = new InsertionContext(offsetMap, (char)0, elements, psiFile, myEditor); + final InsertionContext context = new InsertionContext(offsetMap, (char)0, elements, psiFile, myEditor, false); context.setTailOffset(myEditor.getCaretModel().getOffset()); offsetMap.addOffset(CompletionInitializationContext.START_OFFSET, context.getTailOffset() - item.getLookupString().length()); offsetMap.addOffset(CompletionInitializationContext.SELECTION_END_OFFSET, context.getTailOffset()); diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java index 6e5151894664..4a58c854a986 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -417,6 +417,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { private static void duplicateHighlighters(MarkupModel to, MarkupModel from, int offset, TextRange textRange) { for (RangeHighlighter rangeHighlighter : from.getAllHighlighters()) { + if (!rangeHighlighter.isValid()) continue; final int localOffset = textRange.getStartOffset(); final int start = Math.max(rangeHighlighter.getStartOffset(), localOffset) - localOffset; final int end = Math.min(rangeHighlighter.getEndOffset(), textRange.getEndOffset()) - localOffset; diff --git a/platform/lang-impl/src/com/intellij/ide/actions/CreateFileFromTemplateDialog.java b/platform/lang-impl/src/com/intellij/ide/actions/CreateFileFromTemplateDialog.java index 287cd7a1b320..52a24daa378a 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/CreateFileFromTemplateDialog.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/CreateFileFromTemplateDialog.java @@ -58,7 +58,10 @@ public class CreateFileFromTemplateDialog extends DialogWrapper { } private String getEnteredName() { - return getNameField().getText(); + final JTextField nameField = getNameField(); + final String text = nameField.getText().trim(); + nameField.setText(text); + return text; } @Override diff --git a/platform/lang-impl/src/com/intellij/ide/actions/CreateTemplateInPackageAction.java b/platform/lang-impl/src/com/intellij/ide/actions/CreateTemplateInPackageAction.java index ab3495b150f2..3a70bde9807a 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/CreateTemplateInPackageAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/CreateTemplateInPackageAction.java @@ -36,11 +36,11 @@ import javax.swing.*; * @author peter */ public abstract class CreateTemplateInPackageAction extends CreateFromTemplateAction { - private final boolean myinSourceOnly; + private final boolean myInSourceOnly; protected CreateTemplateInPackageAction(String text, String description, Icon icon, boolean inSourceOnly) { super(text, description, icon); - myinSourceOnly = inSourceOnly; + myInSourceOnly = inSourceOnly; } @Override @@ -65,7 +65,7 @@ public abstract class CreateTemplateInPackageAction extend return false; } - if (!myinSourceOnly) { + if (!myInSourceOnly) { return true; } @@ -82,9 +82,9 @@ public abstract class CreateTemplateInPackageAction extend protected abstract boolean checkPackageExists(PsiDirectory directory); @Nullable - private T checkOrCreate(String newName, PsiDirectory directory, String templateName, boolean check) throws IncorrectOperationException { - PsiDirectory dir = directory; - String className = newName; + private T checkOrCreate(String newName, PsiDirectory directory, String templateName, boolean check) throws IncorrectOperationException { + PsiDirectory dir = directory; + String className = newName; final String extension = StringUtil.getShortName(templateName); if (StringUtil.isNotEmpty(extension)) { @@ -92,33 +92,33 @@ public abstract class CreateTemplateInPackageAction extend } if (className.contains(".")) { - String[] names = className.split("\\."); + String[] names = className.split("\\."); - for (int i = 0; i < names.length - 1; i++) { - String name = names[i]; - PsiDirectory subDir = dir.findSubdirectory(name); + for (int i = 0; i < names.length - 1; i++) { + String name = names[i]; + PsiDirectory subDir = dir.findSubdirectory(name); - if (subDir == null) { - if (check) { - dir.checkCreateSubdirectory(name); - return null; - } + if (subDir == null) { + if (check) { + dir.checkCreateSubdirectory(name); + return null; + } - subDir = dir.createSubdirectory(name); - } + subDir = dir.createSubdirectory(name); + } - dir = subDir; - } + dir = subDir; + } - className = names[names.length - 1]; - } + className = names[names.length - 1]; + } if (check) { doCheckCreate(dir, className, templateName); return null; } - return doCreate(dir, className, templateName); - } + return doCreate(dir, className, templateName); + } protected abstract void doCheckCreate(PsiDirectory dir, String className, String templateName) throws IncorrectOperationException; diff --git a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/AbstractCustomLexer.java b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/AbstractCustomLexer.java index b0607907da73..5ec0ecbe4d4d 100644 --- a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/AbstractCustomLexer.java +++ b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/AbstractCustomLexer.java @@ -38,11 +38,6 @@ public class AbstractCustomLexer extends LexerBase { public AbstractCustomLexer(List tokenParsers) { myTokenParsers = tokenParsers.toArray(new TokenParser[tokenParsers.size()]); - - int smartUpdateShift = 0; - for (TokenParser tokenParser : myTokenParsers) { - smartUpdateShift = Math.max(smartUpdateShift, tokenParser.getSmartUpdateShift()); - } } public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) { diff --git a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/CustomFileTypeLexer.java b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/CustomFileTypeLexer.java index 23d7d2fee9e0..79731c9373cf 100644 --- a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/CustomFileTypeLexer.java +++ b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/CustomFileTypeLexer.java @@ -20,8 +20,8 @@ import com.intellij.ide.highlighter.custom.tokens.*; import com.intellij.psi.CustomHighlighterTokenType; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; -import java.util.Set; /** * @author dsl @@ -41,8 +41,7 @@ public final class CustomFileTypeLexer extends AbstractCustomLexer { MultilineCommentParser.create(table.getStartComment(), table.getEndComment()); final NumberParser numberParser = new NumberParser(table.getNumPostfixChars(), table.isIgnoreCase()); final HexNumberParser hexNumberParser = HexNumberParser.create(table.getHexPrefix()); - final KeywordParser keywordParser = new KeywordParser( - new Set[]{table.getKeywords1(), table.getKeywords2(), table.getKeywords3(), table.getKeywords4()}, + final KeywordParser keywordParser = new KeywordParser(Arrays.asList(table.getKeywords1(), table.getKeywords2(), table.getKeywords3(), table.getKeywords4()), table.isIgnoreCase()); final IdentifierParser identifierParser = new IdentifierParser(); diff --git a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/IdentifierParser.java b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/IdentifierParser.java index 4d95522f8a23..697c8f046f1f 100644 --- a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/IdentifierParser.java +++ b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/IdentifierParser.java @@ -41,8 +41,4 @@ public class IdentifierParser extends TokenParser { private boolean isIdentifierPart(final char c) { return Character.isJavaIdentifierPart(c) || c == '-'; } - - public int getSmartUpdateShift() { - return 0; - } } diff --git a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/KeywordParser.java b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/KeywordParser.java index 42ff77c5cf82..d3c20bdf8b79 100644 --- a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/KeywordParser.java +++ b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/KeywordParser.java @@ -20,38 +20,33 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.CustomHighlighterTokenType; import com.intellij.psi.tree.IElementType; -import java.util.BitSet; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; +import java.util.*; /** * @author dsl */ public class KeywordParser extends TokenParser { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.highlighter.custom.tokens.KeywordParser"); - private final HashSet[] myKeywordSets = new HashSet[CustomHighlighterTokenType.KEYWORD_TYPE_COUNT]; - private final int mySmartUpdateShift; + private final List> myKeywordSets = new ArrayList>(); private final boolean myIgnoreCase; private final BitSet myFirstCharacters = new BitSet(); private final BitSet myCharacters = new BitSet(); - public KeywordParser(Set[] keywordSets, boolean ignoreCase) { - LOG.assertTrue(keywordSets.length == myKeywordSets.length); + public KeywordParser(List> keywordSets, boolean ignoreCase) { + LOG.assertTrue(keywordSets.size() == CustomHighlighterTokenType.KEYWORD_TYPE_COUNT); myIgnoreCase = ignoreCase; int maxLength = 0; - for (int i = 0; i < keywordSets.length; i++) { - Set keywordSet = keywordSets[i]; - myKeywordSets[i] = getKeywordSet(keywordSet); - for (Iterator iterator = keywordSet.iterator(); iterator.hasNext();) { - String s = (String) iterator.next(); + for (Set keywordSet : keywordSets) { + myKeywordSets.add(getKeywordSet(keywordSet)); + for (String s : keywordSet) { maxLength = Math.max(maxLength, s.length()); final char firstChar = s.charAt(0); if (ignoreCase) { myFirstCharacters.set(Character.toUpperCase(firstChar), Character.toUpperCase(firstChar) + 1); myFirstCharacters.set(Character.toLowerCase(firstChar), Character.toLowerCase(firstChar) + 1); - } else { + } + else { myFirstCharacters.set(firstChar, firstChar + 1); } for (int j = 0; j < s.length(); j++) { @@ -66,20 +61,18 @@ public class KeywordParser extends TokenParser { } } } - mySmartUpdateShift = maxLength; } - private HashSet getKeywordSet(Set keywordSet) { + private Set getKeywordSet(Set keywordSet) { if (!myIgnoreCase) { - return new HashSet(keywordSet); - } else { - final HashSet result = new HashSet(); - for (Iterator iterator = keywordSet.iterator(); iterator.hasNext();) { - String s = (String) iterator.next(); - result.add(s.toUpperCase()); - } - return result; + return new HashSet(keywordSet); } + + final Set result = new HashSet(); + for (String s : keywordSet) { + result.add(s.toUpperCase()); + } + return result; } @@ -96,8 +89,8 @@ public class KeywordParser extends TokenParser { final String keyword = myBuffer.subSequence(start, position).toString(); String testKeyword = myIgnoreCase ? keyword.toUpperCase() : keyword; - for (int i = 0; i < myKeywordSets.length; i++) { - HashSet keywordSet = myKeywordSets[i]; + for (int i = 0; i < myKeywordSets.size(); i++) { + Set keywordSet = myKeywordSets.get(i); if (keywordSet.contains(testKeyword)) { myTokenInfo.updateData(start, position, getToken(i)); return true; @@ -114,10 +107,6 @@ public class KeywordParser extends TokenParser { case 2: return CustomHighlighterTokenType.KEYWORD_3; case 3: return CustomHighlighterTokenType.KEYWORD_4; } - return null; - } - - public int getSmartUpdateShift() { - return mySmartUpdateShift; + throw new AssertionError(keywordSetIndex); } } diff --git a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/NumberParser.java b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/NumberParser.java index 9441bdd8f2f3..90cbd8c1747a 100644 --- a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/NumberParser.java +++ b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/NumberParser.java @@ -69,10 +69,6 @@ public final class NumberParser extends TokenParser { return true; } - public int getSmartUpdateShift() { - return 2; // if previous character was a dec point - } - static boolean isDigit(char c) { return c >= '0' && c <= '9'; } diff --git a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/PrefixedTokenParser.java b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/PrefixedTokenParser.java index 67fc1bc59899..2bdc1972a3c2 100644 --- a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/PrefixedTokenParser.java +++ b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/PrefixedTokenParser.java @@ -42,9 +42,5 @@ public abstract class PrefixedTokenParser extends TokenParser { return true; } - public int getSmartUpdateShift() { - return myPrefix.length; - } - protected abstract int getTokenEnd(int position); } diff --git a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/PunctuationParser.java b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/PunctuationParser.java index 1f54ff2acfb3..eaf94955e49b 100644 --- a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/PunctuationParser.java +++ b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/PunctuationParser.java @@ -31,9 +31,4 @@ public class PunctuationParser extends TokenParser { } return false; } - - @Override - public int getSmartUpdateShift() { - return 0; - } } diff --git a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/TokenParser.java b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/TokenParser.java index 29d67158953b..e28ddd48f1ad 100644 --- a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/TokenParser.java +++ b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/TokenParser.java @@ -37,6 +37,4 @@ public abstract class TokenParser { } public abstract boolean hasToken(int position); - - public abstract int getSmartUpdateShift(); } diff --git a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/WhitespaceParser.java b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/WhitespaceParser.java index acd250f869fe..2da63cfe42a4 100644 --- a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/WhitespaceParser.java +++ b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/WhitespaceParser.java @@ -31,8 +31,4 @@ public class WhitespaceParser extends TokenParser { myTokenInfo.updateData(start, position, CustomHighlighterTokenType.WHITESPACE); return true; } - - public int getSmartUpdateShift() { - return 0; - } } diff --git a/platform/lang-impl/src/com/intellij/injected/editor/DocumentWindowImpl.java b/platform/lang-impl/src/com/intellij/injected/editor/DocumentWindowImpl.java index 41ee9e967491..06e9afc0ba37 100644 --- a/platform/lang-impl/src/com/intellij/injected/editor/DocumentWindowImpl.java +++ b/platform/lang-impl/src/com/intellij/injected/editor/DocumentWindowImpl.java @@ -526,10 +526,6 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable return myDelegate.removeRangeMarker(((RangeMarkerWindow)rangeMarker).getDelegate()); } - public void addRangeMarker(@NotNull RangeMarkerEx rangeMarker, int start, int end) { - myDelegate.addRangeMarker(((RangeMarkerWindow)rangeMarker).getDelegate(), start, end); - } - public boolean isInBulkUpdate() { return false; } diff --git a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java index d4a9586fe297..1dd56eedd869 100644 --- a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java +++ b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java @@ -59,6 +59,7 @@ import com.intellij.ui.TitledBorderWithMnemonic; import com.intellij.ui.TreeSpeedSearch; import com.intellij.ui.components.JBList; import com.intellij.ui.treeStructure.Tree; +import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; @@ -869,7 +870,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider { } public void clearSelection() { - if (myHighlighter != null && Arrays.asList(myEditor.getMarkupModel().getAllHighlighters()).contains(myHighlighter)) { + if (myHighlighter != null && ArrayUtil.contains(myHighlighter, myEditor.getMarkupModel().getAllHighlighters())) { myHighlighter.dispose(); myHighlighter = null; } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java index f8008c47e39f..b2578293b317 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java @@ -205,9 +205,11 @@ public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter { mySyncDocument = null; } } - + + @TestOnly public void doCommitTransaction(final Document document){ doCommitTransaction(document, getTransaction(document)); + myBus.syncPublisher(PsiDocumentTransactionListener.TOPIC).transactionCompleted(document, null); } private static void doCommitTransaction(final Document document, final DocumentChangeTransaction documentChangeTransaction) { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/SharedPsiElementImplUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/SharedPsiElementImplUtil.java index 4aaf4f3eccb8..fd628e7b5198 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/SharedPsiElementImplUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/SharedPsiElementImplUtil.java @@ -86,45 +86,47 @@ public class SharedPsiElementImplUtil { @Nullable public static PsiElement getNextSibling(PsiElement element) { - if (element instanceof PsiFile) { - final FileViewProvider viewProvider = ((PsiFile)element).getViewProvider(); - element = viewProvider.getPsi(viewProvider.getBaseLanguage()); - } - PsiElement parent = element.getParent(); + PsiElement parent = getElementParent(element); if (parent == null) return null; - PsiElement[] children = parent.getChildren(); - for (int i = 0; i < children.length; i++) { - PsiElement child = children[i]; - if (child == - element) { //do not use .equals since some smartheads are used to overriding PsiElement.equals e.g. com.intellij.psi.impl.source.jsp.jspJava.JspxImportStatementImpl.equals() - return i < children.length - 1 ? children[i + 1] : null; - } - } - LOG.error("Cannot find element among its parent' children." + - " element: '" + element + "';" + - " parent: '" + parent + "';" + - " children: " + new ArrayList(Arrays.asList(children)) + "; " + - " file:" + element.getContainingFile()); - return null; + + final PsiElement[] children = parent.getChildren(); + final int index = getChildIndex(children, element); + return 0 <= index && index < children.length - 1 ? children[index + 1] : null; } @Nullable public static PsiElement getPrevSibling(PsiElement element) { + PsiElement parent = getElementParent(element); + if (parent == null) return null; + + final PsiElement[] children = parent.getChildren(); + final int index = getChildIndex(children, element); + return index > 0 ? children[index - 1] : null; + } + + @Nullable + private static PsiElement getElementParent(PsiElement element) { if (element instanceof PsiFile) { final FileViewProvider viewProvider = ((PsiFile)element).getViewProvider(); element = viewProvider.getPsi(viewProvider.getBaseLanguage()); } - PsiElement parent = element.getParent(); - if (parent == null) return null; - PsiElement[] children = parent.getChildren(); + if (element == null) return null; + return element.getParent(); + } + + private static int getChildIndex(final PsiElement[] children, final PsiElement child) { for (int i = 0; i < children.length; i++) { - PsiElement child = children[i]; - if (child == - element) { //do not use .equals since some smartheads are used to overriding PsiElement.equals e.g. com.intellij.psi.impl.source.jsp.jspJava.JspxImportStatementImpl.equals() - return i > 0 ? children[i - 1] : null; + PsiElement candidate = children[i]; + // do not use equals() since some smart-heads are used to override it (e.g. JspxImportStatementImpl) + if (candidate == child) { + return i; } } - LOG.assertTrue(false); - return null; + LOG.error("Cannot find element among its parent' children." + + " element: '" + child + "';" + + " parent: '" + child.getParent() + "';" + + " children: " + Arrays.asList(children) + "; " + + " file:" + child.getContainingFile()); + return -1; } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LeafPsiElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LeafPsiElement.java index 0e873c668cbc..26d4ce96484f 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LeafPsiElement.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LeafPsiElement.java @@ -26,6 +26,7 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.FileStatus; +import com.intellij.pom.Navigatable; import com.intellij.psi.*; import com.intellij.psi.impl.CheckUtil; import com.intellij.psi.impl.SharedPsiElementImplUtil; @@ -79,10 +80,9 @@ public class LeafPsiElement extends LeafElement implements PsiElement, Navigatio } public PsiFile getContainingFile() { - PsiFile file = SharedImplUtil.getContainingFile(this); - if (file == null || !file.isValid()) { - invalid(); - } + final PsiFile file = SharedImplUtil.getContainingFile(this); + if (file == null || !file.isValid()) invalid(); + //noinspection ConstantConditions return file; } @@ -92,7 +92,15 @@ public class LeafPsiElement extends LeafElement implements PsiElement, Navigatio indicator.checkCanceled(); } - throw new PsiInvalidElementAccessException(this); + final StringBuilder builder = new StringBuilder(); + TreeElement element = this; + while (element != null) { + if (element != this) builder.append(" / "); + builder.append(element.getClass().getName()).append(':').append(element.getElementType()); + element = element.getTreeParent(); + } + + throw new PsiInvalidElementAccessException(this, builder.toString()); } public PsiElement findElementAt(int offset) { @@ -220,7 +228,7 @@ public class LeafPsiElement extends LeafElement implements PsiElement, Navigatio public Project getProject() { final PsiManager manager = getManager(); if (manager == null) invalid(); - + //noinspection ConstantConditions return manager.getProject(); } @@ -246,7 +254,10 @@ public class LeafPsiElement extends LeafElement implements PsiElement, Navigatio } public void navigate(boolean requestFocus) { - EditSourceUtil.getDescriptor(this).navigate(requestFocus); + final Navigatable descriptor = EditSourceUtil.getDescriptor(this); + if (descriptor != null) { + descriptor.navigate(requestFocus); + } } public boolean canNavigate() { diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java index c2a3e2d99284..a8215c2f9987 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java @@ -407,12 +407,7 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi super.dispose(); } finally { - try { - getStubIndex().dispose(); - } - finally { - ((SerializationManagerImpl)SerializationManager.getInstance()).disposeComponent(); - } + getStubIndex().dispose(); } } } diff --git a/platform/lang-impl/src/com/intellij/refactoring/actions/BaseRefactoringAction.java b/platform/lang-impl/src/com/intellij/refactoring/actions/BaseRefactoringAction.java index cd9b719d660a..0144237af69d 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/actions/BaseRefactoringAction.java +++ b/platform/lang-impl/src/com/intellij/refactoring/actions/BaseRefactoringAction.java @@ -126,6 +126,7 @@ public abstract class BaseRefactoringAction extends AnAction { } else { PsiElement element = e.getData(LangDataKeys.PSI_ELEMENT); + Language[] languages = e.getData(LangDataKeys.CONTEXT_LANGUAGES); if (element == null || !isAvailableForLanguage(element.getLanguage())) { if (file == null) { hideAction(e); @@ -133,7 +134,7 @@ public abstract class BaseRefactoringAction extends AnAction { } element = getElementAtCaret(editor, file); } - Language[] languages = e.getData(LangDataKeys.CONTEXT_LANGUAGES); + if (element == null || element instanceof SyntheticElement || languages == null) { hideAction(e); return; diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java index 617340445c6d..d63296b3277b 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java @@ -57,6 +57,7 @@ import com.intellij.psi.impl.PsiDocumentTransactionListener; import com.intellij.psi.impl.source.PsiFileImpl; import com.intellij.psi.search.EverythingGlobalScope; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.stubs.SerializationManager; import com.intellij.util.ArrayUtil; import com.intellij.util.CommonProcessors; import com.intellij.util.Processor; @@ -132,7 +133,7 @@ public class FileBasedIndex implements ApplicationComponent { boolean acceptInput(VirtualFile file); } - public FileBasedIndex(final VirtualFileManagerEx vfManager, FileDocumentManager fdm, MessageBus bus) throws IOException { + public FileBasedIndex(final VirtualFileManagerEx vfManager, FileDocumentManager fdm, MessageBus bus, SerializationManager sm /*need this parameter to ensure component dependency*/) throws IOException { myVfManager = vfManager; myFileDocumentManager = fdm; myIsUnitTestMode = ApplicationManager.getApplication().isUnitTestMode(); diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java index 919717957f94..c7d1ef878132 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java @@ -71,6 +71,9 @@ public interface IdeActions { @NonNls String ACTION_CHOOSE_LOOKUP_ITEM_REPLACE = "EditorChooseLookupItemReplace"; @NonNls String ACTION_CHOOSE_LOOKUP_ITEM_COMPLETE_STATEMENT = "EditorChooseLookupItemCompleteStatement"; + @NonNls String ACTION_LOOKUP_UP = "EditorLookupUp"; + @NonNls String ACTION_LOOKUP_DOWN = "EditorLookupDown"; + @NonNls String GROUP_EXTERNAL_TOOLS = "ExternalToolsGroup"; @NonNls String GROUP_MAIN_MENU = "MainMenu"; diff --git a/platform/platform-api/src/com/intellij/util/net/HTTPProxySettings.form b/platform/platform-api/src/com/intellij/util/net/HTTPProxySettings.form index c51a9a381614..94d5591186f5 100644 --- a/platform/platform-api/src/com/intellij/util/net/HTTPProxySettings.form +++ b/platform/platform-api/src/com/intellij/util/net/HTTPProxySettings.form @@ -3,7 +3,7 @@ - + @@ -21,6 +21,7 @@ + @@ -29,6 +30,7 @@ + @@ -81,6 +83,7 @@ + @@ -89,6 +92,7 @@ + diff --git a/platform/platform-api/src/com/intellij/util/net/HTTPProxySettingsPanel.java b/platform/platform-api/src/com/intellij/util/net/HTTPProxySettingsPanel.java index 3f3f7bcbb4d5..74376bc0cfaf 100644 --- a/platform/platform-api/src/com/intellij/util/net/HTTPProxySettingsPanel.java +++ b/platform/platform-api/src/com/intellij/util/net/HTTPProxySettingsPanel.java @@ -106,15 +106,21 @@ public class HTTPProxySettingsPanel implements SearchableConfigurable { httpConfigurable.PROXY_AUTHENTICATION = myProxyAuthCheckBox.isSelected(); httpConfigurable.KEEP_PROXY_PASSWORD = myRememberProxyPasswordCheckBox.isSelected(); - httpConfigurable.PROXY_LOGIN = myProxyLoginTextField.getText(); - httpConfigurable.setPlainProxyPassword(new String (myProxyPasswordTextField.getPassword())); + httpConfigurable.PROXY_LOGIN = trimFieldText(myProxyLoginTextField); + httpConfigurable.setPlainProxyPassword(new String(myProxyPasswordTextField.getPassword())); try { - httpConfigurable.PROXY_PORT = Integer.valueOf(myProxyPortTextField.getText()).intValue(); + httpConfigurable.PROXY_PORT = Integer.valueOf(trimFieldText(myProxyPortTextField)).intValue(); } catch (NumberFormatException e) { httpConfigurable.PROXY_PORT = 80; } - httpConfigurable.PROXY_HOST = myProxyHostTextField.getText(); + httpConfigurable.PROXY_HOST = trimFieldText(myProxyHostTextField); + } + + private static String trimFieldText(JTextField field) { + String trimmed = field.getText().trim(); + field.setText(trimmed); + return trimmed; } private void enableProxy (boolean enabled) { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/search/PorterStemmerUtil.java b/platform/platform-impl/src/com/intellij/ide/ui/search/PorterStemmerUtil.java index c1dc0df8495d..7bf8e2ee5fa7 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/search/PorterStemmerUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/search/PorterStemmerUtil.java @@ -28,19 +28,19 @@ public class PorterStemmerUtil { // check for zero length final int strLen = str.length(); if (strLen > 0) { - int lastDigit = -1; + int lastNonLetter = -1; for (int i = 0; i < strLen; ++i) { char c = str.charAt(i); - if (Character.isDigit(c)) { - lastDigit = i; + if (Character.isDigit(c) || c == '-' || c == '_') { + lastNonLetter = i; } else if (!Character.isLetter(c)) { return null; } } - ++lastDigit; - if (lastDigit > 0 && lastDigit < strLen) { - return str.substring(0, lastDigit) + stemString(str.substring(lastDigit)); + ++lastNonLetter; + if (lastNonLetter > 0 && lastNonLetter < strLen) { + return str.substring(0, lastNonLetter) + stemString(str.substring(lastNonLetter)); } return stemString(str); } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/search/SearchUtil.java b/platform/platform-impl/src/com/intellij/ide/ui/search/SearchUtil.java index 4bcb43406275..e69d72a19c8c 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/search/SearchUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/search/SearchUtil.java @@ -447,7 +447,7 @@ public class SearchUtil { final String filter) { if (pos < end) { final Set filters = SearchableOptionsRegistrar.getInstance().getProcessedWords(filter); - final String[] words = text.substring(pos, end).split("[\\W&&[^_-]]"); + final String[] words = text.substring(pos, end).split("[\\W&&[^-]]+"); for (String word : words) { if (filters.contains(PorterStemmerUtil.stem(word.toLowerCase()))) { selectedWords.add(word); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/search/SearchableOptionsRegistrarImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/search/SearchableOptionsRegistrarImpl.java index 5f2b23b5132b..8e069a96fdf9 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/search/SearchableOptionsRegistrarImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/search/SearchableOptionsRegistrarImpl.java @@ -67,7 +67,7 @@ public class SearchableOptionsRegistrarImpl extends SearchableOptionsRegistrar { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.ui.search.SearchableOptionsRegistrarImpl"); public static final int LOAD_FACTOR = 20; @NonNls - private static final Pattern REG_EXP = Pattern.compile("[\\W&&[^_-]]"); + private static final Pattern REG_EXP = Pattern.compile("[\\W&&[^-]]+"); @SuppressWarnings({"HardCodedStringLiteral"}) public SearchableOptionsRegistrarImpl() { @@ -360,14 +360,12 @@ public class SearchableOptionsRegistrarImpl extends SearchableOptionsRegistrar { Set result = new HashSet(); @NonNls final String toLowerCase = text.toLowerCase(); final String[] options = REG_EXP.split(toLowerCase); - if (options != null) { - for (String opt : options) { - if (opt == null) continue; - if (isStopWord(opt)) continue; - final String processed = PorterStemmerUtil.stem(opt); - if (isStopWord(processed)) continue; - result.add(opt); - } + for (String opt : options) { + if (isStopWord(opt)) continue; + final String processed = PorterStemmerUtil.stem(opt); + assert processed != null; + if (isStopWord(processed)) continue; + result.add(opt); } return result; } @@ -376,13 +374,11 @@ public class SearchableOptionsRegistrarImpl extends SearchableOptionsRegistrar { Set result = new HashSet(); @NonNls final String toLowerCase = text.toLowerCase(); final String[] options = REG_EXP.split(toLowerCase); - if (options != null) { - for (String opt : options) { - if (isStopWord(opt)) continue; - opt = PorterStemmerUtil.stem(opt); - if (opt == null) continue; - result.add(opt); - } + for (String opt : options) { + if (isStopWord(opt)) continue; + opt = PorterStemmerUtil.stem(opt); + assert opt != null; + result.add(opt); } return result; } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/DocumentEx.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/DocumentEx.java index 1d7cff61ee85..6757c21e7371 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/DocumentEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/DocumentEx.java @@ -50,7 +50,6 @@ public interface DocumentEx extends Document { void clearLineModificationFlags(); boolean removeRangeMarker(@NotNull RangeMarkerEx rangeMarker); - void addRangeMarker(@NotNull RangeMarkerEx rangeMarker, int start, int end); boolean isInBulkUpdate(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java index 734f2f2cb502..838d0b5770f9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java @@ -213,15 +213,19 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { return myRangeMarkers.removeInterval(rangeMarker); } - public void addRangeMarker(@NotNull RangeMarkerEx rangeMarker, int start, int end) { + public void addRangeMarker(@NotNull RangeMarkerEx rangeMarker, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { ApplicationManagerEx.getApplicationEx().assertReadAccessToDocumentsAllowed(); - myRangeMarkers.addInterval(rangeMarker, start, end, null); + myRangeMarkers.addInterval(rangeMarker, start, end, greedyToLeft, greedyToRight, layer); } @TestOnly public int getRangeMarkersSize() { return myRangeMarkers.size(); } + @TestOnly + public int getRangeMarkersNodeSize() { + return myRangeMarkers.nodeSize(); + } @NotNull public RangeMarker createGuardedBlock(int startOffset, int endOffset) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/Getable.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/Getable.java new file mode 100644 index 000000000000..3ebdfcf3b6b6 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/Getable.java @@ -0,0 +1,31 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * 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.intellij.openapi.editor.impl; + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; + +/** + * User: cdr + */ +interface Getable { + T get(); +} +class WeakReferencedGetable extends WeakReference implements Getable { + public WeakReferencedGetable(T referent, ReferenceQueue q) { + super(referent, q); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/IntervalTree.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/IntervalTree.java index 120878b3c521..2225a43bd179 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/IntervalTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/IntervalTree.java @@ -26,6 +26,5 @@ public interface IntervalTree extends Iterable { boolean processOverlappingWith(int start, int end, @NotNull Processor processor); boolean processOverlappingWith(int offset, @NotNull Processor processor); - Object addInterval(@NotNull T interval, int start, int end, Object data); boolean removeInterval(@NotNull T interval); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java index 76a499692d42..c5f7460f6616 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java @@ -15,17 +15,16 @@ */ package com.intellij.openapi.editor.impl; -import com.intellij.openapi.editor.ex.RangeMarkerEx; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.Trinity; import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; +import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; +import gnu.trove.TLongHashSet; import org.jetbrains.annotations.NotNull; -import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReadWriteLock; @@ -35,13 +34,14 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * User: cdr */ public abstract class IntervalTreeImpl extends RedBlackTree implements IntervalTree { + protected int keySize; // number of all keys protected final ReadWriteLock l = new ReentrantReadWriteLock(); protected abstract EqualStartIntervalComparator getComparator(); private final ReferenceQueue myReferenceQueue = new ReferenceQueue(); private int deadReferenceCount; - public abstract static class IntervalNode extends RedBlackTree.Node implements MutableInterval { + public abstract class IntervalNode extends RedBlackTree.Node implements MutableInterval { protected int maxEnd; // max of all intervalEnd()s among all children. protected int delta; // delta of startOffset. getStartOffset() = myStartOffset + Sum of deltas up to root protected abstract int computeDeltaUpToRoot(); @@ -53,28 +53,98 @@ public abstract class IntervalTreeImpl extends RedBla public IntervalNode getRight() { return (IntervalNode)super.getRight(); } - @Override public IntervalNode getParent() { return (IntervalNode)super.getParent(); } - } - protected class MyNode extends IntervalNode { + protected class MyNode extends IntervalNode { private volatile int myStart; private volatile int myEnd; private volatile boolean isValid = true; - private final Reference interval; + protected final List> intervals; public MyNode(@NotNull T key, int start, int end) { // maxEnd == 0 so to not disrupt existing maxes - interval = new WeakReference(key,myReferenceQueue); + intervals = new SmartList>(createGetable(key)); myStart = start; myEnd = end; } @Override - public T getKey() { - return interval.get(); + public boolean processAliveKeys(@NotNull Processor processor) { + for (Getable interval : intervals) { + T key = interval.get(); + if (key != null && !processor.process(key)) return false; + } + return true; + } + + @NotNull + @Override + public List getAliveKeys() { + List result = null; + for (Getable ref : intervals) { + T interval = ref.get(); + if (interval == null) continue; + if (result == null) { + result = new ArrayList(intervals.size()); + } + result.add(interval); + } + return result == null ? Collections.emptyList() : result; + } + + public boolean hasAliveKey(boolean purgeDead) { + for (int i = intervals.size() - 1; i >= 0; i--) { + Getable interval = intervals.get(i); + if (interval.get() != null) return true; + if (purgeDead) { + assertUnderWriteLock(); + intervals.remove(i); + assert keySize > 0 : keySize; + keySize--; + } + } + return false; + } + + // removes interval and the node, if node become empty + public boolean removeInterval(@NotNull T key) { + checkBelongsToTheTree(key, true); + assertUnderWriteLock(); + for (int i = intervals.size() - 1; i >= 0; i--) { + Getable interval = intervals.get(i); + T t = interval.get(); + if (t == key) { + intervals.remove(i); + assert keySize > 0 : keySize; + keySize--; + if (intervals.isEmpty()) { + removeNode(this); + return true; + } + return false; + } + } + List aliveKeys = getAliveKeys(); + assert false: "not found interval: "+key +"; "+ aliveKeys; + return false; + } + + private void assertUnderWriteLock() { + if (!VERIFY) return; + String s = l.writeLock().toString(); + assert s.contains("Locked by thread") : s; + } + + public void addInterval(@NotNull T interval) { + assertUnderWriteLock(); + intervals.add(createGetable(interval)); + keySize++; + } + + protected Getable createGetable(@NotNull T interval) { + return new WeakReferencedGetable(interval, myReferenceQueue); } @Override @@ -134,38 +204,12 @@ public abstract class IntervalTreeImpl extends RedBla } } - @Override - protected MyNode createNewNode(T key, int start, int end, Object data) { - return new MyNode(key, start, end); - } + @NotNull + protected abstract MyNode createNewNode(@NotNull T key, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer); + protected abstract MyNode lookupNode(@NotNull T key); - @Override - protected IntervalNode lookupNode(@NotNull T key, Node interval) { - return ((RangeMarkerImpl)key).myNode; - //int delta = 0; - //int delta1 = ((RangeMarkerImpl)key).myNode == null ? 0 : ((RangeMarkerImpl)key).myNode.computeDeltaUpToRoot(); - //List invalid = new ArrayList(); - //IntervalNode root = (IntervalNode)interval; - //while (root != null) { - // delta += root.delta; - // int compResult = compareNodes(((RangeMarkerImpl)key).myNode, delta1, root, delta, invalid); - // if (compResult < 0) { - // root = root.getLeft(); - // } - // else if (compResult > 0) { - // root = root.getRight(); - // } - // else { - // return root; - // } - //} - //deleteNodes(invalid); - //return root; - } - - private int compareNodes(@NotNull IntervalNode i1, int delta1, @NotNull IntervalNode i2, int delta2, List invalid) { - T i2Key = (T)i2.getKey(); - if (i2Key == null) { + private int compareNodes(@NotNull IntervalNode i1, int delta1, @NotNull IntervalNode i2, int delta2, @NotNull List invalid) { + if (!i2.hasAliveKey(false)) { invalid.add(i2); //gced } int start1 = i1.intervalStart() + delta1; @@ -179,8 +223,10 @@ public abstract class IntervalTreeImpl extends RedBla protected interface EqualStartIntervalComparator { int compare(T i1, T i2); + } - protected IntervalTreeImpl.IntervalNode getRoot() { + + protected IntervalNode getRoot() { return (IntervalNode)root; } @@ -200,11 +246,8 @@ public abstract class IntervalTreeImpl extends RedBla if (root == null) return true; if (!process(root.getLeft(), processor, modCountBefore)) return false; - T key = (T)root.getKey(); - if (key != null) { - if (!processor.process(key)) return false; - assert modCount == modCountBefore; - } + if (!root.processAliveKeys(processor)) return false; + assert modCount == modCountBefore; return process(root.getRight(), processor, modCountBefore); } @@ -241,9 +284,8 @@ public abstract class IntervalTreeImpl extends RedBla int myStartOffset = root.intervalStart() + delta; int myEndOffset = root.intervalEnd() + delta; boolean overlaps = Math.max(myStartOffset, start) <= Math.min(myEndOffset, end); - T key = (T)root.getKey(); - if (key != null) { - if (overlaps && !processor.process(key)) return false; + if (overlaps) { + if (!root.processAliveKeys(processor)) return false; assert modCount == modCountBefore; } @@ -285,9 +327,8 @@ public abstract class IntervalTreeImpl extends RedBla int myEndOffset = root.intervalEnd() + delta; boolean overlaps = myStartOffset <= offset && offset < myEndOffset; - T key = (T)root.getKey(); - if (key != null) { - if (overlaps && !processor.process(key)) return false; + if (overlaps) { + if (!root.processAliveKeys(processor)) return false; assert modCount == modCountBefore; } @@ -298,7 +339,7 @@ public abstract class IntervalTreeImpl extends RedBla return processOverlapping(root.getRight(), offset, processor, modCountBefore, delta); } - protected void insert(@NotNull IntervalNode node) { + protected MyNode findOrInsert(@NotNull IntervalNode node) { node.color = Color.RED; node.setParent(null); node.setValid(true); @@ -308,8 +349,6 @@ public abstract class IntervalTreeImpl extends RedBla node.setRight(null); List gced = new ArrayList(); - //T nodeKey = (T)node.getKey(); - //assert nodeKey != null; if (root == null) { root = node; } @@ -320,6 +359,9 @@ public abstract class IntervalTreeImpl extends RedBla while (true) { delta += current.delta; int compResult = compareNodes(node, 0, current, delta, gced); + if (compResult == 0) { + return (MyNode)current; + } if (compResult < 0) { if (current.getLeft() == null) { current.setLeft(node); @@ -327,44 +369,25 @@ public abstract class IntervalTreeImpl extends RedBla } current = current.getLeft(); } - else if (compResult > 0) { + else /*if (compResult > 0)*/ { if (current.getRight() == null) { current.setRight(node); break loop; } current = current.getRight(); } - else { - T i1 = (T)node.getKey(); - T i2 = (T)current.getKey(); - int delta1 = 0; - int delta2 = delta; - assert false : "already inserted: " + - i1 + - ":" + - delta1 + - "; " + - ((RangeMarkerEx)i1).getId() + - " <-> " + - i2 + - ":" + - delta2 + - "; " + - ((RangeMarkerEx)i2).getId() + - " iden=" + - (i1 == i2); - return; - } } node.delta = -delta; node.setParent(current); } - size++; correctMaxUp(node); + onInsertNode(); + keySize += ((MyNode)node).intervals.size(); insertCase1(node); verifyProperties(); deleteNodes(gced); + return (MyNode)node; } private void deleteNodes(List collectedAway) { @@ -382,18 +405,21 @@ public abstract class IntervalTreeImpl extends RedBla } } - @Override - public IntervalNode addInterval(@NotNull T interval, int start, int end, Object data) { + public MyNode addInterval(@NotNull T interval, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { try { l.writeLock().lock(); checkMax(true); processReferenceQueue(); modCount++; - IntervalNode newNode = createNewNode(interval, start, end, data); - insert(newNode); + IntervalNode newNode = createNewNode(interval, start, end, greedyToLeft, greedyToRight, layer); + MyNode insertedNode = findOrInsert(newNode); + if (insertedNode != newNode) { + // merged + insertedNode.addInterval(interval); + } - checkMax(true); // myNode assigned - return newNode; + checkMax(true); + return insertedNode; } finally { l.writeLock().unlock(); @@ -404,10 +430,13 @@ public abstract class IntervalTreeImpl extends RedBla public boolean checkMax(boolean assertInvalid) { if (!VERIFY) return false; Ref allValid = new Ref(true); - AtomicInteger counter = new AtomicInteger(); - checkMax(getRoot(), 0, assertInvalid, allValid, counter); + AtomicInteger keyCounter = new AtomicInteger(); + AtomicInteger nodeCounter = new AtomicInteger(); + TLongHashSet ids = new TLongHashSet(); + checkMax(getRoot(), 0, assertInvalid, allValid, keyCounter, nodeCounter, ids); if (assertInvalid) { - assert size == counter.get() : "size: "+size+"; actual: "+counter; + assert nodeSize() == nodeCounter.get() : "node size: "+ nodeSize() +"; actual: "+nodeCounter; + assert keySize == keyCounter.get() : "key size: "+ keySize +"; actual: "+keyCounter; } return allValid.get(); } @@ -416,15 +445,23 @@ public abstract class IntervalTreeImpl extends RedBla protected Trinity checkMax(IntervalNode root, int deltaUpToRootExclusive, boolean assertInvalid, - Ref allValid, AtomicInteger counter) { + Ref allValid, + AtomicInteger keyCounter, + AtomicInteger nodeCounter, + TLongHashSet ids) { if (root == null) return Trinity.create(Integer.MAX_VALUE,Integer.MIN_VALUE,Integer.MIN_VALUE); - counter.getAndIncrement(); + for (T t : root.getAliveKeys()) { + checkBelongsToTheTree(t, assertInvalid); + assert ids.add(((RangeMarkerImpl)t).getId()) : t; + } + keyCounter.addAndGet(((MyNode)root).intervals.size()); + nodeCounter.incrementAndGet(); int delta = deltaUpToRootExclusive + (root.isValid() ? root.delta : 0); - Trinity l = checkMax(root.getLeft(), delta, assertInvalid, allValid, counter); + Trinity l = checkMax(root.getLeft(), delta, assertInvalid, allValid, keyCounter, nodeCounter, ids); int minLeftStart = l.first; int maxLeftStart = l.second; int maxLeftEnd = l.third; - Trinity r = checkMax(root.getRight(), delta, assertInvalid, allValid, counter); + Trinity r = checkMax(root.getRight(), delta, assertInvalid, allValid, keyCounter, nodeCounter, ids); int maxRightEnd = r.third; int minRightStart = r.first; int maxRightStart = r.second; @@ -434,8 +471,7 @@ public abstract class IntervalTreeImpl extends RedBla return Trinity.create(Math.min(minLeftStart, minRightStart), Math.max(maxLeftStart, maxRightStart), Math.max(maxRightEnd, maxLeftEnd)); } IntervalNode parent = root.getParent(); - T rootKey = (T)root.getKey(); - if (parent != null && assertInvalid && rootKey != null) { + if (parent != null && assertInvalid && root.hasAliveKey(false)) { int c = compareNodes(root, delta, parent, delta - root.delta, new ArrayList()); assert c != 0; assert c < 0 && parent.getLeft() == root || c > 0 && parent.getRight() == root; @@ -465,17 +501,39 @@ public abstract class IntervalTreeImpl extends RedBla return root; } + protected void checkBelongsToTheTree(T interval, boolean assertInvalid) { + if (!VERIFY) return; + MyNode root = lookupNode(interval); + if (root == null) return; + assert !root.intervals.isEmpty(); + + assert root.getTree() == this; + List keys = root.getAliveKeys(); + assert keys.contains(interval) : keys + "; " + interval; + for (T key : keys) { + MyNode node = lookupNode(key); + assert assertInvalid && node == root || !assertInvalid && (node == null || node == root) : node; + assert assertInvalid && node.getTree() == this || !assertInvalid && (node == null || node.getTree() == this) : node; + } + + IntervalNode e = root; + while (e.getParent() != null) e = e.getParent(); + assert e == this.root; // assert the node belongs to our tree + } + @Override public boolean removeInterval(@NotNull T interval) { if (!interval.isValid()) return false; try { l.writeLock().lock(); + checkBelongsToTheTree(interval, true); checkMax(true); processReferenceQueue(); - IntervalNode node = lookupNode(interval, root); + MyNode node = lookupNode(interval); if (node == null) return false; - removeNode(node); + + node.removeInterval(interval); checkMax(true); return true; } @@ -493,33 +551,51 @@ public abstract class IntervalTreeImpl extends RedBla @Override protected void deleteNode(Node n) { - pushDeltaFromRoot((IntervalNode)n); + MyNode node = (MyNode)n; + pushDeltaFromRoot(node); super.deleteNode(n); + + keySize -= node.intervals.size(); + assert keySize >= 0 : keySize; } - protected static void pushDelta(IntervalNode root) { - if (root == null || !root.isValid()) return; + @Override + public int size() { + return keySize; + } + + // returns true if some delta was or became not null + protected boolean pushDelta(IntervalNode root) { + if (root == null || !root.isValid()) return false; int delta = root.delta; if (delta != 0) { root.setIntervalStart(root.intervalStart() + delta); root.setIntervalEnd(root.intervalEnd() + delta); root.maxEnd += delta; root.delta = 0; - incDelta(root.getLeft(), delta); + //noinspection NonShortCircuitBooleanExpression + return + incDelta(root.getLeft(), delta) | + incDelta(root.getRight(), delta); + } + return false; + } + + // returns true if some delta was or became not null + private boolean incDelta(IntervalNode root, int delta) { + if (root == null) return false; + if (root.isValid()) { + int newDelta = root.delta += delta; + return newDelta != 0; + } + else { + //noinspection NonShortCircuitBooleanExpression + return + incDelta(root.getLeft(), delta) | incDelta(root.getRight(), delta); } } - private static void incDelta(IntervalNode root, int delta) { - if (root == null) return; - if (root.isValid()) { - root.delta += delta; - } - else { - incDelta(root.getLeft(), delta); - incDelta(root.getRight(), delta); - } - } @Override protected IntervalNode swapWithMaxPred(Node root, Node maxPred) { checkMax(false); @@ -546,7 +622,6 @@ public abstract class IntervalTreeImpl extends RedBla checkMax(false); return a; } - private void swapNodes(IntervalNode n1, IntervalNode n2) { IntervalNode l1 = n1.getLeft(); IntervalNode r1 = n1.getRight(); @@ -580,7 +655,7 @@ public abstract class IntervalTreeImpl extends RedBla if (r2 != null) r2.setParent(n1); } - protected static int maxEndOf(IntervalNode node, int deltaUpToRootExclusive) { + private int maxEndOf(IntervalNode node, int deltaUpToRootExclusive) { if (node == null) { return 0; } @@ -591,14 +666,14 @@ public abstract class IntervalTreeImpl extends RedBla } // max of n.left's maxend, n.right's maxend and its own interval endOffset - protected static void correctMax(@NotNull IntervalNode node, int deltaUpToRoot) { + protected void correctMax(@NotNull IntervalNode node, int deltaUpToRoot) { if (!node.isValid()) return; int realMax = Math.max(Math.max(maxEndOf(node.getLeft(), deltaUpToRoot), maxEndOf(node.getRight(), deltaUpToRoot)), deltaUpToRoot + node.intervalEnd()); node.maxEnd = realMax - deltaUpToRoot; } - private static void correctMaxUp(IntervalNode node) { + private void correctMaxUp(IntervalNode node) { int delta = node == null ? 0 : node.computeDeltaUpToRoot(); while (node != null) { if (node.isValid()) { @@ -720,37 +795,39 @@ public abstract class IntervalTreeImpl extends RedBla final int modCountBefore = modCount; return new Iterator() { private IntervalNode node = firstNode; - private T element = (T)firstNode.getKey(); + private Iterator iteratorInCurrentList = firstNode.getAliveKeys().iterator(); { // find first non-null key - while (element == null) { + while (!iteratorInCurrentList.hasNext()) { moveNext(); if (node == null) break; } } public boolean hasNext() { - return element != null; + Iterator it = iteratorInCurrentList; + return it != null && it.hasNext(); } public T next() { assert modCount == modCountBefore : "Must not modify range markers during iterate"; - if (node == null || element == null) throw new NoSuchElementException(); - T current = element; + if (node == null || iteratorInCurrentList == null || !iteratorInCurrentList.hasNext()) throw new NoSuchElementException(); + T current = iteratorInCurrentList.next(); moveNext(); return current; } private void moveNext() { + if (iteratorInCurrentList != null && iteratorInCurrentList.hasNext()) return; while (true) { node = getNextNode(); if (node == null) { - element = null; + iteratorInCurrentList = null; break; } - element = (T)node.getKey(); - if (element != null) break; + iteratorInCurrentList = node.getAliveKeys().iterator(); + if (iteratorInCurrentList.hasNext()) break; } } @@ -793,14 +870,38 @@ public abstract class IntervalTreeImpl extends RedBla l.writeLock().unlock(); } } - - private static void normalize(IntervalNode root) { + private void normalize(IntervalNode root) { if (root == null) return; pushDelta(root); normalize(root.getLeft()); normalize(root.getRight()); } + public void changeData(T interval, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { + try { + l.writeLock().lock(); + + MyNode node = lookupNode(interval); + if (node == null) return; + int before = size(); + boolean nodeRemoved = node.removeInterval(interval); + assert nodeRemoved || !node.intervals.isEmpty(); + + MyNode insertedNode = addInterval(interval, start, end, greedyToLeft, greedyToRight, layer); + assert node != insertedNode; + + int after = size(); + // can be gced + assert before >= after : before +";" + after; + checkBelongsToTheTree(interval, true); + checkMax(true); + } + finally { + l.writeLock().unlock(); + } + } + + // called under write lock private void processReferenceQueue() { int dead = 0; @@ -821,35 +922,19 @@ public abstract class IntervalTreeImpl extends RedBla deleteNodes(gced); } - private static void collectGced(IntervalNode root, List gced) { + private void collectGced(IntervalNode root, List gced) { if (root == null) return; - if (root.getKey() == null) gced.add(root); + if (!root.hasAliveKey(true)) gced.add(root); collectGced(root.getLeft(), gced); collectGced(root.getRight(), gced); } - public void changeAttribute(@NotNull IntervalNode node, @NotNull Runnable changeAttributes) { - normalize(); - try { - l.writeLock().lock(); - checkMax(true); - removeNode(node); - changeAttributes.run(); - insert(node); - checkMax(true); - } - finally { - l.writeLock().unlock(); - } - } - private void printSorted() { printSorted(getRoot());} - private static void printSorted(IntervalNode root) { + private void printSorted(IntervalNode root) { if (root == null) return; printSorted(root.getLeft()); System.out.println(root); printSorted(root.getRight()); } - } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java index 04812916c5e3..c3efa8a61aed 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java @@ -35,9 +35,7 @@ import com.intellij.openapi.editor.markup.HighlighterTargetArea; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.UserDataHolderBase; -import com.intellij.util.CommonProcessors; -import com.intellij.util.Consumer; -import com.intellij.util.Processor; +import com.intellij.util.*; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -99,6 +97,7 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx return offset; } + // NB: Can return invalid highlighters @NotNull public RangeHighlighter[] getAllHighlighters() { ApplicationManager.getApplication().assertIsDispatchThread(); @@ -123,16 +122,11 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx ApplicationManager.getApplication().assertIsDispatchThread(); RangeHighlighterEx highlighter = isPersistent ? new PersistentRangeHighlighterImpl(this, startOffset, layer, targetArea, textAttributes) - : new RangeHighlighterImpl(this, startOffset, endOffset, layer, targetArea, textAttributes); + : new RangeHighlighterImpl(this, startOffset, endOffset, layer, targetArea, textAttributes, false, false); myCachedHighlighters = null; if (changeAttributesAction != null) { - if (isPersistent) { - ((PersistentRangeHighlighterImpl)highlighter).changeAttributesInBatch(changeAttributesAction); - } - else { - ((RangeHighlighterImpl)highlighter).changeAttributesInBatch(changeAttributesAction); - } + ((RangeHighlighterImpl)highlighter).changeAttributesNoEvents(changeAttributesAction); } fireAfterAdded(highlighter); return highlighter; @@ -141,17 +135,20 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx @Override public void changeAttributesInBatch(@NotNull RangeHighlighterEx highlighter, @NotNull Consumer changeAttributesAction) { ApplicationManager.getApplication().assertIsDispatchThread(); - boolean changed = highlighter instanceof PersistentRangeHighlighterImpl - ? ((PersistentRangeHighlighterImpl)highlighter).changeAttributesInBatch(changeAttributesAction) - : ((RangeHighlighterImpl)highlighter).changeAttributesInBatch(changeAttributesAction); + boolean changed = ((RangeHighlighterImpl)highlighter).changeAttributesNoEvents(changeAttributesAction); if (changed) { fireAttributesChanged(highlighter); } } - void addRangeHighlighter(RangeHighlighterEx marker, int start, int end, RangeHighlighterData data) { + IntervalTreeImpl.IntervalNode addRangeHighlighter(RangeHighlighterEx marker, + int start, + int end, + boolean greedyToLeft, + boolean greedyToRight, + int layer) { ApplicationManager.getApplication().assertIsDispatchThread(); - myHighlighterTree.addInterval(marker, start, end, data); + return myHighlighterTree.addInterval(marker, start, end, greedyToLeft, greedyToRight, layer); } @NotNull diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/PersistentRangeHighlighterImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/PersistentRangeHighlighterImpl.java index 30b1aedf7f52..55b3bb8c3d9a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/PersistentRangeHighlighterImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/PersistentRangeHighlighterImpl.java @@ -34,7 +34,8 @@ class PersistentRangeHighlighterImpl extends RangeHighlighterImpl implements Ran int layer, @NotNull HighlighterTargetArea target, TextAttributes textAttributes) { - super(model, model.getDocument().getLineStartOffset(model.getDocument().getLineNumber(offset)), model.getDocument().getLineEndOffset(model.getDocument().getLineNumber(offset)),layer, target, textAttributes); + super(model, model.getDocument().getLineStartOffset(model.getDocument().getLineNumber(offset)), model.getDocument().getLineEndOffset(model.getDocument().getLineNumber(offset)),layer, target, textAttributes, + false, false); setLine(model.getDocument().getLineNumber(offset)); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterData.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterData.java index fc498a3e15f4..24d1ebec98ee 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterData.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterData.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.editor.impl; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.ex.RangeHighlighterEx; import com.intellij.openapi.editor.markup.*; @@ -30,7 +31,6 @@ import java.awt.*; */ abstract class RangeHighlighterData { private final MarkupModel myModel; - private final int myLayer; private final HighlighterTargetArea myTargetArea; private TextAttributes myTextAttributes; private LineMarkerRenderer myLineMarkerRenderer; @@ -46,12 +46,10 @@ abstract class RangeHighlighterData { int myLine; // for PersistentRangeHighlighterImpl only RangeHighlighterData(@NotNull MarkupModel model, - int layer, @NotNull HighlighterTargetArea target, TextAttributes textAttributes) { myTextAttributes = textAttributes; myTargetArea = target; - myLayer = layer; myModel = model; if (textAttributes != null) { myErrorStripeColor = textAttributes.getErrorStripeColor(); @@ -73,10 +71,6 @@ abstract class RangeHighlighterData { } } - public int getLayer() { - return myLayer; - } - public HighlighterTargetArea getTargetArea() { return myTargetArea; } @@ -127,6 +121,7 @@ abstract class RangeHighlighterData { } public void setErrorStripeTooltip(Object tooltipObject) { + ApplicationManager.getApplication().assertIsDispatchThread(); Object old = myErrorStripeTooltip; myErrorStripeTooltip = tooltipObject; if (!Comparing.equal(old, tooltipObject)) { @@ -139,6 +134,7 @@ abstract class RangeHighlighterData { } public void setThinErrorStripeMark(boolean value) { + ApplicationManager.getApplication().assertIsDispatchThread(); boolean old = myErrorStripeMarkIsThin; myErrorStripeMarkIsThin = value; if (old != value) { @@ -223,16 +219,10 @@ abstract class RangeHighlighterData { return Math.min(textLength, document.getLineEndOffset(document.getLineNumber(endOffset)) + 1); } - public void registerMe(int start, int end) { - ((MarkupModelImpl)myModel).addRangeHighlighter(getRangeHighlighter(), start, end,this); - } - - public void unregisterMe() { - myModel.removeHighlighter(getRangeHighlighter()); - } - // returns true if change was detected boolean changeAttributesInBatch(@NotNull Consumer change) { + assert !inBatchChange; + assert !changed; inBatchChange = true; boolean result; try { @@ -245,4 +235,8 @@ abstract class RangeHighlighterData { } return result; } + + public MarkupModel getMarkupModel() { + return myModel; + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterImpl.java index fe847de29778..9f028ebcbb51 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterImpl.java @@ -28,43 +28,64 @@ import java.awt.*; * Implementation of the markup element for the editor and document. * @author max */ -class RangeHighlighterImpl extends RangeMarkerImpl implements RangeHighlighterEx { +class RangeHighlighterImpl extends RangeMarkerImpl implements RangeHighlighterEx, Getable { + private final RangeHighlighterData data; + RangeHighlighterImpl(@NotNull MarkupModel model, int start, int end, int layer, @NotNull HighlighterTargetArea target, - TextAttributes textAttributes) { + TextAttributes textAttributes, boolean greedyToLeft, boolean greedyToRight) { super((DocumentEx)model.getDocument(), start, end,false); - RangeHighlighterData data = new RangeHighlighterData(model, layer, target, textAttributes) { + data = new RangeHighlighterData(model, target, textAttributes) { @NotNull @Override public RangeHighlighterEx getRangeHighlighter() { return RangeHighlighterImpl.this; } }; - data.registerMe(start, end); + + registerInTree(start, end, greedyToLeft, greedyToRight, layer); + } + + @Override + public void setGreedyToLeft(boolean greedy) { + if (!isValid() || greedy == isGreedyToLeft()) return; + myNode.getTree().changeData(this, getStartOffset(), getEndOffset(), greedy, isGreedyToRight(), getLayer()); + } + + @Override + public void setGreedyToRight(boolean greedy) { + if (!isValid() || greedy == isGreedyToRight()) return; + myNode.getTree().changeData(this, getStartOffset(), getEndOffset(), isGreedyToLeft(), greedy, getLayer()); } protected RangeHighlighterData getData() { - return ((RangeHighlighterTree.RHNode)myNode).data; + return data; } @Override - protected void registerInDocument(int start, int end) { + protected void registerInTree(int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { // we store highlighters in MarkupModel + ((MarkupModelImpl)data.getMarkupModel()).addRangeHighlighter(this, start, end, greedyToLeft, greedyToRight, layer); } @Override - protected boolean unregisterInDocument() { + protected boolean unregisterInTree() { if (myNode == null) return false; // we store highlighters in MarkupModel - getData().unregisterMe(); + getData().getMarkupModel().removeHighlighter(this); myNode = null; return true; } + @Override + public RangeHighlighterImpl get() { + return this; + } + // delegates public TextAttributes getTextAttributes() { return getData().getTextAttributes(); @@ -74,12 +95,13 @@ class RangeHighlighterImpl extends RangeMarkerImpl implements RangeHighlighterEx getData().setTextAttributes(textAttributes); } - boolean changeAttributesInBatch(@NotNull Consumer change) { + boolean changeAttributesNoEvents(@NotNull Consumer change) { return getData().changeAttributesInBatch(change); } public int getLayer() { - return getData().getLayer(); + RangeHighlighterTree.RHNode node = (RangeHighlighterTree.RHNode)myNode; + return node == null ? -1 : node.myLayer; } public HighlighterTargetArea getTargetArea() { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterTree.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterTree.java index fcf92a4c720e..f8fa6ff69c4d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterTree.java @@ -28,8 +28,8 @@ public class RangeHighlighterTree extends RangeMarkerTree { public int compare(IntervalNode i1, IntervalNode i2) { RHNode o1 = (RHNode)i1; RHNode o2 = (RHNode)i2; - if (o1.data.getLayer() != o2.data.getLayer()) { - return o2.data.getLayer() - o1.data.getLayer(); + if (o1.myLayer != o2.myLayer) { + return o2.myLayer - o1.myLayer; } boolean greedyL1 = o1.isGreedyToLeft(); boolean greedyL2 = o2.isGreedyToLeft(); @@ -42,9 +42,7 @@ public class RangeHighlighterTree extends RangeMarkerTree { boolean greedyR2 = o2.isGreedyToRight(); if (greedyR1 != greedyR2) return greedyR1 ? -1 : 1; - // for now we tolerate equal range range markers (till lazy creation impl) - d = (int)(o1.getId() - o2.getId()); - return d; + return 0; } }; @@ -57,19 +55,29 @@ public class RangeHighlighterTree extends RangeMarkerTree { return myComparator; } + @NotNull @Override - protected RHNode createNewNode(RangeHighlighterEx key, int start, int end, Object data) { - RHNode node = new RHNode(key, start, end, (RangeHighlighterData)data); - ((RangeMarkerImpl)key).myNode = node; - return node; + protected RHNode createNewNode(@NotNull RangeHighlighterEx key, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { + return new RHNode(key, start, end, greedyToLeft, greedyToRight,layer); } class RHNode extends RMNode { - final RangeHighlighterData data; - public RHNode(@NotNull final RangeHighlighterEx key, int start, int end, RangeHighlighterData data) { - super(key, start, end); - this.data = data; + final int myLayer; + + public RHNode(@NotNull final RangeHighlighterEx key, + int start, + int end, + boolean greedyToLeft, + boolean greedyToRight, + int layer) { + super(key, start, end, greedyToLeft, greedyToRight); + myLayer = layer; + } + + // range highlighters are strongly referenced + @Override + protected Getable createGetable(@NotNull RangeHighlighterEx interval) { + return (Getable)interval; } } - } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java index 88e05ac03d34..8197d311427f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java @@ -23,13 +23,22 @@ import com.intellij.openapi.util.UserDataHolderBase; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import java.util.concurrent.atomic.AtomicLong; + public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx, MutableInterval { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.RangeMarkerImpl"); protected final DocumentEx myDocument; RangeMarkerTree.RMNode myNode; + private final long myId; + //private static long counter; + private static final AtomicLong counter = new AtomicLong(); + protected RangeMarkerImpl(@NotNull DocumentEx document, int start, int end, boolean register) { + this(document, start, end, register, false, false); + } + private RangeMarkerImpl(@NotNull DocumentEx document, int start, int end, boolean register, boolean greedyToLeft, boolean greedyToRight) { if (start < 0) { throw new IllegalArgumentException("Wrong start: " + start+"; end="+end); } @@ -41,29 +50,34 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx } myDocument = document; + myId = counter.getAndIncrement(); if (register) { - registerInDocument(start, end); + registerInTree(start, end, greedyToLeft, greedyToRight, 0); } } - protected void registerInDocument(int start, int end) { - myNode = null; - myDocument.addRangeMarker(this, start, end); - assert myNode != null; + protected void registerInTree(int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { + ((DocumentImpl)myDocument).addRangeMarker(this, start, end, greedyToLeft, greedyToRight, layer); } - protected boolean unregisterInDocument() { + + protected boolean unregisterInTree() { + IntervalTreeImpl tree = myNode.getTree(); + tree.checkMax(true); boolean b = myDocument.removeRangeMarker(this); myNode = null; + tree.checkMax(true); return b; } public long getId() { - return myNode.getId(); + return myId; } @Override public void dispose() { - unregisterInDocument(); + if(isValid()) { + unregisterInTree(); + } } public int getStartOffset() { @@ -85,22 +99,13 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx public void setGreedyToLeft(final boolean greedy) { if (!isValid() || greedy == isGreedyToLeft()) return; - myNode.getTree().changeAttribute(myNode, new Runnable() { - @Override - public void run() { - myNode.setGreedyToLeft(greedy); - } - }); + + myNode.getTree().changeData(this, getStartOffset(), getEndOffset(), greedy, isGreedyToRight(), 0); } public void setGreedyToRight(final boolean greedy) { if (!isValid() || greedy == isGreedyToRight()) return; - myNode.getTree().changeAttribute(myNode, new Runnable() { - @Override - public void run() { - myNode.setGreedyToRight(greedy); - } - }); + myNode.getTree().changeData(this, getStartOffset(), getEndOffset(), isGreedyToLeft(), greedy, 0); } public boolean isGreedyToLeft() { @@ -210,7 +215,7 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx @NonNls public String toString() { return "RangeMarker" + (isGreedyToLeft() ? "[" : "(") + (isValid() ? "valid" : "invalid") + "," + getStartOffset() + "," + getEndOffset() + ( - isGreedyToRight() ? "]" : ")"); + isGreedyToRight() ? "]" : ")") + " " + getId(); } @Override @@ -241,9 +246,7 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx if (node == null) { return -1; } - else { - return node.intervalStart(); - } + return node.intervalStart(); } @Override @@ -252,8 +255,6 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx if (node == null) { return -1; } - else { - return node.intervalEnd(); - } + return node.intervalEnd(); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java index 1c3dd66d76c8..65e4ba599d06 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java @@ -20,22 +20,18 @@ import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.ex.MarkupModelEx; import com.intellij.openapi.editor.ex.PrioritizedDocumentListener; import com.intellij.openapi.editor.ex.RangeMarkerEx; -import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.Segment; -import com.intellij.openapi.util.Trinity; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; /** * User: cdr */ public class RangeMarkerTree extends IntervalTreeImpl { private final PrioritizedDocumentListener myListener; - private final Document myDocument; + final Document myDocument; private final EqualStartIntervalComparator myEqualStartIntervalComparator = new EqualStartIntervalComparator() { @Override public int compare(IntervalNode i1, IntervalNode i2) { @@ -54,9 +50,7 @@ public class RangeMarkerTree extends IntervalTreeImpl extends IntervalTreeImpl checkMax(IntervalNode root, - int deltaUpToRootExclusive, - boolean assertInvalid, - Ref allValid, AtomicInteger counter) { - if (root != null) { - RangeMarkerImpl r = (RangeMarkerImpl)root.getKey(); - if (r != null) { - assert /*r.myNode == null || */r.myNode == root; - assert r.myNode.getTree() == this; - } - } - return super.checkMax(root, deltaUpToRootExclusive, assertInvalid, allValid, counter); - } - - @Override - public IntervalNode addInterval(@NotNull T interval, int start, int end, Object data) { + public MyNode addInterval(@NotNull T interval, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { RangeMarkerImpl marker = (RangeMarkerImpl)interval; marker.setValid(true); - return super.addInterval(interval, start, end, data); - } + RMNode node = (RMNode)super.addInterval(interval, start, end, greedyToLeft, greedyToRight, layer); + ((RangeMarkerImpl)interval).myNode = node; + + checkBelongsToTheTree(interval, true); - @Override - protected RMNode createNewNode(T key, int start, int end, Object data) { - RMNode node = new RMNode(key, start, end); - ((RangeMarkerImpl)key).myNode = node; return node; } - //private static long counter; - private static final AtomicLong counter = new AtomicLong(); + @NotNull + @Override + protected RMNode createNewNode(@NotNull T key, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { + return new RMNode(key, start, end, greedyToLeft, greedyToRight); + } + + @Override + protected void checkBelongsToTheTree(T interval, boolean assertInvalid) { + if (!VERIFY) return; + assert ((RangeMarkerImpl)interval).myDocument == myDocument; + + super.checkBelongsToTheTree(interval, assertInvalid); + } + + @Override + protected MyNode lookupNode(@NotNull T key) { + return ((RangeMarkerImpl)key).myNode; + } + public class RMNode extends MyNode { - private boolean isExpandToLeft = false; - private boolean isExpandToRight = false; - private final long myId; + private final boolean isExpandToLeft; + private final boolean isExpandToRight; - public RMNode(@NotNull T key, int start, int end) { + public RMNode(@NotNull T key, int start, int end, boolean greedyToLeft, boolean greedyToRight) { super(key, start, end); - myId = counter.getAndIncrement(); - //myId = counter++; + isExpandToLeft = greedyToLeft; + isExpandToRight = greedyToRight; } - public void setGreedyToLeft(boolean greedy) { - isExpandToLeft = greedy; - } - - public void setGreedyToRight(boolean greedy) { - isExpandToRight = greedy; + @Override + public boolean processAliveKeys(@NotNull Processor processor) { + return super.processAliveKeys(processor); } public boolean isGreedyToLeft() { @@ -145,8 +135,18 @@ public class RangeMarkerTree extends IntervalTreeImpl extends IntervalTreeImpl affected = new ArrayList(); - updateMarkersOnChange(getRoot(), e, affected); + normalized &= !collectAffectedMarkers(getRoot(), e, affected); checkMax(false); if (!affected.isEmpty()) { @@ -172,7 +171,7 @@ public class RangeMarkerTree extends IntervalTreeImpl extends IntervalTreeImpl aliveKeys = node.getAliveKeys(); + if (aliveKeys.isEmpty()) continue; // collected + RangeMarkerImpl marker = (RangeMarkerImpl)aliveKeys.get(0); marker.setValid(true); //marker.myNode = null; marker.documentChanged(e); if (marker.isValid()) { - insert(node); + RMNode insertedNode = (RMNode)findOrInsert(node); + // can change if two range become the one + if (insertedNode != node) { + // merge happened + for (T interval : aliveKeys) { + insertedNode.addInterval(interval); + } + } + assert marker.isValid(); } } - checkMax(true); } + checkMax(true); IntervalNode root = getRoot(); assert root == null || root.maxEnd + root.delta <= myDocument.getTextLength(); @@ -201,19 +209,20 @@ public class RangeMarkerTree extends IntervalTreeImpl affected) { - if (root == null) return; - pushDelta(root); + // returns true if some delta was or became not null + private boolean collectAffectedMarkers(IntervalNode root, + @NotNull DocumentEvent e, + @NotNull List affected) { + if (root == null) return false; + boolean denorm = pushDelta(root); int maxEnd = root.maxEnd; assert root.isValid(); int offset = e.getOffset(); int affectedEndOffset = offset + e.getOldLength(); - Object key = root.getKey(); - if (key == null) { + boolean hasAliveKeys = root.hasAliveKey(false); + if (!hasAliveKeys) { // marker was garbage collected affected.add(root); } @@ -222,28 +231,31 @@ public class RangeMarkerTree extends IntervalTreeImpl sweepProcessor) { normalize(); return sweep(new Generator() { @@ -252,7 +264,6 @@ public class RangeMarkerTree extends IntervalTreeImpl { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RedBlackTree.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RedBlackTree.java index c616d49cbeff..88919cc518b9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RedBlackTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RedBlackTree.java @@ -15,8 +15,11 @@ */ package com.intellij.openapi.editor.impl; +import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; +import java.util.List; + /** * User: cdr @@ -24,7 +27,7 @@ import org.jetbrains.annotations.NotNull; public abstract class RedBlackTree { public static boolean VERIFY = false; private static final int INDENT_STEP = 4; - protected int size; + private int nodeSize; // number of nodes protected int modCount; protected Node root; @@ -33,8 +36,6 @@ public abstract class RedBlackTree { verifyProperties(); } - protected abstract Node lookupNode(@NotNull K key, Node root); - protected void rotateLeft(Node n) { Node r = n.getRight(); replaceNode(n, r); @@ -78,7 +79,9 @@ public abstract class RedBlackTree { //oldn.right = null; } - protected abstract Node createNewNode(K key, int start, int end, Object data); + protected void onInsertNode() { + nodeSize++; + } protected void insertCase1(Node n) { if (n.getParent() == null) { @@ -137,12 +140,6 @@ public abstract class RedBlackTree { assert node1 == null || node1.getParent() == null || node1.getParent().getLeft() == node1 || node1.getParent().getRight() == node1; } - public Node delete(@NotNull K key) { - Node n = lookupNode(key, root); - deleteNode(n); - return n; - } - protected void deleteNode(Node n) { modCount++; if (n == null) return; // Key not found, do nothing @@ -175,7 +172,9 @@ public abstract class RedBlackTree { if (nodeColor(root) == Color.RED) { root.color = Color.BLACK; } - size--; + + assert nodeSize > 0 : nodeSize; + nodeSize--; verifyProperties(); } @@ -286,10 +285,10 @@ public abstract class RedBlackTree { System.err.print(" "); } if (n.color == Color.BLACK) { - System.err.println(n.getKey()); + System.err.println(n); } else { - System.err.println("<" + n.getKey() + ">"); + System.err.println("<" + n + ">"); } if (n.getLeft() != null) { printHelper(n.getLeft(), indent + INDENT_STEP); @@ -347,7 +346,10 @@ public abstract class RedBlackTree { this.parent = parent; } - public abstract K getKey(); + public abstract boolean processAliveKeys(@NotNull Processor processor); + @NotNull + public abstract List getAliveKeys(); + public abstract boolean hasAliveKey(boolean purgeDead); } protected static enum Color { @@ -355,7 +357,10 @@ public abstract class RedBlackTree { } public int size() { - return size; + return nodeSize; + } + public int nodeSize() { + return nodeSize; } public void verifyProperties() { @@ -426,6 +431,6 @@ public abstract class RedBlackTree { public void clear() { modCount++; root = null; - size = 0; + nodeSize = 0; } } diff --git a/platform/platform-resources-en/src/messages/CommonBundle.properties b/platform/platform-resources-en/src/messages/CommonBundle.properties index 7b941fe2c63b..f1836e5cfc4f 100644 --- a/platform/platform-resources-en/src/messages/CommonBundle.properties +++ b/platform/platform-resources-en/src/messages/CommonBundle.properties @@ -9,13 +9,13 @@ button.cancel=Cancel button.ok=OK button.help=&Help button.retry=&Retry -editbox.password=Password: -checkbox.remember.password=Remember password -editbox.login=Login: -checkbox.use.http.proxy=Use HTTP proxy -checkbox.proxy.authentication=Proxy authentication -editbox.port.number= Port number: -editbox.host.name= Host name: +editbox.password=&Password: +checkbox.remember.password=&Remember password +editbox.login=&Login: +checkbox.use.http.proxy=&Use HTTP proxy +checkbox.proxy.authentication=Proxy &authentication +editbox.port.number= Port &number: +editbox.host.name= &Host name: title.http.proxy.settings=HTTP Proxy Settings tree.node.loading=Loading... title.error=Error diff --git a/platform/platform-resources-en/src/messages/ProjectBundle.properties b/platform/platform-resources-en/src/messages/ProjectBundle.properties index 66375fb926c4..f091a77df3ce 100644 --- a/platform/platform-resources-en/src/messages/ProjectBundle.properties +++ b/platform/platform-resources-en/src/messages/ProjectBundle.properties @@ -225,7 +225,8 @@ classpath.add.new.library.action=New Library... classpath.add.simple.module.library.action=Single-Entry Module Library... classpath.add.library.action=Library... classpath.add.module.dependency.action=Module Dependency... -classpath.chooser.title.add.module.dependency=Choose Dependent Modules +classpath.chooser.title.add.module.dependency=Choose Modules +classpath.chooser.description.add.module.dependency=Select the modules the current module should depend on classpath.title.adding.dependency=Adding dependency classpath.message.library.already.added=Library ''{0}'' already added to this module message.no.module.dependency.candidates=Found no modules to depend on diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index d71e316e438b..7e58a12cb257 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -116,6 +116,4 @@ vcs.show.history.numbers=true navbar.updateMergeTime=250 navbar.userActivityMergeTime=500 -inspectionGadgets.telemetry.enabled=false - -hint.autopopup=true \ No newline at end of file +inspectionGadgets.telemetry.enabled=false \ No newline at end of file diff --git a/platform/platform-resources/src/idea/Keymap_Mac.xml b/platform/platform-resources/src/idea/Keymap_Mac.xml index f1f615b3ce42..97673b9ad796 100644 --- a/platform/platform-resources/src/idea/Keymap_Mac.xml +++ b/platform/platform-resources/src/idea/Keymap_Mac.xml @@ -309,8 +309,8 @@ - - + + diff --git a/platform/platform-resources/src/idea/Keymap_MacClassic.xml b/platform/platform-resources/src/idea/Keymap_MacClassic.xml index 91b192d9cf14..43d7a13abf56 100644 --- a/platform/platform-resources/src/idea/Keymap_MacClassic.xml +++ b/platform/platform-resources/src/idea/Keymap_MacClassic.xml @@ -77,8 +77,8 @@ - - + + diff --git a/platform/testFramework/src/com/intellij/mock/MockDocument.java b/platform/testFramework/src/com/intellij/mock/MockDocument.java index 2156531a7f69..c5a84d8011d2 100644 --- a/platform/testFramework/src/com/intellij/mock/MockDocument.java +++ b/platform/testFramework/src/com/intellij/mock/MockDocument.java @@ -287,10 +287,6 @@ public class MockDocument implements DocumentEx { return false; } - @Override - public void addRangeMarker(@NotNull RangeMarkerEx rangeMarker, int start, int end) { - } - @Override public boolean isInBulkUpdate() { return false; 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 003e446c9749..7ac2cc1acdc6 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -788,6 +788,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig } for (final RangeHighlighter highlighter : myEditor.getDocument().getMarkupModel(project).getAllHighlighters()) { + if (!highlighter.isValid()) continue; addGutterIconRenderer(highlighter.getGutterIconRenderer(), highlighter.getStartOffset(), result); } return ContainerUtil.concat(result.values()); diff --git a/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java b/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java index 9c7bda8404b2..653fc14bb630 100644 --- a/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java +++ b/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java @@ -19,6 +19,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.text.StringTokenizer; import org.apache.oro.text.regex.MalformedPatternException; import org.apache.oro.text.regex.Pattern; import org.apache.oro.text.regex.Perl5Compiler; @@ -38,6 +39,7 @@ public class NameUtil { } }; private static final int MAX_LENGTH = 40; + public static final boolean useMinusculeHumpMatcher = "true".equals(System.getProperty("minuscule.humps.matching")); private NameUtil() {} @@ -388,7 +390,11 @@ public class NameUtil { return buildMatcher(pattern, buildRegexp(pattern, exactPrefixLen, allowToUpper, allowToLower, lowerCaseWords, false)); } - private static Matcher buildMatcher(String pattern, String regexp) { + private static Matcher buildMatcher(final String pattern, String regexp) { + if (useMinusculeHumpMatcher) { + return new MinusculeMatcher(pattern); + } + return new OptimizedMatcher(pattern, regexp); } @@ -468,4 +474,118 @@ public class NameUtil { return true; } } + + + public static class MinusculeMatcher implements Matcher { + private final String myPattern; + + public MinusculeMatcher(String pattern) { + myPattern = pattern.replaceAll(":", "\\*:").replaceAll("\\.", "\\*\\."); + } + + private boolean matches(int patternIndex, List words, int wordIndex) { + if (patternIndex == myPattern.length()) { + return true; + } + if (wordIndex == words.size()) { + return false; + } + + String w = words.get(wordIndex); + + if ('*' == myPattern.charAt(patternIndex)) { + return handleAsterisk(patternIndex, words, wordIndex); + } + + if (isWordSeparator(w.charAt(0))) { + assert w.length() == 1 : "'" + w + "'"; + return matches(isWordSeparator(myPattern.charAt(patternIndex)) ? patternIndex + 1 : patternIndex, words, wordIndex + 1); + } + + if (StringUtil.toLowerCase(w.charAt(0)) != StringUtil.toLowerCase(myPattern.charAt(patternIndex))) { + return false; + } + + int i = 1; + while (true) { + if (patternIndex + i == myPattern.length()) { + return true; + } + if (i == w.length()) { + break; + } + char p = myPattern.charAt(patternIndex + i); + char n = w.charAt(i); + if (n != p && (!Character.isLowerCase(p) || StringUtil.toLowerCase(n) != p)) { + break; + } + i++; + } + // there's more in the pattern, but no more words + if (wordIndex == words.size() - 1) { + if (patternIndex + i == myPattern.length() - 1 && ' ' == myPattern.charAt(patternIndex + i)) { + return i == w.length(); + } + + return false; + } + while (i > 0) { + if (matches(patternIndex + i, words, wordIndex + 1)) { + return true; + } + i--; + } + return false; + } + + private boolean handleAsterisk(int patternIndex, List words, int wordIndex) { + while ('*' == myPattern.charAt(patternIndex)) { + patternIndex++; + if (patternIndex == myPattern.length()) { + return true; + } + } + + String nextChar = String.valueOf(myPattern.charAt(patternIndex)); + + for (int i = wordIndex; i < words.size(); i++) { + String s = words.get(i); + int fromIndex = 0; + while (true) { + int next = StringUtil.indexOfIgnoreCase(s, nextChar, fromIndex); + if (next < 0) { + break; + } + List newWords = new ArrayList(); + newWords.add(s.substring(fromIndex)); + newWords.addAll(words.subList(i + 1, words.size())); + if (matches(patternIndex, newWords, 0)) { + return true; + } + fromIndex = next + 1; + } + } + return false; + } + + private static boolean isWordSeparator(char c) { + return Character.isWhitespace(c) || c == '_' || c == '-'; + } + + @Override + public boolean matches(String name) { + StringTokenizer tokenizer = new StringTokenizer(name, " -_.:", true); + List words = new ArrayList(); + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + addAllWords(token, words); + } + + if (words.isEmpty()) { + return myPattern.equals(name); + } + + return matches(0, words, 0); + } + } } diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index f6f7f4979abe..ecfb00ea0c68 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -768,11 +768,29 @@ public class ContainerUtil { } return result; } + @NotNull + public static List map(@NotNull Collection iterable, @NotNull Function mapping) { + List result = new ArrayList(iterable.size()); + for (T t : iterable) { + result.add(mapping.fun(t)); + } + return result; + } @NotNull public static List mapNotNull(@NotNull T[] array, Function mapping) { return mapNotNull(Arrays.asList(array), mapping); } + public static V[] mapNotNull(@NotNull T[] arr, @NotNull Function mapping, @NotNull V[] emptyArray) { + List result = new ArrayList(arr.length); + for (T t : arr) { + V v = mapping.fun(t); + if (v != null) { + result.add(v); + } + } + return result.toArray(emptyArray); + } @NotNull public static List mapNotNull(Iterable iterable, Function mapping) { @@ -785,6 +803,17 @@ public class ContainerUtil { } return result; } + @NotNull + public static List mapNotNull(Collection iterable, Function mapping) { + List result = new ArrayList(iterable.size()); + for (T t : iterable) { + final V o = mapping.fun(t); + if (o != null) { + result.add(o); + } + } + return result; + } @NotNull public static List packNullables(@NotNull T... elements) { diff --git a/platform/util/src/com/intellij/util/ui/ComboBoxTableCellRenderer.java b/platform/util/src/com/intellij/util/ui/ComboBoxTableCellRenderer.java index 713bc6258408..279d6fb79399 100644 --- a/platform/util/src/com/intellij/util/ui/ComboBoxTableCellRenderer.java +++ b/platform/util/src/com/intellij/util/ui/ComboBoxTableCellRenderer.java @@ -15,6 +15,7 @@ */ package com.intellij.util.ui; +import com.intellij.openapi.diagnostic.LogUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.util.ListWithSelection; @@ -57,7 +58,7 @@ public class ComboBoxTableCellRenderer extends JPanel implements TableCellRender boolean hasFocus, int row, int column) { - LOG.assertTrue(value instanceof ListWithSelection, value.getClass().getName()); + LOG.assertTrue(value instanceof ListWithSelection, LogUtil.objectAndClass(value)); final ListWithSelection tags = (ListWithSelection)value; if (tags.getSelection() == null) { tags.selectFirst(); diff --git a/platform/util/testSrc/com/intellij/util/Assertion.java b/platform/util/testSrc/com/intellij/util/Assertion.java index d8be62de91ea..72e727ad5b2b 100644 --- a/platform/util/testSrc/com/intellij/util/Assertion.java +++ b/platform/util/testSrc/com/intellij/util/Assertion.java @@ -126,7 +126,7 @@ public class Assertion extends Assert { compareAll(expected.toArray(), actual); } - public void compareUnordered(Object[] expected, Collection actual) { + public static void compareUnordered(Object[] expected, Collection actual) { assertEquals(expected.length, actual.size()); for (Object exp : expected) { assertTrue(actual.contains(exp)); @@ -142,11 +142,11 @@ public class Assertion extends Assert { //compareAll(expectedList, actualList); } - public void compareUnordered(Collection expected, Collection actual) { + public static void compareUnordered(Collection expected, Collection actual) { compareUnordered(expected.toArray(), actual); } - public void compareUnordered(Collection expected, Object[] actual) { + public static void compareUnordered(Collection expected, Object[] actual) { compareUnordered(expected, new ArrayList(Arrays.asList(actual))); } @@ -210,7 +210,7 @@ public class Assertion extends Assert { count(number, Arrays.asList(objects)); } - public void compareUnordered(Object[] expected, Object[] actual) { + public static void compareUnordered(Object[] expected, Object[] actual) { compareUnordered(expected, new HashSet(Arrays.asList(actual))); } @@ -235,7 +235,7 @@ public class Assertion extends Assert { compareAll(new int[]{element}, actual); } - public void size(int size, Collection collection) { + public static void size(int size, Collection collection) { if (collection.size() != size) { System.err.println("Expected: " + size + " actual: " + collection.size()); } @@ -268,7 +268,7 @@ public class Assertion extends Assert { } } - public int countOccurences(Collection collection, T item) { + public static int countOccurences(Collection collection, T item) { int counter = 0; for (T obj : collection) { if (Comparing.equal(item, obj)) counter++; @@ -280,7 +280,7 @@ public class Assertion extends Assert { containsAll(collection, Arrays.asList(subArray)); } - public void size(int size, Object[] objects) { + public static void size(int size, Object[] objects) { size(size, Arrays.asList(objects)); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java index bf0671c4fc21..335b77697a24 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java @@ -271,7 +271,7 @@ public class XLineBreakpointImpl

extends XBreak } private boolean canMoveTo(int line, VirtualFile file) { - return file != null && myType.canPutAt(file, line, getProject()); + return file != null && myType.canPutAt(file, line, getProject()) && getBreakpointManager().findBreakpointAtLine(myType, file, line) == null; } @Nullable diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index cbc743a98150..6b2ec4f92f53 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -34,6 +34,7 @@ concrete.class.method.parameter.display.name=Method parameter of concrete class concrete.class.method.parameter.problem.descriptor=Parameter ''{0}'' of concrete class #ref #loc public.method.not.in.interface.display.name='public' method not exposed in interface public.method.not.in.interface.problem.descriptor='public' method #ref() is not exposed via an interface #loc +public.method.not.in.interface.option=Ignore if the containing class does not implement a non-library interface static.variable.of.concrete.class.display.name=Static field of concrete class static.variable.of.concrete.class.problem.descriptor=Static field ''{0}'' of concrete class #ref #loc incompatible.mask.operation.display.name=Incompatible bitwise mask operation @@ -1474,6 +1475,7 @@ notify.without.corresponding.wait.display.name='notify()' without corresponding notify.without.corresponding.wait.problem.descriptor=Call to #ref without corresponding wait() #loc integer.multiplication.implicit.cast.to.long.display.name=Integer multiplication or shift implicitly cast to long integer.multiplication.implicit.cast.to.long.problem.descriptor=#ref: integer multiplication or shift implicitly cast to long #loc +integer.multiplication.implicit.cast.to.long.option=Ignore compile time constant expressions which do not overflow wait.or.await.without.timeout.display.name='wait()' or 'await()' without timeout wait.or.await.without.timeout.problem.descriptor=#ref without timeout #loc boolean.field.always.negated.display.name=Boolean field always negated on read diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/PublicMethodNotExposedInInterfaceInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/PublicMethodNotExposedInInterfaceInspection.java index 7a71eb61609a..8efcd56a7861 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/PublicMethodNotExposedInInterfaceInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/PublicMethodNotExposedInInterfaceInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2010 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2011 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. @@ -15,6 +15,7 @@ */ package com.siyeh.ig.abstraction; +import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import com.intellij.psi.CommonClassNames; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiMethod; @@ -22,12 +23,18 @@ import com.intellij.psi.PsiModifier; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.psiutils.LibraryUtil; import com.siyeh.ig.psiutils.TestUtils; import org.jetbrains.annotations.NotNull; +import javax.swing.*; + public class PublicMethodNotExposedInInterfaceInspection extends BaseInspection { + @SuppressWarnings({"PublicField"}) + public boolean onlyWarnIfContainingClassImplementsAnInterface = false; + @Override @NotNull public String getDisplayName() { @@ -42,12 +49,19 @@ public class PublicMethodNotExposedInInterfaceInspection "public.method.not.in.interface.problem.descriptor"); } + @Override + public JComponent createOptionsPanel() { + return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message( + "public.method.not.in.interface.option"), + this, "onlyWarnIfContainingClassImplementsAnInterface"); + } + @Override public BaseInspectionVisitor buildVisitor() { return new PublicMethodNotExposedInInterface(); } - private static class PublicMethodNotExposedInInterface + private class PublicMethodNotExposedInInterface extends BaseInspectionVisitor { @Override public void visitMethod(@NotNull PsiMethod method) { @@ -75,6 +89,20 @@ public class PublicMethodNotExposedInInterfaceInspection if (!containingClass.hasModifierProperty(PsiModifier.PUBLIC)) { return; } + if (onlyWarnIfContainingClassImplementsAnInterface) { + final PsiClass[] superClasses = containingClass.getSupers(); + boolean implementsInterface = false; + for (PsiClass superClass : superClasses) { + if (superClass.isInterface() && + !LibraryUtil.classIsInLibrary(superClass)) { + implementsInterface = true; + break; + } + } + if (!implementsInterface) { + return; + } + } if (exposedInInterface(method)) { return; } @@ -84,7 +112,7 @@ public class PublicMethodNotExposedInInterfaceInspection registerMethodError(method); } - private static boolean exposedInInterface(PsiMethod method) { + private boolean exposedInInterface(PsiMethod method) { final PsiMethod[] superMethods = method.findSuperMethods(); for(final PsiMethod superMethod : superMethods) { final PsiClass superClass = superMethod.getContainingClass(); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/FinalClassInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/FinalClassInspection.java index b0dfe1f80e50..3e1964c810eb 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/FinalClassInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/FinalClassInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2011 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. @@ -26,26 +26,30 @@ import org.jetbrains.annotations.NotNull; public class FinalClassInspection extends BaseInspection { + @Override @NotNull public String getDisplayName() { return InspectionGadgetsBundle.message("final.class.display.name"); } + @Override @NotNull protected String buildErrorString(Object... infos) { return InspectionGadgetsBundle.message( "final.class.problem.descriptor"); } + @Override public BaseInspectionVisitor buildVisitor() { - return new FinalStaticMethodVisitor(); + return new FinalStaticClassVisitor(); } + @Override public InspectionGadgetsFix buildFix(Object... infos) { return new RemoveModifierFix((String)infos[0]); } - private static class FinalStaticMethodVisitor + private static class FinalStaticClassVisitor extends BaseInspectionVisitor { @Override public void visitClass(@NotNull PsiClass aClass) { diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/FinalPrivateMethodInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/FinalPrivateMethodInspection.java index 0c5e1732208b..bd1d801a5906 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/FinalPrivateMethodInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/FinalPrivateMethodInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2011 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. @@ -26,31 +26,36 @@ import org.jetbrains.annotations.NotNull; public class FinalPrivateMethodInspection extends BaseInspection { + @Override @NotNull public String getDisplayName() { return InspectionGadgetsBundle.message( "final.private.method.display.name"); } + @Override @NotNull protected String buildErrorString(Object... infos) { return InspectionGadgetsBundle.message( "final.private.method.problem.descriptor"); } + @Override public boolean isEnabledByDefault() { return true; } + @Override public BaseInspectionVisitor buildVisitor() { - return new FinalStaticMethodVisitor(); + return new FinalPrivateMethodVisitor(); } + @Override public InspectionGadgetsFix buildFix(Object... infos) { return new RemoveModifierFix((String) infos[0]); } - private static class FinalStaticMethodVisitor + private static class FinalPrivateMethodVisitor extends BaseInspectionVisitor { @Override public void visitMethod(@NotNull PsiMethod method) { diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/IntegerMultiplicationImplicitCastToLongInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/IntegerMultiplicationImplicitCastToLongInspection.java index 6e024b362cc6..9c1ba2ba268e 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/IntegerMultiplicationImplicitCastToLongInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/IntegerMultiplicationImplicitCastToLongInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2007 Dave Griffith, Bas Leijdekkers + * Copyright 2006-2011 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. @@ -15,14 +15,19 @@ */ package com.siyeh.ig.numeric; +import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.ConstantEvaluationOverflowException; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.psiutils.ExpectedTypeUtils; +import com.siyeh.ig.psiutils.ExpressionUtils; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import javax.swing.*; import java.util.HashSet; import java.util.Set; @@ -30,7 +35,8 @@ public class IntegerMultiplicationImplicitCastToLongInspection extends BaseInspection { /** @noinspection StaticCollection*/ - private static final Set s_typesToCheck = new HashSet(10); + @NonNls + private static final Set s_typesToCheck = new HashSet(4); static { s_typesToCheck.add("int"); s_typesToCheck.add("short"); @@ -38,23 +44,36 @@ public class IntegerMultiplicationImplicitCastToLongInspection extends s_typesToCheck.add("char"); } + @SuppressWarnings({"PublicField"}) + public boolean ignoreNonOverflowingCompileTimeConstants = true; + + @Override @NotNull public String getDisplayName() { return InspectionGadgetsBundle.message( "integer.multiplication.implicit.cast.to.long.display.name"); } + @Override @NotNull protected String buildErrorString(Object... infos) { return InspectionGadgetsBundle.message( "integer.multiplication.implicit.cast.to.long.problem.descriptor"); } + @Override + public JComponent createOptionsPanel() { + return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message( + "integer.multiplication.implicit.cast.to.long.option"), + this, "ignoreNonOverflowingCompileTimeConstants"); + } + + @Override public BaseInspectionVisitor buildVisitor() { return new IntegerMultiplicationImplicitlyCastToLongVisitor(); } - private static class IntegerMultiplicationImplicitlyCastToLongVisitor + private class IntegerMultiplicationImplicitlyCastToLongVisitor extends BaseInspectionVisitor { @Override public void visitBinaryExpression( @@ -90,10 +109,19 @@ public class IntegerMultiplicationImplicitCastToLongInspection extends if (!contextType.equals(PsiType.LONG)) { return; } + try { + final Object result = + ExpressionUtils.computeConstantExpression(expression, + true); + if (ignoreNonOverflowingCompileTimeConstants && + result != null) { + return; + } + } catch (ConstantEvaluationOverflowException ignore) {} registerError(expression); } - private static PsiExpression getContainingExpression( + private PsiExpression getContainingExpression( PsiExpression expression) { final PsiElement parent = expression.getParent(); if (parent instanceof PsiBinaryExpression || @@ -105,15 +133,12 @@ public class IntegerMultiplicationImplicitCastToLongInspection extends return expression; } - private static boolean isNonLongInteger(PsiType type) { + private boolean isNonLongInteger(PsiType type) { if (type == null) { return false; } final String text = type.getCanonicalText(); - if (text == null) { - return false; - } - return s_typesToCheck.contains(text); + return text != null && s_typesToCheck.contains(text); } } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ExpressionUtils.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ExpressionUtils.java index 1f02c89ce512..4663d4a85e31 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ExpressionUtils.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ExpressionUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2010 Bas Leijdekkers + * Copyright 2005-2011 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,7 +34,7 @@ public class ExpressionUtils { public static Object computeConstantExpression( @Nullable PsiExpression expression, - boolean throwExceptionOnOverflow) { + boolean throwConstantEvaluationOverflowException) { if (expression == null) { return null; } @@ -43,7 +43,7 @@ public class ExpressionUtils { final PsiConstantEvaluationHelper constantEvaluationHelper = psiFacade.getConstantEvaluationHelper(); return constantEvaluationHelper.computeConstantExpression(expression, - throwExceptionOnOverflow); + throwConstantEvaluationOverflowException); } public static boolean isConstant(PsiField field) { diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/FinalStaticMethod.html b/plugins/InspectionGadgets/src/inspectionDescriptions/FinalStaticMethod.html index eab6a5cd037e..d78ba0deaec8 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/FinalStaticMethod.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/FinalStaticMethod.html @@ -1,9 +1,11 @@ -This inspection reports methods -declared final and static. -As static methods cannot be meaningfully overridden, declaring them -final is redundant. +This inspection reports methods declared final and static. +When a static method is overridden in a subclass it can still be +accessed via the super class, making a final declaration not very necessary. +Declaring a static method final +does prevent subclasses from defining a static method with the same +signature.

Powered by InspectionGadgets diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/IntegerMultiplicationImplicitCastToLong.html b/plugins/InspectionGadgets/src/inspectionDescriptions/IntegerMultiplicationImplicitCastToLong.html index 4bd07563ca71..b8f997c55025 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/IntegerMultiplicationImplicitCastToLong.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/IntegerMultiplicationImplicitCastToLong.html @@ -4,6 +4,9 @@ This inspection reports integer multiplication or left shift which are implicitly cast to long. Such multiplication is often an error, as overflow truncation may occur unexpectedly.

+Use the checkbox below to ignore compile time constant expressions which evaluate to +a non-overflowing value. +

Powered by InspectionGadgets \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/PublicMethodNotExposedInInterface.html b/plugins/InspectionGadgets/src/inspectionDescriptions/PublicMethodNotExposedInInterface.html index 1e7218036af1..84311308b45d 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/PublicMethodNotExposedInInterface.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/PublicMethodNotExposedInInterface.html @@ -4,6 +4,9 @@ This inspection reports public methods in classes which are not exposed as in interface. Exposing all public methods via interface is important for maintaining loose coupling, and may be necessary for certain component-based programming styles.

+Use the checkbox below to ignore methods of which the containing class does not +implement a non-library interface. +

Powered by InspectionGadgets \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubLoginPanel.form b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubLoginPanel.form index 3fc070c35ec8..218243985ea7 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubLoginPanel.form +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubLoginPanel.form @@ -1,9 +1,9 @@

- + - + @@ -65,7 +65,7 @@ - + @@ -87,6 +87,15 @@ + + + + + +