Index: pkg/analyzer/lib/src/lint/config.dart |
diff --git a/pkg/analyzer/lib/src/lint/config.dart b/pkg/analyzer/lib/src/lint/config.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f33b3f3392b77e7e7cc99efc55c936e322aa360e |
--- /dev/null |
+++ b/pkg/analyzer/lib/src/lint/config.dart |
@@ -0,0 +1,243 @@ |
+// 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 'package:yaml/yaml.dart'; |
+ |
+/** |
+ * Parse the given map into a lint config. |
+ */ |
+LintConfig parseConfig(Map optionsMap) { |
+ if (optionsMap != null) { |
+ var options = optionsMap['linter']; |
+ // Quick check of basic contract. |
+ if (options is Map) { |
+ return new LintConfig.parseMap(options); |
+ } |
+ } |
+ return null; |
+} |
+ |
+/** |
+ * Process the given option [fileContents] and produce a corresponding |
+ * [LintConfig]. |
+ */ |
+LintConfig processAnalysisOptionsFile(String fileContents, {String fileUrl}) { |
+ var yaml = loadYamlNode(fileContents, sourceUrl: fileUrl); |
+ if (yaml is YamlMap) { |
+ return parseConfig(yaml); |
+ } |
+ return null; |
+} |
+ |
+/** |
+ * The configuration of lint rules within an analysis options file. |
+ */ |
+abstract class LintConfig { |
+ factory LintConfig.parse(String source, {String sourceUrl}) => |
+ new _LintConfig().._parse(source, sourceUrl: sourceUrl); |
+ |
+ factory LintConfig.parseMap(Map map) => new _LintConfig().._parseMap(map); |
+ |
+ List<String> get fileExcludes; |
+ List<String> get fileIncludes; |
+ List<RuleConfig> get ruleConfigs; |
+} |
+ |
+/** |
+ * The configuration of a single lint rule within an analysis options file. |
+ */ |
+abstract class RuleConfig { |
+ Map<String, dynamic> args = <String, dynamic>{}; |
+ String get group; |
+ String get name; |
+ |
+ // Provisional |
+ bool disables(String ruleName) => |
+ ruleName == name && args['enabled'] == false; |
+ |
+ bool enables(String ruleName) => ruleName == name && args['enabled'] == true; |
+} |
+ |
+class _LintConfig implements LintConfig { |
+ @override |
+ final fileIncludes = <String>[]; |
+ @override |
+ final fileExcludes = <String>[]; |
+ @override |
+ final ruleConfigs = <RuleConfig>[]; |
+ |
+ void addAsListOrString(value, List<String> list) { |
+ if (value is List) { |
+ value.forEach((v) => list.add(v)); |
+ } else if (value is String) { |
+ list.add(value); |
+ } |
+ } |
+ |
+ bool asBool(scalar) { |
+ if (scalar is bool) { |
+ return scalar; |
+ } |
+ if (scalar is String) { |
+ if (scalar == 'true') { |
+ return true; |
+ } |
+ if (scalar == 'false') { |
+ return false; |
+ } |
+ } |
+ return null; |
+ } |
+ |
+ String asString(scalar) { |
+ if (scalar is String) { |
+ return scalar; |
+ } |
+ return null; |
+ } |
+ |
+ Map<String, dynamic> parseArgs(args) { |
+ bool enabled = asBool(args); |
+ if (enabled != null) { |
+ return {'enabled': enabled}; |
+ } |
+ return null; |
+ } |
+ |
+ void _parse(String src, {String sourceUrl}) { |
+ var yaml = loadYamlNode(src, sourceUrl: sourceUrl); |
+ if (yaml is YamlMap) { |
+ _parseYaml(yaml); |
+ } |
+ } |
+ |
+ void _parseMap(Map options) { |
+ //TODO(pq): unify map parsing. |
+ if (options is YamlMap) { |
+ _parseYaml(options); |
+ } else { |
+ _parseRawMap(options); |
+ } |
+ } |
+ |
+ void _parseRawMap(Map options) { |
+ options.forEach((k, v) { |
+ if (k is! String) { |
+ return; |
+ } |
+ String key = k; |
+ switch (key) { |
+ case 'files': |
+ if (v is Map) { |
+ addAsListOrString(v['include'], fileIncludes); |
+ addAsListOrString(v['exclude'], fileExcludes); |
+ } |
+ break; |
+ |
+ case 'rules': |
+ // - unnecessary_getters |
+ // - camel_case_types |
+ if (v is List) { |
+ v.forEach((rule) { |
+ var config = new _RuleConfig(); |
+ config.name = asString(rule); |
+ config.args = {'enabled': true}; |
+ ruleConfigs.add(config); |
+ }); |
+ } |
+ |
+ // {unnecessary_getters: false, camel_case_types: true} |
+ if (v is Map) { |
+ v.forEach((key, value) { |
+ // style_guide: {unnecessary_getters: false, camel_case_types: true} |
+ if (value is Map) { |
+ value.forEach((rule, args) { |
+ // unnecessary_getters: false |
+ var config = new _RuleConfig(); |
+ config.group = key; |
+ config.name = asString(rule); |
+ config.args = parseArgs(args); |
+ ruleConfigs.add(config); |
+ }); |
+ } else { |
+ //{unnecessary_getters: false} |
+ value = asBool(value); |
+ if (value != null) { |
+ var config = new _RuleConfig(); |
+ config.name = asString(key); |
+ config.args = {'enabled': value}; |
+ ruleConfigs.add(config); |
+ } |
+ } |
+ }); |
+ } |
+ break; |
+ } |
+ }); |
+ } |
+ |
+ void _parseYaml(YamlMap yaml) { |
+ yaml.nodes.forEach((k, v) { |
+ if (k is! YamlScalar) { |
+ return; |
+ } |
+ YamlScalar key = k; |
+ switch (key.toString()) { |
+ case 'files': |
+ if (v is YamlMap) { |
+ addAsListOrString(v['include'], fileIncludes); |
+ addAsListOrString(v['exclude'], fileExcludes); |
+ } |
+ break; |
+ |
+ case 'rules': |
+ |
+ // - unnecessary_getters |
+ // - camel_case_types |
+ if (v is List) { |
+ (v as List).forEach((rule) { |
+ var config = new _RuleConfig(); |
+ config.name = asString(rule); |
+ config.args = {'enabled': true}; |
+ ruleConfigs.add(config); |
+ }); |
+ } |
+ |
+ // style_guide: {unnecessary_getters: false, camel_case_types: true} |
+ if (v is YamlMap) { |
+ v.forEach((key, value) { |
+ //{unnecessary_getters: false} |
+ if (value is bool) { |
+ var config = new _RuleConfig(); |
+ config.name = asString(key); |
+ config.args = {'enabled': value}; |
+ ruleConfigs.add(config); |
+ } |
+ |
+ // style_guide: {unnecessary_getters: false, camel_case_types: true} |
+ if (value is YamlMap) { |
+ value.forEach((rule, args) { |
+ // TODO: verify format |
+ // unnecessary_getters: false |
+ var config = new _RuleConfig(); |
+ config.group = key; |
+ config.name = asString(rule); |
+ config.args = parseArgs(args); |
+ ruleConfigs.add(config); |
+ }); |
+ } |
+ }); |
+ } |
+ break; |
+ } |
+ }); |
+ } |
+} |
+ |
+class _RuleConfig extends RuleConfig { |
+ @override |
+ String group; |
+ @override |
+ String name; |
+} |