Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 7 additions & 11 deletions internal/ls/hover.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,21 +68,21 @@ func (l *LanguageService) getQuickInfoAndDocumentationForSymbol(c *checker.Check
if quickInfo == "" {
return "", ""
}
return quickInfo, l.getDocumentationFromDeclaration(c, declaration, contentFormat)
return quickInfo, l.getDocumentationFromDeclaration(c, declaration, contentFormat, false /*commentOnly*/)
}

func (l *LanguageService) getDocumentationFromDeclaration(c *checker.Checker, declaration *ast.Node, contentFormat lsproto.MarkupKind) string {
func (l *LanguageService) getDocumentationFromDeclaration(c *checker.Checker, declaration *ast.Node, contentFormat lsproto.MarkupKind, commentOnly bool) string {
if declaration == nil {
return ""
}
isMarkdown := contentFormat == lsproto.MarkupKindMarkdown
var b strings.Builder
if jsdoc := getJSDocOrTag(c, declaration); jsdoc != nil && !containsTypedefTag(jsdoc) {
if jsdoc := getJSDocOrTag(c, declaration); jsdoc != nil && !(declaration.Flags&ast.NodeFlagsReparsed == 0 && containsTypedefTag(jsdoc)) {
l.writeComments(&b, c, jsdoc.Comments(), isMarkdown)
if jsdoc.Kind == ast.KindJSDoc {
if jsdoc.Kind == ast.KindJSDoc && !commentOnly {
if tags := jsdoc.AsJSDoc().Tags; tags != nil {
for _, tag := range tags.Nodes {
if tag.Kind == ast.KindJSDocTypeTag {
if tag.Kind == ast.KindJSDocTypeTag || tag.Kind == ast.KindJSDocTypedefTag || tag.Kind == ast.KindJSDocCallbackTag {
continue
}
b.WriteString("\n\n")
Expand Down Expand Up @@ -142,7 +142,7 @@ func (l *LanguageService) getDocumentationFromDeclaration(c *checker.Checker, de
}
} else if len(comments) != 0 {
b.WriteString(" ")
if !commentHasPrefix(comments, "-") {
if comments[0].Kind != ast.KindJSDocText || !strings.HasPrefix(comments[0].Text(), "-") {
b.WriteString("— ")
}
l.writeComments(&b, c, comments, isMarkdown)
Expand Down Expand Up @@ -307,7 +307,7 @@ func getQuickInfoAndDeclarationAtLocation(c *checker.Checker, symbol *ast.Symbol
b.WriteString(" = ")
b.WriteString(c.TypeToStringEx(c.GetDeclaredTypeOfSymbol(symbol), container, typeFormatFlags|checker.TypeFormatFlagsInTypeAlias))
}
declaration = core.Find(symbol.Declarations, ast.IsTypeAliasDeclaration)
declaration = core.Find(symbol.Declarations, ast.IsTypeOrJSTypeAliasDeclaration)
default:
b.WriteString(c.TypeToStringEx(c.GetTypeOfSymbol(symbol), container, typeFormatFlags))
}
Expand Down Expand Up @@ -442,10 +442,6 @@ func containsTypedefTag(jsdoc *ast.Node) bool {
return false
}

func commentHasPrefix(comments []*ast.Node, prefix string) bool {
return comments[0].Kind == ast.KindJSDocText && strings.HasPrefix(comments[0].Text(), prefix)
}

func getJSDoc(node *ast.Node) *ast.Node {
return core.LastOrNil(node.JSDoc(nil))
}
Expand Down
32 changes: 22 additions & 10 deletions internal/ls/signaturehelp.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,17 +418,17 @@ func (l *LanguageService) computeActiveParameter(sig signatureInformation, argum
func (l *LanguageService) getSignatureHelpItem(candidate *checker.Signature, isTypeParameterList bool, callTargetSymbol string, enclosingDeclaration *ast.Node, sourceFile *ast.SourceFile, c *checker.Checker, docFormat lsproto.MarkupKind) []signatureInformation {
var infos []*signatureHelpItemInfo
if isTypeParameterList {
infos = itemInfoForTypeParameters(candidate, c, enclosingDeclaration, sourceFile)
infos = l.itemInfoForTypeParameters(candidate, c, enclosingDeclaration, sourceFile, docFormat)
} else {
infos = itemInfoForParameters(candidate, c, enclosingDeclaration, sourceFile)
infos = l.itemInfoForParameters(candidate, c, enclosingDeclaration, sourceFile, docFormat)
}

suffixDisplayParts := returnTypeToDisplayParts(candidate, c)

// Generate documentation from the signature's declaration
var documentation *string
if declaration := candidate.Declaration(); declaration != nil {
doc := l.getDocumentationFromDeclaration(c, declaration, docFormat)
doc := l.getDocumentationFromDeclaration(c, declaration, docFormat, true /*commentOnly*/)
if doc != "" {
documentation = &doc
}
Expand Down Expand Up @@ -462,7 +462,7 @@ func returnTypeToDisplayParts(candidateSignature *checker.Signature, c *checker.
return returnType.String()
}

func itemInfoForTypeParameters(candidateSignature *checker.Signature, c *checker.Checker, enclosingDeclaration *ast.Node, sourceFile *ast.SourceFile) []*signatureHelpItemInfo {
func (l *LanguageService) itemInfoForTypeParameters(candidateSignature *checker.Signature, c *checker.Checker, enclosingDeclaration *ast.Node, sourceFile *ast.SourceFile, docFormat lsproto.MarkupKind) []*signatureHelpItemInfo {
printer := printer.NewPrinter(printer.PrinterOptions{NewLine: core.NewLineKindLF}, printer.PrintHandlers{}, nil)

var typeParameters []*checker.Type
Expand All @@ -478,7 +478,7 @@ func itemInfoForTypeParameters(candidateSignature *checker.Signature, c *checker

thisParameter := []signatureHelpParameter{}
if candidateSignature.ThisParameter() != nil {
thisParameter = []signatureHelpParameter{createSignatureHelpParameterForParameter(candidateSignature.ThisParameter(), enclosingDeclaration, printer, sourceFile, c)}
thisParameter = []signatureHelpParameter{l.createSignatureHelpParameterForParameter(candidateSignature.ThisParameter(), enclosingDeclaration, printer, sourceFile, c, docFormat)}
}

// Creating type parameter display label
Expand All @@ -504,7 +504,7 @@ func itemInfoForTypeParameters(candidateSignature *checker.Signature, c *checker
displayParameters.WriteString(displayParts.String())
parameters := thisParameter
for j, param := range parameterList {
parameter := createSignatureHelpParameterForParameter(param, enclosingDeclaration, printer, sourceFile, c)
parameter := l.createSignatureHelpParameterForParameter(param, enclosingDeclaration, printer, sourceFile, c, docFormat)
parameters = append(parameters, parameter)
if j > 0 {
displayParameters.WriteString(", ")
Expand All @@ -522,7 +522,7 @@ func itemInfoForTypeParameters(candidateSignature *checker.Signature, c *checker
return result
}

func itemInfoForParameters(candidateSignature *checker.Signature, c *checker.Checker, enclosingDeclaratipn *ast.Node, sourceFile *ast.SourceFile) []*signatureHelpItemInfo {
func (l *LanguageService) itemInfoForParameters(candidateSignature *checker.Signature, c *checker.Checker, enclosingDeclaratipn *ast.Node, sourceFile *ast.SourceFile, docFormat lsproto.MarkupKind) []*signatureHelpItemInfo {
printer := printer.NewPrinter(printer.PrinterOptions{NewLine: core.NewLineKindLF}, printer.PrintHandlers{}, nil)

signatureHelpTypeParameters := make([]signatureHelpParameter, len(candidateSignature.TypeParameters()))
Expand Down Expand Up @@ -564,7 +564,7 @@ func itemInfoForParameters(candidateSignature *checker.Signature, c *checker.Che
var displayParameters strings.Builder
displayParameters.WriteString(displayParts.String())
for j, param := range parameterList {
parameter := createSignatureHelpParameterForParameter(param, enclosingDeclaratipn, printer, sourceFile, c)
parameter := l.createSignatureHelpParameterForParameter(param, enclosingDeclaratipn, printer, sourceFile, c, docFormat)
parameters[j] = parameter
if j > 0 {
displayParameters.WriteString(", ")
Expand All @@ -585,14 +585,26 @@ func itemInfoForParameters(candidateSignature *checker.Signature, c *checker.Che

const signatureHelpNodeBuilderFlags = nodebuilder.FlagsOmitParameterModifiers | nodebuilder.FlagsIgnoreErrors | nodebuilder.FlagsUseAliasDefinedOutsideCurrentScope

func createSignatureHelpParameterForParameter(parameter *ast.Symbol, enclosingDeclaratipn *ast.Node, p *printer.Printer, sourceFile *ast.SourceFile, c *checker.Checker) signatureHelpParameter {
func (l *LanguageService) createSignatureHelpParameterForParameter(parameter *ast.Symbol, enclosingDeclaratipn *ast.Node, p *printer.Printer, sourceFile *ast.SourceFile, c *checker.Checker, docFormat lsproto.MarkupKind) signatureHelpParameter {
display := p.Emit(checker.NewNodeBuilder(c, printer.NewEmitContext()).SymbolToParameterDeclaration(parameter, enclosingDeclaratipn, signatureHelpNodeBuilderFlags, nodebuilder.InternalFlagsNone, nil), sourceFile)
isOptional := parameter.CheckFlags&ast.CheckFlagsOptionalParameter != 0
isRest := parameter.CheckFlags&ast.CheckFlagsRestParameter != 0
var documentation *lsproto.StringOrMarkupContent
if parameter.ValueDeclaration != nil {
doc := l.getDocumentationFromDeclaration(c, parameter.ValueDeclaration, docFormat, true /*commentOnly*/)
if doc != "" {
documentation = &lsproto.StringOrMarkupContent{
MarkupContent: &lsproto.MarkupContent{
Kind: docFormat,
Value: doc,
},
}
}
}
return signatureHelpParameter{
parameterInfo: &lsproto.ParameterInformation{
Label: lsproto.StringOrTuple{String: &display},
Documentation: nil,
Documentation: documentation,
},
isRest: isRest,
isOptional: isOptional,
Expand Down
14 changes: 8 additions & 6 deletions internal/ls/symbols.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,14 @@ func (l *LanguageService) getDocumentSymbolsForChildren(ctx context.Context, nod
if ctx.Err() != nil {
return true
}
if jsdocs := node.JSDoc(file); len(jsdocs) > 0 {
for _, jsdoc := range jsdocs {
if tagList := jsdoc.AsJSDoc().Tags; tagList != nil {
for _, tag := range tagList.Nodes {
if ast.IsJSDocTypedefTag(tag) || ast.IsJSDocCallbackTag(tag) {
addSymbolForNode(tag, nil /*children*/)
if node.Flags&ast.NodeFlagsReparsed == 0 {
if jsdocs := node.JSDoc(file); len(jsdocs) > 0 {
for _, jsdoc := range jsdocs {
if tagList := jsdoc.AsJSDoc().Tags; tagList != nil {
for _, tag := range tagList.Nodes {
if ast.IsJSDocTypedefTag(tag) || ast.IsJSDocCallbackTag(tag) {
addSymbolForNode(tag, nil /*children*/)
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion internal/parser/jsdoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ loop:

func removeLeadingNewlines(comments []string) []string {
i := 0
for i < len(comments) && (comments[i] == "\n" || comments[i] == "\r") {
for i < len(comments) && strings.TrimLeft(comments[i], "\r\n") == "" {
i++
}
return comments[i:]
Expand Down
16 changes: 16 additions & 0 deletions internal/parser/reparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ func (p *Parser) reparseUnhosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Nod
}
typeAlias.AsTypeAliasDeclaration().Type = t
p.finishReparsedNode(typeAlias, tag)
p.jsdocCache[typeAlias] = []*ast.Node{jsDoc}
typeAlias.Flags |= ast.NodeFlagsHasJSDoc
p.reparseList = append(p.reparseList, typeAlias)
case ast.KindJSDocCallbackTag:
callbackTag := tag.AsJSDocCallbackTag()
Expand All @@ -94,6 +96,8 @@ func (p *Parser) reparseUnhosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Nod
typeAlias := p.factory.NewJSTypeAliasDeclaration(nil, p.factory.DeepCloneReparse(callbackTag.FullName), nil, functionType)
typeAlias.AsTypeAliasDeclaration().TypeParameters = p.gatherTypeParameters(jsDoc, tag)
p.finishReparsedNode(typeAlias, tag)
p.jsdocCache[typeAlias] = []*ast.Node{jsDoc}
typeAlias.Flags |= ast.NodeFlagsHasJSDoc
p.reparseList = append(p.reparseList, typeAlias)
case ast.KindJSDocImportTag:
importTag := tag.AsJSDocImportTag()
Expand Down Expand Up @@ -171,6 +175,7 @@ func (p *Parser) reparseJSDocSignature(jsSignature *ast.Node, fun *ast.Node, jsD
}
p.finishReparsedNode(parameter, param)
parameters = append(parameters, parameter)
p.reparseJSDocComment(parameter, param)
}
signature.FunctionLikeData().Parameters = p.newNodeList(jsSignature.AsJSDocSignature().Parameters.Loc, parameters)

Expand Down Expand Up @@ -205,17 +210,28 @@ func (p *Parser) reparseJSDocTypeLiteral(t *ast.TypeNode) *ast.Node {
}
p.finishReparsedNode(property, prop)
properties = append(properties, property)
p.reparseJSDocComment(property, prop)
}
t = p.factory.NewTypeLiteralNode(p.newNodeList(jstypeliteral.Loc, properties))
if isArrayType {
p.finishReparsedNode(t, jstypeliteral.AsNode())
t = p.factory.NewArrayTypeNode(t)
}
p.finishReparsedNode(t, jstypeliteral.AsNode())
return t
}
return p.factory.DeepCloneReparse(t)
}

func (p *Parser) reparseJSDocComment(node *ast.Node, tag *ast.Node) {
if comment := tag.CommentList(); comment != nil {
propJSDoc := p.factory.NewJSDoc(comment, nil)
p.finishReparsedNode(propJSDoc, tag)
p.jsdocCache[node] = []*ast.Node{propJSDoc}
node.Flags |= ast.NodeFlagsHasJSDoc
}
}

func (p *Parser) gatherTypeParameters(j *ast.Node, tagWithTypeParameters *ast.Node) *ast.NodeList {
var typeParameters []*ast.Node
pos := -1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
// | ```tsx
// | (property) https: number
// | ```
// | ://wass
// |
// | ----------------------------------------------------------------------
// */
Expand Down Expand Up @@ -105,7 +106,7 @@
"item": {
"contents": {
"kind": "markdown",
"value": "```tsx\n(property) https: number\n```\n"
"value": "```tsx\n(property) https: number\n```\n://wass\n"
},
"range": {
"start": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// | ```tsx
// | type Bar = { baz: string; qux: string; }
// | ```
// |
// | Bar comment
// | ----------------------------------------------------------------------
// * @property {string} baz - baz comment
// * @property {string} qux - qux comment
Expand All @@ -22,7 +22,7 @@
// | ```tsx
// | type Bar = { baz: string; qux: string; }
// | ```
// |
// | Bar comment
// | ----------------------------------------------------------------------
// * @returns {Bar}
// */
Expand All @@ -43,7 +43,7 @@
"item": {
"contents": {
"kind": "markdown",
"value": "```tsx\ntype Bar = { baz: string; qux: string; }\n```\n"
"value": "```tsx\ntype Bar = { baz: string; qux: string; }\n```\nBar comment"
},
"range": {
"start": {
Expand All @@ -70,7 +70,7 @@
"item": {
"contents": {
"kind": "markdown",
"value": "```tsx\ntype Bar = { baz: string; qux: string; }\n```\n"
"value": "```tsx\ntype Bar = { baz: string; qux: string; }\n```\nBar comment"
},
"range": {
"start": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@
// ^
// | ----------------------------------------------------------------------
// | foo(): module
// |
// |
// | *@returns* — :@nodefuel/web~Webserver~wsServer#hello} Websocket server object
// |
// | ----------------------------------------------------------------------
//
// /**
Expand Down Expand Up @@ -46,10 +42,6 @@
"signatures": [
{
"label": "foo(): module",
"documentation": {
"kind": "markdown",
"value": "\n\n*@returns* — :@nodefuel/web~Webserver~wsServer#hello} Websocket server object\n"
},
"parameters": []
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,9 @@
// ^
// | ----------------------------------------------------------------------
// | pathFilter(**basePath: String**, pattern: String, type: String, options: Object): any[]
// | - `basePath: String`: The base path where the search will be performed.

// | Filters a path based on a regexp or glob pattern.
// |
// | *@param* `basePath` — The base path where the search will be performed.
// |
// |
// | *@param* `pattern` — A string defining a regexp of a glob pattern.
// |
// |
// | *@param* `type` — The search pattern type, can be a regexp or a glob.
// |
// |
// | *@param* `options` — A object containing options to the search.
// |
// |
// | *@return* — A list containing the filtered paths.
// |
// | ----------------------------------------------------------------------
[
{
Expand All @@ -49,20 +36,36 @@
"label": "pathFilter(basePath: String, pattern: String, type: String, options: Object): any[]",
"documentation": {
"kind": "markdown",
"value": "Filters a path based on a regexp or glob pattern.\n\n*@param* `basePath` — The base path where the search will be performed.\n\n\n*@param* `pattern` — A string defining a regexp of a glob pattern.\n\n\n*@param* `type` — The search pattern type, can be a regexp or a glob.\n\n\n*@param* `options` — A object containing options to the search.\n\n\n*@return* — A list containing the filtered paths.\n"
"value": "Filters a path based on a regexp or glob pattern."
},
"parameters": [
{
"label": "basePath: String"
"label": "basePath: String",
"documentation": {
"kind": "markdown",
"value": "The base path where the search will be performed.\n"
}
},
{
"label": "pattern: String"
"label": "pattern: String",
"documentation": {
"kind": "markdown",
"value": "A string defining a regexp of a glob pattern.\n"
}
},
{
"label": "type: String"
"label": "type: String",
"documentation": {
"kind": "markdown",
"value": "The search pattern type, can be a regexp or a glob.\n"
}
},
{
"label": "options: Object"
"label": "options: Object",
"documentation": {
"kind": "markdown",
"value": "A object containing options to the search.\n"
}
}
],
"activeParameter": 0
Expand Down
Loading