| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 | 4 |
| 5 library compiler_helper; | 5 library compiler_helper; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import "package:expect/expect.dart"; | 8 import "package:expect/expect.dart"; |
| 9 | 9 |
| 10 import 'package:compiler/src/elements/elements.dart' | 10 import 'package:compiler/src/elements/elements.dart' as lego; |
| 11 as lego; | |
| 12 export 'package:compiler/src/elements/elements.dart'; | 11 export 'package:compiler/src/elements/elements.dart'; |
| 13 | 12 |
| 14 import 'package:compiler/src/js_backend/js_backend.dart' | 13 import 'package:compiler/src/js_backend/js_backend.dart' as js; |
| 15 as js; | |
| 16 | 14 |
| 17 import 'package:compiler/src/commandline_options.dart'; | 15 import 'package:compiler/src/commandline_options.dart'; |
| 18 import 'package:compiler/src/common/codegen.dart'; | 16 import 'package:compiler/src/common/codegen.dart'; |
| 19 import 'package:compiler/src/common/resolution.dart'; | 17 import 'package:compiler/src/common/resolution.dart'; |
| 20 | 18 |
| 21 export 'package:compiler/src/diagnostics/messages.dart'; | 19 export 'package:compiler/src/diagnostics/messages.dart'; |
| 22 export 'package:compiler/src/diagnostics/source_span.dart'; | 20 export 'package:compiler/src/diagnostics/source_span.dart'; |
| 23 export 'package:compiler/src/diagnostics/spannable.dart'; | 21 export 'package:compiler/src/diagnostics/spannable.dart'; |
| 24 | 22 |
| 25 import 'package:compiler/src/types/types.dart' | 23 import 'package:compiler/src/types/types.dart' as types; |
| 26 as types; | 24 export 'package:compiler/src/types/types.dart' show TypeMask; |
| 27 export 'package:compiler/src/types/types.dart' | |
| 28 show TypeMask; | |
| 29 | 25 |
| 30 import 'package:compiler/src/util/util.dart'; | 26 import 'package:compiler/src/util/util.dart'; |
| 31 export 'package:compiler/src/util/util.dart'; | 27 export 'package:compiler/src/util/util.dart'; |
| 32 | 28 |
| 33 import 'package:compiler/src/compiler.dart' | 29 import 'package:compiler/src/compiler.dart' show Compiler; |
| 34 show Compiler; | |
| 35 | 30 |
| 36 export 'package:compiler/src/tree/tree.dart'; | 31 export 'package:compiler/src/tree/tree.dart'; |
| 37 | 32 |
| 38 import 'mock_compiler.dart'; | 33 import 'mock_compiler.dart'; |
| 39 export 'mock_compiler.dart'; | 34 export 'mock_compiler.dart'; |
| 40 | 35 |
| 41 import 'memory_compiler.dart' hide compilerFor; | 36 import 'memory_compiler.dart' hide compilerFor; |
| 42 | 37 |
| 43 import 'output_collector.dart'; | 38 import 'output_collector.dart'; |
| 44 export 'output_collector.dart'; | 39 export 'output_collector.dart'; |
| 45 | 40 |
| 46 /// Compile [code] and returns either the code for [entry] or, if [returnAll] is | 41 /// Compile [code] and returns either the code for [entry] or, if [returnAll] is |
| 47 /// true, the code for the entire program. | 42 /// true, the code for the entire program. |
| 48 /// | 43 /// |
| 49 /// If [check] is provided, it is executed on the code for [entry] before | 44 /// If [check] is provided, it is executed on the code for [entry] before |
| 50 /// returning. If [useMock] is `true` the [MockCompiler] is used for | 45 /// returning. If [useMock] is `true` the [MockCompiler] is used for |
| 51 /// compilation, otherwise the memory compiler is used. | 46 /// compilation, otherwise the memory compiler is used. |
| 52 Future<String> compile(String code, | 47 Future<String> compile(String code, |
| 53 {String entry: 'main', | 48 {String entry: 'main', |
| 54 bool enableTypeAssertions: false, | 49 bool enableTypeAssertions: false, |
| 55 bool minify: false, | 50 bool minify: false, |
| 56 bool analyzeAll: false, | 51 bool analyzeAll: false, |
| 57 bool disableInlining: true, | 52 bool disableInlining: true, |
| 58 bool trustJSInteropTypeAnnotations: false, | 53 bool trustJSInteropTypeAnnotations: false, |
| 59 bool useMock: false, | 54 bool useMock: false, |
| 60 void check(String generatedEntry), | 55 void check(String generatedEntry), |
| 61 bool returnAll: false}) async { | 56 bool returnAll: false}) async { |
| 62 OutputCollector outputCollector = returnAll ? new OutputCollector() : null; | 57 OutputCollector outputCollector = returnAll ? new OutputCollector() : null; |
| 63 if (useMock) { | 58 if (useMock) { |
| 64 // TODO(johnniwinther): Remove this when no longer needed by | 59 // TODO(johnniwinther): Remove this when no longer needed by |
| 65 // `arithmetic_simplication_test.dart`. | 60 // `arithmetic_simplication_test.dart`. |
| 66 MockCompiler compiler = new MockCompiler.internal( | 61 MockCompiler compiler = new MockCompiler.internal( |
| 67 enableTypeAssertions: enableTypeAssertions, | 62 enableTypeAssertions: enableTypeAssertions, |
| 68 // Type inference does not run when manually | 63 // Type inference does not run when manually |
| 69 // compiling a method. | 64 // compiling a method. |
| 70 disableTypeInference: true, | 65 disableTypeInference: true, |
| 71 enableMinification: minify, | 66 enableMinification: minify, |
| 72 disableInlining: disableInlining, | 67 disableInlining: disableInlining, |
| 73 trustJSInteropTypeAnnotations: trustJSInteropTypeAnnotations, | 68 trustJSInteropTypeAnnotations: trustJSInteropTypeAnnotations, |
| 74 outputProvider: outputCollector); | 69 outputProvider: outputCollector); |
| 75 await compiler.init(); | 70 await compiler.init(); |
| 76 compiler.parseScript(code); | 71 compiler.parseScript(code); |
| 77 lego.Element element = compiler.mainApp.find(entry); | 72 lego.Element element = compiler.mainApp.find(entry); |
| 78 if (element == null) return null; | 73 if (element == null) return null; |
| 79 compiler.phase = Compiler.PHASE_RESOLVING; | 74 compiler.phase = Compiler.PHASE_RESOLVING; |
| 80 compiler.backend.enqueueHelpers(compiler.enqueuer.resolution, | 75 compiler.backend.enqueueHelpers( |
| 81 compiler.globalDependencies); | 76 compiler.enqueuer.resolution, compiler.globalDependencies); |
| 82 compiler.processQueue(compiler.enqueuer.resolution, element); | 77 compiler.processQueue(compiler.enqueuer.resolution, element); |
| 83 compiler.world.populate(); | 78 compiler.world.populate(); |
| 84 compiler.backend.onResolutionComplete(); | 79 compiler.backend.onResolutionComplete(); |
| 85 ResolutionWorkItem resolutionWork = new ResolutionWorkItem(element); | 80 ResolutionWorkItem resolutionWork = new ResolutionWorkItem(element); |
| 86 resolutionWork.run(compiler, compiler.enqueuer.resolution); | 81 resolutionWork.run(compiler, compiler.enqueuer.resolution); |
| 87 CodegenWorkItem work = new CodegenWorkItem(compiler, element); | 82 CodegenWorkItem work = new CodegenWorkItem(compiler, element); |
| 88 compiler.phase = Compiler.PHASE_COMPILING; | 83 compiler.phase = Compiler.PHASE_COMPILING; |
| 89 work.run(compiler, compiler.enqueuer.codegen); | 84 work.run(compiler, compiler.enqueuer.codegen); |
| 90 js.JavaScriptBackend backend = compiler.backend; | 85 js.JavaScriptBackend backend = compiler.backend; |
| 91 String generated = backend.getGeneratedCode(element); | 86 String generated = backend.getGeneratedCode(element); |
| 92 if (check != null) { | 87 if (check != null) { |
| 93 check(generated); | 88 check(generated); |
| 94 } | 89 } |
| 95 return returnAll ? outputCollector.getOutput('', 'js') : generated; | 90 return returnAll ? outputCollector.getOutput('', 'js') : generated; |
| 96 } else { | 91 } else { |
| 97 List<String> options = <String>[ | 92 List<String> options = <String>[Flags.disableTypeInference]; |
| 98 Flags.disableTypeInference]; | |
| 99 if (enableTypeAssertions) { | 93 if (enableTypeAssertions) { |
| 100 options.add(Flags.enableCheckedMode); | 94 options.add(Flags.enableCheckedMode); |
| 101 } | 95 } |
| 102 if (minify) { | 96 if (minify) { |
| 103 options.add(Flags.minify); | 97 options.add(Flags.minify); |
| 104 } | 98 } |
| 105 if (analyzeAll) { | 99 if (analyzeAll) { |
| 106 options.add(Flags.analyzeAll); | 100 options.add(Flags.analyzeAll); |
| 107 } | 101 } |
| 108 if (trustJSInteropTypeAnnotations) { | 102 if (trustJSInteropTypeAnnotations) { |
| 109 options.add(Flags.trustJSInteropTypeAnnotations); | 103 options.add(Flags.trustJSInteropTypeAnnotations); |
| 110 } | 104 } |
| 111 | 105 |
| 112 if (disableInlining) { | 106 if (disableInlining) { |
| 113 options.add(Flags.disableInlining); | 107 options.add(Flags.disableInlining); |
| 114 } | 108 } |
| 115 | 109 |
| 116 Map<String, String> source; | 110 Map<String, String> source; |
| 117 if (entry != 'main') { | 111 if (entry != 'main') { |
| 118 source = {'main.dart': "$code\n\nmain() => $entry;" }; | 112 source = {'main.dart': "$code\n\nmain() => $entry;"}; |
| 119 } else { | 113 } else { |
| 120 source = {'main.dart': code}; | 114 source = {'main.dart': code}; |
| 121 } | 115 } |
| 122 | 116 |
| 123 CompilationResult result = await runCompiler( | 117 CompilationResult result = await runCompiler( |
| 124 memorySourceFiles: source, | 118 memorySourceFiles: source, |
| 125 options: options, | 119 options: options, |
| 126 outputProvider: outputCollector); | 120 outputProvider: outputCollector); |
| 127 Expect.isTrue(result.isSuccess); | 121 Expect.isTrue(result.isSuccess); |
| 128 Compiler compiler = result.compiler; | 122 Compiler compiler = result.compiler; |
| 129 lego.Element element = compiler.mainApp.find(entry); | 123 lego.Element element = compiler.mainApp.find(entry); |
| 130 js.JavaScriptBackend backend = compiler.backend; | 124 js.JavaScriptBackend backend = compiler.backend; |
| 131 String generated = backend.getGeneratedCode(element); | 125 String generated = backend.getGeneratedCode(element); |
| 132 if (check != null) { | 126 if (check != null) { |
| 133 check(generated); | 127 check(generated); |
| 134 } | 128 } |
| 135 return returnAll ? outputCollector.getOutput('', 'js') : generated; | 129 return returnAll ? outputCollector.getOutput('', 'js') : generated; |
| 136 } | 130 } |
| 137 } | 131 } |
| 138 | 132 |
| 139 Future<String> compileAll(String code, | 133 Future<String> compileAll(String code, |
| 140 {Map<String, String> coreSource, | 134 {Map<String, String> coreSource, |
| 141 bool disableInlining: true, | 135 bool disableInlining: true, |
| 142 bool trustTypeAnnotations: false, | 136 bool trustTypeAnnotations: false, |
| 143 bool minify: false, | 137 bool minify: false, |
| 144 int expectedErrors, | 138 int expectedErrors, |
| 145 int expectedWarnings}) { | 139 int expectedWarnings}) { |
| 146 Uri uri = new Uri(scheme: 'source'); | 140 Uri uri = new Uri(scheme: 'source'); |
| 147 OutputCollector outputCollector = new OutputCollector(); | 141 OutputCollector outputCollector = new OutputCollector(); |
| 148 MockCompiler compiler = compilerFor( | 142 MockCompiler compiler = compilerFor(code, uri, |
| 149 code, uri, coreSource: coreSource, disableInlining: disableInlining, | 143 coreSource: coreSource, |
| 150 minify: minify, expectedErrors: expectedErrors, | 144 disableInlining: disableInlining, |
| 145 minify: minify, |
| 146 expectedErrors: expectedErrors, |
| 151 trustTypeAnnotations: trustTypeAnnotations, | 147 trustTypeAnnotations: trustTypeAnnotations, |
| 152 expectedWarnings: expectedWarnings, | 148 expectedWarnings: expectedWarnings, |
| 153 outputProvider: outputCollector); | 149 outputProvider: outputCollector); |
| 154 compiler.diagnosticHandler = createHandler(compiler, code); | 150 compiler.diagnosticHandler = createHandler(compiler, code); |
| 155 return compiler.run(uri).then((compilationSucceded) { | 151 return compiler.run(uri).then((compilationSucceded) { |
| 156 Expect.isTrue(compilationSucceded, | 152 Expect.isTrue( |
| 157 'Unexpected compilation error(s): ' | 153 compilationSucceded, |
| 158 '${compiler.diagnosticCollector.errors}'); | 154 'Unexpected compilation error(s): ' |
| 155 '${compiler.diagnosticCollector.errors}'); |
| 159 return outputCollector.getOutput('', 'js'); | 156 return outputCollector.getOutput('', 'js'); |
| 160 }); | 157 }); |
| 161 } | 158 } |
| 162 | 159 |
| 163 Future compileAndCheck(String code, | 160 Future compileAndCheck(String code, String name, |
| 164 String name, | 161 check(MockCompiler compiler, lego.Element element), |
| 165 check(MockCompiler compiler, lego.Element element), | 162 {int expectedErrors, int expectedWarnings}) { |
| 166 {int expectedErrors, int expectedWarnings}) { | |
| 167 Uri uri = new Uri(scheme: 'source'); | 163 Uri uri = new Uri(scheme: 'source'); |
| 168 MockCompiler compiler = compilerFor(code, uri, | 164 MockCompiler compiler = compilerFor(code, uri, |
| 169 expectedErrors: expectedErrors, | 165 expectedErrors: expectedErrors, expectedWarnings: expectedWarnings); |
| 170 expectedWarnings: expectedWarnings); | |
| 171 return compiler.run(uri).then((_) { | 166 return compiler.run(uri).then((_) { |
| 172 lego.Element element = findElement(compiler, name); | 167 lego.Element element = findElement(compiler, name); |
| 173 return check(compiler, element); | 168 return check(compiler, element); |
| 174 }); | 169 }); |
| 175 } | 170 } |
| 176 | 171 |
| 177 Future compileSources(Map<String, String> sources, | 172 Future compileSources( |
| 178 check(MockCompiler compiler)) { | 173 Map<String, String> sources, check(MockCompiler compiler)) { |
| 179 Uri base = new Uri(scheme: 'source', path: '/'); | 174 Uri base = new Uri(scheme: 'source', path: '/'); |
| 180 Uri mainUri = base.resolve('main.dart'); | 175 Uri mainUri = base.resolve('main.dart'); |
| 181 String mainCode = sources['main.dart']; | 176 String mainCode = sources['main.dart']; |
| 182 Expect.isNotNull(mainCode, 'No source code found for "main.dart"'); | 177 Expect.isNotNull(mainCode, 'No source code found for "main.dart"'); |
| 183 MockCompiler compiler = compilerFor(mainCode, mainUri); | 178 MockCompiler compiler = compilerFor(mainCode, mainUri); |
| 184 sources.forEach((String path, String code) { | 179 sources.forEach((String path, String code) { |
| 185 if (path == 'main.dart') return; | 180 if (path == 'main.dart') return; |
| 186 compiler.registerSource(base.resolve(path), code); | 181 compiler.registerSource(base.resolve(path), code); |
| 187 }); | 182 }); |
| 188 | 183 |
| 189 return compiler.run(mainUri).then((_) { | 184 return compiler.run(mainUri).then((_) { |
| 190 return check(compiler); | 185 return check(compiler); |
| 191 }); | 186 }); |
| 192 } | 187 } |
| 193 | 188 |
| 194 lego.Element findElement(compiler, String name, [Uri library]) { | 189 lego.Element findElement(compiler, String name, [Uri library]) { |
| 195 lego.LibraryElement lib = compiler.mainApp; | 190 lego.LibraryElement lib = compiler.mainApp; |
| 196 if (library != null) { | 191 if (library != null) { |
| 197 lib = compiler.libraryLoader.lookupLibrary(library); | 192 lib = compiler.libraryLoader.lookupLibrary(library); |
| 198 Expect.isNotNull(lib, 'Could not locate library $library.'); | 193 Expect.isNotNull(lib, 'Could not locate library $library.'); |
| 199 } | 194 } |
| 200 var element = lib.find(name); | 195 var element = lib.find(name); |
| 201 Expect.isNotNull(element, 'Could not locate $name.'); | 196 Expect.isNotNull(element, 'Could not locate $name.'); |
| 202 return element; | 197 return element; |
| 203 } | 198 } |
| 204 | 199 |
| 205 types.TypeMask findTypeMask(compiler, String name, | 200 types.TypeMask findTypeMask(compiler, String name, |
| 206 [String how = 'nonNullExact']) { | 201 [String how = 'nonNullExact']) { |
| 207 var sourceName = name; | 202 var sourceName = name; |
| 208 var element = compiler.mainApp.find(sourceName); | 203 var element = compiler.mainApp.find(sourceName); |
| 209 if (element == null) { | 204 if (element == null) { |
| 210 element = compiler.backend.helpers.interceptorsLibrary.find(sourceName); | 205 element = compiler.backend.helpers.interceptorsLibrary.find(sourceName); |
| 211 } | 206 } |
| 212 if (element == null) { | 207 if (element == null) { |
| 213 element = compiler.commonElements.coreLibrary.find(sourceName); | 208 element = compiler.commonElements.coreLibrary.find(sourceName); |
| 214 } | 209 } |
| 215 Expect.isNotNull(element, 'Could not locate $name'); | 210 Expect.isNotNull(element, 'Could not locate $name'); |
| 216 switch (how) { | 211 switch (how) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 228 return new types.TypeMask.nonNullSubtype(element, compiler.world); | 223 return new types.TypeMask.nonNullSubtype(element, compiler.world); |
| 229 } | 224 } |
| 230 Expect.fail('Unknown TypeMask constructor $how'); | 225 Expect.fail('Unknown TypeMask constructor $how'); |
| 231 return null; | 226 return null; |
| 232 } | 227 } |
| 233 | 228 |
| 234 String anyIdentifier = "[a-zA-Z][a-zA-Z0-9]*"; | 229 String anyIdentifier = "[a-zA-Z][a-zA-Z0-9]*"; |
| 235 | 230 |
| 236 String getIntTypeCheck(String variable) { | 231 String getIntTypeCheck(String variable) { |
| 237 return "\\($variable ?!== ?\\($variable ?\\| ?0\\)|" | 232 return "\\($variable ?!== ?\\($variable ?\\| ?0\\)|" |
| 238 "\\($variable ?>>> ?0 ?!== ?$variable"; | 233 "\\($variable ?>>> ?0 ?!== ?$variable"; |
| 239 } | 234 } |
| 240 | 235 |
| 241 String getNumberTypeCheck(String variable) { | 236 String getNumberTypeCheck(String variable) { |
| 242 return """\\(typeof $variable ?!== ?"number"\\)"""; | 237 return """\\(typeof $variable ?!== ?"number"\\)"""; |
| 243 } | 238 } |
| 244 | 239 |
| 245 void checkNumberOfMatches(Iterator it, int nb) { | 240 void checkNumberOfMatches(Iterator it, int nb) { |
| 246 bool hasNext = it.moveNext(); | 241 bool hasNext = it.moveNext(); |
| 247 for (int i = 0; i < nb; i++) { | 242 for (int i = 0; i < nb; i++) { |
| 248 Expect.isTrue(hasNext, "Found less than $nb matches"); | 243 Expect.isTrue(hasNext, "Found less than $nb matches"); |
| 249 hasNext = it.moveNext(); | 244 hasNext = it.moveNext(); |
| 250 } | 245 } |
| 251 Expect.isFalse(hasNext, "Found more than $nb matches"); | 246 Expect.isFalse(hasNext, "Found more than $nb matches"); |
| 252 } | 247 } |
| 253 | 248 |
| 254 Future compileAndMatch(String code, String entry, RegExp regexp, | 249 Future compileAndMatch(String code, String entry, RegExp regexp, |
| 255 {bool useMock: false}) { | 250 {bool useMock: false}) { |
| 256 return compile(code, entry: entry, | 251 return compile(code, entry: entry, useMock: useMock, |
| 257 useMock: useMock, | |
| 258 check: (String generated) { | 252 check: (String generated) { |
| 259 Expect.isTrue(regexp.hasMatch(generated), | 253 Expect.isTrue( |
| 260 '"$generated" does not match /$regexp/'); | 254 regexp.hasMatch(generated), '"$generated" does not match /$regexp/'); |
| 261 }); | 255 }); |
| 262 } | 256 } |
| 263 | 257 |
| 264 Future compileAndDoNotMatch(String code, String entry, RegExp regexp) { | 258 Future compileAndDoNotMatch(String code, String entry, RegExp regexp) { |
| 265 return compile(code, entry: entry, check: (String generated) { | 259 return compile(code, entry: entry, check: (String generated) { |
| 266 Expect.isFalse(regexp.hasMatch(generated), | 260 Expect.isFalse( |
| 267 '"$generated" has a match in /$regexp/'); | 261 regexp.hasMatch(generated), '"$generated" has a match in /$regexp/'); |
| 268 }); | 262 }); |
| 269 } | 263 } |
| 270 | 264 |
| 271 int length(Link link) => link.isEmpty ? 0 : length(link.tail) + 1; | 265 int length(Link link) => link.isEmpty ? 0 : length(link.tail) + 1; |
| 272 | 266 |
| 273 // Does a compile and then a match where every 'x' is replaced by something | 267 // Does a compile and then a match where every 'x' is replaced by something |
| 274 // that matches any variable, and every space is optional. | 268 // that matches any variable, and every space is optional. |
| 275 Future compileAndMatchFuzzy(String code, String entry, String regexp) { | 269 Future compileAndMatchFuzzy(String code, String entry, String regexp) { |
| 276 return compileAndMatchFuzzyHelper(code, entry, regexp, true); | 270 return compileAndMatchFuzzyHelper(code, entry, regexp, true); |
| 277 } | 271 } |
| 278 | 272 |
| 279 Future compileAndDoNotMatchFuzzy(String code, String entry, String regexp) { | 273 Future compileAndDoNotMatchFuzzy(String code, String entry, String regexp) { |
| 280 return compileAndMatchFuzzyHelper(code, entry, regexp, false); | 274 return compileAndMatchFuzzyHelper(code, entry, regexp, false); |
| 281 } | 275 } |
| 282 | 276 |
| 283 Future compileAndMatchFuzzyHelper( | 277 Future compileAndMatchFuzzyHelper( |
| 284 String code, String entry, String regexp, bool shouldMatch) { | 278 String code, String entry, String regexp, bool shouldMatch) { |
| 285 return compile(code, entry: entry, check: (String generated) { | 279 return compile(code, entry: entry, check: (String generated) { |
| 286 final xRe = new RegExp('\\bx\\b'); | 280 final xRe = new RegExp('\\bx\\b'); |
| 287 regexp = regexp.replaceAll(xRe, '(?:$anyIdentifier)'); | 281 regexp = regexp.replaceAll(xRe, '(?:$anyIdentifier)'); |
| 288 final spaceRe = new RegExp('\\s+'); | 282 final spaceRe = new RegExp('\\s+'); |
| 289 regexp = regexp.replaceAll(spaceRe, '(?:\\s*)'); | 283 regexp = regexp.replaceAll(spaceRe, '(?:\\s*)'); |
| 290 if (shouldMatch) { | 284 if (shouldMatch) { |
| 291 Expect.isTrue(new RegExp(regexp).hasMatch(generated)); | 285 Expect.isTrue(new RegExp(regexp).hasMatch(generated)); |
| 292 } else { | 286 } else { |
| 293 Expect.isFalse(new RegExp(regexp).hasMatch(generated)); | 287 Expect.isFalse(new RegExp(regexp).hasMatch(generated)); |
| 294 } | 288 } |
| 295 }); | 289 }); |
| 296 } | 290 } |
| OLD | NEW |