| // Copyright (c) 2012, 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.common.base.Objects; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.Lists; |
| import com.google.common.collect.Sets; |
| import com.google.dart.compiler.DartCompiler; |
| import com.google.dart.compiler.DartCompilerContext; |
| import com.google.dart.compiler.DartSource; |
| import com.google.dart.compiler.LibraryDeps; |
| import com.google.dart.compiler.LibrarySource; |
| import com.google.dart.compiler.resolver.Elements; |
| import com.google.dart.compiler.resolver.LibraryElement; |
| |
| import java.io.IOException; |
| import java.io.Reader; |
| import java.io.Writer; |
| import java.util.Collection; |
| import java.util.LinkedHashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.concurrent.ConcurrentSkipListMap; |
| |
| /** |
| * Represents the parsed source from a {@link LibrarySource}. |
| */ |
| public class LibraryUnit { |
| private final LibrarySource libSource; |
| private final LibraryNode selfSourcePath; |
| private final List<LibraryNode> importPaths = Lists.newArrayList(); |
| private final List<LibraryNode> exportPaths = Lists.newArrayList(); |
| private final List<LibraryNode> sourcePaths = Lists.newArrayList(); |
| private final List<LibraryNode> nativePaths = Lists.newArrayList(); |
| |
| private final Map<String, DartUnit> units = new ConcurrentSkipListMap<String, DartUnit>(); |
| private final List<LibraryImport> imports = Lists.newArrayList(); |
| private final List<LibraryExport> exports = Lists.newArrayList(); |
| |
| private final LibraryElement element; |
| |
| private LibraryDeps deps; |
| |
| private LibraryNode entryNode; |
| private DartUnit selfDartUnit; |
| |
| private String name; |
| |
| private DartExpression entryPoint; |
| |
| private int sourceCount; |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| public LibraryUnit(LibrarySource libSource) { |
| assert libSource != null; |
| this.libSource = libSource; |
| element = Elements.libraryElement(this); |
| |
| // get the name part of the path, since it needs to be relative |
| // TODO(jbrosenberg): change this to use lazy init |
| // Note: We don't want an encoded relative path. |
| String self = libSource.getUri().getSchemeSpecificPart(); |
| int lastSlash; |
| if ((lastSlash = self.lastIndexOf('/')) > -1) { |
| self = self.substring(lastSlash + 1); |
| } |
| selfSourcePath = new LibraryNode(self); |
| } |
| |
| public void addImportPath(LibraryNode path) { |
| assert path != null; |
| importPaths.add(path); |
| } |
| |
| public void addExportPath(LibraryNode path) { |
| assert path != null; |
| exportPaths.add(path); |
| } |
| |
| public void addSourcePath(LibraryNode path) { |
| assert path != null; |
| sourcePaths.add(path); |
| sourceCount++; |
| } |
| |
| public int getSourceCount() { |
| return sourceCount; |
| } |
| |
| public void addNativePath(LibraryNode path) { |
| assert path != null; |
| nativePaths.add(path); |
| } |
| |
| public void putUnit(DartUnit unit) { |
| unit.setLibrary(this); |
| units.put(unit.getSourceName(), unit); |
| } |
| |
| public DartUnit getUnit(String sourceName) { |
| return units.get(sourceName); |
| } |
| |
| public void addImport(LibraryUnit unit, LibraryNode node) { |
| if (unit != null) { |
| if (node != null) { |
| imports.add(new LibraryImport(unit, node.getPrefix(), node.getCombinators())); |
| } else { |
| imports.add(new LibraryImport(unit, null, ImmutableList.<ImportCombinator> of())); |
| } |
| } |
| } |
| |
| public void addExport(LibraryUnit unit, LibraryNode node) { |
| if (unit != null) { |
| if (node != null) { |
| exports.add(new LibraryExport(node.getSourceInfo(), unit, node.getCombinators())); |
| } |
| } |
| } |
| |
| public Collection<LibraryUnit> getLibrariesWithPrefix(String prefixToMatch) { |
| List<LibraryUnit> result = Lists.newArrayList(); |
| for (LibraryImport libraryImport : imports) { |
| if (Objects.equal(libraryImport.getPrefix(), prefixToMatch)) { |
| result.add(libraryImport.getLibrary()); |
| } |
| } |
| return result; |
| } |
| |
| public LibraryElement getElement() { |
| return element; |
| } |
| |
| public Iterable<DartUnit> getUnits() { |
| return units.values(); |
| } |
| |
| public Iterable<LibraryImport> getImports() { |
| return imports; |
| } |
| |
| public List<LibraryExport> getExports() { |
| return exports; |
| } |
| |
| public Iterable<LibraryUnit> getImportedLibraries() { |
| LinkedHashSet<LibraryUnit> libraries = Sets.newLinkedHashSet(); |
| for (LibraryImport libraryImport : imports) { |
| libraries.add(libraryImport.getLibrary()); |
| } |
| return libraries; |
| } |
| |
| public boolean hasImport(LibraryUnit unit) { |
| for (LibraryImport libraryImport : imports) { |
| if (libraryImport.getPrefix() == null && Objects.equal(libraryImport.getLibrary(), unit)) { |
| return true; |
| } |
| } |
| return false; |
| // return imports.contains(new LibraryImport(unit, null, ImmutableList.<ImportCombinator> of())); |
| } |
| |
| public DartExpression getEntryPoint() { |
| return entryPoint; |
| } |
| |
| public void setEntryPoint(DartExpression entry) { |
| this.entryPoint = entry; |
| } |
| |
| public DartUnit getSelfDartUnit() { |
| return this.selfDartUnit; |
| } |
| |
| public void setSelfDartUnit(DartUnit unit) { |
| this.selfDartUnit = unit; |
| // set DartObsoleteMetadata for LibraryElement |
| if (unit != null) { |
| List<DartDirective> directives = unit.getDirectives(); |
| if (!directives.isEmpty() && directives.get(0) instanceof DartLibraryDirective) { |
| DartLibraryDirective libraryDirective = (DartLibraryDirective) directives.get(0); |
| Elements.setLibraryMetadata(element, libraryDirective.getObsoleteMetadata()); |
| } |
| } |
| } |
| |
| /** |
| * Return a collection of paths to {@link LibrarySource}s upon which this library or application |
| * depends. |
| * |
| * @return the paths (not <code>null</code>, contains no <code>null</code>) |
| */ |
| public Iterable<LibraryNode> getImportPaths() { |
| return importPaths; |
| } |
| |
| public Iterable<LibraryNode> getExportPaths() { |
| return exportPaths; |
| } |
| |
| /** |
| * Return all prefixes used by this library. |
| */ |
| public Set<String> getPrefixes() { |
| Set<String> result = Sets.newTreeSet(); |
| for (LibraryImport libraryImport : imports) { |
| String prefix = libraryImport.getPrefix(); |
| if (prefix != null) { |
| result.add(prefix); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Return the path for dart source that corresponds to the same dart file as this library unit. |
| * This is added to the set of sourcePaths for this unit. |
| * |
| * @return the self source path for this unit. |
| */ |
| public LibraryNode getSelfSourcePath() { |
| return selfSourcePath; |
| } |
| |
| /** |
| * Answer the source associated with this unit |
| * |
| * @return the library source (not <code>null</code>) |
| */ |
| public LibrarySource getSource() { |
| return libSource; |
| } |
| |
| /** |
| * Return a collection of paths to {@link DartSource}s that are included in this library or |
| * application. |
| * |
| * @return the paths (not <code>null</code>, contains no <code>null</code>) |
| */ |
| public Iterable<LibraryNode> getSourcePaths() { |
| return sourcePaths; |
| } |
| |
| /** |
| * Returns a collection of paths to native {@link DartSource}s that are included in this library. |
| * |
| * @return the paths (not <code>null</code>, contains no <code>null</code>) |
| */ |
| public Iterable<LibraryNode> getNativePaths() { |
| return nativePaths; |
| } |
| |
| /** |
| * Return the declared entry method, if any |
| * |
| * @return the entry method or <code>null</code> if not defined |
| */ |
| public LibraryNode getEntryNode() { |
| return entryNode; |
| } |
| |
| /** |
| * Set the declared entry method. |
| * |
| * @param libraryNode the entry method or <code>null</code> if none |
| */ |
| public void setEntryNode(LibraryNode libraryNode) { |
| this.entryNode = libraryNode; |
| } |
| |
| /** |
| * Gets the dependencies associated with this library. If no dependencies artifact exists, or the |
| * file is invalid, it will return an empty deps object. |
| */ |
| public LibraryDeps getDeps(DartCompilerContext context) throws IOException { |
| if (deps != null) { |
| return deps; |
| } |
| |
| Reader reader = context.getArtifactReader(libSource, "", DartCompiler.EXTENSION_DEPS); |
| if (reader != null) { |
| deps = LibraryDeps.fromReader(reader); |
| reader.close(); |
| } |
| |
| if (deps == null) { |
| deps = new LibraryDeps(); |
| } |
| return deps; |
| } |
| |
| /** |
| * Writes this library's associated dependencies. |
| */ |
| public void writeDeps(DartCompilerContext context) throws IOException { |
| Writer writer = context.getArtifactWriter(libSource, "", DartCompiler.EXTENSION_DEPS); |
| deps.write(writer); |
| writer.close(); |
| } |
| } |