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);
|
(DeserializedSimpleFunctionDescriptor) functionDescriptor);
|
||||||
|
|
||||||
VirtualFile file = InlineCodegenUtil.getVirtualFileForCallable(containerClassId, state);
|
VirtualFile file = InlineCodegenUtil.getVirtualFileForCallable(containerClassId, state);
|
||||||
if (functionDescriptor.getContainingDeclaration() instanceof PackageFragmentDescriptor) {
|
//if (functionDescriptor.getContainingDeclaration() instanceof PackageFragmentDescriptor) {
|
||||||
/*use facade class*/
|
// /*use facade class*/
|
||||||
containerClassId = PackageClassUtils.getPackageClassId(containerClassId.getPackageFqName());
|
// containerClassId = PackageClassUtils.getPackageClassId(containerClassId.getPackageFqName());
|
||||||
}
|
//}
|
||||||
nodeAndSMAP = InlineCodegenUtil.getMethodNode(file.contentsToByteArray(),
|
nodeAndSMAP = InlineCodegenUtil.getMethodNode(file.contentsToByteArray(),
|
||||||
asmMethod.getName(),
|
asmMethod.getName(),
|
||||||
asmMethod.getDescriptor(),
|
asmMethod.getDescriptor(),
|
||||||
@@ -226,7 +226,7 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
|
|
||||||
SMAP smap;
|
SMAP smap;
|
||||||
if (callDefault) {
|
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,
|
FakeMemberCodegen parentCodegen = new FakeMemberCodegen(codegen.getParentCodegen(), inliningFunction,
|
||||||
(FieldOwnerContext) methodContext.getParentContext(),
|
(FieldOwnerContext) methodContext.getParentContext(),
|
||||||
ownerType.getInternalName());
|
ownerType.getInternalName());
|
||||||
@@ -337,7 +337,8 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
FakeMemberCodegen parentCodegen =
|
FakeMemberCodegen parentCodegen =
|
||||||
new FakeMemberCodegen(codegen.getParentCodegen(), expression,
|
new FakeMemberCodegen(codegen.getParentCodegen(), expression,
|
||||||
(FieldOwnerContext) context.getParentContext(),
|
(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 =
|
FunctionGenerationStrategy strategy =
|
||||||
expression instanceof JetCallableReferenceExpression ?
|
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)
|
val optimizationClassBuilderFactory = OptimizationClassBuilderFactory(builderFactory, disableOptimization)
|
||||||
var interceptedBuilderFactory: ClassBuilderFactory = BuilderFactoryForDuplicateSignatureDiagnostics(
|
var interceptedBuilderFactory: ClassBuilderFactory = BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||||
optimizationClassBuilderFactory, this.bindingContext, diagnostics)
|
optimizationClassBuilderFactory, this.bindingContext, diagnostics)
|
||||||
|
|
||||||
|
interceptedBuilderFactory = BuilderFactoryForDuplicateClassNameDiagnostics(interceptedBuilderFactory, diagnostics);
|
||||||
|
|
||||||
val interceptExtensions = ClassBuilderInterceptorExtension.getInstances(project)
|
val interceptExtensions = ClassBuilderInterceptorExtension.getInstances(project)
|
||||||
|
|
||||||
for (extension in interceptExtensions) {
|
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.Condition;
|
||||||
import com.intellij.openapi.util.io.FileUtil;
|
import com.intellij.openapi.util.io.FileUtil;
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.util.PathUtil;
|
import com.intellij.util.PathUtil;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
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.descriptors.PackageFragmentDescriptor;
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.psi.JetDeclaration;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.psi.JetFile;
|
|
||||||
import org.jetbrains.kotlin.psi.JetNamedFunction;
|
|
||||||
import org.jetbrains.kotlin.psi.JetProperty;
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
||||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf;
|
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf;
|
||||||
@@ -50,18 +50,35 @@ public class PackagePartClassUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@TestOnly
|
||||||
public static FqName getPackagePartFqName(@NotNull FqName facadeFqName, @NotNull VirtualFile file) {
|
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()));
|
String fileName = FileUtil.getNameWithoutExtension(PathUtil.getFileName(file.getName()));
|
||||||
|
|
||||||
// path hashCode to prevent same name / different path collision
|
if (!fileName.isEmpty()) {
|
||||||
String srcName = String.format(
|
char c = fileName.charAt(0);
|
||||||
"%s$%s$%08x",
|
//!Character.isUpperCase also handles non-latin characters
|
||||||
facadeFqName.shortName().asString(),
|
if ('a' <= c && c <= 'z') {
|
||||||
replaceSpecialSymbols(fileName),
|
fileName = Character.toUpperCase(fileName.charAt(0)) + fileName.substring(1);
|
||||||
getPathHashCode(file)
|
}
|
||||||
);
|
}
|
||||||
|
|
||||||
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
|
@NotNull
|
||||||
@@ -77,7 +94,7 @@ public class PackagePartClassUtils {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static FqName getPackagePartFqName(@NotNull JetFile file) {
|
public static FqName getPackagePartFqName(@NotNull JetFile file) {
|
||||||
return getPackagePartFqName(getPackageClassFqName(file.getPackageFqName()), file.getVirtualFile());
|
return getPackagePartFqName(getPackageClassFqName(file.getPackageFqName()), file.getVirtualFile(), file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
+3
@@ -81,8 +81,11 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
|||||||
"Please use the more clear ''::class.java'' syntax to avoid confusion",
|
"Please use the more clear ''::class.java'' syntax to avoid confusion",
|
||||||
Renderers.RENDER_TYPE, Renderers.RENDER_TYPE
|
Renderers.RENDER_TYPE, Renderers.RENDER_TYPE
|
||||||
);
|
);
|
||||||
|
|
||||||
MAP.put(ErrorsJvm.JAVA_TYPE_MISMATCH,
|
MAP.put(ErrorsJvm.JAVA_TYPE_MISMATCH,
|
||||||
"Java type mismatch expected {1} but found {0}. Use explicit cast", Renderers.RENDER_TYPE, Renderers.RENDER_TYPE);
|
"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
|
@NotNull
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ public interface ErrorsJvm {
|
|||||||
DiagnosticFactory2<JetElement, JetType, JetType> JAVA_CLASS_ON_COMPANION = DiagnosticFactory2.create(WARNING);
|
DiagnosticFactory2<JetElement, JetType, JetType> JAVA_CLASS_ON_COMPANION = DiagnosticFactory2.create(WARNING);
|
||||||
DiagnosticFactory2<JetExpression, JetType, JetType> JAVA_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR);
|
DiagnosticFactory2<JetExpression, JetType, JetType> JAVA_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR);
|
||||||
|
|
||||||
|
DiagnosticFactory1<PsiElement, String> DUPLICATE_CLASS_NAMES = DiagnosticFactory1.create(ERROR);
|
||||||
|
|
||||||
enum NullabilityInformationSource {
|
enum NullabilityInformationSource {
|
||||||
KOTLIN {
|
KOTLIN {
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ import static org.jetbrains.kotlin.codegen.CodegenTestUtil.*;
|
|||||||
import static org.jetbrains.kotlin.load.kotlin.PackageClassUtils.getPackageClassFqName;
|
import static org.jetbrains.kotlin.load.kotlin.PackageClassUtils.getPackageClassFqName;
|
||||||
|
|
||||||
public abstract class CodegenTestCase extends UsefulTestCase {
|
public abstract class CodegenTestCase extends UsefulTestCase {
|
||||||
|
|
||||||
|
public static final String DEFAULT_TEST_FILE_NAME = "a_test";
|
||||||
|
|
||||||
protected KotlinCoreEnvironment myEnvironment;
|
protected KotlinCoreEnvironment myEnvironment;
|
||||||
protected CodegenTestFiles myFiles;
|
protected CodegenTestFiles myFiles;
|
||||||
protected ClassFileFactory classFileFactory;
|
protected ClassFileFactory classFileFactory;
|
||||||
@@ -81,7 +84,7 @@ public abstract class CodegenTestCase extends UsefulTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void loadText(@NotNull String text) {
|
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
|
@NotNull
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.codegen;
|
|||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Collections2;
|
import com.google.common.collect.Collections2;
|
||||||
|
import kotlin.KotlinPackage;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.backend.common.output.OutputFile;
|
import org.jetbrains.kotlin.backend.common.output.OutputFile;
|
||||||
import org.jetbrains.kotlin.load.java.AbiVersionUtil;
|
import org.jetbrains.kotlin.load.java.AbiVersionUtil;
|
||||||
@@ -50,7 +51,7 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
|
|||||||
public void testPackagePart() {
|
public void testPackagePart() {
|
||||||
doTestKotlinSyntheticClass(
|
doTestKotlinSyntheticClass(
|
||||||
"fun foo() = 42",
|
"fun foo() = 42",
|
||||||
"$",
|
KotlinPackage.capitalize(DEFAULT_TEST_FILE_NAME),
|
||||||
PACKAGE_PART
|
PACKAGE_PART
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user