/*
* Copyright (c) 2012, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.engine.internal.scope;
import com.google.dart.engine.element.ClassElement;
import com.google.dart.engine.element.CompilationUnitElement;
import com.google.dart.engine.element.Element;
import com.google.dart.engine.element.FunctionElement;
import com.google.dart.engine.element.FunctionTypeAliasElement;
import com.google.dart.engine.element.LibraryElement;
import com.google.dart.engine.element.PrefixElement;
import com.google.dart.engine.element.PropertyAccessorElement;
import com.google.dart.engine.error.AnalysisError;
import com.google.dart.engine.error.AnalysisErrorListener;
import com.google.dart.engine.error.CompileTimeErrorCode;
/**
* Instances of the class {@code LibraryScope} implement a scope containing all of the names defined
* in a given library.
*
* @coverage dart.engine.resolver
*/
public class LibraryScope extends EnclosedScope {
/**
* Initialize a newly created scope representing the names defined in the given library.
*
* @param definingLibrary the element representing the library represented by this scope
* @param errorListener the listener that is to be informed when an error is encountered
*/
public LibraryScope(LibraryElement definingLibrary, AnalysisErrorListener errorListener) {
super(new LibraryImportScope(definingLibrary, errorListener));
defineTopLevelNames(definingLibrary);
}
@Override
protected AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
if (existing instanceof PrefixElement) {
// TODO(scheglov) consider providing actual 'nameOffset' from the synthetic accessor
int offset = duplicate.getNameOffset();
if (duplicate instanceof PropertyAccessorElement) {
PropertyAccessorElement accessor = (PropertyAccessorElement) duplicate;
if (accessor.isSynthetic()) {
offset = accessor.getVariable().getNameOffset();
}
}
return new AnalysisError(
duplicate.getSource(),
offset,
duplicate.getDisplayName().length(),
CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER,
existing.getDisplayName());
}
return super.getErrorForDuplicate(existing, duplicate);
}
/**
* Add to this scope all of the public top-level names that are defined in the given compilation
* unit.
*
* @param compilationUnit the compilation unit defining the top-level names to be added to this
* scope
*/
private void defineLocalNames(CompilationUnitElement compilationUnit) {
for (PropertyAccessorElement element : compilationUnit.getAccessors()) {
define(element);
}
for (ClassElement element : compilationUnit.getEnums()) {
define(element);
}
for (FunctionElement element : compilationUnit.getFunctions()) {
define(element);
}
for (FunctionTypeAliasElement element : compilationUnit.getFunctionTypeAliases()) {
define(element);
}
for (ClassElement element : compilationUnit.getTypes()) {
define(element);
}
}
/**
* Add to this scope all of the names that are explicitly defined in the given library.
*
* @param definingLibrary the element representing the library that defines the names in this
* scope
*/
private final void defineTopLevelNames(LibraryElement definingLibrary) {
for (PrefixElement prefix : definingLibrary.getPrefixes()) {
define(prefix);
}
defineLocalNames(definingLibrary.getDefiningCompilationUnit());
for (CompilationUnitElement compilationUnit : definingLibrary.getParts()) {
defineLocalNames(compilationUnit);
}
}
}