Skip to content

Commit 113067f

Browse files
Update styleguide with cypherfmt rules and recommend its usage (#1289)
## Description Hey, docs team! For the past few months, as a master's thesis project, @simonthuresson and I have been working on a formatter for Cypher. In short, the formatter formats a Cypher query so that it follows the styleguide recommendations. During development, we found that the styleguide is quite far from comprehensive, and also some of the cypher snippets in the docs disagree with it as well. Filling out the missing pieces and addressing any ambiguity became a fairly large part of our project, and we wrote extensively about how we did so in our thesis, which you can find here: - [An Evaluation of Approaches to Code Formatting](https://lup.lub.lu.se/luur/download?func=downloadFile&recordOId=9188816&fileOId=9188817) In short, we did a survey on styling preferences, and talked to Cypher users to try and figure out what the most preferred way of writing Cypher was. We then took those learnings and implemented it in our formatter so that it could automatically enforce the rules. This PR is a draft of how we think the styleguide should be updated in accordance with the new rules. I did not put a lot of time into the wording and structure of the recommendations, as I would prefer to leave that to the professionals (you), but I provided some examples which hopefully illustrate the ideas well. If you want more detailed context on the rules, refer to the thesis (chapter 4 specifically). I also included a recommendation at the start of the style guide that users should use our formatter, as manual formatting is generally not a great idea. #### Note I included a link to the language support npm package that I claim provides a command-line tool. This is not actually live yet, but will be soon: neo4j/cypher-language-support#518 ## Try it out If you want to get a better feel for how the formatter works and how it applies the rules, you can try it out in: - Query in the Aura console (the ... menu -> format query) - [The Cypher Language Support CodeMirror playground](https://neo4j.github.io/cypher-language-support/) - [VS Code](https://marketplace.visualstudio.com/items?itemName=neo4j-extensions.neo4j-for-vscode) I would also recommend running any Cypher queries you add to the docs through the formatter first, to ensure that the styling is always consistent across all documentation. ## Note This is my last day at Neo4j, so I probably will not be able to respond to any comments on this PR. If you have questions, direct them at the language support team (#team-cypher-language-support), they have reviewed every line of code in the formatter, and are well aware of how it works. Feel free to completely change the wording I have used, this is just a first draft that I wanted to get in before leaving. --------- Co-authored-by: Jens Pryce-Åklundh <[email protected]>
1 parent 9353892 commit 113067f

File tree

1 file changed

+123
-1
lines changed

1 file changed

+123
-1
lines changed

modules/ROOT/pages/styleguide.adoc

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ The purpose of the Cypher styleguide is to make queries as easy to read as possi
99

1010
For rules and recommendations for naming of labels, relationship types and properties, please see the xref::syntax/naming.adoc[Naming rules and recommendations].
1111

12+
The best way to make sure your queries follow the styling rules is to use `cypherfmt`, the official Cypher formatter.
13+
It is available as part of the https://marketplace.visualstudio.com/items?itemName=neo4j-extensions.neo4j-for-vscode[Neo4j VS Code Extension], and as a command line tool through the https://www.npmjs.com/package/@neo4j-cypher/language-support[Neo4j Cypher Language Support npm package].
14+
1215
[[cypher-styleguide-general-recommendations]]
1316
== General recommendations
1417

@@ -18,7 +21,6 @@ For rules and recommendations for naming of labels, relationship types and prope
1821
For example: `toString()`.
1922
* If you are storing Cypher statements in a separate file, use the file extension `.cypher`.
2023

21-
2224
[[cypher-styleguide-indentation-and-line-breaks]]
2325
== Indentation and line breaks
2426

@@ -115,6 +117,126 @@ WHERE EXISTS { (a)-->(b:B) }
115117
RETURN a.prop
116118
----
117119

120+
* Limit line length to 80 characters if possible.
121+
Line breaks should be applied starting from the outermost group, with each nested group breaking until either the line fits or no more line breaks can be inserted.
122+
Add two spaces of indentation for each nested broken group.
123+
124+
.Bad
125+
[source, cypher]
126+
----
127+
MATCH (n)
128+
WHERE n.prop <> 'a' AND n.prop <> 'b' AND n.prop <> 'c' AND n.prop <> 'd' AND n.prop <> 'e'
129+
RETURN n
130+
----
131+
132+
.Good
133+
[source, cypher]
134+
----
135+
MATCH (n)
136+
WHERE
137+
n.prop <> 'a' AND
138+
n.prop <> 'b' AND
139+
n.prop <> 'c' AND
140+
n.prop <> 'd' AND
141+
n.prop <> 'e'
142+
RETURN n
143+
----
144+
145+
* Start `ORDER BY` and `LIMIT` clauses on new lines.
146+
147+
.Bad
148+
[source, cypher]
149+
----
150+
MATCH (n)
151+
RETURN 5 ORDER BY n.prop LIMIT 10
152+
----
153+
154+
.Good
155+
[source, cypher]
156+
----
157+
MATCH (n)
158+
RETURN 5
159+
ORDER BY n.prop
160+
LIMIT 10
161+
----
162+
163+
* A group containing a `CASE` expression should always break, and each `WHEN`, `ELSE`, and `END` should be put on a new line.
164+
Additionally, `WHEN` and `ELSE` should add two spaces of indentation.
165+
166+
.Bad
167+
[source, cypher]
168+
----
169+
MATCH (n:Person {name: 'Alice'})
170+
RETURN CASE WHEN n.age >= 18 THEN 'Adult' ELSE 'Minor' END AS ageGroup
171+
----
172+
173+
.Good
174+
[source, cypher]
175+
----
176+
MATCH (n:Person {name: 'Alice'})
177+
RETURN
178+
CASE
179+
WHEN n.age >= 18 THEN 'Adult'
180+
ELSE 'Minor'
181+
END AS ageGroup
182+
----
183+
184+
* When a line ends with a list or map literal that does not fit within the maximum line width, place the opening bracket or brace on the same line as the clause that introduces it.
185+
Start each element of the literal on a new line, indented two spaces further than the line containing the opening bracket or brace.
186+
Close the literal at the original indentation level.
187+
188+
.Bad
189+
[source, cypher]
190+
----
191+
RETURN
192+
[
193+
"Alice",
194+
"Bob",
195+
"Charlie",
196+
"David",
197+
"Eve",
198+
"Frank",
199+
"Grace",
200+
"Heidi",
201+
"Ivan",
202+
"Judy"
203+
]
204+
----
205+
206+
.Good
207+
[source, cypher]
208+
----
209+
RETURN [
210+
"Alice",
211+
"Bob",
212+
"Charlie",
213+
"David",
214+
"Eve",
215+
"Frank",
216+
"Grace",
217+
"Heidi",
218+
"Ivan",
219+
"Judy"
220+
]
221+
----
222+
223+
* A single blank line may be used to separate clauses, queries or comments.
224+
225+
.Good
226+
[source, cypher]
227+
----
228+
MATCH (n)-[r]->(m)
229+
RETURN n, r, m
230+
----
231+
232+
.Also good
233+
[source, cypher]
234+
----
235+
MATCH (n)-[r]->(m)
236+
237+
RETURN n, r, m
238+
----
239+
118240
[[cypher-styleguide-casing]]
119241
== Casing
120242

0 commit comments

Comments
 (0)