From 65f1efb921efca8471dfa429bea5caede88f8691 Mon Sep 17 00:00:00 2001 From: "Natalia.Ukhorskaya" Date: Fri, 11 Jan 2013 15:39:46 +0400 Subject: [PATCH] Add JetPackageClass annotation --- .../jet/codegen/NamespaceCodegen.java | 5 +++ .../resolve/java/DescriptorResolverUtils.java | 3 +- .../jet/lang/resolve/java/JvmStdlibNames.java | 4 +- .../lang/resolve/java/PackageClassUtils.java | 17 +------ .../java/kt/JetPackageClassAnnotation.java | 42 ++++++++++++++++++ .../resolve/java/wrapper/PsiClassWrapper.java | 16 ++++--- .../jetbrains/jet/PackageClassNameTest.java | 34 -------------- .../caches/JetFromJavaDescriptorHelper.java | 40 ++++++++++------- .../importOptimizer/JetImportOptimizer.java | 8 ++-- .../libraries/DecompiledDataFactory.java | 11 ++--- .../basic/TopLevelNonImportedExtFun.jar | Bin 1205 -> 1659 bytes .../basic/TopLevelNonImportedFun.jar | Bin 1205 -> 1659 bytes .../jet/runtime/typeinfo/JetPackageClass.java | 27 +++++++++++ 13 files changed, 124 insertions(+), 83 deletions(-) create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetPackageClassAnnotation.java create mode 100644 runtime/src/jet/runtime/typeinfo/JetPackageClass.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index 7817692fa32..8c6c0fa013e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.java.JvmClassName; +import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; import org.jetbrains.jet.lang.resolve.java.PackageClassUtils; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; @@ -84,6 +85,10 @@ public class NamespaceCodegen extends MemberCodegen { public void generate(CompilationErrorHandler errorHandler) { boolean multiFile = CodegenBinding.isMultiFileNamespace(state.getBindingContext(), name); + if (shouldGenerateNSClass(files)) { + v.getClassBuilder().newAnnotation(JvmStdlibNames.JET_PACKAGE_CLASS.getDescriptor(), true); + } + for (JetFile file : files) { VirtualFile vFile = file.getVirtualFile(); try { diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorResolverUtils.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorResolverUtils.java index 8ebbbe2b096..cf191a33a0f 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorResolverUtils.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorResolverUtils.java @@ -46,7 +46,8 @@ public final class DescriptorResolverUtils { } public static boolean isKotlinClass(@NotNull PsiClass psiClass) { - return new PsiClassWrapper(psiClass).getJetClass().isDefined() || PackageClassUtils.isPackageClass(psiClass); + PsiClassWrapper wrapper = new PsiClassWrapper(psiClass); + return wrapper.getJetClass().isDefined() || wrapper.getJetPackageClass().isDefined(); } public static boolean isInnerEnum(@NotNull PsiClass innerClass, @Nullable DeclarationDescriptor owner) { diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmStdlibNames.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmStdlibNames.java index 69b6f759c47..5f3f6ccecfe 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmStdlibNames.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmStdlibNames.java @@ -68,7 +68,9 @@ public class JvmStdlibNames { public static final JvmClassName JET_CLASS = JvmClassName.byFqNameWithoutInnerClasses("jet.runtime.typeinfo.JetClass"); - + + public static final JvmClassName JET_PACKAGE_CLASS = JvmClassName.byFqNameWithoutInnerClasses("jet.runtime.typeinfo.JetPackageClass"); + public static final String JET_CLASS_SIGNATURE = "signature"; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PackageClassUtils.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PackageClassUtils.java index e309401fc78..b36656abe81 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PackageClassUtils.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PackageClassUtils.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve.java; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiClass; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.resolve.java.kt.JetPackageClassAnnotation; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; @@ -38,21 +39,7 @@ public class PackageClassUtils { return packageFQN.child(Name.identifier(getPackageClassName(packageFQN))); } - public static boolean isPackageClass(@NotNull FqName fqName) { - if (fqName.isRoot()) { - return true; - } - return getPackageClassName(fqName.parent()).equals(fqName.shortName().getName()); - } - public static boolean isPackageClass(@NotNull PsiClass psiClass) { - String qualifiedName = psiClass.getQualifiedName(); - if (qualifiedName == null) { - return false; - } - if (DEFAULT_PACKAGE.equals(qualifiedName)) { - return true; - } - return getPackageClassName(new FqName(qualifiedName).parent()).equals(psiClass.getName()); + return JetPackageClassAnnotation.get(psiClass).isDefined(); } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetPackageClassAnnotation.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetPackageClassAnnotation.java new file mode 100644 index 00000000000..48845354bb8 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetPackageClassAnnotation.java @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2013 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.java.kt; + +import com.intellij.psi.PsiAnnotation; +import com.intellij.psi.PsiClass; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; +import org.jetbrains.jet.lang.resolve.java.resolver.JavaAnnotationResolver; + +public class JetPackageClassAnnotation extends PsiAnnotationWithFlags { + private static final JetPackageClassAnnotation NULL_ANNOTATION = new JetPackageClassAnnotation(null); + static { + NULL_ANNOTATION.checkInitialized(); + } + + private JetPackageClassAnnotation(@Nullable PsiAnnotation psiAnnotation) { + super(psiAnnotation); + } + + @NotNull + public static JetPackageClassAnnotation get(PsiClass psiClass) { + final PsiAnnotation annotation = JavaAnnotationResolver.findOwnAnnotation(psiClass, + JvmStdlibNames.JET_PACKAGE_CLASS.getFqName().getFqName()); + return annotation != null ? new JetPackageClassAnnotation(annotation) : NULL_ANNOTATION; + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/wrapper/PsiClassWrapper.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/wrapper/PsiClassWrapper.java index e9f3bcce786..b639da28f30 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/wrapper/PsiClassWrapper.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/wrapper/PsiClassWrapper.java @@ -17,13 +17,9 @@ package org.jetbrains.jet.lang.resolve.java.wrapper; import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiField; -import com.intellij.psi.PsiMethod; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.resolve.java.kt.JetClassAnnotation; - -import java.util.ArrayList; -import java.util.List; +import org.jetbrains.jet.lang.resolve.java.kt.JetPackageClassAnnotation; public class PsiClassWrapper { @@ -44,6 +40,8 @@ public class PsiClassWrapper { } private JetClassAnnotation jetClass; + private JetPackageClassAnnotation jetPackageClass; + @NotNull public JetClassAnnotation getJetClass() { if (jetClass == null) { @@ -51,4 +49,12 @@ public class PsiClassWrapper { } return jetClass; } + + @NotNull + public JetPackageClassAnnotation getJetPackageClass() { + if (jetPackageClass == null) { + jetPackageClass = JetPackageClassAnnotation.get(psiClass); + } + return jetPackageClass; + } } diff --git a/compiler/tests/org/jetbrains/jet/PackageClassNameTest.java b/compiler/tests/org/jetbrains/jet/PackageClassNameTest.java index a5d003f02b7..cd12a36f0e2 100644 --- a/compiler/tests/org/jetbrains/jet/PackageClassNameTest.java +++ b/compiler/tests/org/jetbrains/jet/PackageClassNameTest.java @@ -57,36 +57,6 @@ public class PackageClassNameTest { doTest(FqName.ROOT.child(Name.identifier("kotlin")), "KotlinPackage", "_DefaultPackage"); } - @Test - public void testIsPackageClass1() { - doTestIsPackageClass("", true); - } - - @Test - public void testIsPackageClass2() { - doTestIsPackageClass("kotlin", false); - } - - @Test - public void testIsPackageClass3() { - doTestIsPackageClass("kotlin.KotlinPackage", true); - } - - @Test - public void testIsPackageClass4() { - doTestIsPackageClass("kotlin.test.SomeClass", false); - } - - @Test - public void testIsPackageClass5() { - doTestIsPackageClass("kotlin.io.IoPackage", true); - } - - @Test - public void testInnerIsPackage() { - doTestIsPackageClass("kotlin.io.IoPackage$Foo", false); - } - private void doTest(@NotNull String name, @NotNull String expectedForChild, @Nullable String expectedForParent) { doTest(new FqName(name), expectedForChild, expectedForParent); } @@ -97,8 +67,4 @@ public class PackageClassNameTest { assertEquals("Wrong result for parent [" + name + "].", expectedForParent, getPackageClassName(name.parent())); } } - - private void doTestIsPackageClass(String testedName, boolean expected) { - assertEquals("Wrong result for [" + testedName + "].", expected, isPackageClass(new FqName(testedName))); - } } diff --git a/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java b/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java index 51b94df8eea..b7365c8263f 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java @@ -23,9 +23,9 @@ import com.intellij.psi.*; import com.intellij.psi.impl.java.stubs.index.JavaAnnotationIndex; import com.intellij.psi.impl.java.stubs.index.JavaMethodNameIndex; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.PsiShortNamesCache; import com.intellij.psi.util.PsiTreeUtil; import jet.runtime.typeinfo.JetClass; +import jet.runtime.typeinfo.JetPackageClass; import jet.runtime.typeinfo.JetValueParameter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -53,12 +53,12 @@ class JetFromJavaDescriptorHelper { /** * Get java equivalents for jet top level classes. */ - static PsiClass[] getClassesForJetNamespaces(Project project, GlobalSearchScope scope) { + static Collection getClassesForJetNamespaces(Project project, GlobalSearchScope scope) { /* Will iterate through short name caches Kotlin namespaces from jar a class files will be collected from java cache Kotlin namespaces classes from sources will be collected with JetShortNamesCache.getClassesByName */ - // TODO Collect all package classes - return PsiShortNamesCache.getInstance(project).getClassesByName("namespace", scope); + + return getClassesByAnnotation(JetPackageClass.class.getSimpleName(), project, scope); } /** @@ -81,16 +81,11 @@ class JetFromJavaDescriptorHelper { static Collection getCompiledClassesForTopLevelObjects(Project project, GlobalSearchScope scope) { Set jetObjectClasses = Sets.newHashSet(); - Collection annotations = JavaAnnotationIndex.getInstance().get(JetClass.class.getSimpleName(), project, scope); - for (PsiAnnotation annotation : annotations) { - PsiModifierList modifierList = (PsiModifierList) annotation.getParent(); - final PsiElement owner = modifierList.getParent(); - if (owner instanceof PsiClass) { - PsiClass psiClass = (PsiClass) owner; - JetClassAnnotation jetAnnotation = JetClassAnnotation.get(psiClass); - if (psiClass.getContainingClass() == null && jetAnnotation.kind() == JvmStdlibNames.FLAG_CLASS_KIND_OBJECT) { - jetObjectClasses.add(psiClass); - } + Collection classesByAnnotation = getClassesByAnnotation(JetClass.class.getSimpleName(), project, scope); + for (PsiClass psiClass : classesByAnnotation) { + JetClassAnnotation jetAnnotation = JetClassAnnotation.get(psiClass); + if (psiClass.getContainingClass() == null && jetAnnotation.kind() == JvmStdlibNames.FLAG_CLASS_KIND_OBJECT) { + jetObjectClasses.add(psiClass); } } @@ -161,7 +156,7 @@ class JetFromJavaDescriptorHelper { FqName classFQN = new FqName(qualifiedName); - if (PackageClassUtils.isPackageClass(classFQN)) { + if (PackageClassUtils.isPackageClass(containingClass)) { FqName classParentFQN = QualifiedNamesUtil.withoutLastSegment(classFQN); return QualifiedNamesUtil.combine(classParentFQN, Name.identifier(method.getName())); } @@ -196,4 +191,19 @@ class JetFromJavaDescriptorHelper { return selectedMethods; } + + private static Collection getClassesByAnnotation( + String annotationName, Project project, GlobalSearchScope scope + ) { + Collection classes = Sets.newHashSet(); + Collection annotations = JavaAnnotationIndex.getInstance().get(annotationName, project, scope); + for (PsiAnnotation annotation : annotations) { + PsiModifierList modifierList = (PsiModifierList) annotation.getParent(); + final PsiElement owner = modifierList.getParent(); + if (owner instanceof PsiClass) { + classes.add((PsiClass) owner); + } + } + return classes; + } } diff --git a/idea/src/org/jetbrains/jet/plugin/editor/importOptimizer/JetImportOptimizer.java b/idea/src/org/jetbrains/jet/plugin/editor/importOptimizer/JetImportOptimizer.java index 6d713428da7..8b0d3a7d5a4 100644 --- a/idea/src/org/jetbrains/jet/plugin/editor/importOptimizer/JetImportOptimizer.java +++ b/idea/src/org/jetbrains/jet/plugin/editor/importOptimizer/JetImportOptimizer.java @@ -230,7 +230,7 @@ public class JetImportOptimizer implements ImportOptimizer { return null; } - return combineClassFqNameWithMemberName(classFQN, field.getName()); + return combineClassFqNameWithMemberName(field.getContainingClass(), classFQN, field.getName()); } // TODO: Still problem with kotlin global properties imported from class files @@ -245,7 +245,7 @@ public class JetImportOptimizer implements ImportOptimizer { return classFQN; } - return combineClassFqNameWithMemberName(classFQN, method.getName()); + return combineClassFqNameWithMemberName(method.getContainingClass(), classFQN, method.getName()); } if (element instanceof PsiPackage) { @@ -256,11 +256,11 @@ public class JetImportOptimizer implements ImportOptimizer { } @Nullable - private static FqName combineClassFqNameWithMemberName(FqName classFQN, String memberName) { + private static FqName combineClassFqNameWithMemberName(PsiClass containingClass, FqName classFQN, String memberName) { if (memberName == null) { return null; } - if (PackageClassUtils.isPackageClass(classFQN)) { + if (PackageClassUtils.isPackageClass(containingClass)) { return QualifiedNamesUtil.combine(classFQN.parent(), Name.identifier(memberName)); } else { diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java index e9adfa0ee94..230785f75de 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java @@ -25,6 +25,7 @@ import com.intellij.psi.impl.compiled.ClsFileImpl; import com.intellij.psi.util.PsiTreeUtil; import jet.runtime.typeinfo.JetClass; import jet.runtime.typeinfo.JetMethod; +import jet.runtime.typeinfo.JetPackageClass; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.di.InjectorForJavaSemanticServices; import org.jetbrains.jet.lang.descriptors.*; @@ -43,6 +44,7 @@ import java.util.*; public class DecompiledDataFactory { private static final String JET_CLASS = JetClass.class.getName(); + private static final String JET_PACKAGE_CLASS = JetPackageClass.class.getName(); private static final String JET_METHOD = JetMethod.class.getName(); private static final String DECOMPILED_COMMENT = "/* compiled code */"; private static final DescriptorRenderer DESCRIPTOR_RENDERER = @@ -233,14 +235,7 @@ public class DecompiledDataFactory { } public static boolean isKotlinNamespaceClass(@NotNull PsiClass psiClass) { - if (PackageClassUtils.isPackageClass(psiClass) && !isKotlinClass(psiClass)) { - for (PsiMethod method : psiClass.getMethods()) { - if (hasAnnotation(method, JET_METHOD)) { - return true; - } - } - } - return false; + return hasAnnotation(psiClass, JET_PACKAGE_CLASS); } public static boolean isCompiledFromKotlin(@NotNull PsiClass psiClass) { diff --git a/idea/testData/completion/basic/TopLevelNonImportedExtFun.jar b/idea/testData/completion/basic/TopLevelNonImportedExtFun.jar index ea3886e9efb31c04581767c10caa7175a459b714..87a2f061f6d127594bf189d6f22f9c7a2092f293 100644 GIT binary patch literal 1659 zcmWIWW@h1H0D+lR+D>2wlwe_CVMt6$*8g{kfgu2>N`!#}2+>uE09AujIVL3sBqnDk zrl;y9=Oh*v_fGK5zw98;c7NmDWxn2--qHr~YXw$a;uc%FeV&ZF$I7l13qCd8J~p$> zH&%MB`P3hgF_s^ge*}gemv`h+I^Y#|{@kAT#+!eC{`Q-n!TpAM&Wc2#mcvhCRKv5* z=n5njFUkvez6HD64HN4ZewMv`{-=kH_w-+v!B zN-7W7`fX8-iok#8yEfNa<(A2$MdnStS{Wv=?ffT~r5lZ+JYO!l!=e9-cfZ@5;%)ZN zf+v57o@>OxXEWt=bH7;FlRqwg-vji2h5em3tzYd?sOEO|h{IKiLh{l(__rIqnfhpE z;|HH_U#%K*-{`p5On)pz>q`r*$zr=-UrK1(!(rxPf(cP`xdig(&{ZorruA3l`*wn2XCrOUD=-_3tGd}RE<4GO-=Np`9a zfu1)21|cGNrlDmeP@onk7iAWd=w+7_ubt|hf7^iP`1^k%P5yV4!`d0GMQ$W!m?vm& z6VQ}MFGke5*q*q93ZWdbqy(4OMF#j3Z6R+Y- ztW(o9Hcn$%`|H7_`U~?Dcz10(yZV)HsZD+Dnrx@Hcek2pE4V#e#iqr-Eb>jwohOM` zUp}Z-+n?1u)8Wia4_%gsq;AKwm(nWyTR;Cbnp!U=_AvHs+M!e~!F-q72NWkqGoN#3 zmdnjLRpax{dDX5;DckJyiG0lb0i74^yDWX1*6%IZtMOWcx6fnt^ixO5R%mU}`ewBE zm-}P?nVy|1<(IwF_@}yV`GR(Z;~#Ao+jV6BznaPZgI98+!y~bR^=Btve*A8F3U6iT z^xMmV?k91 literal 1205 zcmWIWW@h1H0DN`!#}2+>su166}mJA z{1kU+$;-d5zFBUlv|tH;8x!s1_+_u#;*ZS_u57P8^sI3H+H|&wSIytt{2hJmqU#&k zjek#m(|RW>uuRXXbf!g8q?!ot?Z(b?E*=W?E;(kicRvbzzvRTP)gJM!%>UN*e96Aa zamzPayl>j#vlHeDZn~QFR&d#VX}*a28z+AFF=LyPa^&v2_oj=zp1W}C?XGI3m2*>` z?ei-!f8r)`G%QlqopWK447=8ssTaM1(qB6LFpKKCNl zqIXX3owvVxgWZ>TA2zl%&@WMKHigdCxfXweQz48_SsnFS?!*(Jqmr+Vk# zHsCq_{+~#b|6S#eT4hgR7WfNUY1NU%;?yfy`^>fn2_J@(ZZhiAs z&TsWf-y%1a+g<0WpDf?;c|4n{KKe~vp8r);dE-AOrhAU1SJx;NGD}~O*FAL9BX#f5 z47J6qmswZ2ow5zgE`8OwlR5IO>*nCHKA~*S3#<6`T-Vwklq$)c9e#E8tBQZWBCfaG z+Wr34ng)s1)lw^LW~6QWTsXNsRQ+(jPvKQIIsw(Kt(rLCTC*+CJ{$i&5fJI5oJ0Fayw$^VQ@A`FNU068gvN&o~<12VCc2Ow)< k27po=vXdZ=ff?}~=ukxZ3-D%T1IaK0;d&tbff>XD0NW2wlwe_CVMt6$*8g{kfgu2>N`!#}2+>uE09AujIVL3sBqnDk zrl;y9=Oh*v_fGK5zw98;c7NmDWxn2--qHr~YXw$a;uc%FeV&ZF$I7l13qCd8J~p$> zH&%MB`P3hgF_s^ge*}gemv`h+I^Y#|{@kAT#+!eC{`Q-n!TpAM&Wc2#mcvhCRKv5* z=n5njFUkvez6HD64HN4ZewMv`{-=kH_w-+v!B zN-7W7`fX8-iok#8yEfNa<(A2$MdnStS{Wv=?ffT~r5lZ+JYO!l!=e9-cfZ@5;%)ZN zf+v57o@>OxXEWt=bH7;FlRqwg-vji2h5em3tzYd?sOEO|h{IKiLh{l(__rIqnfhpE z;|HH_U#%K*-{`p5On)pz>q`r*$zr=-UrK1(!(rxPf(cP`xdig(&{ZorruA3l`*wn2XCrOUD=-_3tGd}RE<4GO-=Np`9a zfu1)21|cGNrlDmeP@onk7iAWd=w+7_ubt|hf7^iP`1^k%P5yV4!`d0GMQ$W!m?vm& z6VQ}MFGke5*q*q93ZWdbqy(4OMF#j3Z6R+Y- ztW(o9Hcn$%`|H7_`U~?Dcz10(yZV)HsZD+Dnrx@Hcek2pE4V#e#iqr-Eb>jwohOM` zUp}Z-+n?1u)8Wia4_%gsq;AKwm(nWyTR;Cbnp!U=_AvHs+M!e~!F-q72NWkqGoN#3 zmdnjLRpax{dDX5;DckJyiG0lb0i74^yDWX1*6%IZtMOWcx6fnt^ixO5R%mU}`ewBE zm-}P?nVy|1<(IwF_@}yV`GR(Z;~#Ao+jV6BznaPZgI98+!y~bR^=Btve*A8F3U6iT z^xMmV?k91 literal 1205 zcmWIWW@h1H0DN`!#}2+>su166}mJA z{1kU+$;-d5zFBUlv|tH;8x!s1_+_u#;*ZS_u57P8^sI3H+H|&wSIytt{2hJmqU#&k zjek#m(|RW>uuRXXbf!g8q?!ot?Z(b?E*=W?E;(kicRvbzzvRTP)gJM!%>UN*e96Aa zamzPayl>j#vlHeDZn~QFR&d#VX}*a28z+AFF=LyPa^&v2_oj=zp1W}C?XGI3m2*>` z?ei-!f8r)`G%QlqopWK447=8ssTaM1(qB6LFpKKCNl zqIXX3owvVxgWZ>TA2zl%&@WMKHigdCxfXweQz48_SsnFS?!*(Jqmr+Vk# zHsCq_{+~#b|6S#eT4hgR7WfNUY1NU%;?yfy`^>fn2_J@(ZZhiAs z&TsWf-y%1a+g<0WpDf?;c|4n{KKe~vp8r);dE-AOrhAU1SJx;NGD}~O*FAL9BX#f5 z47J6qmswZ2ow5zgE`8OwlR5IO>*nCHKA~*S3#<6`T-Vwklq$)c9e#E8tBQZWBCfaG z+Wr34ng)s1)lw^LW~6QWTsXNsRQ+(jPvKQIIsw(Kt(rLCTC*+CJ{$i&5fJI5oJ0Fayw$^VQ@A`FNU068gvN&o~<12VCc2Ow)< k27po=vXdZ=ff?}~=ukxZ3-D%T1IaK0;d&tbff>XD0NW