blob: 2bd491fbdbb2345b17354b356ccfb61b4558c927 [file] [log] [blame]
// 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.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(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() {
Set<LibraryUnit> libraries = Sets.newHashSet();
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();
}
}