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

Add info re: comment handling to the Plugin API documentation #4290

Open
suchipi opened this issue Apr 9, 2018 · 11 comments
Open

Add info re: comment handling to the Plugin API documentation #4290

suchipi opened this issue Apr 9, 2018 · 11 comments
Labels
area:comments Issues with how Prettier prints comments help wanted We're a small group who can't get to every issue promptly. We’d appreciate help fixing this issue! type:docs Issues about adding or improving documentation

Comments

@suchipi
Copy link
Member

suchipi commented Apr 9, 2018

We should document that you can add handleComments, getCommentChildNodes, canAttachComment, and printComment to your printer, what they're for, how prettier will use them, and how to use addLeadingComment, addTrailingComment, and addDanglingComment. As part of this, we should explain what it means for a comment to be "leading", "trailing", "dangling", "ownLine", "endOfLine", and "remaining".

cc @mgrip

@suchipi suchipi added help wanted We're a small group who can't get to every issue promptly. We’d appreciate help fixing this issue! type:docs Issues about adding or improving documentation labels Apr 9, 2018
@yxliang01
Copy link

yxliang01 commented Sep 24, 2019

@suchipi The documentation is much needed to make plugin development for new developer easier. Hope it can be added soon. (I'm one who doesn't know but need to know what handleComments is and then found this issue)

@thorn0 thorn0 mentioned this issue May 24, 2020
1 task
@siefkenj
Copy link
Contributor

If someone can explain some of these functions to me, I can take a stab at writing documentation. I'm currently trying to figure it out myself...

@thorn0
Copy link
Member

thorn0 commented May 24, 2020

@siefkenj Unfortunately, that's a lot to investigate and explain. I might be able to help you if you ask more specific bite-sized questions.

@siefkenj
Copy link
Contributor

siefkenj commented May 24, 2020

Okay, here's what I understand so far:

ownLineComment is a comment that is on a line by itself. endOfLineComment is a comment at the end of a line of code. What is a remaining comment? And what is a dangling comment?

Also, I don't understand the purpose of willPrintOwnComment. Whether it returns true or false, the printComment function is still called. What exactly does it buy you? Is the data returned by printComment inserted somewhere else if willPrintOwnComment -> true?

It seems the general strategy for printing comments is to find which AST node the comment is contained in, call canAttachComment, and if it returns true, start calling handleComments.ownLine/endOfLine/remaining based on properties of the raw character stream. Each of those functions either "attaches" the comment to the AST with some properties set and returns true or returns false and some default behavior is used.

Other Questions

  • I also see a getCommentChildNodes referenced in printer-estree.js. Does a comment have child nodes? Or is this used for something else?
  • There seems to be a lot of comment functions that can be passed. Would it make sense to collect these into a sub-object that is exported by the plugin?

@thorn0
Copy link
Member

thorn0 commented May 24, 2020

Attaching comments and printing them are separate processes. I've mostly dealt with the former, so I'm going to answer only about that now.

ownLineComment is a comment that is on a line by itself. endOfLineComment is a comment at the end of a line of code. What is a remaining comment? And what is a dangling comment?

If a comment isn't "own-line" and isn't "end-of-line" either, then it's categorized as "remaining". Each category of the three has its own rules for attaching to AST nodes. The rules can be extended by callbacks optionally provided by the printer (handleComments.*). If a callback returns true, it means that the comment has been handled (attached to a node) by the callback. If a callback returns false, default rules are used. At this point there is at least 1 and at most 3 nodes to choose from ("preceding", "following", and "enclosing"), so the goal is to choose one of the nodes and to decide whether the comment is "leading", "trailing", or "dangling" in relation to the chosen node. "Dangling" stands for "neither leading nor trailing". An example of a dangling comment in a BlockStatement node: if (a) { /* comment */ }. Comments are attached by calling one of three functions: addLeadingComment, addTrailingComment, addDanglingComment.

A printer can provide other callbacks to the comment-attaching logic:

  • canAttachComment and getCommentChildNodes participate in the compilation of lists of nodes to which comments can be attached. canAttachComment is a simple filter. A node is added to the list only if this function returns a truthy value for it. getCommentChildNodes allows to customize how the AST is traversed in the process of the building of the list (see [Plugins] Allow custom getCommentChildNodes #3639).
  • getGapRegex. When a "remaining" comment hasn't been handled by the handleComments.remaining printer callback and has both the preceding and the following nodes, Prettier needs to choose from the two somehow. For that it uses an algorithm called tie breaking. The callback allows to adjust this algorithm for specific node types.

@siefkenj
Copy link
Contributor

Should util.addTrailingComment and friends be used by plugins, or are these considered internal functions to be avoided?

@thorn0
Copy link
Member

thorn0 commented May 25, 2020

They totally should.

@siefkenj
Copy link
Contributor

Why does the current plugin documentation say A util module from Prettier core is considered a private API and is not meant to be consumed by plugins.? Is that referring to a different util?

@thorn0
Copy link
Member

thorn0 commented May 25, 2020

Yes, it's not about prettier.util. It's about prettier/common/util and is probably addressed to Prettier contributors, not to plugin developers.

@joeried
Copy link

joeried commented Aug 10, 2020

The work in PR #8407 was already a great help to enable the integration of comments. Thanks a lot for these additions!

Currently I get the error Error: Comment "Comment" was not printed. Please report this error!.
Primarily this happens with dangling comments. I understand that dangling comments probably need separate handling, as their position is not completely clear.
I've already tried to handle all dangling comments in the generic print function, but I have the impression that this is not the way it was intended.

Are the handleComments.* functions designed for this? Is there a way to handle only dangling comments and let prettier attach all other comments?
What is the best way to handle these comments?
What is the best way to debug the mentioned error?

@thorn0 thorn0 added the area:comments Issues with how Prettier prints comments label Jan 25, 2021
@nene
Copy link
Contributor

nene commented Jan 15, 2023

The documentation doesn't really make it clear which methods one should implement to make use of the automatic comment handling.

Reading the docs, I got the impression that I don't have to implement any and it will all work automatically. After lots of trial and error and reading of Prettier source code I've finally figured out that one needs to implement at least two methods:

  • printComment()
  • canAttachComment()

The documentation also only gives you a vague info as to what sort of data the comments field in AST root node should contain. Specifically the docs say:

Prettier assumes that comments stores an array of comment nodes.

What I have figured out about these comment nodes:

  • They have to contain location information (accessed by locStart() and locEnd() methods).
  • They probably should contain the comment text inside value field. Otherwise when the comment doesn't get printed you'll get the error message TypeError: Cannot read properties of undefined (reading 'trim'). Not sure if this is intentional or just a bug in implementation of the Error: Comment "Comment" was not printed. error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:comments Issues with how Prettier prints comments help wanted We're a small group who can't get to every issue promptly. We’d appreciate help fixing this issue! type:docs Issues about adding or improving documentation
Projects
None yet
Development

No branches or pull requests

6 participants