KotlinLightClassBuilderFactory, LightClassBuilder: refactor, clarify

This commit is contained in:
Pavel V. Talanov
2017-03-14 16:20:54 +03:00
parent c73e58516b
commit a645dc109a
4 changed files with 62 additions and 86 deletions
@@ -1,60 +0,0 @@
/*
* Copyright 2010-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 org.jetbrains.kotlin.asJava.builder;
import com.intellij.psi.stubs.StubElement;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.codegen.ClassBuilder;
import org.jetbrains.kotlin.codegen.ClassBuilderFactory;
import org.jetbrains.kotlin.codegen.ClassBuilderMode;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
/*package*/ class KotlinLightClassBuilderFactory implements ClassBuilderFactory {
private final Stack<StubElement> stubStack;
public KotlinLightClassBuilderFactory(Stack<StubElement> stubStack) {
this.stubStack = stubStack;
}
@NotNull
@Override
public ClassBuilderMode getClassBuilderMode() {
return ClassBuilderMode.LIGHT_CLASSES;
}
@NotNull
@Override
public ClassBuilder newClassBuilder(@NotNull JvmDeclarationOrigin origin) {
return new StubClassBuilder(stubStack);
}
@Override
public String asText(ClassBuilder builder) {
throw new UnsupportedOperationException("asText is not implemented"); // TODO
}
@Override
public byte[] asBytes(ClassBuilder builder) {
throw new UnsupportedOperationException("asBytes is not implemented"); // TODO
}
@Override
public void close() {
}
}
@@ -0,0 +1,51 @@
/*
* Copyright 2010-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 org.jetbrains.kotlin.asJava.builder
import com.intellij.openapi.diagnostic.Logger
import com.intellij.psi.PsiElement
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
import com.intellij.psi.stubs.StubElement
import com.intellij.util.containers.Stack
import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.ClassBuilderFactory
import org.jetbrains.kotlin.codegen.ClassBuilderMode
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
class KotlinLightClassBuilderFactory(private val javaFileStub: PsiJavaFileStub) : ClassBuilderFactory {
private val stubStack = Stack<StubElement<PsiElement>>().apply {
@Suppress("UNCHECKED_CAST")
push(javaFileStub as StubElement<PsiElement>)
}
override fun getClassBuilderMode(): ClassBuilderMode = ClassBuilderMode.LIGHT_CLASSES
override fun newClassBuilder(origin: JvmDeclarationOrigin) = StubClassBuilder(stubStack, javaFileStub)
override fun asText(builder: ClassBuilder) = throw UnsupportedOperationException("asText is not implemented")
override fun asBytes(builder: ClassBuilder) = throw UnsupportedOperationException("asBytes is not implemented")
override fun close() {}
fun result(): PsiJavaFileStub {
val pop = stubStack.pop()
if (pop !== javaFileStub) {
LOG.error("Unbalanced stack operations: " + pop)
}
return javaFileStub
}
}
private val LOG = Logger.getInstance(KotlinLightClassBuilderFactory::class.java)
@@ -23,13 +23,10 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.ClassFileViewProvider import com.intellij.psi.ClassFileViewProvider
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiManager import com.intellij.psi.PsiManager
import com.intellij.psi.impl.compiled.ClsFileImpl import com.intellij.psi.impl.compiled.ClsFileImpl
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl
import com.intellij.psi.stubs.StubElement
import com.intellij.util.containers.Stack
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -47,20 +44,12 @@ fun buildLightClass(
generate: (state: GenerationState, files: Collection<KtFile>) -> Unit generate: (state: GenerationState, files: Collection<KtFile>) -> Unit
): LightClassBuilderResult { ): LightClassBuilderResult {
val project = files.first().project val project = files.first().project
val javaFileStub = createJavaFileStub(project, packageFqName, files)
val bindingContext: BindingContext
val state: GenerationState
try { try {
val stubStack = Stack<StubElement<PsiElement>>() val classBuilderFactory = KotlinLightClassBuilderFactory(createJavaFileStub(project, packageFqName, files))
val state = GenerationState(
@Suppress("UNCHECKED_CAST")
stubStack.push(javaFileStub as StubElement<PsiElement>)
state = GenerationState(
project, project,
KotlinLightClassBuilderFactory(stubStack), classBuilderFactory,
context.module, context.module,
context.bindingContext, context.bindingContext,
files.toList(), files.toList(),
@@ -70,17 +59,12 @@ fun buildLightClass(
) )
state.beforeCompile() state.beforeCompile()
bindingContext = state.bindingContext
generate(state, files) generate(state, files)
val pop = stubStack.pop() val javaFileStub = classBuilderFactory.result()
if (pop !== javaFileStub) {
LOG.error("Unbalanced stack operations: " + pop)
}
ServiceManager.getService(project, StubComputationTracker::class.java)?.onStubComputed(javaFileStub, context) ServiceManager.getService(project, StubComputationTracker::class.java)?.onStubComputed(javaFileStub, context)
return LightClassBuilderResult(javaFileStub, bindingContext, state.collectedExtraJvmDiagnostics) return LightClassBuilderResult(javaFileStub, context.bindingContext, state.collectedExtraJvmDiagnostics)
} }
catch (e: ProcessCanceledException) { catch (e: ProcessCanceledException) {
throw e throw e
@@ -50,14 +50,16 @@ public class StubClassBuilder extends AbstractClassBuilder {
} }
}; };
private final StubElement parent; private final StubElement parent;
private final PsiJavaFileStub fileStub;
private StubBuildingVisitor v; private StubBuildingVisitor v;
private final Stack<StubElement> parentStack; private final Stack<StubElement> parentStack;
private boolean isPackageClass = false; private boolean isPackageClass = false;
private int memberIndex = 0; private int memberIndex = 0;
public StubClassBuilder(@NotNull Stack<StubElement> parentStack) { public StubClassBuilder(@NotNull Stack<StubElement> parentStack, @NotNull PsiJavaFileStub fileStub) {
this.parentStack = parentStack; this.parentStack = parentStack;
this.parent = parentStack.peek(); this.parent = parentStack.peek();
this.fileStub = fileStub;
} }
@NotNull @NotNull
@@ -102,7 +104,8 @@ public class StubClassBuilder extends AbstractClassBuilder {
@Nullable @Nullable
private String calculateShortName(@NotNull String internalName) { private String calculateShortName(@NotNull String internalName) {
if (parent instanceof PsiJavaFileStub) { if (parent instanceof PsiJavaFileStub) {
String packagePrefix = getPackageInternalNamePrefix((PsiJavaFileStub) parent); assert parent == fileStub;
String packagePrefix = getPackageInternalNamePrefix();
assert internalName.startsWith(packagePrefix) : internalName + " : " + packagePrefix; assert internalName.startsWith(packagePrefix) : internalName + " : " + packagePrefix;
return internalName.substring(packagePrefix.length()); return internalName.substring(packagePrefix.length());
} }
@@ -118,8 +121,6 @@ public class StubClassBuilder extends AbstractClassBuilder {
@Nullable @Nullable
private String getClassInternalNamePrefix(@NotNull PsiClassStub classStub) { private String getClassInternalNamePrefix(@NotNull PsiClassStub classStub) {
PsiJavaFileStub fileStub = (PsiJavaFileStub) parentStack.get(0);
String packageName = fileStub.getPackageName(); String packageName = fileStub.getPackageName();
String classStubQualifiedName = classStub.getQualifiedName(); String classStubQualifiedName = classStub.getQualifiedName();
@@ -135,7 +136,7 @@ public class StubClassBuilder extends AbstractClassBuilder {
@NotNull @NotNull
private static String getPackageInternalNamePrefix(@NotNull PsiJavaFileStub fileStub) { private String getPackageInternalNamePrefix() {
String packageName = fileStub.getPackageName(); String packageName = fileStub.getPackageName();
if (packageName.isEmpty()) { if (packageName.isEmpty()) {
return ""; return "";