Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Dependency::with_new_resolver() #450

Merged
merged 2 commits into from
Apr 18, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
162 changes: 158 additions & 4 deletions src/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -611,8 +611,7 @@ impl ImportKind {
}
}

#[derive(Clone, Debug, Serialize)]
#[cfg_attr(test, derive(Eq, PartialEq))]
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Import {
pub specifier: String,
Expand All @@ -627,13 +626,15 @@ pub struct Import {
pub attributes: ImportAttributes,
}

#[derive(Debug, Default, Clone, Serialize)]
#[derive(Debug, Default, Clone, Eq, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Dependency {
#[serde(rename = "code", skip_serializing_if = "Resolution::is_none")]
pub maybe_code: Resolution,
#[serde(rename = "type", skip_serializing_if = "Resolution::is_none")]
pub maybe_type: Resolution,
#[serde(skip_serializing)]
pub maybe_deno_types_specifier: Option<String>,
#[serde(skip_serializing_if = "is_false")]
pub is_dynamic: bool,
// todo(dsherret): rename to attributeType in 2.0
Expand Down Expand Up @@ -673,15 +674,86 @@ impl Dependency {
}
None
}

pub fn with_new_resolver(
&self,
specifier: &str,
maybe_resolver: Option<&dyn Resolver>,
maybe_npm_resolver: Option<&dyn NpmResolver>,
) -> Self {
let maybe_code = self
.maybe_code
.maybe_range()
.map(|r| {
resolve(
specifier,
r.clone(),
ResolutionMode::Execution,
maybe_resolver,
maybe_npm_resolver,
)
})
.unwrap_or_default();
let maybe_type = self
.maybe_type
.maybe_range()
.map(|r| {
resolve(
self
.maybe_deno_types_specifier
.as_deref()
.unwrap_or(specifier),
r.clone(),
ResolutionMode::Types,
maybe_resolver,
maybe_npm_resolver,
)
})
.unwrap_or_default();
Self {
maybe_code,
maybe_type,
maybe_deno_types_specifier: self.maybe_deno_types_specifier.clone(),
is_dynamic: self.is_dynamic,
maybe_attribute_type: self.maybe_attribute_type.clone(),
imports: self.imports.clone(),
}
}
}

#[derive(Debug, Clone, Serialize)]
#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TypesDependency {
pub specifier: String,
pub dependency: Resolution,
}

impl TypesDependency {
pub fn with_new_resolver(
&self,
maybe_resolver: Option<&dyn Resolver>,
maybe_npm_resolver: Option<&dyn NpmResolver>,
) -> Self {
let dependency = self
.dependency
.maybe_range()
.map(|r| {
resolve(
&self.specifier,
r.clone(),
ResolutionMode::Types,
maybe_resolver,
maybe_npm_resolver,
)
})
.unwrap_or_default();
Self {
specifier: self.specifier.clone(),
dependency,
}
}
}

fn is_media_type_unknown(media_type: &MediaType) -> bool {
matches!(media_type, MediaType::Unknown)
}
Expand Down Expand Up @@ -975,6 +1047,7 @@ impl GraphImport {
is_dynamic: false,
maybe_code: Resolution::None,
maybe_type,
maybe_deno_types_specifier: None,
maybe_attribute_type: None,
imports: vec![],
},
Expand Down Expand Up @@ -2437,6 +2510,7 @@ fn fill_module_dependencies(
let specifier = module_specifier.clone();
let maybe_type =
if let Some(pragma) = analyze_deno_types(&leading_comments) {
dep.maybe_deno_types_specifier = Some(pragma.specifier.clone());
resolve(
&pragma.specifier,
Range::from_position_range(specifier, pragma.range),
Expand Down Expand Up @@ -4744,6 +4818,86 @@ mod tests {
);
}

#[test]
fn dependency_with_new_resolver() {
let referrer = ModuleSpecifier::parse("file:///a/main.ts").unwrap();
let dependency = Dependency {
maybe_code: Resolution::Ok(Box::new(ResolutionResolved {
specifier: ModuleSpecifier::parse("file:///wrong.ts").unwrap(),
range: Range {
specifier: referrer.clone(),
start: Position::zeroed(),
end: Position::zeroed(),
},
})),
maybe_type: Resolution::Ok(Box::new(ResolutionResolved {
specifier: ModuleSpecifier::parse("file:///wrong.ts").unwrap(),
range: Range {
specifier: referrer.clone(),
start: Position::zeroed(),
end: Position::zeroed(),
},
})),
maybe_deno_types_specifier: Some("./b.d.ts".to_string()),
..Default::default()
};
let new_dependency = dependency.with_new_resolver("./b.ts", None, None);
assert_eq!(
new_dependency,
Dependency {
maybe_code: Resolution::Ok(Box::new(ResolutionResolved {
specifier: ModuleSpecifier::parse("file:///a/b.ts").unwrap(),
range: Range {
specifier: referrer.clone(),
start: Position::zeroed(),
end: Position::zeroed(),
},
})),
maybe_type: Resolution::Ok(Box::new(ResolutionResolved {
specifier: ModuleSpecifier::parse("file:///a/b.d.ts").unwrap(),
range: Range {
specifier: referrer.clone(),
start: Position::zeroed(),
end: Position::zeroed(),
},
})),
maybe_deno_types_specifier: Some("./b.d.ts".to_string()),
..Default::default()
}
);
}

#[test]
fn types_dependency_with_new_resolver() {
let referrer = ModuleSpecifier::parse("file:///a/main.ts").unwrap();
let types_dependency = TypesDependency {
specifier: "./main.d.ts".to_string(),
dependency: Resolution::Ok(Box::new(ResolutionResolved {
specifier: ModuleSpecifier::parse("file:///wrong.ts").unwrap(),
range: Range {
specifier: referrer.clone(),
start: Position::zeroed(),
end: Position::zeroed(),
},
})),
};
let new_types_dependency = types_dependency.with_new_resolver(None, None);
assert_eq!(
new_types_dependency,
TypesDependency {
specifier: "./main.d.ts".to_string(),
dependency: Resolution::Ok(Box::new(ResolutionResolved {
specifier: ModuleSpecifier::parse("file:///a/main.d.ts").unwrap(),
range: Range {
specifier: referrer.clone(),
start: Position::zeroed(),
end: Position::zeroed(),
},
})),
}
);
}

#[tokio::test]
async fn static_dep_of_dynamic_dep_is_dynamic() {
struct TestLoader {
Expand Down