blob: e64e4d0f2699a954eb2bf592dbb38442acf241ab [file] [log] [blame]
// Copyright (c) 2022, 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.
/// @assertion @metadata (a, b) function() {}
/// This could be a metadata annotation @metadata(a, b) associated with a
/// function declaration with no return type. Or it could be a metadata
/// annotation @metadata associated with a function whose return type is the
/// record type (a, b).
///
/// In practice, idiomatically written code is clear thanks to whitespace:
///
/// @metadata(a, b) function() {}
///
/// @metadata (a, b) function() {}
///
/// The former applies (a, b) to the metadata annotation and the latter is a
/// return type. We disambiguate in the same way, by making whitespace after a
/// metadata annotation name significant. Change the grammar to:
///
/// metadatum ::= identifier // Existing rule.
/// | qualifiedName // Existing rule.
/// | constructorDesignation NO_SPACE arguments // Changed.
/// The NO_SPACE lexical rule matches when there are no whitespace characters or
/// comments (according to the existing WHITESPACE and COMMENT lexical rules)
/// between the constructorDesignation and arguments. In other words, for an
/// argument list to be part of the metadata annotation, the ( must occur
/// immediately after the last character in the constructorDesignation. The last
/// character in constructorDesignation may be an identifier or the > in a type
/// argument list.
///
/// @description Checks that it is a compile-time error if there is a space
/// between metadata and its arguments list.
/// @author sgrekhov22@gmail.com
class Meta {
const Meta(Type t1, Type t2);
}
class M {
const M();
}
/**/@Meta (int, String) foo1() => (1, "2");
// ^^^^^
// [analyzer] unspecified
// [cfe] unspecified
/**/@Meta
// ^^^^^
// [analyzer] unspecified
// [cfe] unspecified
(int, String) foo2() => (3, "4");
/**/@M () foo3() => ();
// ^^
// [analyzer] unspecified
// [cfe] unspecified
/**/@M
// ^^
// [analyzer] unspecified
// [cfe] unspecified
() foo4() => ();
/**/@Meta/* comment */(int, String) foo5() => (5, "6");
// ^^^^^
// [analyzer] unspecified
// [cfe] unspecified
/**/@Meta // comment
// ^^^^^
// [analyzer] unspecified
// [cfe] unspecified
(int, String) foo6() => (7, "8");
/**/@M/* comment */ () foo7() => ();
// ^^
// [analyzer] unspecified
// [cfe] unspecified
/**/@M // comment
// ^^
// [analyzer] unspecified
// [cfe] unspecified
() foo8() => ();
main() {
foo1();
foo2();
foo3();
foo4();
foo5();
foo6();
foo7();
foo8();
}