Go 言語での関数一覧についてNo.32721
もとはし さん 13/11/15 14:15
 
現状の秀丸は、アウトライン解析の関数一覧機能で
「C言語/Java」のみしか対応していないとのことですが、
ぜひ「Go 言語」への対応をお願いできませんでしょうか?

ご参考までに申し上げますと、例えば Go 言語付属の
os パッケージ(=ライブラリみたいなもの)に含まれている
*File.Write 関数のシグネチャは、次のように定義されて
います。

  func (file *File) Write(b []byte) (n int, err Error)

これの意味する所は、

・"Write()":関数名
・(b []byte):引数は1個で、型は byte(≒char)の配列
・(n int, err Error):返り値は2個で、1つ目の型は int、2つ目の型は Error 型。
・(file *file):これはレシーバーと呼ばれるものですが、ここでは詳細は説明は省
略させて頂きます。

http://golang.jp/effective_go#functions

現状の秀丸では、このような行が関数として認識されません。

現象を見る限りでは、この不具合の原因は関数名の後ろに
"(n int, err Error)" のような丸カッコでくくられた文字列
が存在しているからのようです。

対応策としては、以下のような方法があるかと存じます。

・アウトライン解析の対象言語に「Go」言語を追加する。
・関数宣言部を見つけるための正規表現をユーザ設定可能とする。

現在日々の開発で不便を感じておりますので、ぜひ前向きに
ご検討頂けますと幸いに存じます。

以上です。よろしくお願い致します。

[ ]
RE:32721 Go 言語での関数一覧についてNo.32722
秀丸担当 さん 13/11/15 15:00
 

Go言語について、いまのところ詳しくはわかりませんが、そういう言語もあると
いうことでご意見参考にさせていただきます。

ちょっと見た感じでは、C言語に似ているようで、C言語のデフォルトの状態の
「行の強調表示」で関数は表示されているようです。
アウトライン解析を「強調一覧」にすると、検索して出てきたページのサンプル
ではうまくいっているようです。
強調表示をデフォルトのC言語のようにするとしたら、[その他]→[ファイルタイ
プ別の設定]→[デザイン]→[強調表示]で、「リセット(E)>>」から「C言語用」
を選びます。

行まるごとではなく、関数名の部分だけを一覧に出したいという場合は、アウト
ライン解析で「ツリー表示 - 通常」を使うと可能です。
C言語用の行の強調表示と同じ正規表現をちょっと変えて加えてもできますが、
説明するのにわかりづらいので、行頭に「func」があるものとして書きます。
(見た感じ必ず行頭に「func」があるようですが合っているでしょうか?)

[その他]→[ファイルタイプ別の設定]→[アウトライン]→[解析]で、「ツリー表
示 - 通常」にします。
「追加...」で以下のものを追加します。

「種類」は「文字列」

「文字列」は
^func\s+(?:\(.*?\)\s)?(\i+)\((?\1)

「正規表現」をON
「オプション>>」を出して、「表示範囲」を「ヒットした文字のみ」
(必要であれば「コメントを無視」もON」)

こうして追加しておくと、行頭にfuncがある行のうち、関数名の部分だけがアウ
トライン解析に一覧として出ます。


ちなみに現在β版のV8.33においては、「C言語/Java」は「C言語/Java等」とい
う表記に改め、C#やObjective-Cなどにも対応範囲を広げています。

[ ]
RE:32722 Go 言語での関数一覧についてNo.32723
もとはし さん 13/11/15 16:31
 
もとはしです。
お世話になります。

まず秀丸を最新βの 8.33 Beta 11 にアップデートさせて頂きました。

>ちょっと見た感じでは、C言語に似ているようで、C言語のデフォルトの状態の
>「行の強調表示」で関数は表示されているようです。
>アウトライン解析を「強調一覧」にすると、検索して出てきたページのサンプル
>ではうまくいっているようです。

ありがとうございます。確かにこれで関数が強調表示され、強調一覧にも全ての関数
が表示されました。
ただ若干の不具合がありまして、以下のようなソースコードの場合に関数では無い "
import (" の行が
強調表示対象に含まれてしまいました。

  import (
    "fmt"
    "encoding/json"
    "io"
  )

しかしこの強調表示を使用すると、アウトライン解析の一覧に強調対象行の全体が表
示されてしまうため、
一覧表示の所が文字ばかりになってしまって、お目当ての関数を見つけづらいように
と感じました。
できましたら標準機能の関数一覧の時と同様に、関数名と引数部分のみをスッキリと
表示できるとありがたいです。

>行まるごとではなく、関数名の部分だけを一覧に出したいという場合は、アウト
>ライン解析で「ツリー表示 - 通常」を使うと可能です。

確かにこの方法では関数名の部分だけを一覧に出すことができました。
しかいこのツリー表示機能を使用すると行番号が表示されないため、プログラマとし
てはあまり使いたくない
と感じました。

> (見た感じ必ず行頭に「func」があるようですが合っているでしょうか?)

Go 言語における標準的なコーディングスタイルでは、"func" は必ず行頭に書きます。
ただ、必須ではありません。

>「文字列」は
>^func\s+(?:\(.*?\)\s)?(\i+)\((?\1)

ちなみに関数名は英数字とアンダースコアが利用可能なので、"\i" の部分は "\c"
とするのが正しそうです。

>ちなみに現在β版のV8.33においては、「C言語/Java」は「C言語/Java等」とい
>う表記に改め、C#やObjective-Cなどにも対応範囲を広げています。

なるほど。Go 言語はいまいちメジャーではないようですが、2009年には「TIOBE Pro
gramming Language of Year」
を受賞しておりますので、できれば今後の秀丸のバージョンアップ時に Go 言語への
対応を追加して頂けますと幸いです。

http://www.atmarkit.co.jp/fcoding/articles/go/03/go03a.html

今後ともよろしくお願い致します。

[ ]
RE:32723 Go 言語での関数一覧についてNo.32724
秀まるお2 さん 13/11/18 17:25
 
 サイト−企画の斉藤秀夫です。

 最近、C言語関数一覧関係をいろいろいじったのでついでにGo言語対応も、簡
単そうでしたらやってみたいと思ったのですが、2点ほど教えて欲しい所があり
ます。

 1.関数には必ず「func」が付くということでいいのかどうか。

   

 2.現状の「C言語/Java等」の関数一覧で無理矢理Go言語のソースコードを
   見た時に、余計な物(関数じゃない物)が関数として出てきてしまう物
   があるかどうか。あるとしたら、その例を教えて欲しい。

 です。

 もしここの発言を参照されておられましたら、その辺のお返事よろしくお願い
します。

 「1」については、もしもfuncが付くって前提なら非常に簡単に対応できると
思いますが、funcが付かないパターンもあるとなると、対応が難しくなるかと思
います。

 「2」については、もしも余計な物が関数として出てこないようであれば、特
に新しい言語として対応しなくても、現状のC言語/Javaに追加的な処理だけで対
応出来ます。余計な物が関数と誤判定されるようであれば、設定の追加からしな
いといけなくて、ちょっと面倒かなぁと思いました。

[ ]
RE:32724 Go 言語での関数一覧についてNo.32725
秀まるお2 さん 13/11/18 17:44
 
>  1.関数には必ず「func」が付くということでいいのかどうか。

 自分でコメントするのもなんですが、

> Go 言語における標準的なコーディングスタイルでは、"func" は必ず行頭に書きま
>す。
> ただ、必須ではありません。

 とあって、この「必須ではありません」が、「行頭に書かなくてもいい」とい
う意味なのか、それとも「func」というキーワード自体を省略可能という意味な
のか、どっちか分からなくて質問してしまいました。

 go言語の説明を見た限りでは、「func」が省略可能であるような記述はなさそ
うですけども。

[ ]
RE:32725 Go 言語での関数一覧についてNo.32726
もとはし さん 13/11/18 18:06
 
こんにちは、もとはしです。

>>  1.関数には必ず「func」が付くということでいいのかどうか。
>> Go 言語における標準的なコーディングスタイルでは、"func" は必ず行頭に書き
>ます。
>> ただ、必須ではありません。
> とあって、この「必須ではありません」が、「行頭に書かなくてもいい」とい
>う意味なのか、それとも「func」というキーワード自体を省略可能という意味な
>のか、どっちか分からなくて質問してしまいました。

まぎらわしい書き方をして、申し訳ありませんでした。
もう少し正確に回答させて頂くと、

・関数名の前に "func" を書くのは必須です。
・"func" の前にスペースを入れることは可能ですが、推奨されていません。

となります。なお、こちらに Go 言語の関数宣言に関する言語仕様が書かれています。
http://golang.org/ref/spec#Function_declarations

Go 言語では "go" というコマンドで以下のような操作が可能なのですが、

・go build: プログラムのビルド
・go run: プログラムのビルド&実行
・go fmt: ソースコードの整形

"go fmt" でソースコードを整形すると、"func" の前のスペースは取り除かれます。

> 2.現状の「C言語/Java等」の関数一覧で無理矢理Go言語のソースコードを
>    見た時に、余計な物(関数じゃない物)が関数として出てきてしまう物
>    があるかどうか。あるとしたら、その例を教えて欲しい。

以下のような例があります。

| import (
|     "fmt"
| )
| var (
|     i int
| )
| const (
|     a string = "Hello, world!"
| )
| type (
|     TYPE_A struct {
|         a int
|     }
| )

また "(" の後には何も書かないで改行するのが、一般的なコーディングスタイルです。

☆参考
http://dave.cheney.net/2013/11/14/stupid-go-declaration-tricks

以上です。よろしくお願い致します。

[ ]
RE:32726 Go 言語での関数一覧についてNo.32727
秀まるお2 さん 13/11/18 18:24
 
 素早いコメントありがとうございます。

import (
    "fmt"
)


 これらは、アウトライン解析の方法を「強調一覧」にした時に出てくるってこ
とで、「関数一覧」にしてる場合は出てこないと思います。

 こちらでテストした限りは出てこないので大丈夫かと思った所でした。

 「設定・ファイルタイプ別の設定...」の「アウトライン - 解析」ページにあ
る「アウトライン解析の方法」を「関数一覧」にしたら出ないかと思うのですが、
その辺どうでしょうか。

> ☆参考
> → http://dave.cheney.net/2013/11/14/stupid-go-declaration-tricks

 ここを見ると、

func ( main() { ... } )

 のような記述の例もあるようですね。これはちょっとややこしいです。

func (
    main() { ... }
    sub() { ... }
)

 とか書いたらmainとsubの両方出さないといけないということで…。

 これは対応不可って制限にしたい所です。

[ ]
RE:32727 Go 言語での関数一覧についてNo.32728
もとはし さん 13/11/19 11:45
 
こんにちは、もとはしです。

>  「設定・ファイルタイプ別の設定...」の「アウトライン - 解析」ページにあ
> る「アウトライン解析の方法」を「関数一覧」にしたら出ないかと思うのですが、
> その辺どうでしょうか。

確かに「関数一覧」を選択した所、"import (" のような行は表示されませんでした。
確認不足で、失礼致しました。

> func (
>     main() { ... }
>     sub() { ... }
> )
> とか書いたらmainとsubの両方出さないといけないということで…。

確かにこの書き方も文法上は可能ですね。

> これは対応不可って制限にしたい所です。

この書き方は一般的ではないので、これを制約事項としても困る人はいないと
思います。

あと他にも関数ではないのに関数として表示される例をいくつか見つけましたので、
以下にご報告させて頂きたいと思います。

func main() {
    f := func(s string) { // @関数リテラル(匿名関数)の例
  fmt.Println(s)
 }
 
 cb, ok = f.(CallBackFunc) // A型アサーションの例
 if !ok {
  t.Errorf("UnmarshalJson() returned unexpected type:[%T]\n", msg)
 }
 
 value, ok = cmd.getValue()  // Bメソッドコールの例
 if !ok {
  Println("cannot get value")
 }
 
 j = func2(100)    // C単なる関数コール
 str := `{}`
}

まず@に関しては、匿名の関数は関数一覧に表示されても役に立たないので、
できれば表示対象外として頂けると助かります。

AとBは、いずれも次行の if 文の条件式がカッコで括られていないのが
影響しているようです。

最後のCは、バッククォートで囲んだ文字列の中に "{}" が含まれている
ことが影響しているようです。

以上です。よろしくお願い致します。

[ ]
RE:32728 Go 言語での関数一覧についてNo.32729
秀まるお2 さん 13/11/19 12:00
 
 またまた情報ありがとうございます。

 今見た所、少し困ったことに気づいてしまいました。文の区切りにセミコロン
が無いです。

 j = func2(100)    // C単なる関数コール
 str := `{}`

 これって、セミコロンで区切ってないのですね。普通だったら

 j = func2(100);    // C単なる関数コール
 str := `{}`;

 みたいに書いてくれそうな気がするし、例えばWikipediaにあるサンプルとか
はセミコロンで区切られてるみていですけども。

 っと調べてみたら、

http://golang.jp/2010/01/1134

 って所にセミコロンが省略できるルールが書いてありました。ちょっとその辺
勉強してみます。

 セミコロンなしで書かれている場合は、やはり現状の「C言語/Java等」とは別
の言語種別設定を用意しないと対応出来ないかと思います。あるいはGo言語の
ソースコードであることが、ファイルの先頭付近で自動判別出来たらいいですけ
ども。

 もうちょっと勉強してから考えてみます。

[ ]
RE:32729 Go 言語での関数一覧についてNo.32730
秀まるお2 さん 13/11/19 15:37
 
 とりあえずこんなロジックで判定出来そうなので、そういう方向でいじってみ
ます。

 何かこうした方がいい的なご意見があればお願いします。


■1.go言語のソースコードかどうかの判定

 コメントや空白/改行を除いたファイルの先頭のキーワードが"package"かど
うか見て、packageがある場合は、C言語/go言語の自動判定モードに入る。

 自動判定モードに入った状態で、行の先頭(インデントはあってもいい)に
"func"のキーワードを見つけたら、go言語モードにする。
 "func"を見つける前に何らかのC言語関数を見つけたら、C言語モードとする。

 ちなみにJavaのソースコードでもファイルの先頭に"package"が入ることがあ
るのですけど、"func"で始まる行は無いはずなので、上記の判定でいけると思い
ます。

■2.go言語モードでの関数の拾い方ロジック:

 "func"のキーワードがあることが前提。

 "func"があったら、それより後ろから"{"までが関数。

 funcがあれば基本関数だけど、無名関数(匿名関数)は除外しないといけない。

■3.匿名関数(無名関数)

 匿名関数か普通の関数かどうかは、"func"と"{"の間にある"(...)"のパターン
で判定する。

 普通の関数:(XXX部分が関数名)

 func (...) XXX (...) {
 func (...) XXX (...) ... {
 func XXX (...) {
 func XXX (...) ... {
 func XXX (...) (...) ... {   // "(...)"が何個あってもOK

 匿名関数:

 func (...) {
 func (...) ... {

 判定ロジック:
 "func"の後に括弧がある場合は、その後ろにあるキーワードのさらに後ろにも
(...)が必ず必要。
 "func"の後ろが括弧でない場合は、そのままOK。

 "func"から"{"の間に改行がある場合で、その行の末尾(コメントや空白を除
いた実質的なプログラムの行末)が"("じゃない場合は、それは関数扱いしない。
同様に、"func"から"{"の間にセミコロンが1つでもある場合は、それも関数扱
いしない。

■4.関数名

   func (aaa) XXX (bbb) {

 のように宣言された場合、関数名は

    (aaa) XXX

 となり、パラメータは

   (bbb)

 としたらいいのかなぁと思います。

 関数名として"XXX"のみの方がいいってご意見があればそうします。

 パラメータ非表示時には"XXX"のみ表示、パラメータ表示時には
" (aaa) XXX (bbb)" のように表示ってのはちょっと面倒なのでやりたくないで
す。

[ ]
RE:32730 Go 言語での関数一覧についてNo.32731
秀まるお2 さん 13/11/19 15:44
 
>  "func"から"{"の間に改行がある場合で、その行の末尾(コメントや空白を除
> いた実質的なプログラムの行末)が"("じゃない場合は、それは関数扱いしない。

 "("と、あと","も含める必要がありました。

 他にも何かあれば教えて欲しいです。

[ ]
RE:32731 Go 言語での関数一覧についてNo.32733
もとはし さん 13/11/19 18:04
 
こんにちは、もとはしです。

前向きに色々とご検討して頂きまして、ありがとうございます。

まず1点、訂正させてください。

> > ☆参考
> > → http://dave.cheney.net/2013/11/14/stupid-go-declaration-tricks
>  ここを見ると、
> func ( main() { ... } )
> のような記述の例もあるようですね。これはちょっとややこしいです。

の件ですが、リンク先にはこのような書き方は構文的に正しくないと説明されていま
すので
(the following is not valid syntax)、このような書き方には対応しないのが正
解でした。

> ■1.go言語のソースコードかどうかの判定
> ■2.go言語モードでの関数の拾い方ロジック:
> ■3.匿名関数(無名関数)

いずれもこの仕様で問題無さそうです。

> ■4.関数名

関数名としては "(aaa) XXX" を表示するのが正しいと思います。

この構文はオブジェクト aaa のメソッド XXX をコールするという意味なので、ソース
コード中に同一名称のメソッドが存在するが、それは別の関数であるという状況は普通
にあり得ます。

> "("と、あと","も含める必要がありました。
> 他にも何かあれば教えて欲しいです。

私の方では特に他の文字を思い当たりませんでした。

以上です。よろしくお願い致します。

[ ]
RE:32733 Go 言語での関数一覧についてNo.32738
秀まるお2 さん 13/11/22 17:13
 
 ちなみにですが、今日アップロードされた秀丸エディタV8.33β12にて、今回
の修正が入っています。

 もしよかったらこれで試してみてほしいです。

[ ]
RE:32738 Go 言語での関数一覧についてNo.32739
もとはし さん 13/11/25 13:19
 
こんにちは、もとはしです。

> ちなみにですが、今日アップロードされた秀丸エディタV8.33β12にて、今回
>の修正が入っています。

秀丸エディタ V8.33β12 を試してみた所、残念ながらアウトライン解析 - 関数一覧
 で、
いくつか誤動作するパターンが見つかりましたのでご報告させて頂きます。

■hidemaru-test1.go
------------------------------
package main

func func1(a interface{}) {
  a := func2()
  if !a {
   
  }
}

func func3() (int, int) {
}
------------------------------
・不具合1:func1() が関数一覧に表示されない。
・不具合2:func2() が関数一覧に表示されてしまう。
・不具合3:func3() が関数一覧に表示されない。

■hidemaru-test2.go
------------------------------
package main

func Func1(bbb int64) *int {
}

func (int *a) Func2BBBBBBBBBBBBBBBBBBBBBBBBB() (CCCCCCCCCCCCCCCCCCCCCCCCCCC,
 bool) {
}
------------------------------
□不具合再現手順
(1) 上記内容で hidemaru-test2.go を作成し、秀丸を一旦終了する。
(2) Func2BBB..() の行にカーソルを移動する。
(3) アウトライン解析 - 関数一覧を表示すると、アウトライン解析ウィンドウの一
覧の所で
    "3 Func1()" の行が選択状態になってしまう。

ユーザの期待としては、Func2BBB..() の行が選択されているべきと考えます。

以上です。よろしくお願い致します。

[ ]
RE:32739 Go 言語での関数一覧についてNo.32740
秀まるお2 さん 13/11/25 17:04
 
 詳しい情報ありがとうございます。

 連絡いただいた現象はすべてこちらでも再現しました。一応、バグとしては
2点だと思うのですが、詳しくテストして修正させていただきます。

> func func1(a interface{}) {

 interfaceの後ろに{}があって、それで誤判定してしまってるようです。

>
> func (int *a) Func2BBBBBBBBBBBBBBBBBBBBBBBBB() (CCCCCCCCCCCCCCCCCCCCCCCCCCC,
>  bool) {

 ウィンドウ右端で自動折り返しが発生すると狂ってしまうようでした。これま
た修正させていただきます。

[ ]
RE:32740 Go 言語での関数一覧についてNo.32744
秀まるお2 さん 13/11/26 18:10
 
 以下の関数は関数一覧に出るようにしました。

func func1(a interface{}) {
}
func func2(a interface{}) interface{} {
}
func func3(a interface{}) interface{} {
}
func func4(a interface{}) (interface{}) interface{} {
}

 interfaceのうしろが{}である場合は、それ全体を普通の文字列と同じ扱いに
しました。

  interface { } のように空白が混じっててもOKとしました。

 もしかして

func func5( interface { aaa } ) {
}

 のような表記がありえるとしたらダメですけども、そういう表記は無いはずだ
と思いました。(ネット検索した限りは)

 あと、

func func8(
func func9() {
}

 みたいに壊れた関数の直後の関数がうまくヒットしないのも直しました。

 次のβ版に反映させていただきます。

[ ]