| // Copyright (c) 2020, 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. |
| |
| /// Contains all the neccesary classes required by config. |
| |
| import 'package:meta/meta.dart'; |
| import 'package:quiver/pattern.dart' as quiver; |
| |
| class CommentType { |
| CommentStyle style; |
| CommentLength length; |
| CommentType(this.style, this.length); |
| |
| /// Sets default style as [CommentStyle.doxygen], default length as |
| /// [CommentLength.full]. |
| CommentType.def() |
| : style = CommentStyle.doxygen, |
| length = CommentLength.full; |
| |
| /// Disables any comments. |
| CommentType.none() |
| : style = CommentStyle.doxygen, |
| length = CommentLength.none; |
| } |
| |
| enum CommentStyle { doxygen, any } |
| enum CommentLength { none, brief, full } |
| |
| /// Represents a single specification in configurations. |
| /// |
| /// [E] is the return type of the extractedResult. |
| class Specification<E> { |
| final bool Function(String name, dynamic value) validator; |
| final E Function(dynamic map) extractor; |
| final E Function() defaultValue; |
| |
| final Requirement requirement; |
| final void Function(dynamic result) extractedResult; |
| |
| Specification({ |
| @required this.extractedResult, |
| @required this.validator, |
| @required this.extractor, |
| this.defaultValue, |
| this.requirement = Requirement.no, |
| }); |
| } |
| |
| enum Requirement { yes, prefer, no } |
| |
| // Holds headers and filters for header. |
| class Headers { |
| /// Path to headers. |
| /// |
| /// This contains all the headers, after extraction from Globs. |
| List<String> entryPoints = []; |
| |
| /// Include filter for headers. |
| HeaderIncludeFilter includeFilter = GlobHeaderFilter(); |
| |
| Headers({this.entryPoints, this.includeFilter}); |
| } |
| |
| abstract class HeaderIncludeFilter { |
| bool shouldInclude(String headerSourceFile); |
| } |
| |
| class GlobHeaderFilter extends HeaderIncludeFilter { |
| List<quiver.Glob> includeGlobs = []; |
| |
| GlobHeaderFilter({ |
| this.includeGlobs, |
| }); |
| |
| @override |
| bool shouldInclude(String header) { |
| // Return true if header was included. |
| for (final globPattern in includeGlobs) { |
| if (quiver.matchesFull(globPattern, header)) { |
| return true; |
| } |
| } |
| |
| // If any includedInclusionHeaders is provided, return false. |
| if (includeGlobs.isNotEmpty) { |
| return false; |
| } else { |
| return true; |
| } |
| } |
| } |
| |
| /// A generic declaration config, used for Functions, Structs and Enums. |
| class Declaration { |
| final Includer _includer; |
| final Renamer _renamer; |
| final MemberRenamer _memberRenamer; |
| |
| Declaration({ |
| Includer includer, |
| Renamer renamer, |
| MemberRenamer memberRenamer, |
| }) : _includer = includer ?? Includer(), |
| _renamer = renamer ?? Renamer(), |
| _memberRenamer = memberRenamer ?? MemberRenamer(); |
| |
| /// Applies renaming and returns the result. |
| String renameUsingConfig(String name) => _renamer.rename(name); |
| |
| /// Applies member renaming and returns the result. |
| String renameMemberUsingConfig(String declaration, String member) => |
| _memberRenamer.rename(declaration, member); |
| |
| /// Checks if a name is allowed by a filter. |
| bool shouldInclude(String name) => _includer.shouldInclude(name); |
| } |
| |
| /// Matches `$<single_digit_int>`, value can be accessed in group 1 of match. |
| final replaceGroupRegexp = RegExp(r'\$([0-9])'); |
| |
| /// Match/rename using [regExp]. |
| class RegExpRenamer { |
| final RegExp regExp; |
| final String replacementPattern; |
| |
| RegExpRenamer(this.regExp, this.replacementPattern); |
| |
| /// Returns true if [str] has a full match with [regExp]. |
| bool matches(String str) => quiver.matchesFull(regExp, str); |
| |
| /// Renames [str] according to [replacementPattern]. |
| /// |
| /// Returns [str] if [regExp] doesn't have a full match. |
| String rename(String str) { |
| if (matches(str)) { |
| // Get match. |
| final regExpMatch = regExp.firstMatch(str); |
| |
| /// Get group values. |
| /// E.g for `str`: `clang_dispose` and `regExp`: `clang_(.*)` |
| /// groups will be `0`: `clang_disponse`, `1`: `dispose`. |
| final groups = regExpMatch.groups( |
| List.generate(regExpMatch.groupCount, (index) => index) + |
| [regExpMatch.groupCount]); |
| |
| /// Replace all `$<int>` symbols with respective groups (if any). |
| final result = |
| replacementPattern.replaceAllMapped(replaceGroupRegexp, (match) { |
| final groupInt = int.parse(match.group(1)); |
| return groups[groupInt]; |
| }); |
| return result; |
| } else { |
| return str; |
| } |
| } |
| |
| @override |
| String toString() { |
| return 'Regexp: $regExp, ReplacementPattern: $replacementPattern'; |
| } |
| } |
| |
| /// Handles `include/exclude` logic for a declaration. |
| class Includer { |
| final List<RegExp> _includeMatchers; |
| final Set<String> _includeFull; |
| final List<RegExp> _excludeMatchers; |
| final Set<String> _excludeFull; |
| |
| Includer({ |
| List<RegExp> includeMatchers, |
| Set<String> includeFull, |
| List<RegExp> excludeMatchers, |
| Set<String> excludeFull, |
| }) : _includeMatchers = includeMatchers ?? [], |
| _includeFull = includeFull ?? {}, |
| _excludeMatchers = excludeMatchers ?? [], |
| _excludeFull = excludeFull ?? {}; |
| |
| /// Returns true if [name] is allowed. |
| /// |
| /// Exclude overrides include. |
| bool shouldInclude(String name) { |
| if (_excludeFull.contains(name)) { |
| return false; |
| } |
| |
| for (final em in _excludeMatchers) { |
| if (quiver.matchesFull(em, name)) { |
| return false; |
| } |
| } |
| |
| if (_includeFull.contains(name)) { |
| return true; |
| } |
| |
| for (final im in _includeMatchers) { |
| if (quiver.matchesFull(im, name)) { |
| return true; |
| } |
| } |
| |
| // If user has provided 'include' field in the filter, then default |
| // matching is false. |
| if (_includeMatchers.isNotEmpty || _includeFull.isNotEmpty) { |
| return false; |
| } else { |
| return true; |
| } |
| } |
| } |
| |
| /// Handles `full/regexp` renaming logic. |
| class Renamer { |
| final Map<String, String> _renameFull; |
| final List<RegExpRenamer> _renameMatchers; |
| |
| Renamer({ |
| List<RegExpRenamer> renamePatterns, |
| Map<String, String> renameFull, |
| }) : _renameMatchers = renamePatterns ?? [], |
| _renameFull = renameFull ?? {}; |
| |
| Renamer.noRename() |
| : _renameMatchers = [], |
| _renameFull = {}; |
| |
| String rename(String name) { |
| // Apply full rename (if any). |
| if (_renameFull.containsKey(name)) { |
| return _renameFull[name]; |
| } |
| |
| // Apply rename regexp (if matches). |
| for (final renamer in _renameMatchers) { |
| if (renamer.matches(name)) { |
| return renamer.rename(name); |
| } |
| } |
| |
| // No renaming is provided for this declaration, return unchanged. |
| return name; |
| } |
| } |
| |
| /// Match declaration name using [declarationRegExp]. |
| class RegExpMemberRenamer { |
| final RegExp declarationRegExp; |
| final Renamer memberRenamer; |
| |
| RegExpMemberRenamer(this.declarationRegExp, this.memberRenamer); |
| |
| /// Returns true if [declaration] has a full match with [regExp]. |
| bool matchesDeclarationName(String declaration) => |
| quiver.matchesFull(declarationRegExp, declaration); |
| |
| @override |
| String toString() { |
| return 'DeclarationRegExp: $declarationRegExp, MemberRenamer: $memberRenamer'; |
| } |
| } |
| |
| /// Handles `full/regexp` member renaming. |
| class MemberRenamer { |
| final Map<String, Renamer> _memberRenameFull; |
| final List<RegExpMemberRenamer> _memberRenameMatchers; |
| |
| final Map<String, Renamer> _cache = {}; |
| |
| MemberRenamer({ |
| Map<String, Renamer> memberRenameFull, |
| List<RegExpMemberRenamer> memberRenamePattern, |
| }) : _memberRenameFull = memberRenameFull ?? {}, |
| _memberRenameMatchers = memberRenamePattern ?? []; |
| |
| String rename(String declaration, String member) { |
| if (_cache.containsKey(declaration)) { |
| return _cache[declaration].rename(member); |
| } |
| |
| // Apply full rename (if any). |
| if (_memberRenameFull.containsKey(declaration)) { |
| // Add to cache. |
| _cache[declaration] = _memberRenameFull[declaration]; |
| return _cache[declaration].rename(member); |
| } |
| |
| // Apply rename regexp (if matches). |
| for (final renamer in _memberRenameMatchers) { |
| if (renamer.matchesDeclarationName(declaration)) { |
| // Add to cache. |
| _cache[declaration] = renamer.memberRenamer; |
| return _cache[declaration].rename(member); |
| } |
| } |
| |
| // No renaming is provided for this declaration, return unchanged. |
| return member; |
| } |
| } |