OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library name_validator; | |
6 | |
7 import 'dart:async'; | |
8 import 'dart:io'; | |
9 | |
10 import 'package:pathos/path.dart' as path; | |
11 | |
12 import '../entrypoint.dart'; | |
13 import '../io.dart'; | |
14 import '../utils.dart'; | |
15 import '../validator.dart'; | |
16 | |
17 /// Dart reserved words, from the Dart spec. | |
18 final _RESERVED_WORDS = [ | |
19 "assert", "break", "case", "catch", "class", "const", "continue", "default", | |
20 "do", "else", "extends", "false", "final", "finally", "for", "if", "in", "is", | |
21 "new", "null", "return", "super", "switch", "this", "throw", "true", "try", | |
22 "var", "void", "while", "with" | |
23 ]; | |
24 | |
25 /// A validator that validates the name of the package and its libraries. | |
26 class NameValidator extends Validator { | |
27 NameValidator(Entrypoint entrypoint) | |
28 : super(entrypoint); | |
29 | |
30 Future validate() { | |
31 return new Future.sync(() { | |
32 _checkName(entrypoint.root.name, 'Package name "${entrypoint.root.name}"', | |
33 isPackage: true); | |
34 | |
35 var libraries = _libraries; | |
36 for (var library in libraries) { | |
37 var libName = path.basenameWithoutExtension(library); | |
38 _checkName(libName, 'The name of "$library", "$libName",', | |
39 isPackage: false); | |
40 } | |
41 | |
42 if (libraries.length == 1) { | |
43 var libName = path.basenameWithoutExtension(libraries[0]); | |
44 if (libName == entrypoint.root.name) return; | |
45 warnings.add('The name of "${libraries[0]}", "$libName", should match ' | |
46 'the name of the package, "${entrypoint.root.name}".\n' | |
47 'This helps users know what library to import.'); | |
48 } | |
49 }); | |
50 } | |
51 | |
52 /// Returns a list of all libraries in the current package as paths relative | |
53 /// to the package's root directory. | |
54 List<String> get _libraries { | |
55 var libDir = path.join(entrypoint.root.dir, "lib"); | |
56 if (!dirExists(libDir)) return []; | |
57 return listDir(libDir, recursive: true) | |
58 .map((file) => path.relative(file, from: path.dirname(libDir))) | |
59 .where((file) => !path.split(file).contains("src") && | |
60 path.extension(file) == '.dart') | |
61 .toList(); | |
62 } | |
63 | |
64 void _checkName(String name, String description, {bool isPackage}) { | |
65 // Packages names are more stringent than libraries. | |
66 var messages = isPackage ? errors : warnings; | |
67 | |
68 if (name == "") { | |
69 errors.add("$description may not be empty."); | |
70 } else if (!new RegExp(r"^[a-zA-Z0-9_]*$").hasMatch(name)) { | |
71 messages.add("$description may only contain letters, numbers, and " | |
72 "underscores.\n" | |
73 "Using a valid Dart identifier makes the name usable in Dart code."); | |
74 } else if (!new RegExp(r"^[a-zA-Z]").hasMatch(name)) { | |
75 messages.add("$description must begin with letter.\n" | |
76 "Using a valid Dart identifier makes the name usable in Dart code."); | |
77 } else if (_RESERVED_WORDS.contains(name.toLowerCase())) { | |
78 messages.add("$description may not be a reserved word in Dart.\n" | |
79 "Using a valid Dart identifier makes the name usable in Dart code."); | |
80 } else if (new RegExp(r"[A-Z]").hasMatch(name)) { | |
81 warnings.add('$description should be lower-case. Maybe use ' | |
82 '"${_unCamelCase(name)}"?'); | |
83 } | |
84 } | |
85 | |
86 String _unCamelCase(String source) { | |
87 var builder = new StringBuffer(); | |
88 var lastMatchEnd = 0; | |
89 for (var match in new RegExp(r"[a-z]([A-Z])").allMatches(source)) { | |
90 builder | |
91 ..write(source.substring(lastMatchEnd, match.start + 1)) | |
92 ..write("_") | |
93 ..write(match.group(1).toLowerCase()); | |
94 lastMatchEnd = match.end; | |
95 } | |
96 builder.write(source.substring(lastMatchEnd)); | |
97 return builder.toString().toLowerCase(); | |
98 } | |
99 } | |
OLD | NEW |