1/* 2* Copyright (c) Microsoft Corporation. All rights reserved. 3* Copyright (c) 2023 Huawei Device Co., Ltd. 4* Licensed under the Apache License, Version 2.0 (the "License"); 5* you may not use this file except in compliance with the License. 6* You may obtain a copy of the License at 7* 8* http://www.apache.org/licenses/LICENSE-2.0 9* 10* Unless required by applicable law or agreed to in writing, software 11* distributed under the License is distributed on an "AS IS" BASIS, 12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13* See the License for the specific language governing permissions and 14* limitations under the License. 15* 16* This file has been modified by Huawei to verify type inference by adding verification statements. 17*/ 18 19// === tests/cases/compiler/staticAnonymousTypeNotReferencingTypeParameter.ts === 20declare function AssertType(value:any, type:string):void; 21// This test case is a condensed version of Angular 2's ListWrapper. Prior to #7448 22// this would cause the compiler to run out of memory. 23 24function outer<T>(x: T) { 25 class Inner { 26 static y: T = x; 27 } 28AssertType(Inner, "typeof Inner"); 29 return Inner; 30} 31let y: number = outer(5).y; 32AssertType(y, "number"); 33AssertType(outer(5).y, "number"); 34 35class ListWrapper2 { 36 static clone<T>(dit: typeof ListWrapper2, array: T[]): T[] { 37AssertType(array.slice(0), "T[]"); 38return array.slice(0); 39 40AssertType(array.slice, "(?number, ?number) => T[]"); 41 42AssertType(0, "int"); 43} 44 45 static reversed<T>(dit: typeof ListWrapper2, array: T[]): T[] { 46 let a = ListWrapper2.clone(dit, array); 47AssertType(a, "T[]"); 48AssertType(ListWrapper2.clone(dit, array), "T[]"); 49AssertType(ListWrapper2.clone, "<T>(typeof ListWrapper2, T[]) => T[]"); 50AssertType(dit, "typeof ListWrapper2"); 51AssertType(array, "T[]"); 52 53AssertType(a, "T[]"); 54 return a; 55 } 56} 57namespace tessst { 58 /** 59 * Iterates through 'array' by index and performs the callback on each element of array until the callback 60 * 61returns a truthy value, then returns that value. 62 * If no such value is found, the callback is applied to each element of array and undefined is 63returned. 64 */ 65 export function funkyFor<T, U>(array: T[], callback: (element: T, index: number) => U): U { 66 if (array) { 67AssertType(array, "T[]"); 68 69 for (let i = 0, len = array.length; i < len; i++) { 70AssertType(i, "number"); 71AssertType(0, "int"); 72AssertType(len, "number"); 73AssertType(array.length, "number"); 74AssertType(i < len, "boolean"); 75AssertType(i, "number"); 76AssertType(len, "number"); 77AssertType(i++, "number"); 78AssertType(i, "number"); 79 80 const result = callback(array[i], i); 81AssertType(result, "U"); 82AssertType(callback(array[i], i), "U"); 83AssertType(callback, "(T, number) => U"); 84AssertType(array[i], "T"); 85AssertType(array, "T[]"); 86AssertType(i, "number"); 87AssertType(i, "number"); 88 89 if (result) { 90AssertType(result, "U"); 91 92AssertType(result, "U"); 93 return result; 94 } 95 } 96 } 97AssertType(undefined, "undefined"); 98 return undefined; 99 } 100} 101interface Scanner { 102 scanRange<T>(start: number, length: number, callback: () => T): T; 103} 104class ListWrapper { 105 // JS has no way to express a statically fixed size list, but dart does so we 106 // keep both methods. 107 static createFixedSize(dit: typeof ListWrapper, size: number): any[] { 108AssertType(new Array(size), "any[]"); 109return new Array(size); 110 111AssertType(Array, "ArrayConstructor"); 112 113AssertType(size, "number"); 114} 115 116 static createGrowableSize(dit: typeof ListWrapper, size: number): any[] { 117AssertType(new Array(size), "any[]"); 118return new Array(size); 119 120AssertType(Array, "ArrayConstructor"); 121 122AssertType(size, "number"); 123} 124 125 static clone<T>(dit: typeof ListWrapper, array: T[]): T[] { 126AssertType(array.slice(0), "T[]"); 127return array.slice(0); 128 129AssertType(array.slice, "(?number, ?number) => T[]"); 130 131AssertType(0, "int"); 132} 133 134 static forEachWithIndex<T>(dit: typeof ListWrapper, array: T[], fn: (t: T, n: number) => void) { 135 for (let i = 0; i < array.length; i++) { 136AssertType(i, "number"); 137AssertType(0, "int"); 138AssertType(i < array.length, "boolean"); 139AssertType(i, "number"); 140AssertType(array.length, "number"); 141AssertType(i++, "number"); 142AssertType(i, "number"); 143 144 fn(array[i], i); 145AssertType(fn(array[i], i), "void"); 146AssertType(fn, "(T, number) => void"); 147AssertType(array[i], "T"); 148AssertType(array, "T[]"); 149AssertType(i, "number"); 150AssertType(i, "number"); 151 } 152 } 153 static first<T>(dit: typeof ListWrapper, array: T[]): T { 154 if (!array) 155AssertType(!array, "boolean"); 156AssertType(array, "T[]"); 157AssertType(null, "null"); 158return null; 159 160AssertType(array[0], "T"); 161AssertType(array, "T[]"); 162AssertType(0, "int"); 163 return array[0]; 164 } 165 static last<T>(dit: typeof ListWrapper, array: T[]): T { 166 if (!array || array.length == 0) 167AssertType(!array || array.length == 0, "boolean"); 168AssertType(!array, "boolean"); 169AssertType(array, "T[]"); 170AssertType(array.length == 0, "boolean"); 171AssertType(array.length, "number"); 172AssertType(0, "int"); 173AssertType(null, "null"); 174return null; 175 176AssertType(array[array.length - 1], "T"); 177AssertType(array, "T[]"); 178AssertType(array.length - 1, "number"); 179AssertType(array.length, "number"); 180AssertType(1, "int"); 181 return array[array.length - 1]; 182 } 183 static indexOf<T>(dit: typeof ListWrapper, array: T[], value: T, startIndex: number = 0): number { 184AssertType(array.indexOf(value, startIndex), "number"); 185AssertType(array.indexOf, "(T, ?number) => number"); 186AssertType(value, "T"); 187AssertType(startIndex, "number"); 188 return array.indexOf(value, startIndex); 189 } 190 static contains<T>(dit: typeof ListWrapper, list: T[], el: T): boolean { 191AssertType(list.indexOf(el) !== -1, "boolean"); 192return list.indexOf(el) !== -1; 193 194AssertType(list.indexOf(el), "number"); 195 196AssertType(list.indexOf, "(T, ?number) => number"); 197 198AssertType(el, "T"); 199 200AssertType(-1, "int"); 201 202AssertType(1, "int"); 203} 204 205 static reversed<T>(dit: typeof ListWrapper, array: T[]): T[] { 206 let a = ListWrapper.clone(dit, array); 207AssertType(a, "T[]"); 208AssertType(ListWrapper.clone(dit, array), "T[]"); 209AssertType(ListWrapper.clone, "<T>(typeof ListWrapper, T[]) => T[]"); 210AssertType(dit, "typeof ListWrapper"); 211AssertType(array, "T[]"); 212 213 let scanner: Scanner; 214AssertType(scanner, "Scanner"); 215 216 scanner.scanRange(3, 5, () => { }); 217AssertType(scanner.scanRange(3, 5, () => { }), "void"); 218AssertType(scanner.scanRange, "<T>(number, number, () => T) => T"); 219AssertType(3, "int"); 220AssertType(5, "int"); 221AssertType(() => { }, "() => void"); 222 223AssertType(tessst.funkyFor(array, t => t.toString()) ? a.reverse() : a, "T[]"); 224AssertType(tessst.funkyFor(array, t => t.toString()), "string"); 225AssertType(tessst.funkyFor, "<T, U>(T[], (T, number) => U) => U"); 226AssertType(array, "T[]"); 227AssertType(t => t.toString(), "(T) => string"); 228AssertType(t, "T"); 229AssertType(t.toString(), "string"); 230AssertType(t.toString, "() => string"); 231AssertType(a.reverse(), "T[]"); 232AssertType(a.reverse, "() => T[]"); 233AssertType(a, "T[]"); 234 return tessst.funkyFor(array, t => t.toString()) ? a.reverse() : a; 235 } 236 static concat(dit: typeof ListWrapper, a: any[], b: any[]): any[] { 237AssertType(a.concat(b), "any[]"); 238return a.concat(b); 239 240AssertType(a.concat, "{ (...ConcatArray<any>[]): any[]; (...any[]): any[]; }"); 241 242AssertType(b, "any[]"); 243} 244 245 static insert<T>(dit: typeof ListWrapper, list: T[], index: number, value: T) { list.splice(index, 0, value); 246AssertType(list.splice(index, 0, value), "T[]"); 247 248AssertType(list.splice, "{ (number, ?number): T[]; (number, number, ...T[]): T[]; }"); 249 250AssertType(index, "number"); 251 252AssertType(0, "int"); 253 254AssertType(value, "T"); 255} 256 257 static removeAt<T>(dit: typeof ListWrapper, list: T[], index: number): T { 258 let res = list[index]; 259AssertType(res, "T"); 260AssertType(list[index], "T"); 261AssertType(list, "T[]"); 262AssertType(index, "number"); 263 264 list.splice(index, 1); 265AssertType(list.splice(index, 1), "T[]"); 266AssertType(list.splice, "{ (number, ?number): T[]; (number, number, ...T[]): T[]; }"); 267AssertType(index, "number"); 268AssertType(1, "int"); 269 270AssertType(res, "T"); 271 return res; 272 } 273 static removeAll<T>(dit: typeof ListWrapper, list: T[], items: T[]) { 274 for (let i = 0; i < items.length; ++i) { 275AssertType(i, "number"); 276AssertType(0, "int"); 277AssertType(i < items.length, "boolean"); 278AssertType(i, "number"); 279AssertType(items.length, "number"); 280AssertType(++i, "number"); 281AssertType(i, "number"); 282 283 let index = list.indexOf(items[i]); 284AssertType(index, "number"); 285AssertType(list.indexOf(items[i]), "number"); 286AssertType(list.indexOf, "(T, ?number) => number"); 287AssertType(items[i], "T"); 288AssertType(items, "T[]"); 289AssertType(i, "number"); 290 291 list.splice(index, 1); 292AssertType(list.splice(index, 1), "T[]"); 293AssertType(list.splice, "{ (number, ?number): T[]; (number, number, ...T[]): T[]; }"); 294AssertType(index, "number"); 295AssertType(1, "int"); 296 } 297 } 298 static remove<T>(dit: typeof ListWrapper, list: T[], el: T): boolean { 299 let index = list.indexOf(el); 300AssertType(index, "number"); 301AssertType(list.indexOf(el), "number"); 302AssertType(list.indexOf, "(T, ?number) => number"); 303AssertType(el, "T"); 304 305 if (index > -1) { 306AssertType(index > -1, "boolean"); 307AssertType(index, "number"); 308AssertType(-1, "int"); 309AssertType(1, "int"); 310 311 list.splice(index, 1); 312AssertType(list.splice(index, 1), "T[]"); 313AssertType(list.splice, "{ (number, ?number): T[]; (number, number, ...T[]): T[]; }"); 314AssertType(index, "number"); 315AssertType(1, "int"); 316 317AssertType(true, "boolean"); 318 return true; 319 } 320AssertType(false, "boolean"); 321 return false; 322 } 323 static clear(dit: typeof ListWrapper, list: any[]) { list.length = 0; 324AssertType(list.length = 0, "int"); 325 326AssertType(list.length, "number"); 327 328AssertType(0, "int"); 329} 330 331 static isEmpty(dit: typeof ListWrapper, list: any[]): boolean { 332AssertType(list.length == 0, "boolean"); 333return list.length == 0; 334 335AssertType(list.length, "number"); 336 337AssertType(0, "int"); 338} 339 340 static fill(dit: typeof ListWrapper, list: any[], value: any, start: number = 0, end: number = null) { 341 list.fill(value, start, end === null ? list.length : end); 342AssertType(list.fill(value, start, end === null ? list.length : end), "void"); 343AssertType(list.fill, "(any, number, number) => void"); 344AssertType(value, "any"); 345AssertType(start, "number"); 346AssertType(end === null ? list.length : end, "number"); 347AssertType(end === null, "boolean"); 348AssertType(end, "number"); 349AssertType(null, "null"); 350AssertType(list.length, "number"); 351AssertType(end, "number"); 352 } 353 static equals(dit: typeof ListWrapper, a: any[], b: any[]): boolean { 354 if (a.length != b.length) 355AssertType(a.length != b.length, "boolean"); 356AssertType(a.length, "number"); 357AssertType(b.length, "number"); 358AssertType(false, "boolean"); 359return false; 360 361 for (let i = 0; i < a.length; ++i) { 362AssertType(i, "number"); 363AssertType(0, "int"); 364AssertType(i < a.length, "boolean"); 365AssertType(i, "number"); 366AssertType(a.length, "number"); 367AssertType(++i, "number"); 368AssertType(i, "number"); 369 370 if (a[i] !== b[i]) 371AssertType(a[i] !== b[i], "boolean"); 372AssertType(a[i], "any"); 373AssertType(a, "any[]"); 374AssertType(i, "number"); 375AssertType(b[i], "any"); 376AssertType(b, "any[]"); 377AssertType(i, "number"); 378AssertType(false, "boolean"); 379return false; 380 } 381AssertType(true, "boolean"); 382 return true; 383 } 384 static slice<T>(dit: typeof ListWrapper, l: T[], from: number = 0, to: number = null): T[] { 385AssertType(l.slice(from, to === null ? undefined : to), "T[]"); 386AssertType(l.slice, "(?number, ?number) => T[]"); 387AssertType(from, "number"); 388AssertType(to === null ? undefined : to, "number"); 389AssertType(to === null, "boolean"); 390AssertType(to, "number"); 391AssertType(null, "null"); 392AssertType(undefined, "undefined"); 393AssertType(to, "number"); 394 return l.slice(from, to === null ? undefined : to); 395 } 396 static splice<T>(dit: typeof ListWrapper, l: T[], from: number, length: number): T[] { 397AssertType(l.splice(from, length), "T[]"); 398return l.splice(from, length); 399 400AssertType(l.splice, "{ (number, ?number): T[]; (number, number, ...T[]): T[]; }"); 401 402AssertType(from, "number"); 403 404AssertType(length, "number"); 405} 406 407 static sort<T>(dit: typeof ListWrapper, l: T[], compareFn?: (a: T, b: T) => number) { 408 if (isPresent(compareFn)) { 409AssertType(isPresent(compareFn), "boolean"); 410AssertType(isPresent, "<T>(?(T, T) => number) => boolean"); 411AssertType(compareFn, "(T, T) => number"); 412 413 l.sort(compareFn); 414AssertType(l.sort(compareFn), "T[]"); 415AssertType(l.sort, "(?(T, T) => number) => T[]"); 416AssertType(compareFn, "(T, T) => number"); 417 418 } else { 419 l.sort(); 420AssertType(l.sort(), "T[]"); 421AssertType(l.sort, "(?(T, T) => number) => T[]"); 422 } 423 } 424 static toString<T>(dit: typeof ListWrapper, l: T[]): string { 425AssertType(l.toString(), "string"); 426return l.toString(); 427 428AssertType(l.toString, "() => string"); 429} 430 431 static toJSON<T>(dit: typeof ListWrapper, l: T[]): string { 432AssertType(JSON.stringify(l), "string"); 433return JSON.stringify(l); 434 435AssertType(JSON.stringify, "{ (any, ?(any, string, any) => any, ?union): string; (any, ?(union)[], ?union): string; }"); 436 437AssertType(l, "T[]"); 438} 439 440 static maximum<T>(dit: typeof ListWrapper, list: T[], predicate: (t: T) => number): T { 441 if (list.length == 0) { 442AssertType(list.length == 0, "boolean"); 443AssertType(list.length, "number"); 444AssertType(0, "int"); 445 446AssertType(null, "null"); 447 return null; 448 } 449 let solution: T = null; 450AssertType(solution, "T"); 451AssertType(null, "null"); 452 453 let maxValue = -Infinity; 454AssertType(maxValue, "number"); 455AssertType(-Infinity, "number"); 456AssertType(Infinity, "number"); 457 458 for (let index = 0; index < list.length; index++) { 459AssertType(index, "number"); 460AssertType(0, "int"); 461AssertType(index < list.length, "boolean"); 462AssertType(index, "number"); 463AssertType(list.length, "number"); 464AssertType(index++, "number"); 465AssertType(index, "number"); 466 467 let candidate = list[index]; 468AssertType(candidate, "T"); 469AssertType(list[index], "T"); 470AssertType(list, "T[]"); 471AssertType(index, "number"); 472 473 if (isBlank(candidate)) { 474AssertType(isBlank(candidate), "boolean"); 475AssertType(isBlank, "(any) => boolean"); 476AssertType(candidate, "T"); 477 478 continue; 479 } 480 let candidateValue = predicate(candidate); 481AssertType(candidateValue, "number"); 482AssertType(predicate(candidate), "number"); 483AssertType(predicate, "(T) => number"); 484AssertType(candidate, "T"); 485 486 if (candidateValue > maxValue) { 487AssertType(candidateValue > maxValue, "boolean"); 488AssertType(candidateValue, "number"); 489AssertType(maxValue, "number"); 490 491 solution = candidate; 492AssertType(solution = candidate, "T"); 493AssertType(solution, "T"); 494AssertType(candidate, "T"); 495 496 maxValue = candidateValue; 497AssertType(maxValue = candidateValue, "number"); 498AssertType(maxValue, "number"); 499AssertType(candidateValue, "number"); 500 } 501 } 502AssertType(solution, "T"); 503 return solution; 504 } 505} 506let cloned = ListWrapper.clone(ListWrapper, [1,2,3,4]); 507AssertType(cloned, "number[]"); 508AssertType(ListWrapper.clone(ListWrapper, [1,2,3,4]), "number[]"); 509AssertType(ListWrapper.clone, "<T>(typeof ListWrapper, T[]) => T[]"); 510AssertType(ListWrapper, "typeof ListWrapper"); 511AssertType([1,2,3,4], "number[]"); 512AssertType(1, "int"); 513AssertType(2, "int"); 514AssertType(3, "int"); 515AssertType(4, "int"); 516 517declare function isBlank(x: any): boolean; 518declare function isPresent<T>(compareFn?: (a: T, b: T) => number): boolean; 519interface Array<T> { 520 fill(value: any, start: number, end: number): void; 521} 522 523