/* * Copyright (c) 2013, the Dart project authors. * * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.dart.engine.internal.task; import com.google.dart.engine.ast.CompilationUnit; import com.google.dart.engine.ast.Directive; import com.google.dart.engine.ast.StringLiteral; import com.google.dart.engine.ast.UriBasedDirective; import com.google.dart.engine.context.AnalysisContext; import com.google.dart.engine.context.AnalysisException; import com.google.dart.engine.element.LibraryElement; import com.google.dart.engine.error.AnalysisError; import com.google.dart.engine.error.AnalysisErrorListener; import com.google.dart.engine.error.CompileTimeErrorCode; import com.google.dart.engine.internal.context.InternalAnalysisContext; import com.google.dart.engine.internal.context.PerformanceStatistics; import com.google.dart.engine.internal.context.RecordingErrorListener; import com.google.dart.engine.internal.error.ErrorReporter; import com.google.dart.engine.internal.resolver.InheritanceManager; import com.google.dart.engine.internal.resolver.TypeProvider; import com.google.dart.engine.internal.verifier.ConstantVerifier; import com.google.dart.engine.internal.verifier.ErrorVerifier; import com.google.dart.engine.source.Source; import com.google.dart.engine.utilities.general.TimeCounter.TimeCounterHandle; /** * Instances of the class {@code GenerateDartErrorsTask} generate errors and warnings for a single * Dart source. */ public class GenerateDartErrorsTask extends AnalysisTask { /** * Check each directive in the given compilation unit to see if the referenced source exists and * report an error if it does not. * * @param context the context in which the library exists * @param librarySource the source representing the library containing the directives * @param unit the compilation unit containing the directives to be validated * @param errorListener the error listener to which errors should be reported */ public static void validateDirectives(AnalysisContext context, Source librarySource, CompilationUnit unit, AnalysisErrorListener errorListener) { for (Directive directive : unit.getDirectives()) { if (directive instanceof UriBasedDirective) { validateReferencedSource( context, librarySource, (UriBasedDirective) directive, errorListener); } } } /** * Check the given directive to see if the referenced source exists and report an error if it does * not. * * @param context the context in which the library exists * @param librarySource the source representing the library containing the directive * @param directive the directive to be verified * @param errorListener the error listener to which errors should be reported */ public static void validateReferencedSource(AnalysisContext context, Source librarySource, UriBasedDirective directive, AnalysisErrorListener errorListener) { Source source = directive.getSource(); if (source != null) { if (context.exists(source)) { return; } } else { // Don't report errors already reported by ParseDartTask#resolveDirective if (directive.validate() != null) { return; } } StringLiteral uriLiteral = directive.getUri(); errorListener.onError(new AnalysisError( librarySource, uriLiteral.getOffset(), uriLiteral.getLength(), CompileTimeErrorCode.URI_DOES_NOT_EXIST, directive.getUriContent())); } /** * The source for which errors and warnings are to be produced. */ private Source source; /** * The time at which the contents of the source were last modified. */ private long modificationTime; /** * The compilation unit used to resolve the dependencies. */ private CompilationUnit unit; /** * The element model for the library containing the source. */ private LibraryElement libraryElement; /** * The errors that were generated for the source. */ private AnalysisError[] errors; /** * Initialize a newly created task to perform analysis within the given context. * * @param context the context in which the task is to be performed * @param source the source for which errors and warnings are to be produced * @param modificationTime the time at which the contents of the source were last modified * @param unit the compilation unit used to resolve the dependencies * @param libraryElement the element model for the library containing the source */ public GenerateDartErrorsTask(InternalAnalysisContext context, Source source, long modificationTime, CompilationUnit unit, LibraryElement libraryElement) { super(context); this.source = source; this.modificationTime = modificationTime; this.unit = unit; this.libraryElement = libraryElement; } @Override public <E> E accept(AnalysisTaskVisitor<E> visitor) throws AnalysisException { return visitor.visitGenerateDartErrorsTask(this); } /** * Return the errors that were generated for the source. * * @return the errors that were generated for the source */ public AnalysisError[] getErrors() { return errors; } /** * Return the element model for the library containing the source. * * @return the element model for the library containing the source */ public LibraryElement getLibraryElement() { return libraryElement; } /** * Return the time at which the contents of the source that was verified were last modified, or a * negative value if the task has not yet been performed or if an exception occurred. * * @return the time at which the contents of the source that was verified were last modified */ public long getModificationTime() { return modificationTime; } /** * Return the source for which errors and warnings are to be produced. * * @return the source for which errors and warnings are to be produced */ public Source getSource() { return source; } @Override protected String getTaskDescription() { return "generate errors and warnings for " + source.getFullName(); } @Override protected void internalPerform() throws AnalysisException { TimeCounterHandle timeCounter = PerformanceStatistics.errors.start(); try { RecordingErrorListener errorListener = new RecordingErrorListener(); ErrorReporter errorReporter = new ErrorReporter(errorListener, source); TypeProvider typeProvider = getContext().getTypeProvider(); // // Validate the directives // validateDirectives(getContext(), source, unit, errorListener); // // Use the ConstantVerifier to verify the use of constants. This needs to happen before using // the ErrorVerifier because some error codes need the computed constant values. // ConstantVerifier constantVerifier = new ConstantVerifier( errorReporter, libraryElement, typeProvider); unit.accept(constantVerifier); // // Use the ErrorVerifier to compute the rest of the errors. // ErrorVerifier errorVerifier = new ErrorVerifier( errorReporter, libraryElement, typeProvider, new InheritanceManager(libraryElement)); unit.accept(errorVerifier); errors = errorListener.getErrorsForSource(source); } finally { timeCounter.stop(); } } }