From c8f98b9e43ffa3645688d6bca2c459fb2239cc77 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 25 Aug 2010 20:04:01 +0100 Subject: [PATCH 1/9] dead code --- .../extapi/psi/MetadataPsiFileBase.java | 63 ------------------- 1 file changed, 63 deletions(-) delete mode 100644 platform/lang-impl/src/com/intellij/extapi/psi/MetadataPsiFileBase.java diff --git a/platform/lang-impl/src/com/intellij/extapi/psi/MetadataPsiFileBase.java b/platform/lang-impl/src/com/intellij/extapi/psi/MetadataPsiFileBase.java deleted file mode 100644 index b5d408fc51e8..000000000000 --- a/platform/lang-impl/src/com/intellij/extapi/psi/MetadataPsiFileBase.java +++ /dev/null @@ -1,63 +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. - */ - -package com.intellij.extapi.psi; - -import com.intellij.lang.Language; -import com.intellij.lang.LanguageParserDefinitions; -import com.intellij.lang.ParserDefinition; -import com.intellij.psi.FileViewProvider; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.PsiFileImpl; -import com.intellij.psi.tree.IFileElementType; -import org.jetbrains.annotations.NotNull; - -public abstract class MetadataPsiFileBase extends PsiFileImpl { - - @NotNull private final Language myLanguage; - @NotNull private final ParserDefinition myParserDefinition; - private PsiFile mySourceFile; - - public MetadataPsiFileBase(FileViewProvider provider, @NotNull Language language) { - super(provider); - myLanguage = language; - final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(language); - if (parserDefinition == null) { - throw new RuntimeException("PsiFileBase: language.getParserDefinition() returned null."); - } - myParserDefinition = parserDefinition; - final IFileElementType nodeType = parserDefinition.getFileNodeType(); - init(nodeType, nodeType); - } - - public void accept(@NotNull PsiElementVisitor visitor) { - visitor.visitFile(this); - } - - @NotNull - public final Language getLanguage() { - return myLanguage; - } - - public final PsiFile getSourceFile() { - return mySourceFile; - } - - public final void setSourceFile(final PsiFile sourceFile) { - mySourceFile = sourceFile; - } -} From ce2b00c138b5a88b6dbd5d27b17a05692eef9dee Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 26 Aug 2010 11:52:14 +0100 Subject: [PATCH 2/9] brace matching for plain text files, also when used as the template data in freemarker --- .../psi/CustomHighlighterTokenType.java | 2 + .../editorActions/TypedHandler.java | 7 +- .../BraceHighlightingHandler.java | 3 +- .../highlighting/BraceMatchingUtil.java | 7 +- .../custom/AbstractCustomLexer.java | 8 ++- .../custom/CustomFileTypeLexer.java | 17 ++--- .../impl/CustomFileTypeBraceMatcher.java | 8 ++- .../custom/tokens/BraceTokenParser.java | 13 ++++ .../PlainTextSyntaxHighlighterFactory.java | 69 +++++++++++++++++++ .../psi/impl/source/PsiPlainTextFileImpl.java | 4 +- .../fileTypes/SyntaxHighlighterBase.java | 2 +- .../src/META-INF/LangExtensions.xml | 3 +- 12 files changed, 116 insertions(+), 27 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/openapi/fileTypes/PlainTextSyntaxHighlighterFactory.java diff --git a/platform/lang-api/src/com/intellij/psi/CustomHighlighterTokenType.java b/platform/lang-api/src/com/intellij/psi/CustomHighlighterTokenType.java index 41ae1093e409..69ec75192dbe 100644 --- a/platform/lang-api/src/com/intellij/psi/CustomHighlighterTokenType.java +++ b/platform/lang-api/src/com/intellij/psi/CustomHighlighterTokenType.java @@ -49,6 +49,8 @@ public interface CustomHighlighterTokenType { IElementType L_BRACE = new CustomElementType("L_BRACE"); IElementType R_BRACE = new CustomElementType("R_BRACE"); + IElementType L_ANGLE = new CustomElementType("L_BROCKET"); + IElementType R_ANGLE = new CustomElementType("R_BROCKET"); IElementType L_BRACKET = new CustomElementType("L_BRACKET"); IElementType R_BRACKET = new CustomElementType("R_BRACKET"); IElementType L_PARENTH = new CustomElementType("L_PARENTH"); 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 91952b218816..4a7186134f0d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java @@ -43,7 +43,6 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -182,8 +181,7 @@ public class TypedHandler implements TypedActionHandler { EditorModificationUtil.deleteSelectedText(editor); } - final VirtualFile virtualFile = file.getVirtualFile(); - FileType fileType = virtualFile == null ? file.getFileType() : virtualFile.getFileType(); + FileType fileType = file.getFileType(); for(TypedHandlerDelegate delegate: delegates) { final TypedHandlerDelegate.Result result = delegate.beforeCharTyped(charTyped, project, editor, file, fileType); @@ -428,8 +426,7 @@ public class TypedHandler implements TypedActionHandler { text = "}"; } else { - LOG.error("Unknown char "+lparenChar); - return; + throw new AssertionError("Unknown char "+lparenChar); } editor.getDocument().insertString(offset, text); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java index 307946e4e48a..23b38fc4e612 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java @@ -98,8 +98,7 @@ public class BraceHighlightingHandler { if (isReallyDisposed(editor, project)) return; final PsiFile injected = ApplicationManager.getApplication().runReadAction(new Computable() { public PsiFile compute() { - Document document = editor.getDocument(); - PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); + PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(editor, project); return null != psiFile ? getInjectedFileIfAny(editor, project, offset, psiFile, alarm) : null; } }); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceMatchingUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceMatchingUtil.java index c3bbed3225fa..bc88310ff066 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceMatchingUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceMatchingUtil.java @@ -320,13 +320,14 @@ public class BraceMatchingUtil { @NotNull public static BraceMatcher getBraceMatcher(FileType fileType, Language lang) { - final BraceMatcher byFileType = getBraceMatcherByFileType(fileType); - if (byFileType != null) return byFileType; - PairedBraceMatcher matcher = LanguageBraceMatching.INSTANCE.forLanguage(lang); if (matcher != null) { return new PairedBraceMatcherAdapter(matcher, lang); } + + final BraceMatcher byFileType = getBraceMatcherByFileType(fileType); + if (byFileType != null) return byFileType; + if (fileType instanceof LanguageFileType) { final Language language = ((LanguageFileType)fileType).getLanguage(); if (lang != language) { 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 bd4b8ed2bfa9..b0607907da73 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 @@ -23,10 +23,12 @@ import com.intellij.psi.CustomHighlighterTokenType; import com.intellij.psi.tree.IElementType; import com.intellij.util.ArrayUtil; +import java.util.List; + /** * @author dsl */ -public abstract class AbstractCustomLexer extends LexerBase { +public class AbstractCustomLexer extends LexerBase { protected CharSequence myBuffer = ArrayUtil.EMPTY_CHAR_SEQUENCE; protected int myStartOffset = 0; protected int myEndOffset = 0; @@ -34,8 +36,8 @@ public abstract class AbstractCustomLexer extends LexerBase { private TokenInfo myCurrentToken; private int myPosition; - public AbstractCustomLexer(TokenParser[] tokenParsers) { - myTokenParsers = tokenParsers; + public AbstractCustomLexer(List tokenParsers) { + myTokenParsers = tokenParsers.toArray(new TokenParser[tokenParsers.size()]); int smartUpdateShift = 0; for (TokenParser tokenParser : myTokenParsers) { 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 6506934c0c73..f7cd4d844c6b 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,6 +20,7 @@ import com.intellij.ide.highlighter.custom.tokens.*; import com.intellij.psi.CustomHighlighterTokenType; import java.util.ArrayList; +import java.util.List; import java.util.Set; /** @@ -34,8 +35,7 @@ public final class CustomFileTypeLexer extends AbstractCustomLexer { this(table, false); } - private static TokenParser[] buildTokenParsers(SyntaxTable table, boolean forHighlighting) { - final WhitespaceParser whitespaceParser = new WhitespaceParser(); + private static List buildTokenParsers(SyntaxTable table, boolean forHighlighting) { final LineCommentParser lineCommentParser = LineCommentParser.create(table.getLineComment()); final MultilineCommentParser multilineCommentParser = MultilineCommentParser.create(table.getStartComment(), table.getEndComment()); @@ -55,7 +55,7 @@ public final class CustomFileTypeLexer extends AbstractCustomLexer { ); ArrayList tokenParsers = new ArrayList(); - tokenParsers.add(whitespaceParser); + tokenParsers.add(new WhitespaceParser()); tokenParsers.add(quotedStringParser); tokenParsers.add(quotedStringParser2); if (lineCommentParser != null) { @@ -73,21 +73,18 @@ public final class CustomFileTypeLexer extends AbstractCustomLexer { tokenParsers.add(identifierParser); if (table.isHasBraces()) { - tokenParsers.add(new BraceTokenParser("{", CustomHighlighterTokenType.L_BRACE)); - tokenParsers.add(new BraceTokenParser("}", CustomHighlighterTokenType.R_BRACE)); + tokenParsers.addAll(BraceTokenParser.BRACES); } if (table.isHasParens()) { - tokenParsers.add(new BraceTokenParser("(", CustomHighlighterTokenType.L_PARENTH)); - tokenParsers.add(new BraceTokenParser(")", CustomHighlighterTokenType.R_PARENTH)); + tokenParsers.addAll(BraceTokenParser.PARENS); } if (table.isHasBrackets()) { - tokenParsers.add(new BraceTokenParser("[", CustomHighlighterTokenType.L_BRACKET)); - tokenParsers.add(new BraceTokenParser("]", CustomHighlighterTokenType.R_BRACKET)); + tokenParsers.addAll(BraceTokenParser.BRACKETS); } - return tokenParsers.toArray(new TokenParser[tokenParsers.size()]); + return tokenParsers; } diff --git a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeBraceMatcher.java b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeBraceMatcher.java index 684ab7972e54..83fc1c33e143 100644 --- a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeBraceMatcher.java +++ b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeBraceMatcher.java @@ -28,7 +28,7 @@ import org.jetbrains.annotations.Nullable; /** * @author Maxim.Mossienko */ -class CustomFileTypeBraceMatcher implements BraceMatcher { +public class CustomFileTypeBraceMatcher implements BraceMatcher { public int getBraceTokenGroupId(IElementType tokenType) { return 777; } @@ -37,6 +37,7 @@ class CustomFileTypeBraceMatcher implements BraceMatcher { final IElementType tokenType = iterator.getTokenType(); return tokenType == CustomHighlighterTokenType.L_BRACKET || + tokenType == CustomHighlighterTokenType.L_ANGLE || tokenType == CustomHighlighterTokenType.L_PARENTH || tokenType == CustomHighlighterTokenType.L_BRACE; } @@ -47,6 +48,7 @@ class CustomFileTypeBraceMatcher implements BraceMatcher { private static boolean isRBraceToken(IElementType tokenType) { return tokenType == CustomHighlighterTokenType.R_BRACKET || + tokenType == CustomHighlighterTokenType.R_ANGLE || tokenType == CustomHighlighterTokenType.R_PARENTH || tokenType == CustomHighlighterTokenType.R_BRACE; } @@ -56,6 +58,8 @@ class CustomFileTypeBraceMatcher implements BraceMatcher { (tokenType == CustomHighlighterTokenType.R_BRACE && tokenType2 == CustomHighlighterTokenType.L_BRACE) || (tokenType == CustomHighlighterTokenType.L_BRACKET && tokenType2 == CustomHighlighterTokenType.R_BRACKET) || (tokenType == CustomHighlighterTokenType.R_BRACKET && tokenType2 == CustomHighlighterTokenType.L_BRACKET) || + (tokenType == CustomHighlighterTokenType.L_ANGLE && tokenType2 == CustomHighlighterTokenType.R_ANGLE) || + (tokenType == CustomHighlighterTokenType.R_ANGLE && tokenType2 == CustomHighlighterTokenType.L_ANGLE) || (tokenType == CustomHighlighterTokenType.L_PARENTH && tokenType2 == CustomHighlighterTokenType.R_PARENTH) || (tokenType == CustomHighlighterTokenType.R_PARENTH && tokenType2 == CustomHighlighterTokenType.L_PARENTH); } @@ -75,6 +79,8 @@ class CustomFileTypeBraceMatcher implements BraceMatcher { if (type == CustomHighlighterTokenType.L_BRACKET) return CustomHighlighterTokenType.R_BRACKET; if (type == CustomHighlighterTokenType.R_BRACKET) return CustomHighlighterTokenType.L_BRACKET; + if (type == CustomHighlighterTokenType.L_ANGLE) return CustomHighlighterTokenType.R_ANGLE; + if (type == CustomHighlighterTokenType.R_ANGLE) return CustomHighlighterTokenType.L_ANGLE; if (type == CustomHighlighterTokenType.L_PARENTH) return CustomHighlighterTokenType.R_PARENTH; if (type == CustomHighlighterTokenType.R_PARENTH) return CustomHighlighterTokenType.L_PARENTH; diff --git a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/BraceTokenParser.java b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/BraceTokenParser.java index dea3904e99a7..748fd0de4b6b 100644 --- a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/BraceTokenParser.java +++ b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/tokens/BraceTokenParser.java @@ -16,12 +16,25 @@ package com.intellij.ide.highlighter.custom.tokens; +import com.intellij.psi.CustomHighlighterTokenType; import com.intellij.psi.tree.IElementType; +import java.util.Arrays; +import java.util.List; + /** * @author Maxim.Mossienko */ public class BraceTokenParser extends PrefixedTokenParser { + public static final List BRACES = Arrays.asList(new BraceTokenParser("{", CustomHighlighterTokenType.L_BRACE), + new BraceTokenParser("}", CustomHighlighterTokenType.R_BRACE)); + public static final List PARENS = Arrays.asList(new BraceTokenParser("(", CustomHighlighterTokenType.L_PARENTH), + new BraceTokenParser(")", CustomHighlighterTokenType.R_PARENTH)); + public static final List BRACKETS = Arrays.asList(new BraceTokenParser("[", CustomHighlighterTokenType.L_BRACKET), + new BraceTokenParser("]", CustomHighlighterTokenType.R_BRACKET)); + public static final List ANGLE_BRACKETS = Arrays.asList(new BraceTokenParser("<", CustomHighlighterTokenType.L_ANGLE), + new BraceTokenParser(">", CustomHighlighterTokenType.R_ANGLE)); + public BraceTokenParser(String prefix, IElementType tokenType) { super(prefix, tokenType); } diff --git a/platform/lang-impl/src/com/intellij/openapi/fileTypes/PlainTextSyntaxHighlighterFactory.java b/platform/lang-impl/src/com/intellij/openapi/fileTypes/PlainTextSyntaxHighlighterFactory.java new file mode 100644 index 000000000000..e8dd39e090ec --- /dev/null +++ b/platform/lang-impl/src/com/intellij/openapi/fileTypes/PlainTextSyntaxHighlighterFactory.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +/* + * @author max + */ +package com.intellij.openapi.fileTypes; + +import com.intellij.ide.highlighter.custom.AbstractCustomLexer; +import com.intellij.ide.highlighter.custom.CustomHighlighterColors; +import com.intellij.ide.highlighter.custom.tokens.*; +import com.intellij.lexer.Lexer; +import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.CustomHighlighterTokenType; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; + +/** + * @author peter + */ +public class PlainTextSyntaxHighlighterFactory extends SyntaxHighlighterFactory { + @NotNull + public SyntaxHighlighter getSyntaxHighlighter(final Project project, final VirtualFile virtualFile) { + return new SyntaxHighlighterBase() { + @NotNull + @Override + public Lexer getHighlightingLexer() { + ArrayList tokenParsers = new ArrayList(); + tokenParsers.add(new WhitespaceParser()); + tokenParsers.add(new NumberParser("", false)); + tokenParsers.add(new PunctuationParser()); + tokenParsers.add(new IdentifierParser()); + + tokenParsers.addAll(BraceTokenParser.BRACES); + tokenParsers.addAll(BraceTokenParser.PARENS); + tokenParsers.addAll(BraceTokenParser.BRACKETS); + tokenParsers.addAll(BraceTokenParser.ANGLE_BRACKETS); + + return new AbstractCustomLexer(tokenParsers); + } + + @NotNull + @Override + public TextAttributesKey[] getTokenHighlights(IElementType tokenType) { + if (tokenType == CustomHighlighterTokenType.NUMBER) { + return new TextAttributesKey[]{CustomHighlighterColors.CUSTOM_NUMBER_ATTRIBUTES}; + } + return EMPTY; + } + }; + } +} \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/PsiPlainTextFileImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/PsiPlainTextFileImpl.java index 6ec5b043281a..2f955978b7f6 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/PsiPlainTextFileImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/PsiPlainTextFileImpl.java @@ -17,6 +17,8 @@ package com.intellij.psi.impl.source; import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.PlainTextLanguage; +import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; import org.jetbrains.annotations.NotNull; @@ -26,7 +28,7 @@ public class PsiPlainTextFileImpl extends PsiFileImpl implements PsiPlainTextFil public PsiPlainTextFileImpl(FileViewProvider viewProvider) { super(PlainTextTokenTypes.PLAIN_TEXT_FILE, PlainTextTokenTypes.PLAIN_TEXT_FILE, viewProvider); - myFileType = viewProvider.getVirtualFile().getFileType(); + myFileType = viewProvider.getBaseLanguage() != PlainTextLanguage.INSTANCE ? StdFileTypes.PLAIN_TEXT : viewProvider.getVirtualFile().getFileType(); } public void accept(@NotNull PsiElementVisitor visitor){ diff --git a/platform/platform-api/src/com/intellij/openapi/fileTypes/SyntaxHighlighterBase.java b/platform/platform-api/src/com/intellij/openapi/fileTypes/SyntaxHighlighterBase.java index d8c21862cfae..6b8e055d4cf2 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileTypes/SyntaxHighlighterBase.java +++ b/platform/platform-api/src/com/intellij/openapi/fileTypes/SyntaxHighlighterBase.java @@ -22,7 +22,7 @@ import com.intellij.psi.tree.TokenSet; import java.util.Map; public abstract class SyntaxHighlighterBase implements SyntaxHighlighter { - private static final TextAttributesKey[] EMPTY = new TextAttributesKey[0]; + protected static final TextAttributesKey[] EMPTY = new TextAttributesKey[0]; public static TextAttributesKey[] pack(TextAttributesKey key) { if (key == null) return EMPTY; diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 267f44fe3c8b..21c5ea185308 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -282,7 +282,8 @@ - + + From acac73de5e948eb509e85fa2d260f292aeaf46de Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 26 Aug 2010 16:47:32 +0100 Subject: [PATCH 3/9] smart primitive constant completion to work in binary expressions like | --- .../psi/filters/getters/MembersGetter.java | 55 +++++++++++-------- .../smartType/UseIntConstantsInOr-out.java | 15 +++++ .../smartType/UseIntConstantsInOr.java | 15 +++++ .../smartType/UseIntConstantsInPlus-out.java | 15 +++++ .../smartType/UseIntConstantsInPlus.java | 15 +++++ .../completion/SmartTypeCompletionTest.java | 2 + 6 files changed, 94 insertions(+), 23 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInOr-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInOr.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInPlus-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInPlus.java diff --git a/java/java-impl/src/com/intellij/psi/filters/getters/MembersGetter.java b/java/java-impl/src/com/intellij/psi/filters/getters/MembersGetter.java index 5606d343ccab..48faf39370bc 100644 --- a/java/java-impl/src/com/intellij/psi/filters/getters/MembersGetter.java +++ b/java/java-impl/src/com/intellij/psi/filters/getters/MembersGetter.java @@ -25,6 +25,7 @@ import com.intellij.codeInsight.lookup.LookupItemUtil; import com.intellij.psi.*; import com.intellij.psi.filters.TrueFilter; import com.intellij.psi.scope.processor.FilterScopeProcessor; +import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.Nullable; @@ -40,31 +41,35 @@ public class MembersGetter { public static void addMembers(PsiElement position, PsiType expectedType, CompletionResultSet results) { final PsiClass psiClass = PsiUtil.resolveClassInType(expectedType); - if (psiClass != null) { - processMembers(position, results, psiClass, PsiTreeUtil.getParentOfType(position, PsiAnnotation.class) != null, expectedType); - } + processMembers(position, results, psiClass, PsiTreeUtil.getParentOfType(position, PsiAnnotation.class) != null, expectedType); if (expectedType instanceof PsiPrimitiveType && PsiType.DOUBLE.isAssignableFrom(expectedType)) { - final PsiElement parent = position.getParent(); - if (parent instanceof PsiReferenceExpression) { - final PsiElement refParent = parent.getParent(); - if (refParent instanceof PsiExpressionList) { - final PsiClass aClass = getCalledClass(refParent.getParent()); - if (aClass != null) { - processMembers(position, results, aClass, false, expectedType); - } - } - else if (refParent instanceof PsiBinaryExpression) { - final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)refParent; - if (parent == binaryExpression.getROperand() && - JavaTokenType.EQEQ == binaryExpression.getOperationSign().getTokenType()) { - final PsiClass aClass = getCalledClass(binaryExpression.getLOperand()); - if (aClass != null) { - processMembers(position, results, aClass, false, expectedType); - } - } + addConstantsFromTargetClass(position, expectedType, results); + } + } + + private static void addConstantsFromTargetClass(PsiElement position, PsiType expectedType, CompletionResultSet results) { + PsiElement parent = position.getParent(); + if (!(parent instanceof PsiReferenceExpression)) { + return; + } + + PsiElement prev = parent; + parent = parent.getParent(); + while (parent instanceof PsiBinaryExpression) { + final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)parent; + final IElementType op = binaryExpression.getOperationSign().getTokenType(); + if (JavaTokenType.EQEQ == op || JavaTokenType.NE == op) { + if (prev == binaryExpression.getROperand()) { + processMembers(position, results, getCalledClass(binaryExpression.getLOperand()), false, expectedType); } + return; } + prev = parent; + parent = parent.getParent(); + } + if (parent instanceof PsiExpressionList) { + processMembers(position, results, getCalledClass(parent.getParent()), false, expectedType); } } @@ -95,8 +100,10 @@ public class MembersGetter { return null; } - private static void processMembers(final PsiElement context, final CompletionResultSet results, final PsiClass where, + private static void processMembers(final PsiElement context, final CompletionResultSet results, @Nullable final PsiClass where, final boolean acceptMethods, PsiType expectedType) { + if (where == null) return; + final FilterScopeProcessor processor = new FilterScopeProcessor(TrueFilter.INSTANCE); where.processDeclarations(processor, ResolveState.initial(), null, context); @@ -113,7 +120,9 @@ public class MembersGetter { item.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE); JavaCompletionUtil.qualify(item); if (member instanceof PsiMethod) { - ((JavaMethodCallElement) item).setInferenceSubstitutor(SmartCompletionDecorator.calculateMethodReturnTypeSubstitutor((PsiMethod) member, expectedType)); + final PsiMethod method = (PsiMethod)member; + final PsiSubstitutor substitutor = SmartCompletionDecorator.calculateMethodReturnTypeSubstitutor(method, expectedType); + ((JavaMethodCallElement) item).setInferenceSubstitutor(substitutor); } results.addElement(item); } diff --git a/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInOr-out.java b/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInOr-out.java new file mode 100644 index 000000000000..2c6d84a06d75 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInOr-out.java @@ -0,0 +1,15 @@ +class Foo { + public static final int FOO_FOO; + public static final int FOO_BAR; + + Foo(int a) {} + + void foo(int x); +} + +public class Bar { + + { + new Foo(2 | Foo.FOO_BAR) + } +} diff --git a/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInOr.java b/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInOr.java new file mode 100644 index 000000000000..7c4d822b11ca --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInOr.java @@ -0,0 +1,15 @@ +class Foo { + public static final int FOO_FOO; + public static final int FOO_BAR; + + Foo(int a) {} + + void foo(int x); +} + +public class Bar { + + { + new Foo(2 | FB) + } +} diff --git a/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInPlus-out.java b/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInPlus-out.java new file mode 100644 index 000000000000..8122f1052be4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInPlus-out.java @@ -0,0 +1,15 @@ +class Foo { + public static final int FOO_FOO; + public static final int FOO_BAR; + + Foo(int a) {} + + void foo(int x); +} + +public class Bar { + + { + new Foo(2 + Foo.FOO_BAR) + } +} diff --git a/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInPlus.java b/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInPlus.java new file mode 100644 index 000000000000..88d89a73a2b4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInPlus.java @@ -0,0 +1,15 @@ +class Foo { + public static final int FOO_FOO; + public static final int FOO_BAR; + + Foo(int a) {} + + void foo(int x); +} + +public class Bar { + + { + new Foo(2 + FB) + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java index d194054d0279..c76e9cfb2c18 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -636,6 +636,8 @@ public class SmartTypeCompletionTest extends LightCompletionTestCase { public void testUseIntConstantsFromTargetClass() throws Throwable { doTest(); } public void testUseIntConstantsFromTargetClassReturnValue() throws Throwable { doTest(); } public void testUseIntConstantsFromConstructedClass() throws Throwable { doTest(); } + public void testUseIntConstantsInPlus() throws Throwable { doTest(); } + public void testUseIntConstantsInOr() throws Throwable { doTest(); } public void testExtraSemicolonAfterMethodParam() throws Throwable { CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(getProject()); From 0afff998b0337345dff65ab67dbd74d6800ae9b2 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 26 Aug 2010 17:07:18 +0100 Subject: [PATCH 4/9] don't throw exceptions when completing in the RHS of >>, complete instead --- .../com/intellij/codeInsight/ExpectedTypesProvider.java | 4 +--- .../codeInsight/completion/normal/RightShift.java | 8 ++++++++ .../codeInsight/completion/NormalCompletionTest.java | 5 +++++ 3 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normal/RightShift.java diff --git a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java index 50ab6cf4d823..fa4f769e6142 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java @@ -645,9 +645,7 @@ public class ExpectedTypesProvider { myResult = ExpectedTypeInfo.EMPTY_ARRAY; } else { - ExpectedTypeInfoImpl info = createInfoImpl(PsiType.LONG, ExpectedTypeInfo.TYPE_BETWEEN, - myExpr.getType(), TailType.NONE); - myResult = new ExpectedTypeInfo[]{info}; + myResult = new ExpectedTypeInfo[]{createInfoImpl(PsiType.LONG, ExpectedTypeInfo.TYPE_BETWEEN, PsiType.INT, TailType.NONE)}; } } else if (i == JavaTokenType.OROR || i == JavaTokenType.ANDAND) { diff --git a/java/java-tests/testData/codeInsight/completion/normal/RightShift.java b/java/java-tests/testData/codeInsight/completion/normal/RightShift.java new file mode 100644 index 000000000000..40d03f2b9c7b --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/RightShift.java @@ -0,0 +1,8 @@ +public class SomeClass { + Object myField1; + Object myField2; + + void foo(int param) { + int a = param >> my + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.java index ca2bcc875713..8f0fbf5e1482 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.java @@ -645,5 +645,10 @@ public class NormalCompletionTest extends LightCompletionTestCase { public void testPrimitiveMethodParameter() throws Throwable { doTest(); } + public void testRightShift() throws Throwable { + configureByFile("/codeInsight/completion/normal/" + getTestName(false) + ".java"); + assertStringItems("myField1", "myField2"); + } + } From 3a364bbe419a0622bb76a3ec16e4d771e1dba67f Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 26 Aug 2010 19:23:28 +0100 Subject: [PATCH 5/9] java global member name completion initial (IDEA-54855) --- ...GlobalMemberNameCompletionContributor.java | 113 ++++++++++++++++++ .../simple/PsiMethodInsertHandler.java | 16 +-- java/java-tests/java-tests.iml | 1 + .../GlobalMemberNameCompletionTest.groovy | 29 +++++ .../completion/InsertionContext.java | 8 +- .../fixtures/CodeInsightTestFixture.java | 2 + .../impl/CodeInsightTestFixtureImpl.java | 7 ++ resources/src/META-INF/IdeaPlugin.xml | 5 +- 8 files changed, 171 insertions(+), 10 deletions(-) create mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java create mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/completion/GlobalMemberNameCompletionTest.groovy diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java new file mode 100644 index 000000000000..4930dcf47973 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java @@ -0,0 +1,113 @@ +package com.intellij.codeInsight.completion; + +import com.intellij.codeInsight.completion.simple.PsiMethodInsertHandler; +import com.intellij.codeInsight.lookup.*; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.Iconable; +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.PsiTreeUtil; + +/** + * @author peter + */ +public class JavaGlobalMemberNameCompletionContributor extends CompletionContributor { + + private static final LookupElementRenderer STATIC_METHOD_RENDERER = new LookupElementRenderer() { + @Override + public void renderElement(LookupElement element, LookupElementPresentation presentation) { + PsiMethod method = (PsiMethod)element.getObject(); + final PsiClass containingClass = method.getContainingClass(); + presentation.setIcon(method.getIcon(Iconable.ICON_FLAG_VISIBILITY)); //todo don't calculate if not a real presentation + presentation.setItemText(method.getName()); + final String params = PsiFormatUtil.formatMethod(method, PsiSubstitutor.EMPTY, + PsiFormatUtil.SHOW_PARAMETERS, + PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE); + if (containingClass != null) { + presentation.setTailText(params + " in (" + containingClass.getName() + ")"); + } else { + presentation.setTailText(params); + } + final PsiType type = method.getReturnType(); + if (type != null) { + presentation.setTypeText(type.getPresentableText()); + } + } + }; + private static final InsertHandler STATIC_METHOD_INSERT_HANDLER = new InsertHandler() { + @Override + public void handleInsert(InsertionContext context, LookupElement item) { + PsiMethodInsertHandler.INSTANCE.handleInsert(context, item); + final PsiClass containingClass = ((PsiMethod)item.getObject()).getContainingClass(); + if (containingClass != null) { + PsiDocumentManager.getInstance(containingClass.getProject()).commitDocument(context.getDocument()); + final PsiReferenceExpression ref = PsiTreeUtil + .findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiReferenceExpression.class, false); + if (ref != null) { + ref.bindToElementViaStaticImport(containingClass); + } + } + } + }; + + @Override + public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet result) { + if (parameters.getCompletionType() != CompletionType.CLASS_NAME) { + return; + } + + final PrefixMatcher matcher = result.getPrefixMatcher(); + final String prefix = matcher.getPrefix(); + if (prefix.length() == 0 || !Character.isLowerCase(prefix.charAt(0))) { + return; + } + + final PsiElement position = parameters.getPosition(); + final PsiElement parent = position.getParent(); + if (!(parent instanceof PsiReferenceExpression)) { + return; + } + final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)parent; + if (referenceExpression.isQualified()) { + return; + } + + final Project project = position.getProject(); + final GlobalSearchScope scope = GlobalSearchScope.allScope(project); + final PsiShortNamesCache namesCache = JavaPsiFacade.getInstance(project).getShortNamesCache(); + final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper(); + final String[] methodNames = ApplicationManager.getApplication().runReadAction(new Computable() { + public String[] compute() { + return namesCache.getAllMethodNames(); + } + }); + for (final String methodName : methodNames) { + if (matcher.prefixMatches(methodName)) { + final PsiMethod[] methods = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiMethod[] compute() { + return namesCache.getMethodsByName(methodName, scope); + } + }); + for (final PsiMethod method : methods) { + ApplicationManager.getApplication().runReadAction(new Runnable() { + public void run() { + if (method.hasModifierProperty(PsiModifier.STATIC) && resolveHelper.isAccessible(method, position, null)) { + final PsiClass containingClass = method.getContainingClass(); + if (containingClass != null) { + result.addElement(LookupElementDecorator.withInsertHandler( + LookupElementDecorator.withRenderer(LookupElementBuilder.create(method), STATIC_METHOD_RENDERER), + STATIC_METHOD_INSERT_HANDLER)); + } + } + } + }); + + } + } + } + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/simple/PsiMethodInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/simple/PsiMethodInsertHandler.java index 5826964f43a9..fb6cad1fd4fa 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/simple/PsiMethodInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/simple/PsiMethodInsertHandler.java @@ -39,11 +39,11 @@ import org.jetbrains.annotations.Nullable; /** * @author peter */ -public class PsiMethodInsertHandler implements InsertHandler> { +public class PsiMethodInsertHandler implements InsertHandler { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.simple.PsiMethodInsertHandler"); public static final PsiMethodInsertHandler INSTANCE = new PsiMethodInsertHandler(); - public static void insertParentheses(final InsertionContext context, final LookupItem item, boolean overloadsMatter, boolean hasParams) { + public static void insertParentheses(final InsertionContext context, final LookupElement item, boolean overloadsMatter, boolean hasParams) { final Editor editor = context.getEditor(); final TailType tailType = getTailType(item, context); final PsiFile file = context.getFile(); @@ -73,12 +73,12 @@ public class PsiMethodInsertHandler implements InsertHandler item) { + public void handleInsert(final InsertionContext context, final LookupElement item) { final Editor editor = context.getEditor(); final Document document = editor.getDocument(); final PsiFile file = context.getFile(); final int offset = editor.getCaretModel().getOffset(); - final PsiMethod method = item.getObject(); + final PsiMethod method = (PsiMethod)item.getObject(); final LookupElement[] allItems = context.getElements(); final boolean overloadsMatter = allItems.length == 1 && item.getUserData(LookupItem.FORCE_SHOW_SIGNATURE_ATTR) == null; @@ -115,9 +115,9 @@ public class PsiMethodInsertHandler implements InsertHandler item, final Document document, final int offset, PsiFile file) { - final PsiMethod method = item.getObject(); + private static void insertExplicitTypeParams(final LookupElement item, final Document document, final int offset, PsiFile file) { + final PsiMethod method = (PsiMethod)item.getObject(); if (!SmartCompletionDecorator.hasUnboundTypeParams(method)) { return; } diff --git a/java/java-tests/java-tests.iml b/java/java-tests/java-tests.iml index 643d97843f30..c2ad4c94f0a0 100644 --- a/java/java-tests/java-tests.iml +++ b/java/java-tests/java-tests.iml @@ -18,6 +18,7 @@ + diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/GlobalMemberNameCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/GlobalMemberNameCompletionTest.groovy new file mode 100644 index 000000000000..26f55ee19067 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/GlobalMemberNameCompletionTest.groovy @@ -0,0 +1,29 @@ +package com.intellij.codeInsight.completion; + +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; + +/** + * @author peter + */ +public class GlobalMemberNameCompletionTest extends LightCodeInsightFixtureTestCase { + + public void testMethodName() throws Exception { + myFixture.addClass(""" +package foo; + +public class Foo { + public static int abcmethod() {} + static void methodThatsNotVisible() {} +} +""") + + myFixture.configureByText("a.java", "class Bar {{ abcm }}") + + myFixture.complete(CompletionType.CLASS_NAME) + myFixture.type('\n') + myFixture.checkResult """import static foo.Foo.abcmethod; + +class Bar {{ abcmethod() }}""" + } + +} 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 1017e5ac6482..21a9b72bf873 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/InsertionContext.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/InsertionContext.java @@ -16,11 +16,12 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiFile; -import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author peter @@ -65,6 +66,11 @@ public class InsertionContext { return myEditor; } + @NotNull + public Document getDocument() { + return getEditor().getDocument(); + } + public OffsetMap getOffsetMap() { return myOffsetMap; } diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java index 4b7d2b81ee06..19a1c8bd8345 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java @@ -305,6 +305,8 @@ public interface CodeInsightTestFixture extends IdeaProjectTestFixture { void type(final char c); + void type(final String s); + void performEditorAction(String actionId); /** 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 7b0b083f207e..768df215da7f 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -602,6 +602,13 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig }.execute(); } + @Override + public void type(String s) { + for (int i = 0; i < s.length(); i++) { + type(s.charAt(i)); + } + } + public void performEditorAction(final String actionId) { assertInitialized(); final DataContext dataContext = DataManager.getInstance().getDataContext(); diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index bab0c5b4e992..2e70419025bc 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -229,7 +229,8 @@ order="first, before javaMemberName, after xml"/> - + @@ -237,6 +238,8 @@ order="before javaLegacy"/> + From da3434e44d15f874f5876015e90752a718ffd573 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 26 Aug 2010 19:34:18 +0100 Subject: [PATCH 6/9] honor 'exclude from completion' settings (IDEA-54855) --- ...GlobalMemberNameCompletionContributor.java | 12 ++-- .../impl/quickfix/StaticImportMethodFix.java | 2 +- .../GlobalMemberNameCompletionTest.groovy | 57 +++++++++++++++++-- 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java index 4930dcf47973..a22d9871539d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java @@ -1,6 +1,7 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.completion.simple.PsiMethodInsertHandler; +import com.intellij.codeInsight.daemon.impl.quickfix.StaticImportMethodFix; import com.intellij.codeInsight.lookup.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; @@ -28,7 +29,7 @@ public class JavaGlobalMemberNameCompletionContributor extends CompletionContrib PsiFormatUtil.SHOW_PARAMETERS, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE); if (containingClass != null) { - presentation.setTailText(params + " in (" + containingClass.getName() + ")"); + presentation.setTailText(params + " in " + containingClass.getName()); } else { presentation.setTailText(params); } @@ -98,9 +99,12 @@ public class JavaGlobalMemberNameCompletionContributor extends CompletionContrib if (method.hasModifierProperty(PsiModifier.STATIC) && resolveHelper.isAccessible(method, position, null)) { final PsiClass containingClass = method.getContainingClass(); if (containingClass != null) { - result.addElement(LookupElementDecorator.withInsertHandler( - LookupElementDecorator.withRenderer(LookupElementBuilder.create(method), STATIC_METHOD_RENDERER), - STATIC_METHOD_INSERT_HANDLER)); + if (!JavaCompletionUtil.isInExcludedPackage(containingClass) && !StaticImportMethodFix.isExcluded(method)) { + result.addElement(LookupElementDecorator.withInsertHandler( + LookupElementDecorator.withRenderer(LookupElementBuilder.create(method), STATIC_METHOD_RENDERER), + STATIC_METHOD_INSERT_HANDLER)); + } + } } } 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 5cc6eb917471..1ee165ecd32a 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 @@ -138,7 +138,7 @@ public class StaticImportMethodFix implements IntentionAction { return result; } - private static boolean isExcluded(PsiMethod method) { + public static boolean isExcluded(PsiMethod method) { String name = getQName(method); CodeInsightSettings cis = CodeInsightSettings.getInstance(); for (String excluded : cis.EXCLUDED_PACKAGES) { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/GlobalMemberNameCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/GlobalMemberNameCompletionTest.groovy index 26f55ee19067..9fae06d94d27 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/GlobalMemberNameCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/GlobalMemberNameCompletionTest.groovy @@ -1,6 +1,8 @@ package com.intellij.codeInsight.completion; -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import com.intellij.codeInsight.CodeInsightSettings +import com.intellij.util.ArrayUtil; /** * @author peter @@ -17,13 +19,56 @@ public class Foo { } """) - myFixture.configureByText("a.java", "class Bar {{ abcm }}") - - myFixture.complete(CompletionType.CLASS_NAME) - myFixture.type('\n') - myFixture.checkResult """import static foo.Foo.abcmethod; + doTest "class Bar {{ abcm }}", """import static foo.Foo.abcmethod; class Bar {{ abcmethod() }}""" } + @Override protected void tearDown() { + CodeInsightSettings.instance.EXCLUDED_PACKAGES = ArrayUtil.EMPTY_STRING_ARRAY + super.tearDown() + } + + public void testExcludeClassFromCompletion() throws Exception { + myFixture.addClass("""package foo; + public class Foo { + public static int abcmethod() {} + } + """) + myFixture.addClass("""package foo; + public class Excl { + public static int abcmethod2() {} + } + """) + + CodeInsightSettings.instance.EXCLUDED_PACKAGES = ["foo.Excl"] as String[] + + doTest "class Bar {{ abcm }}", """import static foo.Foo.abcmethod; + +class Bar {{ abcmethod() }}""" + } + + public void testExcludeMethodFromCompletion() throws Exception { + myFixture.addClass("""package foo; + public class Foo { + public static int abcmethod1() {} + public static int abcmethodExcluded() {} + } + """) + + CodeInsightSettings.instance.EXCLUDED_PACKAGES = ["foo.Foo.abcmethodExcluded"] as String[] + + doTest "class Bar {{ abcm }}", """import static foo.Foo.abcmethod1; + +class Bar {{ abcmethod1() }}""" + } + + private void doTest(String input, String output) { + myFixture.configureByText("a.java", input) + + assertOneElement myFixture.complete(CompletionType.CLASS_NAME) + myFixture.type('\n') + myFixture.checkResult output + } + } From ead539493d437fb81107751e39987d698ad01476 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 26 Aug 2010 19:38:14 +0100 Subject: [PATCH 7/9] faster icon computation --- .../JavaGlobalMemberNameCompletionContributor.java | 3 +-- .../codeInsight/lookup/DefaultLookupItemRenderer.java | 10 ++++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java index a22d9871539d..4bda4b1b9bd8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java @@ -6,7 +6,6 @@ import com.intellij.codeInsight.lookup.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.Iconable; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiShortNamesCache; @@ -23,7 +22,7 @@ public class JavaGlobalMemberNameCompletionContributor extends CompletionContrib public void renderElement(LookupElement element, LookupElementPresentation presentation) { PsiMethod method = (PsiMethod)element.getObject(); final PsiClass containingClass = method.getContainingClass(); - presentation.setIcon(method.getIcon(Iconable.ICON_FLAG_VISIBILITY)); //todo don't calculate if not a real presentation + presentation.setIcon(DefaultLookupItemRenderer.getRawIcon(element, presentation.isReal())); presentation.setItemText(method.getName()); final String params = PsiFormatUtil.formatMethod(method, PsiSubstitutor.EMPTY, PsiFormatUtil.SHOW_PARAMETERS, diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/DefaultLookupItemRenderer.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/DefaultLookupItemRenderer.java index bdb0b8adb28b..02e7ef4b71b2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/DefaultLookupItemRenderer.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/DefaultLookupItemRenderer.java @@ -44,7 +44,7 @@ public class DefaultLookupItemRenderer extends LookupElementRenderer } @Nullable - public static Icon getRawIcon(final LookupItem item, boolean real) { + public static Icon getRawIcon(final LookupElement item, boolean real) { final Icon icon = _getRawIcon(item, real); if (icon != null && icon.getIconHeight() > SAMPLE_ICON.getIconHeight()) { return new SizedIcon(icon, icon.getIconWidth(), SAMPLE_ICON.getIconHeight()); @@ -53,9 +53,11 @@ public class DefaultLookupItemRenderer extends LookupElementRenderer } @Nullable - private static Icon _getRawIcon(LookupItem item, boolean real) { - Icon icon = (Icon)item.getAttribute(LookupItem.ICON_ATTR); - if (icon != null) return icon; + private static Icon _getRawIcon(LookupElement item, boolean real) { + if (item instanceof LookupItem) { + Icon icon = (Icon)((LookupItem)item).getAttribute(LookupItem.ICON_ATTR); + if (icon != null) return icon; + } Object o = item.getObject(); From 56cc43472d55ec2dcb905ad3d74e85731bd22d2e Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 26 Aug 2010 19:51:08 +0100 Subject: [PATCH 8/9] exclude static methods from completion --- ...udeFromCompletionLookupActionProvider.java | 32 ++++++++++--------- .../impl/quickfix/StaticImportMethodFix.java | 13 +++++--- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ExcludeFromCompletionLookupActionProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/ExcludeFromCompletionLookupActionProvider.java index 6d48746bb20c..c4d92cf8f258 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ExcludeFromCompletionLookupActionProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ExcludeFromCompletionLookupActionProvider.java @@ -16,15 +16,17 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.daemon.impl.actions.AddImportAction; +import com.intellij.codeInsight.daemon.impl.quickfix.StaticImportMethodFix; import com.intellij.codeInsight.lookup.Lookup; import com.intellij.codeInsight.lookup.LookupActionProvider; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementAction; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiType; -import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.PsiMember; +import com.intellij.psi.PsiMethod; import com.intellij.util.Consumer; +import org.jetbrains.annotations.Nullable; /** * @author peter @@ -32,20 +34,20 @@ import com.intellij.util.Consumer; public class ExcludeFromCompletionLookupActionProvider implements LookupActionProvider { public void fillActions(LookupElement element, Lookup lookup, Consumer consumer) { final Object o = element.getObject(); - PsiClass clazz = null; - if (o instanceof PsiType) { - clazz = PsiUtil.resolveClassInType((PsiType)o); - } else if (o instanceof PsiClass) { - clazz = (PsiClass)o; + if (o instanceof PsiClass) { + PsiClass clazz = (PsiClass)o; + addExcludes(consumer, clazz, clazz.getQualifiedName()); + } else if (o instanceof PsiMethod) { + final PsiMethod method = (PsiMethod)o; + addExcludes(consumer, method, StaticImportMethodFix.getMethodQualifiedName(method)); } - if (clazz != null && clazz.isValid()) { - final String qname = clazz.getQualifiedName(); - if (qname != null) { - final Project project = clazz.getProject(); - for (final String s : AddImportAction.getAllExcludableStrings(qname)) { - consumer.consume(new ExcludeFromCompletionAction(project, s)); - } - } + } + + private static void addExcludes(Consumer consumer, PsiMember element, @Nullable String qname) { + if (qname == null) return; + final Project project = element.getProject(); + for (final String s : AddImportAction.getAllExcludableStrings(qname)) { + consumer.consume(new ExcludeFromCompletionAction(project, s)); } } 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 1ee165ecd32a..cc5d211ae100 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 @@ -42,6 +42,7 @@ import com.intellij.ui.popup.list.PopupListElementRenderer; import com.intellij.util.IncorrectOperationException; import com.intellij.util.ObjectUtils; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -139,7 +140,8 @@ public class StaticImportMethodFix implements IntentionAction { } public static boolean isExcluded(PsiMethod method) { - String name = getQName(method); + String name = getMethodQualifiedName(method); + if (name == null) return false; CodeInsightSettings cis = CodeInsightSettings.getInstance(); for (String excluded : cis.EXCLUDED_PACKAGES) { if (name.equals(excluded) || name.startsWith(excluded + ".")) { @@ -199,7 +201,7 @@ public class StaticImportMethodFix implements IntentionAction { return FINAL_CHOICE; } - String qname = getQName(selectedValue); + String qname = getMethodQualifiedName(selectedValue); if (qname == null) return FINAL_CHOICE; List excludableStrings = AddImportAction.getAllExcludableStrings(qname); return new BaseListPopupStep(null, excludableStrings) { @@ -264,12 +266,13 @@ public class StaticImportMethodFix implements IntentionAction { popup.showInBestPositionFor(editor); } - private static String getQName(PsiMethod selectedValue) { - PsiClass containingClass = selectedValue.getContainingClass(); + @Nullable + public static String getMethodQualifiedName(PsiMethod method) { + PsiClass containingClass = method.getContainingClass(); if (containingClass == null) return null; String className = containingClass.getQualifiedName(); if (className == null) return null; - return className + "." + selectedValue.getName(); + return className + "." + method.getName(); } public boolean startInWriteAction() { From 5c3bc4ba1ed63243f3f1d0cc197482293b73e2bd Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 26 Aug 2010 20:23:29 +0100 Subject: [PATCH 9/9] statically imported methods completion in groovy --- ...GlobalMemberNameCompletionContributor.java | 9 ++++- .../GroovyCompletionContributor.java | 33 +++++++++++++++++-- .../GroovyClassNameCompletionTest.groovy | 13 ++++++++ 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java index 4bda4b1b9bd8..ab0b2c164fb0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java @@ -76,6 +76,13 @@ public class JavaGlobalMemberNameCompletionContributor extends CompletionContrib return; } + processStaticMethods(result, position, STATIC_METHOD_INSERT_HANDLER); + } + + public static void processStaticMethods(final CompletionResultSet result, + final PsiElement position, + final InsertHandler insertHandler) { + PrefixMatcher matcher = result.getPrefixMatcher(); final Project project = position.getProject(); final GlobalSearchScope scope = GlobalSearchScope.allScope(project); final PsiShortNamesCache namesCache = JavaPsiFacade.getInstance(project).getShortNamesCache(); @@ -101,7 +108,7 @@ public class JavaGlobalMemberNameCompletionContributor extends CompletionContrib if (!JavaCompletionUtil.isInExcludedPackage(containingClass) && !StaticImportMethodFix.isExcluded(method)) { result.addElement(LookupElementDecorator.withInsertHandler( LookupElementDecorator.withRenderer(LookupElementBuilder.create(method), STATIC_METHOD_RENDERER), - STATIC_METHOD_INSERT_HANDLER)); + insertHandler)); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java index 91bcad8e84c7..a22e14032890 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java @@ -45,7 +45,6 @@ import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; @@ -98,6 +97,22 @@ public class GroovyCompletionContributor extends CompletionContributor { psiElement().withParent(psiElement(GrReferenceExpression.class).withParent(psiElement(GrArgumentList.class).withParent(GrCall.class))); private static final String[] THIS_SUPER = {"this", "super"}; + private static final InsertHandler STATIC_IMPORT_INSERT_HANDLER = new InsertHandler() { + @Override + public void handleInsert(InsertionContext context, LookupElement item) { + new GroovyInsertHandler().handleInsert(context, item); + final PsiClass containingClass = ((PsiMethod)item.getObject()).getContainingClass(); + if (containingClass != null) { + PsiDocumentManager.getInstance(containingClass.getProject()).commitDocument(context.getDocument()); + final GrReferenceExpression ref = PsiTreeUtil + .findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), GrReferenceExpression.class, false); + if (ref != null) { + ref.bindToElementViaStaticImport(containingClass); + } + } + + } + }; public static boolean isReferenceInNewExpression(PsiElement reference) { if (!(reference instanceof GrCodeReferenceElement)) return false; @@ -303,7 +318,7 @@ public class GroovyCompletionContributor extends CompletionContributor { } }); - extend(CompletionType.BASIC, psiElement().withParent(GrReferenceElement.class), new CompletionProvider() { + extend(CompletionType.BASIC, psiElement().withParent(GrReferenceElement.class), new CompletionProvider(false) { @Override protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @@ -323,6 +338,20 @@ public class GroovyCompletionContributor extends CompletionContributor { } }); + extend(CompletionType.CLASS_NAME, psiElement().withParent(GrReferenceElement.class), new CompletionProvider(false) { + @Override + protected void addCompletions(@NotNull CompletionParameters parameters, + ProcessingContext context, + @NotNull final CompletionResultSet result) { + final PsiElement position = parameters.getPosition(); + if (((GrReferenceElement)position.getParent()).getQualifier() != null) return; + + final String s = result.getPrefixMatcher().getPrefix(); + if (StringUtil.isEmpty(s) || !Character.isLowerCase(s.charAt(0))) return; + + JavaGlobalMemberNameCompletionContributor.processStaticMethods(result, position, STATIC_IMPORT_INSERT_HANDLER); + } + }); } private static void addPropertiesForClass(CompletionResultSet result, diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyClassNameCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyClassNameCompletionTest.groovy index 71b585c28c10..918921dd044c 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyClassNameCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyClassNameCompletionTest.groovy @@ -107,4 +107,17 @@ public class GroovyClassNameCompletionTest extends LightCodeInsightFixtureTestCa myFixture.checkResult "a.FooBarGooDoo" } + public void testStaticMethod() throws Exception { + myFixture.addFileToProject("b.groovy", """ +class Foo { + static def abcmethod(int a) {} +}""") + myFixture.configureByText("a.groovy", "abcme") + myFixture.complete(CompletionType.CLASS_NAME) + myFixture.checkResult """import static Foo.abcmethod + +abcmethod()""" + + } + }