diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassCodegen.kt index 13be7b6a667..1d6f37c9d1a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassCodegen.kt @@ -320,7 +320,7 @@ class MultifileClassCodegenImpl( private fun writeKotlinMultifileFacadeAnnotationIfNeeded() { if (!state.classBuilderMode.generateMetadata) return - if (files.any { it.isScript }) return + if (files.any { it.isScript() }) return val extraFlags = if (shouldGeneratePartHierarchy) JvmAnnotationNames.METADATA_MULTIFILE_PARTS_INHERIT_FLAG else 0 diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtCodeFragment.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtCodeFragment.kt index d4c27d161c3..5a0da935d42 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtCodeFragment.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtCodeFragment.kt @@ -144,9 +144,8 @@ abstract class KtCodeFragment( return null } - override fun getImportDirectives(): List { - return importsAsImportList()?.imports ?: emptyList() - } + override val importDirectives: List + get() = importsAsImportList()?.imports ?: emptyList() override fun setVisibilityChecker(checker: JavaCodeFragment.VisibilityChecker?) { } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtFile.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtFile.kt index 226b5b3a406..4335f68cf80 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtFile.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtFile.kt @@ -14,290 +14,189 @@ * limitations under the License. */ -package org.jetbrains.kotlin.psi; +package org.jetbrains.kotlin.psi -import com.intellij.extapi.psi.PsiFileBase; -import com.intellij.lang.ASTNode; -import com.intellij.lang.FileASTNode; -import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.fileTypes.FileType; -import com.intellij.psi.*; -import com.intellij.psi.stubs.StubElement; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.FileContentUtilCore; -import com.intellij.util.IncorrectOperationException; -import kotlin.collections.ArraysKt; -import kotlin.collections.CollectionsKt; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.KtNodeTypes; -import org.jetbrains.kotlin.idea.KotlinFileType; -import org.jetbrains.kotlin.idea.KotlinLanguage; -import org.jetbrains.kotlin.name.FqName; -import org.jetbrains.kotlin.parsing.KotlinParserDefinition; -import org.jetbrains.kotlin.psi.stubs.KotlinFileStub; -import org.jetbrains.kotlin.psi.stubs.elements.KtPlaceHolderStubElementType; -import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes; +import com.intellij.extapi.psi.PsiFileBase +import com.intellij.openapi.components.ServiceManager +import com.intellij.openapi.fileTypes.FileType +import com.intellij.psi.* +import com.intellij.psi.stubs.StubElement +import com.intellij.psi.util.PsiTreeUtil +import com.intellij.util.FileContentUtilCore +import com.intellij.util.IncorrectOperationException +import org.jetbrains.kotlin.KtNodeTypes +import org.jetbrains.kotlin.idea.KotlinFileType +import org.jetbrains.kotlin.idea.KotlinLanguage +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.parsing.KotlinParserDefinition +import org.jetbrains.kotlin.psi.psiUtil.getChildOfType +import org.jetbrains.kotlin.psi.stubs.KotlinFileStub +import org.jetbrains.kotlin.psi.stubs.elements.KtPlaceHolderStubElementType +import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +open class KtFile(viewProvider: FileViewProvider, val isCompiled: Boolean) : + PsiFileBase(viewProvider, KotlinLanguage.INSTANCE), + KtDeclarationContainer, + KtAnnotated, + KtElement, + PsiClassOwner, + PsiNamedElement, + PsiModifiableCodeBlock { -public class KtFile extends PsiFileBase implements KtDeclarationContainer, KtAnnotated, KtElement, PsiClassOwner, PsiNamedElement, PsiModifiableCodeBlock { + private var isScript: Boolean? = null - private final boolean isCompiled; - private Boolean isScript = null; + val importList: KtImportList? + get() = findChildByTypeOrClass(KtStubElementTypes.IMPORT_LIST, KtImportList::class.java) - public KtFile(FileViewProvider viewProvider, boolean compiled) { - super(viewProvider, KotlinLanguage.INSTANCE); - this.isCompiled = compiled; - } + val fileAnnotationList: KtFileAnnotationList? + get() = findChildByTypeOrClass(KtStubElementTypes.FILE_ANNOTATION_LIST, KtFileAnnotationList::class.java) - @Override - public FileASTNode getNode() { - return super.getNode(); - } - - public boolean isCompiled() { - return isCompiled; - } - - @Override - @NotNull - public FileType getFileType() { - return KotlinFileType.INSTANCE; - } - - @Override - public String toString() { - return "KtFile: " + getName(); - } - - @NotNull - @Override - public List getDeclarations() { - KotlinFileStub stub = getStub(); - if (stub != null) { - return Arrays.asList(stub.getChildrenByType(KtStubElementTypes.DECLARATION_TYPES, KtDeclaration.ARRAY_FACTORY)); - } - return PsiTreeUtil.getChildrenOfTypeAsList(this, KtDeclaration.class); - } - - @Nullable - public KtImportList getImportList() { - return findChildByTypeOrClass(KtStubElementTypes.IMPORT_LIST, KtImportList.class); - } - - @Nullable - public KtFileAnnotationList getFileAnnotationList() { - return findChildByTypeOrClass(KtStubElementTypes.FILE_ANNOTATION_LIST, KtFileAnnotationList.class); - } - - @Nullable - public >> T findChildByTypeOrClass( - @NotNull KtPlaceHolderStubElementType elementType, - @NotNull Class elementClass - ) { - KotlinFileStub stub = getStub(); - if (stub != null) { - StubElement importListStub = stub.findChildStubByType(elementType); - return importListStub != null ? importListStub.getPsi() : null; - } - return findChildByClass(elementClass); - } - - @NotNull - public List getImportDirectives() { - KtImportList importList = getImportList(); - return importList != null ? importList.getImports() : Collections.emptyList(); - } - - @Nullable - public KtImportDirective findImportByAlias(@NotNull String name) { - for (KtImportDirective directive : getImportDirectives()) { - if (name.equals(directive.getAliasName())) { - return directive; - } - } - return null; - } + open val importDirectives: List + get() = importList?.imports ?: emptyList() // scripts have no package directive, all other files must have package directives - @Nullable - public KtPackageDirective getPackageDirective() { - KotlinFileStub stub = getStub(); - if (stub != null) { - StubElement packageDirectiveStub = stub.findChildStubByType(KtStubElementTypes.PACKAGE_DIRECTIVE); - return packageDirectiveStub != null ? packageDirectiveStub.getPsi() : null; - } - return getPackageDirectiveByTree(); - } - - @Nullable - private KtPackageDirective getPackageDirectiveByTree() { - ASTNode ast = getNode().findChildByType(KtNodeTypes.PACKAGE_DIRECTIVE); - return ast != null ? (KtPackageDirective) ast.getPsi() : null; - } - - @Deprecated // getPackageFqName should be used instead - @Override - @NotNull - public String getPackageName() { - return getPackageFqName().asString(); - } - - @NotNull - public FqName getPackageFqName() { - KotlinFileStub stub = getStub(); - if (stub != null) { - return stub.getPackageFqName(); - } - return getPackageFqNameByTree(); - } - - @NotNull - public FqName getPackageFqNameByTree() { - KtPackageDirective packageDirective = getPackageDirectiveByTree(); - if (packageDirective == null) { - return FqName.ROOT; - } - return packageDirective.getFqName(); - } - - @Override - @Nullable - public KotlinFileStub getStub() { - return (KotlinFileStub) super.getStub(); - } - - @NotNull - @Override - public PsiClass[] getClasses() { - KtFileClassProvider fileClassProvider = ServiceManager.getService(getProject(), KtFileClassProvider.class); - // TODO We don't currently support finding light classes for scripts - if (fileClassProvider != null && !isScript()) { - return fileClassProvider.getFileClasses(this); - } - return PsiClass.EMPTY_ARRAY; - } - - @Override - public void setPackageName(String packageName) { } - - @Override - public void clearCaches() { - super.clearCaches(); - isScript = null; - } - - @Nullable - public KtScript getScript() { - if (isScript != null && !isScript) return null; - - KtScript result = PsiTreeUtil.getChildOfType(this, KtScript.class); - if (isScript == null) { - isScript = result != null; + val packageDirective: KtPackageDirective? + get() { + val stub = stub + if (stub != null) { + val packageDirectiveStub = stub.findChildStubByType(KtStubElementTypes.PACKAGE_DIRECTIVE) + return packageDirectiveStub?.psi + } + return packageDirectiveByTree } - return result; - } - - public boolean isScript() { - KotlinFileStub stub = getStub(); - if (stub != null) { - return stub.isScript(); + private val packageDirectiveByTree: KtPackageDirective? + get() { + val ast = node.findChildByType(KtNodeTypes.PACKAGE_DIRECTIVE) + return if (ast != null) ast.psi as KtPackageDirective else null } - return isScriptByTree(); - } - public boolean isScriptByTree() { - return getScript() != null; - } + val packageFqName: FqName + get() = stub?.getPackageFqName() ?: packageFqNameByTree - @NotNull - @Override - public String getName() { - return super.getName(); // TODO - } + val packageFqNameByTree: FqName + get() = packageDirectiveByTree?.fqName ?: FqName.ROOT - @Override - public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof KtVisitor) { - accept((KtVisitor) visitor, null); + val script: KtScript? + get() { + isScript?.let { if (!it) return null } + + val result = getChildOfType() + if (isScript == null) { + isScript = result != null + } + + return result } - else { - visitor.visitFile(this); - } - } - @NotNull - @Override - public KtFile getContainingKtFile() { - return this; - } - - @Override - public void acceptChildren(@NotNull KtVisitor visitor, D data) { - KtPsiUtil.visitChildren(this, visitor, data); - } - - @Override - public R accept(@NotNull KtVisitor visitor, D data) { - return visitor.visitKtFile(this, data); - } - - @NotNull - @Override - public List getAnnotations() { - KtFileAnnotationList fileAnnotationList = getFileAnnotationList(); - if (fileAnnotationList == null) return Collections.emptyList(); - - return fileAnnotationList.getAnnotations(); - } - - @NotNull - @Override - public List getAnnotationEntries() { - KtFileAnnotationList fileAnnotationList = getFileAnnotationList(); - if (fileAnnotationList == null) return Collections.emptyList(); - - return fileAnnotationList.getAnnotationEntries(); - } + val isScriptByTree: Boolean + get() = script != null /** * @return annotations that do not belong to any declaration due to incomplete code or syntax errors */ - @NotNull - public List getDanglingAnnotations() { - KotlinFileStub stub = getStub(); - KtModifierList[] danglingModifierLists = stub == null - ? findChildrenByClass(KtModifierList.class) - : stub.getChildrenByType( - KtStubElementTypes.MODIFIER_LIST, - KtStubElementTypes.MODIFIER_LIST.getArrayFactory() - ); - return ArraysKt.flatMap(danglingModifierLists, KtModifierList::getAnnotationEntries); - } - - @Override - public PsiElement setName(@NotNull String name) throws IncorrectOperationException { - PsiElement result = super.setName(name); - boolean willBeScript = name.endsWith(KotlinParserDefinition.STD_SCRIPT_EXT); - if (isScript() != willBeScript) { - FileContentUtilCore.reparseFiles(CollectionsKt.listOfNotNull(getVirtualFile())); + val danglingAnnotations: List + get() { + val stub = stub + val danglingModifierLists = stub?.getChildrenByType( + KtStubElementTypes.MODIFIER_LIST, + KtStubElementTypes.MODIFIER_LIST.arrayFactory + ) ?: findChildrenByClass(KtModifierList::class.java) + return danglingModifierLists.flatMap { obj: KtModifierList -> obj.annotationEntries } } - return result; + + override fun getFileType(): FileType = KotlinFileType.INSTANCE + + override fun toString(): String = "KtFile: " + name + + override fun getDeclarations(): List { + val stub = stub + return stub?.getChildrenByType(KtStubElementTypes.DECLARATION_TYPES, KtDeclaration.ARRAY_FACTORY)?.toList() + ?: PsiTreeUtil.getChildrenOfTypeAsList(this, KtDeclaration::class.java) } - @NotNull - @Override - public KtElement getPsiOrParent() { - return this; + fun >> findChildByTypeOrClass( + elementType: KtPlaceHolderStubElementType, + elementClass: Class + ): T? { + val stub = stub + if (stub != null) { + val importListStub = stub.findChildStubByType(elementType) + return importListStub?.psi + } + return findChildByClass(elementClass) } - @Override - public boolean shouldChangeModificationCount(PsiElement place) { + fun findImportByAlias(name: String): KtImportDirective? = + importDirectives.firstOrNull { name == it.aliasName } + + @Deprecated("") // getPackageFqName should be used instead + override fun getPackageName(): String { + return packageFqName.asString() + } + + override fun getStub(): KotlinFileStub? { + return super.getStub() as KotlinFileStub? + } + + override fun getClasses(): Array { + val fileClassProvider = ServiceManager.getService(project, KtFileClassProvider::class.java) + // TODO We don't currently support finding light classes for scripts + return if (fileClassProvider != null && !isScript()) { + fileClassProvider.getFileClasses(this) + } + else PsiClass.EMPTY_ARRAY + } + + override fun setPackageName(packageName: String) {} + + override fun clearCaches() { + super.clearCaches() + isScript = null + } + + fun isScript(): Boolean = stub?.isScript() ?: isScriptByTree + + override fun accept(visitor: PsiElementVisitor) { + if (visitor is KtVisitor<*, *>) { + @Suppress("UNCHECKED_CAST") + accept(visitor as KtVisitor, null) + } + else { + visitor.visitFile(this) + } + } + + override fun getContainingKtFile(): KtFile = this + + override fun acceptChildren(visitor: KtVisitor, data: D) { + KtPsiUtil.visitChildren(this, visitor, data) + } + + override fun accept(visitor: KtVisitor, data: D): R { + return visitor.visitKtFile(this, data) + } + + override fun getAnnotations(): List = + fileAnnotationList?.annotations ?: emptyList() + + override fun getAnnotationEntries(): List = + fileAnnotationList?.annotationEntries ?: emptyList() + + @Throws(IncorrectOperationException::class) + override fun setName(name: String): PsiElement { + val result = super.setName(name) + val willBeScript = name.endsWith(KotlinParserDefinition.STD_SCRIPT_EXT) + if (isScript() != willBeScript) { + FileContentUtilCore.reparseFiles(listOfNotNull(virtualFile)) + } + return result + } + + override fun getPsiOrParent(): KtElement = this + + override fun shouldChangeModificationCount(place: PsiElement): Boolean { // Modification count for Kotlin files is tracked entirely by KotlinCodeBlockModificationListener - return false; + return false } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/LazyTopDownAnalyzer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/LazyTopDownAnalyzer.kt index 2262577985e..5453579f8b5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/LazyTopDownAnalyzer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/LazyTopDownAnalyzer.kt @@ -91,7 +91,7 @@ class LazyTopDownAnalyzer( DescriptorResolver.registerFileInPackage(trace, file) registerDeclarations(file.declarations) val packageDirective = file.packageDirective - assert(file.isScript || packageDirective != null) { "No package in a non-script file: " + file } + assert(file.isScript() || packageDirective != null) { "No package in a non-script file: " + file } packageDirective?.accept(this) c.addFile(file) topLevelFqNames.put(file.packageFqName, packageDirective) @@ -169,7 +169,7 @@ class LazyTopDownAnalyzer( } override fun visitDestructuringDeclaration(destructuringDeclaration: KtDestructuringDeclaration) { - if (destructuringDeclaration.containingKtFile.isScript) { + if (destructuringDeclaration.containingKtFile.isScript()) { destructuringDeclarations.add(destructuringDeclaration) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt index b50cef9583a..d380e249bd4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt @@ -268,7 +268,7 @@ class CandidateResolver( private fun checkOuterClassMemberIsAccessible(context: CallCandidateResolutionContext<*>): Boolean { - fun KtElement.insideScript() = (containingFile as? KtFile)?.isScript ?: false + fun KtElement.insideScript() = (containingFile as? KtFile)?.isScript() ?: false // context.scope doesn't contains outer class implicit receiver if we inside nested class // Outer scope for some class in script file is scopeForInitializerResolution see: DeclarationScopeProviderImpl.getResolutionScopeForDeclaration diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt index b53b83c85f5..9598f5ceac6 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt @@ -334,7 +334,7 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC fun create(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? { - if (classOrObject.containingKtFile.isScript || classOrObject.hasModifier(KtTokens.HEADER_KEYWORD)) { + if (classOrObject.containingKtFile.isScript() || classOrObject.hasModifier(KtTokens.HEADER_KEYWORD)) { return null } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/duplicateJvmSignatureUtil.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/duplicateJvmSignatureUtil.kt index 26fdc20af27..c0a34a454f9 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/duplicateJvmSignatureUtil.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/duplicateJvmSignatureUtil.kt @@ -51,7 +51,7 @@ fun getJvmSignatureDiagnostics(element: PsiElement, otherDiagnostics: Diagnostic fun doGetDiagnostics(): Diagnostics? { //TODO: enable this diagnostic when light classes for scripts are ready - if ((element.containingFile as? KtFile)?.isScript ?: false) return null + if ((element.containingFile as? KtFile)?.isScript() ?: false) return null var parent = element.parent if (element is KtPropertyAccessor) { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/lightClasses/IDELightClassContexts.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/lightClasses/IDELightClassContexts.kt index adf371974f9..3b542eefaac 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/lightClasses/IDELightClassContexts.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/lightClasses/IDELightClassContexts.kt @@ -204,7 +204,7 @@ object IDELightClassContexts { fun forceResolvePackageDeclarations(files: Collection, session: ResolveSession) { for (file in files) { - if (file.isScript) continue + if (file.isScript()) continue val packageFqName = file.packageFqName diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingUtil.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingUtil.kt index d566d2c7ed1..3229563b5a1 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingUtil.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingUtil.kt @@ -27,12 +27,12 @@ object KotlinHighlightingUtil { fun shouldHighlight(psiElement: PsiElement): Boolean { val ktFile = psiElement.containingFile as? KtFile ?: return false return ktFile is KtCodeFragment && ktFile.context != null || - ktFile.isScript || + ktFile.isScript() || ProjectRootsUtil.isInProjectOrLibraryContent(ktFile) && ktFile.getModuleInfo() !is NotUnderContentRootModuleInfo } fun shouldHighlightErrors(psiElement: PsiElement): Boolean { val ktFile = psiElement.containingFile as? KtFile ?: return false - return (ktFile is KtCodeFragment && ktFile.context != null) || ktFile.isScript || ProjectRootsUtil.isInProjectSource(ktFile) + return (ktFile is KtCodeFragment && ktFile.context != null) || ktFile.isScript() || ProjectRootsUtil.isInProjectSource(ktFile) } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/internal/benchmark/AbstractCompletionBenchmarkAction.kt b/idea/src/org/jetbrains/kotlin/idea/actions/internal/benchmark/AbstractCompletionBenchmarkAction.kt index bb897e09465..c6f31de8f83 100644 --- a/idea/src/org/jetbrains/kotlin/idea/actions/internal/benchmark/AbstractCompletionBenchmarkAction.kt +++ b/idea/src/org/jetbrains/kotlin/idea/actions/internal/benchmark/AbstractCompletionBenchmarkAction.kt @@ -89,7 +89,7 @@ abstract class AbstractCompletionBenchmarkAction : AnAction() { fun KtFile.isUsableForBenchmark(): Boolean { val moduleInfo = this.getNullableModuleInfo() ?: return false - if (this.isCompiled || !this.isWritable || this.isScript) return false + if (this.isCompiled || !this.isWritable || this.isScript()) return false return moduleInfo.moduleOrigin == ModuleOrigin.MODULE } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractableAnalysisUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractableAnalysisUtil.kt index 7d7e4581d78..fd7891387f1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractableAnalysisUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractableAnalysisUtil.kt @@ -609,7 +609,7 @@ private fun ExtractionData.getLocalInstructions(pseudocode: Pseudocode): List - parent.getExtractionContainers(strict = true, includeAll = true).filter { it is KtClassBody || (it is KtFile && !it.isScript) } + parent.getExtractionContainers(strict = true, includeAll = true).filter { it is KtClassBody || (it is KtFile && !it.isScript()) } }, continuation )