|
58 | 58 | import com.google.devtools.j2objc.ast.VariableDeclarationFragment; |
59 | 59 | import com.google.devtools.j2objc.util.CodeReferenceMap; |
60 | 60 | import com.google.devtools.j2objc.util.ElementUtil; |
| 61 | +import com.google.devtools.j2objc.util.ProGuardUsageParser; |
61 | 62 | import com.google.devtools.j2objc.util.TypeUtil; |
| 63 | +import java.io.File; |
62 | 64 | import java.lang.reflect.Modifier; |
63 | 65 | import java.util.ArrayDeque; |
| 66 | +import java.util.ArrayList; |
64 | 67 | import java.util.Deque; |
65 | 68 | import java.util.HashMap; |
66 | 69 | import java.util.HashSet; |
@@ -494,6 +497,9 @@ private static Annotations getAnnotations(AnnotatedConstruct annotatedConstruct) |
494 | 497 | private void startTypeScope( |
495 | 498 | String typeName, String superName, List<String> interfaces, boolean isExported) { |
496 | 499 | Integer id = getTypeId(typeName); |
| 500 | + if (!context.currentTypeInfoScope.isEmpty()) { |
| 501 | + context.currentTypeInfoScope.peek().addInnerTypes(id); |
| 502 | + } |
497 | 503 | Integer eid = getTypeId(superName); |
498 | 504 | ImmutableList<Integer> iids = |
499 | 505 | interfaces.stream().map(this::getTypeId).collect(toImmutableList()); |
@@ -626,6 +632,104 @@ private void popClinit() { |
626 | 632 | context.referencedTypesScope.pop(); |
627 | 633 | } |
628 | 634 |
|
| 635 | + private static ImmutableSet<String> getExportedClasses(CodeReferenceMap rootSet) { |
| 636 | + return rootSet == null ? ImmutableSet.of() : rootSet.getReferencedClasses(); |
| 637 | + } |
| 638 | + |
| 639 | + private static ImmutableSet<String> getExportedMethods(CodeReferenceMap rootSet) { |
| 640 | + Set<String> exportedMethods = new HashSet<>(); |
| 641 | + if (rootSet != null) { |
| 642 | + rootSet |
| 643 | + .getReferencedMethods() |
| 644 | + .cellSet() |
| 645 | + .forEach( |
| 646 | + cell -> |
| 647 | + cell.getValue() |
| 648 | + .forEach( |
| 649 | + signature -> |
| 650 | + exportedMethods.add( |
| 651 | + getQualifiedMethodName( |
| 652 | + cell.getRowKey(), cell.getColumnKey(), signature)))); |
| 653 | + } |
| 654 | + return ImmutableSet.copyOf(exportedMethods); |
| 655 | + } |
| 656 | + |
| 657 | + private static List<TypeInfo> markClasses( |
| 658 | + List<TypeInfo> types, List<String> typeMap, Set<String> markedClasses) { |
| 659 | + if (markedClasses.isEmpty()) { |
| 660 | + return types; |
| 661 | + } |
| 662 | + List<TypeInfo> markedTypes = new ArrayList<>(); |
| 663 | + Set<String> nextMarkedClasses = new HashSet<>(); |
| 664 | + for (TypeInfo type : types) { |
| 665 | + TypeInfo.Builder typeBuilder = type.toBuilder(); |
| 666 | + if (markedClasses.contains(typeMap.get(type.getTypeId()))) { |
| 667 | + // Set type as exported. |
| 668 | + typeBuilder.setExported(true).clearMember(); |
| 669 | + for (MemberInfo member : type.getMemberList()) { |
| 670 | + // Set each method of the type as exported. |
| 671 | + typeBuilder.addMember(member.toBuilder().setExported(true).build()); |
| 672 | + } |
| 673 | + // Add inner types that need to be exported to a list. |
| 674 | + nextMarkedClasses.addAll( |
| 675 | + type.getInnerTypesList().stream().map(typeMap::get).collect(toImmutableList())); |
| 676 | + } |
| 677 | + // Add type to list of marked types |
| 678 | + markedTypes.add(typeBuilder.build()); |
| 679 | + } |
| 680 | + // Recursively call with the list of exported classes as the inner classes that need to be |
| 681 | + // exported. |
| 682 | + // This is because we do not know if the inner class has inner classes (alternative, while |
| 683 | + // loop). |
| 684 | + return markClasses(markedTypes, typeMap, nextMarkedClasses); |
| 685 | + } |
| 686 | + |
| 687 | + private static TypeInfo markMethodsOfType( |
| 688 | + TypeInfo type, List<String> typeMap, Set<String> markedMethods) { |
| 689 | + TypeInfo.Builder typeBuilder = type.toBuilder().clearMember(); |
| 690 | + for (MemberInfo member : type.getMemberList()) { |
| 691 | + MemberInfo.Builder memberBuilder = member.toBuilder(); |
| 692 | + if (markedMethods.contains( |
| 693 | + getQualifiedMethodName(typeMap.get(type.getTypeId()), member.getName()))) { |
| 694 | + memberBuilder.setExported(true); |
| 695 | + } |
| 696 | + typeBuilder.addMember(memberBuilder.build()); |
| 697 | + } |
| 698 | + return typeBuilder.build(); |
| 699 | + } |
| 700 | + |
| 701 | + private static ImmutableList<TypeInfo> markMethods( |
| 702 | + List<TypeInfo> types, List<String> typeMap, Set<String> markedMethods) { |
| 703 | + List<TypeInfo> typesWithMarkedMembers = new ArrayList<>(); |
| 704 | + for (TypeInfo type : types) { |
| 705 | + typesWithMarkedMembers.add(markMethodsOfType(type, typeMap, markedMethods)); |
| 706 | + } |
| 707 | + return ImmutableList.copyOf(typesWithMarkedMembers); |
| 708 | + } |
| 709 | + |
| 710 | + /* |
| 711 | + * Uses exported classes given to 'mark' summary information as 'live' for TypeGraphAnalyzer. |
| 712 | + */ |
| 713 | + private static LibraryInfo markEntryClasses( |
| 714 | + LibraryInfo summary, |
| 715 | + ImmutableSet<String> exportedClasses, |
| 716 | + ImmutableSet<String> exportedMethods) { |
| 717 | + return summary.toBuilder() |
| 718 | + .clearType() |
| 719 | + .addAllType( |
| 720 | + markClasses( |
| 721 | + markMethods(summary.getTypeList(), summary.getTypeMapList(), exportedMethods), |
| 722 | + summary.getTypeMapList(), |
| 723 | + exportedClasses)) |
| 724 | + .build(); |
| 725 | + } |
| 726 | + |
| 727 | + static LibraryInfo mark(LibraryInfo summary, File roots) { |
| 728 | + CodeReferenceMap rootSet = ProGuardUsageParser.parseDeadCodeFile(roots); |
| 729 | + return markEntryClasses( |
| 730 | + summary, getExportedClasses(rootSet), UsedCodeMarker.getExportedMethods(rootSet)); |
| 731 | + } |
| 732 | + |
629 | 733 | static final class Context { |
630 | 734 | // Map of type names to unique integer. |
631 | 735 | private int typeCount; |
@@ -653,20 +757,13 @@ static final class Context { |
653 | 757 | private final Deque<Set<Integer>> clinitReferencedTypesScope = new ArrayDeque<>(); |
654 | 758 |
|
655 | 759 | Context(CodeReferenceMap rootSet) { |
| 760 | + exportedMethods = getExportedMethods(rootSet); |
| 761 | + exportedClasses = getExportedClasses(rootSet); |
| 762 | + } |
| 763 | + |
| 764 | + Context() { |
656 | 765 | exportedMethods = new HashSet<>(); |
657 | | - rootSet |
658 | | - .getReferencedMethods() |
659 | | - .cellSet() |
660 | | - .forEach( |
661 | | - cell -> { |
662 | | - String type = cell.getRowKey(); |
663 | | - String name = cell.getColumnKey(); |
664 | | - cell.getValue() |
665 | | - .forEach( |
666 | | - signature -> |
667 | | - exportedMethods.add(getQualifiedMethodName(type, name, signature))); |
668 | | - }); |
669 | | - exportedClasses = rootSet.getReferencedClasses(); |
| 766 | + exportedClasses = ImmutableSet.copyOf(new HashSet<>()); |
670 | 767 | } |
671 | 768 |
|
672 | 769 | LibraryInfo getLibraryInfo() { |
|
0 commit comments