001 /*
002 * Copyright 2010-2015 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.kotlin.serialization;
018
019 import com.google.protobuf.MessageLite;
020 import kotlin.CollectionsKt;
021 import kotlin.jvm.functions.Function1;
022 import org.jetbrains.annotations.NotNull;
023 import org.jetbrains.annotations.Nullable;
024 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
025 import org.jetbrains.kotlin.descriptors.*;
026 import org.jetbrains.kotlin.descriptors.annotations.Annotated;
027 import org.jetbrains.kotlin.name.Name;
028 import org.jetbrains.kotlin.resolve.DescriptorUtils;
029 import org.jetbrains.kotlin.resolve.MemberComparator;
030 import org.jetbrains.kotlin.resolve.constants.ConstantValue;
031 import org.jetbrains.kotlin.resolve.constants.NullValue;
032 import org.jetbrains.kotlin.types.*;
033 import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
034 import org.jetbrains.kotlin.utils.Interner;
035
036 import java.io.ByteArrayOutputStream;
037 import java.io.IOException;
038 import java.util.ArrayList;
039 import java.util.Collection;
040 import java.util.Collections;
041 import java.util.List;
042
043 import static org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry;
044
045 public class DescriptorSerializer {
046 private final DeclarationDescriptor containingDeclaration;
047 private final Interner<TypeParameterDescriptor> typeParameters;
048 private final SerializerExtension extension;
049 private final MutableTypeTable typeTable;
050 private final boolean serializeTypeTableToFunction;
051
052 private DescriptorSerializer(
053 @Nullable DeclarationDescriptor containingDeclaration,
054 @NotNull Interner<TypeParameterDescriptor> typeParameters,
055 @NotNull SerializerExtension extension,
056 @NotNull MutableTypeTable typeTable,
057 boolean serializeTypeTableToFunction
058 ) {
059 this.containingDeclaration = containingDeclaration;
060 this.typeParameters = typeParameters;
061 this.extension = extension;
062 this.typeTable = typeTable;
063 this.serializeTypeTableToFunction = serializeTypeTableToFunction;
064 }
065
066 @NotNull
067 public byte[] serialize(@NotNull MessageLite message) {
068 try {
069 ByteArrayOutputStream result = new ByteArrayOutputStream();
070 getStringTable().serializeTo(result);
071 message.writeTo(result);
072 return result.toByteArray();
073 }
074 catch (IOException e) {
075 throw ExceptionUtilsKt.rethrow(e);
076 }
077 }
078
079 @NotNull
080 public static DescriptorSerializer createTopLevel(@NotNull SerializerExtension extension) {
081 return new DescriptorSerializer(null, new Interner<TypeParameterDescriptor>(), extension, new MutableTypeTable(), false);
082 }
083
084 @NotNull
085 public static DescriptorSerializer createForLambda(@NotNull SerializerExtension extension) {
086 return new DescriptorSerializer(null, new Interner<TypeParameterDescriptor>(), extension, new MutableTypeTable(), true);
087 }
088
089 @NotNull
090 public static DescriptorSerializer create(@NotNull ClassDescriptor descriptor, @NotNull SerializerExtension extension) {
091 DeclarationDescriptor container = descriptor.getContainingDeclaration();
092 DescriptorSerializer parentSerializer =
093 container instanceof ClassDescriptor
094 ? create((ClassDescriptor) container, extension)
095 : createTopLevel(extension);
096
097 // Calculate type parameter ids for the outer class beforehand, as it would've had happened if we were always
098 // serializing outer classes before nested classes.
099 // Otherwise our interner can get wrong ids because we may serialize classes in any order.
100 DescriptorSerializer serializer = new DescriptorSerializer(
101 descriptor,
102 new Interner<TypeParameterDescriptor>(parentSerializer.typeParameters),
103 parentSerializer.extension,
104 new MutableTypeTable(),
105 false
106 );
107 for (TypeParameterDescriptor typeParameter : descriptor.getDeclaredTypeParameters()) {
108 serializer.typeParameters.intern(typeParameter);
109 }
110 return serializer;
111 }
112
113 @NotNull
114 private DescriptorSerializer createChildSerializer(@NotNull CallableDescriptor callable) {
115 return new DescriptorSerializer(callable, new Interner<TypeParameterDescriptor>(typeParameters), extension, typeTable, false);
116 }
117
118 @NotNull
119 public StringTable getStringTable() {
120 return extension.getStringTable();
121 }
122
123 private boolean useTypeTable() {
124 return extension.shouldUseTypeTable();
125 }
126
127 @NotNull
128 public ProtoBuf.Class.Builder classProto(@NotNull ClassDescriptor classDescriptor) {
129 ProtoBuf.Class.Builder builder = ProtoBuf.Class.newBuilder();
130
131 int flags = Flags.getClassFlags(hasAnnotations(classDescriptor), classDescriptor.getVisibility(), classDescriptor.getModality(),
132 classDescriptor.getKind(), classDescriptor.isInner(), classDescriptor.isCompanionObject(),
133 classDescriptor.isData());
134 if (flags != builder.getFlags()) {
135 builder.setFlags(flags);
136 }
137
138 builder.setFqName(getClassId(classDescriptor));
139
140 for (TypeParameterDescriptor typeParameterDescriptor : classDescriptor.getDeclaredTypeParameters()) {
141 builder.addTypeParameter(typeParameter(typeParameterDescriptor));
142 }
143
144 if (!KotlinBuiltIns.isSpecialClassWithNoSupertypes(classDescriptor)) {
145 // Special classes (Any, Nothing) have no supertypes
146 for (KotlinType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
147 if (useTypeTable()) {
148 builder.addSupertypeId(typeId(supertype));
149 }
150 else {
151 builder.addSupertype(type(supertype));
152 }
153 }
154 }
155
156 for (ConstructorDescriptor descriptor : classDescriptor.getConstructors()) {
157 builder.addConstructor(constructorProto(descriptor));
158 }
159
160 for (DeclarationDescriptor descriptor : sort(DescriptorUtils.getAllDescriptors(classDescriptor.getDefaultType().getMemberScope()))) {
161 if (descriptor instanceof CallableMemberDescriptor) {
162 CallableMemberDescriptor member = (CallableMemberDescriptor) descriptor;
163 if (member.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) continue;
164
165 if (descriptor instanceof PropertyDescriptor) {
166 builder.addProperty(propertyProto((PropertyDescriptor) descriptor));
167 }
168 else if (descriptor instanceof FunctionDescriptor) {
169 builder.addFunction(functionProto((FunctionDescriptor) descriptor));
170 }
171 }
172 }
173
174 for (DeclarationDescriptor descriptor : sort(DescriptorUtils.getAllDescriptors(classDescriptor.getUnsubstitutedInnerClassesScope()))) {
175 int name = getSimpleNameIndex(descriptor.getName());
176 if (isEnumEntry(descriptor)) {
177 builder.addEnumEntryName(name);
178 builder.addEnumEntry(enumEntryProto((ClassDescriptor) descriptor));
179 }
180 else {
181 builder.addNestedClassName(name);
182 }
183 }
184
185 ClassDescriptor companionObjectDescriptor = classDescriptor.getCompanionObjectDescriptor();
186 if (companionObjectDescriptor != null) {
187 builder.setCompanionObjectName(getSimpleNameIndex(companionObjectDescriptor.getName()));
188 }
189
190 ProtoBuf.TypeTable typeTableProto = typeTable.serialize();
191 if (typeTableProto != null) {
192 builder.setTypeTable(typeTableProto);
193 }
194
195 extension.serializeClass(classDescriptor, builder);
196
197 return builder;
198 }
199
200 @NotNull
201 public ProtoBuf.Property.Builder propertyProto(@NotNull PropertyDescriptor descriptor) {
202 ProtoBuf.Property.Builder builder = ProtoBuf.Property.newBuilder();
203
204 DescriptorSerializer local = createChildSerializer(descriptor);
205
206 boolean hasGetter = false;
207 boolean hasSetter = false;
208 boolean lateInit = descriptor.isLateInit();
209 boolean isConst = descriptor.isConst();
210
211 ConstantValue<?> compileTimeConstant = descriptor.getCompileTimeInitializer();
212 boolean hasConstant = !(compileTimeConstant == null || compileTimeConstant instanceof NullValue);
213
214 boolean hasAnnotations = !descriptor.getAnnotations().getAllAnnotations().isEmpty();
215
216 int propertyFlags = Flags.getAccessorFlags(
217 hasAnnotations,
218 descriptor.getVisibility(),
219 descriptor.getModality(),
220 false,
221 false
222 );
223
224 PropertyGetterDescriptor getter = descriptor.getGetter();
225 if (getter != null) {
226 hasGetter = true;
227 int accessorFlags = getAccessorFlags(getter);
228 if (accessorFlags != propertyFlags) {
229 builder.setGetterFlags(accessorFlags);
230 }
231 }
232
233 PropertySetterDescriptor setter = descriptor.getSetter();
234 if (setter != null) {
235 hasSetter = true;
236 int accessorFlags = getAccessorFlags(setter);
237 if (accessorFlags != propertyFlags) {
238 builder.setSetterFlags(accessorFlags);
239 }
240
241 if (!setter.isDefault()) {
242 DescriptorSerializer setterLocal = local.createChildSerializer(setter);
243 for (ValueParameterDescriptor valueParameterDescriptor : setter.getValueParameters()) {
244 builder.setSetterValueParameter(setterLocal.valueParameter(valueParameterDescriptor));
245 }
246 }
247 }
248
249 int flags = Flags.getPropertyFlags(
250 hasAnnotations, descriptor.getVisibility(), descriptor.getModality(), descriptor.getKind(), descriptor.isVar(),
251 hasGetter, hasSetter, hasConstant, isConst, lateInit
252 );
253 if (flags != builder.getFlags()) {
254 builder.setFlags(flags);
255 }
256
257 builder.setName(getSimpleNameIndex(descriptor.getName()));
258
259 if (useTypeTable()) {
260 builder.setReturnTypeId(local.typeId(descriptor.getType()));
261 }
262 else {
263 builder.setReturnType(local.type(descriptor.getType()));
264 }
265
266 for (TypeParameterDescriptor typeParameterDescriptor : descriptor.getTypeParameters()) {
267 builder.addTypeParameter(local.typeParameter(typeParameterDescriptor));
268 }
269
270 ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter();
271 if (receiverParameter != null) {
272 if (useTypeTable()) {
273 builder.setReceiverTypeId(local.typeId(receiverParameter.getType()));
274 }
275 else {
276 builder.setReceiverType(local.type(receiverParameter.getType()));
277 }
278 }
279
280 extension.serializeProperty(descriptor, builder);
281
282 return builder;
283 }
284
285 @NotNull
286 public ProtoBuf.Function.Builder functionProto(@NotNull FunctionDescriptor descriptor) {
287 ProtoBuf.Function.Builder builder = ProtoBuf.Function.newBuilder();
288
289 DescriptorSerializer local = createChildSerializer(descriptor);
290
291 int flags = Flags.getFunctionFlags(
292 hasAnnotations(descriptor), descriptor.getVisibility(), descriptor.getModality(), descriptor.getKind(),
293 descriptor.isOperator(), descriptor.isInfix(), descriptor.isInline(), descriptor.isTailrec(),
294 descriptor.isExternal()
295 );
296 if (flags != builder.getFlags()) {
297 builder.setFlags(flags);
298 }
299
300 builder.setName(getSimpleNameIndex(descriptor.getName()));
301
302 if (useTypeTable()) {
303 //noinspection ConstantConditions
304 builder.setReturnTypeId(local.typeId(descriptor.getReturnType()));
305 }
306 else {
307 //noinspection ConstantConditions
308 builder.setReturnType(local.type(descriptor.getReturnType()));
309 }
310
311 for (TypeParameterDescriptor typeParameterDescriptor : descriptor.getTypeParameters()) {
312 builder.addTypeParameter(local.typeParameter(typeParameterDescriptor));
313 }
314
315 ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter();
316 if (receiverParameter != null) {
317 if (useTypeTable()) {
318 builder.setReceiverTypeId(local.typeId(receiverParameter.getType()));
319 }
320 else {
321 builder.setReceiverType(local.type(receiverParameter.getType()));
322 }
323 }
324
325 for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getValueParameters()) {
326 builder.addValueParameter(local.valueParameter(valueParameterDescriptor));
327 }
328
329 if (serializeTypeTableToFunction) {
330 ProtoBuf.TypeTable typeTableProto = typeTable.serialize();
331 if (typeTableProto != null) {
332 builder.setTypeTable(typeTableProto);
333 }
334 }
335
336 extension.serializeFunction(descriptor, builder);
337
338 return builder;
339 }
340
341 @NotNull
342 public ProtoBuf.Constructor.Builder constructorProto(@NotNull ConstructorDescriptor descriptor) {
343 ProtoBuf.Constructor.Builder builder = ProtoBuf.Constructor.newBuilder();
344
345 DescriptorSerializer local = createChildSerializer(descriptor);
346
347 int flags = Flags.getConstructorFlags(hasAnnotations(descriptor), descriptor.getVisibility(), !descriptor.isPrimary());
348 if (flags != builder.getFlags()) {
349 builder.setFlags(flags);
350 }
351
352 for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getValueParameters()) {
353 builder.addValueParameter(local.valueParameter(valueParameterDescriptor));
354 }
355
356 extension.serializeConstructor(descriptor, builder);
357
358 return builder;
359 }
360
361 @NotNull
362 public ProtoBuf.EnumEntry.Builder enumEntryProto(@NotNull ClassDescriptor descriptor) {
363 ProtoBuf.EnumEntry.Builder builder = ProtoBuf.EnumEntry.newBuilder();
364 builder.setName(getSimpleNameIndex(descriptor.getName()));
365 extension.serializeEnumEntry(descriptor, builder);
366 return builder;
367 }
368
369 private static int getAccessorFlags(@NotNull PropertyAccessorDescriptor accessor) {
370 return Flags.getAccessorFlags(
371 hasAnnotations(accessor),
372 accessor.getVisibility(),
373 accessor.getModality(),
374 !accessor.isDefault(),
375 accessor.isExternal()
376 );
377 }
378
379 @NotNull
380 private ProtoBuf.ValueParameter.Builder valueParameter(@NotNull ValueParameterDescriptor descriptor) {
381 ProtoBuf.ValueParameter.Builder builder = ProtoBuf.ValueParameter.newBuilder();
382
383 int flags = Flags.getValueParameterFlags(hasAnnotations(descriptor), descriptor.declaresDefaultValue(),
384 descriptor.isCrossinline(), descriptor.isNoinline());
385 if (flags != builder.getFlags()) {
386 builder.setFlags(flags);
387 }
388
389 builder.setName(getSimpleNameIndex(descriptor.getName()));
390
391 if (useTypeTable()) {
392 builder.setTypeId(typeId(descriptor.getType()));
393 }
394 else {
395 builder.setType(type(descriptor.getType()));
396 }
397
398 KotlinType varargElementType = descriptor.getVarargElementType();
399 if (varargElementType != null) {
400 if (useTypeTable()) {
401 builder.setVarargElementTypeId(typeId(varargElementType));
402 }
403 else {
404 builder.setVarargElementType(type(varargElementType));
405 }
406 }
407
408 extension.serializeValueParameter(descriptor, builder);
409
410 return builder;
411 }
412
413 private ProtoBuf.TypeParameter.Builder typeParameter(TypeParameterDescriptor typeParameter) {
414 ProtoBuf.TypeParameter.Builder builder = ProtoBuf.TypeParameter.newBuilder();
415
416 builder.setId(getTypeParameterId(typeParameter));
417
418 builder.setName(getSimpleNameIndex(typeParameter.getName()));
419
420 if (typeParameter.isReified() != builder.getReified()) {
421 builder.setReified(typeParameter.isReified());
422 }
423
424 ProtoBuf.TypeParameter.Variance variance = variance(typeParameter.getVariance());
425 if (variance != builder.getVariance()) {
426 builder.setVariance(variance);
427 }
428 extension.serializeTypeParameter(typeParameter, builder);
429
430 List<KotlinType> upperBounds = typeParameter.getUpperBounds();
431 if (upperBounds.size() == 1 && KotlinBuiltIns.isDefaultBound(CollectionsKt.single(upperBounds))) return builder;
432
433 for (KotlinType upperBound : upperBounds) {
434 if (useTypeTable()) {
435 builder.addUpperBoundId(typeId(upperBound));
436 }
437 else {
438 builder.addUpperBound(type(upperBound));
439 }
440 }
441
442 return builder;
443 }
444
445 private static ProtoBuf.TypeParameter.Variance variance(Variance variance) {
446 switch (variance) {
447 case INVARIANT:
448 return ProtoBuf.TypeParameter.Variance.INV;
449 case IN_VARIANCE:
450 return ProtoBuf.TypeParameter.Variance.IN;
451 case OUT_VARIANCE:
452 return ProtoBuf.TypeParameter.Variance.OUT;
453 }
454 throw new IllegalStateException("Unknown variance: " + variance);
455 }
456
457 private int typeId(@NotNull KotlinType type) {
458 return typeTable.get(type(type));
459 }
460
461 @NotNull
462 private ProtoBuf.Type.Builder type(@NotNull KotlinType type) {
463 assert !type.isError() : "Can't serialize error types: " + type; // TODO
464
465 if (FlexibleTypesKt.isFlexible(type)) {
466 Flexibility flexibility = FlexibleTypesKt.flexibility(type);
467
468 ProtoBuf.Type.Builder lowerBound = type(flexibility.getLowerBound());
469 lowerBound.setFlexibleTypeCapabilitiesId(getStringTable().getStringIndex(flexibility.getExtraCapabilities().getId()));
470 if (useTypeTable()) {
471 lowerBound.setFlexibleUpperBoundId(typeId(flexibility.getUpperBound()));
472 }
473 else {
474 lowerBound.setFlexibleUpperBound(type(flexibility.getUpperBound()));
475 }
476 return lowerBound;
477 }
478
479 ProtoBuf.Type.Builder builder = ProtoBuf.Type.newBuilder();
480
481 ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
482 if (descriptor instanceof ClassDescriptor) {
483 PossiblyInnerType possiblyInnerType = TypeParameterUtilsKt.buildPossiblyInnerType(type);
484 assert possiblyInnerType != null : "possiblyInnerType should not be null in case of class";
485
486 fillFromPossiblyInnerType(builder, possiblyInnerType);
487
488 }
489 if (descriptor instanceof TypeParameterDescriptor) {
490 TypeParameterDescriptor typeParameter = (TypeParameterDescriptor) descriptor;
491 if (typeParameter.getContainingDeclaration() == containingDeclaration) {
492 builder.setTypeParameterName(getSimpleNameIndex(typeParameter.getName()));
493 }
494 else {
495 builder.setTypeParameter(getTypeParameterId(typeParameter));
496 }
497
498 assert type.getArguments().isEmpty() : "Found arguments for type constructor build on type parameter: " + descriptor;
499 }
500
501 if (type.isMarkedNullable() != builder.getNullable()) {
502 builder.setNullable(type.isMarkedNullable());
503 }
504
505 extension.serializeType(type, builder);
506
507 return builder;
508 }
509
510 private void fillFromPossiblyInnerType(
511 @NotNull ProtoBuf.Type.Builder builder,
512 @NotNull PossiblyInnerType type
513 ) {
514 builder.setClassName(getClassId(type.getClassDescriptor()));
515
516 for (TypeProjection projection : type.getArguments()) {
517 builder.addArgument(typeArgument(projection));
518 }
519
520 if (type.getOuterType() != null) {
521 ProtoBuf.Type.Builder outerBuilder = ProtoBuf.Type.newBuilder();
522 fillFromPossiblyInnerType(outerBuilder, type.getOuterType());
523 if (useTypeTable()) {
524 builder.setOuterTypeId(typeTable.get(outerBuilder));
525 }
526 else {
527 builder.setOuterType(outerBuilder);
528 }
529
530 }
531 }
532
533 @NotNull
534 private ProtoBuf.Type.Argument.Builder typeArgument(@NotNull TypeProjection typeProjection) {
535 ProtoBuf.Type.Argument.Builder builder = ProtoBuf.Type.Argument.newBuilder();
536
537 if (typeProjection.isStarProjection()) {
538 builder.setProjection(ProtoBuf.Type.Argument.Projection.STAR);
539 }
540 else {
541 ProtoBuf.Type.Argument.Projection projection = projection(typeProjection.getProjectionKind());
542
543 if (projection != builder.getProjection()) {
544 builder.setProjection(projection);
545 }
546
547 if (useTypeTable()) {
548 builder.setTypeId(typeId(typeProjection.getType()));
549 }
550 else {
551 builder.setType(type(typeProjection.getType()));
552 }
553 }
554
555 return builder;
556 }
557
558 @NotNull
559 public ProtoBuf.Package.Builder packageProto(@NotNull Collection<PackageFragmentDescriptor> fragments) {
560 return packageProto(fragments, null);
561 }
562
563 @NotNull
564 public ProtoBuf.Package.Builder packageProto(
565 @NotNull Collection<PackageFragmentDescriptor> fragments,
566 @Nullable Function1<DeclarationDescriptor, Boolean> skip
567 ) {
568 ProtoBuf.Package.Builder builder = ProtoBuf.Package.newBuilder();
569
570 Collection<DeclarationDescriptor> members = new ArrayList<DeclarationDescriptor>();
571 for (PackageFragmentDescriptor fragment : fragments) {
572 members.addAll(DescriptorUtils.getAllDescriptors(fragment.getMemberScope()));
573 }
574
575 for (DeclarationDescriptor declaration : sort(members)) {
576 if (skip != null && skip.invoke(declaration)) continue;
577
578 if (declaration instanceof PropertyDescriptor) {
579 builder.addProperty(propertyProto((PropertyDescriptor) declaration));
580 }
581 else if (declaration instanceof FunctionDescriptor) {
582 builder.addFunction(functionProto((FunctionDescriptor) declaration));
583 }
584 }
585
586 ProtoBuf.TypeTable typeTableProto = typeTable.serialize();
587 if (typeTableProto != null) {
588 builder.setTypeTable(typeTableProto);
589 }
590
591 extension.serializePackage(fragments, builder);
592
593 return builder;
594 }
595
596 @NotNull
597 public ProtoBuf.Package.Builder packagePartProto(@NotNull Collection<DeclarationDescriptor> members) {
598 ProtoBuf.Package.Builder builder = ProtoBuf.Package.newBuilder();
599
600 for (DeclarationDescriptor declaration : sort(members)) {
601 if (declaration instanceof PropertyDescriptor) {
602 builder.addProperty(propertyProto((PropertyDescriptor) declaration));
603 }
604 else if (declaration instanceof FunctionDescriptor) {
605 builder.addFunction(functionProto((FunctionDescriptor) declaration));
606 }
607 }
608
609 ProtoBuf.TypeTable typeTableProto = typeTable.serialize();
610 if (typeTableProto != null) {
611 builder.setTypeTable(typeTableProto);
612 }
613
614 return builder;
615 }
616
617 @NotNull
618 private static ProtoBuf.Type.Argument.Projection projection(@NotNull Variance projectionKind) {
619 switch (projectionKind) {
620 case INVARIANT:
621 return ProtoBuf.Type.Argument.Projection.INV;
622 case IN_VARIANCE:
623 return ProtoBuf.Type.Argument.Projection.IN;
624 case OUT_VARIANCE:
625 return ProtoBuf.Type.Argument.Projection.OUT;
626 }
627 throw new IllegalStateException("Unknown projectionKind: " + projectionKind);
628 }
629
630 private int getClassId(@NotNull ClassDescriptor descriptor) {
631 return getStringTable().getFqNameIndex(descriptor);
632 }
633
634 private int getSimpleNameIndex(@NotNull Name name) {
635 return getStringTable().getStringIndex(name.asString());
636 }
637
638 private int getTypeParameterId(@NotNull TypeParameterDescriptor descriptor) {
639 return typeParameters.intern(descriptor);
640 }
641
642 private static boolean hasAnnotations(Annotated descriptor) {
643 return !descriptor.getAnnotations().isEmpty();
644 }
645
646 @NotNull
647 public static <T extends DeclarationDescriptor> List<T> sort(@NotNull Collection<T> descriptors) {
648 List<T> result = new ArrayList<T>(descriptors);
649 //NOTE: the exact comparator does matter here
650 Collections.sort(result, MemberComparator.INSTANCE);
651 return result;
652
653 }
654 }