| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 library initialize.build.initializer_plugin; | 4 library initialize.build.initializer_plugin; |
| 5 | 5 |
| 6 import 'package:analyzer/src/generated/ast.dart'; | 6 import 'package:analyzer/src/generated/ast.dart'; |
| 7 import 'package:analyzer/src/generated/element.dart'; | 7 import 'package:analyzer/src/generated/element.dart'; |
| 8 import 'package:barback/barback.dart'; | 8 import 'package:barback/barback.dart'; |
| 9 import 'package:code_transformers/resolver.dart'; | 9 import 'package:code_transformers/resolver.dart'; |
| 10 import 'package:initialize/transformer.dart'; | 10 import 'package:initialize/transformer.dart'; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 var annotation = pluginData.initializer.annotationNode; | 85 var annotation = pluginData.initializer.annotationNode; |
| 86 if (annotation == null) { | 86 if (annotation == null) { |
| 87 logger.error( | 87 logger.error( |
| 88 'Initializer annotations are only supported on libraries, classes, ' | 88 'Initializer annotations are only supported on libraries, classes, ' |
| 89 'and top level methods. Found $node.'); | 89 'and top level methods. Found $node.'); |
| 90 } | 90 } |
| 91 var clazz = annotation.name; | 91 var clazz = annotation.name; |
| 92 var constructor = annotation.constructorName == null | 92 var constructor = annotation.constructorName == null |
| 93 ? '' | 93 ? '' |
| 94 : '.${annotation.constructorName}'; | 94 : '.${annotation.constructorName}'; |
| 95 // TODO(jakemac): Support more than raw values here | |
| 96 // https://github.com/dart-lang/static_init/issues/5 | |
| 97 var args = buildArgumentList(annotation.arguments, pluginData); | 95 var args = buildArgumentList(annotation.arguments, pluginData); |
| 98 return 'const $metaPrefix.${clazz}$constructor$args'; | 96 return 'const $metaPrefix.${clazz}$constructor$args'; |
| 99 } | 97 } |
| 100 | 98 |
| 101 /// Builds a [String] representing the meta of an [InitEntry] given an | 99 /// Builds a [String] representing the meta of an [InitEntry] given an |
| 102 /// [ElementAnnotation] whose element was a [PropertyAccessorElement]. | 100 /// [ElementAnnotation] whose element was a [PropertyAccessorElement]. |
| 103 String buildPropertyMeta( | 101 String buildPropertyMeta( |
| 104 ElementAnnotation annotation, InitializerPluginData pluginData) { | 102 ElementAnnotation annotation, InitializerPluginData pluginData) { |
| 105 var metaPrefix = pluginData.libraryPrefixes[annotation.element.library]; | 103 var metaPrefix = pluginData.libraryPrefixes[annotation.element.library]; |
| 106 return '$metaPrefix.${annotation.element.name}'; | 104 return '$metaPrefix.${annotation.element.name}'; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 return buffer.toString(); | 193 return buffer.toString(); |
| 196 } | 194 } |
| 197 | 195 |
| 198 /// Builds a [String] representing [expression] taking into account the | 196 /// Builds a [String] representing [expression] taking into account the |
| 199 /// [libraryPrefixes] from [pluginData]. | 197 /// [libraryPrefixes] from [pluginData]. |
| 200 String buildExpression( | 198 String buildExpression( |
| 201 Expression expression, InitializerPluginData pluginData) { | 199 Expression expression, InitializerPluginData pluginData) { |
| 202 var logger = pluginData.logger; | 200 var logger = pluginData.logger; |
| 203 var libraryPrefixes = pluginData.libraryPrefixes; | 201 var libraryPrefixes = pluginData.libraryPrefixes; |
| 204 var buffer = new StringBuffer(); | 202 var buffer = new StringBuffer(); |
| 205 if (expression is StringLiteral) { | 203 if (expression is StringLiteral && expression.stringValue != null) { |
| 206 var value = expression.stringValue; | 204 buffer.write(_stringValue(expression.stringValue)); |
| 207 if (value == null) { | |
| 208 logger.error('Only const strings are allowed in initializer ' | |
| 209 'expressions, found $expression'); | |
| 210 } | |
| 211 value = value.replaceAll(r'\', r'\\').replaceAll(r"'", r"\'"); | |
| 212 buffer.write("'$value'"); | |
| 213 } else if (expression is BooleanLiteral || | 205 } else if (expression is BooleanLiteral || |
| 214 expression is DoubleLiteral || | 206 expression is DoubleLiteral || |
| 215 expression is IntegerLiteral || | 207 expression is IntegerLiteral || |
| 216 expression is NullLiteral) { | 208 expression is NullLiteral) { |
| 217 buffer.write('${expression}'); | 209 buffer.write('${expression}'); |
| 218 } else if (expression is ListLiteral) { | 210 } else if (expression is ListLiteral) { |
| 219 buffer.write('const ['); | 211 buffer.write('const ['); |
| 220 var first = true; | 212 var first = true; |
| 221 for (Expression listExpression in expression.elements) { | 213 for (Expression listExpression in expression.elements) { |
| 222 if (!first) buffer.write(', '); | 214 if (!first) buffer.write(', '); |
| 223 first = false; | 215 first = false; |
| 224 buffer.write(buildExpression(listExpression, pluginData)); | 216 buffer.write(buildExpression(listExpression, pluginData)); |
| 225 } | 217 } |
| 226 buffer.write(']'); | 218 buffer.write(']'); |
| 227 } else if (expression is MapLiteral) { | 219 } else if (expression is MapLiteral) { |
| 228 buffer.write('const {'); | 220 buffer.write('const {'); |
| 229 var first = true; | 221 var first = true; |
| 230 for (MapLiteralEntry entry in expression.entries) { | 222 for (MapLiteralEntry entry in expression.entries) { |
| 231 if (!first) buffer.write(', '); | 223 if (!first) buffer.write(', '); |
| 232 first = false; | 224 first = false; |
| 233 buffer.write(buildExpression(entry.key, pluginData)); | 225 buffer.write(buildExpression(entry.key, pluginData)); |
| 234 buffer.write(': '); | 226 buffer.write(': '); |
| 235 buffer.write(buildExpression(entry.value, pluginData)); | 227 buffer.write(buildExpression(entry.value, pluginData)); |
| 236 } | 228 } |
| 237 buffer.write('}'); | 229 buffer.write('}'); |
| 238 } else if (expression is Identifier) { | 230 } else if (expression is Identifier) { |
| 239 var element = expression.bestElement; | 231 var element = expression.bestElement; |
| 240 if (element == null || !element.isPublic) { | 232 if (element == null || !element.isPublic) { |
| 241 logger.error('Private constants are not supported in intializer ' | 233 logger.error('Private constants are not supported in intializer ' |
| 242 'constructors, found $element.'); | 234 'constructors, found $element.'); |
| 243 } | 235 } |
| 244 libraryPrefixes.putIfAbsent( | 236 libraryPrefixes.putIfAbsent( |
| 245 element.library, () => 'i${libraryPrefixes.length}'); | 237 element.library, () => 'i${libraryPrefixes.length}'); |
| 246 | 238 |
| 247 buffer.write('${libraryPrefixes[element.library]}.'); | 239 buffer.write('${libraryPrefixes[element.library]}.'); |
| 248 if (element is ClassElement) { | 240 if (element is ClassElement) { |
| 249 buffer.write(element.name); | 241 buffer.write(element.name); |
| 250 } else if (element is PropertyAccessorElement) { | 242 } else if (element is PropertyAccessorElement) { |
| 251 var variable = element.variable; | 243 var variable = element.variable; |
| 252 if (variable is FieldElement) { | 244 if (variable is FieldElement) { |
| 253 buffer.write('${variable.enclosingElement.name}.'); | 245 buffer.write('${variable.enclosingElement.name}.'); |
| 254 } | 246 } |
| 255 buffer.write('${variable.name}'); | 247 buffer.write('${variable.name}'); |
| 256 } else { | 248 } else { |
| 257 logger.error('Unsupported argument to initializer constructor.'); | 249 logger.error('Unsupported argument to initializer constructor.'); |
| 258 } | 250 } |
| 251 } else if (expression is PropertyAccess) { |
| 252 buffer.write(buildExpression(expression.target, pluginData)); |
| 253 buffer.write('.${expression.propertyName}'); |
| 254 } else if (expression is InstanceCreationExpression) { |
| 255 logger.error('Unsupported expression in initializer, found $expression. ' |
| 256 'Instance creation expressions are not supported (yet). Instead, ' |
| 257 'please assign it to a const variable and use that instead.'); |
| 259 } else { | 258 } else { |
| 260 logger.error('Only literals and identifiers are allowed for initializer ' | 259 // Try to evaluate the constant and use that. |
| 261 'expressions, found $expression.'); | 260 var result = pluginData.resolver.evaluateConstant( |
| 261 pluginData.initializer.targetElement.library, expression); |
| 262 if (!result.isValid) { |
| 263 logger.error('Invalid expression in initializer, found $expression. ' |
| 264 'And got the following errors: ${result.errors}.'); |
| 265 } |
| 266 var value = result.value.value; |
| 267 if (value == null) { |
| 268 logger.error('Unsupported expression in initializer, found ' |
| 269 '$expression. Please file a bug at ' |
| 270 'https://github.com/dart-lang/initialize/issues'); |
| 271 } |
| 272 |
| 273 if (value is String) value = _stringValue(value); |
| 274 buffer.write(value); |
| 262 } | 275 } |
| 263 return buffer.toString(); | 276 return buffer.toString(); |
| 264 } | 277 } |
| 278 |
| 279 // Returns an expression for a string value. Wraps it in single quotes and |
| 280 // escapes existing single quotes and escapes. |
| 281 _stringValue(String value) { |
| 282 value = value.replaceAll(r'\', r'\\').replaceAll(r"'", r"\'"); |
| 283 return "'$value'"; |
| 284 } |
| 265 } | 285 } |
| OLD | NEW |