diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java index 5224d6aac84..fbfcd1a7441 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java @@ -113,7 +113,7 @@ public abstract class CodegenContext { while(!(descriptor instanceof NamespaceDescriptor)) { descriptor = descriptor.getContainingDeclaration(); } - return NamespaceCodegen.getJVMClassName(DescriptorUtils.getFQName(descriptor), true); + return NamespaceCodegen.getJVMClassName(DescriptorUtils.getFQName(descriptor).toSafe(), true); } public OwnerKind getContextKind() { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index e762ad6790a..dc553c2cf47 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -318,7 +318,7 @@ public class FunctionCodegen { int flags = ACC_PUBLIC | ACC_SYNTHETIC; // TODO. String ownerInternalName = contextClass instanceof NamespaceDescriptor ? - NamespaceCodegen.getJVMClassName(DescriptorUtils.getFQName(contextClass), true) : + NamespaceCodegen.getJVMClassName(DescriptorUtils.getFQName(contextClass).toSafe(), true) : state.getTypeMapper().mapType(((ClassDescriptor) contextClass).getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(); String descriptor = jvmSignature.getDescriptor().replace(")","I)"); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index a07c12f61db..cb0e114e16c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -114,9 +114,9 @@ public class JetTypeMapper { DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); if (containingDeclaration instanceof JavaNamespaceDescriptor) { JavaNamespaceDescriptor javaNamespaceDescriptor = (JavaNamespaceDescriptor) containingDeclaration; - owner = NamespaceCodegen.getJVMClassName(DescriptorUtils.getFQName(containingDeclaration), javaNamespaceDescriptor.isNamespace()); + owner = NamespaceCodegen.getJVMClassName(DescriptorUtils.getFQName(containingDeclaration).toSafe(), javaNamespaceDescriptor.isNamespace()); } else if (containingDeclaration instanceof NamespaceDescriptor) { - owner = NamespaceCodegen.getJVMClassName(DescriptorUtils.getFQName(containingDeclaration), true); + owner = NamespaceCodegen.getJVMClassName(DescriptorUtils.getFQName(containingDeclaration).toSafe(), true); } else if (containingDeclaration instanceof ClassDescriptor) { ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration; @@ -395,7 +395,7 @@ public class JetTypeMapper { if (functionParent instanceof JavaNamespaceDescriptor) { namespace = ((JavaNamespaceDescriptor) functionParent).isNamespace(); } - owner = NamespaceCodegen.getJVMClassName(DescriptorUtils.getFQName(functionParent), namespace); + owner = NamespaceCodegen.getJVMClassName(DescriptorUtils.getFQName(functionParent).toSafe(), namespace); ownerForDefaultImpl = ownerForDefaultParam = owner; invokeOpcode = INVOKESTATIC; thisClass = null; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaBridgeConfiguration.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaBridgeConfiguration.java index c41515e932c..7e30f64a42d 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaBridgeConfiguration.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaBridgeConfiguration.java @@ -66,7 +66,7 @@ public class JavaBridgeConfiguration implements ModuleConfiguration { @Override public void extendNamespaceScope(@NotNull BindingTrace trace, @NotNull NamespaceDescriptor namespaceDescriptor, @NotNull WritableScope namespaceMemberScope) { - namespaceMemberScope.importScope(new JavaPackageScope(DescriptorUtils.getFQName(namespaceDescriptor), namespaceDescriptor, javaSemanticServices)); + namespaceMemberScope.importScope(new JavaPackageScope(DescriptorUtils.getFQName(namespaceDescriptor).toSafe(), namespaceDescriptor, javaSemanticServices)); delegateConfiguration.extendNamespaceScope(trace, namespaceDescriptor, namespaceMemberScope); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index e18213de8d1..ce144af5d0d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -178,25 +178,28 @@ public class DescriptorUtils { return false; } - public static FqName getFQName(@NotNull DeclarationDescriptor descriptor) { - if (descriptor instanceof ModuleDescriptor || descriptor.getContainingDeclaration() instanceof ModuleDescriptor) { - return FqName.ROOT; + @NotNull + public static FqNameUnsafe getFQName(@NotNull DeclarationDescriptor descriptor) { + DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); + + if (descriptor instanceof ModuleDescriptor || containingDeclaration instanceof ModuleDescriptor) { + return FqName.ROOT.toUnsafe(); } - if (descriptor.getContainingDeclaration() == null) { + if (containingDeclaration == null) { if (descriptor instanceof NamespaceDescriptor) { // TODO: namespace must always have parent if (descriptor.getName().equals("jet")) { - return FqName.topLevel("jet"); + return FqNameUnsafe.topLevel("jet"); } if (descriptor.getName().equals("")) { - return FqName.ROOT; + return FqName.ROOT.toUnsafe(); } } - throw new IllegalStateException("descriptor is not module descriptor and has null containingDeclaration: " + descriptor.getContainingDeclaration()); + throw new IllegalStateException("descriptor is not module descriptor and has null containingDeclaration: " + containingDeclaration); } - return getFQName(descriptor.getContainingDeclaration()).child(descriptor.getName()); + return getFQName(containingDeclaration).child(descriptor.getName()); } public static boolean isTopLevelFunction(@NotNull SimpleFunctionDescriptor functionDescriptor) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FqName.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FqName.java index a4b5c7b002e..284d5452996 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FqName.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FqName.java @@ -18,9 +18,7 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; import java.util.List; /** @@ -31,60 +29,50 @@ public class FqName { public static final FqName ROOT = new FqName(""); @NotNull - private final String fqName; + private final FqNameUnsafe fqName; // cache private transient FqName parent; - private transient String shortName; public FqName(@NotNull String fqName) { + this.fqName = new FqNameUnsafe(fqName, this); + } + + public FqName(@NotNull FqNameUnsafe fqName) { this.fqName = fqName; validateFqName(); } - private FqName(@NotNull String fqName, FqName parent, String shortName) { + private FqName(@NotNull FqNameUnsafe fqName, FqName parent) { this.fqName = fqName; this.parent = parent; - this.shortName = shortName; validateFqName(); } private void validateFqName() { - if (fqName.length() == 0) { - return; - } - - // TODO: prohibit < everywhere - if (fqName.indexOf('/') >= 0 || fqName.charAt(0) == '<') { + if (fqName.getFqName().indexOf('<') >= 0) { throw new IllegalArgumentException("incorrect fq name: " + fqName); } } - private void compute() { - int lastDot = fqName.lastIndexOf('.'); - if (lastDot >= 0) { - shortName = fqName.substring(lastDot + 1); - parent = new FqName(fqName.substring(0, lastDot)); - } else { - shortName = fqName; - parent = ROOT; - } - } - - - @NotNull public String getFqName() { + return fqName.getFqName(); + } + + @NotNull + public FqNameUnsafe toUnsafe() { return fqName; } public boolean isRoot() { - return fqName.equals(""); + return fqName.isRoot(); } + @NotNull public FqName parent() { if (parent != null) { @@ -95,49 +83,30 @@ public class FqName { throw new IllegalStateException("root"); } - compute(); + parent = new FqName(fqName.parent()); return parent; } @NotNull public FqName child(@NotNull String name) { - String childFqName; - if (isRoot()) { - childFqName = name; - } else { - childFqName = fqName + "." + name; - } - return new FqName(childFqName, this, name); + return new FqName(fqName.child(name), this); } @NotNull public String shortName() { - if (shortName != null) { - return shortName; - } - - if (isRoot()) { - throw new IllegalStateException("root"); - } - - compute(); - - return shortName; - } - - private interface WalkCallback { - void segment(@NotNull String shortName, @NotNull FqName fqName); + return fqName.shortName(); } @NotNull public List path() { final List path = Lists.newArrayList(); path.add(ROOT); - walk(new WalkCallback() { + fqName.walk(new FqNameUnsafe.WalkCallback() { @Override - public void segment(@NotNull String shortName, @NotNull FqName fqName) { - path.add(fqName); + public void segment(@NotNull String shortName, @NotNull FqNameUnsafe fqName) { + // TODO: do not validate + path.add(new FqName(fqName)); } }); return path; @@ -145,75 +114,19 @@ public class FqName { @NotNull public List pathSegments() { - final List path = Lists.newArrayList(); - walk(new WalkCallback() { - @Override - public void segment(@NotNull String shortName, @NotNull FqName fqName) { - path.add(shortName); - } - }); - return path; + return fqName.pathSegments(); } - private void walk(@NotNull WalkCallback callback) { - if (isRoot()) { - return; - } - - int pos = fqName.indexOf('.'); - - if (pos < 0) { - if (this.parent == null) { - this.parent = ROOT; - } - if (this.shortName == null) { - this.shortName = fqName; - } - callback.segment(fqName, this); - return; - } - - String firstSegment = fqName.substring(0, pos); - FqName last = new FqName(firstSegment, ROOT, firstSegment); - callback.segment(firstSegment, last); - - for (;;) { - int next = fqName.indexOf('.', pos + 1); - if (next < 0) { - if (this.parent == null) { - this.parent = last; - } - String shortName = fqName.substring(pos + 1); - if (this.shortName == null) { - this.shortName = shortName; - } - callback.segment(shortName, this); - return; - } - - String shortName = fqName.substring(pos + 1, next); - last = new FqName(fqName.substring(0, next), last, shortName); - callback.segment(shortName, last); - - pos = next; - } - } - - - @NotNull public static FqName topLevel(@NotNull String shortName) { - if (shortName.indexOf('.') >= 0) { - throw new IllegalArgumentException(); - } - return new FqName(shortName, ROOT, shortName); + return new FqName(FqNameUnsafe.topLevel(shortName)); } @Override public String toString() { - return isRoot() ? "" : fqName; + return fqName.toString(); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FqNameUnsafe.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FqNameUnsafe.java new file mode 100644 index 00000000000..e674572b788 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FqNameUnsafe.java @@ -0,0 +1,247 @@ +/* + * Copyright 2010-2012 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.jet.lang.resolve; + +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * Like {@link FqName} but allows '<' and '>' characters in name. + * + * @author Stepan Koltsov + */ +public class FqNameUnsafe { + + @NotNull + private final String fqName; + + // cache + private transient FqName safe; + private transient FqNameUnsafe parent; + private transient String shortName; + + FqNameUnsafe(@NotNull String fqName, @NotNull FqName safe) { + this.fqName = fqName; + this.safe = safe; + + validateFqName(); + } + + public FqNameUnsafe(@NotNull String fqName) { + this.fqName = fqName; + + validateFqName(); + } + + private FqNameUnsafe(@NotNull String fqName, FqNameUnsafe parent, String shortName) { + this.fqName = fqName; + this.parent = parent; + this.shortName = shortName; + + validateFqName(); + } + + + private void validateFqName() { + if (fqName.indexOf('/') >= 0) { + throw new IllegalArgumentException("incorrect fq name: " + fqName); + } + } + + private void compute() { + int lastDot = fqName.lastIndexOf('.'); + if (lastDot >= 0) { + shortName = fqName.substring(lastDot + 1); + parent = new FqNameUnsafe(fqName.substring(0, lastDot)); + } else { + shortName = fqName; + parent = FqName.ROOT.toUnsafe(); + } + } + + + + @NotNull + public String getFqName() { + return fqName; + } + + @NotNull + public FqName toSafe() { + if (safe != null) { + return safe; + } + safe = new FqName(this); + return safe; + } + + public boolean isRoot() { + return fqName.equals(""); + } + + @NotNull + public FqNameUnsafe parent() { + if (parent != null) { + return parent; + } + + if (isRoot()) { + throw new IllegalStateException("root"); + } + + compute(); + + return parent; + } + + @NotNull + public FqNameUnsafe child(@NotNull String name) { + String childFqName; + if (isRoot()) { + childFqName = name; + } else { + childFqName = fqName + "." + name; + } + return new FqNameUnsafe(childFqName, this, name); + } + + @NotNull + public String shortName() { + if (shortName != null) { + return shortName; + } + + if (isRoot()) { + throw new IllegalStateException("root"); + } + + compute(); + + return shortName; + } + + interface WalkCallback { + void segment(@NotNull String shortName, @NotNull FqNameUnsafe fqName); + } + + @NotNull + public List path() { + final List path = Lists.newArrayList(); + path.add(FqName.ROOT.toUnsafe()); + walk(new WalkCallback() { + @Override + public void segment(@NotNull String shortName, @NotNull FqNameUnsafe fqName) { + path.add(fqName); + } + }); + return path; + } + + @NotNull + public List pathSegments() { + final List path = Lists.newArrayList(); + walk(new WalkCallback() { + @Override + public void segment(@NotNull String shortName, @NotNull FqNameUnsafe fqName) { + path.add(shortName); + } + }); + return path; + } + + + void walk(@NotNull WalkCallback callback) { + if (isRoot()) { + return; + } + + int pos = fqName.indexOf('.'); + + if (pos < 0) { + if (this.parent == null) { + this.parent = FqName.ROOT.toUnsafe(); + } + if (this.shortName == null) { + this.shortName = fqName; + } + callback.segment(fqName, this); + return; + } + + String firstSegment = fqName.substring(0, pos); + FqNameUnsafe last = new FqNameUnsafe(firstSegment, FqName.ROOT.toUnsafe(), firstSegment); + callback.segment(firstSegment, last); + + for (;;) { + int next = fqName.indexOf('.', pos + 1); + if (next < 0) { + if (this.parent == null) { + this.parent = last; + } + String shortName = fqName.substring(pos + 1); + if (this.shortName == null) { + this.shortName = shortName; + } + callback.segment(shortName, this); + return; + } + + String shortName = fqName.substring(pos + 1, next); + last = new FqNameUnsafe(fqName.substring(0, next), last, shortName); + callback.segment(shortName, last); + + pos = next; + } + } + + + + @NotNull + public static FqNameUnsafe topLevel(@NotNull String shortName) { + if (shortName.indexOf('.') >= 0) { + throw new IllegalArgumentException(); + } + return new FqNameUnsafe(shortName, FqName.ROOT.toUnsafe(), shortName); + } + + + @Override + public String toString() { + return isRoot() ? "" : fqName; + } + + @Override + public boolean equals(Object o) { + // generated by Idea + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + FqNameUnsafe that = (FqNameUnsafe) o; + + if (fqName != null ? !fqName.equals(that.fqName) : that.fqName != null) return false; + + return true; + } + + @Override + public int hashCode() { + // generated by Idea + return fqName != null ? fqName.hashCode() : 0; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/NamespaceFactoryImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/NamespaceFactoryImpl.java index 7547a960979..4682a5838c2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/NamespaceFactoryImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/NamespaceFactoryImpl.java @@ -119,7 +119,7 @@ public class NamespaceFactoryImpl implements NamespaceFactory { namespaceDescriptor = ((ModuleDescriptor) owner).getRootNs(); } else { - FqName ownerFqName = DescriptorUtils.getFQName(owner); + FqName ownerFqName = DescriptorUtils.getFQName(owner).toSafe(); fqName = ownerFqName.child(name); namespaceDescriptor = ((NamespaceDescriptorImpl) owner).getNamespace(name); } diff --git a/compiler/tests/org/jetbrains/jet/FqNameTest.java b/compiler/tests/org/jetbrains/jet/FqNameTest.java index 5cb2b766d07..bfb77782aaf 100644 --- a/compiler/tests/org/jetbrains/jet/FqNameTest.java +++ b/compiler/tests/org/jetbrains/jet/FqNameTest.java @@ -18,6 +18,7 @@ package org.jetbrains.jet; import com.google.common.collect.Lists; import org.jetbrains.jet.lang.resolve.FqName; +import org.jetbrains.jet.lang.resolve.FqNameUnsafe; import org.junit.Assert; import org.junit.Test; @@ -85,4 +86,15 @@ public class FqNameTest { } } + @Test + public void safeUnsafe() { + FqName fqName = new FqName("com.yandex"); + Assert.assertSame(fqName, fqName.toUnsafe().toSafe()); + } + + @Test + public void unsafeSafe() { + FqNameUnsafe fqName = new FqNameUnsafe("ru.yandex"); + Assert.assertSame(fqName, fqName.toSafe().toUnsafe()); + } } diff --git a/idea/src/org/jetbrains/jet/plugin/JetPluginUtil.java b/idea/src/org/jetbrains/jet/plugin/JetPluginUtil.java index 27bb98a892f..37c647ee4ff 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetPluginUtil.java +++ b/idea/src/org/jetbrains/jet/plugin/JetPluginUtil.java @@ -40,7 +40,7 @@ public class JetPluginUtil { @NotNull public static FqName computeTypeFullName(@NotNull JetType type) { ClassDescriptor clazz = (ClassDescriptor) type.getConstructor().getDeclarationDescriptor(); - return DescriptorUtils.getFQName(clazz); + return DescriptorUtils.getFQName(clazz).toSafe(); } @NotNull diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java index e9498fb272d..5e78526d427 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java @@ -134,7 +134,7 @@ public class JetFunctionInsertHandler implements InsertHandler { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { - final FqName fqn = DescriptorUtils.getFQName(functionDescriptor); + final FqName fqn = DescriptorUtils.getFQName(functionDescriptor).toSafe(); ImportClassHelper.addImportDirective(fqn.getFqName(), file); } }); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java index b9b96f7accc..e4c69793f5d 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java @@ -101,7 +101,7 @@ public class ImportClassAndFunFix extends JetHintAction @Override public FqName apply(@Nullable DeclarationDescriptor declarationDescriptor) { assert declarationDescriptor != null; - return DescriptorUtils.getFQName(declarationDescriptor); + return DescriptorUtils.getFQName(declarationDescriptor).toSafe(); } }); } @@ -126,7 +126,7 @@ public class ImportClassAndFunFix extends JetHintAction @Override public FqName apply(@Nullable DeclarationDescriptor declarationDescriptor) { assert declarationDescriptor != null; - return DescriptorUtils.getFQName(declarationDescriptor); + return DescriptorUtils.getFQName(declarationDescriptor).toSafe(); } }); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java index 11c75706b81..2e8dd70b492 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java @@ -22,7 +22,7 @@ import com.google.dart.compiler.backend.js.ast.JsScope; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.resolve.FqName; +import org.jetbrains.jet.lang.resolve.FqNameUnsafe; import java.util.Map; @@ -39,13 +39,13 @@ public final class StandardClasses { private final class Builder { @Nullable - private /*var*/ FqName currentFQName = null; + private /*var*/ FqNameUnsafe currentFQName = null; @Nullable private /*var*/ String currentObjectName = null; @NotNull public Builder forFQ(@NotNull String classFQName) { - currentFQName = new FqName(classFQName); + currentFQName = new FqNameUnsafe(classFQName); return this; } @@ -119,46 +119,46 @@ public final class StandardClasses { @NotNull - private final Map standardObjects = Maps.newHashMap(); + private final Map standardObjects = Maps.newHashMap(); @NotNull - private final Map scopeMap = Maps.newHashMap(); + private final Map scopeMap = Maps.newHashMap(); private StandardClasses(@NotNull JsScope kotlinScope) { this.kotlinScope = kotlinScope; } - private void declareTopLevelObjectInScope(@NotNull JsScope scope, @NotNull Map map, - @NotNull FqName fullQualifiedName, @NotNull String name) { + private void declareTopLevelObjectInScope(@NotNull JsScope scope, @NotNull Map map, + @NotNull FqNameUnsafe fullQualifiedName, @NotNull String name) { JsName declaredName = scope.declareName(name); declaredName.setObfuscatable(false); map.put(fullQualifiedName, declaredName); scopeMap.put(fullQualifiedName, new JsScope(scope, "scope for " + name)); } - private void declareKotlinObject(@NotNull FqName fullQualifiedName, @NotNull String kotlinLibName) { + private void declareKotlinObject(@NotNull FqNameUnsafe fullQualifiedName, @NotNull String kotlinLibName) { declareTopLevelObjectInScope(kotlinScope, standardObjects, fullQualifiedName, kotlinLibName); } - private void declareInner(@NotNull FqName fullQualifiedClassName, + private void declareInner(@NotNull FqNameUnsafe fullQualifiedClassName, @NotNull String shortMethodName, @NotNull String javascriptName) { JsScope classScope = scopeMap.get(fullQualifiedClassName); assert classScope != null; - FqName fullQualifiedMethodName = new FqName(fullQualifiedClassName + "." + shortMethodName); + FqNameUnsafe fullQualifiedMethodName = fullQualifiedClassName.child(shortMethodName); JsName declaredName = classScope.declareName(javascriptName); declaredName.setObfuscatable(false); standardObjects.put(fullQualifiedMethodName, declaredName); } - private void declareMethods(@NotNull FqName classFQName, + private void declareMethods(@NotNull FqNameUnsafe classFQName, @NotNull String... methodNames) { for (String methodName : methodNames) { declareInner(classFQName, methodName, methodName); } } - private void declareReadonlyProperties(@NotNull FqName classFQName, + private void declareReadonlyProperties(@NotNull FqNameUnsafe classFQName, @NotNull String... propertyNames) { for (String propertyName : propertyNames) { declareInner(classFQName, propertyName, propertyName);