From 2dfacc24f153214de7095b6e60a8ea9543fa228b Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Fri, 27 Jan 2012 18:17:55 +0400 Subject: [PATCH 1/2] Jet stubs (beginning) --- .../src/org/jetbrains/jet/JetNodeTypes.java | 10 ++- .../lang/parsing/JetExpressionParsing.java | 12 ++- .../jet/lang/parsing/JetParserDefinition.java | 28 ++++++- .../jet/lang/parsing/JetParsing.java | 12 +-- .../org/jetbrains/jet/lang/psi/JetClass.java | 27 ++++++- .../jetbrains/jet/lang/psi/JetFunction.java | 4 +- .../jet/lang/psi/JetNamedFunction.java | 16 +++- .../jet/lang/psi/stubs/PsiJetClassStub.java | 21 ++++++ .../jet/lang/psi/stubs/PsiJetFileStub.java | 15 ++++ .../lang/psi/stubs/PsiJetFunctionStub.java | 22 ++++++ .../stubs/elements/JetClassElementType.java | 70 ++++++++++++++++++ .../elements/JetFakeStubElementFactory.java | 28 +++++++ .../stubs/elements/JetFileElementType.java | 74 +++++++++++++++++++ .../stubs/elements/JetFileStubBuilder.java | 37 ++++++++++ .../elements/JetFunctionElementType.java | 56 ++++++++++++++ .../stubs/elements/JetStubElementFactory.java | 9 +++ .../stubs/elements/JetStubElementType.java | 46 ++++++++++++ .../stubs/elements/JetStubElementTypes.java | 13 ++++ .../psi/stubs/impl/PsiJetClassStubImpl.java | 57 ++++++++++++++ .../psi/stubs/impl/PsiJetFileStubImpl.java | 43 +++++++++++ .../stubs/impl/PsiJetFunctionStubImpl.java | 59 +++++++++++++++ .../jet/plugin/ParserConfigurator.java | 15 ++++ .../stubindex/JetFullClassNameIndex.java | 31 ++++++++ .../jet/plugin/stubindex/JetIndexKeys.java | 20 +++++ .../JetIndexedStubElementFactory.java | 40 ++++++++++ .../stubindex/JetShortClassNameIndex.java | 30 ++++++++ .../stubindex/JetShortFunctionNameIndex.java | 31 ++++++++ .../stubindex/JetSourceFilterScope.java | 34 +++++++++ 28 files changed, 840 insertions(+), 20 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetClassStub.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetFileStub.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetFunctionStub.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetClassElementType.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFakeStubElementFactory.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileElementType.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileStubBuilder.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFunctionElementType.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementFactory.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementType.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementTypes.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetClassStubImpl.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetFileStubImpl.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetFunctionStubImpl.java create mode 100644 idea/src/org/jetbrains/jet/plugin/ParserConfigurator.java create mode 100644 idea/src/org/jetbrains/jet/plugin/stubindex/JetFullClassNameIndex.java create mode 100644 idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexKeys.java create mode 100644 idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexedStubElementFactory.java create mode 100644 idea/src/org/jetbrains/jet/plugin/stubindex/JetShortClassNameIndex.java create mode 100644 idea/src/org/jetbrains/jet/plugin/stubindex/JetShortFunctionNameIndex.java create mode 100644 idea/src/org/jetbrains/jet/plugin/stubindex/JetSourceFilterScope.java diff --git a/compiler/frontend/src/org/jetbrains/jet/JetNodeTypes.java b/compiler/frontend/src/org/jetbrains/jet/JetNodeTypes.java index f58817258be..cc2f2d80824 100644 --- a/compiler/frontend/src/org/jetbrains/jet/JetNodeTypes.java +++ b/compiler/frontend/src/org/jetbrains/jet/JetNodeTypes.java @@ -3,16 +3,20 @@ */ package org.jetbrains.jet; +import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IFileElementType; -import org.jetbrains.jet.plugin.JetLanguage; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes; +import org.jetbrains.jet.plugin.JetLanguage; public interface JetNodeTypes { IFileElementType JET_FILE = new IFileElementType(JetLanguage.INSTANCE); - JetNodeType CLASS = new JetNodeType("CLASS", JetClass.class); + IElementType CLASS = JetStubElementTypes.CLASS; + IElementType FUN = JetStubElementTypes.FUNCTION; + JetNodeType PROPERTY = new JetNodeType("PROPERTY", JetProperty.class); - JetNodeType FUN = new JetNodeType("FUN", JetNamedFunction.class); + JetNodeType TYPEDEF = new JetNodeType("TYPEDEF", JetTypedef.class); JetNodeType OBJECT_DECLARATION = new JetNodeType("OBJECT_DECLARATION", JetObjectDeclaration.class); JetNodeType OBJECT_DECLARATION_NAME = new JetNodeType("OBJECT_DECLARATION_NAME", JetObjectDeclarationName.class); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index 7c2d367f74e..697d2ce4182 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -220,7 +220,7 @@ public class JetExpressionParsing extends AbstractJetParsing { usedSet.removeAll(opSet); - assert usedSet.isEmpty() : "" + usedSet; + assert usedSet.isEmpty() : usedSet.toString(); } @@ -239,9 +239,7 @@ public class JetExpressionParsing extends AbstractJetParsing { Precedence precedence = Precedence.ELVIS; while (precedence != null) { IElementType[] types = precedence.getOperations().getTypes(); - for (IElementType type : types) { - elvisFollow.add(type); - } + Collections.addAll(elvisFollow, types); precedence = precedence.higher; } decomposerExpressionFollow = TokenSet.orSet(EXPRESSION_FOLLOW, TokenSet.create(elvisFollow.toArray(new IElementType[elvisFollow.size()]))); @@ -1052,7 +1050,7 @@ public class JetExpressionParsing extends AbstractJetParsing { JetParsing.TokenDetector enumDetector = new JetParsing.TokenDetector(ENUM_KEYWORD); myJetParsing.parseModifierList(MODIFIER_LIST, enumDetector, false); - JetNodeType declType = parseLocalDeclarationRest(enumDetector.isDetected()); + IElementType declType = parseLocalDeclarationRest(enumDetector.isDetected()); if (declType != null) { decl.done(declType); @@ -1369,9 +1367,9 @@ public class JetExpressionParsing extends AbstractJetParsing { * : object * ; */ - private JetNodeType parseLocalDeclarationRest(boolean isEnum) { + private IElementType parseLocalDeclarationRest(boolean isEnum) { IElementType keywordToken = tt(); - JetNodeType declType = null; + IElementType declType = null; if (keywordToken == CLASS_KEYWORD || keywordToken == TRAIT_KEYWORD) { declType = myJetParsing.parseClass(isEnum); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParserDefinition.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParserDefinition.java index 317ad356d04..9ee73e0aeba 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParserDefinition.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParserDefinition.java @@ -3,11 +3,11 @@ */ package org.jetbrains.jet.lang.parsing; -import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.lang.ASTNode; import com.intellij.lang.ParserDefinition; import com.intellij.lang.PsiParser; import com.intellij.lexer.Lexer; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.psi.FileViewProvider; import com.intellij.psi.PsiElement; @@ -18,10 +18,30 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetNodeType; import org.jetbrains.jet.JetNodeTypes; import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.stubs.elements.JetFakeStubElementFactory; +import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementFactory; +import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementType; import org.jetbrains.jet.lexer.JetLexer; import org.jetbrains.jet.lexer.JetTokens; public class JetParserDefinition implements ParserDefinition { + + // TODO (stubs): + private static JetStubElementFactory stubElementFactory = new JetFakeStubElementFactory(); + + public static void setStubFactory(JetStubElementFactory factory) { + stubElementFactory = factory; + } + + public static JetStubElementFactory getStubElementTypeFactory() { + return stubElementFactory; + } + + public JetParserDefinition() { + if (!ApplicationManager.getApplication().isCommandLine()) { + } + } + @NotNull public Lexer createLexer(Project project) { return new JetLexer(); @@ -32,7 +52,9 @@ public class JetParserDefinition implements ParserDefinition { } public IFileElementType getFileNodeType() { + // TODO (stubs) return JetNodeTypes.JET_FILE; + // return JetStubElementTypes.FILE; } @NotNull @@ -52,6 +74,10 @@ public class JetParserDefinition implements ParserDefinition { @NotNull public PsiElement createElement(ASTNode astNode) { + if (astNode.getElementType() instanceof JetStubElementType) { + return ((JetStubElementType) astNode.getElementType()).createPsiFromAst(astNode); + } + return ((JetNodeType) astNode.getElementType()).createPsi(astNode); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java index 153cc928d49..38b4f2c7479 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -232,7 +232,7 @@ public class JetParsing extends AbstractJetParsing { parseModifierList(MODIFIER_LIST, detector, true); IElementType keywordToken = tt(); - JetNodeType declType = null; + IElementType declType = null; // if (keywordToken == PACKAGE_KEYWORD) { // declType = parseNamespaceBlock(); // } @@ -385,7 +385,7 @@ public class JetParsing extends AbstractJetParsing { * (classBody? | enumClassBody) * ; */ - public JetNodeType parseClass(boolean enumClass) { + public IElementType parseClass(boolean enumClass) { assert _atSet(CLASS_KEYWORD, TRAIT_KEYWORD); advance(); // CLASS_KEYWORD or TRAIT_KEYWORD @@ -558,7 +558,7 @@ public class JetParsing extends AbstractJetParsing { TokenDetector enumDetector = new TokenDetector(ENUM_KEYWORD); parseModifierList(MODIFIER_LIST, enumDetector, true); - JetNodeType declType = parseMemberDeclarationRest(enumDetector.isDetected()); + IElementType declType = parseMemberDeclarationRest(enumDetector.isDetected()); if (declType == null) { errorAndAdvance("Expecting member declaration"); @@ -569,9 +569,9 @@ public class JetParsing extends AbstractJetParsing { } } - private JetNodeType parseMemberDeclarationRest(boolean isEnum) { + private IElementType parseMemberDeclarationRest(boolean isEnum) { IElementType keywordToken = tt(); - JetNodeType declType = null; + IElementType declType = null; if (keywordToken == CLASS_KEYWORD) { if (lookahead(1) == OBJECT_KEYWORD) { declType = parseClassObject(); @@ -925,7 +925,7 @@ public class JetParsing extends AbstractJetParsing { * functionBody? * ; */ - public JetNodeType parseFunction() { + public IElementType parseFunction() { assert _at(FUN_KEYWORD); advance(); // FUN_KEYWORD diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetClass.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetClass.java index 81f1dc63fae..818eaf7a907 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetClass.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetClass.java @@ -1,9 +1,13 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; +import com.intellij.psi.StubBasedPsiElement; +import com.intellij.psi.stubs.IStubElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; +import org.jetbrains.jet.lang.psi.stubs.PsiJetClassStub; +import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes; import org.jetbrains.jet.lexer.JetTokens; import java.util.Collections; @@ -12,11 +16,20 @@ import java.util.List; /** * @author max */ -public class JetClass extends JetTypeParameterListOwner implements JetClassOrObject, JetModifierListOwner { +public class JetClass extends JetTypeParameterListOwner + implements JetClassOrObject, JetModifierListOwner, StubBasedPsiElement> { + + private PsiJetClassStub stub; + public JetClass(@NotNull ASTNode node) { super(node); } + // TODO (stubs) +// public JetClass(final PsiJetClassStub stub) { +// this.stub = stub; +// } + @Override public List getDeclarations() { JetClassBody body = (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY); @@ -112,4 +125,16 @@ public class JetClass extends JetTypeParameterListOwner implements JetClassOrObj public boolean isTrait() { return findChildByType(JetTokens.TRAIT_KEYWORD) != null; } + + @Override + public IStubElementType getElementType() { + // TODO (stubs) + return JetStubElementTypes.CLASS; + } + + @Override + public PsiJetClassStub getStub() { + // TODO (stubs) + return null; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunction.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunction.java index 52c987ea24f..67b0b7c6b85 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunction.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunction.java @@ -14,7 +14,9 @@ import java.util.List; /** * @author abreslav */ -abstract public class JetFunction extends JetTypeParameterListOwner implements JetDeclarationWithBody, JetModifierListOwner { +abstract public class JetFunction extends JetTypeParameterListOwner + implements JetDeclarationWithBody, JetModifierListOwner { + public JetFunction(@NotNull ASTNode node) { super(node); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetNamedFunction.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetNamedFunction.java index 30ffa3b5248..3786dfe3fc6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetNamedFunction.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetNamedFunction.java @@ -2,13 +2,17 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; +import com.intellij.psi.StubBasedPsiElement; +import com.intellij.psi.stubs.IStubElementType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub; +import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes; import org.jetbrains.jet.lexer.JetTokens; /** * @author max */ -public class JetNamedFunction extends JetFunction { +public class JetNamedFunction extends JetFunction implements StubBasedPsiElement> { public JetNamedFunction(@NotNull ASTNode node) { super(node); } @@ -62,4 +66,14 @@ public class JetNamedFunction extends JetFunction { return this; } + @Override + public IStubElementType getElementType() { + return JetStubElementTypes.FUNCTION; + } + + @Override + public PsiJetFunctionStub getStub() { + // TODO (stubs) + return null; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetClassStub.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetClassStub.java new file mode 100644 index 00000000000..36899124b73 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetClassStub.java @@ -0,0 +1,21 @@ +package org.jetbrains.jet.lang.psi.stubs; + +import com.intellij.psi.stubs.StubElement; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.psi.JetClass; + +/** + * @author Nikolay Krasko + */ +public interface PsiJetClassStub extends StubElement { + @NonNls + @Nullable + String getQualifiedName(); + + @Nullable + String getName(); + + boolean isDeprecated(); + boolean hasDeprecatedAnnotation(); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetFileStub.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetFileStub.java new file mode 100644 index 00000000000..77108284e13 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetFileStub.java @@ -0,0 +1,15 @@ +package org.jetbrains.jet.lang.psi.stubs; + +import com.intellij.psi.impl.java.stubs.StubPsiFactory; +import com.intellij.psi.stubs.PsiClassHolderFileStub; +import org.jetbrains.jet.lang.psi.JetFile; + +/** + * @author Nikolay Krasko + */ +public interface PsiJetFileStub extends PsiClassHolderFileStub { + String getPackageName(); + + StubPsiFactory getPsiFactory(); + void setPsiFactory(StubPsiFactory factory); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetFunctionStub.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetFunctionStub.java new file mode 100644 index 00000000000..3d8af9463a4 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetFunctionStub.java @@ -0,0 +1,22 @@ +package org.jetbrains.jet.lang.psi.stubs; + +import com.intellij.psi.stubs.StubElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.psi.JetFunction; + +/** + * @author Nikolay Krasko + */ +public interface PsiJetFunctionStub extends StubElement { + @Nullable + String getName(); + + boolean isDeclaration(); + + @NotNull + String[] getAnnotations(); + + @NotNull + String getReturnTypeText(); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetClassElementType.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetClassElementType.java new file mode 100644 index 00000000000..8ed623b10a9 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetClassElementType.java @@ -0,0 +1,70 @@ +package org.jetbrains.jet.lang.psi.stubs.elements; + +import com.intellij.lang.ASTNode; +import com.intellij.lang.LighterAST; +import com.intellij.lang.LighterASTNode; +import com.intellij.psi.stubs.IndexSink; +import com.intellij.psi.stubs.StubElement; +import com.intellij.psi.stubs.StubInputStream; +import com.intellij.psi.stubs.StubOutputStream; +import com.intellij.util.io.StringRef; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetClass; +import org.jetbrains.jet.lang.psi.stubs.PsiJetClassStub; +import org.jetbrains.jet.lang.psi.stubs.impl.PsiJetClassStubImpl; +import org.jetbrains.jet.plugin.JetLanguage; + +import java.io.IOException; + +/** + * @author Nikolay Krasko + */ +public abstract class JetClassElementType extends JetStubElementType { + + public JetClassElementType(@NotNull @NonNls String debugName) { + super(debugName, JetLanguage.INSTANCE); + } + + @Override + public PsiJetClassStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public JetClass createPsi(@NotNull PsiJetClassStub stub) { + // TODO: Don't work for kotlin classes + // return getPsiFactory(stub).createClass(stub); + return null; + } + + @Override + public JetClass createPsiFromAst(@NotNull ASTNode node) { + return new JetClass(node); + } + + @Override + public PsiJetClassStub createStub(@NotNull JetClass psi, StubElement parentStub) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void serialize(PsiJetClassStub stub, StubOutputStream dataStream) throws IOException { + dataStream.writeName(stub.getName()); + dataStream.writeName(stub.getQualifiedName()); + } + + @Override + public PsiJetClassStub deserialize(StubInputStream dataStream, StubElement parentStub) throws IOException { + final StringRef name = dataStream.readName(); + final StringRef qualifiedName = dataStream.readName(); + + final JetClassElementType type = JetStubElementTypes.CLASS; + final PsiJetClassStubImpl classStub = new PsiJetClassStubImpl(type, parentStub, qualifiedName, name); + + return classStub; + } + + @Override + public abstract void indexStub(PsiJetClassStub stub, IndexSink sink); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFakeStubElementFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFakeStubElementFactory.java new file mode 100644 index 00000000000..29c8e566f5c --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFakeStubElementFactory.java @@ -0,0 +1,28 @@ +package org.jetbrains.jet.lang.psi.stubs.elements; + +import com.intellij.psi.stubs.IndexSink; +import org.jetbrains.jet.lang.psi.stubs.PsiJetClassStub; +import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub; + +/** + * @author Nikolay Krasko + */ +public class JetFakeStubElementFactory implements JetStubElementFactory { + @Override + public JetClassElementType getClassElementType() { + return new JetClassElementType("CLASS") { + @Override + public void indexStub(PsiJetClassStub stub, IndexSink sink) { + } + }; + } + + @Override + public JetFunctionElementType getFunctionElementType() { + return new JetFunctionElementType("FUN") { + @Override + public void indexStub(PsiJetFunctionStub stub, IndexSink sink) { + } + }; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileElementType.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileElementType.java new file mode 100644 index 00000000000..c8a5ce58bd1 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileElementType.java @@ -0,0 +1,74 @@ +package org.jetbrains.jet.lang.psi.stubs.elements; + +import com.intellij.lang.ASTNode; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.StubBuilder; +import com.intellij.psi.stubs.IndexSink; +import com.intellij.psi.stubs.StubElement; +import com.intellij.psi.stubs.StubInputStream; +import com.intellij.psi.stubs.StubOutputStream; +import com.intellij.psi.tree.IStubFileElementType; +import com.intellij.util.io.StringRef; +import org.jetbrains.jet.lang.psi.stubs.PsiJetFileStub; +import org.jetbrains.jet.lang.psi.stubs.impl.PsiJetFileStubImpl; +import org.jetbrains.jet.plugin.JetLanguage; + +import java.io.IOException; + +/** + * @author Nikolay Krasko + */ +public class JetFileElementType extends IStubFileElementType { + public static final int STUB_VERSION = 1; + + public JetFileElementType() { + super("jet.FILE", JetLanguage.INSTANCE); + } + + @Override + public StubBuilder getBuilder() { + return new JetFileStubBuilder(); + } + + @Override + public int getStubVersion() { + return STUB_VERSION; + } + + @Override + public boolean shouldBuildStubFor(final VirtualFile file) { + // TODO: + return true; + +// final VirtualFile dir = file.getParent(); +// return dir == null || dir.getUserData(LanguageLevel.KEY) != null; + } + + @Override + public ASTNode createNode(final CharSequence text) { + // TODO (stub): + return super.createNode(text); + } + + @Override + public String getExternalId() { + return "jet.FILE"; + } + + @Override + public void serialize(final PsiJetFileStub stub, final StubOutputStream dataStream) + throws IOException { + dataStream.writeName(stub.getPackageName()); + } + + @Override + public PsiJetFileStub deserialize(final StubInputStream dataStream, final StubElement parentStub) throws IOException { + StringRef packName = dataStream.readName(); + return new PsiJetFileStubImpl(null, packName); + } + + @Override + public void indexStub(final PsiJetFileStub stub, final IndexSink sink) { + // Don't index file + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileStubBuilder.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileStubBuilder.java new file mode 100644 index 00000000000..2b93cb40860 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileStubBuilder.java @@ -0,0 +1,37 @@ +package org.jetbrains.jet.lang.psi.stubs.elements; + +import com.intellij.psi.PsiFile; +import com.intellij.psi.stubs.DefaultStubBuilder; +import com.intellij.psi.stubs.StubElement; +import com.intellij.util.io.StringRef; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.stubs.impl.PsiJetFileStubImpl; + +/** + * @author Nikolay Krasko + */ +public class JetFileStubBuilder extends DefaultStubBuilder { + @Override + protected StubElement createStubForFile(PsiFile file) { + + if (!(file instanceof JetFile)) return super.createStubForFile(file); + + JetFile jetFile = (JetFile) file; + + // TODO (stubs): + String packageName = "default"; + +// String refText = ""; +// +// final LighterASTNode pkg = LightTreeUtil.firstChildOfType(tree, tree.getRoot(), JavaElementType.PACKAGE_STATEMENT); +// if (pkg != null) { +// final LighterASTNode ref = LightTreeUtil.firstChildOfType(tree, pkg, JavaElementType.JAVA_CODE_REFERENCE); +// if (ref != null) { +// refText = SourceUtil.getTextSkipWhiteSpaceAndComments(tree, ref); +// +// } +// } + + return new PsiJetFileStubImpl(jetFile, StringRef.fromString(packageName)); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFunctionElementType.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFunctionElementType.java new file mode 100644 index 00000000000..12f2eda3c83 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFunctionElementType.java @@ -0,0 +1,56 @@ +package org.jetbrains.jet.lang.psi.stubs.elements; + +import com.intellij.lang.ASTNode; +import com.intellij.lang.LighterAST; +import com.intellij.lang.LighterASTNode; +import com.intellij.psi.stubs.StubElement; +import com.intellij.psi.stubs.StubInputStream; +import com.intellij.psi.stubs.StubOutputStream; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetFunction; +import org.jetbrains.jet.lang.psi.JetNamedFunction; +import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub; +import org.jetbrains.jet.plugin.JetLanguage; + +import java.io.IOException; + +/** + * @author Nikolay Krasko + */ +public abstract class JetFunctionElementType extends JetStubElementType { + + public JetFunctionElementType(@NotNull @NonNls String debugName) { + super(debugName, JetLanguage.INSTANCE); + } + + @Override + public JetFunction createPsiFromAst(@NotNull ASTNode node) { + return new JetNamedFunction(node); + } + + @Override + public PsiJetFunctionStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public JetFunction createPsi(@NotNull PsiJetFunctionStub stub) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public PsiJetFunctionStub createStub(@NotNull JetFunction psi, StubElement parentStub) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void serialize(PsiJetFunctionStub stub, StubOutputStream dataStream) throws IOException { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public PsiJetFunctionStub deserialize(StubInputStream dataStream, StubElement parentStub) throws IOException { + return null; //To change body of implemented methods use File | Settings | File Templates. + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementFactory.java new file mode 100644 index 00000000000..12674702df9 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementFactory.java @@ -0,0 +1,9 @@ +package org.jetbrains.jet.lang.psi.stubs.elements; + +/** + * @author Nikolay Krasko + */ +public interface JetStubElementFactory { + JetClassElementType getClassElementType(); + JetFunctionElementType getFunctionElementType(); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementType.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementType.java new file mode 100644 index 00000000000..3211f89feb3 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementType.java @@ -0,0 +1,46 @@ +package org.jetbrains.jet.lang.psi.stubs.elements; + +import com.intellij.lang.ASTNode; +import com.intellij.lang.Language; +import com.intellij.psi.PsiElement; +import com.intellij.psi.impl.java.stubs.PsiJavaFileStub; +import com.intellij.psi.impl.java.stubs.StubPsiFactory; +import com.intellij.psi.stubs.ILightStubElementType; +import com.intellij.psi.stubs.PsiFileStub; +import com.intellij.psi.stubs.StubElement; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Nikolay Krasko + */ +public abstract class JetStubElementType + extends ILightStubElementType { + + public JetStubElementType(@NotNull @NonNls String debugName, @Nullable Language language) { + super(debugName, language); + } + + + + public abstract PsiT createPsiFromAst(@NotNull ASTNode node); + + protected StubPsiFactory getPsiFactory(StubT stub) { + return getFileStub(stub).getPsiFactory(); + } + + private PsiJavaFileStub getFileStub(StubT stub) { + StubElement parent = stub; + while (!(parent instanceof PsiFileStub)) { + parent = parent.getParentStub(); + } + + return (PsiJavaFileStub)parent; + } + + @Override + public String getExternalId() { + return "jet." + toString(); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementTypes.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementTypes.java new file mode 100644 index 00000000000..e37bf075100 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementTypes.java @@ -0,0 +1,13 @@ +package org.jetbrains.jet.lang.psi.stubs.elements; + +import org.jetbrains.jet.lang.parsing.JetParserDefinition; + +/** + * @author Nikolay Krasko + */ +public interface JetStubElementTypes { + JetFileElementType FILE = new JetFileElementType(); + + JetClassElementType CLASS = JetParserDefinition.getStubElementTypeFactory().getClassElementType(); + JetFunctionElementType FUNCTION = JetParserDefinition.getStubElementTypeFactory().getFunctionElementType(); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetClassStubImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetClassStubImpl.java new file mode 100644 index 00000000000..5a480366c00 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetClassStubImpl.java @@ -0,0 +1,57 @@ +package org.jetbrains.jet.lang.psi.stubs.impl; + +import com.intellij.psi.stubs.StubBase; +import com.intellij.psi.stubs.StubElement; +import com.intellij.util.io.StringRef; +import org.jetbrains.jet.lang.psi.JetClass; +import org.jetbrains.jet.lang.psi.stubs.PsiJetClassStub; +import org.jetbrains.jet.lang.psi.stubs.elements.JetClassElementType; + +/** + * @author Nikolay Krasko + */ +public class PsiJetClassStubImpl extends StubBase implements PsiJetClassStub { + + private final StringRef qualifiedName; + private final StringRef name; + + public PsiJetClassStubImpl( + JetClassElementType type, + final StubElement parent, + final String qualifiedName, + final String name) { + + this(type, parent, StringRef.fromString(qualifiedName), StringRef.fromString(name)); + } + + public PsiJetClassStubImpl( + JetClassElementType type, + final StubElement parent, + final StringRef qualifiedName, + final StringRef name) { + + super(parent, type); + this.qualifiedName = qualifiedName; + this.name = name; + } + + @Override + public String getQualifiedName() { + return StringRef.toString(qualifiedName); + } + + @Override + public boolean isDeprecated() { + return false; + } + + @Override + public boolean hasDeprecatedAnnotation() { + return false; + } + + @Override + public String getName() { + return StringRef.toString(name); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetFileStubImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetFileStubImpl.java new file mode 100644 index 00000000000..78dfaa14b13 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetFileStubImpl.java @@ -0,0 +1,43 @@ +package org.jetbrains.jet.lang.psi.stubs.impl; + +import com.intellij.psi.PsiClass; +import com.intellij.psi.impl.java.stubs.StubPsiFactory; +import com.intellij.psi.stubs.PsiFileStubImpl; +import com.intellij.util.io.StringRef; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.stubs.PsiJetFileStub; + +/** + * @author Nikolay Krasko + */ +public class PsiJetFileStubImpl extends PsiFileStubImpl implements PsiJetFileStub { + + private final StringRef packageName; + private StubPsiFactory psiFactory; + + public PsiJetFileStubImpl(JetFile jetFile, StringRef packageName) { + super(jetFile); + + this.packageName = packageName; + } + + @Override + public String getPackageName() { + return StringRef.toString(packageName); + } + + @Override + public StubPsiFactory getPsiFactory() { + return psiFactory; + } + + @Override + public void setPsiFactory(StubPsiFactory factory) { + psiFactory = factory; + } + + @Override + public PsiClass[] getClasses() { + return new PsiClass[0]; //To change body of implemented methods use File | Settings | File Templates. + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetFunctionStubImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetFunctionStubImpl.java new file mode 100644 index 00000000000..b8f580be58e --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetFunctionStubImpl.java @@ -0,0 +1,59 @@ +package org.jetbrains.jet.lang.psi.stubs.impl; + +import com.intellij.psi.stubs.IStubElementType; +import com.intellij.psi.stubs.StubBase; +import com.intellij.psi.stubs.StubElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetFunction; +import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub; + +/** + * @author Nikolay Krasko + */ +public class PsiJetFunctionStubImpl extends StubBase implements PsiJetFunctionStub { + protected PsiJetFunctionStubImpl(StubElement parent, IStubElementType elementType) { + super(parent, elementType); + } + +// public PsiJetFunctionStubImpl( +// Jet type, +// final StubElement parent, +// final String qualifiedName, +// final String name) { +// +// this(type, parent, StringRef.fromString(qualifiedName), StringRef.fromString(name)); +// } +// +// public PsiJetFunctionStubImpl( +// JetClassElementType type, +// final StubElement parent, +// final StringRef qualifiedName, +// final StringRef name) { +// +// super(parent, type); +// this.qualifiedName = qualifiedName; +// this.name = name; +// } + + @Override + public String getName() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean isDeclaration() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @NotNull + @Override + public String[] getAnnotations() { + return new String[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + @NotNull + @Override + public String getReturnTypeText() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/ParserConfigurator.java b/idea/src/org/jetbrains/jet/plugin/ParserConfigurator.java new file mode 100644 index 00000000000..36eb6db31d4 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/ParserConfigurator.java @@ -0,0 +1,15 @@ +package org.jetbrains.jet.plugin; + +/** + * Configures jet parser for using indexed stubs instead of default set. + * So if parser is used from IDEA it creates indexed stubs, if not direct psi elements are used. + * + * IMPORTANT: Should be called before loading parser. + * + * @author Nikolay Krasko + */ +public class ParserConfigurator { +// static { +// JetParserDefinition.setStubFactory(new JetIndexedStubElementFactory()); +// } +} diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/JetFullClassNameIndex.java b/idea/src/org/jetbrains/jet/plugin/stubindex/JetFullClassNameIndex.java new file mode 100644 index 00000000000..5f17ff4459d --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/JetFullClassNameIndex.java @@ -0,0 +1,31 @@ +package org.jetbrains.jet.plugin.stubindex; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.stubs.StringStubIndexExtension; +import com.intellij.psi.stubs.StubIndexKey; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetClassOrObject; + +import java.util.Collection; + +/** + * @author Nikolay Krasko + */ +public class JetFullClassNameIndex extends StringStubIndexExtension { + + private static final JetFullClassNameIndex ourInstance = new JetFullClassNameIndex(); + public static JetFullClassNameIndex getInstance() { + return ourInstance; + } + + @Override + public StubIndexKey getKey() { + return JetIndexKeys.FQN_KEY; + } + + @Override + public Collection get(final String integer, final Project project, @NotNull final GlobalSearchScope scope) { + return super.get(integer, project, new JetSourceFilterScope(scope)); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexKeys.java b/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexKeys.java new file mode 100644 index 00000000000..fed0fe7e5c8 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexKeys.java @@ -0,0 +1,20 @@ +package org.jetbrains.jet.plugin.stubindex; + +import com.intellij.psi.stubs.StubIndexKey; +import org.jetbrains.jet.lang.psi.JetClassOrObject; +import org.jetbrains.jet.lang.psi.JetFunction; + +/** + * @author Nikolay Krasko + */ +public interface JetIndexKeys { + StubIndexKey SHORT_NAME_KEY = StubIndexKey.createIndexKey("jet.class.shortName"); + StubIndexKey FQN_KEY = StubIndexKey.createIndexKey("jet.fqn"); + + StubIndexKey TOP_LEVEL_FUNCTION_SHORT_NAME_KEY = StubIndexKey.createIndexKey("jet.top.level.function.short.name"); +// StubIndexKey TOP_LEVEL_FUNCTION_FQN_KEY = StubIndexKey.createIndexKey("jet.top.level.function.short.name"); + +// StubIndexKey PACKAGE_OBJECT_KEY = StubIndexKey.createIndexKey("jet.package.object.fqn"); +// StubIndexKey EXTENSION_FUNCTION_TO_TYPE_FQN = StubIndexKey.createIndexKey("jet.extension.function.to.type.fqn"); +} + diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexedStubElementFactory.java b/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexedStubElementFactory.java new file mode 100644 index 00000000000..773389dc288 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexedStubElementFactory.java @@ -0,0 +1,40 @@ +package org.jetbrains.jet.plugin.stubindex; + +import com.intellij.psi.stubs.IndexSink; +import org.jetbrains.jet.lang.psi.stubs.PsiJetClassStub; +import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub; +import org.jetbrains.jet.lang.psi.stubs.elements.JetClassElementType; +import org.jetbrains.jet.lang.psi.stubs.elements.JetFunctionElementType; +import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementFactory; + +/** + * @author Nikolay Krasko + */ +public class JetIndexedStubElementFactory implements JetStubElementFactory { + @Override + public JetClassElementType getClassElementType() { + return new JetClassElementType("CLASS") { + @Override + public void indexStub(PsiJetClassStub stub, IndexSink sink) { + String name = stub.getName(); + if (name != null) { + sink.occurrence(JetIndexKeys.SHORT_NAME_KEY, name); + } + } + }; + } + + @Override + public JetFunctionElementType getFunctionElementType() { + return new JetFunctionElementType("FUN") { + @Override + public void indexStub(PsiJetFunctionStub stub, IndexSink sink) { + String name = stub.getName(); + // TODO: Check that function defined in top level + if (name != null) { + sink.occurrence(JetIndexKeys.TOP_LEVEL_FUNCTION_SHORT_NAME_KEY, name); + } + } + }; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/JetShortClassNameIndex.java b/idea/src/org/jetbrains/jet/plugin/stubindex/JetShortClassNameIndex.java new file mode 100644 index 00000000000..60afb4e5db2 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/JetShortClassNameIndex.java @@ -0,0 +1,30 @@ +package org.jetbrains.jet.plugin.stubindex; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.stubs.StringStubIndexExtension; +import com.intellij.psi.stubs.StubIndexKey; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetClassOrObject; + +import java.util.Collection; + +/** + * @author Nikolay Krasko + */ +public class JetShortClassNameIndex extends StringStubIndexExtension { + private static final JetShortClassNameIndex ourInstance = new JetShortClassNameIndex(); + public static JetShortClassNameIndex getInstance() { + return ourInstance; + } + + @Override + public StubIndexKey getKey() { + return JetIndexKeys.SHORT_NAME_KEY; + } + + @Override + public Collection get(final String s, final Project project, @NotNull final GlobalSearchScope scope) { + return super.get(s, project, new JetSourceFilterScope(scope)); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/JetShortFunctionNameIndex.java b/idea/src/org/jetbrains/jet/plugin/stubindex/JetShortFunctionNameIndex.java new file mode 100644 index 00000000000..bb167dfc667 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/JetShortFunctionNameIndex.java @@ -0,0 +1,31 @@ +package org.jetbrains.jet.plugin.stubindex; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.stubs.StringStubIndexExtension; +import com.intellij.psi.stubs.StubIndexKey; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetFunction; + +import java.util.Collection; + +/** + * @author Nikolay Krasko + */ +public class JetShortFunctionNameIndex extends StringStubIndexExtension { + private static final JetShortClassNameIndex ourInstance = new JetShortClassNameIndex(); + + public static JetShortClassNameIndex getInstance() { + return ourInstance; + } + + @Override + public StubIndexKey getKey() { + return JetIndexKeys.TOP_LEVEL_FUNCTION_SHORT_NAME_KEY; + } + + @Override + public Collection get(final String s, final Project project, @NotNull final GlobalSearchScope scope) { + return super.get(s, project, new JetSourceFilterScope(scope)); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/JetSourceFilterScope.java b/idea/src/org/jetbrains/jet/plugin/stubindex/JetSourceFilterScope.java new file mode 100644 index 00000000000..45a65a6573a --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/JetSourceFilterScope.java @@ -0,0 +1,34 @@ +package org.jetbrains.jet.plugin.stubindex; + +import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.search.DelegatingGlobalSearchScope; +import com.intellij.psi.search.GlobalSearchScope; +import org.jetbrains.annotations.NotNull; + +/** + * @author Nikolay Krasko + */ +public class JetSourceFilterScope extends DelegatingGlobalSearchScope { + private final ProjectFileIndex myIndex; + + public JetSourceFilterScope(@NotNull final GlobalSearchScope delegate) { + super(delegate); + myIndex = ProjectRootManager.getInstance(getProject()).getFileIndex(); + } + + @Override + public boolean contains(final VirtualFile file) { + if (!super.contains(file)) { + return false; + } + + if (StdFileTypes.CLASS == file.getFileType()) { + return myIndex.isInLibraryClasses(file); + } + + return myIndex.isInSourceContent(file); + } +} From ca1abed3a9f09162f91288d0fc0d67b9c8a90512 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Fri, 27 Jan 2012 18:30:18 +0400 Subject: [PATCH 2/2] Added example-vfs project written on Kotlin. --- .idea/modules.xml | 1 + examples/example-vfs/example-vfs.iml | 13 ++ examples/example-vfs/example-vfs.ipr | 170 +++++++++++++++++++ examples/example-vfs/src/FileSystem.kt | 130 ++++++++++++++ examples/example-vfs/src/Main.kt | 36 ++++ examples/example-vfs/src/RefreshQueue.kt | 138 +++++++++++++++ examples/example-vfs/src/Utils.kt | 42 +++++ examples/example-vfs/src/VirtualFile.kt | 164 ++++++++++++++++++ examples/example-vfs/src/VirtualFileEvent.kt | 42 +++++ 9 files changed, 736 insertions(+) create mode 100644 examples/example-vfs/example-vfs.iml create mode 100644 examples/example-vfs/example-vfs.ipr create mode 100644 examples/example-vfs/src/FileSystem.kt create mode 100644 examples/example-vfs/src/Main.kt create mode 100644 examples/example-vfs/src/RefreshQueue.kt create mode 100644 examples/example-vfs/src/Utils.kt create mode 100644 examples/example-vfs/src/VirtualFile.kt create mode 100644 examples/example-vfs/src/VirtualFileEvent.kt diff --git a/.idea/modules.xml b/.idea/modules.xml index 36ef0191ae1..c1f4844a4d1 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -7,6 +7,7 @@ + diff --git a/examples/example-vfs/example-vfs.iml b/examples/example-vfs/example-vfs.iml new file mode 100644 index 00000000000..37bed8abc1d --- /dev/null +++ b/examples/example-vfs/example-vfs.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/examples/example-vfs/example-vfs.ipr b/examples/example-vfs/example-vfs.ipr new file mode 100644 index 00000000000..77f63b1e9c3 --- /dev/null +++ b/examples/example-vfs/example-vfs.ipr @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + http://www.w3.org/1999/xhtml + + + + + + + + + diff --git a/examples/example-vfs/src/FileSystem.kt b/examples/example-vfs/src/FileSystem.kt new file mode 100644 index 00000000000..e9380227794 --- /dev/null +++ b/examples/example-vfs/src/FileSystem.kt @@ -0,0 +1,130 @@ +package org.jetbrains.jet.samples.vfs; + +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import org.jetbrains.jet.samples.vfs.utils.*; +import java.util.concurrent.locks.Lock +import java.io.File +import java.util.List +import java.util.ArrayList +import java.util.HashMap +import java.util.Arrays +import java.util.Map + +import std.util.* + +/** + * File system singleton. To work with virtual file system, read/write locks should be + * acquired: use read() and write() higher-order functions. + */ +public object FileSystem { + private val lock = ReentrantReadWriteLock() + internal val watchedDirectories = ArrayList + + // FIXME VirtualFiles should be used as hashmap keys themselves, + // but overriden hashCode() method fails in runtime with ClassCastException (KT-1134) + /** + * Mapping from virtual files to metainformation + */ + internal val fileToInfo = HashMap() + private val listeners = ArrayList() + + /** + * Returns corresponding virtual file for java.io.File. + * + * @param ioFile file + */ + public fun getFileByIoFile(ioFile : File) : VirtualFile { + FileSystem.assertCanRead() + return PhysicalVirtualFile(ioFile.getAbsolutePath().sure().toSystemIndependentPath()) + } + + /** + * Returns virtual file for path to it. + * + * @param path path to file + */ + public fun getFileByPath(path : String) : VirtualFile { + return getFileByIoFile(File(path)) + } + + /** + * Runs function with read lock. + */ + public inline fun read(task : () -> T) : T { + return locked(lock.readLock().sure(), task) + } + + /** + * Runs function with write lock. + */ + public inline fun write(task : () -> T) : T { + return locked(lock.writeLock().sure(), task) + } + + /** + * Adds directory to list of watched directories. Watched directories are + * periodically refreshed and corresponding events are sent to file system listeners. + * + * @param dir directory which should be watched + */ + public fun addWatchedDirectory(dir : VirtualFile) { + assertCanRead() + if (dir.isDirectory()) { + watchedDirectories.add(dir) + scanAndAddRecursivelyNoEvents(dir) + + RefreshQueue.scheduleRefresh() + } + } + + /* Scans file recursively and adds info about it to fileToInfo map */ + private fun scanAndAddRecursivelyNoEvents(file : VirtualFile) { + assert(FileSystem.fileToInfo[file.path] == null) + + val fileInfo = VirtualFileInfo(file) + FileSystem.fileToInfo[file.path] = fileInfo + fileInfo.children.foreach{ scanAndAddRecursivelyNoEvents(it) } + } + + internal inline fun assertCanRead() { + assert(lock.getReadHoldCount() != 0 || lock.isWriteLockedByCurrentThread()) + } + + internal inline fun assertCanWrite() { + assert(lock.isWriteLockedByCurrentThread()) + } + + /** + * Adds file system listener which should be notified about changing of file system. + */ + public fun addVirtualFileListener(listener : VirtualFileListener) { + listeners.add(listener) + } + + /** + * Removes file system listener. + */ + public fun removeVirtualFileListener(listener : VirtualFileListener) { + listeners.remove(listener) + } + + /* Notifies all listeners */ + internal fun notifyEventHappened(event : VirtualFileEvent) { + for (listener in listeners) { + listener.eventHappened(event) + } + } +} + +private class VirtualFileInfo(file : VirtualFile) { + /* Last modification time */ + var lastModified : Long = 0 + /* List of known children */ + val children : List = ArrayList; + + { + children.addAll(file.children()) + lastModified = file.modificationTime() + } +} diff --git a/examples/example-vfs/src/Main.kt b/examples/example-vfs/src/Main.kt new file mode 100644 index 00000000000..7c288a228b2 --- /dev/null +++ b/examples/example-vfs/src/Main.kt @@ -0,0 +1,36 @@ +package org.jetbrains.jet.samples.vfs.sandbox; + +import org.jetbrains.jet.samples.vfs.*; +import java.io.InputStreamReader +import java.util.Scanner + +/** + * Receives list of directories which should be watched, adds them to virtual file system, + * adds virtual file system listener and waits for 1 minutes, printing out all received event. + */ +fun main(args : Array) { + if (args.size == 0) { + println("Provide list of watched directories as command line arguments") + return + } + + // add watched directory + FileSystem.write { + for (val arg in args) { + FileSystem.addWatchedDirectory(FileSystem.getFileByPath(arg)) + } + } + + // add listener which prints out everything + FileSystem.addVirtualFileListener(object : VirtualFileListener { + override fun eventHappened(event: VirtualFileEvent) { + println(event) + if (event is VirtualFileChangedEvent) { + println("new file size is ${event.file.size()}") + } + } + }) + + // wait for 1 minute + Thread.sleep(60000) +} \ No newline at end of file diff --git a/examples/example-vfs/src/RefreshQueue.kt b/examples/example-vfs/src/RefreshQueue.kt new file mode 100644 index 00000000000..09e7f21713f --- /dev/null +++ b/examples/example-vfs/src/RefreshQueue.kt @@ -0,0 +1,138 @@ +package org.jetbrains.jet.samples.vfs; + +import java.util.concurrent.ConcurrentLinkedQueue +import java.util.List +import java.util.concurrent.locks.ReentrantLock +import java.util.concurrent.LinkedBlockingQueue +import java.util.ArrayList + +import std.util.* +import java.util.Timer +import java.util.TimerTask + +import org.jetbrains.jet.samples.vfs.utils.* + +/** + * Singleton which creates thread for periodically checking if there are changes in + * file system and notifying file system listeners. + */ +internal object RefreshQueue : Runnable { + private val taskQueue = LinkedBlockingQueue>() + private val workerThread: Thread = Thread(this) + private val fullRefreshScheduler = Timer(true); + + { + workerThread.setDaemon(true) + workerThread.start() + + fullRefreshScheduler.scheduleAtFixedRate(createTimerTask { + scheduleRefresh(FileSystem.watchedDirectories) + }, 0, 5000) + } + + private fun takeAndRefreshFiles() { + refreshFiles(taskQueue.take()) + } + + /* Acquires write lock and refreshes file system */ + private fun refreshFiles(files : List) { + FileSystem.write { + files.foreach{ refreshFile(it) } + } + } + + /* Checks for changes in virtual file recursively, notifying listeners. */ + private fun refreshFile(file : VirtualFile) { + FileSystem.assertCanWrite() + if (file.isDirectory()) { + val fileToInfo = FileSystem.fileToInfo + val fileInfo = fileToInfo[file.path] + val oldChildren = fileInfo.children + val newChildren = file.children() + + val addedChildren = listDifference(newChildren, oldChildren) + val deletedChildren = listDifference(oldChildren, newChildren) + val commonChildren = listIntersection(oldChildren, newChildren) + + addedChildren.foreach{ addRecursively(it) } + deletedChildren.foreach{ deleteRecursively(it) } + + fileInfo.children.clear() + fileInfo.children.addAll(newChildren) + + commonChildren.foreach{ refreshFile(it) } + } else { + val fileInfo = FileSystem.fileToInfo[file.path] + assert(fileInfo != null) + + val newModificationTime = file.modificationTime() + if (fileInfo.lastModified != newModificationTime) { + fileInfo.lastModified = newModificationTime + + FileSystem.notifyEventHappened(VirtualFileChangedEvent(file)) + } + } + } + + /* Adds file to file system recursively, notifying listeners */ + private fun addRecursively(file : VirtualFile) { + assert(FileSystem.fileToInfo[file] == null) + + val fileInfo = VirtualFileInfo(file) + + FileSystem.fileToInfo[file.path] = fileInfo + FileSystem.notifyEventHappened(VirtualFileCreateEvent(file)) + + fileInfo.children.foreach{ addRecursively(it) } + } + + /* Deletes file from file system recursively, notifying listeners */ + private fun deleteRecursively(file : VirtualFile) { + val fileInfoMaybe : VirtualFileInfo? = FileSystem.fileToInfo[file.path] + val fileInfo = fileInfoMaybe.sure() + fileInfo.children.foreach{ deleteRecursively(it) } + FileSystem.notifyEventHappened(VirtualFileDeletedEvent(file)) + FileSystem.fileToInfo.remove(file) + } + + /** + * Schedules refresh for given list of files. + */ + public fun scheduleRefresh(files : List) { + taskQueue.put(files) + } + + /** + * Schedules refresh for given list of files. + */ + public fun scheduleRefresh(vararg files : VirtualFile) { + // FIXME This could be written more concise, using map() & toList() (KT-1164 & KT-1172) + val filesList = ArrayList() + files.foreach{ filesList.add(it) } + taskQueue.put(filesList) + + // taskQueue.put(ArrayList(files.map{ it })) + // taskQueue.put(files.map{ it }.toList()) + } + + // FIXME RefreshQueue implements Runnable because of error on accessing + // private fields and methods from anonymous class (KT-1157 & KT-1159) ( + override fun run() { + while (!workerThread.isInterrupted()) { + try { + takeAndRefreshFiles() + } catch (e : InterruptedException) { + } + } + } +} + +// FIXME this method is used because of error on accessing +// private methods from anonymous class (KT-1157) ( +private fun createTimerTask(task : () -> Unit) : TimerTask { + return object : TimerTask() { + override fun run() { + task() + } + } +} \ No newline at end of file diff --git a/examples/example-vfs/src/Utils.kt b/examples/example-vfs/src/Utils.kt new file mode 100644 index 00000000000..7926599c927 --- /dev/null +++ b/examples/example-vfs/src/Utils.kt @@ -0,0 +1,42 @@ +package org.jetbrains.jet.samples.vfs.utils; + +import java.util.concurrent.locks.Lock +import java.util.List +import std.util.* + +/** + * Executes task with given lock acquired. + */ +private fun locked(lock : Lock, body : () -> T) : T { + lock.lock() + try { + return body() + } finally { + lock.unlock(); + } +} + +/** + * Checks boolean value which should be true. If it is false, throws Assertion Error + * + * @param value value to be checked + */ +public fun assert(value : Boolean) { + if (!value) { + throw AssertionError() + } +} + +/** + * Returns list containing all elements which first contains and second does not. + */ +public fun listDifference(first : List, second : List) : List { + return first.filter{ !second.contains(it) }.toList() +} + +/** + * Returns list containing all elements which both lists contain. + */ +public fun listIntersection(first : List, second : List) : List { + return first.filter{ second.contains(it) }.toList() +} diff --git a/examples/example-vfs/src/VirtualFile.kt b/examples/example-vfs/src/VirtualFile.kt new file mode 100644 index 00000000000..f848cedf4c7 --- /dev/null +++ b/examples/example-vfs/src/VirtualFile.kt @@ -0,0 +1,164 @@ +package org.jetbrains.jet.samples.vfs; + +import org.jetbrains.jet.samples.vfs.utils.*; +import java.io.File +import java.io.InputStream +import java.io.FileInputStream +import java.util.ArrayList +import java.util.List + +import std.util.* + +/** + * Abstract virtual file. + */ +public abstract class VirtualFile(public val path : String) { + // FIXME this method should be replaced with val (KT-1168, KT-1170) + protected abstract fun kind() : String + + // FIXME these abstract methods should be replaced with vals (KT-1165) + /** + * Returns file size. + */ + public abstract fun size() : Long + /** + * Returns the time that the virtual file was last modified (milliseconds since + * the epoch (00:00:00 GMT, January 1, 1970). + */ + public abstract fun modificationTime() : Long + /** + * Returns if virtual file exists. + */ + public abstract fun exists() : Boolean + /** + * Returns if virtual file is directory + */ + public abstract fun isDirectory() : Boolean + /** + * Returns list of virtual files which are children for this. + */ + public abstract fun children() : List + + /** + * Opens input stream for reading. After reading, stream should be closed. + * Reading from stream should be performed with read lock acquired. + */ + public abstract fun openInputStream() : InputStream + + fun equals(other : Any?) : Boolean { + return other is VirtualFile && kind() == other.kind() && path == other.path + } + + fun hashCode() : Int { + // FIXME rewrite without casting when it will be possible + return (kind() as java.lang.String).hashCode() * 31 + (path as java.lang.String).hashCode() + } + + fun toString(): String { + return "${kind()}[path=$path]" + } +} + +/** + * Type of virtual file which corresponds to real file in file system of OS. + */ +public class PhysicalVirtualFile(path : String) : VirtualFile(path) { + override fun kind() : String = "Physical" + + private val ioFile : File + get() = File(this.path.toSystemDependentPath()) + + override fun exists(): Boolean { + FileSystem.assertCanRead() + return ioFile.exists() + } + + override fun size(): Long { + FileSystem.assertCanRead() + return ioFile.length() + } + + override fun modificationTime(): Long { + FileSystem.assertCanRead() + return ioFile.lastModified() + } + + override fun isDirectory(): Boolean { + FileSystem.assertCanRead() + return ioFile.isDirectory() + } + + override fun children(): List { + FileSystem.assertCanRead() + return (ioFile.listFiles() ?: Array(0)). + map{ FileSystem.getFileByIoFile(it.sure()) }?.toList() + } + + override fun openInputStream(): InputStream { + FileSystem.assertCanRead() + if (isDirectory()) { + throw IllegalArgumentException("Can't open directory for reading"); + } + return CheckedInputStream(FileInputStream(ioFile)) + } +} + +private fun String.toSystemDependentPath() : String { + // FIXME constants should be extracted (NPE in compiler, KT-1111) + return this.replaceAll("/", java.io.File.separator.sure()) +} + +private fun String.toSystemIndependentPath() : String { + // FIXME constants should be extracted (NPE in compiler, KT-1111) + return this.replaceAll(java.io.File.separator.sure(), "/") +} + +/** + * InputStream wrapper which checks that file system read lock is acquired on each operation. + */ +private class CheckedInputStream(private val wrapped : InputStream) : InputStream() { + override fun read(): Int { + FileSystem.assertCanRead() + return wrapped.read() + } + + override fun read(b: ByteArray?, off: Int, len: Int) : Int { + FileSystem.assertCanRead() + return wrapped.read(b, off, len) + } + + override fun markSupported(): Boolean { + FileSystem.assertCanRead() + return wrapped.markSupported() + } + + override fun skip(n: Long): Long { + FileSystem.assertCanRead() + return wrapped.skip(n) + } + + override fun close() { + FileSystem.assertCanRead() + return wrapped.close() + } + + override fun mark(readlimit: Int) { + FileSystem.assertCanRead() + return wrapped.mark(readlimit) + } + + override fun read(b: ByteArray?): Int { + FileSystem.assertCanRead() + return wrapped.read(b) + } + + override fun reset() { + FileSystem.assertCanRead() + return wrapped.reset() + } + + override fun available(): Int { + FileSystem.assertCanRead() + return wrapped.available() + } +} \ No newline at end of file diff --git a/examples/example-vfs/src/VirtualFileEvent.kt b/examples/example-vfs/src/VirtualFileEvent.kt new file mode 100644 index 00000000000..7f3d043a5c4 --- /dev/null +++ b/examples/example-vfs/src/VirtualFileEvent.kt @@ -0,0 +1,42 @@ +package org.jetbrains.jet.samples.vfs; + +/** + * Listener for receiving virtual file event + */ +public trait VirtualFileListener : java.util.EventListener { + fun eventHappened(val event : VirtualFileEvent) +} + +/** + * Base type of virtual file events + * @property file affected by event + */ +public abstract class VirtualFileEvent(val file : VirtualFile) : Object() { +} + +/** + * Event of creating file + */ +public class VirtualFileCreateEvent(file : VirtualFile) : VirtualFileEvent(file) { + override fun toString(): String? { + return "created ${file}" + } +} + +/** + * Event of deleting file + */ +public class VirtualFileDeletedEvent(file : VirtualFile) : VirtualFileEvent(file) { + override fun toString(): String? { + return "deleted ${file}" + } +} + +/** + * Event of changing file contents + */ +public class VirtualFileChangedEvent(file : VirtualFile) : VirtualFileEvent(file) { + override fun toString(): String? { + return "changed ${file}" + } +}