From 901d6570090be48c3876b724ea2023010950f5bf Mon Sep 17 00:00:00 2001 From: Andrey Lunyov Date: Tue, 22 Mar 2022 13:46:16 -0700 Subject: [PATCH] Add JavaScript language Summary: Add new language option: JavaScript - for this language we won't emit any type information in the generated artifacts. Next diff in stack will change the configuration of the compiler to explicitly specify the language. Reviewed By: josephsavona Differential Revision: D35049339 fbshipit-source-id: 39be62a597d9b8cbdaeb644994941d2a1867e766 --- .../src/build_project/artifact_content.rs | 31 +++++--- .../src/build_project/artifact_locator.rs | 4 +- compiler/crates/relay-compiler/src/config.rs | 2 +- .../src/file_source/file_categorizer.rs | 7 +- .../src/file_source/walk_dir_file_source.rs | 2 +- .../src/file_source/watchman_query_builder.rs | 4 +- .../crates/relay-config/src/typegen_config.rs | 5 +- .../crates/relay-typegen/src/javascript.rs | 71 +++++++++++++++++++ compiler/crates/relay-typegen/src/lib.rs | 7 +- 9 files changed, 115 insertions(+), 18 deletions(-) create mode 100644 compiler/crates/relay-typegen/src/javascript.rs diff --git a/compiler/crates/relay-compiler/src/build_project/artifact_content.rs b/compiler/crates/relay-compiler/src/build_project/artifact_content.rs index 888057d33e264..c8d570d49835d 100644 --- a/compiler/crates/relay-compiler/src/build_project/artifact_content.rs +++ b/compiler/crates/relay-compiler/src/build_project/artifact_content.rs @@ -215,7 +215,9 @@ fn generate_updatable_query( writeln!(content, " */\n")?; write_disable_lint_header(&project_config.typegen_config.language, &mut content)?; - if project_config.typegen_config.language == TypegenLanguage::Flow { + if project_config.typegen_config.language == TypegenLanguage::Flow + || project_config.typegen_config.language == TypegenLanguage::JavaScript + { writeln!(content, "'use strict';\n")?; } @@ -254,7 +256,7 @@ fn generate_updatable_query( match project_config.typegen_config.language { TypegenLanguage::Flow => writeln!(content, "*/\n")?, - TypegenLanguage::TypeScript => writeln!(content)?, + TypegenLanguage::TypeScript | TypegenLanguage::JavaScript => writeln!(content)?, } let request = printer.print_updatable_query(schema, &operation_fragment); @@ -333,7 +335,9 @@ fn generate_operation( writeln!(content, " */\n")?; write_disable_lint_header(&project_config.typegen_config.language, &mut content)?; - if project_config.typegen_config.language == TypegenLanguage::Flow { + if project_config.typegen_config.language == TypegenLanguage::Flow + || project_config.typegen_config.language == TypegenLanguage::JavaScript + { writeln!(content, "'use strict';\n")?; } @@ -396,7 +400,7 @@ fn generate_operation( match project_config.typegen_config.language { TypegenLanguage::Flow => writeln!(content, "*/\n")?, - TypegenLanguage::TypeScript => writeln!(content)?, + TypegenLanguage::TypeScript | TypegenLanguage::JavaScript => writeln!(content)?, } let mut top_level_statements = Default::default(); if let Some(provided_variables) = @@ -450,6 +454,12 @@ fn generate_operation( "require('relay-runtime').PreloadableQueryRegistry.set((node.params/*: any*/).id, node);\n", )?; } + TypegenLanguage::JavaScript => { + writeln!( + content, + "require('relay-runtime').PreloadableQueryRegistry.set(node.params).id, node);\n", + )?; + } TypegenLanguage::TypeScript => { writeln!( content, @@ -520,7 +530,7 @@ fn generate_split_operation( } match project_config.typegen_config.language { TypegenLanguage::Flow => writeln!(content, "*/\n")?, - TypegenLanguage::TypeScript => writeln!(content)?, + TypegenLanguage::TypeScript | TypegenLanguage::JavaScript => writeln!(content)?, } let mut top_level_statements = Default::default(); @@ -649,7 +659,7 @@ fn generate_read_only_fragment( match project_config.typegen_config.language { TypegenLanguage::Flow => writeln!(content, "*/\n")?, - TypegenLanguage::TypeScript => writeln!(content)?, + TypegenLanguage::TypeScript | TypegenLanguage::JavaScript => writeln!(content)?, } let mut top_level_statements = Default::default(); let fragment = printer.print_fragment(schema, reader_fragment, &mut top_level_statements); @@ -721,7 +731,7 @@ fn generate_assignable_fragment( match project_config.typegen_config.language { TypegenLanguage::Flow => writeln!(content, "*/\n")?, - TypegenLanguage::TypeScript => writeln!(content)?, + TypegenLanguage::TypeScript | TypegenLanguage::JavaScript => writeln!(content)?, } // Assignable fragments should never be passed to useFragment, and thus, we @@ -743,6 +753,7 @@ fn write_variable_value_with_type( value: &str, ) -> FmtResult { match language { + TypegenLanguage::JavaScript => writeln!(content, "var {} = {};\n", variable_name, value), TypegenLanguage::Flow => writeln!( content, "var {}/*: {}*/ = {};\n", @@ -764,6 +775,7 @@ fn write_disable_lint_header(language: &TypegenLanguage, content: &mut String) - TypegenLanguage::Flow => { writeln!(content, "/* eslint-disable */\n") } + TypegenLanguage::JavaScript => Ok(()), } } @@ -774,6 +786,7 @@ fn write_import_type_from( from: &str, ) -> FmtResult { match language { + TypegenLanguage::JavaScript => Ok(()), TypegenLanguage::Flow => writeln!(content, "import type {{ {} }} from '{}';", type_, from), TypegenLanguage::TypeScript => writeln!(content, "import {{ {} }} from '{}';", type_, from), } @@ -789,7 +802,7 @@ fn write_export_generated_node( writeln!(content, "export default {};", variable_node) } else { match (typegen_config.language, forced_type) { - (TypegenLanguage::Flow, None) => { + (TypegenLanguage::Flow, None) | (TypegenLanguage::JavaScript, _) => { writeln!(content, "module.exports = {};", variable_node) } (TypegenLanguage::Flow, Some(forced_type)) => writeln!( @@ -827,6 +840,7 @@ fn write_source_hash( TypegenLanguage::Flow => { writeln!(content, " (node/*: any*/).hash = \"{}\";", source_hash)? } + TypegenLanguage::JavaScript => writeln!(content, "node.hash = \"{}\";", source_hash)?, TypegenLanguage::TypeScript => { writeln!(content, " (node as any).hash = \"{}\";", source_hash)? } @@ -837,6 +851,7 @@ fn write_source_hash( TypegenLanguage::Flow => { writeln!(content, "(node/*: any*/).hash = \"{}\";\n", source_hash)? } + TypegenLanguage::JavaScript => writeln!(content, "node.hash = \"{}\";", source_hash)?, TypegenLanguage::TypeScript => { writeln!(content, "(node as any).hash = \"{}\";\n", source_hash)? } diff --git a/compiler/crates/relay-compiler/src/build_project/artifact_locator.rs b/compiler/crates/relay-compiler/src/build_project/artifact_locator.rs index 5df634cf15b1a..f5eaed77d8fac 100644 --- a/compiler/crates/relay-compiler/src/build_project/artifact_locator.rs +++ b/compiler/crates/relay-compiler/src/build_project/artifact_locator.rs @@ -51,7 +51,9 @@ pub fn path_for_artifact( filename_for_artifact(source_file, definition_name) } else { match &project_config.typegen_config.language { - TypegenLanguage::Flow => format!("{}.graphql.js", definition_name), + TypegenLanguage::Flow | TypegenLanguage::JavaScript => { + format!("{}.graphql.js", definition_name) + } TypegenLanguage::TypeScript => format!("{}.graphql.ts", definition_name), } }; diff --git a/compiler/crates/relay-compiler/src/config.rs b/compiler/crates/relay-compiler/src/config.rs index bcdb19d6fb217..6d11ea7b968ae 100644 --- a/compiler/crates/relay-compiler/src/config.rs +++ b/compiler/crates/relay-compiler/src/config.rs @@ -746,7 +746,7 @@ impl SingleProjectConfigFile { .collect(), persist: self.persist_config, typegen_config: TypegenConfig { - language: self.language.unwrap_or(TypegenLanguage::TypeScript), + language: self.language.unwrap_or_default(), custom_scalar_types: self.custom_scalars.clone(), eager_es_modules: self.eager_es_modules, flow_typegen: FlowTypegenConfig { diff --git a/compiler/crates/relay-compiler/src/file_source/file_categorizer.rs b/compiler/crates/relay-compiler/src/file_source/file_categorizer.rs index 43670b70f0fa4..3dd9561f1e9e4 100644 --- a/compiler/crates/relay-compiler/src/file_source/file_categorizer.rs +++ b/compiler/crates/relay-compiler/src/file_source/file_categorizer.rs @@ -349,7 +349,9 @@ fn is_extra_extensions(extension: &OsStr) -> bool { fn is_valid_source_code_extension(typegen_language: &TypegenLanguage, extension: &OsStr) -> bool { match typegen_language { TypegenLanguage::TypeScript => is_source_code_extension(extension), - TypegenLanguage::Flow => extension == "js" || extension == "jsx", + TypegenLanguage::Flow | TypegenLanguage::JavaScript => { + extension == "js" || extension == "jsx" + } } } @@ -385,7 +387,8 @@ mod tests { "language": "flow" }, "typescript": { - "schema": "graphql/ts_schema.graphql" + "schema": "graphql/ts_schema.graphql", + "language": "typescript" }, "overlapping_generated_dir": { "schema": "graphql/__generated__/custom.graphql", diff --git a/compiler/crates/relay-compiler/src/file_source/walk_dir_file_source.rs b/compiler/crates/relay-compiler/src/file_source/walk_dir_file_source.rs index c53ea3ef62569..2990cb5d81f9b 100644 --- a/compiler/crates/relay-compiler/src/file_source/walk_dir_file_source.rs +++ b/compiler/crates/relay-compiler/src/file_source/walk_dir_file_source.rs @@ -36,7 +36,7 @@ fn get_expected_file_extensions(config: &Config) -> HashSet<&str> { for project in config.enabled_projects() { match project.typegen_config.language { - TypegenLanguage::Flow => { + TypegenLanguage::Flow | TypegenLanguage::JavaScript => { file_extensions.insert("js"); file_extensions.insert("jsx"); } diff --git a/compiler/crates/relay-compiler/src/file_source/watchman_query_builder.rs b/compiler/crates/relay-compiler/src/file_source/watchman_query_builder.rs index df18c013a1a19..8fd2cc68e89cc 100644 --- a/compiler/crates/relay-compiler/src/file_source/watchman_query_builder.rs +++ b/compiler/crates/relay-compiler/src/file_source/watchman_query_builder.rs @@ -25,7 +25,9 @@ pub fn get_watchman_expr(config: &Config) -> Expr { Expr::All(vec![ // Ending in *.js(x) or *.ts(x) depending on the project language. Expr::Suffix(match &project.typegen_config.language { - TypegenLanguage::Flow => vec![PathBuf::from("js"), PathBuf::from("jsx")], + TypegenLanguage::Flow | TypegenLanguage::JavaScript => { + vec![PathBuf::from("js"), PathBuf::from("jsx")] + } TypegenLanguage::TypeScript => { vec![ PathBuf::from("js"), diff --git a/compiler/crates/relay-config/src/typegen_config.rs b/compiler/crates/relay-config/src/typegen_config.rs index 571fe982e72db..4fa901b6624e7 100644 --- a/compiler/crates/relay-config/src/typegen_config.rs +++ b/compiler/crates/relay-config/src/typegen_config.rs @@ -16,13 +16,14 @@ type FnvIndexMap = IndexMap; #[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq)] #[serde(deny_unknown_fields, rename_all = "lowercase")] pub enum TypegenLanguage { - Flow, + JavaScript, TypeScript, + Flow, } impl Default for TypegenLanguage { fn default() -> Self { - Self::TypeScript + Self::JavaScript } } diff --git a/compiler/crates/relay-typegen/src/javascript.rs b/compiler/crates/relay-typegen/src/javascript.rs new file mode 100644 index 0000000000000..0d272fdf9006f --- /dev/null +++ b/compiler/crates/relay-typegen/src/javascript.rs @@ -0,0 +1,71 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +use crate::writer::{Writer, AST}; + +use std::fmt::{Result as FmtResult, Write}; + +#[derive(Default)] +pub struct JavaScriptPrinter { + result: String, +} + +impl Write for JavaScriptPrinter { + fn write_str(&mut self, s: &str) -> FmtResult { + self.result.write_str(s) + } +} + +impl Writer for JavaScriptPrinter { + fn into_string(self: Box) -> String { + self.result + } + + fn write(&mut self, _ast: &AST) -> FmtResult { + Ok(()) + } + + fn get_runtime_fragment_import(&self) -> &'static str { + "" + } + + fn write_local_type(&mut self, _name: &str, _value: &AST) -> FmtResult { + Ok(()) + } + + fn write_export_type(&mut self, _name: &str, _value: &AST) -> FmtResult { + Ok(()) + } + + fn write_import_module_default(&mut self, _name: &str, _from: &str) -> FmtResult { + Ok(()) + } + + fn write_import_type(&mut self, _types: &[&str], _from: &str) -> FmtResult { + Ok(()) + } + + fn write_import_fragment_type(&mut self, _types: &[&str], _from: &str) -> FmtResult { + Ok(()) + } + + fn write_export_fragment_type(&mut self, _old_name: &str, _new_name: &str) -> FmtResult { + Ok(()) + } + + fn write_export_fragment_types( + &mut self, + _fragment_type_name_1: &str, + _fragment_type_name_2: &str, + ) -> FmtResult { + Ok(()) + } + + fn write_any_type_definition(&mut self, _name: &str) -> FmtResult { + Ok(()) + } +} diff --git a/compiler/crates/relay-typegen/src/lib.rs b/compiler/crates/relay-typegen/src/lib.rs index 2f0ca6271d584..c4e5cf133e0a5 100644 --- a/compiler/crates/relay-typegen/src/lib.rs +++ b/compiler/crates/relay-typegen/src/lib.rs @@ -10,6 +10,7 @@ #![deny(clippy::all)] mod flow; +mod javascript; mod typescript; mod writer; @@ -26,6 +27,7 @@ use graphql_ir::{ }; use indexmap::{map::Entry, IndexMap, IndexSet}; use itertools::Itertools; +use javascript::JavaScriptPrinter; use lazy_static::lazy_static; pub use relay_config::{FlowTypegenPhase, TypegenConfig, TypegenLanguage}; use relay_config::{JsModuleFormat, ProjectConfig, SchemaConfig}; @@ -239,6 +241,7 @@ impl<'a> TypeGenerator<'a> { match_fields: Default::default(), runtime_imports: RuntimeImports::default(), writer: match &typegen_config.language { + TypegenLanguage::JavaScript => Box::new(JavaScriptPrinter::default()), TypegenLanguage::Flow => Box::new(FlowPrinter::new(flow_typegen_phase)), TypegenLanguage::TypeScript => Box::new(TypeScriptPrinter::new( typegen_config, @@ -1791,7 +1794,7 @@ impl<'a> TypeGenerator<'a> { )); let (open_comment, close_comment) = match self.typegen_config.language { - TypegenLanguage::Flow => ("/*", "*/"), + TypegenLanguage::Flow | TypegenLanguage::JavaScript => ("/*", "*/"), TypegenLanguage::TypeScript => ("", ""), }; @@ -1883,7 +1886,7 @@ impl<'a> TypeGenerator<'a> { )); let (open_comment, close_comment) = match self.typegen_config.language { - TypegenLanguage::Flow => ("/*", "*/"), + TypegenLanguage::Flow | TypegenLanguage::JavaScript => ("/*", "*/"), TypegenLanguage::TypeScript => ("", ""), };