diff --git a/java/java-psi-api/src/com/intellij/psi/PsiExportsStatement.java b/java/java-psi-api/src/com/intellij/psi/PsiExportsStatement.java index 3e383abc3d81..b0c68a8e4072 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiExportsStatement.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiExportsStatement.java @@ -23,5 +23,7 @@ import org.jetbrains.annotations.Nullable; * @since 2016.3 */ public interface PsiExportsStatement extends PsiElement { + PsiExportsStatement[] EMPTY_ARRAY = new PsiExportsStatement[0]; + @Nullable PsiJavaCodeReferenceElement getPackageReference(); } \ No newline at end of file diff --git a/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java b/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java index 7063b26b5e74..4f51300982bc 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java @@ -30,4 +30,7 @@ public interface PsiJavaModule extends NavigatablePsiElement, PsiNamedElement, P @NotNull PsiJavaModuleReferenceElement getNameElement(); @NotNull String getModuleName(); + + @NotNull Iterable getRequires(); + @NotNull Iterable getExports(); } \ No newline at end of file diff --git a/java/java-psi-api/src/com/intellij/psi/PsiRequiresStatement.java b/java/java-psi-api/src/com/intellij/psi/PsiRequiresStatement.java index 9c1dd8cd2947..0396011c63b9 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiRequiresStatement.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiRequiresStatement.java @@ -23,5 +23,7 @@ import org.jetbrains.annotations.Nullable; * @since 2016.3 */ public interface PsiRequiresStatement extends PsiElement { + PsiRequiresStatement[] EMPTY_ARRAY = new PsiRequiresStatement[0]; + @Nullable PsiJavaModuleReferenceElement getReferenceElement(); } \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java index 7811ea8626d5..c0214158562f 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java @@ -38,7 +38,7 @@ import static com.intellij.psi.compiled.ClassFileDecompilers.Full; public class ClassFileStubBuilder implements BinaryFileStubBuilder { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.compiled.ClassFileStubBuilder"); - public static final int STUB_VERSION = 17; + public static final int STUB_VERSION = 18; @Override public boolean acceptsFile(@NotNull VirtualFile file) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsExportsStatementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsExportsStatementImpl.java new file mode 100644 index 000000000000..1360368bd1be --- /dev/null +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsExportsStatementImpl.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2016 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.psi.impl.compiled; + +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiExportsStatement; +import com.intellij.psi.PsiJavaCodeReferenceElement; +import com.intellij.psi.impl.java.stubs.PsiExportsStatementStub; +import com.intellij.psi.impl.source.tree.JavaElementType; +import com.intellij.psi.impl.source.tree.TreeElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class ClsExportsStatementImpl extends ClsRepositoryPsiElement implements PsiExportsStatement { + public ClsExportsStatementImpl(PsiExportsStatementStub stub) { + super(stub); + } + + @Nullable + @Override + public PsiJavaCodeReferenceElement getPackageReference() { + return null; + } + + @Override + public void appendMirrorText(int indentLevel, @NotNull StringBuilder buffer) { + StringUtil.repeatSymbol(buffer, ' ', indentLevel); + PsiExportsStatementStub stub = getStub(); + buffer.append("exports ").append(stub.getPackageName()); + List targets = stub.getTargets(); + if (!targets.isEmpty()) { + buffer.append(" to "); + for (int i = 0; i < targets.size(); i++) { + if (i > 0) buffer.append(", "); + buffer.append(targets.get(i)); + } + } + buffer.append(";\n"); + } + + @Override + public void setMirror(@NotNull TreeElement element) throws InvalidMirrorException { + setMirrorCheckingType(element, JavaElementType.EXPORTS_STATEMENT); + } + + @Override + public String toString() { + return "PsiExportsStatement"; + } +} \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaModuleImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaModuleImpl.java index 42fbc9ff4b4e..446779744943 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaModuleImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaModuleImpl.java @@ -17,17 +17,24 @@ package com.intellij.psi.impl.compiled; import com.intellij.navigation.ItemPresentation; import com.intellij.navigation.ItemPresentationProviders; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.java.stubs.PsiJavaModuleStub; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.impl.source.tree.TreeElement; import com.intellij.psi.javadoc.PsiDocComment; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.JBIterable; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; + +import static java.util.Arrays.asList; + public class ClsJavaModuleImpl extends ClsRepositoryPsiElement implements PsiJavaModule { private PsiJavaModuleReferenceElement myReference; @@ -48,15 +55,50 @@ public class ClsJavaModuleImpl extends ClsRepositoryPsiElement getRequires() { + return JBIterable.of(getStub().getChildrenByType(JavaElementType.REQUIRES_STATEMENT, PsiRequiresStatement.EMPTY_ARRAY)); + } + + @NotNull + @Override + public Iterable getExports() { + return JBIterable.of(getStub().getChildrenByType(JavaElementType.EXPORTS_STATEMENT, PsiExportsStatement.EMPTY_ARRAY)); + } + @Override public void appendMirrorText(int indentLevel, @NotNull StringBuilder buffer) { - buffer.append("module ").append(getModuleName()).append(" { /* compiled code */ }"); + buffer.append("module ").append(getModuleName()).append(" {\n"); + + int newIndentLevel = indentLevel + getIndentSize(); + + int position = buffer.length(); + for (PsiRequiresStatement statement : getRequires()) appendText(statement, newIndentLevel, buffer); + + if (buffer.length() > position) buffer.append('\n'); + position = buffer.length(); + for (PsiExportsStatement statement : getExports()) appendText(statement, newIndentLevel, buffer); + + if (buffer.length() > position) buffer.append('\n'); + StringUtil.repeatSymbol(buffer, ' ', newIndentLevel); + buffer.append("/* ... */\n}"); } @Override public void setMirror(@NotNull TreeElement element) throws InvalidMirrorException { + PsiJavaModule mirror = SourceTreeToPsiMap.treeToPsiNotNull(element); + setMirrorCheckingType(element, JavaElementType.MODULE); - setMirror(getNameElement(), SourceTreeToPsiMap.treeToPsiNotNull(element).getNameElement()); + setMirror(getNameElement(), mirror.getNameElement()); + + List requires = + asList(getStub().getChildrenByType(JavaElementType.REQUIRES_STATEMENT, PsiRequiresStatement.EMPTY_ARRAY)); + setMirrors(requires, PsiTreeUtil.getChildrenOfTypeAsList(mirror, PsiRequiresStatement.class)); + + List exports = + asList(getStub().getChildrenByType(JavaElementType.EXPORTS_STATEMENT, PsiExportsStatement.EMPTY_ARRAY)); + setMirrors(exports, PsiTreeUtil.getChildrenOfTypeAsList(mirror, PsiExportsStatement.class)); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsRequiresStatementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsRequiresStatementImpl.java new file mode 100644 index 000000000000..9b617657ad9b --- /dev/null +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsRequiresStatementImpl.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2016 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.psi.impl.compiled; + +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiJavaModuleReferenceElement; +import com.intellij.psi.PsiRequiresStatement; +import com.intellij.psi.impl.java.stubs.PsiRequiresStatementStub; +import com.intellij.psi.impl.source.tree.JavaElementType; +import com.intellij.psi.impl.source.tree.TreeElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ClsRequiresStatementImpl extends ClsRepositoryPsiElement implements PsiRequiresStatement { + public ClsRequiresStatementImpl(PsiRequiresStatementStub stub) { + super(stub); + } + + @Nullable + @Override + public PsiJavaModuleReferenceElement getReferenceElement() { + return null; + } + + @Override + public void appendMirrorText(int indentLevel, @NotNull StringBuilder buffer) { + StringUtil.repeatSymbol(buffer, ' ', indentLevel); + PsiRequiresStatementStub stub = getStub(); + buffer.append("requires "); + if (stub.isPublic()) buffer.append("public "); + if (stub.isStatic()) buffer.append("static "); + buffer.append(stub.getModuleName()).append(";\n"); + } + + @Override + public void setMirror(@NotNull TreeElement element) throws InvalidMirrorException { + setMirrorCheckingType(element, JavaElementType.REQUIRES_STATEMENT); + } + + @Override + public String toString() { + return "PsiRequiresStatement"; + } +} \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ModuleStubBuildingVisitor.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ModuleStubBuildingVisitor.java index 377d8c2003a4..0506bd594861 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ModuleStubBuildingVisitor.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ModuleStubBuildingVisitor.java @@ -17,12 +17,21 @@ package com.intellij.psi.impl.compiled; import com.intellij.psi.impl.java.stubs.PsiJavaFileStub; import com.intellij.psi.impl.java.stubs.PsiJavaModuleStub; +import com.intellij.psi.impl.java.stubs.impl.PsiExportsStatementStubImpl; import com.intellij.psi.impl.java.stubs.impl.PsiJavaModuleStubImpl; +import com.intellij.psi.impl.java.stubs.impl.PsiRequiresStatementStubImpl; import org.jetbrains.org.objectweb.asm.ClassVisitor; import org.jetbrains.org.objectweb.asm.ModuleVisitor; import org.jetbrains.org.objectweb.asm.Opcodes; +import java.util.Arrays; + +import static com.intellij.util.BitUtil.isSet; + public class ModuleStubBuildingVisitor extends ClassVisitor { + private static final int ACC_TRANSITIVE = 0x0010; + private static final int ACC_STATIC_PHASE = 0x0020; + private final PsiJavaFileStub myParent; private final String myModuleName; private PsiJavaModuleStub myResult; @@ -40,6 +49,19 @@ public class ModuleStubBuildingVisitor extends ClassVisitor { @Override public ModuleVisitor visitModule() { myResult = new PsiJavaModuleStubImpl(myParent, myModuleName); - return null; + return new ModuleVisitor(Opcodes.API_VERSION) { + @Override + public void visitRequire(String module, int access) { + if (!isSet(access, Opcodes.ACC_SYNTHETIC) && !isSet(access, Opcodes.ACC_MANDATED)) { + boolean isPublic = isSet(access, ACC_TRANSITIVE) | isSet(access, Opcodes.ACC_PUBLIC); + new PsiRequiresStatementStubImpl(myResult, module, isPublic, isSet(access, ACC_STATIC_PHASE)); + } + } + + @Override + public void visitExport(String packageName, String... modules) { + new PsiExportsStatementStubImpl(myResult, packageName.replace('/', '.'), modules == null ? null : Arrays.asList(modules)); + } + }; } } \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/ClsStubPsiFactory.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/ClsStubPsiFactory.java index fedd8d58a9ee..ca56d1838ef1 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/ClsStubPsiFactory.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/ClsStubPsiFactory.java @@ -105,4 +105,14 @@ public class ClsStubPsiFactory extends StubPsiFactory { public PsiJavaModule createModule(PsiJavaModuleStub stub) { return new ClsJavaModuleImpl(stub); } + + @Override + public PsiRequiresStatement createRequiresStatement(PsiRequiresStatementStub stub) { + return new ClsRequiresStatementImpl(stub); + } + + @Override + public PsiExportsStatement createExportsStatement(PsiExportsStatementStub stub) { + return new ClsExportsStatementImpl(stub); + } } \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaExportsStatementElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaExportsStatementElementType.java new file mode 100644 index 000000000000..e3d4c2cf3cfd --- /dev/null +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaExportsStatementElementType.java @@ -0,0 +1,90 @@ +/* + * Copyright 2000-2016 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.psi.impl.java.stubs; + +import com.intellij.lang.ASTNode; +import com.intellij.lang.LighterAST; +import com.intellij.lang.LighterASTNode; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiExportsStatement; +import com.intellij.psi.impl.java.stubs.impl.PsiExportsStatementStubImpl; +import com.intellij.psi.impl.source.PsiExportsStatementImpl; +import com.intellij.psi.impl.source.tree.CompositeElement; +import com.intellij.psi.impl.source.tree.JavaElementType; +import com.intellij.psi.impl.source.tree.JavaSourceUtil; +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.IElementType; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.util.List; + +public class JavaExportsStatementElementType extends JavaStubElementType { + public JavaExportsStatementElementType() { + super("EXPORTS_STATEMENT"); + } + + @NotNull + @Override + public ASTNode createCompositeNode() { + return new CompositeElement(this); + } + + @Override + public PsiExportsStatement createPsi(@NotNull PsiExportsStatementStub stub) { + return getPsiFactory(stub).createExportsStatement(stub); + } + + @Override + public PsiExportsStatement createPsi(@NotNull ASTNode node) { + return new PsiExportsStatementImpl(node); + } + + @Override + public PsiExportsStatementStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { + String refText = null; + List to = ContainerUtil.newSmartList(); + + for (LighterASTNode child : tree.getChildren(node)) { + IElementType type = child.getTokenType(); + if (type == JavaElementType.JAVA_CODE_REFERENCE) refText = JavaSourceUtil.getReferenceText(tree, child); + else if (type == JavaElementType.MODULE_REFERENCE) to.add(JavaSourceUtil.getReferenceText(tree, child)); + } + + return new PsiExportsStatementStubImpl(parentStub, refText, to); + } + + @Override + public void serialize(@NotNull PsiExportsStatementStub stub, @NotNull StubOutputStream dataStream) throws IOException { + dataStream.writeUTFFast(stub.getPackageName()); + dataStream.writeUTFFast(StringUtil.join(stub.getTargets(), "/")); + } + + @NotNull + @Override + public PsiExportsStatementStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException { + String packageName = dataStream.readUTFFast(); + List targets = StringUtil.split(dataStream.readUTFFast(), "/"); + return new PsiExportsStatementStubImpl(parentStub, packageName, targets); + } + + @Override + public void indexStub(@NotNull PsiExportsStatementStub stub, @NotNull IndexSink sink) { } +} \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaRequiresStatementElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaRequiresStatementElementType.java new file mode 100644 index 000000000000..405f8f3478d7 --- /dev/null +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaRequiresStatementElementType.java @@ -0,0 +1,90 @@ +/* + * Copyright 2000-2016 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.psi.impl.java.stubs; + +import com.intellij.lang.ASTNode; +import com.intellij.lang.LighterAST; +import com.intellij.lang.LighterASTNode; +import com.intellij.psi.JavaTokenType; +import com.intellij.psi.PsiRequiresStatement; +import com.intellij.psi.impl.java.stubs.impl.PsiRequiresStatementStubImpl; +import com.intellij.psi.impl.source.PsiRequiresStatementImpl; +import com.intellij.psi.impl.source.tree.CompositeElement; +import com.intellij.psi.impl.source.tree.JavaElementType; +import com.intellij.psi.impl.source.tree.JavaSourceUtil; +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.IElementType; +import com.intellij.util.io.StringRef; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; + +public class JavaRequiresStatementElementType extends JavaStubElementType { + public JavaRequiresStatementElementType() { + super("REQUIRES_STATEMENT"); + } + + @NotNull + @Override + public ASTNode createCompositeNode() { + return new CompositeElement(this); + } + + @Override + public PsiRequiresStatement createPsi(@NotNull PsiRequiresStatementStub stub) { + return getPsiFactory(stub).createRequiresStatement(stub); + } + + @Override + public PsiRequiresStatement createPsi(@NotNull ASTNode node) { + return new PsiRequiresStatementImpl(node); + } + + @Override + public PsiRequiresStatementStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { + String refText = null; + boolean isPublic = false, isStatic = false; + + for (LighterASTNode child : tree.getChildren(node)) { + IElementType type = child.getTokenType(); + if (type == JavaElementType.MODULE_REFERENCE) refText = JavaSourceUtil.getReferenceText(tree, child); + else if (type == JavaTokenType.PUBLIC_KEYWORD) isPublic = true; + else if (type == JavaTokenType.STATIC_KEYWORD) isStatic = true; + } + + return new PsiRequiresStatementStubImpl(parentStub, refText, isPublic, isStatic); + } + + @Override + public void serialize(@NotNull PsiRequiresStatementStub stub, @NotNull StubOutputStream dataStream) throws IOException { + dataStream.writeName(stub.getModuleName()); + dataStream.writeByte(stub.getFlags()); + } + + @NotNull + @Override + public PsiRequiresStatementStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException { + String name = StringRef.toString(dataStream.readName()); + byte flags = dataStream.readByte(); + return new PsiRequiresStatementStubImpl(parentStub, name, flags); + } + + @Override + public void indexStub(@NotNull PsiRequiresStatementStub stub, @NotNull IndexSink sink) { } +} \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaStubElementTypes.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaStubElementTypes.java index 981e99112707..be56a34a5166 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaStubElementTypes.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaStubElementTypes.java @@ -39,6 +39,8 @@ public interface JavaStubElementTypes { JavaClassInitializerElementType CLASS_INITIALIZER = new JavaClassInitializerElementType(); JavaImportListElementType IMPORT_LIST = new JavaImportListElementType(); JavaModuleElementType MODULE = new JavaModuleElementType(); + JavaRequiresStatementElementType REQUIRES_STATEMENT = new JavaRequiresStatementElementType(); + JavaExportsStatementElementType EXPORTS_STATEMENT = new JavaExportsStatementElementType(); JavaClassElementType CLASS = new JavaClassElementType("CLASS") { @NotNull @@ -137,4 +139,4 @@ public interface JavaStubElementTypes { }; IStubFileElementType JAVA_FILE = new JavaFileElementType(); -} +} \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiExportsStatementStub.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiExportsStatementStub.java new file mode 100644 index 000000000000..3448453e1410 --- /dev/null +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiExportsStatementStub.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2016 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.psi.impl.java.stubs; + +import com.intellij.psi.PsiExportsStatement; +import com.intellij.psi.stubs.StubElement; + +import java.util.List; + +public interface PsiExportsStatementStub extends StubElement { + String getPackageName(); + List getTargets(); +} \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiRequiresStatementStub.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiRequiresStatementStub.java new file mode 100644 index 000000000000..2728b5f1323a --- /dev/null +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiRequiresStatementStub.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2016 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.psi.impl.java.stubs; + +import com.intellij.psi.PsiRequiresStatement; +import com.intellij.psi.stubs.StubElement; + +public interface PsiRequiresStatementStub extends StubElement { + String getModuleName(); + byte getFlags(); + boolean isPublic(); + boolean isStatic(); +} \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/SourceStubPsiFactory.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/SourceStubPsiFactory.java index 453cbbfc0a27..7c6ec8c530be 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/SourceStubPsiFactory.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/SourceStubPsiFactory.java @@ -116,4 +116,14 @@ public class SourceStubPsiFactory extends StubPsiFactory { public PsiJavaModule createModule(PsiJavaModuleStub stub) { return new PsiJavaModuleImpl(stub); } + + @Override + public PsiRequiresStatement createRequiresStatement(PsiRequiresStatementStub stub) { + return new PsiRequiresStatementImpl(stub); + } + + @Override + public PsiExportsStatement createExportsStatement(PsiExportsStatementStub stub) { + return new PsiExportsStatementImpl(stub); + } } \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/StubPsiFactory.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/StubPsiFactory.java index 40a23f5b48c7..bce30c89c30f 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/StubPsiFactory.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/StubPsiFactory.java @@ -55,4 +55,12 @@ public abstract class StubPsiFactory { public PsiJavaModule createModule(PsiJavaModuleStub stub) { return null; } + + public PsiRequiresStatement createRequiresStatement(PsiRequiresStatementStub stub) { + return null; + } + + public PsiExportsStatement createExportsStatement(PsiExportsStatementStub stub) { + return null; + } } \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiExportsStatementStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiExportsStatementStubImpl.java new file mode 100644 index 000000000000..9bfd35f5824c --- /dev/null +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiExportsStatementStubImpl.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2016 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.psi.impl.java.stubs.impl; + +import com.intellij.psi.PsiExportsStatement; +import com.intellij.psi.impl.java.stubs.JavaStubElementTypes; +import com.intellij.psi.impl.java.stubs.PsiExportsStatementStub; +import com.intellij.psi.stubs.StubBase; +import com.intellij.psi.stubs.StubElement; + +import java.util.Collections; +import java.util.List; + +public class PsiExportsStatementStubImpl extends StubBase implements PsiExportsStatementStub { + private final String myPackageName; + private final List myTargets; + + public PsiExportsStatementStubImpl(StubElement parent, String packageName, List targets) { + super(parent, JavaStubElementTypes.EXPORTS_STATEMENT); + myPackageName = packageName; + myTargets = targets == null || targets.isEmpty() ? Collections.emptyList() : Collections.unmodifiableList(targets); + } + + @Override + public String getPackageName() { + return myPackageName; + } + + @Override + public List getTargets() { + return myTargets; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("PsiExportsStatementStub:").append(myPackageName); + for (String target : myTargets) sb.append(':').append(target); + return sb.toString(); + } +} \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiRequiresStatementStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiRequiresStatementStubImpl.java new file mode 100644 index 000000000000..f4469aeda47e --- /dev/null +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiRequiresStatementStubImpl.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2016 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.psi.impl.java.stubs.impl; + +import com.intellij.psi.PsiRequiresStatement; +import com.intellij.psi.impl.java.stubs.JavaStubElementTypes; +import com.intellij.psi.impl.java.stubs.PsiRequiresStatementStub; +import com.intellij.psi.stubs.StubBase; +import com.intellij.psi.stubs.StubElement; + +public class PsiRequiresStatementStubImpl extends StubBase implements PsiRequiresStatementStub { + private static final byte PUBLIC = 0x01; + private static final byte STATIC = 0x02; + + private final String myModuleName; + private final byte myFlags; + + public PsiRequiresStatementStubImpl(StubElement parent, String refText, boolean isPublic, boolean isStatic) { + this(parent, refText, (byte)((isPublic ? PUBLIC : 0) | (isStatic ? STATIC : 0))); + } + + public PsiRequiresStatementStubImpl(StubElement parent, String refText, byte flags) { + super(parent, JavaStubElementTypes.REQUIRES_STATEMENT); + myModuleName = refText; + myFlags = flags; + } + + @Override + public String getModuleName() { + return myModuleName; + } + + @Override + public byte getFlags() { + return myFlags; + } + + @Override + public boolean isPublic() { + return (myFlags & PUBLIC) != 0; + } + + @Override + public boolean isStatic() { + return (myFlags & STATIC) != 0; + } + + @Override + public String toString() { + return "PsiRequiresStatementStub:" + myFlags + ":" + myModuleName; + } +} \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/JavaFileElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/JavaFileElementType.java index 9dc457c6e3fd..61e11fb8f93d 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/JavaFileElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/JavaFileElementType.java @@ -38,7 +38,7 @@ import java.io.IOException; * @author max */ public class JavaFileElementType extends ILightStubFileElementType { - public static final int STUB_VERSION = 37; + public static final int STUB_VERSION = 38; public JavaFileElementType() { super("java.FILE", JavaLanguage.INSTANCE); @@ -115,4 +115,4 @@ public class JavaFileElementType extends ILightStubFileElementType implements PsiExportsStatement { + public PsiExportsStatementImpl(@NotNull PsiExportsStatementStub stub) { + super(stub, JavaStubElementTypes.EXPORTS_STATEMENT); + } + + public PsiExportsStatementImpl(@NotNull ASTNode node) { + super(node); } @Nullable diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java index 8698d35572d6..300ca43cdd3c 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java @@ -21,12 +21,16 @@ import com.intellij.navigation.ItemPresentationProviders; import com.intellij.psi.*; import com.intellij.psi.impl.java.stubs.JavaStubElementTypes; import com.intellij.psi.impl.java.stubs.PsiJavaModuleStub; +import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.JBIterable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import static com.intellij.psi.SyntaxTraverser.psiTraverser; + public class PsiJavaModuleImpl extends JavaStubPsiElement implements PsiJavaModule { public PsiJavaModuleImpl(@NotNull PsiJavaModuleStub stub) { super(stub, JavaStubElementTypes.MODULE); @@ -49,8 +53,33 @@ public class PsiJavaModuleImpl extends JavaStubPsiElement imp if (stub != null) { return stub.getName(); } + else { + return getNameElement().getReferenceText(); + } + } - return getNameElement().getReferenceText(); + @NotNull + @Override + public Iterable getRequires() { + PsiJavaModuleStub stub = getGreenStub(); + if (stub != null) { + return JBIterable.of(stub.getChildrenByType(JavaElementType.REQUIRES_STATEMENT, PsiRequiresStatement.EMPTY_ARRAY)); + } + else { + return psiTraverser().children(this).filter(PsiRequiresStatement.class); + } + } + + @NotNull + @Override + public Iterable getExports() { + PsiJavaModuleStub stub = getGreenStub(); + if (stub != null) { + return JBIterable.of(stub.getChildrenByType(JavaElementType.EXPORTS_STATEMENT, PsiExportsStatement.EMPTY_ARRAY)); + } + else { + return psiTraverser().children(this).filter(PsiExportsStatement.class); + } } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiRequiresStatementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiRequiresStatementImpl.java index 43e438152e4c..00dc7981d979 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiRequiresStatementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiRequiresStatementImpl.java @@ -15,19 +15,24 @@ */ package com.intellij.psi.impl.source; +import com.intellij.lang.ASTNode; import com.intellij.psi.JavaElementVisitor; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiJavaModuleReferenceElement; import com.intellij.psi.PsiRequiresStatement; -import com.intellij.psi.impl.source.tree.CompositePsiElement; -import com.intellij.psi.impl.source.tree.JavaElementType; +import com.intellij.psi.impl.java.stubs.JavaStubElementTypes; +import com.intellij.psi.impl.java.stubs.PsiRequiresStatementStub; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class PsiRequiresStatementImpl extends CompositePsiElement implements PsiRequiresStatement { - public PsiRequiresStatementImpl() { - super(JavaElementType.REQUIRES_STATEMENT); +public class PsiRequiresStatementImpl extends JavaStubPsiElement implements PsiRequiresStatement { + public PsiRequiresStatementImpl(@NotNull PsiRequiresStatementStub stub) { + super(stub, JavaStubElementTypes.REQUIRES_STATEMENT); + } + + public PsiRequiresStatementImpl(@NotNull ASTNode node) { + super(node); } @Nullable diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java index 4bc6de09db0e..a13993907c3f 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java @@ -83,9 +83,11 @@ public interface JavaElementType { IElementType PARAMETER_LIST = JavaStubElementTypes.PARAMETER_LIST; IElementType EXTENDS_BOUND_LIST = JavaStubElementTypes.EXTENDS_BOUND_LIST; IElementType THROWS_LIST = JavaStubElementTypes.THROWS_LIST; - IElementType MODULE = JavaStubElementTypes.MODULE; IElementType LAMBDA_EXPRESSION = JavaStubElementTypes.LAMBDA_EXPRESSION; IElementType METHOD_REF_EXPRESSION = JavaStubElementTypes.METHOD_REFERENCE; + IElementType MODULE = JavaStubElementTypes.MODULE; + IElementType REQUIRES_STATEMENT = JavaStubElementTypes.REQUIRES_STATEMENT; + IElementType EXPORTS_STATEMENT = JavaStubElementTypes.EXPORTS_STATEMENT; IElementType IMPORT_STATIC_REFERENCE = new JavaCompositeElementType("IMPORT_STATIC_REFERENCE", PsiImportStaticReferenceElementImpl.class); IElementType TYPE = new JavaCompositeElementType("TYPE", PsiTypeElementImpl.class); @@ -140,8 +142,6 @@ public interface JavaElementType { IElementType ANNOTATION_ARRAY_INITIALIZER = new JavaCompositeElementType("ANNOTATION_ARRAY_INITIALIZER", PsiArrayInitializerMemberValueImpl.class); IElementType RECEIVER_PARAMETER = new JavaCompositeElementType("RECEIVER", PsiReceiverParameterImpl.class); IElementType MODULE_REFERENCE = new JavaCompositeElementType("MODULE_REFERENCE", PsiJavaModuleReferenceElementImpl.class); - IElementType REQUIRES_STATEMENT = new JavaCompositeElementType("REQUIRES_STATEMENT", PsiRequiresStatementImpl.class); - IElementType EXPORTS_STATEMENT = new JavaCompositeElementType("EXPORTS_STATEMENT", PsiExportsStatementImpl.class); IElementType USES_STATEMENT = new JavaCompositeElementType("USES_STATEMENT", PsiUsesStatementImpl.class); IElementType PROVIDES_STATEMENT = new JavaCompositeElementType("PROVIDES_STATEMENT", PsiProvidesStatementImpl.class); @@ -293,4 +293,4 @@ public interface JavaElementType { } } IElementType DUMMY_ELEMENT = new JavaDummyElementType(); -} +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/cls/mirror/module-info.txt b/java/java-tests/testData/psi/cls/mirror/module-info.txt index 6a885b363c1a..4ebaa716e475 100644 --- a/java/java-tests/testData/psi/cls/mirror/module-info.txt +++ b/java/java-tests/testData/psi/cls/mirror/module-info.txt @@ -2,4 +2,12 @@ // IntelliJ API Decompiler stub source generated from a class file // Implementation of methods is not available -module M.N { /* compiled code */ } \ No newline at end of file +module M.N { + requires java.desktop; + requires public java.logging; + + exports pkg.d1; + exports pkg.d2 to java.desktop; + + /* ... */ +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/cls/stubBuilder/module-info.class b/java/java-tests/testData/psi/cls/stubBuilder/module-info.class index e6b1506e9dbf..012110655449 100644 Binary files a/java/java-tests/testData/psi/cls/stubBuilder/module-info.class and b/java/java-tests/testData/psi/cls/stubBuilder/module-info.class differ diff --git a/java/java-tests/testData/psi/cls/stubBuilder/module-info.txt b/java/java-tests/testData/psi/cls/stubBuilder/module-info.txt index fedac2fb4405..c3b01dfb0a5e 100644 --- a/java/java-tests/testData/psi/cls/stubBuilder/module-info.txt +++ b/java/java-tests/testData/psi/cls/stubBuilder/module-info.txt @@ -1,2 +1,6 @@ PsiJavaFileStub [] - PsiJavaModuleStub:M.N \ No newline at end of file + PsiJavaModuleStub:M.N + PsiRequiresStatementStub:0:java.desktop + PsiRequiresStatementStub:1:java.logging + PsiExportsStatementStub:pkg.d1 + PsiExportsStatementStub:pkg.d2:java.desktop \ No newline at end of file