/*
* Copyright (c) 2013, 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.resolver;
import com.google.dart.engine.EngineTestCase;
import com.google.dart.engine.element.ClassElement;
import com.google.dart.engine.element.CompilationUnitElement;
import com.google.dart.engine.element.LibraryElement;
import com.google.dart.engine.element.PropertyAccessorElement;
import com.google.dart.engine.error.CompileTimeErrorCode;
import com.google.dart.engine.error.ErrorCode;
import com.google.dart.engine.error.GatheringErrorListener;
import com.google.dart.engine.internal.context.AnalysisContextImpl;
import com.google.dart.engine.resolver.ResolverErrorCode;
import com.google.dart.engine.sdk.DirectoryBasedDartSdk;
import com.google.dart.engine.source.DartUriResolver;
import com.google.dart.engine.source.FileBasedSource;
import com.google.dart.engine.source.FileUriResolver;
import com.google.dart.engine.source.Source;
import com.google.dart.engine.source.SourceFactory;
import static com.google.dart.engine.utilities.io.FileUtilities2.createFile;
import java.lang.reflect.Method;
public class LibraryElementBuilderTest extends EngineTestCase {
/**
* The analysis context used to analyze sources.
*/
private AnalysisContextImpl context;
@Override
public void setUp() {
SourceFactory sourceFactory = new SourceFactory(new DartUriResolver(
DirectoryBasedDartSdk.getDefaultSdk()), new FileUriResolver());
context = new AnalysisContextImpl();
context.setSourceFactory(sourceFactory);
}
public void test_accessorsAcrossFiles() throws Exception {
Source librarySource = addSource("/lib.dart", createSource(//
"library lib;",
"part 'first.dart';",
"part 'second.dart';"));
addSource("/first.dart", createSource(//
"part of lib;",
"int get V => 0;"));
addSource("/second.dart", createSource(//
"part of lib;",
"void set V(int v) {}"));
LibraryElement element = buildLibrary(librarySource);
assertNotNull(element);
CompilationUnitElement[] sourcedUnits = element.getParts();
assertLength(2, sourcedUnits);
PropertyAccessorElement[] firstAccessors = sourcedUnits[0].getAccessors();
assertLength(1, firstAccessors);
PropertyAccessorElement[] secondAccessors = sourcedUnits[1].getAccessors();
assertLength(1, secondAccessors);
assertSame(firstAccessors[0].getVariable(), secondAccessors[0].getVariable());
}
public void test_empty() throws Exception {
Source librarySource = addSource("/lib.dart", "library lib;");
LibraryElement element = buildLibrary(librarySource);
assertNotNull(element);
assertEquals("lib", element.getName());
assertNull(element.getEntryPoint());
assertLength(0, element.getImportedLibraries());
assertLength(0, element.getImports());
assertSame(element, element.getLibrary());
assertLength(0, element.getPrefixes());
assertLength(0, element.getParts());
CompilationUnitElement unit = element.getDefiningCompilationUnit();
assertNotNull(unit);
assertEquals("lib.dart", unit.getName());
assertEquals(element, unit.getLibrary());
assertLength(0, unit.getAccessors());
assertLength(0, unit.getFunctions());
assertLength(0, unit.getFunctionTypeAliases());
assertLength(0, unit.getTypes());
assertLength(0, unit.getTopLevelVariables());
}
public void test_missingLibraryDirectiveWithPart() throws Exception {
addSource("/a.dart", createSource(//
"part of lib;"));
Source librarySource = addSource("/lib.dart", createSource(//
"part 'a.dart';"));
LibraryElement element = buildLibrary(
librarySource,
ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART);
assertNotNull(element);
}
public void test_missingPartOfDirective() throws Exception {
addSource("/a.dart", "class A {}");
Source librarySource = addSource("/lib.dart", createSource(//
"library lib;",
"",
"part 'a.dart';"));
LibraryElement element = buildLibrary(librarySource, CompileTimeErrorCode.PART_OF_NON_PART);
assertNotNull(element);
}
public void test_multipleFiles() throws Exception {
Source librarySource = addSource("/lib.dart", createSource(//
"library lib;",
"part 'first.dart';",
"part 'second.dart';",
"",
"class A {}"));
addSource("/first.dart", createSource(//
"part of lib;",
"class B {}"));
addSource("/second.dart", createSource(//
"part of lib;",
"class C {}"));
LibraryElement element = buildLibrary(librarySource);
assertNotNull(element);
CompilationUnitElement[] sourcedUnits = element.getParts();
assertLength(2, sourcedUnits);
assertTypes(element.getDefiningCompilationUnit(), "A");
if (sourcedUnits[0].getName().equals("first.dart")) {
assertTypes(sourcedUnits[0], "B");
assertTypes(sourcedUnits[1], "C");
} else {
assertTypes(sourcedUnits[0], "C");
assertTypes(sourcedUnits[1], "B");
}
}
public void test_singleFile() throws Exception {
Source librarySource = addSource("/lib.dart", createSource(//
"library lib;",
"",
"class A {}"));
LibraryElement element = buildLibrary(librarySource);
assertNotNull(element);
assertTypes(element.getDefiningCompilationUnit(), "A");
}
/**
* Add a source file to the content provider. The file path should be absolute.
*
* @param filePath the path of the file being added
* @param contents the contents to be returned by the content provider for the specified file
* @return the source object representing the added file
*/
protected Source addSource(String filePath, String contents) {
Source source = new FileBasedSource(createFile(filePath));
context.setContents(source, contents);
return source;
}
@Override
protected void tearDown() throws Exception {
context = null;
super.tearDown();
}
/**
* Ensure that there are elements representing all of the types in the given array of type names.
*
* @param unit the compilation unit containing the types
* @param typeNames the names of the types that should be found
*/
private void assertTypes(CompilationUnitElement unit, String... typeNames) {
assertNotNull(unit);
ClassElement[] types = unit.getTypes();
assertLength(typeNames.length, types);
for (ClassElement type : types) {
assertNotNull(type);
String actualTypeName = type.getDisplayName();
boolean wasExpected = false;
for (String expectedTypeName : typeNames) {
if (expectedTypeName.equals(actualTypeName)) {
wasExpected = true;
}
}
if (!wasExpected) {
fail("Found unexpected type " + actualTypeName);
}
}
}
/**
* Build the element model for the library whose defining compilation unit has the given source.
*
* @param librarySource the source of the defining compilation unit for the library
* @param expectedErrorCodes the errors that are expected to be found while building the element
* model
* @return the element model that was built for the library
* @throws Exception if the element model could not be built
*/
private LibraryElement buildLibrary(Source librarySource, ErrorCode... expectedErrorCodes)
throws Exception {
LibraryResolver resolver = new LibraryResolver(context);
LibraryElementBuilder builder = new LibraryElementBuilder(
resolver.getAnalysisContext(),
resolver.getErrorListener());
Method method = resolver.getClass().getDeclaredMethod(
"createLibrary",
new Class[] {Source.class});
method.setAccessible(true);
Library library = (Library) method.invoke(resolver, librarySource);
LibraryElement element = builder.buildLibrary(library);
GatheringErrorListener listener = new GatheringErrorListener();
listener.addAll(resolver.getErrorListener());
listener.assertErrorsWithCodes(expectedErrorCodes);
return element;
}
}