package com.google.dart.dev.util.analysis; import com.google.dart.engine.ast.AnnotatedNode; import com.google.dart.engine.ast.Annotation; import com.google.dart.engine.ast.ArgumentList; import com.google.dart.engine.ast.AsExpression; import com.google.dart.engine.ast.AssignmentExpression; import com.google.dart.engine.ast.AstNode; import com.google.dart.engine.ast.BinaryExpression; import com.google.dart.engine.ast.Block; import com.google.dart.engine.ast.BreakStatement; import com.google.dart.engine.ast.CascadeExpression; import com.google.dart.engine.ast.Comment; import com.google.dart.engine.ast.CompilationUnit; import com.google.dart.engine.ast.ConditionalExpression; import com.google.dart.engine.ast.ConstructorDeclaration; import com.google.dart.engine.ast.ContinueStatement; import com.google.dart.engine.ast.ExportDirective; import com.google.dart.engine.ast.Expression; import com.google.dart.engine.ast.ForStatement; import com.google.dart.engine.ast.FormalParameterList; import com.google.dart.engine.ast.FunctionExpression; import com.google.dart.engine.ast.FunctionExpressionInvocation; import com.google.dart.engine.ast.ImportDirective; import com.google.dart.engine.ast.IndexExpression; import com.google.dart.engine.ast.InstanceCreationExpression; import com.google.dart.engine.ast.IsExpression; import com.google.dart.engine.ast.LibraryIdentifier; import com.google.dart.engine.ast.ListLiteral; import com.google.dart.engine.ast.Literal; import com.google.dart.engine.ast.MapLiteral; import com.google.dart.engine.ast.MethodInvocation; import com.google.dart.engine.ast.NamedExpression; import com.google.dart.engine.ast.NamespaceDirective; import com.google.dart.engine.ast.NormalFormalParameter; import com.google.dart.engine.ast.ParenthesizedExpression; import com.google.dart.engine.ast.PostfixExpression; import com.google.dart.engine.ast.PrefixExpression; import com.google.dart.engine.ast.PrefixedIdentifier; import com.google.dart.engine.ast.PropertyAccess; import com.google.dart.engine.ast.RethrowExpression; import com.google.dart.engine.ast.ReturnStatement; import com.google.dart.engine.ast.SimpleIdentifier; import com.google.dart.engine.ast.SimpleStringLiteral; import com.google.dart.engine.ast.SuperExpression; import com.google.dart.engine.ast.SwitchMember; import com.google.dart.engine.ast.ThisExpression; import com.google.dart.engine.ast.ThrowExpression; import com.google.dart.engine.ast.TryStatement; import com.google.dart.engine.ast.TypeParameter; import com.google.dart.engine.ast.visitor.GeneralizingAstVisitor; import com.google.dart.engine.element.Element; import com.google.dart.engine.element.LibraryElement; import com.google.dart.engine.element.visitor.GeneralizingElementVisitor; import com.google.dart.engine.internal.cache.AnalysisCache; import com.google.dart.engine.internal.cache.CachePartition; import com.google.dart.engine.internal.cache.DartEntry; import com.google.dart.engine.internal.cache.DartEntryImpl; import com.google.dart.engine.internal.cache.HtmlEntry; import com.google.dart.engine.internal.cache.HtmlEntryImpl; import com.google.dart.engine.internal.cache.SourceEntry; import com.google.dart.engine.internal.context.InternalAnalysisContext; import com.google.dart.engine.scanner.Token; import com.google.dart.engine.scanner.TokenType; import com.google.dart.engine.source.Source; import com.google.dart.engine.utilities.io.PrintStringWriter; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; public class MemoryUsageData { private static class ClassData { public static final Comparator<MemoryUsageData.ClassData> SORT_BY_NAME = new Comparator<MemoryUsageData.ClassData>() { @Override public int compare(MemoryUsageData.ClassData firstData, MemoryUsageData.ClassData secondData) { return firstData.getClassObject().getName().compareTo(secondData.getClassObject().getName()); } }; public static final Comparator<MemoryUsageData.ClassData> SORT_BY_TOTAL_SIZE = new Comparator<MemoryUsageData.ClassData>() { @Override public int compare(MemoryUsageData.ClassData firstData, MemoryUsageData.ClassData secondData) { return secondData.getTotalSize() - firstData.getTotalSize(); } }; private Class<?> classObject; private int objectSize; private int objectCount; private HashMap<String, Integer> counts; public ClassData(Class<?> classObject) { this.classObject = classObject; objectSize = computeObjectSize(); } public Class<?> getClassObject() { return classObject; } public int getCount(String name) { Integer count = counts.get(name); if (count == null) { return 0; } return count; } public HashMap<String, Integer> getCounts() { return counts; } public int getObjectCount() { return objectCount; } public int getObjectSize() { return objectSize; } public int getTotalSize() { return objectSize * objectCount; } public void incrementCount() { objectCount++; } public void incrementCount(String name, int delta) { if (counts == null) { counts = new HashMap<String, Integer>(); } Integer count = counts.get(name); if (count == null) { count = 0; } counts.put(name, count + delta); } public void incrementCountIfNotEmpty(String countName, List<?> list) { incrementCountIfTrue("non-empty " + countName, list != null && list.size() > 0); } public void incrementCountIfNotNull(String countName, Object value) { incrementCountIfTrue(countName, value != null); } public void incrementCountIfTrue(String countName, boolean value) { incrementCount(countName, value ? 1 : 0); } public void incrementFieldCount(String fieldName, Object object) { try { Field field = object.getClass().getDeclaredField(fieldName); field.setAccessible(true); incrementCountIfNotNull(fieldName, field.get(object)); } catch (Exception exception) { // Ignored } } private int computeObjectSize() { Class<?> currentClass = classObject; int size = 0; while (currentClass != null) { Field[] fields = currentClass.getDeclaredFields(); for (Field field : fields) { if (!Modifier.isStatic(field.getModifiers())) { size++; } } currentClass = currentClass.getSuperclass(); } return size; } } /** * A table mapping the classes for which size information is being computed to the information for * that class. */ private HashMap<Class<?>, MemoryUsageData.ClassData> classData = new HashMap<Class<?>, MemoryUsageData.ClassData>(); /** * A collection of cache partitions that have been visited, used to prevent the same partition * from being counted multiple times. */ private HashSet<CachePartition> visitedPartitions = new HashSet<CachePartition>(); private static final int[] CLASS_SPECIFIC_ALIGNMENTS = new int[] { PrintStringWriter.ALIGN_LEFT, PrintStringWriter.ALIGN_RIGHT, PrintStringWriter.ALIGN_RIGHT}; private static final int[] CLASS_USAGE_ALIGNMENTS = new int[] { PrintStringWriter.ALIGN_LEFT, PrintStringWriter.ALIGN_RIGHT, PrintStringWriter.ALIGN_RIGHT, PrintStringWriter.ALIGN_RIGHT}; private static final int[] SUMMARY_ALIGNMENTS = new int[] { PrintStringWriter.ALIGN_LEFT, PrintStringWriter.ALIGN_RIGHT}; public void addContext(InternalAnalysisContext context) { AnalysisCache cache = getAnalysisCache(context); if (cache == null) { return; } CachePartition[] partitions = getPartitions(cache); if (partitions == null) { return; } for (CachePartition partition : partitions) { if (visitedPartitions.add(partition)) { for (SourceEntry entry : partition.getMap().values()) { addCacheEntry(entry); } } } } public String getReport() { MemoryUsageData.ClassData[] entries = classData.values().toArray( new MemoryUsageData.ClassData[classData.size()]); Arrays.sort(entries, ClassData.SORT_BY_TOTAL_SIZE); int rowCount = entries.length; int totalTotalSize = 0; int totalObjectCount = 0; String[][] data = new String[rowCount + 1][]; data[0] = new String[] {"Class Name", "Total Size", "Object Count", "Object Size"}; for (int i = 0; i < rowCount; i++) { ClassData entry = entries[i]; int totalSize = entry.getTotalSize(); totalTotalSize += totalSize; int objectCount = entry.getObjectCount(); totalObjectCount += objectCount; data[i + 1] = new String[] { entry.getClassObject().getName(), Integer.toString(totalSize), Integer.toString(objectCount), Integer.toString(entry.getObjectSize())}; } PrintStringWriter writer = new PrintStringWriter(); writer.println("Summary"); writer.println(); writer.printTable( new String[][] { {"Total memory usage:", Integer.toString(totalTotalSize)}, {"Total object count:", Integer.toString(totalObjectCount)}}, SUMMARY_ALIGNMENTS); writer.println(); writer.println("Usage by Class"); writer.println(); writer.printTable(data, CLASS_USAGE_ALIGNMENTS); writer.println(); writer.println("Class-specific Counts"); // Arrays.sort(entries, ClassData.SORT_BY_NAME); for (int i = 0; i < rowCount; i++) { printClassSpecificReportData(writer, entries[i]); } return writer.toString(); } private void addAllObjects(Object[] objects) { if (objects != null) { for (Object object : objects) { if (object != null) { MemoryUsageData.ClassData data = getDataFor(object.getClass()); data.incrementCount(); } } } } private void addAst(CompilationUnit unit) { if (unit != null) { addTokens(unit.getBeginToken()); unit.accept(new GeneralizingAstVisitor<Void>() { @Override public Void visitAnnotatedNode(AnnotatedNode node) { ClassData data = getDataFor(AnnotatedNode.class); data.incrementCount(); data.incrementCountIfNotNull("documentationComment", node.getDocumentationComment()); data.incrementCountIfNotEmpty("metadata", node.getMetadata()); return super.visitAnnotatedNode(node); } @Override public Void visitAnnotation(Annotation node) { ClassData data = getDataFor(Annotation.class); data.incrementCountIfNotNull("element", node.getElement()); data.incrementCountIfNotNull("elementAnnotation", node.getElementAnnotation()); return super.visitAnnotation(node); } @Override public Void visitArgumentList(ArgumentList node) { ClassData data = getDataFor(ArgumentList.class); data.incrementCountIfNotEmpty("arguments", node.getArguments()); data.incrementFieldCount("correspondingPropagatedParameters", node); data.incrementFieldCount("correspondingStaticParameters", node); return super.visitArgumentList(node); } @Override public Void visitAsExpression(AsExpression node) { ClassData data = getDataFor(AsExpression.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitAsExpression(node); } @Override public Void visitAssignmentExpression(AssignmentExpression node) { ClassData data = getDataFor(AssignmentExpression.class); data.incrementCountIfNotNull("propagatedElement", node.getPropagatedElement()); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticElement", node.getStaticElement()); data.incrementCountIfNotNull("staticType", node.getStaticType()); if (node.getOperator().getType() != TokenType.EQ) { data.incrementCount("compound", 1); } return super.visitAssignmentExpression(node); } @Override public Void visitBinaryExpression(BinaryExpression node) { ClassData data = getDataFor(BinaryExpression.class); data.incrementCountIfNotNull("propagatedElement", node.getPropagatedElement()); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticElement", node.getStaticElement()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitBinaryExpression(node); } @Override public Void visitBlock(Block node) { ClassData data = getDataFor(Block.class); data.incrementCountIfNotEmpty("statements", node.getStatements()); return super.visitBlock(node); } @Override public Void visitBreakStatement(BreakStatement node) { ClassData data = getDataFor(BreakStatement.class); data.incrementCountIfNotNull("label", node.getLabel()); return super.visitBreakStatement(node); } @Override public Void visitCascadeExpression(CascadeExpression node) { ClassData data = getDataFor(CascadeExpression.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitCascadeExpression(node); } @Override public Void visitComment(Comment node) { ClassData data = getDataFor(Comment.class); data.incrementCountIfNotEmpty("references", node.getReferences()); return super.visitComment(node); } @Override public Void visitCompilationUnit(CompilationUnit node) { ClassData data = getDataFor(CompilationUnit.class); data.incrementCountIfNotEmpty("declarations", node.getDeclarations()); data.incrementCountIfNotEmpty("directives", node.getDirectives()); data.incrementCountIfNotNull("lineInfo", node.getLineInfo()); return super.visitCompilationUnit(node); } @Override public Void visitConditionalExpression(ConditionalExpression node) { ClassData data = getDataFor(ConditionalExpression.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitConditionalExpression(node); } @Override public Void visitConstructorDeclaration(ConstructorDeclaration node) { ClassData data = getDataFor(ConstructorDeclaration.class); data.incrementCountIfNotEmpty("initializers", node.getInitializers()); return super.visitConstructorDeclaration(node); } @Override public Void visitContinueStatement(ContinueStatement node) { ClassData data = getDataFor(ContinueStatement.class); data.incrementCountIfNotNull("label", node.getLabel()); return super.visitContinueStatement(node); } @Override public Void visitExportDirective(ExportDirective node) { ClassData data = getDataFor(ExportDirective.class); data.incrementCountIfNotEmpty("combinators", node.getCombinators()); return super.visitExportDirective(node); } @Override public Void visitExpression(Expression node) { ClassData data = getDataFor(Expression.class); data.incrementCount(); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitExpression(node); } @Override public Void visitFormalParameterList(FormalParameterList node) { ClassData data = getDataFor(FormalParameterList.class); data.incrementCountIfNotEmpty("", node.getParameters()); return super.visitFormalParameterList(node); } @Override public Void visitForStatement(ForStatement node) { ClassData data = getDataFor(ForStatement.class); data.incrementCountIfNotNull("initialization", node.getInitialization()); data.incrementCountIfNotNull("variables", node.getVariables()); data.incrementCountIfNotEmpty("updaters", node.getUpdaters()); return super.visitForStatement(node); } @Override public Void visitFunctionExpression(FunctionExpression node) { ClassData data = getDataFor(FunctionExpression.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitFunctionExpression(node); } @Override public Void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { ClassData data = getDataFor(FunctionExpressionInvocation.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitFunctionExpressionInvocation(node); } @Override public Void visitImportDirective(ImportDirective node) { ClassData data = getDataFor(ImportDirective.class); data.incrementCountIfNotEmpty("combinators", node.getCombinators()); data.incrementCountIfNotNull("deferred", node.getDeferredToken()); data.incrementCountIfNotNull("prefix", node.getPrefix()); return super.visitImportDirective(node); } @Override public Void visitIndexExpression(IndexExpression node) { ClassData data = getDataFor(IndexExpression.class); data.incrementCountIfNotNull("auxiliaryElements", node.getAuxiliaryElements()); data.incrementCountIfNotNull("propagatedElement", node.getPropagatedElement()); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticElement", node.getStaticElement()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitIndexExpression(node); } @Override public Void visitInstanceCreationExpression(InstanceCreationExpression node) { ClassData data = getDataFor(InstanceCreationExpression.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitInstanceCreationExpression(node); } @Override public Void visitIsExpression(IsExpression node) { ClassData data = getDataFor(IsExpression.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitIsExpression(node); } @Override public Void visitLibraryIdentifier(LibraryIdentifier node) { ClassData data = getDataFor(LibraryIdentifier.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitLibraryIdentifier(node); } @Override public Void visitListLiteral(ListLiteral node) { ClassData data = getDataFor(ListLiteral.class); data.incrementCountIfNotEmpty("elements", node.getElements()); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitListLiteral(node); } @Override public Void visitLiteral(Literal node) { ClassData data = getDataFor(Literal.class); data.incrementCount(); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitLiteral(node); } @Override public Void visitMapLiteral(MapLiteral node) { ClassData data = getDataFor(MapLiteral.class); data.incrementCountIfNotEmpty("entries", node.getEntries()); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitMapLiteral(node); } @Override public Void visitMethodInvocation(MethodInvocation node) { ClassData data = getDataFor(MethodInvocation.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitMethodInvocation(node); } @Override public Void visitNamedExpression(NamedExpression node) { ClassData data = getDataFor(NamedExpression.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitNamedExpression(node); } @Override public Void visitNamespaceDirective(NamespaceDirective node) { ClassData data = getDataFor(NamespaceDirective.class); data.incrementCount(); data.incrementCountIfNotEmpty("combinators", node.getCombinators()); return super.visitNamespaceDirective(node); } @Override public Void visitNode(AstNode node) { addObject(node); return super.visitNode(node); } @Override public Void visitNormalFormalParameter(NormalFormalParameter node) { ClassData data = getDataFor(NormalFormalParameter.class); data.incrementCount(); data.incrementCountIfNotNull("", node.getDocumentationComment()); data.incrementCountIfNotEmpty("", node.getMetadata()); return super.visitNormalFormalParameter(node); } @Override public Void visitParenthesizedExpression(ParenthesizedExpression node) { ClassData data = getDataFor(ParenthesizedExpression.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitParenthesizedExpression(node); } @Override public Void visitPostfixExpression(PostfixExpression node) { ClassData data = getDataFor(PostfixExpression.class); data.incrementCountIfNotNull("propagatedElement", node.getPropagatedElement()); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticElement", node.getStaticElement()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitPostfixExpression(node); } @Override public Void visitPrefixedIdentifier(PrefixedIdentifier node) { ClassData data = getDataFor(PrefixedIdentifier.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitPrefixedIdentifier(node); } @Override public Void visitPrefixExpression(PrefixExpression node) { ClassData data = getDataFor(PrefixExpression.class); data.incrementCountIfNotNull("propagatedElement", node.getPropagatedElement()); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticElement", node.getStaticElement()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitPrefixExpression(node); } @Override public Void visitPropertyAccess(PropertyAccess node) { ClassData data = getDataFor(PropertyAccess.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitPropertyAccess(node); } @Override public Void visitRethrowExpression(RethrowExpression node) { ClassData data = getDataFor(RethrowExpression.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitRethrowExpression(node); } @Override public Void visitReturnStatement(ReturnStatement node) { ClassData data = getDataFor(ReturnStatement.class); data.incrementCountIfNotNull("expression", node.getExpression()); return super.visitReturnStatement(node); } @Override public Void visitSimpleIdentifier(SimpleIdentifier node) { ClassData data = getDataFor(SimpleIdentifier.class); data.incrementCountIfNotNull("auxiliaryElements", node.getAuxiliaryElements()); data.incrementCountIfNotNull("propagatedElement", node.getPropagatedElement()); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticElement", node.getStaticElement()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitSimpleIdentifier(node); } @Override public Void visitSimpleStringLiteral(SimpleStringLiteral node) { ClassData data = getDataFor(SimpleStringLiteral.class); data.incrementCountIfNotNull("toolkitElement", node.getToolkitElement()); return super.visitSimpleStringLiteral(node); } @Override public Void visitSuperExpression(SuperExpression node) { ClassData data = getDataFor(SuperExpression.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitSuperExpression(node); } @Override public Void visitSwitchMember(SwitchMember node) { ClassData data = getDataFor(SwitchMember.class); data.incrementCount(); data.incrementCountIfNotEmpty("labels", node.getLabels()); data.incrementCountIfNotEmpty("statements", node.getStatements()); return super.visitSwitchMember(node); } @Override public Void visitThisExpression(ThisExpression node) { ClassData data = getDataFor(ThisExpression.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitThisExpression(node); } @Override public Void visitThrowExpression(ThrowExpression node) { ClassData data = getDataFor(ThrowExpression.class); data.incrementCountIfNotNull("propagatedType", node.getPropagatedType()); data.incrementCountIfNotNull("staticType", node.getStaticType()); return super.visitThrowExpression(node); } @Override public Void visitTryStatement(TryStatement node) { ClassData data = getDataFor(TryStatement.class); data.incrementCountIfNotEmpty("catchClauses", node.getCatchClauses()); return super.visitTryStatement(node); } @Override public Void visitTypeParameter(TypeParameter node) { ClassData data = getDataFor(TypeParameter.class); data.incrementCountIfNotNull("bound", node.getBound()); return super.visitTypeParameter(node); } }); } } private void addCacheEntry(SourceEntry entry) { // TODO(brianwilkerson) This method is out-of-date. addObject(entry); addObject(entry.getException()); addObject(entry.getValue(SourceEntry.LINE_INFO)); if (entry instanceof DartEntryImpl) { DartEntryImpl dartEntry = (DartEntryImpl) entry; addAllObjects(dartEntry.getValue(DartEntry.ANGULAR_ERRORS)); addElements(dartEntry.getValue(DartEntry.ELEMENT)); addAllObjects(dartEntry.getValue(DartEntry.PARSE_ERRORS)); addAst(dartEntry.getValue(DartEntry.PARSED_UNIT)); addObject(dartEntry.getValue(DartEntry.PUBLIC_NAMESPACE)); addAllObjects(dartEntry.getValue(DartEntry.SCAN_ERRORS)); addTokens(dartEntry.getValue(DartEntry.TOKEN_STREAM)); Source[] containingLibraries = dartEntry.getValue(DartEntry.CONTAINING_LIBRARIES); for (Source librarySource : containingLibraries) { addAllObjects(dartEntry.getValueInLibrary(DartEntry.RESOLUTION_ERRORS, librarySource)); addAst(dartEntry.getValueInLibrary(DartEntry.RESOLVED_UNIT, librarySource)); addAllObjects(dartEntry.getValueInLibrary(DartEntry.VERIFICATION_ERRORS, librarySource)); addAllObjects(dartEntry.getValueInLibrary(DartEntry.HINTS, librarySource)); } } else if (entry instanceof HtmlEntryImpl) { HtmlEntryImpl htmlEntry = (HtmlEntryImpl) entry; addObject(htmlEntry.getValue(HtmlEntry.ANGULAR_APPLICATION)); addObject(htmlEntry.getValue(HtmlEntry.ANGULAR_COMPONENT)); addObject(htmlEntry.getValue(HtmlEntry.ANGULAR_ENTRY)); addAllObjects(htmlEntry.getValue(HtmlEntry.ANGULAR_ERRORS)); addObject(htmlEntry.getValue(HtmlEntry.ELEMENT)); addAllObjects(htmlEntry.getValue(HtmlEntry.PARSE_ERRORS)); addObject(htmlEntry.getValue(HtmlEntry.PARSED_UNIT)); addObject(htmlEntry.getValue(HtmlEntry.RESOLVED_UNIT)); addAllObjects(htmlEntry.getValue(HtmlEntry.RESOLUTION_ERRORS)); addAllObjects(htmlEntry.getValue(HtmlEntry.HINTS)); addAllObjects(htmlEntry.getValue(HtmlEntry.POLYMER_BUILD_ERRORS)); addAllObjects(htmlEntry.getValue(HtmlEntry.POLYMER_RESOLUTION_ERRORS)); } } private void addElements(LibraryElement element) { if (element != null) { element.accept(new GeneralizingElementVisitor<Void>() { @Override public Void visitElement(Element element) { addObject(element); return super.visitElement(element); } }); } } private void addObject(Object object) { if (object != null) { MemoryUsageData.ClassData data = getDataFor(object.getClass()); data.incrementCount(); } } private void addTokens(Token token) { if (token != null) { while (token.getNext() != token) { addObject(token); token = token.getNext(); } } } private AnalysisCache getAnalysisCache(InternalAnalysisContext context) { try { Field field = context.getClass().getDeclaredField("cache"); field.setAccessible(true); return (AnalysisCache) field.get(context); } catch (Exception exception) { return null; } } private String[][] getClassSpecificReportData(ClassData classData) { HashMap<String, Integer> counts = classData.getCounts(); int rowCount = counts.size(); String[] countNames = counts.keySet().toArray(new String[rowCount]); Arrays.sort(countNames); String[][] data = new String[rowCount][]; int objectCount = classData.getObjectCount(); for (int i = 0; i < rowCount; i++) { String countName = countNames[i]; int count = classData.getCount(countName); int pecentage = (int) Math.round((count * 100.0) / objectCount); data[i] = new String[] {countName, Integer.toString(count), Integer.toString(pecentage) + "%"}; } return data; } private MemoryUsageData.ClassData getDataFor(Class<?> someClass) { MemoryUsageData.ClassData data = classData.get(someClass); if (data == null) { data = new ClassData(someClass); classData.put(someClass, data); } return data; } private CachePartition[] getPartitions(AnalysisCache cache) { try { Field field = cache.getClass().getDeclaredField("partitions"); field.setAccessible(true); return (CachePartition[]) field.get(cache); } catch (Exception exception) { return null; } } private void printClassSpecificReportData(PrintStringWriter writer, ClassData data) { if (data.getCounts() != null) { writer.println(); writer.print(data.getClassObject().getName()); writer.print(" ("); writer.print(data.getObjectCount()); writer.println(")"); writer.printTable(getClassSpecificReportData(data), CLASS_SPECIFIC_ALIGNMENTS); } } }