/**
  * Build the HTML element for the given source.
  *
  * @param source the source describing the compilation unit
  * @param unit the AST structure representing the HTML
  * @throws AnalysisException if the analysis could not be performed
  */
 public HtmlElementImpl buildHtmlElement(Source source, HtmlUnit unit) throws AnalysisException {
   HtmlElementImpl result = new HtmlElementImpl(context, source.getShortName());
   result.setSource(source);
   htmlElement = result;
   unit.accept(this);
   htmlElement = null;
   unit.setElement(result);
   return result;
 }
 private void validate(HtmlElementImpl element, ExpectedScript... expectedScripts) {
   assertSame(context, element.getContext());
   HtmlScriptElement[] scripts = element.getScripts();
   assertNotNull(scripts);
   assertLength(expectedScripts.length, scripts);
   for (int scriptIndex = 0; scriptIndex < scripts.length; scriptIndex++) {
     expectedScripts[scriptIndex].validate(scriptIndex, scripts[scriptIndex]);
   }
 }
 @Override
 public Void visitHtmlUnit(HtmlUnit node) {
   scripts = new ArrayList<HtmlScriptElement>();
   node.visitChildren(this);
   htmlElement.setScripts(scripts.toArray(new HtmlScriptElement[scripts.size()]));
   scripts = null;
   return null;
 }
  @Override
  public Void visitXmlTagNode(XmlTagNode node) {
    if (isScriptNode(node)) {
      Source htmlSource = htmlElement.getSource();
      String scriptSourcePath = getScriptSourcePath(node);
      if (node.getAttributeEnd().getType() == TokenType.GT && scriptSourcePath == null) {
        EmbeddedHtmlScriptElementImpl script = new EmbeddedHtmlScriptElementImpl(node);
        String contents = node.getContent();

        // TODO (danrubel): Move scanning embedded scripts into AnalysisContextImpl
        // so that clients such as builder can scan, parse, and get errors without resolving
        AnalysisErrorListener errorListener =
            new AnalysisErrorListener() {
              @Override
              public void onError(AnalysisError error) {
                // TODO (danrubel): make errors accessible once this is moved into
                // AnalysisContextImpl
              }
            };
        StringScanner scanner = new StringScanner(null, contents, errorListener);
        com.google.dart.engine.scanner.Token firstToken = scanner.tokenize();
        int[] lineStarts = scanner.getLineStarts();

        // TODO (danrubel): Move parsing embedded scripts into AnalysisContextImpl
        // so that clients such as builder can scan, parse, and get errors without resolving
        Parser parser = new Parser(null, errorListener);
        CompilationUnit unit = parser.parseCompilationUnit(firstToken);

        try {
          CompilationUnitBuilder builder = new CompilationUnitBuilder();
          CompilationUnitElementImpl elem = builder.buildCompilationUnit(htmlSource, unit);
          LibraryElementImpl library = new LibraryElementImpl(context, null);
          library.setDefiningCompilationUnit(elem);
          script.setScriptLibrary(library);
        } catch (AnalysisException e) {
          // TODO (danrubel): Handle or forward the exception
          e.printStackTrace();
        }

        scripts.add(script);
      } else {
        ExternalHtmlScriptElementImpl script = new ExternalHtmlScriptElementImpl(node);
        if (scriptSourcePath != null) {
          script.setScriptSource(
              context.getSourceFactory().resolveUri(htmlSource, scriptSourcePath));
        }
        scripts.add(script);
      }
    } else {
      node.visitChildren(this);
    }
    return null;
  }