hunk.code_window:     );
     }
     const generatedTable = userAnalyticsTable({ data }).trim();
     if (metricsTable !== generatedTable) {
       logger.error('Expected metrics table to be the same as generated. Copy the lines below:');
       logger.error(generatedTable);
  
hunk.labels: keep keep add keep keep keep keep keep
hunk.after_edit:   for (const { parameter } of data) {
       const param = parameter.split('.')[1];
       if (param.length > 40) {
         throw new Error(`Event metric parameter ${param} is more than 40 characters.`);
       }
     }
  
hunk.file_path: scripts/validate-user-analytics.ts
hunk.type: add
file: /**
   * @license
   * Copyright Google LLC All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  
  export class LinkedList<T extends { next: T | null }> {
    constructor(private _head: T) {}
  
    get(l: number) {
      let c: T | null = this._head;
      while (c && l > 0) {
        l--;
        c = c.next;
      }
  
      return c;
    }
  
    get head() {
      return this._head;
    }
    get length() {
      let c: T | null = this._head;
      let i = 0;
      while (c) {
        i++;
        c = c.next;
      }
  
      return i;
    }
  
    reduce<R>(accumulator: (acc: R, value: T, index?: number) => R, seed: R) {
      let c: T | null = this._head;
      let acc = seed;
      let i = 0;
      while (c) {
        acc = accumulator(acc, c, i);
        i++;
        c = c.next;
      }
  
      return acc;
    }
  
    find(predicate: (value: T, index?: number) => boolean) {
      let c: T | null = this._head;
      let i = 0;
      while (c) {
        if (predicate(c, i)) {
          break;
        }
        i++;
        c = c.next;
      }
  
      return c;
    }
  
    forEach(visitor: (value: T, index?: number) => void) {
      let c: T | null = this._head;
      let i = 0;
      while (c) {
        visitor(c, i);
        i++;
        c = c.next;
      }
    }
  }
  