New package part naming
This commit is contained in:
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.codegen
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ConflictingJvmDeclarationsData
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.MemberKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.RawSignature
|
||||
import org.jetbrains.org.objectweb.asm.FieldVisitor
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
|
||||
public abstract class ClassNameCollectionClassBuilderFactory(
|
||||
private val delegate: ClassBuilderFactory
|
||||
|
||||
) : ClassBuilderFactory by delegate {
|
||||
|
||||
protected abstract fun handleClashingNames(internalName: String, origin: JvmDeclarationOrigin)
|
||||
|
||||
override fun newClassBuilder(origin: JvmDeclarationOrigin): ClassNameCollectionClassBuilder {
|
||||
return ClassNameCollectionClassBuilder(origin, delegate.newClassBuilder(origin))
|
||||
}
|
||||
|
||||
public override fun asBytes(builder: ClassBuilder?): ByteArray? {
|
||||
return delegate.asBytes((builder as ClassNameCollectionClassBuilder)._delegate)
|
||||
}
|
||||
|
||||
public override fun asText(builder: ClassBuilder?): String? {
|
||||
return delegate.asText((builder as ClassNameCollectionClassBuilder)._delegate)
|
||||
}
|
||||
|
||||
public override fun close() {
|
||||
delegate.close()
|
||||
}
|
||||
|
||||
private inner class ClassNameCollectionClassBuilder(
|
||||
private val classCreatedFor: JvmDeclarationOrigin,
|
||||
internal val _delegate: ClassBuilder
|
||||
) : DelegatingClassBuilder() {
|
||||
|
||||
override fun getDelegate() = _delegate
|
||||
|
||||
private var classInternalName: String? = null
|
||||
|
||||
override fun defineClass(origin: PsiElement?, version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<out String>) {
|
||||
classInternalName = name
|
||||
super.defineClass(origin, version, access, name, signature, superName, interfaces)
|
||||
}
|
||||
|
||||
override fun done() {
|
||||
if (classInternalName != null) {
|
||||
handleClashingNames(classInternalName!!, classCreatedFor)
|
||||
}
|
||||
super.done()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -192,10 +192,10 @@ public class InlineCodegen extends CallGenerator {
|
||||
(DeserializedSimpleFunctionDescriptor) functionDescriptor);
|
||||
|
||||
VirtualFile file = InlineCodegenUtil.getVirtualFileForCallable(containerClassId, state);
|
||||
if (functionDescriptor.getContainingDeclaration() instanceof PackageFragmentDescriptor) {
|
||||
/*use facade class*/
|
||||
containerClassId = PackageClassUtils.getPackageClassId(containerClassId.getPackageFqName());
|
||||
}
|
||||
//if (functionDescriptor.getContainingDeclaration() instanceof PackageFragmentDescriptor) {
|
||||
// /*use facade class*/
|
||||
// containerClassId = PackageClassUtils.getPackageClassId(containerClassId.getPackageFqName());
|
||||
//}
|
||||
nodeAndSMAP = InlineCodegenUtil.getMethodNode(file.contentsToByteArray(),
|
||||
asmMethod.getName(),
|
||||
asmMethod.getDescriptor(),
|
||||
@@ -226,7 +226,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
SMAP smap;
|
||||
if (callDefault) {
|
||||
Type ownerType = typeMapper.mapOwner(functionDescriptor, false/*use facade class*/);
|
||||
Type ownerType = typeMapper.mapOwner(functionDescriptor, true/*TODO: false, migration*/);
|
||||
FakeMemberCodegen parentCodegen = new FakeMemberCodegen(codegen.getParentCodegen(), inliningFunction,
|
||||
(FieldOwnerContext) methodContext.getParentContext(),
|
||||
ownerType.getInternalName());
|
||||
@@ -337,7 +337,8 @@ public class InlineCodegen extends CallGenerator {
|
||||
FakeMemberCodegen parentCodegen =
|
||||
new FakeMemberCodegen(codegen.getParentCodegen(), expression,
|
||||
(FieldOwnerContext) context.getParentContext(),
|
||||
isLambda ? codegen.getParentCodegen().getClassName() : typeMapper.mapOwner(descriptor, false).getInternalName());
|
||||
isLambda ? codegen.getParentCodegen().getClassName()
|
||||
: typeMapper.mapOwner(descriptor, true /*TODO: false, migration*/).getInternalName());
|
||||
|
||||
FunctionGenerationStrategy strategy =
|
||||
expression instanceof JetCallableReferenceExpression ?
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.codegen.state
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilderFactory
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilderMode
|
||||
import org.jetbrains.kotlin.codegen.ClassNameCollectionClassBuilderFactory
|
||||
import org.jetbrains.kotlin.codegen.SignatureCollectingClassBuilderFactory
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamAdapterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.*
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.util.*
|
||||
|
||||
|
||||
class BuilderFactoryForDuplicateClassNameDiagnostics(
|
||||
builderFactory: ClassBuilderFactory,
|
||||
private val diagnostics: DiagnosticSink
|
||||
) : ClassNameCollectionClassBuilderFactory(builderFactory) {
|
||||
|
||||
private val className = hashMapOf<String, JvmDeclarationOrigin> ()
|
||||
|
||||
override fun handleClashingNames(internalName: String, origin: JvmDeclarationOrigin) {
|
||||
val another = className.getOrPut(internalName, { origin })
|
||||
if (origin.element != another.element) {
|
||||
if (origin.originKind == JvmDeclarationOriginKind.PACKAGE_FACADE || another.originKind == JvmDeclarationOriginKind.PACKAGE_FACADE) {
|
||||
if (origin.originKind == JvmDeclarationOriginKind.PACKAGE_FACADE) {
|
||||
reportError(another, internalName)
|
||||
} else {
|
||||
reportError(another, internalName)
|
||||
}
|
||||
} else {
|
||||
if (origin.element != null) {
|
||||
reportError(origin, internalName)
|
||||
}
|
||||
if (another.element != null) {
|
||||
reportError(another, internalName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportError(another: JvmDeclarationOrigin, internalName: String) {
|
||||
diagnostics.report(ErrorsJvm.DUPLICATE_CLASS_NAMES.on(another.element, internalName))
|
||||
}
|
||||
}
|
||||
@@ -102,6 +102,9 @@ public class GenerationState jvmOverloads constructor(
|
||||
val optimizationClassBuilderFactory = OptimizationClassBuilderFactory(builderFactory, disableOptimization)
|
||||
var interceptedBuilderFactory: ClassBuilderFactory = BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
optimizationClassBuilderFactory, this.bindingContext, diagnostics)
|
||||
|
||||
interceptedBuilderFactory = BuilderFactoryForDuplicateClassNameDiagnostics(interceptedBuilderFactory, diagnostics);
|
||||
|
||||
val interceptExtensions = ClassBuilderInterceptorExtension.getInstances(project)
|
||||
|
||||
for (extension in interceptExtensions) {
|
||||
|
||||
+30
-13
@@ -19,16 +19,16 @@ package org.jetbrains.kotlin.load.kotlin;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.JetDeclaration;
|
||||
import org.jetbrains.kotlin.psi.JetFile;
|
||||
import org.jetbrains.kotlin.psi.JetNamedFunction;
|
||||
import org.jetbrains.kotlin.psi.JetProperty;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf;
|
||||
@@ -50,18 +50,35 @@ public class PackagePartClassUtils {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@TestOnly
|
||||
public static FqName getPackagePartFqName(@NotNull FqName facadeFqName, @NotNull VirtualFile file) {
|
||||
return getPackagePartFqName(facadeFqName, file, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static FqName getPackagePartFqName(@NotNull FqName facadeFqName, @NotNull VirtualFile file, @Nullable JetFile jetFile) {
|
||||
String fileName = FileUtil.getNameWithoutExtension(PathUtil.getFileName(file.getName()));
|
||||
|
||||
// path hashCode to prevent same name / different path collision
|
||||
String srcName = String.format(
|
||||
"%s$%s$%08x",
|
||||
facadeFqName.shortName().asString(),
|
||||
replaceSpecialSymbols(fileName),
|
||||
getPathHashCode(file)
|
||||
);
|
||||
if (!fileName.isEmpty()) {
|
||||
char c = fileName.charAt(0);
|
||||
//!Character.isUpperCase also handles non-latin characters
|
||||
if ('a' <= c && c <= 'z') {
|
||||
fileName = Character.toUpperCase(fileName.charAt(0)) + fileName.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
return facadeFqName.parent().child(Name.identifier(srcName));
|
||||
if (jetFile != null) {
|
||||
for (PsiElement child : jetFile.getDeclarations()) {
|
||||
if (child instanceof JetClassOrObject) {
|
||||
if (fileName.equalsIgnoreCase(((JetClassOrObject) child).getName())) {
|
||||
fileName += "_";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return facadeFqName.parent().child(Name.identifier(replaceSpecialSymbols(fileName)));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -77,7 +94,7 @@ public class PackagePartClassUtils {
|
||||
|
||||
@NotNull
|
||||
public static FqName getPackagePartFqName(@NotNull JetFile file) {
|
||||
return getPackagePartFqName(getPackageClassFqName(file.getPackageFqName()), file.getVirtualFile());
|
||||
return getPackagePartFqName(getPackageClassFqName(file.getPackageFqName()), file.getVirtualFile(), file);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+3
@@ -81,8 +81,11 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
"Please use the more clear ''::class.java'' syntax to avoid confusion",
|
||||
Renderers.RENDER_TYPE, Renderers.RENDER_TYPE
|
||||
);
|
||||
|
||||
MAP.put(ErrorsJvm.JAVA_TYPE_MISMATCH,
|
||||
"Java type mismatch expected {1} but found {0}. Use explicit cast", Renderers.RENDER_TYPE, Renderers.RENDER_TYPE);
|
||||
|
||||
MAP.put(ErrorsJvm.DUPLICATE_CLASS_NAMES, "Class names ''{0}'' conflict with package name (facade or part)", Renderers.TO_STRING);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -69,6 +69,8 @@ public interface ErrorsJvm {
|
||||
DiagnosticFactory2<JetElement, JetType, JetType> JAVA_CLASS_ON_COMPANION = DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory2<JetExpression, JetType, JetType> JAVA_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR);
|
||||
|
||||
DiagnosticFactory1<PsiElement, String> DUPLICATE_CLASS_NAMES = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
enum NullabilityInformationSource {
|
||||
KOTLIN {
|
||||
@NotNull
|
||||
|
||||
@@ -53,6 +53,9 @@ import static org.jetbrains.kotlin.codegen.CodegenTestUtil.*;
|
||||
import static org.jetbrains.kotlin.load.kotlin.PackageClassUtils.getPackageClassFqName;
|
||||
|
||||
public abstract class CodegenTestCase extends UsefulTestCase {
|
||||
|
||||
public static final String DEFAULT_TEST_FILE_NAME = "a_test";
|
||||
|
||||
protected KotlinCoreEnvironment myEnvironment;
|
||||
protected CodegenTestFiles myFiles;
|
||||
protected ClassFileFactory classFileFactory;
|
||||
@@ -81,7 +84,7 @@ public abstract class CodegenTestCase extends UsefulTestCase {
|
||||
}
|
||||
|
||||
protected void loadText(@NotNull String text) {
|
||||
myFiles = CodegenTestFiles.create("a.kt", text, myEnvironment.getProject());
|
||||
myFiles = CodegenTestFiles.create(DEFAULT_TEST_FILE_NAME + ".kt", text, myEnvironment.getProject());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Collections2;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFile;
|
||||
import org.jetbrains.kotlin.load.java.AbiVersionUtil;
|
||||
@@ -50,7 +51,7 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
|
||||
public void testPackagePart() {
|
||||
doTestKotlinSyntheticClass(
|
||||
"fun foo() = 42",
|
||||
"$",
|
||||
KotlinPackage.capitalize(DEFAULT_TEST_FILE_NAME),
|
||||
PACKAGE_PART
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user