src/vs/base/common/equals.ts

206 LOC · 145 covered · 61 uncovered · 30 ranges · 8274 concepts · 9 introducers · 4190 tests

File neighbourhood

The centred file is linked to every concept that introduces one of its ranges, every test that runs code from the file, and the gray connector concepts standing between those tests and the file's own introducer concepts. Undirected links join concepts to every file where they introduce source and concepts to the tests they introduce; arrows show specialization between the displayed concepts and bridge only concepts omitted from this view. Concept colors match the source ranges below; connector concepts have no source color and are shown in gray.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the file

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the related-file, concept, and source links on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the related-file, concept, and source links on this page while the interactive map is unavailable.

1 > /*--------------------------------------------------------------------------------------------- equals.ts ×14
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import * as arrays from './arrays.js';
7 >
8 > /*
9 > * Each function in this file which offers an equality comparison, has an accompanying
10 > * `*C` variant which returns an EqualityComparer function.
11 > *
12 > * The `*C` variant allows for easier composition of equality comparers and improved type-inference.
13 > */
14 >
15 >
16 > /** Represents a function that decides if two values are equal. */
17 > export type EqualityComparer<T> = (a: T, b: T) => boolean;
18 >
19 > export interface IEquatable<T> {
20 > equals(other: T): boolean;
21 > }
22 >
23 > /**
24 > * Compares two items for equality using strict equality.
25 > */
26 > export function strictEquals<T>(a: T, b: T): boolean {
27 > return a === b; equals.ts ×1
28 > }
30 > export function strictEqualsC<T>(): EqualityComparer<T> {
31 return (a, b) => a === b;
32 }
34 > /**
35 > * Checks if the items of two arrays are equal.
36 > * By default, strict equality is used to compare elements, but a custom equality comparer can be provided.
37 > */
38 > export function arrayEquals<T>(a: readonly T[], b: readonly T[], itemEquals?: EqualityComparer<T>): boolean {
39 > return arrays.equals(a, b, itemEquals ?? strictEquals); agentHostStateManager.ts ×3
40 > }
42 > /**
43 > * Checks if the items of two arrays are equal.
44 > * By default, strict equality is used to compare elements, but a custom equality comparer can be provided.
45 > */
46 > export function arrayEqualsC<T>(itemEquals?: EqualityComparer<T>): EqualityComparer<readonly T[]> {
47 > return (a, b) => arrays.equals(a, b, itemEquals ?? strictEquals); textModel.ts ×20
48 > }
50 > /**
51 > * Drills into arrays (items ordered) and objects (keys unordered) and uses strict equality on everything else.
52 > */
53 > export function structuralEquals<T>(a: T, b: T): boolean {
54 > if (a === b) { equals.ts ×3
55 > return true;
56 > }
58 > if (Array.isArray(a) && Array.isArray(b)) { equals.ts ×3
59 if (a.length !== b.length) {
60 return false;
61 }
62 for (let i = 0; i < a.length; i++) {
63 if (!structuralEquals(a[i], b[i])) {
64 return false;
65 }
66 }
67 return true;
68 }
70 > if (a && typeof a === 'object' && b && typeof b === 'object') { equals.ts ×3
71 > if (Object.getPrototypeOf(a) === Object.prototype && Object.getPrototypeOf(b) === Object.prototype) { equals.ts ×4
72 > const aObj = a as Record<string, unknown>;
73 > const bObj = b as Record<string, unknown>;
74 > const keysA = Object.keys(aObj);
75 > const keysB = Object.keys(bObj);
76 > const keysBSet = new Set(keysB);
77 >
78 > if (keysA.length !== keysB.length) {
79 return false;
80 }
82 > for (const key of keysA) {
83 > if (!keysBSet.has(key)) {
84 return false;
85 }
86 > if (!structuralEquals(aObj[key], bObj[key])) { equals.ts ×4
87 return false;
88 }
89 > } equals.ts ×4
90 >
91 > return true;
92 > }
93 > }
95 > return false;
96 > }
98 > export function structuralEqualsC<T>(): EqualityComparer<T> {
99 return (a, b) => structuralEquals(a, b);
100 }
102 > /**
103 > * `getStructuralKey(a) === getStructuralKey(b) <=> structuralEquals(a, b)`
104 > * (assuming that a and b are not cyclic structures and nothing extends globalThis Array).
105 > */
106 > export function getStructuralKey(t: unknown): string {
107 return JSON.stringify(toNormalizedJsonStructure(t));
108 }
110 > let objectId = 0;
111 > const objIds = new WeakMap<object, number>();
112 >
113 function toNormalizedJsonStructure(t: unknown): unknown {
114 if (Array.isArray(t)) {
115 return t.map(toNormalizedJsonStructure);
116 }
117
118 if (t && typeof t === 'object') {
119 if (Object.getPrototypeOf(t) === Object.prototype) {
120 const tObj = t as Record<string, unknown>;
121 const res: Record<string, unknown> = Object.create(null);
122 for (const key of Object.keys(tObj).sort()) {
123 res[key] = toNormalizedJsonStructure(tObj[key]);
124 }
125 return res;
126 } else {
127 let objId = objIds.get(t);
128 if (objId === undefined) {
129 objId = objectId++;
130 objIds.set(t, objId);
131 }
132 // Random string to prevent collisions
133 return objId + '----2b76a038c20c4bcc';
134 }
135 }
136 return t;
137 }
139 >
140 > /**
141 > * Two items are considered equal, if their stringified representations are equal.
142 > */
143 > export function jsonStringifyEquals<T>(a: T, b: T): boolean {
144 return JSON.stringify(a) === JSON.stringify(b);
145 }
147 > /**
148 > * Two items are considered equal, if their stringified representations are equal.
149 > */
150 > export function jsonStringifyEqualsC<T>(): EqualityComparer<T> {
151 return (a, b) => JSON.stringify(a) === JSON.stringify(b);
152 }
154 > /**
155 > * Uses `item.equals(other)` to determine equality.
156 > */
157 > export function thisEqualsC<T extends IEquatable<T>>(): EqualityComparer<T> {
158 > return (a, b) => a.equals(b); textModel.ts ×20
159 > }
161 > /**
162 > * Checks if two items are both null or undefined, or are equal according to the provided equality comparer.
163 > */
164 > export function equalsIfDefined<T>(v1: T | undefined | null, v2: T | undefined | null, equals: EqualityComparer<T>): boolean {
165 if (v1 === undefined || v1 === null || v2 === undefined || v2 === null) {
166 return v2 === v1;
167 }
168 return equals(v1, v2);
169 }
171 > /**
172 > * Returns an equality comparer that checks if two items are both null or undefined, or are equal according to the provided equality comparer.
173 > */
174 > export function equalsIfDefinedC<T>(equals: EqualityComparer<T>): EqualityComparer<T | undefined | null> {
175 > return (v1, v2) => { abstractSyntaxTokenBackend.ts ×3
176 if (v1 === undefined || v1 === null || v2 === undefined || v2 === null) {
177 return v2 === v1;
178 }
179 return equals(v1, v2);
180 };
183 > /**
184 > * Each function in this file which offers an equality comparison, has an accompanying
185 > * `*C` variant which returns an EqualityComparer function.
186 > *
187 > * The `*C` variant allows for easier composition of equality comparers and improved type-inference.
188 > */
189 > export namespace equals {
190 > export const strict = strictEquals;
191 > export const strictC = strictEqualsC;
192 >
193 > export const array = arrayEquals;
194 > export const arrayC = arrayEqualsC;
195 >
196 > export const structural = structuralEquals;
197 > export const structuralC = structuralEqualsC;
198 >
199 > export const jsonStringify = jsonStringifyEquals;
200 > export const jsonStringifyC = jsonStringifyEqualsC;
201 >
202 > export const thisC = thisEqualsC;
203 >
204 > export const ifDefined = equalsIfDefined;
205 > export const ifDefinedC = equalsIfDefinedC;
206 > }