OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2013, the Dart project authors. | |
3 * | |
4 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u se this file except | |
5 * in compliance with the License. You may obtain a copy of the License at | |
6 * | |
7 * http://www.eclipse.org/legal/epl-v10.html | |
8 * | |
9 * Unless required by applicable law or agreed to in writing, software distribut ed under the License | |
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K IND, either express | |
11 * or implied. See the License for the specific language governing permissions a nd limitations under | |
12 * the License. | |
13 */ | |
14 package com.google.dart.engine.internal.verifier; | |
15 | |
16 import com.google.dart.engine.ast.CompilationUnit; | |
17 import com.google.dart.engine.ast.ImportDirective; | |
18 import com.google.dart.engine.ast.StringLiteral; | |
19 import com.google.dart.engine.ast.visitor.RecursiveASTVisitor; | |
20 import com.google.dart.engine.element.CompilationUnitElement; | |
21 import com.google.dart.engine.error.PubSuggestionCode; | |
22 import com.google.dart.engine.internal.error.ErrorReporter; | |
23 import com.google.dart.engine.source.Source; | |
24 | |
25 import java.io.File; | |
26 | |
27 /** | |
28 * Instances of the class {@code PubVerifier} traverse an AST structure looking for deviations from | |
29 * pub best practices. | |
30 */ | |
31 public class PubVerifier extends RecursiveASTVisitor<Void> { | |
32 | |
33 /** | |
34 * The error reporter by which errors will be reported. | |
35 */ | |
36 private final ErrorReporter errorReporter; | |
37 | |
38 public PubVerifier(ErrorReporter errorReporter) { | |
39 this.errorReporter = errorReporter; | |
40 } | |
41 | |
42 @Override | |
43 public Void visitImportDirective(ImportDirective directive) { | |
44 | |
45 // Don't bother showing a suggestion if there is a more important issue to b e solved. | |
46 StringLiteral uriLiteral = directive.getUri(); | |
47 if (uriLiteral == null) { | |
48 return null; | |
49 } | |
50 String uriContent = uriLiteral.getStringValue(); | |
51 if (uriContent == null) { | |
52 return null; | |
53 } | |
54 uriContent = uriContent.trim(); | |
55 | |
56 // Analyze the URI | |
57 int index = uriContent.indexOf(':'); | |
58 String scheme; | |
59 String path; | |
60 if (index > -1) { | |
61 scheme = uriContent.substring(0, index); | |
62 path = uriContent.substring(index + 1); | |
63 } else { | |
64 scheme = "file"; | |
Brian Wilkerson
2013/05/31 15:28:58
Consider using FileUriResolver.FILE_SCHEME (yes, w
danrubel
2013/05/31 19:43:45
Done.
| |
65 path = uriContent; | |
66 } | |
67 | |
68 if (scheme.equals("file")) { | |
69 verifyFilePath(directive, uriLiteral, path); | |
70 } else if (scheme.equals("package")) { | |
Brian Wilkerson
2013/05/31 15:28:58
Ditto with PackageUriResolver fields and methods.
danrubel
2013/05/31 19:43:45
Done.
| |
71 verifyPackagePath(uriLiteral, path); | |
72 } | |
73 return null; | |
74 } | |
75 | |
76 /** | |
77 * Verify that the file import follows best practices. | |
78 * | |
79 * @param directive | |
Brian Wilkerson
2013/05/31 15:28:58
nit: incomplete comment
danrubel
2013/05/31 19:43:45
Done.
| |
80 * @param uriLiteral the node being analyzed (not {@code null}) | |
81 * @param path the file path extracted from the uriLiteral | |
82 */ | |
83 private void verifyFilePath(ImportDirective directive, StringLiteral uriLitera l, String path) { | |
Brian Wilkerson
2013/05/31 15:28:58
nit: The convention in ErrorVerifier is for the pr
danrubel
2013/05/31 19:43:45
Done.
| |
84 CompilationUnit unit = directive.getAncestor(CompilationUnit.class); | |
85 if (unit == null) { | |
86 return; | |
87 } | |
88 CompilationUnitElement element = unit.getElement(); | |
89 if (element == null) { | |
90 return; | |
91 } | |
92 Source librarySource = element.getSource(); | |
93 if (librarySource == null) { | |
94 return; | |
95 } | |
96 String fullName = librarySource.getFullName(); | |
97 if (fullName == null) { | |
98 return; | |
99 } | |
100 fullName = fullName.replace(File.separatorChar, '/'); | |
101 if (path.startsWith("lib/") || path.contains("/lib/")) { | |
102 if (!fullName.contains("/lib/")) { | |
103 // Files outside the lib directory hierarchy should not reference files inside | |
104 // ... use package: url instead | |
105 errorReporter.reportError( | |
106 PubSuggestionCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE, | |
107 uriLiteral); | |
108 } | |
109 } else { | |
110 int pathIndex = 0; | |
111 int fullNameIndex = fullName.length(); | |
112 while (pathIndex < path.length() && path.substring(pathIndex).startsWith(" ../")) { | |
Brian Wilkerson
2013/05/31 15:28:58
It would be more efficient to replace "path.substr
danrubel
2013/05/31 19:43:45
Good suggestion! Done.
| |
113 fullNameIndex = fullName.lastIndexOf('/', fullNameIndex); | |
114 if (fullNameIndex == -1) { | |
115 return; | |
116 } | |
117 if (fullName.substring(0, fullNameIndex).endsWith("/lib")) { | |
Brian Wilkerson
2013/05/31 15:28:58
It isn't as clear, but would be more efficient the
danrubel
2013/05/31 19:43:45
Yes. Thanks!
| |
118 // Files inside the lib directory hierarchy should not reference files outside | |
119 errorReporter.reportError( | |
120 PubSuggestionCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE, | |
121 uriLiteral); | |
122 } | |
123 pathIndex += 3; | |
124 } | |
125 } | |
126 } | |
127 | |
128 private void verifyPackagePath(StringLiteral uriLiteral, String path) { | |
129 if (path.contains("/../")) { | |
130 // Package import should not to contain ".." | |
131 errorReporter.reportError(PubSuggestionCode.PACKAGE_IMPORT_CONTAINS_DOT_DO T, uriLiteral); | |
132 } | |
133 } | |
134 } | |
OLD | NEW |