| // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'dart:collection'; | |
| import 'dart:convert'; | |
| import 'package:analyzer/dart/element/element.dart'; | |
| import 'package:analyzer/exception/exception.dart'; | |
| import 'package:analyzer/source/source.dart'; | |
| import 'package:analyzer/src/dart/constant/value.dart'; | |
| import 'package:analyzer/src/dart/element/element.dart'; | |
| /// Utility methods that can be mixed in to classes that produce an HTML | |
| /// representation of a tree structure. | |
| mixin TreeWriter { | |
| /// The current level of indentation. | |
| int indentLevel = 0; | |
| /// A list containing the exceptions that were caught while attempting to | |
| /// write out the tree structure. | |
| List<CaughtException> exceptions = <CaughtException>[]; | |
| /// The buffer on which the HTML is to be written. | |
| StringBuffer get buffer; | |
| void indent([int extra = 0]) { | |
| for (var i = 0; i < indentLevel; i++) { | |
| buffer.write('┊ '); | |
| } | |
| if (extra > 0) { | |
| buffer.write('┊ '); | |
| for (var i = 1; i < extra; i++) { | |
| buffer.write(' '); | |
| } | |
| } | |
| } | |
| /// Write a representation of the given [properties] to the buffer. | |
| void writeProperties(Map<String, Object> properties) { | |
| for (var MapEntry(:key, :value) in SplayTreeMap.of(properties).entries) { | |
| writeProperty(key, value); | |
| } | |
| } | |
| /// Write the [value] of the property with the given [name]. | |
| void writeProperty(String name, Object value) { | |
| indent(2); | |
| buffer.write('$name = '); | |
| _writePropertyValue(value, indentLevel); | |
| buffer.write('<br>'); | |
| } | |
| String? _toString(Object? value) { | |
| try { | |
| if (value is DirectiveUri) { | |
| if (value is DirectiveUriWithSource) { | |
| var sourceStr = _toString(value.source); | |
| return 'DirectiveUriWithSource (source=$sourceStr)'; | |
| } | |
| return value.toString(); | |
| } else if (value is Source) { | |
| return 'Source (uri="${value.uri}", path="${value.fullName}")'; | |
| } else if (value is ElementAnnotationImpl) { | |
| var buffer = StringBuffer(); | |
| buffer.write(_toString(value.element)); | |
| var result = value.evaluationResult; | |
| switch (result) { | |
| case null: | |
| buffer.write(': no result'); | |
| case DartObjectImpl(): | |
| buffer.write(': value = '); | |
| buffer.write(result); | |
| case InvalidConstant(): | |
| buffer.write('; errors = '); | |
| buffer.writeAll(value.constantEvaluationErrors, ', '); | |
| } | |
| return buffer.toString(); | |
| } else { | |
| return value.toString(); | |
| } | |
| } catch (exception, stackTrace) { | |
| exceptions.add(CaughtException(exception, stackTrace)); | |
| } | |
| return null; | |
| } | |
| /// Writes the [value] of the property. | |
| void _writePropertyValue(Object value, int baseIndent) { | |
| if (value is List<Object>) { | |
| if (value.isEmpty) { | |
| buffer.write('[]'); | |
| } else { | |
| var elementIndent = baseIndent + 2; | |
| buffer.write('[<br>'); | |
| for (var element in value) { | |
| indent(elementIndent); | |
| _writePropertyValue(element, elementIndent); | |
| buffer.write('<br>'); | |
| } | |
| indent(baseIndent); | |
| buffer.write(']'); | |
| } | |
| } else { | |
| var valueString = _toString(value); | |
| if (valueString == null) { | |
| buffer.write('<span style="color: #FF0000">'); | |
| buffer.write(htmlEscape.convert(value.runtimeType.toString())); | |
| buffer.write('</span>'); | |
| } else { | |
| buffer.write(htmlEscape.convert(valueString)); | |
| } | |
| } | |
| } | |
| } |