Add telemetry events for loading extensions (#9793)

* Store extensions versions' wasm API version in the database
* Share a common struct for extension API responses between collab and
client
* Add wasm API version and schema version to extension API responses

Release Notes:

- N/A

Co-authored-by: Marshall <marshall@zed.dev>
This commit is contained in:
Max Brunsfeld 2024-03-25 14:30:48 -07:00 committed by GitHub
parent 9b62e461ed
commit 5adc51f113
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 531 additions and 306 deletions

View file

@ -1,7 +1,14 @@
use anyhow::{anyhow, Context, Result};
use collections::BTreeMap;
use fs::Fs;
use language::LanguageServerName;
use serde::{Deserialize, Serialize};
use std::{path::PathBuf, sync::Arc};
use std::{
ffi::OsStr,
path::{Path, PathBuf},
sync::Arc,
};
use util::SemanticVersion;
/// This is the old version of the extension manifest, from when it was `extension.json`.
#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
@ -53,6 +60,7 @@ pub struct ExtensionManifest {
#[derive(Clone, Default, PartialEq, Eq, Debug, Deserialize, Serialize)]
pub struct LibManifestEntry {
pub kind: Option<ExtensionLibraryKind>,
pub version: Option<SemanticVersion>,
}
#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
@ -71,3 +79,68 @@ pub struct GrammarManifestEntry {
pub struct LanguageServerManifestEntry {
pub language: Arc<str>,
}
impl ExtensionManifest {
pub async fn load(fs: Arc<dyn Fs>, extension_dir: &Path) -> Result<Self> {
let extension_name = extension_dir
.file_name()
.and_then(OsStr::to_str)
.ok_or_else(|| anyhow!("invalid extension name"))?;
let mut extension_manifest_path = extension_dir.join("extension.json");
if fs.is_file(&extension_manifest_path).await {
let manifest_content = fs
.load(&extension_manifest_path)
.await
.with_context(|| format!("failed to load {extension_name} extension.json"))?;
let manifest_json = serde_json::from_str::<OldExtensionManifest>(&manifest_content)
.with_context(|| {
format!("invalid extension.json for extension {extension_name}")
})?;
Ok(manifest_from_old_manifest(manifest_json, extension_name))
} else {
extension_manifest_path.set_extension("toml");
let manifest_content = fs
.load(&extension_manifest_path)
.await
.with_context(|| format!("failed to load {extension_name} extension.toml"))?;
toml::from_str(&manifest_content)
.with_context(|| format!("invalid extension.json for extension {extension_name}"))
}
}
}
fn manifest_from_old_manifest(
manifest_json: OldExtensionManifest,
extension_id: &str,
) -> ExtensionManifest {
ExtensionManifest {
id: extension_id.into(),
name: manifest_json.name,
version: manifest_json.version,
description: manifest_json.description,
repository: manifest_json.repository,
authors: manifest_json.authors,
schema_version: 0,
lib: Default::default(),
themes: {
let mut themes = manifest_json.themes.into_values().collect::<Vec<_>>();
themes.sort();
themes.dedup();
themes
},
languages: {
let mut languages = manifest_json.languages.into_values().collect::<Vec<_>>();
languages.sort();
languages.dedup();
languages
},
grammars: manifest_json
.grammars
.into_keys()
.map(|grammar_name| (grammar_name, Default::default()))
.collect(),
language_servers: Default::default(),
}
}