Chromium Code Reviews| 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 |