.lib" protocol.
+ */
+public class SystemLibrary {
+
+ private final String shortName;
+ private final String host;
+ private final String pathToLib;
+ private final File dirOrZip;
+
+ /**
+ * Define a new system library such that dart:[shortLibName] will automatically be expanded to
+ * dart://[host]/[pathToLib]. For example this call
+ *
+ *
+ * new SystemLibrary("dom.lib", "dom", "dart_dom.lib");
+ *
+ *
+ * will define a new system library such that "dart:dom.lib" to automatically be expanded to
+ * "dart://dom/dart_dom.lib". The dirOrZip argument is either the root directory or a zip file
+ * containing all files for this library.
+ */
+ public SystemLibrary(String shortName, String host, String pathToLib, File dirOrZip) {
+ this.shortName = shortName;
+ this.host = host;
+ this.pathToLib = pathToLib;
+ this.dirOrZip = dirOrZip;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public String getPathToLib() {
+ return pathToLib;
+ }
+
+ public String getShortName() {
+ return shortName;
+ }
+
+ public URI translateUri(URI dartUri) {
+ if (!dirOrZip.exists()) {
+ throw new RuntimeException("System library for " + dartUri + " does not exist: " + dirOrZip.getPath());
+ }
+ String spec = "file:" + dirOrZip.getPath();
+ if (dirOrZip.isFile()) {
+ spec = "jar:" + spec + "!";
+ }
+ try {
+ return new URI(spec + dartUri.getPath());
+ } catch (URISyntaxException e) {
+ throw new AssertionError();
+ }
+ }
+
+ public File getFile() {
+ return this.dirOrZip;
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/SystemLibraryManager.java b/compiler/java/com/google/dart/compiler/SystemLibraryManager.java
new file mode 100644
index 00000000000..5b53048df31
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/SystemLibraryManager.java
@@ -0,0 +1,314 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarFile;
+
+/**
+ * Manages the collection of {@link SystemLibrary}s.
+ */
+public class SystemLibraryManager {
+ private enum SystemLibraryPath {
+ CORE("core", "core", "com/google/dart/corelib/", "corelib.dart", "corelib.jar", true),
+ COREIMPL("core", "coreimpl", "com/google/dart/corelib/", "corelib_impl.dart", "corelib.jar",
+ CORE, true),
+ DOM("dom", "dom", "dom/", "dom.dart", "domlib.jar"),
+ HTML("html", "html", "html/", "html.dart", "htmllib.jar"),
+ JSON("json", "json", "json/", "json.dart", "jsonlib.jar");
+
+ final String hostName;
+ final SystemLibraryPath base;
+ final String shortName;
+ final String jar;
+ final String lib;
+ final boolean failIfMissing;
+
+ SystemLibraryPath(String hostName, String shortName, String path, String file, String jar,
+ boolean failIfMissing) {
+ this(hostName, shortName, path, file, jar, null, failIfMissing);
+ }
+
+ SystemLibraryPath(String hostName, String shortName, String path, String file, String jar) {
+ this(hostName, shortName, path, file, jar, null, false);
+ }
+
+ SystemLibraryPath(String hostName, String shortName, String path, String file, String jar,
+ SystemLibraryPath base, boolean failIfMissing) {
+ this.hostName = hostName;
+ this.shortName = shortName;
+ this.jar = jar;
+ this.lib = path + file;
+ this.base = base;
+ this.failIfMissing = failIfMissing;
+ }
+ }
+
+ private static final String DART_SCHEME = "dart";
+ private static final String DART_SCHEME_SPEC = "dart:";
+
+ // executionFile is used to search for loose files on disk when the system libraries
+ // are not on the classpath (e.g. Eclipse)
+ private static final File executionFile = new File(SystemLibraryManager.class
+ .getProtectionDomain().getCodeSource().getLocation().getPath());
+
+ private HashMap expansionMap;
+ private Map hostMap;
+
+ private SystemLibrary[] libraries;
+
+ public SystemLibraryManager() {
+ setLibraries(getDefaultLibraries());
+ }
+
+ /**
+ * Expand a relative or short URI (e.g. "dart:dom") which is implementation independent to its
+ * full URI (e.g. "dart://dom/com/google/dart/domlib/dom.dart") and then translate that URI to
+ * either a "file:" or "jar:" URI (e.g.
+ * "jar:file:/some/install/director/dom.jar!/com/google/dart/domlib/dom.dart").
+ *
+ * @param uri the original URI
+ * @return the expanded and translated URI, which may be null and may not exist
+ * @exception RuntimeException if the URI is a "dart" scheme, but does not map to a defined system
+ * library
+ */
+ public URI resolveDartUri(URI uri) {
+ return translateDartUri(expandRelativeDartUri(uri));
+ }
+
+ /**
+ * Translate the URI from dart://[host]/[pathToLib] (e.g. dart://dom/dom.dart)
+ * to either a "file:" or "jar:" URI (e.g. "jar:file:/some/install/director/dom.jar!/dom.dart")
+ *
+ * @param uri the original URI
+ * @return the translated URI, which may be null and may not exist
+ * @exception RuntimeException if the URI is a "dart" scheme,
+ * but does not map to a defined system library
+ */
+ public URI translateDartUri(URI uri) {
+ if (isDartUri(uri)) {
+ String host = uri.getHost();
+ SystemLibrary library = hostMap.get(host);
+ if (library == null) {
+ throw new RuntimeException("No system library defined for " + uri);
+ }
+ return library.translateUri(uri);
+ }
+
+ return uri;
+ }
+
+ /**
+ * Expand a relative or short URI (e.g. "dart:dom") which is implementation independent
+ * to its full URI (e.g. "dart://dom/com/google/dart/domlib/dom.dart")
+ *
+ * @param uri the relative URI
+ * @return the expanded URI or the original URI if it could not be expanded
+ * @exception RuntimeException if the short URI is of the form "dart:"
+ * but does not correspond to a system library
+ */
+ public URI expandRelativeDartUri(URI uri) throws AssertionError {
+ if (isDartUri(uri)) {
+ String host = uri.getHost();
+ if (host == null) {
+ String spec = uri.getSchemeSpecificPart();
+ String replacement = expansionMap.get(spec);
+ if (replacement != null) {
+ try {
+ uri = new URI(DART_SCHEME + ":" + replacement);
+ } catch (URISyntaxException e) {
+ throw new AssertionError();
+ }
+ } else {
+ throw new RuntimeException("Don't know how to expand dart URI: " + uri);
+ }
+ }
+ }
+ return uri;
+ }
+
+ /**
+ * Answer true if the specified URI has a "dart" scheme
+ */
+ public static boolean isDartUri(URI uri) {
+ return uri != null && DART_SCHEME.equals(uri.getScheme());
+ }
+
+ /**
+ * Answer true if the string is a dart spec
+ */
+ public static boolean isDartSpec(String spec) {
+ return spec != null && spec.startsWith(DART_SCHEME_SPEC);
+ }
+
+ /**
+ * Register system libraries for the "dart:" protocol such that dart:[shortLibName] (e.g.
+ * "dart:dom") will automatically be expanded to dart://[host]/[pathToLib] (e.g.
+ * dart://dom/dom.dart)
+ */
+ private void setLibraries(SystemLibrary[] newLibraries) {
+ libraries = newLibraries;
+ hostMap = new HashMap();
+ expansionMap = new HashMap();
+ for (SystemLibrary library : libraries) {
+ hostMap.put(library.getHost(), library);
+ expansionMap.put(library.getShortName(),
+ "//" + library.getHost() + "/" + library.getPathToLib());
+ }
+ }
+
+ private File getResource(String name, boolean failOnMissing) {
+ URL baseUrl = SystemLibraryManager.class.getClassLoader().getResource(name);
+ if (baseUrl == null) {
+ if (!failOnMissing) {
+ return null;
+ }
+ throw new RuntimeException("Failed to find the system library: " + name);
+ }
+ return resolveResource(baseUrl, name);
+ }
+
+ static private File resolveResource(URL baseUrl, String name) {
+ if (baseUrl == null) {
+ return null;
+ }
+ File coreDirOrZip = null;
+ String protocol = baseUrl.getProtocol();
+ String path = baseUrl.getPath();
+ if ("file".equals(protocol)) {
+ coreDirOrZip = new File(path.substring(0, path.lastIndexOf(name)));
+ } else if ("jar".equals(protocol)) {
+ // jar:file://www.foo.com/bar/baz.jar!/com/google/some.class
+ if (path.startsWith("file:")) {
+ int index = path.indexOf('!');
+ coreDirOrZip = new File(path.substring(5, index > 0 ? index : path.length()));
+ }
+ }
+ if (coreDirOrZip == null) {
+ throw new RuntimeException("Failed to find system library in " + baseUrl);
+ }
+ if (!coreDirOrZip.exists()) {
+ throw new RuntimeException("System library container does not exist " + coreDirOrZip
+ + "\n from " + baseUrl);
+ }
+ return coreDirOrZip;
+ }
+
+ private File searchForResource(String searchPath, String libraryName, boolean failOnMissing) {
+ URL urlPath = null;
+ File sourcePath = new File(searchPath);
+
+ /* The source can be a directory or a jar file. Search both for our library. */
+ if (sourcePath.isDirectory()) {
+ File foundLibrary = new File(sourcePath.getPath() + File.separator + libraryName);
+ if (!foundLibrary.exists()) {
+ if (failOnMissing) {
+ throw new RuntimeException("Failed to find system library " + libraryName + " with "
+ + sourcePath.toString());
+ }
+ return null;
+ }
+ try {
+ urlPath = foundLibrary.toURI().toURL();
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+ } else if (sourcePath.isFile() && sourcePath.toString().endsWith(".jar")) {
+ // Support for jar only right now...
+ JarFile jarFile = null;
+ try {
+ jarFile = new JarFile(sourcePath);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ if (null != jarFile.getJarEntry(libraryName)) {
+ String path = "jar:file:" + sourcePath.getPath() + "!/" + libraryName;
+ try {
+ urlPath = new URL(path);
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+ } else {
+ if (failOnMissing) {
+ throw new RuntimeException("Failed to find system library " + libraryName + " with "
+ + sourcePath.getPath());
+ }
+ return null;
+ }
+ }
+
+ File foundLibrary = resolveResource(urlPath, libraryName);
+ if (foundLibrary == null && failOnMissing) {
+ throw new RuntimeException("Failed to find system library " + libraryName + " with "
+ + sourcePath.getPath());
+ }
+ return foundLibrary;
+ }
+
+ protected SystemLibrary locateSystemLibrary(SystemLibraryPath path) {
+ // First, check for jars on the class path
+ File libraryDirOrZip = getResource(path.lib, path.failIfMissing);
+
+ // TODO(codefu): This is a hack. To keep Eclipse happy and to find the
+ // sources, we hard code this path. In the future, when the libraries are
+ // all gathered into a common "lib/" path, we can search from there.
+ if (libraryDirOrZip == null) {
+ // Eclipse's executionPath should be a directory, unless a jar file was included.
+ String executionPath;
+ if (executionFile.isDirectory()) {
+ // Universal location of eclipse workspace to the dart source tree is
+ // 'dart/compiler/eclipse.workspace/dartc/output'
+ // and we need 'dart/client'
+ executionPath =
+ executionFile.getParent() + File.separator + ".." + File.separator + ".."
+ + File.separator + ".." + File.separator + "client";
+ } else {
+ executionPath = executionFile.getParent() + File.separator + path.jar;
+ }
+ libraryDirOrZip = searchForResource(executionPath, path.lib, false);
+ if (libraryDirOrZip == null && executionFile.isFile()) {
+ // Last ditch; are the artifacts just in a flat file...
+ libraryDirOrZip = searchForResource(executionFile.getParent(), path.lib, false);
+ }
+ }
+ if (libraryDirOrZip != null) {
+ return new SystemLibrary(path.shortName, path.hostName, path.lib,
+ libraryDirOrZip);
+ }
+ return null;
+ }
+
+ /**
+ * Answer the libraries that are built into the compiler jar
+ */
+ protected SystemLibrary[] getDefaultLibraries() {
+ ArrayList defaultLibraries = new ArrayList();
+ File[] baseFiles = new File[SystemLibraryPath.values().length];
+
+ for (SystemLibraryPath path : SystemLibraryPath.values()) {
+ if (path.base != null) {
+ defaultLibraries.add(new SystemLibrary(path.shortName, path.hostName, path.lib,
+ baseFiles[path.base.ordinal()]));
+ baseFiles[path.ordinal()] = baseFiles[path.base.ordinal()];
+ } else {
+ SystemLibrary library = locateSystemLibrary(path);
+ if (library != null) {
+ defaultLibraries.add(library);
+ baseFiles[path.ordinal()] = library.getFile();
+ }
+ }
+ }
+
+ return defaultLibraries.toArray(new SystemLibrary[defaultLibraries.size()]);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/UnitTestBatchRunner.java b/compiler/java/com/google/dart/compiler/UnitTestBatchRunner.java
new file mode 100644
index 00000000000..e8225f41715
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/UnitTestBatchRunner.java
@@ -0,0 +1,61 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+/**
+ * Provides a framework to read command line options from stdin and feed them to
+ * either the DartCompiler or TestRunner.
+ *
+ */
+public class UnitTestBatchRunner {
+
+ public interface Invocation {
+ public boolean invoke (String[] args) throws Throwable;
+ }
+
+ /**
+ * Run the tool in 'batch' mode, receiving command lines through stdin and returning
+ * pass/fail status through stdout. This feature is intended for use in unit testing.
+ *
+ * @param batchArgs command line arguments forwarded from main().
+ */
+ public static void runAsBatch(String[] batchArgs, Invocation toolInvocation) throws Throwable {
+ System.out.println(">>> BATCH START");
+
+ // Read command lines in from stdin and create a new compiler for each one.
+ BufferedReader cmdlineReader = new BufferedReader(new InputStreamReader(
+ System.in));
+ long startTime = System.currentTimeMillis();
+ int testsFailed = 0;
+ int totalTests = 0;
+ try {
+ String line;
+ for (; (line = cmdlineReader.readLine()) != null; totalTests++) {
+ long testStart = System.currentTimeMillis();
+ // TODO(zundel): These are shell script cmdlines: be smarter about
+ // quoted strings.
+ String[] args = line.trim().split("\\s+");
+ boolean result = toolInvocation.invoke(args);
+ if (!result) {
+ testsFailed++;
+ }
+ System.out.println(">>> TEST " + (result ? "PASS" : "FAIL") + " "
+ + (System.currentTimeMillis() - testStart) + "ms");
+ System.out.flush();
+ }
+ } catch (Throwable e) {
+ System.out.println(">>> TEST CRASH");
+ System.out.flush();
+ throw e;
+ }
+ long elapsed = System.currentTimeMillis() - startTime;
+ System.out.println(">>> BATCH END (" + (totalTests - testsFailed) + "/"
+ + totalTests + ") " + elapsed + "ms");
+ System.out.flush();
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/UrlDartSource.java b/compiler/java/com/google/dart/compiler/UrlDartSource.java
new file mode 100644
index 00000000000..8d0913b22b9
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/UrlDartSource.java
@@ -0,0 +1,54 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * A {@link DartSource} backed by a URL.
+ */
+public class UrlDartSource extends UrlSource implements DartSource {
+
+ private final LibrarySource lib;
+ private final String relPath;
+
+ protected UrlDartSource(URI uri, String relPath, LibrarySource lib, SystemLibraryManager slm) {
+ super(uri,slm);
+ this.relPath = relPath;
+ this.lib = lib;
+ }
+
+ protected UrlDartSource(URI uri, String relPath, LibrarySource lib) {
+ this(uri, relPath, lib, null);
+ }
+
+ public UrlDartSource(File file, LibrarySource lib) {
+ super(file);
+ this.relPath = file.getPath();
+ this.lib = lib;
+ }
+
+ @Override
+ public LibrarySource getLibrary() {
+ return lib;
+ }
+
+ @Override
+ public String getName() {
+ try {
+ String uriSafeName = new URI(null, null, relPath, null).toString();
+ return lib.getName() + File.separatorChar + uriSafeName;
+ } catch (URISyntaxException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @Override
+ public String getRelativePath() {
+ return relPath;
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/UrlLibrarySource.java b/compiler/java/com/google/dart/compiler/UrlLibrarySource.java
new file mode 100644
index 00000000000..ed973ea92d1
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/UrlLibrarySource.java
@@ -0,0 +1,48 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * A {@link LibrarySource} backed by a URL.
+ */
+public class UrlLibrarySource extends UrlSource implements LibrarySource {
+
+ public UrlLibrarySource(URI uri, SystemLibraryManager slm) {
+ super(uri, slm);
+ }
+
+ public UrlLibrarySource(URI uri) {
+ this(uri, null);
+ }
+
+ public UrlLibrarySource(File file) {
+ super(file);
+ }
+
+ @Override
+ public String getName() {
+ return getUri().toString();
+ }
+
+ @Override
+ public DartSource getSourceFor(final String relPath) {
+ try {
+ // Force the creation of an escaped relative URI to deal with spaces, etc.
+ URI uri = getAbsoluteUri().resolve(new URI(null, null, relPath, null)).normalize();
+ return new UrlDartSource(uri, relPath, this, systemLibraryManager);
+ } catch (URISyntaxException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @Override
+ public LibrarySource getImportFor(String relPath) {
+ return new UrlLibrarySource(getAbsoluteUri().resolve(relPath).normalize(), systemLibraryManager);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/UrlSource.java b/compiler/java/com/google/dart/compiler/UrlSource.java
new file mode 100644
index 00000000000..a59866f2837
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/UrlSource.java
@@ -0,0 +1,194 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.JarURLConnection;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.util.jar.JarEntry;
+
+/**
+ * A {@link Source} backed by a URL (or optionally by a file).
+ */
+public abstract class UrlSource implements Source {
+
+ private final static String FILE_PROTOCOL = "file";
+ private final static String JAR_PROTOCOL = "jar";
+ private final static URI CURRENT_DIR = new File(".").toURI().normalize();
+ private final static Charset UTF8 = Charset.forName("UTF8");
+ private final static URI BASE_URI = CURRENT_DIR;
+
+ private final URI uri;
+ private final URI absoluteUri;
+ private final URI translatedUri;
+ private final boolean shouldCareAboutLastModified;
+ private volatile boolean exists = false;
+ private volatile long lastModified = -1;
+ private volatile boolean propertiesInitialized = false;
+
+ // generally, one or the other of these will be non-null after properties are initialized
+ private volatile File sourceFile = null;
+ private volatile JarURLConnection jarConn = null;
+
+ protected final SystemLibraryManager systemLibraryManager;
+
+ protected UrlSource(URI uri) {
+ this(uri,null);
+ }
+
+ protected UrlSource(URI uri, SystemLibraryManager slm) {
+ URI expanded = slm != null ? slm.expandRelativeDartUri(uri) : uri;
+ this.uri = BASE_URI.relativize(expanded.normalize());
+ this.absoluteUri = BASE_URI.resolve(expanded);
+ this.systemLibraryManager = slm;
+ if (SystemLibraryManager.isDartUri(this.uri)) {
+ assert slm != null;
+ this.shouldCareAboutLastModified = false;
+ this.translatedUri = slm.resolveDartUri(this.absoluteUri);
+ } else {
+ this.shouldCareAboutLastModified = true;
+ this.translatedUri = this.absoluteUri;
+ }
+ }
+
+ protected UrlSource(File file) {
+ URI uri = file.toURI().normalize();
+ if (!file.exists()) {
+ // TODO(jgw): This is a bit ugly, but some of the test infrastructure depends upon
+ // non-existant relative files being looked up as classpath resources. This was
+ // previously embedded in DartSourceFile.getSourceReader().
+ URL url = getClass().getClassLoader().getResource(file.getPath());
+ if (url != null) {
+ uri = URI.create(url.toString());
+ }
+ }
+
+ this.uri = BASE_URI.relativize(uri);
+ this.translatedUri = this.absoluteUri = BASE_URI.resolve(uri);
+ this.systemLibraryManager = null;
+ this.shouldCareAboutLastModified = true;
+ }
+
+ @Override
+ public boolean exists() {
+ initProperties();
+ return exists;
+ }
+
+ @Override
+ public long getLastModified() {
+ if (!shouldCareAboutLastModified) {
+ return 0;
+ }
+ initProperties();
+ return lastModified;
+ }
+
+ @Override
+ public Reader getSourceReader() throws IOException {
+ initProperties();
+ if (sourceFile != null) {
+ return new FileReader(sourceFile);
+ } else if (jarConn != null) {
+ return new InputStreamReader(jarConn.getInputStream());
+ }
+ // fall back case
+ if (translatedUri != null) {
+ InputStream stream = translatedUri.toURL().openStream();
+ if (stream != null) {
+ return new InputStreamReader(stream, UTF8);
+ }
+ }
+ throw new FileNotFoundException(getName());
+ }
+
+ @Override
+ public URI getUri() {
+ return uri;
+ }
+
+ protected URI getAbsoluteUri() {
+ return absoluteUri;
+ }
+
+ private void initProperties() {
+ if (!propertiesInitialized) {
+ synchronized(this) {
+ if (!propertiesInitialized) {
+ try {
+ URI resolvedUri = BASE_URI.resolve(uri);
+ String scheme = resolvedUri.getScheme();
+ if (scheme == null || FILE_PROTOCOL.equals(scheme)) {
+ // Faster than using URLConnection
+ File file = new File(resolvedUri);
+ lastModified = file.lastModified();
+ exists = file.exists();
+ sourceFile = file;
+ } else {
+ try {
+ URL url = translatedUri.toURL();
+ if (JAR_PROTOCOL.equals(url.getProtocol())) {
+ getJarEntryProperties(url);
+ } else {
+ /*
+ * TODO(jbrosenberg): Flesh out the support for other
+ * protocols, like http, etc. Note, calling
+ * URLConnection.getLastModified() can be dangerous, some
+ * URLConnection sub-classes don't have a way to close a
+ * connection opened by this call. Return 0 for now.
+ */
+ lastModified = 0;
+ // Default this to true for now.
+ exists = true;
+ }
+ } catch (MalformedURLException e) {
+ return;
+ }
+ }
+ } finally {
+ propertiesInitialized = true;
+ }
+ }
+ }
+ }
+ }
+
+ private void getJarEntryProperties(URL url) {
+ try {
+ jarConn = (JarURLConnection) url.openConnection();
+ // useCaches is usually set to true by default, but make sure here
+ jarConn.setUseCaches(true);
+ // See if our entry exists
+ JarEntry jarEntry = jarConn.getJarEntry();
+ if (jarEntry != null) {
+ exists = true;
+ if (!shouldCareAboutLastModified) {
+ lastModified = 0;
+ return;
+ }
+ // TODO(jbrosenberg): Note the time field for a jarEntry can be
+ // unreliable, and is not always required in a jar file. Consider using
+ // the timestamp on the jar file itself.
+ lastModified = jarEntry.getTime();
+ }
+ if (!exists) {
+ lastModified = -1;
+ return;
+ }
+ } catch (IOException e) {
+ exists = false;
+ lastModified = -1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/compiler/java/com/google/dart/compiler/ast/DartArrayAccess.java b/compiler/java/com/google/dart/compiler/ast/DartArrayAccess.java
new file mode 100644
index 00000000000..75136f03410
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartArrayAccess.java
@@ -0,0 +1,65 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.resolver.Element;
+
+/**
+ * Represents a Dart array access expression (a[b]).
+ */
+public class DartArrayAccess extends DartExpression implements ElementReference {
+
+ private DartExpression target;
+ private DartExpression key;
+ private Element referencedElement;
+
+ public DartArrayAccess(DartExpression target, DartExpression key) {
+ this.target = becomeParentOf(target);
+ this.key = becomeParentOf(key);
+ }
+
+ @Override
+ public boolean isAssignable() {
+ return true;
+ }
+
+ public DartExpression getKey() {
+ return key;
+ }
+
+ public DartExpression getTarget() {
+ return target;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ target = becomeParentOf(v.accept(target));
+ key = becomeParentOf(v.accept(key));
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ target.accept(visitor);
+ key.accept(visitor);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitArrayAccess(this);
+ }
+
+ @Override
+ public Element getReferencedElement() {
+ return referencedElement;
+ }
+
+ @Override
+ public void setReferencedElement(Element element) {
+ referencedElement = element;
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartArrayLiteral.java b/compiler/java/com/google/dart/compiler/ast/DartArrayLiteral.java
new file mode 100644
index 00000000000..376e8ce40fa
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartArrayLiteral.java
@@ -0,0 +1,45 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import java.util.List;
+
+/**
+ * Represents a Dart array literal value.
+ */
+public class DartArrayLiteral extends DartTypedLiteral {
+
+ private final List expressions;
+
+ public DartArrayLiteral(boolean isConst, List typeArguments,
+ List expressions) {
+ super(isConst, typeArguments);
+ this.expressions = becomeParentOf(expressions);
+ }
+
+ public List getExpressions() {
+ return expressions;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ super.traverse(v, ctx);
+ v.acceptWithInsertRemove(this, expressions);
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ super.visitChildren(visitor);
+ visitor.visit(expressions);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitArrayLiteral(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartAssertion.java b/compiler/java/com/google/dart/compiler/ast/DartAssertion.java
new file mode 100644
index 00000000000..6b8622adb64
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartAssertion.java
@@ -0,0 +1,58 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Implements the "assert" statement.
+ */
+public class DartAssertion extends DartStatement {
+ private DartExpression expression;
+ private DartExpression message;
+
+ public DartAssertion(DartExpression expression, DartExpression message) {
+ this.expression = becomeParentOf(expression);
+ this.message = becomeParentOf(message);
+ }
+
+ public void setExpression(DartExpression expression) {
+ this.expression = expression;
+ }
+
+ public DartExpression getExpression() {
+ return expression;
+ }
+
+ public void setMessage(DartExpression message) {
+ this.message = message;
+ }
+
+ public DartExpression getMessage() {
+ return message;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ expression = becomeParentOf(v.accept(expression));
+ if (message != null) {
+ message = becomeParentOf(v.accept(message));
+ }
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ expression.accept(visitor);
+ if (message != null) {
+ message.accept(visitor);
+ }
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitAssertion(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartBinaryExpression.java b/compiler/java/com/google/dart/compiler/ast/DartBinaryExpression.java
new file mode 100644
index 00000000000..592ca63d051
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartBinaryExpression.java
@@ -0,0 +1,84 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.parser.Token;
+import com.google.dart.compiler.resolver.Element;
+
+/**
+ * Represents a Dart binary expression.
+ */
+public class DartBinaryExpression extends DartExpression implements ElementReference {
+
+ private final Token op;
+ private DartExpression arg1;
+ private DartExpression arg2;
+ private DartExpression normalizedNode = this;
+ private Element referencedElement;
+
+ public DartBinaryExpression(Token op, DartExpression arg1, DartExpression arg2) {
+ assert op.isBinaryOperator() : op;
+
+ this.op = op;
+ this.arg1 = becomeParentOf(arg1);
+ this.arg2 = becomeParentOf(arg2);
+ }
+
+ public DartExpression getArg1() {
+ return arg1;
+ }
+
+ public DartExpression getArg2() {
+ return arg2;
+ }
+
+ public Token getOperator() {
+ return op;
+ }
+
+ public void setNormalizedNode(DartExpression normalizedNode) {
+ normalizedNode.setSourceInfo(this);
+ this.normalizedNode = normalizedNode;
+ }
+
+ @Override
+ public DartExpression getNormalizedNode() {
+ return normalizedNode;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ if (op.isAssignmentOperator()) {
+ arg1 = becomeParentOf(v.acceptLvalue(arg1));
+ } else {
+ arg1 = becomeParentOf(v.accept(arg1));
+ }
+ arg2 = becomeParentOf(v.accept(arg2));
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ arg1.accept(visitor);
+ arg2.accept(visitor);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitBinaryExpression(this);
+ }
+
+ @Override
+ public Element getReferencedElement() {
+ return referencedElement;
+ }
+
+ @Override
+ public void setReferencedElement(Element referencedElement) {
+ this.referencedElement = referencedElement;
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartBlock.java b/compiler/java/com/google/dart/compiler/ast/DartBlock.java
new file mode 100644
index 00000000000..151c6d7ac2c
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartBlock.java
@@ -0,0 +1,51 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import java.util.List;
+
+/**
+ * Represents a Dart statement block.
+ */
+public class DartBlock extends DartStatement {
+
+ private final List stmts;
+
+ public DartBlock(List statements) {
+ this.stmts = becomeParentOf(statements);
+ }
+
+ public List getStatements() {
+ return stmts;
+ }
+
+ @Override
+ public boolean isAbruptCompletingStatement() {
+ for (DartStatement stmt : stmts) {
+ if (stmt.isAbruptCompletingStatement()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ v.acceptWithInsertRemove(this, stmts);
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ visitor.visit(stmts);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitBlock(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartBooleanLiteral.java b/compiler/java/com/google/dart/compiler/ast/DartBooleanLiteral.java
new file mode 100644
index 00000000000..f1da6cb7af6
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartBooleanLiteral.java
@@ -0,0 +1,40 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Represents a Dart boolean literal value.
+ */
+public class DartBooleanLiteral extends DartLiteral {
+
+ public static DartBooleanLiteral get(boolean value) {
+ return new DartBooleanLiteral(value);
+ }
+
+ private final boolean value;
+
+ private DartBooleanLiteral(boolean value) {
+ this.value = value;
+ }
+
+ public boolean getValue() {
+ return value;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ v.visit(this, ctx);
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitBooleanLiteral(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartBreakStatement.java b/compiler/java/com/google/dart/compiler/ast/DartBreakStatement.java
new file mode 100644
index 00000000000..4f25c14be31
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartBreakStatement.java
@@ -0,0 +1,34 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Represents a Dart 'break' statement.
+ */
+public class DartBreakStatement extends DartGotoStatement {
+
+ public DartBreakStatement(DartIdentifier label) {
+ super(label);
+ }
+
+ @Override
+ public boolean isAbruptCompletingStatement() {
+ return true;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ DartIdentifier label = getLabel();
+ if (v.visit(this, ctx) && label != null) {
+ label = becomeParentOf(v.accept(label));
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitBreakStatement(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartCase.java b/compiler/java/com/google/dart/compiler/ast/DartCase.java
new file mode 100644
index 00000000000..4e62e4b0e3d
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartCase.java
@@ -0,0 +1,55 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import java.util.List;
+
+/**
+ * Represents a Dart 'case' switch member.
+ */
+public class DartCase extends DartSwitchMember {
+
+ private DartExpression expr;
+ private DartCase normalizedNode = this;
+
+ public DartCase(DartExpression expr, DartLabel label, List statements) {
+ super(label, statements);
+ this.expr = becomeParentOf(expr);
+ }
+
+ public DartExpression getExpr() {
+ return expr;
+ }
+
+ public void setNormalizedNode(DartCase normalizedNode) {
+ normalizedNode.setSourceInfo(this);
+ this.normalizedNode = normalizedNode;
+ }
+
+ @Override
+ public DartCase getNormalizedNode() {
+ return normalizedNode;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ expr = becomeParentOf(v.accept(expr));
+ v.acceptWithInsertRemove(this, getStatements());
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ expr.accept(visitor);
+ super.visitChildren(visitor);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitCase(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartCatchBlock.java b/compiler/java/com/google/dart/compiler/ast/DartCatchBlock.java
new file mode 100644
index 00000000000..78820d654a8
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartCatchBlock.java
@@ -0,0 +1,60 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Represents a Dart 'catch' block.
+ */
+public class DartCatchBlock extends DartStatement {
+ private DartParameter exception;
+ private DartParameter stackTrace;
+ private DartBlock block;
+
+ public DartCatchBlock(DartBlock block,
+ DartParameter exception,
+ DartParameter stackTrace) {
+ this.block = becomeParentOf(block);
+ this.exception = becomeParentOf(exception);
+ this.stackTrace = becomeParentOf(stackTrace);
+ }
+
+ public DartParameter getException() {
+ return exception;
+ }
+
+ public DartParameter getStackTrace() {
+ return stackTrace;
+ }
+
+ public DartBlock getBlock() {
+ return block;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ exception = becomeParentOf(v.accept(exception));
+ if (stackTrace != null) {
+ stackTrace = becomeParentOf(v.accept(stackTrace));
+ }
+ block = becomeParentOf(v.accept(block));
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ exception.accept(visitor);
+ if (stackTrace != null) {
+ stackTrace.accept(visitor);
+ }
+ block.accept(visitor);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitCatchBlock(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartClass.java b/compiler/java/com/google/dart/compiler/ast/DartClass.java
new file mode 100644
index 00000000000..31394935301
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartClass.java
@@ -0,0 +1,188 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.common.HasSymbol;
+import com.google.dart.compiler.common.Symbol;
+import com.google.dart.compiler.resolver.ClassElement;
+
+import java.util.List;
+
+/**
+ * Represents a Dart class.
+ */
+public class DartClass extends DartDeclaration implements HasSymbol {
+
+ private ClassElement element;
+
+ private DartTypeNode superclass;
+
+ private final List members;
+ private final List typeParameters;
+ private final List interfaces;
+
+ private boolean isInterface;
+ private DartTypeNode defaultClass;
+
+ private int hash = -1;
+
+ // If the Dart class is implemented by a native JS class the nativeName
+ // points to the JS class. Otherwise it is null.
+ private final DartStringLiteral nativeName;
+
+ public DartClass(DartIdentifier name, DartStringLiteral nativeName,
+ DartTypeNode superclass, List interfaces,
+ List members,
+ List typeParameters) {
+ this(name, nativeName, superclass, interfaces, members, typeParameters, null, false);
+ }
+
+ public DartClass(DartIdentifier name, DartTypeNode superclass, List interfaces,
+ List members,
+ List typeParameters, DartTypeNode defaultClass) {
+ this(name, null, superclass, interfaces, members, typeParameters, defaultClass, true);
+ }
+
+ /**
+ * Set the diet-string hash code for the class
+ * @param hash the hash code to set
+ */
+ void setHash(int hash) {
+ this.hash = hash;
+ }
+
+ public DartClass(DartIdentifier name, DartStringLiteral nativeName,
+ DartTypeNode superclass, List interfaces,
+ List members,
+ List typeParameters, DartTypeNode defaultClass,
+ boolean isInterface) {
+ super(name);
+ this.nativeName = nativeName;
+ this.superclass = becomeParentOf(superclass);
+ this.members = becomeParentOf(members);
+ this.typeParameters = becomeParentOf(typeParameters);
+ this.interfaces = becomeParentOf(interfaces);
+ this.defaultClass = becomeParentOf(defaultClass);
+ this.isInterface = isInterface;
+ }
+
+ public boolean isInterface() {
+ return isInterface;
+ }
+
+ public List getMembers() {
+ return members;
+ }
+
+ public List getTypeParameters() {
+ return typeParameters;
+ }
+
+ public List getInterfaces() {
+ return interfaces;
+ }
+
+ public String getClassName() {
+ if (getName() == null) {
+ return null;
+ }
+ return getName().getTargetName();
+ }
+
+ public DartTypeNode getSuperclass() {
+ return superclass;
+ }
+
+ public DartTypeNode getDefaultClass() {
+ return defaultClass;
+ }
+
+ public Symbol getDefaultSymbol() {
+ if (defaultClass != null) {
+ return defaultClass.getType().getElement();
+ } else {
+ return null;
+ }
+ }
+
+ public Symbol getSuperSymbol() {
+ if (superclass != null) {
+ return superclass.getType().getElement();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public ClassElement getSymbol() {
+ return element;
+ }
+
+ public void setDefaultClass(DartTypeNode newName) {
+ defaultClass = becomeParentOf(newName);
+ }
+
+ public void setSuperclass(DartTypeNode newName) {
+ superclass = becomeParentOf(newName);
+ }
+
+ @Override
+ public void setSymbol(Symbol symbol) {
+ this.element = (ClassElement) symbol;
+ }
+
+ public DartStringLiteral getNativeName() {
+ return nativeName;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ if (superclass != null) {
+ superclass = becomeParentOf(v.accept(superclass));
+ }
+ v.acceptWithInsertRemove(this, getMembers());
+ if (getTypeParameters() != null) {
+ v.acceptWithInsertRemove(this, getTypeParameters());
+ }
+ if (getInterfaces() != null) {
+ v.acceptWithInsertRemove(this, getInterfaces());
+ }
+ if (defaultClass != null) {
+ defaultClass = becomeParentOf(v.accept(defaultClass));
+ }
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ visitor.visit(typeParameters);
+ if (superclass != null) {
+ superclass.accept(visitor);
+ }
+ visitor.visit(interfaces);
+ if (defaultClass != null) {
+ defaultClass.accept(visitor);
+ }
+ visitor.visit(members);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitClass(this);
+ }
+
+ @Override
+ public int computeHash() {
+ // TODO(jgw): Remove this altogether in fixing b/5324113.
+
+ // Cache hashes for DartClass, because they're always needed.
+ if (this.hash == -1) {
+ this.hash = super.computeHash();
+ }
+ return this.hash;
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartClassMember.java b/compiler/java/com/google/dart/compiler/ast/DartClassMember.java
new file mode 100644
index 00000000000..4669a460bd8
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartClassMember.java
@@ -0,0 +1,33 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.common.HasSymbol;
+import com.google.dart.compiler.resolver.Element;
+
+/**
+ * Base class for class members (fields and methods).
+ */
+public abstract class DartClassMember extends DartDeclaration
+ implements HasSymbol {
+
+ private final Modifiers modifiers;
+
+ protected DartClassMember(N name, Modifiers modifiers) {
+ super(name);
+ this.modifiers = modifiers;
+ }
+
+ public Modifiers getModifiers() {
+ return modifiers;
+ }
+
+ @Override
+ public abstract Element getSymbol();
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartComment.java b/compiler/java/com/google/dart/compiler/ast/DartComment.java
new file mode 100644
index 00000000000..2f8cbae1253
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartComment.java
@@ -0,0 +1,64 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.Source;
+
+public class DartComment extends DartNode {
+
+ private static final long serialVersionUID = 6066713446767517627L;
+
+ public static enum Style {
+ END_OF_LINE, BLOCK, DART_DOC;
+ }
+
+ private Style style;
+
+ public DartComment(Source source, int start, int length, int line, int col, Style style) {
+ setSourceLocation(source, line, col, start, length);
+ this.style = style;
+ }
+
+ /**
+ * Return true if this comment is a block comment.
+ *
+ * @return true if this comment is a block comment
+ */
+ public boolean isBlock() {
+ return style == Style.BLOCK;
+ }
+
+ /**
+ * Return true if this comment is a DartDoc comment.
+ *
+ * @return true if this comment is a DartDoc comment
+ */
+ public boolean isDartDoc() {
+ return style == Style.DART_DOC;
+ }
+
+ /**
+ * Return true if this comment is an end-of-line comment.
+ *
+ * @return true if this comment is an end-of-line comment
+ */
+ public boolean isEndOfLine() {
+ return style == Style.END_OF_LINE;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return null;
+ }
+
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartConditional.java b/compiler/java/com/google/dart/compiler/ast/DartConditional.java
new file mode 100644
index 00000000000..23989789cf9
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartConditional.java
@@ -0,0 +1,55 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Represents a Dart conditional expression.
+ */
+public class DartConditional extends DartExpression {
+
+ private DartExpression condition;
+ private DartExpression elseExpr;
+ private DartExpression thenExpr;
+
+ public DartConditional(DartExpression condition, DartExpression thenExpr,
+ DartExpression elseExpr) {
+ this.condition = becomeParentOf(condition);
+ this.thenExpr = becomeParentOf(thenExpr);
+ this.elseExpr = becomeParentOf(elseExpr);
+ }
+
+ public DartExpression getCondition() {
+ return condition;
+ }
+
+ public DartExpression getElseExpression() {
+ return elseExpr;
+ }
+
+ public DartExpression getThenExpression() {
+ return thenExpr;
+ }
+
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ condition = becomeParentOf(v.accept(condition));
+ thenExpr = becomeParentOf(v.accept(thenExpr));
+ elseExpr = becomeParentOf(v.accept(elseExpr));
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ condition.accept(visitor);
+ thenExpr.accept(visitor);
+ elseExpr.accept(visitor);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitConditional(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartContext.java b/compiler/java/com/google/dart/compiler/ast/DartContext.java
new file mode 100644
index 00000000000..07d6a0f28c5
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartContext.java
@@ -0,0 +1,27 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * The context in which a DartNode visitation occurs. This represents the set of
+ * possible operations a DartVisitor subclass can perform on the currently
+ * visited node.
+ */
+public interface DartContext {
+
+ boolean canInsert();
+
+ boolean canRemove();
+
+ void insertAfter(DartVisitable node);
+
+ void insertBefore(DartVisitable node);
+
+ boolean isLvalue();
+
+ void removeMe();
+
+ void replaceMe(DartVisitable node);
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartContinueStatement.java b/compiler/java/com/google/dart/compiler/ast/DartContinueStatement.java
new file mode 100644
index 00000000000..fbd6cccbaff
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartContinueStatement.java
@@ -0,0 +1,34 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Represents a Dart 'continue' statement.
+ */
+public class DartContinueStatement extends DartGotoStatement {
+
+ public DartContinueStatement(DartIdentifier label) {
+ super(label);
+ }
+
+ @Override
+ public boolean isAbruptCompletingStatement() {
+ return true;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ DartIdentifier label = getLabel();
+ if (v.visit(this, ctx) && label != null) {
+ label = becomeParentOf(v.accept(label));
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitContinueStatement(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartDeclaration.java b/compiler/java/com/google/dart/compiler/ast/DartDeclaration.java
new file mode 100644
index 00000000000..c2b3eafcc69
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartDeclaration.java
@@ -0,0 +1,33 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.resolver.Element;
+
+/**
+ * Common supertype for most declarations. A declaration introduces a new name
+ * in a scope. Certain tools, such as the IDE, need to know the location of this
+ * name, but the name should otherwise be considered a part of the declaration,
+ * not an independent node. So the name is not visited when traversing the AST.
+ */
+public abstract class DartDeclaration extends DartNode {
+
+ private N name; // Not visited.
+
+ protected DartDeclaration(N name) {
+ this.name = becomeParentOf(name);
+ }
+
+ public final N getName() {
+ return name;
+ }
+
+ public final void setName(N newName) {
+ name = becomeParentOf(newName);
+ }
+
+ @Override
+ public abstract Element getSymbol();
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartDefault.java b/compiler/java/com/google/dart/compiler/ast/DartDefault.java
new file mode 100644
index 00000000000..c495f5213ca
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartDefault.java
@@ -0,0 +1,30 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import java.util.List;
+
+/**
+ * Represents a Dart 'default' switch member.
+ */
+public class DartDefault extends DartSwitchMember {
+
+ public DartDefault(DartLabel label, List statements) {
+ super(label, statements);
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ v.acceptWithInsertRemove(this, getStatements());
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitDefault(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartDirective.java b/compiler/java/com/google/dart/compiler/ast/DartDirective.java
new file mode 100644
index 00000000000..3a1fe7e0122
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartDirective.java
@@ -0,0 +1,11 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Base class for directives.
+ */
+public abstract class DartDirective extends DartNode {
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartDoWhileStatement.java b/compiler/java/com/google/dart/compiler/ast/DartDoWhileStatement.java
new file mode 100644
index 00000000000..6c5d7eab916
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartDoWhileStatement.java
@@ -0,0 +1,47 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Represents a Dart 'do/while' statement.
+ */
+public class DartDoWhileStatement extends DartStatement {
+
+ private DartExpression condition;
+ private DartStatement body;
+
+ public DartDoWhileStatement(DartExpression condition, DartStatement body) {
+ this.condition = becomeParentOf(condition);
+ this.body = becomeParentOf(body);
+ }
+
+ public DartStatement getBody() {
+ return body;
+ }
+
+ public DartExpression getCondition() {
+ return condition;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ condition = becomeParentOf(v.accept(condition));
+ body = becomeParentOf(v.accept(body));
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ condition.accept(visitor);
+ body.accept(visitor);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitDoWhileStatement(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartDoubleLiteral.java b/compiler/java/com/google/dart/compiler/ast/DartDoubleLiteral.java
new file mode 100644
index 00000000000..9c35c942c5c
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartDoubleLiteral.java
@@ -0,0 +1,40 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Represents a Dart double literal value.
+ */
+public class DartDoubleLiteral extends DartLiteral {
+
+ public static DartDoubleLiteral get(double x) {
+ return new DartDoubleLiteral(x);
+ }
+
+ private final double value;
+
+ private DartDoubleLiteral(double value) {
+ this.value = value;
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ v.visit(this, ctx);
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitDoubleLiteral(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartEmptyStatement.java b/compiler/java/com/google/dart/compiler/ast/DartEmptyStatement.java
new file mode 100644
index 00000000000..1c59e328ecb
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartEmptyStatement.java
@@ -0,0 +1,26 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Represents an empty Dart statement.
+ */
+public class DartEmptyStatement extends DartStatement {
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ v.visit(this, ctx);
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitEmptyStatement(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartExprStmt.java b/compiler/java/com/google/dart/compiler/ast/DartExprStmt.java
new file mode 100644
index 00000000000..40c7a9fcedf
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartExprStmt.java
@@ -0,0 +1,38 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Represents a Dart expression-as-statement.
+ */
+public class DartExprStmt extends DartStatement {
+
+ private DartExpression expr;
+
+ public DartExprStmt(DartExpression expr) {
+ this.expr = becomeParentOf(expr);
+ }
+
+ public DartExpression getExpression() {
+ return expr;
+ }
+
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ expr = becomeParentOf(v.accept(expr));
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ expr.accept(visitor);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitExprStmt(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartExpression.java b/compiler/java/com/google/dart/compiler/ast/DartExpression.java
new file mode 100644
index 00000000000..9b0bb15a81c
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartExpression.java
@@ -0,0 +1,21 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Abstract base class for Dart expressions.
+ */
+public abstract class DartExpression extends DartNode {
+
+ public boolean isAssignable() {
+ // By default you cannot assign to expressions.
+ return false;
+ }
+
+ @Override
+ public DartExpression getNormalizedNode() {
+ return (DartExpression) super.getNormalizedNode();
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartField.java b/compiler/java/com/google/dart/compiler/ast/DartField.java
new file mode 100644
index 00000000000..4a2c587fab4
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartField.java
@@ -0,0 +1,95 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.common.Symbol;
+import com.google.dart.compiler.resolver.FieldElement;
+
+/**
+ * Represents a single field within a field definition.
+ */
+public class DartField extends DartClassMember {
+
+ private DartExpression value;
+ private FieldElement element;
+ private DartMethodDefinition accessor;
+
+ public DartField(DartIdentifier name, Modifiers modifiers, DartMethodDefinition accessor,
+ DartExpression value) {
+ super(name, modifiers);
+ this.accessor = becomeParentOf(accessor);
+ this.value = becomeParentOf(value);
+ }
+
+ public void setValue(DartExpression value) {
+ this.value = becomeParentOf(value);
+ }
+
+ public DartExpression getValue() {
+ return value;
+ }
+
+ public void setAccessor(DartMethodDefinition accessor) {
+ this.accessor = becomeParentOf(accessor);
+ }
+
+ public DartMethodDefinition getAccessor() {
+ return accessor;
+ }
+
+ @Override
+ public FieldElement getSymbol() {
+ return element;
+ }
+
+ @Override
+ public void setSymbol(Symbol symbol) {
+ this.element = (FieldElement) symbol;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ if (getValue() != null) {
+ setValue(v.accept(getValue()));
+ }
+ if (getAccessor() != null) {
+ setAccessor(v.accept(getAccessor()));
+ }
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ super.visitChildren(visitor);
+ if (getAccessor() != null) {
+ getAccessor().accept(visitor);
+ }
+ if (getValue() != null) {
+ getValue().accept(visitor);
+ }
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitField(this);
+ }
+
+ @Override
+ public int computeHash() {
+ // TODO(jgw): Remove this altogether in fixing b/5324113.
+
+ // DartField doesn't include the type-node, so we directly return the hash of its type, which
+ // is all that matters for the purposes of dependency-tracking.
+ DartFieldDefinition def = (DartFieldDefinition) getParent();
+ DartTypeNode typeNode = def.getTypeNode();
+ if (typeNode == null) {
+ // Use 0 to represent an untyped field.
+ return 0;
+ }
+ return typeNode.computeHash();
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartFieldDefinition.java b/compiler/java/com/google/dart/compiler/ast/DartFieldDefinition.java
new file mode 100644
index 00000000000..8e90cc0ef00
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartFieldDefinition.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import java.util.List;
+
+/**
+ * Represents a Dart field definition.
+ */
+public class DartFieldDefinition extends DartNode {
+
+ private DartTypeNode typeNode;
+ private final List fields;
+
+ public DartFieldDefinition(DartTypeNode typeNode, List fields) {
+ this.setTypeNode(typeNode);
+ this.fields = becomeParentOf(fields);
+ }
+
+ public DartTypeNode getTypeNode() {
+ return typeNode;
+ }
+
+ public void setTypeNode(DartTypeNode typeNode) {
+ this.typeNode = becomeParentOf(typeNode);
+ }
+
+ public List getFields() {
+ return fields;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ if (getTypeNode() != null) {
+ setTypeNode(v.accept(getTypeNode()));
+ }
+ v.acceptWithInsertRemove(this, getFields());
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ if (getTypeNode() != null) {
+ getTypeNode().accept(visitor);
+ }
+ visitor.visit(getFields());
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitFieldDefinition(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartForInStatement.java b/compiler/java/com/google/dart/compiler/ast/DartForInStatement.java
new file mode 100644
index 00000000000..31f096c399e
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartForInStatement.java
@@ -0,0 +1,78 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Represents a Dart 'for (.. in ..)' statement.
+ */
+public class DartForInStatement extends DartStatement {
+
+ private DartStatement setup;
+ private DartExpression iterable;
+ private DartStatement body;
+
+ private DartStatement normalizedNode = this;
+
+ public DartForInStatement(DartStatement setup,
+ DartExpression iterable,
+ DartStatement body) {
+ this.setup = becomeParentOf(setup);
+ this.iterable = becomeParentOf(iterable);
+ this.body = becomeParentOf(body);
+ }
+
+ public DartStatement getBody() {
+ return body;
+ }
+
+ public DartExpression getIterable() {
+ return iterable;
+ }
+
+ public void setNormalizedNode(DartStatement statement) {
+ normalizedNode = statement;
+ }
+
+ @Override
+ public DartStatement getNormalizedNode() {
+ return normalizedNode;
+ }
+
+ public boolean introducesVariable() {
+ return setup instanceof DartVariableStatement;
+ }
+
+ public DartIdentifier getIdentifier() {
+ assert !introducesVariable();
+ return (DartIdentifier) ((DartExprStmt) setup).getExpression();
+ }
+
+ public DartVariableStatement getVariableStatement() {
+ assert introducesVariable();
+ return (DartVariableStatement) setup;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ setup = becomeParentOf(v.accept(setup));
+ iterable = becomeParentOf(v.accept(iterable));
+ body = becomeParentOf(v.accept(body));
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ setup.accept(visitor);
+ iterable.accept(visitor);
+ body.accept(visitor);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitForInStatement(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartForStatement.java b/compiler/java/com/google/dart/compiler/ast/DartForStatement.java
new file mode 100644
index 00000000000..b5f635f052c
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartForStatement.java
@@ -0,0 +1,76 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Represents a Dart 'for' statement.
+ */
+public class DartForStatement extends DartStatement {
+
+ private DartStatement init;
+ private DartExpression condition;
+ private DartExpression increment;
+ private DartStatement body;
+
+ public DartForStatement(DartStatement init, DartExpression condition, DartExpression increment,
+ DartStatement body) {
+ this.init = becomeParentOf(init);
+ this.condition = becomeParentOf(condition);
+ this.increment = becomeParentOf(increment);
+ this.body = becomeParentOf(body);
+ }
+
+ public DartStatement getBody() {
+ return body;
+ }
+
+ public DartExpression getCondition() {
+ return condition;
+ }
+
+ public DartExpression getIncrement() {
+ return increment;
+ }
+
+ public DartStatement getInit() {
+ return init;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ if (init != null) {
+ init = becomeParentOf(v.accept(init));
+ }
+ if (condition != null) {
+ condition = becomeParentOf(v.accept(condition));
+ }
+ if (increment != null) {
+ increment = becomeParentOf(v.accept(increment));
+ }
+ body = becomeParentOf(v.accept(body));
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ if (init != null) {
+ init.accept(visitor);
+ }
+ if (condition != null) {
+ condition.accept(visitor);
+ }
+ if (increment != null) {
+ increment.accept(visitor);
+ }
+ body.accept(visitor);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitForStatement(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartFunction.java b/compiler/java/com/google/dart/compiler/ast/DartFunction.java
new file mode 100644
index 00000000000..76e161c6f7d
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartFunction.java
@@ -0,0 +1,68 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import java.util.List;
+
+/**
+ * Represents a Dart function.
+ */
+public class DartFunction extends DartNode {
+
+ private final List params;
+ private DartBlock body;
+ private DartTypeNode returnTypeNode;
+
+ public DartFunction(List arguments, DartBlock body, DartTypeNode returnTypeNode) {
+ this.params = becomeParentOf(arguments);
+ this.body = becomeParentOf(body);
+ this.returnTypeNode = becomeParentOf(returnTypeNode);
+ }
+
+ public void addParam(DartParameter param) {
+ params.add(param);
+ }
+
+ public DartBlock getBody() {
+ return body;
+ }
+
+ public List getParams() {
+ return params;
+ }
+
+ public DartTypeNode getReturnTypeNode() {
+ return returnTypeNode;
+ }
+
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ v.acceptWithInsertRemove(this, params);
+ if (body != null) {
+ body = becomeParentOf(v.accept(body));
+ }
+ if (returnTypeNode != null) {
+ returnTypeNode = becomeParentOf(v.accept(returnTypeNode));
+ }
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ visitor.visit(params);
+ if (body != null) {
+ body.accept(visitor);
+ }
+ if (returnTypeNode != null) {
+ returnTypeNode.accept(visitor);
+ }
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitFunction(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartFunctionExpression.java b/compiler/java/com/google/dart/compiler/ast/DartFunctionExpression.java
new file mode 100644
index 00000000000..06245acf23c
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartFunctionExpression.java
@@ -0,0 +1,80 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.common.HasSymbol;
+import com.google.dart.compiler.common.Symbol;
+import com.google.dart.compiler.resolver.MethodElement;
+
+/**
+ * Represents a Dart 'function' expression.
+ */
+public class DartFunctionExpression extends DartExpression implements HasSymbol {
+
+ // Not visited. Similar to DartDeclaration, but DartDeclaration shouldn't be
+ // a statement or an expression.
+ private DartIdentifier name;
+
+ private final boolean isStmt;
+ private MethodElement symbol;
+ private DartFunction function;
+
+ public DartFunctionExpression(DartIdentifier name, DartFunction function, boolean isStmt) {
+ this.name = becomeParentOf(name);
+ this.function = becomeParentOf(function);
+ this.isStmt = isStmt;
+ }
+
+ public DartFunction getFunction() {
+ return function;
+ }
+
+ public String getFunctionName() {
+ if (name == null) {
+ return null;
+ }
+ return name.getTargetName();
+ }
+
+ public DartIdentifier getName() {
+ return name;
+ }
+
+ @Override
+ public MethodElement getSymbol() {
+ return symbol;
+ }
+
+ public boolean isStatement() {
+ return isStmt;
+ }
+
+ public void setName(DartIdentifier newName) {
+ name = becomeParentOf(newName);
+ }
+
+ @Override
+ public void setSymbol(Symbol symbol) {
+ this.symbol = (MethodElement) symbol;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ function = becomeParentOf(v.accept(function));
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ function.accept(visitor);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitFunctionExpression(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartFunctionObjectInvocation.java b/compiler/java/com/google/dart/compiler/ast/DartFunctionObjectInvocation.java
new file mode 100644
index 00000000000..400f349259e
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartFunctionObjectInvocation.java
@@ -0,0 +1,46 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import java.util.List;
+
+/**
+ * Function-object invocation AST node.
+ */
+public class DartFunctionObjectInvocation extends DartInvocation {
+
+ private DartExpression target;
+
+ public DartFunctionObjectInvocation(DartExpression target,
+ List args) {
+ super(args);
+ this.target = becomeParentOf(target);
+ }
+
+ @Override
+ public DartExpression getTarget() {
+ return target;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ target = becomeParentOf(v.accept(target));
+ v.acceptWithInsertRemove(this, getArgs());
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ target.accept(visitor);
+ visitor.visit(getArgs());
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitFunctionObjectInvocation(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartFunctionTypeAlias.java b/compiler/java/com/google/dart/compiler/ast/DartFunctionTypeAlias.java
new file mode 100644
index 00000000000..22dac3c032c
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartFunctionTypeAlias.java
@@ -0,0 +1,83 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.common.HasSymbol;
+import com.google.dart.compiler.common.Symbol;
+import com.google.dart.compiler.resolver.FunctionAliasElement;
+
+import java.util.List;
+
+/**
+ * Named function-type alias AST node.
+ */
+public class DartFunctionTypeAlias extends DartDeclaration implements HasSymbol {
+
+ private DartTypeNode returnTypeNode;
+ private final List parameters;
+ private FunctionAliasElement element;
+ private final List typeParameters;
+
+ public DartFunctionTypeAlias(DartIdentifier name, DartTypeNode returnTypeNode,
+ List parameters,
+ List typeParameters) {
+ super(name);
+ this.returnTypeNode = becomeParentOf(returnTypeNode);
+ this.parameters = becomeParentOf(parameters);
+ this.typeParameters = becomeParentOf(typeParameters);
+ }
+
+ public List getParameters() {
+ return parameters;
+ }
+
+ public DartTypeNode getReturnTypeNode() {
+ return returnTypeNode;
+ }
+
+ public List getTypeParameters() {
+ return typeParameters;
+ }
+
+ @Override
+ public FunctionAliasElement getSymbol() {
+ return element;
+ }
+
+ public void setReturnTypeNode(DartTypeNode newReturnType) {
+ returnTypeNode = becomeParentOf(newReturnType);
+ }
+
+ @Override
+ public void setSymbol(Symbol symbol) {
+ element = (FunctionAliasElement) symbol;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ if (returnTypeNode != null) {
+ returnTypeNode = becomeParentOf(v.accept(returnTypeNode));
+ }
+ v.acceptWithInsertRemove(this, parameters);
+ v.acceptWithInsertRemove(this, typeParameters);
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ if (returnTypeNode != null) {
+ returnTypeNode.accept(visitor);
+ }
+ visitor.visit(parameters);
+ visitor.visit(typeParameters);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitFunctionTypeAlias(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartGotoStatement.java b/compiler/java/com/google/dart/compiler/ast/DartGotoStatement.java
new file mode 100644
index 00000000000..5ad227f54b3
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartGotoStatement.java
@@ -0,0 +1,51 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.common.Symbol;
+
+/**
+ * Base class of {@link DartBreakStatement} and {@link DartContinueStatement}.
+ */
+public abstract class DartGotoStatement extends DartStatement {
+
+ private DartIdentifier label;
+ private Symbol targetSymbol;
+
+ public DartGotoStatement(DartIdentifier label) {
+ this.label = becomeParentOf(label);
+ }
+
+ public DartIdentifier getLabel() {
+ return label;
+ }
+
+ public String getTargetName() {
+ if (label == null) {
+ return null;
+ }
+ return label.getTargetName();
+ }
+
+ public Symbol getTargetSymbol() {
+ return targetSymbol;
+ }
+
+ public void setLabel(DartIdentifier newLabel) {
+ label = newLabel;
+ }
+
+ @Override
+ public void setSymbol(Symbol symbol) {
+ this.targetSymbol = symbol;
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ if (label != null) {
+ label.accept(visitor);
+ }
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartIdentifier.java b/compiler/java/com/google/dart/compiler/ast/DartIdentifier.java
new file mode 100644
index 00000000000..fcd2a515fa4
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartIdentifier.java
@@ -0,0 +1,86 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.common.Symbol;
+import com.google.dart.compiler.resolver.Element;
+
+/**
+ * Represents a Dart identifier expression.
+ */
+public class DartIdentifier extends DartExpression implements ElementReference {
+
+ private final String targetName;
+ private Element targetSymbol;
+ private DartExpression normalizedNode = this;
+ private Element referencedElement;
+
+ public DartIdentifier(String targetName) {
+ assert targetName != null;
+ this.targetName = targetName;
+ }
+
+ public DartIdentifier(DartIdentifier original) {
+ this.targetName = original.targetName;
+ }
+
+ public void setNormalizedNode(DartExpression normalizedNode) {
+ normalizedNode.setSourceInfo(this);
+ this.normalizedNode = normalizedNode;
+ }
+
+ @Override
+ public DartExpression getNormalizedNode() {
+ return normalizedNode;
+ }
+
+ @Override
+ public Element getSymbol() {
+ return targetSymbol;
+ }
+
+ @Override
+ public boolean isAssignable() {
+ return true;
+ }
+
+ public String getTargetName() {
+ return targetName;
+ }
+
+ public Element getTargetSymbol() {
+ return targetSymbol;
+ }
+
+ @Override
+ public void setSymbol(Symbol symbol) {
+ this.targetSymbol = (Element) symbol;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ v.visit(this, ctx);
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitIdentifier(this);
+ }
+
+ @Override
+ public void setReferencedElement(Element element) {
+ referencedElement = element;
+ }
+
+ @Override
+ public Element getReferencedElement() {
+ return referencedElement;
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartIfStatement.java b/compiler/java/com/google/dart/compiler/ast/DartIfStatement.java
new file mode 100644
index 00000000000..7df42b89437
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartIfStatement.java
@@ -0,0 +1,59 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Represents a Dart 'if' statement.
+ */
+public class DartIfStatement extends DartStatement {
+
+ private DartExpression condition;
+ private DartStatement thenStmt;
+ private DartStatement elseStmt;
+
+ public DartIfStatement(DartExpression condition, DartStatement thenStmt, DartStatement elseStmt) {
+ this.condition = becomeParentOf(condition);
+ this.thenStmt = becomeParentOf(thenStmt);
+ this.elseStmt = becomeParentOf(elseStmt);
+ }
+
+ public DartExpression getCondition() {
+ return condition;
+ }
+
+ public DartStatement getElseStatement() {
+ return elseStmt;
+ }
+
+ public DartStatement getThenStatement() {
+ return thenStmt;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ condition = becomeParentOf(v.accept(condition));
+ thenStmt = becomeParentOf(v.accept(thenStmt));
+ if (elseStmt != null) {
+ elseStmt = becomeParentOf(v.accept(elseStmt));
+ }
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ condition.accept(visitor);
+ thenStmt.accept(visitor);
+ if (elseStmt != null) {
+ elseStmt.accept(visitor);
+ }
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitIfStatement(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartImportDirective.java b/compiler/java/com/google/dart/compiler/ast/DartImportDirective.java
new file mode 100644
index 00000000000..c5c65be8acb
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartImportDirective.java
@@ -0,0 +1,51 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Implements the #import directive.
+ */
+public class DartImportDirective extends DartDirective {
+ private DartStringLiteral libraryUri;
+
+ private DartStringLiteral prefix;
+
+ public DartImportDirective(DartStringLiteral libraryUri, DartStringLiteral prefix) {
+ this.libraryUri = becomeParentOf(libraryUri);
+ this.prefix = becomeParentOf(prefix);
+ }
+
+ public DartStringLiteral getLibraryUri() {
+ return libraryUri;
+ }
+
+ public DartStringLiteral getPrefix() {
+ return prefix;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ libraryUri = becomeParentOf(v.accept(libraryUri));
+ if (prefix != null) {
+ prefix = becomeParentOf(v.accept(prefix));
+ }
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ libraryUri.accept(visitor);
+ if (prefix != null) {
+ prefix.accept(visitor);
+ }
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitImportDirective(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartInitializer.java b/compiler/java/com/google/dart/compiler/ast/DartInitializer.java
new file mode 100644
index 00000000000..18a06730619
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartInitializer.java
@@ -0,0 +1,74 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Represents a constructor initializer expression.
+ */
+public class DartInitializer extends DartNode {
+
+ private DartIdentifier name;
+ private DartExpression value;
+
+ public DartInitializer(DartIdentifier name, DartExpression value) {
+ this.name = becomeParentOf(name);
+ this.value = becomeParentOf(value);
+ }
+
+ public String getInitializerName() {
+ if (name == null) {
+ return null;
+ }
+ return name.getTargetName();
+ }
+
+ public DartIdentifier getName() {
+ return name;
+ }
+
+ public DartExpression getValue() {
+ return value;
+ }
+
+ /**
+ * Determines if initializer is an invocation.
+ * @return true if initializer is either super or redirected constructor invocation.
+ */
+ public boolean isInvocation() {
+ return name == null;
+ }
+
+ public void setName(DartIdentifier newName) {
+ name = becomeParentOf(newName);
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ if (name != null) {
+ name = becomeParentOf(v.accept(name));
+ }
+ if (value != null) {
+ value = becomeParentOf(v.accept(value));
+ }
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ if (name != null) {
+ name.accept(visitor);
+ }
+ if (value != null) {
+ value.accept(visitor);
+ }
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitInitializer(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartIntegerLiteral.java b/compiler/java/com/google/dart/compiler/ast/DartIntegerLiteral.java
new file mode 100644
index 00000000000..e00ff421107
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartIntegerLiteral.java
@@ -0,0 +1,46 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import java.math.BigInteger;
+
+/**
+ * Represents a Dart integer literal value.
+ */
+public class DartIntegerLiteral extends DartLiteral {
+
+ public static DartIntegerLiteral get(BigInteger x) {
+ return new DartIntegerLiteral(x);
+ }
+
+ public static DartIntegerLiteral one() {
+ return new DartIntegerLiteral(BigInteger.ONE);
+ }
+
+ private final BigInteger value;
+
+ private DartIntegerLiteral(BigInteger value) {
+ this.value = value;
+ }
+
+ public BigInteger getValue() {
+ return value;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ v.visit(this, ctx);
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitIntegerLiteral(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartInvocation.java b/compiler/java/com/google/dart/compiler/ast/DartInvocation.java
new file mode 100644
index 00000000000..4993e2d6077
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartInvocation.java
@@ -0,0 +1,48 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import java.util.List;
+
+/**
+ * Common superclass for all invocation expressions. In
+ * a Dart program, there are different kinds of invocation:
+ *
+ * - expression.identifier() is a method invocation, where the
+ * receiver is 'expression' and the method name 'identifier'.
+ * This invocation is represented as a DartMethodInvocation.
+ * Examples: A.foo(), this.foo(), super.foo(), bar().foo().
+ *
+ *
+ * - identifier() is an unqualified invocation. After the resolver has
+ * resolved 'identifier', the normalizer will transform the node to
+ * either a DartFunctionObjectInvocation or a DartMethodInvocation.
+ * This invocation is represented as a DartUnqualifiedInvocation.
+ * Examples: foo().
+ *
+ *
+ * - expression() is a function object invocation.
+ * This invocation is represented as a DartFunctionObjectInvocation.
+ * Examples: bar()(), (A.bar)(), bar[0](), (bar)().
+ *
+ *
+ *
+ */
+public abstract class DartInvocation extends DartExpression {
+
+ private List args;
+
+ public DartInvocation(List args) {
+ this.args = becomeParentOf(args);
+ }
+
+ public DartExpression getTarget() {
+ return null;
+ }
+
+ public List getArgs() {
+ return args;
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartLabel.java b/compiler/java/com/google/dart/compiler/ast/DartLabel.java
new file mode 100644
index 00000000000..33fdaedf16c
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartLabel.java
@@ -0,0 +1,73 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.common.HasSymbol;
+import com.google.dart.compiler.common.Symbol;
+
+/**
+ * Represents a Dart statement label.
+ */
+public class DartLabel extends DartStatement implements HasSymbol {
+
+ // Not visited. Similar to DartDeclaration, but DartDeclaration shouldn't be
+ // a statement or an expression.
+ private DartIdentifier label;
+
+ private Symbol symbol;
+
+ private DartStatement statement;
+
+ public DartLabel(DartIdentifier label, DartStatement statement) {
+ this.label = becomeParentOf(label);
+ this.statement = becomeParentOf(statement);
+ }
+
+ public DartIdentifier getLabel() {
+ return label;
+ }
+
+ public String getName() {
+ return label.getTargetName();
+ }
+
+ public DartStatement getStatement() {
+ return statement;
+ }
+
+ @Override
+ public Symbol getSymbol() {
+ return symbol;
+ }
+
+ public void setLabel(DartIdentifier newLabel) {
+ label = newLabel;
+ }
+
+ @Override
+ public void setSymbol(Symbol symbol) {
+ this.symbol = symbol;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ statement = becomeParentOf(v.accept(statement));
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ if (statement != null) {
+ statement.accept(visitor);
+ }
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitLabel(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartLibraryDirective.java b/compiler/java/com/google/dart/compiler/ast/DartLibraryDirective.java
new file mode 100644
index 00000000000..18433d7b924
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartLibraryDirective.java
@@ -0,0 +1,38 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Implements the #library directive.
+ */
+public class DartLibraryDirective extends DartDirective {
+ private DartStringLiteral name;
+
+ public DartLibraryDirective(DartStringLiteral name) {
+ this.name = becomeParentOf(name);
+ }
+
+ public DartStringLiteral getName() {
+ return name;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ name = becomeParentOf(v.accept(name));
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ name.accept(visitor);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitLibraryDirective(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartLiteral.java b/compiler/java/com/google/dart/compiler/ast/DartLiteral.java
new file mode 100644
index 00000000000..289dcb05a91
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartLiteral.java
@@ -0,0 +1,24 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.type.Type;
+
+/**
+ * Abstract base class for Dart literal values.
+ */
+public abstract class DartLiteral extends DartExpression {
+ private Type type;
+
+ @Override
+ public void setType(Type type) {
+ this.type = type;
+ }
+
+ @Override
+ public Type getType() {
+ return type;
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartMapLiteral.java b/compiler/java/com/google/dart/compiler/ast/DartMapLiteral.java
new file mode 100644
index 00000000000..ad0bcdb9ae9
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartMapLiteral.java
@@ -0,0 +1,45 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import java.util.List;
+
+/**
+ * Represents a Dart map literal value.
+ */
+public class DartMapLiteral extends DartTypedLiteral {
+
+ private final List entries;
+
+ public DartMapLiteral(boolean isConst, List typeArguments,
+ List entries) {
+ super(isConst, typeArguments);
+ this.entries = becomeParentOf(entries);
+ }
+
+ public List getEntries() {
+ return entries;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ super.traverse(v, ctx);
+ v.acceptWithInsertRemove(this, entries);
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ super.visitChildren(visitor);
+ visitor.visit(entries);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitMapLiteral(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartMapLiteralEntry.java b/compiler/java/com/google/dart/compiler/ast/DartMapLiteralEntry.java
new file mode 100644
index 00000000000..e913bad381b
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartMapLiteralEntry.java
@@ -0,0 +1,47 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Represents an entry in a Dart map literal value.
+ */
+public class DartMapLiteralEntry extends DartNode {
+
+ private DartExpression key;
+ private DartExpression value;
+
+ public DartMapLiteralEntry(DartExpression key, DartExpression value) {
+ this.key = becomeParentOf(key);
+ this.value = becomeParentOf(value);
+ }
+
+ public DartExpression getKey() {
+ return key;
+ }
+
+ public DartExpression getValue() {
+ return value;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ key = becomeParentOf(v.accept(key));
+ value = becomeParentOf(v.accept(value));
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ key.accept(visitor);
+ value.accept(visitor);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitMapLiteralEntry(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartMethodDefinition.java b/compiler/java/com/google/dart/compiler/ast/DartMethodDefinition.java
new file mode 100644
index 00000000000..2836c446429
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartMethodDefinition.java
@@ -0,0 +1,128 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.common.Symbol;
+import com.google.dart.compiler.resolver.MethodElement;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Represents a Dart method definition.
+ */
+public class DartMethodDefinition extends DartClassMember {
+
+ protected DartFunction function;
+ private MethodElement element;
+ private DartMethodDefinition normalizedNode = this;
+ private final List typeParameters;
+
+ public static DartMethodDefinition create(DartExpression name,
+ DartFunction function,
+ Modifiers modifiers,
+ List initializers,
+ List typeParameters) {
+ if (initializers == null) {
+ return new DartMethodDefinition(name, function, modifiers, typeParameters);
+ } else {
+ return new DartMethodWithInitializersDefinition(name, function, modifiers, initializers);
+ }
+ }
+
+ private DartMethodDefinition(DartExpression name, DartFunction function, Modifiers modifiers,
+ List typeParameters) {
+ super(name, modifiers);
+ this.function = becomeParentOf(function);
+ this.typeParameters = typeParameters;
+ }
+
+ public DartFunction getFunction() {
+ return function;
+ }
+
+ @Override
+ public MethodElement getSymbol() {
+ return element;
+ }
+
+ @Override
+ public void setSymbol(Symbol symbol) {
+ element = (MethodElement) symbol;
+ }
+
+ public void setNormalizedNode(DartMethodDefinition normalizedNode) {
+ normalizedNode.setSourceInfo(this);
+ this.normalizedNode = normalizedNode;
+ }
+
+ @Override
+ public DartMethodDefinition getNormalizedNode() {
+ return normalizedNode;
+ }
+
+ public List getInitializers() {
+ return Collections.emptyList();
+ }
+
+ public List getTypeParameters() {
+ return typeParameters;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ function = becomeParentOf(v.accept(function));
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ super.visitChildren(visitor);
+ function.accept(visitor);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitMethodDefinition(this);
+ }
+
+ private static class DartMethodWithInitializersDefinition extends DartMethodDefinition {
+
+ private final List initializers;
+
+ DartMethodWithInitializersDefinition(DartExpression name,
+ DartFunction function,
+ Modifiers modifiers,
+ List initializers) {
+ super(name, function, modifiers, null);
+ this.initializers = becomeParentOf(initializers);
+ }
+
+ @Override
+ public List getInitializers() {
+ return initializers;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ function = becomeParentOf(v.accept(function));
+ v.acceptWithInsertRemove(this, initializers);
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ super.visitChildren(visitor);
+ visitor.visit(initializers);
+ if (getTypeParameters() != null) {
+ visitor.visit(getTypeParameters());
+ }
+ }
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartMethodInvocation.java b/compiler/java/com/google/dart/compiler/ast/DartMethodInvocation.java
new file mode 100644
index 00000000000..3d9d377cdb1
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartMethodInvocation.java
@@ -0,0 +1,79 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.common.Symbol;
+
+import java.util.List;
+
+/**
+ * Method invocation AST node. The name of the method must not be
+ * null. The receiver is an expression, super, or a classname.
+ */
+public class DartMethodInvocation extends DartInvocation {
+
+ private DartExpression target;
+ private DartIdentifier functionName;
+ private Symbol targetSymbol;
+
+ public DartMethodInvocation(DartExpression target,
+ DartIdentifier functionName,
+ List args) {
+ super(args);
+ functionName.getClass(); // Quick null-check.
+ this.target = becomeParentOf(target);
+ this.functionName = becomeParentOf(functionName);
+ }
+
+ @Override
+ public DartExpression getTarget() {
+ return target;
+ }
+
+ public String getFunctionNameString() {
+ return functionName.getTargetName();
+ }
+
+ public DartIdentifier getFunctionName() {
+ return functionName;
+ }
+
+ public void setFunctionName(DartIdentifier newName) {
+ newName.getClass(); // Quick null-check.
+ functionName = becomeParentOf(newName);
+ }
+
+ @Override
+ public void setSymbol(Symbol symbol) {
+ this.targetSymbol = symbol;
+ }
+
+ public Symbol getTargetSymbol() {
+ return targetSymbol;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ target = becomeParentOf(v.accept(target));
+ functionName = becomeParentOf(v.accept(functionName));
+ functionName.getClass(); // Quick null-check.
+ v.acceptWithInsertRemove(this, getArgs());
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ target.accept(visitor);
+ functionName.accept(visitor);
+ visitor.visit(getArgs());
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitMethodInvocation(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartModVisitor.java b/compiler/java/com/google/dart/compiler/ast/DartModVisitor.java
new file mode 100644
index 00000000000..7e9db90ad3f
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartModVisitor.java
@@ -0,0 +1,190 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.util.Hack;
+
+import java.util.List;
+
+/**
+ * A visitor for iterating through and modifying an AST.
+ */
+public class DartModVisitor extends DartVisitor {
+
+ private class ListContext implements DartContext {
+
+ private DartNode parent;
+ private List collection;
+ private int index;
+ private boolean removed;
+ private boolean replaced;
+
+ public ListContext(DartNode parent) {
+ this.parent = parent;
+ }
+
+ public boolean canInsert() {
+ return true;
+ }
+
+ public boolean canRemove() {
+ return true;
+ }
+
+ public void insertAfter(DartVisitable node) {
+ checkRemoved();
+ parent.becomeParentOf((DartNode) node);
+ collection.add(index + 1, Hack.cast(node));
+ didChange = true;
+ }
+
+ public void insertBefore(DartVisitable node) {
+ checkRemoved();
+ parent.becomeParentOf((DartNode) node);
+ collection.add(index++, Hack.cast(node));
+ didChange = true;
+ }
+
+ public boolean isLvalue() {
+ return false;
+ }
+
+ public void removeMe() {
+ checkState();
+ collection.remove(index--);
+ didChange = removed = true;
+ }
+
+ public void replaceMe(DartVisitable node) {
+ checkState();
+ checkReplacement(collection.get(index), node);
+ parent.becomeParentOf((DartNode) node);
+ collection.set(index, Hack.cast(node));
+ didChange = replaced = true;
+ }
+
+ protected void traverse(List collection) {
+ this.collection = collection;
+ for (index = 0; index < collection.size(); ++index) {
+ removed = replaced = false;
+ doTraverse(collection.get(index), this);
+ }
+ }
+
+ private void checkRemoved() {
+ if (removed) {
+ throw new RuntimeException("Node was already removed");
+ }
+ }
+
+ private void checkState() {
+ checkRemoved();
+ if (replaced) {
+ throw new RuntimeException("Node was already replaced");
+ }
+ }
+ }
+
+ private class LvalueContext extends NodeContext {
+ @Override
+ public boolean isLvalue() {
+ return true;
+ }
+ }
+
+ private class NodeContext implements DartContext {
+ private T node;
+ private boolean replaced;
+
+ public boolean canInsert() {
+ return false;
+ }
+
+ public boolean canRemove() {
+ return false;
+ }
+
+ public void insertAfter(DartVisitable node) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void insertBefore(DartVisitable node) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isLvalue() {
+ return false;
+ }
+
+ public void removeMe() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void replaceMe(DartVisitable node) {
+ if (replaced) {
+ throw new RuntimeException("Node was already replaced");
+ }
+ checkReplacement(this.node, node);
+ this.node = Hack.cast(node);
+ didChange = replaced = true;
+ }
+
+ protected T traverse(T node) {
+ this.node = node;
+ replaced = false;
+ doTraverse(node, this);
+ return this.node;
+ }
+ }
+
+ protected static void checkReplacement(T origNode, T newNode) {
+ if (newNode == null) {
+ throw new RuntimeException("Cannot replace with null");
+ }
+ if (newNode == origNode) {
+ throw new RuntimeException("The replacement is the same as the original");
+ }
+ }
+
+ protected boolean didChange = false;
+
+ @Override
+ public boolean didChange() {
+ return didChange;
+ }
+
+ @Override
+ protected T doAccept(T node) {
+ return new NodeContext().traverse(node);
+ }
+
+ @Override
+ protected void doAcceptList(List extends DartVisitable> collection) {
+ doAcceptListImpl(collection);
+ }
+
+ private void doAcceptListImpl(List collection) {
+ NodeContext ctx = new NodeContext();
+ for (int i = 0, c = collection.size(); i < c; ++i) {
+ ctx.traverse(collection.get(i));
+ if (ctx.replaced) {
+ collection.set(i, ctx.node);
+ }
+ }
+ }
+
+ @Override
+ protected DartExpression doAcceptLvalue(DartExpression expr) {
+ return new LvalueContext().traverse(expr);
+ }
+
+ @Override
+ protected List doAcceptWithInsertRemove(
+ DartNode parent, List collection) {
+ ListContext ctx = new ListContext(parent);
+ ctx.traverse(collection);
+ return ctx.collection;
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartNamedExpression.java b/compiler/java/com/google/dart/compiler/ast/DartNamedExpression.java
new file mode 100644
index 00000000000..a49c1cc9d70
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartNamedExpression.java
@@ -0,0 +1,56 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Represents a labeled expression (used in named method arguments).
+ */
+public class DartNamedExpression extends DartExpression {
+
+ private DartIdentifier name;
+ private DartExpression expression;
+
+ public DartNamedExpression(DartIdentifier ident, DartExpression expression) {
+ this.name = ident;
+ this.expression = becomeParentOf(expression);
+ }
+
+ public DartIdentifier getName() {
+ return name;
+ }
+
+ public DartExpression getExpression() {
+ return expression;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ if (name != null) {
+ name = becomeParentOf(v.accept(name));
+ }
+ if (expression != null) {
+ expression = becomeParentOf(v.accept(expression));
+ }
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ if (name != null) {
+ name.accept(visitor);
+ }
+ if (expression != null) {
+ expression.accept(visitor);
+ }
+ expression.accept(visitor);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitNamedExpression(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartNativeBlock.java b/compiler/java/com/google/dart/compiler/ast/DartNativeBlock.java
new file mode 100644
index 00000000000..7030feef4c1
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartNativeBlock.java
@@ -0,0 +1,31 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+
+/**
+ * Unofficial Dart native block for built in native invocations.
+ */
+public class DartNativeBlock extends DartBlock {
+
+ public DartNativeBlock() {
+ super(null);
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ v.visit(this, ctx);
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitNativeBlock(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartNativeDirective.java b/compiler/java/com/google/dart/compiler/ast/DartNativeDirective.java
new file mode 100644
index 00000000000..2780a984fb4
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartNativeDirective.java
@@ -0,0 +1,38 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+/**
+ * Implements the #native directive.
+ */
+public class DartNativeDirective extends DartDirective {
+ private DartStringLiteral nativeUri;
+
+ public DartNativeDirective(DartStringLiteral nativeUri) {
+ this.nativeUri = becomeParentOf(nativeUri);
+ }
+
+ public DartStringLiteral getNativeUri() {
+ return nativeUri;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ nativeUri = becomeParentOf(v.accept(nativeUri));
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ nativeUri.accept(visitor);
+ }
+
+ @Override
+ public R accept(DartPlainVisitor visitor) {
+ return visitor.visitNativeDirective(this);
+ }
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/DartNewExpression.java b/compiler/java/com/google/dart/compiler/ast/DartNewExpression.java
new file mode 100644
index 00000000000..7d9012c604e
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/DartNewExpression.java
@@ -0,0 +1,69 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.ast;
+
+import com.google.dart.compiler.common.HasSymbol;
+import com.google.dart.compiler.common.Symbol;
+import com.google.dart.compiler.resolver.ConstructorElement;
+
+import java.util.List;
+
+/**
+ * Represents a Dart 'new' expression.
+ */
+public class DartNewExpression extends DartInvocation implements HasSymbol {
+
+ private DartNode constructor;
+ private ConstructorElement typeSymbol;
+ private final boolean isConst;
+
+ public DartNewExpression(DartNode constructor, List args, boolean isConst) {
+ super(args);
+ this.constructor = becomeParentOf(constructor);
+ this.isConst = isConst;
+ }
+
+ public DartNode getConstructor() {
+ return constructor;
+ }
+
+ public boolean isConst() {
+ return isConst;
+ }
+
+ @Override
+ public ConstructorElement getSymbol() {
+ return typeSymbol;
+ }
+
+ public void setConstructor(DartExpression newConstructor) {
+ constructor = becomeParentOf(newConstructor);
+ }
+
+ @Override
+ public void setSymbol(Symbol symbol) {
+ this.typeSymbol = (ConstructorElement) symbol;
+ }
+
+ @Override
+ public void traverse(DartVisitor v, DartContext ctx) {
+ if (v.visit(this, ctx)) {
+ constructor = becomeParentOf(v.accept(constructor));
+ v.acceptWithInsertRemove(this, getArgs());
+ }
+ v.endVisit(this, ctx);
+ }
+
+ @Override
+ public void visitChildren(DartPlainVisitor> visitor) {
+ constructor.accept(visitor);
+ visitor.visit(getArgs());
+ }
+
+ @Override
+ public R accept(DartPlainVisitor