GDQuest / gdscript-docs-maker

Create documentation and class references from your Godot GDScript code
MIT License
263 stars 26 forks source link

Using GDScript language server to dump script symbols #12

Closed Geequlim closed 4 years ago

Geequlim commented 4 years ago

The functionality of parsing GDScript symbols with documentations with javadoc liked behavior is already implemented by the GDScript language server.

I think you don't need to make another parser as you can dump all the informations to json with an editor plugin. The lsp using the original gdscript parser so it should be the best choice to do this kind of work.

To dump the script symbols to json you just need to call this api in your editor plugin

https://github.com/godotengine/godot/blob/096bf873bc44a942ba7d5c4e52bf089fda6fdd6b/modules/gdscript/language_server/gdscript_workspace.cpp#L46

Geequlim commented 4 years ago

The dumped json should contains constants,functions,signals and all symbols defined in script files with javadoc liked documents and signatures. We can make a tool to render the generated json to webpage like read the doc

NathanLovato commented 4 years ago

Thanks! But this function doesn't seem to be exposed in the editor (just rebuilt Godot).

Would you have a brief usage example? I looked for a feature like this in the editor, couldn't find one before making this tool.

Geequlim commented 4 years ago

var symbols = Engine.get_singleton('GDScriptLanguageProtocol').get_workspace().generate_script_api('res://main.gd')

NathanLovato commented 4 years ago

Ah, that's why I couldn't find it! Thank you :)

NathanLovato commented 4 years ago

Got it working! Is there a way to collect the description key from the source code directly? Without that I still have to parse every file a second time from python to collect docstrings, and might as well do it all from Python (removes the need for running Godot + gdscript as a dependency)

{
    "constants": [],
    "description": "",
    "extends_class": ["GSTGroupBehavior"],
    "extends_file": "",
    "icon": "",
...
}
Geequlim commented 4 years ago

What is the description key ?

Nathan Lovato notifications@github.com于2020年1月28日 周二23:21写道:

Got it working! Is there a way to collect the description key from the source code directly? Without that I still have to parse every file a second time from python to collect docstrings.

{ "constants": [], "description": "", "extends_class": ["GSTGroupBehavior"], "extends_file": "", "icon": "",... }

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/GDQuest/gdscript-docs-maker/issues/12?email_source=notifications&email_token=ABVEKTF3ZBSUEB55OELXDUDRABEPTA5CNFSM4KMMFX6KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKDV6CA#issuecomment-579297032, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABVEKTHL6OIC4ASA5PVG5OLRABEPTANCNFSM4KMMFX6A .

Razoric480 commented 4 years ago

It should be the docstring for the class itself. It works for functions and properties, but this code:

if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(p_class->line))) {
    class_api["signature"] = symbol->detail;
    class_api["description"] = symbol->documentation;
}

seems to be returning null in dump_class_api, which means the class itself doesn't have documentation.

Geequlim commented 4 years ago

What is the script content look like?

Francois Belair notifications@github.com于2020年1月29日 周三00:30写道:

It should be the docstring for the class itself. It works for functions and properties, but this code:

get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(p_class->line))

seems to be returning null in dump_class_api, which means the class doesn't have documentation.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/GDQuest/gdscript-docs-maker/issues/12?email_source=notifications&email_token=ABVEKTB7GTWRWRKBSNWXV7DRABMSHA5CNFSM4KMMFX6KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKD7T3I#issuecomment-579336685, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABVEKTHQHSDBQ4JDCREJKJTRABMSHANCNFSM4KMMFX6A .

Razoric480 commented 4 years ago
extends Reference
class_name GSTPath
# Represents a path made up of Vector3 waypoints, split into path segments for use by path
# following behaviors.

# Whether the path is a loop, or has its start and end disconnected and open ended
var open: bool
# The length of the full path
var length: float

# Creates a path with the provided waypoints
func create_path(waypoints: Array) -> void:
    pass

truncated. the parser returns the docstring for the function and the members, but not the class.

I've tried putting the string in a variety of places - in line with the class name, with the extends, at the end, but it's never detected. My only guess is that the class' line number is -1 or something else to indicate "does not count", which means it cannot return a proper index. That would make this a bug in the parser.

I've not debugged it, though, so that's only a guess.

NathanLovato commented 4 years ago

Ah that's why I wasn't getting any description for the scripts I tested! They only have a class docstring.

Geequlim commented 4 years ago

You'd better move the documentation to the top.

Geequlim commented 4 years ago

Here is an example https://github.com/GodotExplorer/gdutils/blob/master/utils/RandomPool.gd

Razoric480 commented 4 years ago

No change - Dictionary.description is still empty.

# Represents a path made up of Vector3 waypoints, split into path segments for use by path
# following behaviors.

extends Reference
class_name GSTPath

#...
Razoric480 commented 4 years ago

LINE_NUMBER_TO_INDEX is a macro that takes the line number and -1s it.

The ClassNode's line variable is never modified, and so its default is 0 as an integer. So it tries to pass in -1 as an index to get_symbol_defined_at_line, which should return the class symbol, but clearly does not.

NathanLovato commented 4 years ago

I also have one or more GDScript files that crash the parser. We're moving to a new apartment in a few hours so I'll have to debug later, but I'll open a bug on the godot repo in a while.

NathanLovato commented 4 years ago

@Razoric480 is the class docstring bug something you could fix? If so, you can do it as part of your work for GDQuest, and open an issue and a PR on the godotengine repo

Razoric480 commented 4 years ago

I'll give it a poke, sure.

Geequlim commented 4 years ago

By the way the docstring can be markdown or bbcode we are using in the class documentation xml files for C++ classes

Razoric480 commented 4 years ago

Okay, so apparently, changing a script file does not recache its contents for the GDScript server until you close and reload the project, at least not with class_name loaded files.

Turns out, that having the docstring as the first line of a GDScript does, in fact, get put into the description key of the output.

"name": "GSTPath",
  "path": "res://src/GSTPath.gd",
  "extends_class": [
    "Reference"
  ],
  "extends_file": "",
  "icon": "",
  "signature": "class GSTPath",
  "description": " Represents a path made up of Vector3 waypoints, split into path segments for use by path\n following behaviors.\n",
# Represents a path made up of Vector3 waypoints, split into path segments for use by path
# following behaviors.
extends Reference
class_name GSTPath

The question then becomes how to make it an easy to use parser. Could be a TSCN with a simple Node with some exported options (what files to document, output to what file, export template, etc) and a way to trigger the export function which you can import into your project. Might make it a bit user friendlier that way than a command line argument.

Or an EditorPlugin.

Since it requires a tool script to get the language protocol, we can't just use the -s argument and run it as a command line script.

NathanLovato commented 4 years ago

@Razoric480 I already made an EditorScript, with the instructions: https://github.com/GDQuest/gdscript-docs-maker/tree/master/godot-scripts

NathanLovato commented 4 years ago

For now it's fine by me to generate the docs that way, if we happen to do it so much we could use a plugin, it won't take long to add some bit of interface for it and turn it into a package.

Razoric480 commented 4 years ago

Noted. I did post an issue and PR for a related crashing bug, though, while testing it.