Update map literal syntax to expect only one type parameter

As of the spec v0.6, the correct syntax is now:
  <V>{"key" : value };
Whereas you used to also specify the key. Added a deprecation warning
for the old syntax.

http://code.google.com/p/dart/issues/detail?id=1151

Review URL: https://chromiumcodereview.appspot.com//9235015

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@3606 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
zundel@google.com 2012-01-25 20:21:24 +00:00
parent 86fa666526
commit 7169189529
11 changed files with 72 additions and 29 deletions

View file

@ -23030,9 +23030,7 @@ class EventsImplementation implements Events {
Map<String, EventListenerList> _listenerMap;
EventsImplementation._wrap(this._ptr) {
// TODO(sigmund): the key type (String) yields a warning in frog and the vm,
// but it is currently necessary to compile with dartc.
_listenerMap = <String, EventListenerList>{};
_listenerMap = <EventListenerList>{};
}
EventListenerList operator [](String type) {

View file

@ -1,4 +1,4 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// 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.
@ -9,9 +9,7 @@ class EventsImplementation implements Events {
Map<String, EventListenerList> _listenerMap;
EventsImplementation._wrap(this._ptr) {
// TODO(sigmund): the key type (String) yields a warning in frog and the vm,
// but it is currently necessary to compile with dartc.
_listenerMap = <String, EventListenerList>{};
_listenerMap = <EventListenerList>{};
}
EventListenerList operator [](String type) {

View file

@ -278,7 +278,7 @@ public class ResolutionContext implements ResolutionErrorListener {
errorCode instanceof ResolverErrorCode
? ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS
: TypeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS;
onError(node, wrongNumberErrorCode, element.getType(), typeParameters.size());
onError(node, wrongNumberErrorCode, element.getType(), typeArgumentNodes.size(), typeParameters.size());
}
int index = 0;
if (typeArgumentNodes != null) {

View file

@ -5,6 +5,7 @@
package com.google.dart.compiler.resolver;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.dart.compiler.DartCompilationPhase;
import com.google.dart.compiler.DartCompilerContext;
@ -1606,7 +1607,34 @@ public class Resolver {
@Override
public Element visitMapLiteral(DartMapLiteral node) {
List<DartTypeNode> typeArgs = node.getTypeArguments();
List<DartTypeNode> originalTypeArgs = node.getTypeArguments();
List<DartTypeNode> typeArgs = Lists.newArrayList();
DartTypeNode implicitKey = new DartTypeNode(
new DartIdentifier("String"));
switch (originalTypeArgs.size()) {
case 1:
typeArgs.add(implicitKey);
typeArgs.addAll(originalTypeArgs);
break;
case 2:
// Old (pre spec 0.6) map specification
// TODO(zundel): remove this case after a while (added on 24 Jan 2012)
typeArgs.add(implicitKey);
typeArgs.add(originalTypeArgs.get(1));
topLevelContext.onError(originalTypeArgs.get(0), ResolverErrorCode.DEPRECATED_MAP_LITERAL_SYNTAX);
break;
default:
topLevelContext.onError(node, ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
defaultLiteralMapType,
originalTypeArgs.size(), 1);
// fall through
case 0:
typeArgs.add(implicitKey);
DartTypeNode implicitValue = new DartTypeNode(new DartIdentifier("Dynamic"));
typeArgs.add(implicitValue);
break;
}
InterfaceType type =
topLevelContext.instantiateParameterizedType(
defaultLiteralMapType.getElement(),

View file

@ -59,6 +59,8 @@ public enum ResolverErrorCode implements ErrorCode {
DEFAULT_CONSTRUCTOR_NAMED_PARAMETERS(
"Constructor '%s' in '%s' has named parameters %s, doesn't match '%s' in '%s' with %s"),
DEFAULT_MUST_SPECIFY_CLASS("default must indicate a class, not an interface"),
DEPRECATED_MAP_LITERAL_SYNTAX(ErrorSeverity.WARNING,
"Deprecated Map literal syntax. Only specify a single value type as a type argument."),
DID_YOU_MEAN_NEW("%1$s is a %2$s. Did you mean (new %1$s)?"),
DUPLICATED_INTERFACE("%s and %s are duplicated in the supertype graph"),
DUPLICATE_INITIALIZATION(ErrorSeverity.ERROR, "Duplicate initialization of '%s'"),
@ -145,7 +147,7 @@ public enum ResolverErrorCode implements ErrorCode {
TYPE_PARAMETERS_MUST_MATCH_EXACTLY(
"Type parameters in default declaration must match referenced class exactly"),
TYPE_VARIABLE_IN_STATIC_CONTEXT("cannot access type variable %s in static context"),
WRONG_NUMBER_OF_TYPE_ARGUMENTS("%s: wrong number of type arguments. Expected %d");
WRONG_NUMBER_OF_TYPE_ARGUMENTS("%s: wrong number of type arguments (%d). Expected %d");
private final ErrorSeverity severity;
private final String message;

View file

@ -50,7 +50,7 @@ public enum TypeErrorCode implements ErrorCode {
TYPE_NOT_ASSIGNMENT_COMPATIBLE("%s is not assignable to %s"),
USE_ASSIGNMENT_ON_SETTER("Use assignment to set field \"%s\" in %s"),
VOID("expression does not yield a value"),
WRONG_NUMBER_OF_TYPE_ARGUMENTS("%s: wrong number of type arguments, Expected %d");
WRONG_NUMBER_OF_TYPE_ARGUMENTS("%s: wrong number of type arguments (%d), Expected %d");
private final ErrorSeverity severity;
private final String message;

View file

@ -1059,8 +1059,8 @@ public class TypeAnalyzer implements DartCompilationPhase {
visit(node.getTypeArguments());
InterfaceType type = node.getType();
// This ensures that the declared type is assignable to Map<String, dynamic>.
// For example, the user should not write Map<int,int>.
// The Map literal has an implicit key type of String, so only one parameter is
// specified <V> where V is the type of the value.
checkAssignable(node, type, defaultLiteralMapType);
Type valueType = type.getArguments().get(1);

View file

@ -23,10 +23,10 @@ class ListObjectLiterals {
var n = <int>[1,2,3];
var o = const {};
var p = const <String, int>{};
var q = <String, int>{};
var p = const <int>{};
var q = <int>{};
var r = const {'a':1, 'b':2, 'c':3};
var s = const <String, int> {'a':1, 'b':2, 'c':3 };
var s = const <int> {'a':1, 'b':2, 'c':3 };
var t = {'a':1, 'b':2, 'c':3};
}
}

View file

@ -971,15 +971,32 @@ public class ResolverTest extends ResolverTestCase {
public void test_noSuchType_mapLiteral_typeArgument() throws Exception {
resolveAndTest(Joiner.on("\n").join(
"class Object {}",
"class String {}",
"class MyClass {",
" foo() {",
" var map = <T>{};",
" }",
"}"),
ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
ResolverErrorCode.NO_SUCH_TYPE);
}
public void test_noSuchType_mapLiteral_num_type_args() throws Exception {
resolveAndTest(Joiner.on("\n").join(
"class Object {}",
"interface int {}",
"interface String {}",
"class MyClass {",
" foo() {",
" var map0 = {};",
" var map1 = <int>{'foo': 1};",
" var map2 = <String, int>{'foo' : 1};",
" var map3 = <String, int, int>{'foo' : 1};",
" }",
"}"),
ResolverErrorCode.DEPRECATED_MAP_LITERAL_SYNTAX,
ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS);
}
public void test_noSuchType_arrayLiteral_typeArgument() throws Exception {
resolveAndTest(Joiner.on("\n").join(
"class Object {}",

View file

@ -715,25 +715,25 @@ public class TypeAnalyzerTest extends TypeAnalyzerTestCase {
public void testMapLiteral() {
analyze("{ var x = {\"key\": 42}; }");
analyze("{ var x = {'key': 42}; }");
analyze("{ var x = <String, num>{'key': 42}; }");
analyze("{ var x = <String, int>{'key': 42}; }");
analyze("{ var x = <String, num>{'key': 0.42}; }");
analyze("{ var x = <Object, num>{'key': 42}; }");
analyzeFail("{ var x = <String, int>{'key': 0.42}; }",
analyze("{ var x = <num>{'key': 42}; }");
analyze("{ var x = <int>{'key': 42}; }");
analyze("{ var x = <num>{'key': 0.42}; }");
analyze("{ var x = <num>{'key': 42}; }");
analyzeFail("{ var x = <int>{'key': 0.42}; }",
TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
analyzeFail("{ int i; var x = {'key': i = 0.42}; }",
TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
analyze("{ var x = const {\"key\": 42}; }");
analyze("{ var x = const {'key': 42}; }");
analyze("{ var x = const <String, num>{'key': 42}; }");
analyze("{ var x = const <String, int>{'key': 42}; }");
analyze("{ var x = const <String, num>{'key': 0.42}; }");
analyze("{ var x = const <Object, num>{'key': 42}; }");
analyzeFail("{ var x = const <String, int>{'key': 0.42}; }",
analyze("{ var x = const <num>{'key': 42}; }");
analyze("{ var x = const <int>{'key': 42}; }");
analyze("{ var x = const <num>{'key': 0.42}; }");
analyze("{ var x = const <num>{'key': 42}; }");
analyzeFail("{ var x = const <int>{'key': 0.42}; }",
TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
analyzeFail("{ int i; var x = const {'key': i = 0.42}; }",
TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
analyzeFail("{var x = const <num, num>{}; }",
analyzeFail("{Map<num, num> x = const <num>{}; }",
TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
}

View file

@ -132,7 +132,7 @@ ListLiteral4Test: Fail # Issue 220
ListTest: Fail # Bug 5146975.
LocalFunction3Test: Fail # Bug 4202974.
LocalFunctionTest: Fail # Bug in test. Bug 4202989 (shadowing).
MapLiteral3Test: Fail # Issue 221
MapLiteral1NegativeTest: Fail # Issue 221
MapLiteral4Test: Fail # Issue 221
ManyOverriddenNoSuchMethodTest: Fail # Bug 4202974.
NamedParametersTypeTest: Fail # Implementation in progress.