0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-01 09:24:20 -04:00
denoland-deno/cli/tools/vendor/analyze.rs
David Sherret 10e4b2e140
chore: update copyright year to 2023 (#17247)
Yearly tradition of creating extra noise in git.
2023-01-02 21:00:42 +00:00

113 lines
3.1 KiB
Rust

// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use deno_ast::swc::ast::ExportDefaultDecl;
use deno_ast::swc::ast::ExportSpecifier;
use deno_ast::swc::ast::ModuleExportName;
use deno_ast::swc::ast::NamedExport;
use deno_ast::swc::ast::Program;
use deno_ast::swc::visit::noop_visit_type;
use deno_ast::swc::visit::Visit;
use deno_ast::swc::visit::VisitWith;
use deno_ast::ParsedSource;
/// Gets if the parsed source has a default export.
pub fn has_default_export(source: &ParsedSource) -> bool {
let mut visitor = DefaultExportFinder {
has_default_export: false,
};
let program = source.program();
let program: &Program = &program;
program.visit_with(&mut visitor);
visitor.has_default_export
}
struct DefaultExportFinder {
has_default_export: bool,
}
impl Visit for DefaultExportFinder {
noop_visit_type!();
fn visit_export_default_decl(&mut self, _: &ExportDefaultDecl) {
self.has_default_export = true;
}
fn visit_named_export(&mut self, named_export: &NamedExport) {
if named_export
.specifiers
.iter()
.any(export_specifier_has_default)
{
self.has_default_export = true;
}
}
}
fn export_specifier_has_default(s: &ExportSpecifier) -> bool {
match s {
ExportSpecifier::Default(_) => true,
ExportSpecifier::Namespace(_) => false,
ExportSpecifier::Named(named) => {
let export_name = named.exported.as_ref().unwrap_or(&named.orig);
match export_name {
ModuleExportName::Str(_) => false,
ModuleExportName::Ident(ident) => &*ident.sym == "default",
}
}
}
}
#[cfg(test)]
mod test {
use deno_ast::MediaType;
use deno_ast::ParseParams;
use deno_ast::ParsedSource;
use deno_ast::SourceTextInfo;
use super::has_default_export;
#[test]
fn has_default_when_export_default_decl() {
let parsed_source = parse_module("export default class Class {}");
assert!(has_default_export(&parsed_source));
}
#[test]
fn has_default_when_named_export() {
let parsed_source = parse_module("export {default} from './test.ts';");
assert!(has_default_export(&parsed_source));
}
#[test]
fn has_default_when_named_export_alias() {
let parsed_source =
parse_module("export {test as default} from './test.ts';");
assert!(has_default_export(&parsed_source));
}
#[test]
fn not_has_default_when_named_export_not_exported() {
let parsed_source =
parse_module("export {default as test} from './test.ts';");
assert!(!has_default_export(&parsed_source));
}
#[test]
fn not_has_default_when_not() {
let parsed_source = parse_module("export {test} from './test.ts'; export class Test{} export * from './test';");
assert!(!has_default_export(&parsed_source));
}
fn parse_module(text: &str) -> ParsedSource {
deno_ast::parse_module(ParseParams {
specifier: "file:///mod.ts".to_string(),
capture_tokens: false,
maybe_syntax: None,
media_type: MediaType::TypeScript,
scope_analysis: false,
text_info: SourceTextInfo::from_string(text.to_string()),
})
.unwrap()
}
}