Skip to content

Commit 21e9d9c

Browse files
committed
2 parents 4ca8a25 + 272cb32 commit 21e9d9c

File tree

916 files changed

+119731
-26453
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

916 files changed

+119731
-26453
lines changed

.github/workflows/inform-pages-repo.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ jobs:
6363
python ./scripts/docs/append-file-docs.py
6464
6565
- name: Upload Docs Artifact
66-
uses: actions/upload-artifact@v3
66+
uses: actions/upload-artifact@v4
6767
with:
6868
name: opengoal-docs
6969
if-no-files-found: error

.github/workflows/linux-build-clang.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ jobs:
7171
strip ./build/lsp/lsp
7272
7373
- name: Upload artifact
74-
uses: actions/upload-artifact@v3
74+
uses: actions/upload-artifact@v4
7575
if: ${{ inputs.uploadArtifacts }}
7676
with:
7777
name: opengoal-linux-${{ inputs.cachePrefix }}

.github/workflows/macos-build-arm.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ jobs:
5555
run: ./test.sh
5656

5757
- name: Upload artifact
58-
uses: actions/upload-artifact@v3
58+
uses: actions/upload-artifact@v4
5959
with:
6060
name: opengoal-macos-${{ inputs.cachePrefix }}
6161
if-no-files-found: error

.github/workflows/macos-build.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ jobs:
6464
strip ./build/lsp/lsp
6565
6666
- name: Upload artifact
67-
uses: actions/upload-artifact@v3
67+
uses: actions/upload-artifact@v4
6868
if: ${{ inputs.uploadArtifacts }}
6969
with:
7070
name: opengoal-macos-${{ inputs.cachePrefix }}

.github/workflows/release-pipeline.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
- name: Prepare Artifact Folder
5252
run: mkdir -p ./ci-artifacts/final
5353

54-
- uses: actions/download-artifact@v3
54+
- uses: actions/download-artifact@v4
5555
name: Download all Artifacts
5656
with:
5757
path: ./ci-artifacts/

.github/workflows/windows-build-clang.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ jobs:
7171
run: ./build/bin/goalc-test.exe --gtest_color=yes --gtest_brief=0 --gtest_filter="-*MANUAL_TEST*"
7272

7373
- name: Upload artifact
74-
uses: actions/upload-artifact@v3
74+
uses: actions/upload-artifact@v4
7575
if: ${{ inputs.uploadArtifacts }}
7676
with:
7777
name: opengoal-windows-${{ inputs.cachePrefix }}

.prettierrc

-1
This file was deleted.

.prettierrc.json

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"endOfLine": "auto",
3+
"overrides": [
4+
{
5+
"files": ["**/*.jsonc"],
6+
"options": {
7+
"parser": "json"
8+
}
9+
}
10+
]
11+
}

.vs/launch.vs.json

+25
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,18 @@
6868
"jak2"
6969
]
7070
},
71+
{
72+
"type": "default",
73+
"project": "CMakeLists.txt",
74+
"projectTarget": "offline-test.exe (bin\\offline-test.exe)",
75+
"name": "Tests - Offline Tests - Jak 3",
76+
"args": [
77+
"--iso_data_path",
78+
"${workspaceRoot}/iso_data/jak3",
79+
"--game",
80+
"jak3"
81+
]
82+
},
7183
{
7284
"type": "default",
7385
"project": "CMakeLists.txt",
@@ -218,6 +230,19 @@
218230
"--config-override \"{\\\"decompile_code\\\": false, \\\"levels_extract\\\": true, \\\"allowed_objects\\\": []}\""
219231
]
220232
},
233+
{
234+
"type": "default",
235+
"project": "CMakeLists.txt",
236+
"projectTarget": "decompiler.exe (bin\\decompiler.exe)",
237+
"name": "Decompiler - Jak 3",
238+
"args": [
239+
"${workspaceRoot}/decompiler/config/jak3/jak3_config.jsonc",
240+
"${workspaceRoot}/iso_data",
241+
"${workspaceRoot}/decompiler_out",
242+
"--version",
243+
"ntsc_v1"
244+
]
245+
},
221246
{
222247
"type": "default",
223248
"project": "CMakeLists.txt",

CMakePresets.json

+10
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,16 @@
108108
"description": "Build with Clang with Debug Symbols",
109109
"inherits": ["base-windows-debug", "base-clang"]
110110
},
111+
{
112+
"name": "Debug-windows-clang-static",
113+
"displayName": "Windows Static Debug (clang)",
114+
"description": "Build with Clang as Debug but statically linked",
115+
"inherits": ["base-windows-debug", "base-clang"],
116+
"cacheVariables": {
117+
"STATICALLY_LINK": "true",
118+
"ZYDIS_BUILD_SHARED_LIB": "OFF"
119+
}
120+
},
111121
{
112122
"name": "RelWithDebInfo-windows-clang",
113123
"displayName": "Windows RelWithDebInfo (clang)",

Taskfile.yml

+9-13
Original file line numberDiff line numberDiff line change
@@ -74,24 +74,23 @@ tasks:
7474
msg: "Couldn't locate compiler executable in '{{.GOALC_BIN_RELEASE_DIR}}/goalc'"
7575
cmds:
7676
- "{{.GOALC_BIN_RELEASE_DIR}}/goalc --user-auto --game {{.GAME}}"
77-
format:
77+
format-json:
7878
desc: "Format code"
7979
cmds:
80-
- cmd: python ./scripts/cpp/format-includes.py
81-
- cmd: python ./third-party/run-clang-format/run-clang-format.py -r common decompiler game goalc test tools lsp -i
8280
# npm install -g prettier
8381
- cmd: npx prettier --write ./decompiler/config/jak1/**/*.jsonc
8482
ignore_error: true
8583
- cmd: npx prettier --write ./decompiler/config/jak2/**/*.jsonc
8684
ignore_error: true
87-
format-json:
85+
- cmd: npx prettier --write ./decompiler/config/jak3/**/*.jsonc
86+
ignore_error: true
87+
format:
8888
desc: "Format code"
8989
cmds:
90-
# npm install -g prettier
91-
- cmd: npx prettier --write ./decompiler/config/jak1/**/*.jsonc
92-
ignore_error: true
93-
- cmd: npx prettier --write ./decompiler/config/jak2/**/*.jsonc
94-
ignore_error: true
90+
- cmd: python ./scripts/cpp/format-includes.py
91+
- cmd: python ./third-party/run-clang-format/run-clang-format.py -r common decompiler game goalc test tools lsp -i
92+
- task: format-json
93+
9594
# DECOMPILING
9695
decomp:
9796
cmds:
@@ -166,9 +165,6 @@ tasks:
166165
ignore_error: true
167166
- python ./scripts/update_decomp_reference.py ./failures ./test/decompiler/reference/ --game {{.GAME}}
168167
- task: offline-test-file
169-
type-test-jak1:
170-
cmds:
171-
- cmd: '{{.GOALCTEST_BIN_RELEASE_DIR}}/goalc-test --gtest_brief=0 --gtest_filter="*Jak1TypeConsistency*" --gtest_break_on_failure'
172168
type-test:
173169
cmds:
174-
- cmd: '{{.GOALCTEST_BIN_RELEASE_DIR}}/goalc-test --gtest_brief=0 --gtest_filter="*Jak2TypeConsistency*" --gtest_break_on_failure'
170+
- cmd: '{{.GOALCTEST_BIN_RELEASE_DIR}}/goalc-test --gtest_brief=0 --gtest_filter="*{{.TYPE_CONSISTENCY_TEST_FILTER}}*" --gtest_break_on_failure'

common/formatter/formatter.cpp

+28-6
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ void apply_formatting_config(
6767
//
6868
// Otherwise, we always default to a hang.
6969
//
70-
// NOTE - any modifications here to child elements could be superseeded later in the recursion
71-
// in order to maintain your sanity, only modify things here that _arent_ touched by default
70+
// NOTE - any modifications here to child elements could be superseeded later in the recursion!
71+
// In order to maintain your sanity, only modify things here that _arent_ touched by default
7272
// configurations. These are explicitly prepended with `parent_mutable_`
7373
if (!predefined_config) {
7474
if (curr_node.metadata.is_top_level) {
@@ -104,6 +104,8 @@ void apply_formatting_config(
104104
}
105105
// If we are hanging, lets determine the indentation width since it is based on the form itself
106106
if (curr_node.formatting_config.hang_forms) {
107+
// TODO - this isn't being calculated for a pre-defined config
108+
// TODO - another idea is to do this during consolidation
107109
curr_node.formatting_config.indentation_width = hang_indentation_width(curr_node);
108110
}
109111
// iterate through the refs
@@ -123,6 +125,7 @@ void apply_formatting_config(
123125
}
124126
}
125127

128+
// TODO - this doesn't account for paren's width contribution!
126129
int get_total_form_inlined_width(const FormatterTreeNode& curr_node) {
127130
if (curr_node.token) {
128131
return curr_node.token->length();
@@ -191,17 +194,20 @@ bool can_node_be_inlined(const FormatterTreeNode& curr_node, int cursor_pos) {
191194
}
192195

193196
std::vector<std::string> apply_formatting(const FormatterTreeNode& curr_node,
194-
std::vector<std::string> output = {},
197+
std::vector<std::string> /*output*/ = {},
195198
int cursor_pos = 0) {
196199
using namespace formatter_rules;
197200
if (!curr_node.token && curr_node.refs.empty()) {
198201
// special case to handle an empty list
202+
if (curr_node.node_prefix) {
203+
return {fmt::format("{}()", curr_node.node_prefix.value())};
204+
}
199205
return {"()"};
200206
}
201207

202208
// If its a token, just print the token and move on
203209
if (curr_node.token) {
204-
return {curr_node.token.value()};
210+
return {curr_node.token_str()};
205211
}
206212

207213
bool inline_form = can_node_be_inlined(curr_node, cursor_pos);
@@ -220,13 +226,19 @@ std::vector<std::string> apply_formatting(const FormatterTreeNode& curr_node,
220226
// Add new line entry
221227
if (ref.token) {
222228
// Cleanup block-comments
223-
std::string val = ref.token.value();
229+
std::string val = ref.token_str();
224230
if (ref.metadata.node_type == "block_comment") {
225231
// TODO - change this sanitization to return a list of lines instead of a single new-lined
226232
// line
227-
val = comments::format_block_comment(ref.token.value());
233+
val = comments::format_block_comment(ref.token_str());
228234
}
229235
form_lines.push_back(val);
236+
if (!curr_node.metadata.is_top_level && i == curr_node.refs.size() - 1 &&
237+
(ref.metadata.is_comment)) {
238+
// if there's an inline comment at the end of a form, we have to force the paren to the next
239+
// line and do a new-line paren this is ugly, but we have no choice!
240+
form_lines.push_back("");
241+
}
230242
} else {
231243
// If it's not a token, we have to recursively build up the form
232244
// TODO - add the cursor_pos here
@@ -250,6 +262,9 @@ std::vector<std::string> apply_formatting(const FormatterTreeNode& curr_node,
250262
if ((next_ref.metadata.node_type == "comment" && next_ref.metadata.is_inline) ||
251263
(curr_node.formatting_config.has_constant_pairs &&
252264
constant_pairs::is_element_second_in_constant_pair(curr_node, next_ref, i + 1))) {
265+
// TODO
266+
// has issues with not consolidating first lines, this should probably just be moved to
267+
// outside this loop for simplicity, do it later
253268
if (next_ref.token) {
254269
form_lines.at(form_lines.size() - 1) += fmt::format(" {}", next_ref.token.value());
255270
i++;
@@ -260,6 +275,10 @@ std::vector<std::string> apply_formatting(const FormatterTreeNode& curr_node,
260275
}
261276
i++;
262277
}
278+
if (!curr_node.metadata.is_top_level && next_ref.metadata.node_type == "comment" &&
279+
(i + 1) == (int)curr_node.refs.size()) {
280+
form_lines.push_back("");
281+
}
263282
}
264283
}
265284
// If we are at the top level, potential separate with a new line
@@ -288,6 +307,9 @@ std::vector<std::string> apply_formatting(const FormatterTreeNode& curr_node,
288307
// Apply necessary indentation to each line and add parens
289308
if (!curr_node.metadata.is_top_level) {
290309
std::string form_surround_start = "(";
310+
if (curr_node.node_prefix) {
311+
form_surround_start = fmt::format("{}(", curr_node.node_prefix.value());
312+
}
291313
std::string form_surround_end = ")";
292314
form_lines[0] = fmt::format("{}{}", form_surround_start, form_lines[0]);
293315
form_lines[form_lines.size() - 1] =

common/formatter/formatter_tree.cpp

+35-9
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,24 @@ FormatterTree::FormatterTree(const std::string& source, const TSNode& root_node)
7878
construct_formatter_tree_recursive(source, root_node, root);
7979
}
8080

81+
const std::unordered_map<std::string, std::vector<std::string>> node_type_ignorable_contents = {
82+
{"list_lit", {"(", ")"}},
83+
{"quoting_lit", {"'"}},
84+
{"unquoting_lit", {","}},
85+
{"quasi_quoting_lit", {"`"}}};
86+
8187
// TODO make an imperative version eventually
8288
void FormatterTree::construct_formatter_tree_recursive(const std::string& source,
8389
TSNode curr_node,
84-
FormatterTreeNode& tree_node) {
90+
FormatterTreeNode& tree_node,
91+
std::optional<std::string> node_prefix) {
8592
if (ts_node_child_count(curr_node) == 0) {
8693
tree_node.refs.push_back(FormatterTreeNode(source, curr_node));
8794
return;
8895
}
8996
const std::string curr_node_type = ts_node_type(curr_node);
9097
FormatterTreeNode list_node;
98+
std::optional<std::string> next_node_prefix;
9199
if (curr_node_type == "list_lit") {
92100
list_node = FormatterTreeNode();
93101
} else if (curr_node_type == "str_lit") {
@@ -97,22 +105,40 @@ void FormatterTree::construct_formatter_tree_recursive(const std::string& source
97105
tree_node.refs.push_back(FormatterTreeNode(source, curr_node));
98106
return;
99107
} else if (curr_node_type == "quoting_lit") {
100-
// same story for quoted symbols
101-
// TODO - expect to have to add more here
102-
tree_node.refs.push_back(FormatterTreeNode(source, curr_node));
103-
return;
108+
next_node_prefix = "'";
109+
} else if (curr_node_type == "unquoting_lit") {
110+
next_node_prefix = ",";
111+
} else if (curr_node_type == "quasi_quoting_lit") {
112+
next_node_prefix = "`";
113+
}
114+
std::vector<std::string> skippable_nodes = {};
115+
if (node_type_ignorable_contents.find(curr_node_type) != node_type_ignorable_contents.end()) {
116+
skippable_nodes = node_type_ignorable_contents.at(curr_node_type);
104117
}
105118
for (size_t i = 0; i < ts_node_child_count(curr_node); i++) {
106119
const auto child_node = ts_node_child(curr_node, i);
107-
// We skip parens
108120
const auto contents = get_source_code(source, child_node);
109-
if (contents == "(" || contents == ")") {
121+
bool skip_node = false;
122+
for (const auto& skippable_content : skippable_nodes) {
123+
if (skippable_content == contents) {
124+
skip_node = true;
125+
break;
126+
}
127+
}
128+
if (skip_node) {
110129
continue;
111130
}
112131
if (curr_node_type == "list_lit") {
113-
construct_formatter_tree_recursive(source, child_node, list_node);
132+
construct_formatter_tree_recursive(source, child_node, list_node, next_node_prefix);
133+
if (node_prefix) {
134+
list_node.node_prefix = node_prefix;
135+
}
114136
} else {
115-
construct_formatter_tree_recursive(source, child_node, tree_node);
137+
construct_formatter_tree_recursive(source, child_node, tree_node, next_node_prefix);
138+
// TODO - im not sure if this is correct
139+
if (node_prefix && !tree_node.refs.empty()) {
140+
tree_node.refs.at(tree_node.refs.size() - 1).node_prefix = node_prefix;
141+
}
116142
}
117143
}
118144
if (curr_node_type == "list_lit") {

common/formatter/formatter_tree.h

+16-4
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@
1818
// we really care about is:
1919
// - getting all the text tokens for the source code
2020
// - having them in a proper, nested format
21-
// The treesitter format is complicated and highly nested, leading to some very hard to understand
22-
// code. So my solution is a 2-pass format.
21+
//
22+
// TLDR - The treesitter format is complicated and highly nested, leading to some very hard to
23+
// understand code. So my solution is atleast a 2-pass format.
2324
//
2425
// Pass 1 - convert the AST into a simplified FormatterTree
2526
// Pass 2 - use the simplified tree to output the final code
@@ -37,8 +38,9 @@ class FormatterTreeNode {
3738
std::vector<FormatterTreeNode> refs;
3839
Metadata metadata;
3940
// The token is optional because list nodes do not contain a token, they just contain a bunch of
40-
// eventually token node refs
41+
// eventually-containing token node refs
4142
std::optional<std::string> token;
43+
std::optional<std::string> node_prefix;
4244

4345
formatter_rules::config::FormFormattingConfig formatting_config;
4446

@@ -47,6 +49,15 @@ class FormatterTreeNode {
4749
FormatterTreeNode(const Metadata& _metadata) : metadata(_metadata){};
4850

4951
bool is_list() const { return !token.has_value(); }
52+
std::string token_str() const {
53+
if (node_prefix && token) {
54+
return node_prefix.value() + token.value();
55+
}
56+
if (token) {
57+
return token.value();
58+
}
59+
return "";
60+
}
5061
};
5162

5263
// A FormatterTree has a very simple and crude tree structure where:
@@ -62,5 +73,6 @@ class FormatterTree {
6273
private:
6374
void construct_formatter_tree_recursive(const std::string& source,
6475
TSNode curr_node,
65-
FormatterTreeNode& tree_node);
76+
FormatterTreeNode& tree_node,
77+
std::optional<std::string> node_prefix = {});
6678
};

0 commit comments

Comments
 (0)