diff --git a/cl/doc.go b/cl/doc.go index 3e331c065..1b162d6fe 100644 --- a/cl/doc.go +++ b/cl/doc.go @@ -59,11 +59,12 @@ func toLineComments(raw string) []*ast.Comment { switch { case strings.HasPrefix(raw, "/*"): body := strings.TrimPrefix(raw, "/*") + body = strings.TrimPrefix(body, "!") body = strings.TrimSuffix(body, "*/") for _, line := range strings.Split(body, "\n") { line = strings.TrimSpace(line) // Drop a Doxygen/Javadoc-style leading "*" decoration. - if line == "*" { + if strings.Trim(line, "*") == "" { line = "" } else if s, ok := strings.CutPrefix(line, "* "); ok { line = s diff --git a/cl/doc_test.go b/cl/doc_test.go new file mode 100644 index 000000000..ab1d92e09 --- /dev/null +++ b/cl/doc_test.go @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2026 The XGo Authors (xgo.dev). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cl + +import ( + "reflect" + "testing" +) + +func TestToLineComments(t *testing.T) { + tests := []struct { + name string + raw string + want []string + }{ + { + name: "asterisk banner delimiters", + raw: `/************************************************************************** +Symbols and macros. + +Please preserve this description. +**************************************************************************/`, + want: []string{ + "// Symbols and macros.", + "//", + "// Please preserve this description.", + }, + }, + { + name: "bang block comment", + raw: "/*! A documented declaration. */", + want: []string{"// A documented declaration."}, + }, + { + name: "doxygen block comment", + raw: "/**\n * A documented declaration.\n */", + want: []string{"// A documented declaration."}, + }, + { + name: "doxygen line comment", + raw: "/// A documented declaration.", + want: []string{"// A documented declaration."}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotComments := toLineComments(tt.raw) + got := make([]string, len(gotComments)) + for i, comment := range gotComments { + got[i] = comment.Text + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("toLineComments() = %#v, want %#v", got, tt.want) + } + }) + } +} diff --git a/tool/_testc/python-3.14.8/llcppg.cfg b/tool/_testc/python-3.14.8/llcppg.cfg index 998886eec..c206f0a2b 100644 --- a/tool/_testc/python-3.14.8/llcppg.cfg +++ b/tool/_testc/python-3.14.8/llcppg.cfg @@ -20,5 +20,6 @@ "GroupSubdirBy": "fname", "FailFast": 10, "IgnoreInline": true, + "KeepDoc": true, "Language": "c" } diff --git a/tool/_testcpp/llvm-22.1.8-support/go.mod b/tool/_testcpp/llvm-22.1.8-support/go.mod index f01dc51a9..c10378236 100644 --- a/tool/_testcpp/llvm-22.1.8-support/go.mod +++ b/tool/_testcpp/llvm-22.1.8-support/go.mod @@ -2,10 +2,6 @@ module llvm go 1.23 -require ( - github.com/goplus/lib v0.5.9 - github.com/llarhub/libcxx v0.1.1 - github.com/llarhub/llvm-c v0.2.0 -) +require github.com/goplus/lib v0.5.9 require github.com/qiniu/x v1.18.3 // indirect diff --git a/tool/_testcpp/llvm-22.1.8-support/go.sum b/tool/_testcpp/llvm-22.1.8-support/go.sum index f279ba905..8b6af0496 100644 --- a/tool/_testcpp/llvm-22.1.8-support/go.sum +++ b/tool/_testcpp/llvm-22.1.8-support/go.sum @@ -1,8 +1,4 @@ github.com/goplus/lib v0.5.9 h1:XTUGEBqzrqMKmN7n+bCsLSq2MxK0pnP+Ea+gjcfBMjM= github.com/goplus/lib v0.5.9/go.mod h1:t4Cgs4QYbPzpI1RnYRA0iXWTgUFUuE09TrE2PvuU0VM= -github.com/llarhub/libcxx v0.1.1 h1:pq/qd3sgtDsima+rrgwOEHYGd/YnyePe6p86rHFD+Xs= -github.com/llarhub/libcxx v0.1.1/go.mod h1:5ANUOJMknbqPXhwxbXnLLA8NbHHyfYWUVQNCPiz04f8= -github.com/llarhub/llvm-c v0.2.0 h1:KXSm+1A9AjyxOcVTtZnlgvWDaWwBySMR27xSouaOaGg= -github.com/llarhub/llvm-c v0.2.0/go.mod h1:5Z6A6u+TghfHdA82zNAhYZHlUkzra7YdUJWc8q3IoJ4= github.com/qiniu/x v1.18.3 h1:trrBKBNszHGwV8XynnbddJr+A7Vca8/xlWP4F/Z4my8= github.com/qiniu/x v1.18.3/go.mod h1:Sx3Wy+0GI9OsX4a53mYj6A0o7mHJ94PUvraqGYb4EIs= diff --git a/tool/config.go b/tool/config.go index 59bc91c71..7c02f2809 100644 --- a/tool/config.go +++ b/tool/config.go @@ -56,6 +56,7 @@ type Config struct { Pkgs []string `json:"Pkgs"` // sub-packages to generate, optional FailFast int `json:"FailFast"` // exit on first N errors, optional IgnoreInline bool `json:"IgnoreInline"` // quietly ignore inline functions + KeepDoc bool `json:"KeepDoc"` // parse all comments for documentation extraction NoManglingIgnore bool `json:"NoManglingIgnore"` // quietly ignore functions with no mangled symbol GroupSubdir bool `json:"GroupSubdir"` // treats sub-directory files as a single file. Deprecated: use GroupSubdirBy instead. GroupSubdirBy string `json:"GroupSubdirBy"` // criterion to group sub-directory files by, e.g., "dir" or "fname". `GroupSubdir = true` is equivalent to `GroupSubdirBy = "dir"`. @@ -91,6 +92,9 @@ func (cfg *Config) Apply(parent *Config) { if cfg.CFlags == "" { cfg.CFlags = parent.CFlags } + if !cfg.KeepDoc { + cfg.KeepDoc = parent.KeepDoc + } if cfg.Deps == nil { cfg.Deps = parent.Deps } diff --git a/tool/gen.go b/tool/gen.go index f0de094f9..9f0a76137 100644 --- a/tool/gen.go +++ b/tool/gen.go @@ -167,7 +167,7 @@ func (cfg *Config) NewPackage(pkgPath, pkgName, workDir string, index clang.Inde } } - files, err := ParseSources(index, topHeaders, incDirs, cfg.Language) + files, err := ParseSources(index, topHeaders, incDirs, cfg.Language, cfg.KeepDoc) if err != nil { return } @@ -348,10 +348,12 @@ func ParseFlags(includeDirs []string, lang string) []string { } // ParseSources parses the given source files and returns the translation units corresponding -// to those files. -func ParseSources(index clang.Index, headerFiles, includeDirs []string, lang string) ([]cl.Source, error) { +// to those files. If keepDoc is true, it also parses ordinary comments. +func ParseSources(index clang.Index, headerFiles, includeDirs []string, lang string, keepDoc ...bool) ([]cl.Source, error) { flags := ParseFlags(includeDirs, lang) - flags = append(flags, "-fparse-all-comments") + if len(keepDoc) > 0 && keepDoc[0] { + flags = append(flags, "-fparse-all-comments") + } files := make([]cl.Source, len(headerFiles)) for i, headerFile := range headerFiles { tu, e := index.ParseTranslationUnit(clang.DetailedPreprocessingRecord, headerFile, flags...)