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 PHP language #52

Merged
merged 42 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
bb95dad
added tree-sitter-php
urbit-pilled Mar 22, 2024
b1493d1
fix CONTRIBUTING.md link
urbit-pilled Mar 22, 2024
4a5c70f
add tree-sitter-python to lsp and target_language
urbit-pilled Mar 22, 2024
7aacc80
added tree-sitter-php to resources
urbit-pilled Mar 22, 2024
a8f3731
added wasm
urbit-pilled Mar 22, 2024
1f1a15d
add metavariable to grammar (initial)
urbit-pilled Mar 22, 2024
fcc3fc7
udpated tree-sitter-gritql submodule
urbit-pilled Mar 22, 2024
b6ac729
initial php tests working now
urbit-pilled Mar 22, 2024
ae56041
updated node-types and grammar.js
urbit-pilled Mar 22, 2024
0229548
fix conflicting metavariable prefix and php variable prefix
urbit-pilled Mar 22, 2024
a379303
deleted c bindings
urbit-pilled Mar 22, 2024
3d442ec
updated tree-sitter grammar with metavariable prefix change
urbit-pilled Mar 22, 2024
48f5a27
updated tests
urbit-pilled Mar 25, 2024
eace2a4
updated gritql to accept ^ as prefix
urbit-pilled Mar 25, 2024
d5c1201
updated php with php_only as default
urbit-pilled Mar 25, 2024
197575d
took a lot of debugging to find this
urbit-pilled Mar 25, 2024
0a8d0fc
added php to patterns_directory
urbit-pilled Mar 25, 2024
f009c77
Merge branch 'main' into main
urbit-pilled Mar 25, 2024
bc91a14
fix merge
urbit-pilled Mar 25, 2024
4a5c69f
remove yaml snapshot basic_php test
urbit-pilled Mar 25, 2024
a3c0e4f
added 2 more php tests
urbit-pilled Mar 25, 2024
9acad21
idk about these snapshots
urbit-pilled Mar 26, 2024
2225d9a
fixed tests
urbit-pilled Mar 27, 2024
8b4dba9
restore the parse_correct_variable_ranges snapshots
urbit-pilled Mar 27, 2024
6c98c81
merge with main
urbit-pilled Mar 27, 2024
55ff702
revert php grammar changes so that semicolons are required in snippet
urbit-pilled Mar 27, 2024
8c77c49
Merge branch 'main' into main
urbit-pilled Mar 27, 2024
9f4f125
added tests
urbit-pilled Mar 27, 2024
fc90e44
updated php grammar with new fields and placed more grit_metavariables
urbit-pilled Mar 28, 2024
cbf8081
added tests
urbit-pilled Mar 28, 2024
16f4d8a
Merge pull request #1 from urbit-pilled/add_tests
urbit-pilled Mar 28, 2024
c432a14
fixed array support
urbit-pilled Mar 28, 2024
8a54196
updated php resources
urbit-pilled Mar 28, 2024
066da65
updated tree-sitter-gritql submodule
urbit-pilled Mar 29, 2024
b0870fb
merge with remote main
urbit-pilled Mar 29, 2024
17d80bc
fix conflicts
urbit-pilled Mar 29, 2024
c631247
updated edit_grammars.mjs
urbit-pilled Mar 29, 2024
c469d93
edit_grammar.mjs GNU compatibility issue fixed and changed php->metav…
urbit-pilled Mar 29, 2024
6fedda7
removed grammar conflict, using precedence instead
urbit-pilled Mar 29, 2024
27ea566
updated php grammar
urbit-pilled Mar 30, 2024
df1a576
regenerating php files
urbit-pilled Mar 30, 2024
fd4e1d6
removed named_child_count == 1 and added more grammar fields
urbit-pilled Mar 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,6 @@
[submodule "resources/language-submodules/tree-sitter-toml"]
path = resources/language-submodules/tree-sitter-toml
url = https://github.com/ikatyang/tree-sitter-toml
[submodule "resources/language-submodules/tree-sitter-php"]
path = resources/language-submodules/tree-sitter-php
url = https://github.com/tree-sitter/tree-sitter-php
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Here are the steps for adding a new target language:
3. Copy the grammar file into `resources/metavariable-grammars`. This alternative grammar is used for parsing `snippets` in GritQL.
4. Patch the metavariable grammar to include `$.grit_metavariable` anywhere we want to substitute a metavariable. This is usually at least `$identifier` and `$literal`.
- For a snippet to match, it also needs to be a field. Often you’ll want to wrap `$thing` like: `field('thing', choice($.grit_metavariable, $thing))`
5. Add a new language implementation in `crates/core/src/languages`. This involves implementing the `Language` trait and adding a new `Language` enum variant.
5. Add a new language implementation in `crates/core/languages/src`. This involves implementing the `Language` trait and adding a new `Language` enum variant.
6. Add `snippet_context_strings` [like this](https://github.com/getgrit/gritql/blob/main/crates/language/src/sql.rs#L52) to provide context for snippets to match in.
7. Add test cases for the language in `crates/core/src/test.rs`. This is a good time to add a few dozen test cases to ensure that the language is parsed correctly, and that the metavariable grammar is working.

Expand Down
57 changes: 57 additions & 0 deletions crates/core/src/snapshots/marzano_core__test__basic_php.snap
urbit-pilled marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
source: crates/core/src/test.rs
expression: results
---
- __typename: Rewrite
original:
messages: []
variables:
- name: $new_files
scopedName: 0_0_$new_files
ranges: []
- name: $program
scopedName: 0_1_$program
ranges: []
- name: $filename
scopedName: 0_2_$filename
ranges: []
- name: $absolute_filename
scopedName: 0_3_$absolute_filename
ranges: []
- name: $str
scopedName: 1_0_$str
ranges: []
- name: $match
scopedName: 1_1_$match
ranges:
- start:
line: 1
column: 1
end:
line: 1
column: 19
startByte: 0
endByte: 18
sourceFile: foo.php
ranges:
- start:
line: 1
column: 1
end:
line: 1
column: 19
startByte: 0
endByte: 18
debug: "{\n \"SORT\": \"program\",\n \"RANGE\": {\n \"start\": {\n \"line\": 1,\n \"column\": 1\n },\n \"end\": {\n \"line\": 1,\n \"column\": 19\n }\n },\n \"TEXT\": \"echo \\\"hello world\\\"\",\n \"CHILDREN\": [\n {\n \"SORT\": \"text\",\n \"RANGE\": {\n \"start\": {\n \"line\": 1,\n \"column\": 1\n },\n \"end\": {\n \"line\": 1,\n \"column\": 19\n }\n },\n \"TEXT\": \"echo \\\"hello world\\\"\"\n }\n ]\n}"
rewritten:
messages: []
variables: []
sourceFile: foo.php
content: "echo \"hello world\";"
byteRanges:
- start: 0
end: 19
ansiSummary: ""
reason: ~
- __typename: DoneFile
relativeFilePath: foo.php
71 changes: 71 additions & 0 deletions crates/core/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8073,6 +8073,29 @@ fn test_basic_md() {
assert_yaml_snapshot!(results);
}

#[test]
fn test_basic_php() {
let pattern = r#"
|language php
|
|`echo $str` => `echo $str;`
|"#
.trim_margin()
.unwrap();

let source = r#"echo "hello world""#.trim_margin().unwrap();
let file = "foo.php";

let context = ExecutionContext::default();
let language: TargetLanguage = PatternLanguage::Php.try_into().unwrap();
// println!("language: {language} pattern: {pattern}");

let pattern = src_to_problem(pattern, language).unwrap();
let results = pattern.execute_file(&RichFile::new(file.to_owned(), source), &context);
// println!("results: {results}");
assert_yaml_snapshot!(results);
}
urbit-pilled marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of assert_yaml_snapshot! for testing is discouraged as per previous comments. Instead, consider using run_test_expected function with TestArgExpected struct to assert specific expected outcomes, which provides clearer, more maintainable tests.


#[test]
fn md_link_metavariable() {
let pattern = r#"
Expand Down Expand Up @@ -12725,3 +12748,51 @@ fn go_package_type() {
})
.unwrap();
}

#[test]
fn call_php() {
run_test_no_match({
TestArg {
pattern: r#"
|language php
|
|`TEST`
|"#
.trim_margin()
.unwrap(),
source: r#"
|echo "hello world"
|"#
.trim_margin()
.unwrap(),
}
})
.unwrap();
}


#[test]
fn call_php_2() {
run_test_expected({
urbit-pilled marked this conversation as resolved.
Show resolved Hide resolved
TestArgExpected {
pattern: r#"
|language php
|
|`echo $str` => `echo "modified"`
urbit-pilled marked this conversation as resolved.
Show resolved Hide resolved
|"#
.trim_margin()
.unwrap(),
source: r#"
|echo "this is a message"
|"#
.trim_margin()
.unwrap(),
expected: r#"
|echo "modified"
|"#
.trim_margin()
.unwrap(),
}
})
.unwrap();
}
4 changes: 4 additions & 0 deletions crates/gritmodule/src/patterns_directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub struct PatternsDirectory {
sql: BTreeMap<String, String>,
vue: BTreeMap<String, String>,
toml: BTreeMap<String, String>,
php: BTreeMap<String, String>,
universal: BTreeMap<String, String>,
}

Expand Down Expand Up @@ -80,6 +81,7 @@ impl PatternsDirectory {
sql: BTreeMap::new(),
vue: BTreeMap::new(),
toml: BTreeMap::new(),
php: BTreeMap::new(),
universal: BTreeMap::new(),
}
}
Expand Down Expand Up @@ -109,6 +111,7 @@ impl PatternsDirectory {
PatternLanguage::Sql => &mut self.sql,
PatternLanguage::Vue => &mut self.vue,
PatternLanguage::Toml => &mut self.toml,
PatternLanguage::Php => &mut self.php,
PatternLanguage::Universal => &mut self.universal,
}
}
Expand All @@ -135,6 +138,7 @@ impl PatternsDirectory {
PatternLanguage::Sql => &self.sql,
PatternLanguage::Vue => &self.vue,
PatternLanguage::Toml => &self.toml,
PatternLanguage::Php => &self.php,
PatternLanguage::Universal => &self.universal,
}
}
Expand Down
2 changes: 2 additions & 0 deletions crates/language/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ tree-sitter-ruby = { path = "../../resources/language-metavariables/tree-sitter-
tree-sitter-sql = { path = "../../resources/language-metavariables/tree-sitter-sql", optional = true }
tree-sitter-vue = { path = "../../resources/language-metavariables/tree-sitter-vue", optional = true }
tree-sitter-toml = { path = "../../resources/language-metavariables/tree-sitter-toml", optional = true }
tree-sitter-php = { path = "../../resources/language-metavariables/tree-sitter-php", optional = true }
serde_json = { version = "1.0.91", features = ["preserve_order"] }
marzano-util = { path = "../util" }
regex = "1.7.1"
Expand Down Expand Up @@ -63,5 +64,6 @@ builtin-parser = [
"tree-sitter-sql",
"tree-sitter-vue",
"tree-sitter-toml",
"tree-sitter-php",
]
finder = ["ignore"]
10 changes: 9 additions & 1 deletion crates/language/src/language.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ pub fn fields_for_nodes(language: &TSLanguage, types: &str) -> Vec<Vec<Field>> {
#[cfg(test)]
mod tests {
use super::nodes_from_indices;
use crate::{language::Language, tsx::Tsx};
use crate::{language::Language, php::Php, tsx::Tsx};
use tree_sitter::Parser;
use trim_margin::MarginTrimmable;

Expand Down Expand Up @@ -536,6 +536,14 @@ mod tests {
assert_eq!(subbed, "µfoo$('µbar')");
}

#[test]
fn test_php_substitute_variable() {
let snippet = "$foo$('$bar')";
let lang = Php::new(None);
let subbed = lang.substitute_metavariable_prefix(snippet);
assert_eq!(subbed, "µ[foo]$('µ[bar]')");
}
urbit-pilled marked this conversation as resolved.
Show resolved Hide resolved

#[test]
fn test_substitute_variable_template() {
let snippet = r#"
Expand Down
1 change: 1 addition & 0 deletions crates/language/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub mod language;
pub mod markdown_block;
pub mod markdown_inline;
pub mod parent_traverse;
pub mod php;
pub mod python;
pub mod ruby;
pub mod rust;
Expand Down
76 changes: 76 additions & 0 deletions crates/language/src/php.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use std::sync::OnceLock;

use crate::language::{fields_for_nodes, Field, Language, SortId, TSLanguage};

static NODE_TYPES_STRING: &str = include_str!("../../../resources/node-types/php-node-types.json");

static NODE_TYPES: OnceLock<Vec<Vec<Field>>> = OnceLock::new();
static LANGUAGE: OnceLock<TSLanguage> = OnceLock::new();

#[cfg(not(feature = "builtin-parser"))]
fn language() -> TSLanguage {
unimplemented!(
"tree-sitter parser must be initialized before use when [builtin-parser] is off."
)
}
#[cfg(feature = "builtin-parser")]
fn language() -> TSLanguage {
tree_sitter_php::language_php().into()
}

#[derive(Debug, Clone)]
pub struct Php {
node_types: &'static [Vec<Field>],
metavariable_sort: SortId,
language: &'static TSLanguage,
}

impl Php {
pub(crate) fn new(lang: Option<TSLanguage>) -> Self {
let language = LANGUAGE.get_or_init(|| lang.unwrap_or_else(language));
let node_types = NODE_TYPES.get_or_init(|| fields_for_nodes(language, NODE_TYPES_STRING));
let metavariable_sort = language.id_for_node_kind("grit_metavariable", true);
Self {
node_types,
metavariable_sort,
language,
}
}
pub(crate) fn is_initialized() -> bool {
LANGUAGE.get().is_some()
}
}

impl Language for Php {
fn get_ts_language(&self) -> &TSLanguage {
self.language
}

fn comment_prefix(&self) -> &'static str {
"//"
}

fn language_name(&self) -> &'static str {
"Php"
}
fn snippet_context_strings(&self) -> &[(&'static str, &'static str)] {
&[("", "")]
}

fn node_types(&self) -> &[Vec<Field>] {
self.node_types
}

fn metavariable_sort(&self) -> SortId {
self.metavariable_sort
}

fn substitute_metavariable_prefix(&self, src: &str) -> String {
self.metavariable_regex()
.replace_all(
src,
format!("{}[$1]", self.metavariable_prefix_substitute()).as_str(),
)
.to_string()
}
urbit-pilled marked this conversation as resolved.
Show resolved Hide resolved
}
Loading