diff options
Diffstat (limited to 'java/java-impl/src/com/intellij/spi')
15 files changed, 1453 insertions, 0 deletions
diff --git a/java/java-impl/src/com/intellij/spi/SPIAnnotator.java b/java/java-impl/src/com/intellij/spi/SPIAnnotator.java new file mode 100644 index 000000000000..f834542854cb --- /dev/null +++ b/java/java-impl/src/com/intellij/spi/SPIAnnotator.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2013 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.spi; + +import com.intellij.lang.annotation.AnnotationHolder; +import com.intellij.lang.annotation.Annotator; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.util.ClassUtil; +import com.intellij.psi.util.PsiUtilCore; +import com.intellij.spi.psi.SPIProviderElement; +import org.jetbrains.annotations.NotNull; + +/** + * User: anna + */ +public class SPIAnnotator implements Annotator{ + @Override + public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) { + final VirtualFile file = PsiUtilCore.getVirtualFile(element); + if (file != null && file.getFileType() instanceof SPIFileType) { + final String serviceProviderName = file.getName(); + final PsiClass psiClass = + ClassUtil.findPsiClass(element.getManager(), serviceProviderName, null, true, element.getContainingFile().getResolveScope()); + if (element instanceof PsiFile) { + if (psiClass == null) { + holder.createErrorAnnotation(element, "No service provider \"" + serviceProviderName + "\' found").setFileLevelAnnotation(true); + } + } else if (element instanceof SPIProviderElement) { + final PsiElement resolve = ((SPIProviderElement)element).resolve(); + if (resolve == null) { + holder.createErrorAnnotation(element, "Cannot resolve symbol " + element.getText()); + } else if (resolve instanceof PsiClass && psiClass != null) { + if (!((PsiClass)resolve).isInheritor(psiClass, true)) { + holder.createErrorAnnotation(element, "Registered extension should implement " + serviceProviderName); + } + } + } + } + } +} diff --git a/java/java-impl/src/com/intellij/spi/SPICommenter.java b/java/java-impl/src/com/intellij/spi/SPICommenter.java new file mode 100644 index 000000000000..0afd9cdd717b --- /dev/null +++ b/java/java-impl/src/com/intellij/spi/SPICommenter.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2013 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.spi; + +import com.intellij.lang.Commenter; +import org.jetbrains.annotations.Nullable; + +/** + * User: anna + */ +public class SPICommenter implements Commenter { + @Nullable + @Override + public String getLineCommentPrefix() { + return "#"; + } + + @Nullable + @Override + public String getBlockCommentPrefix() { + return null; + } + + @Nullable + @Override + public String getBlockCommentSuffix() { + return null; + } + + @Nullable + @Override + public String getCommentedBlockCommentPrefix() { + return null; + } + + @Nullable + @Override + public String getCommentedBlockCommentSuffix() { + return null; + } +} diff --git a/java/java-impl/src/com/intellij/spi/SPIFileType.java b/java/java-impl/src/com/intellij/spi/SPIFileType.java new file mode 100644 index 000000000000..0d4a3bd8e474 --- /dev/null +++ b/java/java-impl/src/com/intellij/spi/SPIFileType.java @@ -0,0 +1,92 @@ +/* + * Copyright 2000-2013 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.spi; + +import com.intellij.icons.AllIcons; +import com.intellij.lang.spi.SPILanguage; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.LanguageFileType; +import com.intellij.openapi.fileTypes.ex.FileTypeIdentifiableByVirtualFile; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +/** + * User: anna + */ +public class SPIFileType extends LanguageFileType implements FileTypeIdentifiableByVirtualFile { + public static final SPIFileType INSTANCE = new SPIFileType(); + + private SPIFileType() { + super(SPILanguage.INSTANCE); + } + + @Override + public boolean isMyFileType(VirtualFile file) { + VirtualFile parent = file.getParent(); + if (parent != null && "services".equals(parent.getName())) { + final VirtualFile gParent = parent.getParent(); + if (gParent != null && "META-INF".equals(gParent.getName())) { + final String fileName = file.getName(); + for (Object condition : Extensions.getExtensions("com.intellij.vetoSPICondition")) { + if (((Condition<String>)condition).value(fileName)) return false; + } + return true; + } + } + return false; + } + + @NotNull + @Override + public String getName() { + return "SPI"; + } + + @NotNull + @Override + public String getDescription() { + return "Service Provider Interface"; + } + + @NotNull + @Override + public String getDefaultExtension() { + return ""; + } + + @Nullable + @Override + public Icon getIcon() { + return AllIcons.FileTypes.Text; + } + + @Override + public boolean isReadOnly() { + return false; + } + + @Nullable + @Override + public String getCharset(@NotNull VirtualFile file, byte[] content) { + return CharsetToolkit.UTF8; + } +} diff --git a/java/java-impl/src/com/intellij/spi/SPIFileTypeFactory.java b/java/java-impl/src/com/intellij/spi/SPIFileTypeFactory.java new file mode 100644 index 000000000000..ae61295651b4 --- /dev/null +++ b/java/java-impl/src/com/intellij/spi/SPIFileTypeFactory.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2013 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.spi; + +import com.intellij.openapi.fileTypes.FileTypeConsumer; +import com.intellij.openapi.fileTypes.FileTypeFactory; +import org.jetbrains.annotations.NotNull; + +/** + * User: anna + */ +public class SPIFileTypeFactory extends FileTypeFactory { + @Override + public void createFileTypes(@NotNull FileTypeConsumer consumer) { + consumer.consume(SPIFileType.INSTANCE); + } +} diff --git a/java/java-impl/src/com/intellij/spi/SPIGotoSuperHandler.java b/java/java-impl/src/com/intellij/spi/SPIGotoSuperHandler.java new file mode 100644 index 000000000000..a4a01485313d --- /dev/null +++ b/java/java-impl/src/com/intellij/spi/SPIGotoSuperHandler.java @@ -0,0 +1,38 @@ +/* + * Copyright 2000-2013 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.spi; + +import com.intellij.codeInsight.navigation.JavaGotoSuperHandler; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiNameIdentifierOwner; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.spi.psi.SPIProviderElement; + +/** + * User: anna + */ +public class SPIGotoSuperHandler extends JavaGotoSuperHandler { + @Override + protected PsiNameIdentifierOwner getElement(PsiFile file, int offset) { + final SPIProviderElement providerElement = PsiTreeUtil.getParentOfType(file.findElementAt(offset), SPIProviderElement.class); + if (providerElement != null) { + return (PsiClass)providerElement.resolve(); + } + + return null; + } +} diff --git a/java/java-impl/src/com/intellij/spi/parsing/SPIElementType.java b/java/java-impl/src/com/intellij/spi/parsing/SPIElementType.java new file mode 100644 index 000000000000..9d5c9cb655f9 --- /dev/null +++ b/java/java-impl/src/com/intellij/spi/parsing/SPIElementType.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2013 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.spi.parsing; + +import com.intellij.psi.tree.IElementType; +import com.intellij.lang.spi.SPILanguage; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +/** + * User: anna + */ +public class SPIElementType extends IElementType { + public SPIElementType(@NotNull @NonNls String debugName) { + super(debugName, SPILanguage.INSTANCE); + } +} diff --git a/java/java-impl/src/com/intellij/spi/parsing/SPIElementTypes.java b/java/java-impl/src/com/intellij/spi/parsing/SPIElementTypes.java new file mode 100644 index 000000000000..228a8459d14f --- /dev/null +++ b/java/java-impl/src/com/intellij/spi/parsing/SPIElementTypes.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2013 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.spi.parsing; + +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.IFileElementType; +import com.intellij.psi.tree.TokenSet; +import com.intellij.lang.spi.SPILanguage; + +public interface SPIElementTypes { + + IFileElementType FILE = new IFileElementType(SPILanguage.INSTANCE); + IElementType PROVIDER = new IElementType("PROVIDER", SPILanguage.INSTANCE); + + IElementType PROVIDERS_LIST = new IElementType("ROVIDER_LIST", SPILanguage.INSTANCE); + TokenSet PROVIDERS = TokenSet.create(PROVIDER); +} diff --git a/java/java-impl/src/com/intellij/spi/parsing/SPILexer.java b/java/java-impl/src/com/intellij/spi/parsing/SPILexer.java new file mode 100644 index 000000000000..6a698a9ea5a8 --- /dev/null +++ b/java/java-impl/src/com/intellij/spi/parsing/SPILexer.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2013 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.spi.parsing; + +import com.intellij.lexer.FlexAdapter; + + +public class SPILexer extends FlexAdapter { + public SPILexer() { + super(new _SPILexer()); + } +} diff --git a/java/java-impl/src/com/intellij/spi/parsing/SPIParserDefinition.java b/java/java-impl/src/com/intellij/spi/parsing/SPIParserDefinition.java new file mode 100644 index 000000000000..f32bd37a11d9 --- /dev/null +++ b/java/java-impl/src/com/intellij/spi/parsing/SPIParserDefinition.java @@ -0,0 +1,137 @@ +/* + * Copyright 2000-2013 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.spi.parsing; + +import com.intellij.lang.ASTNode; +import com.intellij.lang.ParserDefinition; +import com.intellij.lang.PsiBuilder; +import com.intellij.lang.PsiParser; +import com.intellij.lexer.Lexer; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.IFileElementType; +import com.intellij.psi.tree.TokenSet; +import com.intellij.psi.util.PsiUtilCore; +import com.intellij.spi.psi.SPIProviderElement; +import com.intellij.spi.psi.SPIProvidersElementList; +import com.intellij.spi.psi.SPIFile; +import com.intellij.lang.spi.SPILanguage; +import org.jetbrains.annotations.NotNull; + +/** + * User: anna + */ +public class SPIParserDefinition implements ParserDefinition { + public static final IFileElementType SPI_FILE_ELEMENT_TYPE = new IFileElementType(SPILanguage.INSTANCE); + + private static final TokenSet WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE); + private static final Logger LOG = Logger.getInstance("#" + SPIParserDefinition.class.getName()); + + @NotNull + @Override + public Lexer createLexer(Project project) { + return new SPILexer(); + } + + @Override + public PsiParser createParser(Project project) { + return new PsiParser() { + @NotNull + @Override + public ASTNode parse(IElementType root, PsiBuilder builder) { + final PsiBuilder.Marker rootMarker = builder.mark(); + final PsiBuilder.Marker propertiesList = builder.mark(); + while (!builder.eof()) { + parseProvider(builder); + } + propertiesList.done(SPIElementTypes.PROVIDERS_LIST); + rootMarker.done(root); + return builder.getTreeBuilt(); + } + }; + } + + @Override + public IFileElementType getFileNodeType() { + return SPI_FILE_ELEMENT_TYPE; + } + + @NotNull + @Override + public TokenSet getWhitespaceTokens() { + return WHITE_SPACES; + } + + @NotNull + @Override + public TokenSet getCommentTokens() { + return TokenSet.create(JavaTokenType.END_OF_LINE_COMMENT); + } + + @NotNull + @Override + public TokenSet getStringLiteralElements() { + return TokenSet.EMPTY; + } + + @NotNull + @Override + public PsiElement createElement(ASTNode node) { + final IElementType elementType = node.getElementType(); + if (elementType == SPIElementTypes.PROVIDERS_LIST) { + return new SPIProvidersElementList(node); + } + if (elementType == SPIElementTypes.PROVIDER) { + return new SPIProviderElement(node); + } + return PsiUtilCore.NULL_PSI_ELEMENT; + } + + @Override + public PsiFile createFile(FileViewProvider viewProvider) { + return new SPIFile(viewProvider); + } + + @Override + public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) { + return SpaceRequirements.MAY; + } + + public static void parseProvider(PsiBuilder builder) { + if (builder.getTokenType() == JavaTokenType.IDENTIFIER) { + final PsiBuilder.Marker prop = builder.mark(); + + parseProviderChar(builder); + prop.done(SPIElementTypes.PROVIDER); + } + else { + builder.advanceLexer(); + builder.error("Unexpected token"); + } + } + + private static void parseProviderChar(final PsiBuilder builder) { + LOG.assertTrue(builder.getTokenType() == JavaTokenType.IDENTIFIER); + builder.advanceLexer(); + final IElementType tokenType = builder.getTokenType(); + if (tokenType == JavaTokenType.DOT || tokenType == SPITokenType.DOLLAR) { + builder.advanceLexer(); + parseProviderChar(builder); + } + } +} diff --git a/java/java-impl/src/com/intellij/spi/parsing/SPITokenType.java b/java/java-impl/src/com/intellij/spi/parsing/SPITokenType.java new file mode 100644 index 000000000000..cd8b0e6d4e08 --- /dev/null +++ b/java/java-impl/src/com/intellij/spi/parsing/SPITokenType.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2013 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.spi.parsing; + +import com.intellij.psi.JavaTokenType; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.java.IKeywordElementType; + +/** + * User: anna + */ +public interface SPITokenType extends JavaTokenType { + IElementType SHARP = new IKeywordElementType("SHARP"); + IElementType DOLLAR = new IKeywordElementType("DOLLAR"); +} diff --git a/java/java-impl/src/com/intellij/spi/parsing/_SPILexer.flex b/java/java-impl/src/com/intellij/spi/parsing/_SPILexer.flex new file mode 100644 index 000000000000..b49ef5dac14a --- /dev/null +++ b/java/java-impl/src/com/intellij/spi/parsing/_SPILexer.flex @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2013 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.spi.parsing; + +import com.intellij.psi.JavaTokenType; +import com.intellij.psi.tree.IElementType; +import com.intellij.spi.parsing.SPITokenType; +import com.intellij.lexer.FlexLexer; + +@SuppressWarnings({"ALL"}) +%% + +%{ + public _SPILexer() { + this((java.io.Reader)null); + } + + public void goTo(int offset) { + zzCurrentPos = zzMarkedPos = zzStartRead = offset; + zzPushbackPos = 0; + zzAtEOF = offset < zzEndRead; + } +%} + +%unicode +%class _SPILexer +%implements FlexLexer +%function advance +%type IElementType +%eof{ return; +%eof} + +WHITE_SPACE_CHAR=[\ \n\r\t\f] + +IDENTIFIER=[:jletter:] [:jletterdigit:]* + +END_OF_LINE_COMMENT="#"[^\r\n]* + +DIGIT = [0-9] +DIGIT_OR_UNDERSCORE = [_0-9] +DIGITS = {DIGIT} | {DIGIT} {DIGIT_OR_UNDERSCORE}* + +%% + +<YYINITIAL> {WHITE_SPACE_CHAR}+ { return JavaTokenType.WHITE_SPACE; } + +<YYINITIAL> {END_OF_LINE_COMMENT} { return JavaTokenType.END_OF_LINE_COMMENT; } +<YYINITIAL> {IDENTIFIER} { return JavaTokenType.IDENTIFIER; } + +<YYINITIAL> "." { return JavaTokenType.DOT; } + +<YYINITIAL> "$" { return SPITokenType.DOLLAR; } + +<YYINITIAL> . { return JavaTokenType.BAD_CHARACTER; } diff --git a/java/java-impl/src/com/intellij/spi/parsing/_SPILexer.java b/java/java-impl/src/com/intellij/spi/parsing/_SPILexer.java new file mode 100644 index 000000000000..f08e8b295d1e --- /dev/null +++ b/java/java-impl/src/com/intellij/spi/parsing/_SPILexer.java @@ -0,0 +1,603 @@ +/* The following code was generated by JFlex 1.4.3 on 6/5/13 9:20 PM */ + +/* + * Copyright 2000-2013 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.spi.parsing; + +import com.intellij.psi.JavaTokenType; +import com.intellij.psi.tree.IElementType; +import com.intellij.spi.parsing.SPITokenType; +import com.intellij.lexer.FlexLexer; + +@SuppressWarnings({"ALL"}) + +/** + * This class is a scanner generated by + * <a href="http://www.jflex.de/">JFlex</a> 1.4.3 + * on 6/5/13 9:20 PM from the specification file + * <tt>D:/Projects/IDEA.anna/tools/lexer/../../community/java/java-impl/src/com/intellij/spi/parsing/_SPILexer.flex</tt> + */ +class _SPILexer implements FlexLexer { + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 16384; + + /** lexical states */ + public static final int YYINITIAL = 0; + + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0 + }; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\3\1\1\1\5\1\0\1\1\1\5\16\3\4\0\1\1\2\0"+ + "\1\4\1\2\11\0\1\6\1\0\12\3\7\0\32\2\4\0\1\2"+ + "\1\0\32\2\4\0\41\3\2\0\4\2\4\0\1\2\2\0\1\3"+ + "\7\0\1\2\4\0\1\2\5\0\27\2\1\0\37\2\1\0\u013f\2"+ + "\31\0\162\2\4\0\14\2\16\0\5\2\11\0\1\2\21\0\130\3"+ + "\5\0\23\3\12\0\1\2\13\0\1\2\1\0\3\2\1\0\1\2"+ + "\1\0\24\2\1\0\54\2\1\0\46\2\1\0\5\2\4\0\202\2"+ + "\1\0\4\3\3\0\105\2\1\0\46\2\2\0\2\2\6\0\20\2"+ + "\41\0\46\2\2\0\1\2\7\0\47\2\11\0\21\3\1\0\27\3"+ + "\1\0\3\3\1\0\1\3\1\0\2\3\1\0\1\3\13\0\33\2"+ + "\5\0\3\2\15\0\4\3\14\0\6\3\13\0\32\2\5\0\13\2"+ + "\16\3\7\0\12\3\4\0\2\2\1\3\143\2\1\0\1\2\10\3"+ + "\1\0\6\3\2\2\2\3\1\0\4\3\2\2\12\3\3\2\2\0"+ + "\1\2\17\0\1\3\1\2\1\3\36\2\33\3\2\0\3\2\60\0"+ + "\46\2\13\3\1\2\u014f\0\3\3\66\2\2\0\1\3\1\2\20\3"+ + "\2\0\1\2\4\3\3\0\12\2\2\3\2\0\12\3\21\0\3\3"+ + "\1\0\10\2\2\0\2\2\2\0\26\2\1\0\7\2\1\0\1\2"+ + "\3\0\4\2\2\0\1\3\1\2\7\3\2\0\2\3\2\0\3\3"+ + "\11\0\1\3\4\0\2\2\1\0\3\2\2\3\2\0\12\3\4\2"+ + "\15\0\3\3\1\0\6\2\4\0\2\2\2\0\26\2\1\0\7\2"+ + "\1\0\2\2\1\0\2\2\1\0\2\2\2\0\1\3\1\0\5\3"+ + "\4\0\2\3\2\0\3\3\13\0\4\2\1\0\1\2\7\0\14\3"+ + "\3\2\14\0\3\3\1\0\11\2\1\0\3\2\1\0\26\2\1\0"+ + "\7\2\1\0\2\2\1\0\5\2\2\0\1\3\1\2\10\3\1\0"+ + "\3\3\1\0\3\3\2\0\1\2\17\0\2\2\2\3\2\0\12\3"+ + "\1\0\1\2\17\0\3\3\1\0\10\2\2\0\2\2\2\0\26\2"+ + "\1\0\7\2\1\0\2\2\1\0\5\2\2\0\1\3\1\2\6\3"+ + "\3\0\2\3\2\0\3\3\10\0\2\3\4\0\2\2\1\0\3\2"+ + "\4\0\12\3\1\0\1\2\20\0\1\3\1\2\1\0\6\2\3\0"+ + "\3\2\1\0\4\2\3\0\2\2\1\0\1\2\1\0\2\2\3\0"+ + "\2\2\3\0\3\2\3\0\10\2\1\0\3\2\4\0\5\3\3\0"+ + "\3\3\1\0\4\3\11\0\1\3\17\0\11\3\11\0\1\2\7\0"+ + "\3\3\1\0\10\2\1\0\3\2\1\0\27\2\1\0\12\2\1\0"+ + "\5\2\4\0\7\3\1\0\3\3\1\0\4\3\7\0\2\3\11\0"+ + "\2\2\4\0\12\3\22\0\2\3\1\0\10\2\1\0\3\2\1\0"+ + "\27\2\1\0\12\2\1\0\5\2\2\0\1\3\1\2\7\3\1\0"+ + "\3\3\1\0\4\3\7\0\2\3\7\0\1\2\1\0\2\2\4\0"+ + "\12\3\22\0\2\3\1\0\10\2\1\0\3\2\1\0\27\2\1\0"+ + "\20\2\4\0\6\3\2\0\3\3\1\0\4\3\11\0\1\3\10\0"+ + "\2\2\4\0\12\3\22\0\2\3\1\0\22\2\3\0\30\2\1\0"+ + "\11\2\1\0\1\2\2\0\7\2\3\0\1\3\4\0\6\3\1\0"+ + "\1\3\1\0\10\3\22\0\2\3\15\0\60\2\1\3\2\2\7\3"+ + "\4\0\10\2\10\3\1\0\12\3\47\0\2\2\1\0\1\2\2\0"+ + "\2\2\1\0\1\2\2\0\1\2\6\0\4\2\1\0\7\2\1\0"+ + "\3\2\1\0\1\2\1\0\1\2\2\0\2\2\1\0\4\2\1\3"+ + "\2\2\6\3\1\0\2\3\1\2\2\0\5\2\1\0\1\2\1\0"+ + "\6\3\2\0\12\3\2\0\2\2\42\0\1\2\27\0\2\3\6\0"+ + "\12\3\13\0\1\3\1\0\1\3\1\0\1\3\4\0\2\3\10\2"+ + "\1\0\42\2\6\0\24\3\1\0\2\3\4\2\4\0\10\3\1\0"+ + "\44\3\11\0\1\3\71\0\42\2\1\0\5\2\1\0\2\2\1\0"+ + "\7\3\3\0\4\3\6\0\12\3\6\0\6\2\4\3\106\0\46\2"+ + "\12\0\51\2\7\0\132\2\5\0\104\2\5\0\122\2\6\0\7\2"+ + "\1\0\77\2\1\0\1\2\1\0\4\2\2\0\7\2\1\0\1\2"+ + "\1\0\4\2\2\0\47\2\1\0\1\2\1\0\4\2\2\0\37\2"+ + "\1\0\1\2\1\0\4\2\2\0\7\2\1\0\1\2\1\0\4\2"+ + "\2\0\7\2\1\0\7\2\1\0\27\2\1\0\37\2\1\0\1\2"+ + "\1\0\4\2\2\0\7\2\1\0\47\2\1\0\23\2\16\0\11\3"+ + "\56\0\125\2\14\0\u026c\2\2\0\10\2\12\0\32\2\5\0\113\2"+ + "\3\0\3\2\17\0\15\2\1\0\4\2\3\3\13\0\22\2\3\3"+ + "\13\0\22\2\2\3\14\0\15\2\1\0\3\2\1\0\2\3\14\0"+ + "\64\2\40\3\3\0\1\2\3\0\2\2\1\3\2\0\12\3\41\0"+ + "\3\3\2\0\12\3\6\0\130\2\10\0\51\2\1\3\126\0\35\2"+ + "\3\0\14\3\4\0\14\3\12\0\12\3\36\2\2\0\5\2\u038b\0"+ + "\154\2\224\0\234\2\4\0\132\2\6\0\26\2\2\0\6\2\2\0"+ + "\46\2\2\0\6\2\2\0\10\2\1\0\1\2\1\0\1\2\1\0"+ + "\1\2\1\0\37\2\2\0\65\2\1\0\7\2\1\0\1\2\3\0"+ + "\3\2\1\0\7\2\3\0\4\2\2\0\6\2\4\0\15\2\5\0"+ + "\3\2\1\0\7\2\17\0\4\3\32\0\5\3\20\0\2\2\23\0"+ + "\1\2\13\0\4\3\6\0\6\3\1\0\1\2\15\0\1\2\40\0"+ + "\22\2\36\0\15\3\4\0\1\3\3\0\6\3\27\0\1\2\4\0"+ + "\1\2\2\0\12\2\1\0\1\2\3\0\5\2\6\0\1\2\1\0"+ + "\1\2\1\0\1\2\1\0\4\2\1\0\3\2\1\0\7\2\3\0"+ + "\3\2\5\0\5\2\26\0\44\2\u0e81\0\3\2\31\0\11\2\6\3"+ + "\1\0\5\2\2\0\5\2\4\0\126\2\2\0\2\3\2\0\3\2"+ + "\1\0\137\2\5\0\50\2\4\0\136\2\21\0\30\2\70\0\20\2"+ + "\u0200\0\u19b6\2\112\0\u51a6\2\132\0\u048d\2\u0773\0\u2ba4\2\u215c\0\u012e\2"+ + "\2\0\73\2\225\0\7\2\14\0\5\2\5\0\1\2\1\3\12\2"+ + "\1\0\15\2\1\0\5\2\1\0\1\2\1\0\2\2\1\0\2\2"+ + "\1\0\154\2\41\0\u016b\2\22\0\100\2\2\0\66\2\50\0\15\2"+ + "\3\0\20\3\20\0\4\3\17\0\2\2\30\0\3\2\31\0\1\2"+ + "\6\0\5\2\1\0\207\2\2\0\1\3\4\0\1\2\13\0\12\3"+ + "\7\0\32\2\4\0\1\2\1\0\32\2\12\0\132\2\3\0\6\2"+ + "\2\0\6\2\2\0\6\2\2\0\3\2\3\0\2\2\3\0\2\2"+ + "\22\0\3\3\4\0"; + + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\1\0\1\1\1\2\1\3\1\4\1\5"; + + private static int [] zzUnpackAction() { + int [] result = new int[6]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /** + * Translates a state to a row index in the transition table + */ + private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); + + private static final String ZZ_ROWMAP_PACKED_0 = + "\0\0\0\7\0\16\0\25\0\34\0\7"; + + private static int [] zzUnpackRowMap() { + int [] result = new int[6]; + int offset = 0; + offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackRowMap(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int high = packed.charAt(i++) << 16; + result[j++] = high | packed.charAt(i++); + } + return j; + } + + /** + * The transition table of the DFA + */ + private static final int [] ZZ_TRANS = zzUnpackTrans(); + + private static final String ZZ_TRANS_PACKED_0 = + "\1\2\1\3\1\4\1\2\1\5\1\3\1\6\10\0"+ + "\1\3\3\0\1\3\3\0\2\4\3\0\5\5\1\0"+ + "\1\5"; + + private static int [] zzUnpackTrans() { + int [] result = new int[35]; + int offset = 0; + offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackTrans(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + value--; + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; + private static final char[] EMPTY_BUFFER = new char[0]; + private static final int YYEOF = -1; + private static java.io.Reader zzReader = null; // Fake + + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** + * ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code> + */ + private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); + + private static final String ZZ_ATTRIBUTE_PACKED_0 = + "\1\0\1\11\3\1\1\11"; + + private static int [] zzUnpackAttribute() { + int [] result = new int[6]; + int offset = 0; + offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAttribute(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + /** the current state of the DFA */ + private int zzState; + + /** the current lexical state */ + private int zzLexicalState = YYINITIAL; + + /** this buffer contains the current text to be matched and is + the source of the yytext() string */ + private CharSequence zzBuffer = ""; + + /** this buffer may contains the current text array to be matched when it is cheap to acquire it */ + private char[] zzBufferArray; + + /** the textposition at the last accepting state */ + private int zzMarkedPos; + + /** the textposition at the last state to be included in yytext */ + private int zzPushbackPos; + + /** the current text position in the buffer */ + private int zzCurrentPos; + + /** startRead marks the beginning of the yytext() string in the buffer */ + private int zzStartRead; + + /** endRead marks the last character in the buffer, that has been read + from input */ + private int zzEndRead; + + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; + + /** zzAtEOF == true <=> the scanner is at the EOF */ + private boolean zzAtEOF; + + /** denotes if the user-EOF-code has already been executed */ + private boolean zzEOFDone; + + /* user code: */ + public _SPILexer() { + this((java.io.Reader)null); + } + + public void goTo(int offset) { + zzCurrentPos = zzMarkedPos = zzStartRead = offset; + zzPushbackPos = 0; + zzAtEOF = offset < zzEndRead; + } + + + _SPILexer(java.io.Reader in) { + this.zzReader = in; + } + + /** + * Creates a new scanner. + * There is also java.io.Reader version of this constructor. + * + * @param in the java.io.Inputstream to read input from. + */ + _SPILexer(java.io.InputStream in) { + this(new java.io.InputStreamReader(in)); + } + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x10000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 1666) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do map[j++] = value; while (--count > 0); + } + return map; + } + + public final int getTokenStart(){ + return zzStartRead; + } + + public final int getTokenEnd(){ + return getTokenStart() + yylength(); + } + + public void reset(CharSequence buffer, int start, int end,int initialState){ + zzBuffer = buffer; + zzBufferArray = com.intellij.util.text.CharArrayUtil.fromSequenceWithoutCopying(buffer); + zzCurrentPos = zzMarkedPos = zzStartRead = start; + zzPushbackPos = 0; + zzAtEOF = false; + zzAtBOL = true; + zzEndRead = end; + yybegin(initialState); + } + + /** + * Refills the input buffer. + * + * @return <code>false</code>, iff there was new input. + * + * @exception java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + return true; + } + + + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } + + + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } + + + /** + * Returns the text matched by the current regular expression. + */ + public final CharSequence yytext() { + return zzBuffer.subSequence(zzStartRead, zzMarkedPos); + } + + + /** + * Returns the character at position <tt>pos</tt> from the + * matched text. + * + * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBufferArray != null ? zzBufferArray[zzStartRead+pos]:zzBuffer.charAt(zzStartRead+pos); + } + + + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos-zzStartRead; + } + + + /** + * Reports an error that occured while scanning. + * + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + * + * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } + catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } + + + /** + * Pushes the specified amount of characters back into the input stream. + * + * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if ( number > yylength() ) + zzScanError(ZZ_PUSHBACK_2BIG); + + zzMarkedPos -= number; + } + + + /** + * Contains user EOF-code, which will be executed exactly once, + * when the end of file is reached + */ + private void zzDoEOF() { + if (!zzEOFDone) { + zzEOFDone = true; + + } + } + + + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @exception java.io.IOException if any I/O-Error occurs + */ + public IElementType advance() throws java.io.IOException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + CharSequence zzBufferL = zzBuffer; + char[] zzBufferArrayL = zzBufferArray; + char [] zzCMapL = ZZ_CMAP; + + int [] zzTransL = ZZ_TRANS; + int [] zzRowMapL = ZZ_ROWMAP; + int [] zzAttrL = ZZ_ATTRIBUTE; + + while (true) { + zzMarkedPosL = zzMarkedPos; + + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; + + + zzForAction: { + while (true) { + + if (zzCurrentPosL < zzEndReadL) + zzInput = (zzBufferArrayL != null ? zzBufferArrayL[zzCurrentPosL++] : zzBufferL.charAt(zzCurrentPosL++)); + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } + else { + zzInput = (zzBufferArrayL != null ? zzBufferArrayL[zzCurrentPosL++] : zzBufferL.charAt(zzCurrentPosL++)); + } + } + int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; + if (zzNext == -1) break zzForAction; + zzState = zzNext; + + int zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( (zzAttributes & 8) == 8 ) break zzForAction; + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 2: + { return JavaTokenType.WHITE_SPACE; + } + case 6: break; + case 5: + { return JavaTokenType.DOT; + } + case 7: break; + case 3: + { return JavaTokenType.IDENTIFIER; + } + case 8: break; + case 4: + { return JavaTokenType.END_OF_LINE_COMMENT; + } + case 9: break; + case 1: + { return JavaTokenType.BAD_CHARACTER; + } + case 10: break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + zzDoEOF(); + return null; + } + else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } + + +} diff --git a/java/java-impl/src/com/intellij/spi/psi/SPIFile.java b/java/java-impl/src/com/intellij/spi/psi/SPIFile.java new file mode 100644 index 000000000000..9f1e8106878a --- /dev/null +++ b/java/java-impl/src/com/intellij/spi/psi/SPIFile.java @@ -0,0 +1,97 @@ +/* + * Copyright 2000-2013 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.spi.psi; + +import com.intellij.extapi.psi.PsiFileBase; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.psi.util.ClassUtil; +import com.intellij.spi.SPIFileType; +import com.intellij.lang.spi.SPILanguage; +import com.intellij.util.ArrayUtil; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * User: anna + */ +public class SPIFile extends PsiFileBase { + public SPIFile(@NotNull FileViewProvider viewProvider) { + super(viewProvider, SPILanguage.INSTANCE); + } + + @Override + public PsiReference getReference() { + return new SPIFileName2ClassReference(this, ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() { + @Override + public PsiClass compute() { + return ClassUtil.findPsiClass(getManager(), getName(), null, true, getResolveScope()); + } + })); + } + + @NotNull + @Override + public FileType getFileType() { + return SPIFileType.INSTANCE; + } + + private static class SPIFileName2ClassReference extends PsiReferenceBase<PsiFile> { + private final PsiClass myClass; + + public SPIFileName2ClassReference(PsiFile file, PsiClass aClass) { + super(file, new TextRange(0, 0), false); + myClass = aClass; + } + + @Nullable + @Override + public PsiElement resolve() { + return myClass; + } + + @Override + public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { + final String className = ClassUtil.getJVMClassName(myClass); + if (className != null) { + final String newFileName = className.substring(0, className.lastIndexOf(myClass.getName())) + newElementName; + return getElement().setName(newFileName); + } + return getElement(); + } + + @Override + public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException { + if (element instanceof PsiClass) { + final String className = ClassUtil.getJVMClassName((PsiClass)element); + if (className != null) { + return getElement().setName(className); + } + } + return getElement(); + } + + @NotNull + @Override + public Object[] getVariants() { + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + } +} diff --git a/java/java-impl/src/com/intellij/spi/psi/SPIProviderElement.java b/java/java-impl/src/com/intellij/spi/psi/SPIProviderElement.java new file mode 100644 index 000000000000..17c47b0ffbcc --- /dev/null +++ b/java/java-impl/src/com/intellij/spi/psi/SPIProviderElement.java @@ -0,0 +1,127 @@ +/* + * Copyright 2000-2013 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.spi.psi; + +import com.intellij.extapi.psi.ASTWrapperPsiElement; +import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.psi.infos.ClassCandidateInfo; +import com.intellij.psi.scope.PsiScopeProcessor; +import com.intellij.psi.util.ClassUtil; +import com.intellij.spi.SPIFileType; +import com.intellij.util.ArrayUtil; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * User: anna + */ +public class SPIProviderElement extends ASTWrapperPsiElement implements PsiJavaReference { + public SPIProviderElement(ASTNode node) { + super(node); + } + + @Override + public void processVariants(PsiScopeProcessor processor) { + } + + @NotNull + @Override + public JavaResolveResult advancedResolve(boolean incompleteCode) { + final PsiElement resolve = resolve(); + if (resolve instanceof PsiClass) { + return new ClassCandidateInfo(resolve, PsiSubstitutor.EMPTY); + } + return JavaResolveResult.EMPTY; + } + + @NotNull + @Override + public JavaResolveResult[] multiResolve(boolean incompleteCode) { + final PsiElement resolve = resolve(); + if (resolve instanceof PsiClass) { + return new JavaResolveResult[]{new ClassCandidateInfo(resolve, PsiSubstitutor.EMPTY)}; + } + return JavaResolveResult.EMPTY_ARRAY; + } + + @Override + public PsiElement getElement() { + return this; + } + + @Override + public TextRange getRangeInElement() { + return new TextRange(0, getTextLength()); + } + + @Nullable + @Override + public PsiElement resolve() { + return ClassUtil.findPsiClass(getManager(), getText(), null, true, getResolveScope()); + } + + @NotNull + @Override + public String getCanonicalText() { + return getText(); + } + + @Override + public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { + final SPIProvidersElementList firstChild = + (SPIProvidersElementList)PsiFileFactory.getInstance(getProject()) + .createFileFromText("spi_dummy", SPIFileType.INSTANCE, newElementName).getFirstChild(); + return replace(firstChild.getElements().get(0)); + } + + @Override + public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException { + if (element instanceof PsiClass) { + final String className = ClassUtil.getJVMClassName((PsiClass)element); + if (className != null) { + return handleElementRename(className); + } + } + return null; + } + + @Override + public boolean isReferenceTo(PsiElement element) { + if (element instanceof PsiClass) { + return getText().equals(ClassUtil.getJVMClassName((PsiClass)element)); + } + return false; + } + + @NotNull + @Override + public Object[] getVariants() { + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + + @Override + public PsiReference getReference() { + return this; + } + + @Override + public boolean isSoft() { + return false; + } +} diff --git a/java/java-impl/src/com/intellij/spi/psi/SPIProvidersElementList.java b/java/java-impl/src/com/intellij/spi/psi/SPIProvidersElementList.java new file mode 100644 index 000000000000..75cc44cb700f --- /dev/null +++ b/java/java-impl/src/com/intellij/spi/psi/SPIProvidersElementList.java @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2013 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.spi.psi; + +import com.intellij.extapi.psi.ASTWrapperPsiElement; +import com.intellij.lang.ASTNode; +import com.intellij.spi.parsing.SPIElementType; +import com.intellij.spi.parsing.SPIElementTypes; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * User: anna + */ +public class SPIProvidersElementList extends ASTWrapperPsiElement { + public SPIProvidersElementList(@NotNull ASTNode node) { + super(node); + } + + public List<SPIProviderElement> getElements() { + return findChildrenByType(SPIElementTypes.PROVIDER); + } +} |