Allow empty URI strings in library directives

Fixes #38859

Change-Id: I1698b09bfee367634782f6f7c61f1dbda22edc0a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/127600
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Sam Rawlins 2019-12-11 02:20:16 +00:00 committed by commit-bot@chromium.org
parent 18b2d24887
commit bd008dd1e4
11 changed files with 77 additions and 45 deletions

View file

@ -134,9 +134,12 @@ class SourceFactoryImpl implements SourceFactory {
@override
Source resolveUri(Source containingSource, String containedUri) {
if (containedUri == null || containedUri.isEmpty) {
if (containedUri == null) {
return null;
}
if (containedUri.isEmpty) {
return containingSource;
}
try {
// Force the creation of an escaped URI to deal with spaces, etc.
return _internalResolveUri(containingSource, Uri.parse(containedUri));

View file

@ -521,7 +521,8 @@ class LibraryAnalyzer {
return file.exists;
}
}
return false;
// A library can refer to itself with an empty URI.
return source == _library.source;
}
/**

View file

@ -10192,6 +10192,9 @@ abstract class UriBasedDirectiveImpl extends DirectiveImpl
if (uriContent == null) {
return UriValidationCode.INVALID_URI;
}
if (uriContent.isEmpty) {
return null;
}
if (isImport && uriContent.startsWith(_DART_EXT_SCHEME)) {
return UriValidationCode.URI_WITH_DART_EXT_SCHEME;
}

View file

@ -296,7 +296,7 @@ class LibraryBuilder {
directive.configurations,
directive.uri.stringValue,
);
if (relativeUriStr == null || relativeUriStr.isEmpty) {
if (relativeUriStr == null) {
return null;
}
var relativeUri = Uri.parse(relativeUriStr);

View file

@ -137,7 +137,7 @@ class LinkedUnitContext {
/// Return the [LibraryElement] referenced in the [node].
LibraryElement directiveLibrary(UriBasedDirective node) {
var uriStr = LazyDirective.getSelectedUri(node);
if (uriStr == null || uriStr.isEmpty) return null;
if (uriStr == null) return null;
return bundleContext.elementFactory.libraryOfUri(uriStr);
}

View file

@ -2354,31 +2354,6 @@ class A<E> {
]);
}
test_invalidUri_export() async {
await assertErrorsInCode('''
export 'ht:';
''', [
error(CompileTimeErrorCode.INVALID_URI, 7, 5),
]);
}
test_invalidUri_import() async {
await assertErrorsInCode('''
import 'ht:';
''', [
error(CompileTimeErrorCode.INVALID_URI, 7, 5),
]);
}
test_invalidUri_part() async {
await assertErrorsInCode(r'''
library lib;
part 'ht:';
''', [
error(CompileTimeErrorCode.INVALID_URI, 18, 5),
]);
}
test_isInConstInstanceCreation_restored() async {
// If ErrorVerifier._isInConstInstanceCreation is not properly restored on
// exit from visitInstanceCreationExpression, the error at (1) will be

View file

@ -74,9 +74,9 @@ void f() {
test_invalidUri() {
assertErrorsInCode('''
import '' deferred as foo;
import 'ht:' deferred as foo;
''', [
error(CompileTimeErrorCode.INVALID_URI, 7, 2),
error(CompileTimeErrorCode.INVALID_URI, 7, 5),
]);
}
}

View file

@ -0,0 +1,53 @@
// Copyright (c) 2019, 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.
import 'package:analyzer/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../dart/resolution/driver_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(InvalidUriTest);
});
}
@reflectiveTest
class InvalidUriTest extends DriverResolutionTest {
test_emptyUri() async {
await assertNoErrorsInCode('''
import '' as top;
int x;
class C {
int x;
int get y => top.x; // ref
}
''');
assertElement(findNode.simple('x; // ref'), findElement.topGet('x'));
}
test_invalidScheme_export() async {
await assertErrorsInCode('''
export 'ht:';
''', [
error(CompileTimeErrorCode.INVALID_URI, 7, 5),
]);
}
test_invalidScheme_import() async {
await assertErrorsInCode('''
import 'ht:';
''', [
error(CompileTimeErrorCode.INVALID_URI, 7, 5),
]);
}
test_invalidScheme_part() async {
await assertErrorsInCode(r'''
part 'ht:';
''', [
error(CompileTimeErrorCode.INVALID_URI, 5, 5),
]);
}
}

View file

@ -160,6 +160,7 @@ import 'invalid_required_optional_positional_param_test.dart'
import 'invalid_required_positional_param_test.dart'
as invalid_required_positional_param;
import 'invalid_sealed_annotation_test.dart' as invalid_sealed_annotation;
import 'invalid_uri_test.dart' as invalid_uri;
import 'invalid_use_of_covariant_in_extension_test.dart'
as invalid_use_of_covariant_in_extension;
import 'invalid_use_of_never_value_test.dart' as invalid_use_of_never_value;
@ -504,6 +505,7 @@ main() {
invalid_required_optional_positional_param.main();
invalid_required_positional_param.main();
invalid_sealed_annotation.main();
invalid_uri.main();
invalid_use_of_covariant_in_extension.main();
invalid_use_of_never_value.main();
invalid_use_of_null_value.main();

View file

@ -6801,7 +6801,7 @@ Future<dynamic> f;
allowMissingFiles = true;
var library = await checkLibrary('''
@foo
import '';
import 'ht:';
''');
checkElementText(library, r'''
@
@ -7878,19 +7878,18 @@ class C {
''');
}
test_invalidUri_part_emptyUri() async {
test_part_emptyUri() async {
allowMissingFiles = true;
var library = await checkLibrary(r'''
part '';
class B extends A {}
''');
checkElementText(library, r'''
part '<unresolved>';
part 'test.dart';
class B {
}
class B {
}
--------------------
unit: null
''');
}

View file

@ -27,7 +27,6 @@ class export { }
// [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
// [cfe] Expected an identifier, but got 'export'.
// [error line 19, column 14, length 0]
// [analyzer] COMPILE_TIME_ERROR.INVALID_URI
// [cfe] Expected ';' after this.
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_EXECUTABLE
@ -63,11 +62,9 @@ class implements { }
// ^^^^^^^^^^
// [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
// [cfe] Expected an identifier, but got 'implements'.
// [error line 62, column 18, length 0]
// [error line 61, column 18, length 0]
// [analyzer] COMPILE_TIME_ERROR.IMPLEMENTS_NON_CLASS
// [cfe] Expected a type, but got '{'.
// [error line 62, column 18, length 0]
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_CLASS
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TYPE_NAME
class import { }
@ -80,8 +77,7 @@ class import { }
// ^^^^^^
// [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
// [cfe] Expected an identifier, but got 'import'.
// [error line 73, column 14, length 0]
// [analyzer] COMPILE_TIME_ERROR.INVALID_URI
// [error line 70, column 14, length 0]
// [cfe] Expected ';' after this.
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_EXECUTABLE
@ -134,8 +130,8 @@ class part { }
// ^^^^
// [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
// [cfe] Expected an identifier, but got 'part'.
// [error line 127, column 12, length 0]
// [analyzer] COMPILE_TIME_ERROR.INVALID_URI
// [error line 123, column 12, length 0]
// [analyzer] COMPILE_TIME_ERROR.PART_OF_NON_PART
// [cfe] Expected ';' after this.
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_EXECUTABLE