66import { IConfigurationService } from 'vs/platform/configuration/common/configuration' ;
77import { IExtensionManifest } from 'vs/platform/extensionManagement/common/extensionManagement' ;
88import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil' ;
9+ import * as strings from 'vs/base/common/strings' ;
910
1011export const MANIFEST_CACHE_FOLDER = 'CachedExtensions' ;
1112export const USER_MANIFEST_CACHE_FILE = 'user' ;
@@ -31,3 +32,58 @@ export function isUIExtension(manifest: IExtensionManifest, configurationService
3132 default : return uiExtensions . has ( extensionId ) || ! manifest . main ;
3233 }
3334}
35+
36+ /**
37+ * **!Do not construct directly!**
38+ *
39+ * **!Only static methods because it gets serialized!**
40+ *
41+ * This represents the "canonical" version for an extension identifier. Extension ids
42+ * have to be case-insensitive (due to the marketplace), but we must ensure case
43+ * preservation because the extension API is already public at this time.
44+ *
45+ * For example, given an extension with the publisher `"Hello"` and the name `"World"`,
46+ * its canonical extension identifier is `"Hello.World"`. This extension could be
47+ * referenced in some other extension's dependencies using the string `"hello.world"`.
48+ *
49+ * To make matters more complicated, an extension can optionally have an UUID. When two
50+ * extensions have the same UUID, they are considered equal even if their identifier is different.
51+ */
52+ export class CanonicalExtensionIdentifier {
53+ public readonly value : string ;
54+ private readonly _lower : string ;
55+
56+ constructor ( value : string ) {
57+ this . value = value ;
58+ this . _lower = value . toLowerCase ( ) ;
59+ }
60+
61+ public static equals ( a : CanonicalExtensionIdentifier | string | null | undefined , b : CanonicalExtensionIdentifier | string | null | undefined ) {
62+ if ( typeof a === 'undefined' || a === null ) {
63+ return ( typeof b === 'undefined' || b === null ) ;
64+ }
65+ if ( typeof b === 'undefined' || b === null ) {
66+ return false ;
67+ }
68+ if ( typeof a === 'string' || typeof b === 'string' ) {
69+ // At least one of the arguments is an extension id in string form,
70+ // so we have to use the string comparison which ignores case.
71+ let aValue = ( typeof a === 'string' ? a : a . value ) ;
72+ let bValue = ( typeof b === 'string' ? b : b . value ) ;
73+ return strings . equalsIgnoreCase ( aValue , bValue ) ;
74+ }
75+
76+ // Now we know both arguments are CanonicalExtensionIdentifier
77+ return ( a . _lower === b . _lower ) ;
78+ }
79+
80+ /**
81+ * Gives the value by which to index (for equality).
82+ */
83+ public static toKey ( id : CanonicalExtensionIdentifier | string ) : string {
84+ if ( typeof id === 'string' ) {
85+ return id . toLowerCase ( ) ;
86+ }
87+ return id . _lower ;
88+ }
89+ }
0 commit comments