Skip to content
This repository has been archived by the owner on May 29, 2018. It is now read-only.

Commit

Permalink
Merge pull request #38 from alexsaveliev/master
Browse files Browse the repository at this point in the history
Fixes #37
  • Loading branch information
beyang committed Dec 14, 2015
2 parents 4a05690 + 5ca3e06 commit cb1e5d1
Show file tree
Hide file tree
Showing 2 changed files with 266 additions and 49 deletions.
142 changes: 93 additions & 49 deletions java_def/formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ func init() {
// DefData should be kept in sync with the def 'Data' field emitted by the Java
// grapher.
type DefData struct {
JavaKind string
JavaKind string
TypeExpression string
Modifiers []string
Package string
Modifiers []string
Package string
}

func (s *DefData) isLocalVar() bool {
return s.JavaKind == "LOCAL_VARIABLE";
return s.JavaKind == "LOCAL_VARIABLE"
}

func newDefFormatter(s *graph.Def) graph.DefFormatter {
Expand All @@ -44,65 +44,109 @@ func (f defFormatter) Language() string { return "Java" }

func (f defFormatter) DefKeyword() string {
switch f.data.JavaKind {
case "CLASS":
return "class"
case "INTERFACE":
return "interface"
case "ENUM":
return "enum"
case "PACKAGE":
return "package"
case "PARAMETER", "LOCAL_VARIABLE":
return f.data.TypeExpression
case "METHOD":
return "method"
case "CONSTRUCTOR":
return "constructor"
default:
return ""
case "CLASS":
return "class"
case "INTERFACE":
return "interface"
case "ENUM":
return "enum"
case "PACKAGE":
return "package"
case "PARAMETER", "LOCAL_VARIABLE":
return f.data.TypeExpression
case "METHOD":
return "method"
case "CONSTRUCTOR":
return "constructor"
default:
return ""
}
}

func (f defFormatter) Kind() string { return f.data.JavaKind }

func (f defFormatter) Name(qual graph.Qualification) string {
if qual == graph.Unqualified {
return f.def.Name
}

if f.data.Package == "" { return f.def.Name }
switch qual {
case graph.Unqualified:
return f.def.Name
case graph.ScopeQualified:
return f.scopePrefix() + f.def.Name
case graph.DepQualified, graph.RepositoryWideQualified:
return f.widePrefix() + f.def.Name
case graph.LanguageWideQualified:
return string(f.def.Repo) + "/" + f.Name(graph.RepositoryWideQualified)
}
panic("Name: unhandled qual " + string(qual))
}

func (f defFormatter) Type(qual graph.Qualification) string {
switch f.data.JavaKind {
case "CLASS", "INTERFACE", "METHOD", "CONSTRUCTOR", "ENUM":
pathComponents := strings.Split(string(f.def.Path), "/");
pathComponents = pathComponents[:len(pathComponents)-1]
for i, component := range pathComponents {
pathComponents[i] = strings.Replace(component, ":type", "", -1)
}
return strings.Join(pathComponents, ".") + "." + f.def.Name
case "CLASS":
return "class"
case "INTERFACE":
return "interface"
case "ENUM":
return "enum"
case "PACKAGE":
return "package"
default:
return f.data.TypeExpression
}
}

return f.def.Name
func (f defFormatter) NameAndTypeSeparator() string {
if f.data.JavaKind == "CONSTRUCTOR" || f.data.JavaKind == "METHOD" {
return ""
}
return " "
}

func (f defFormatter) Type(qual graph.Qualification) string {
switch f.data.JavaKind {
case "CLASS":
return "class"
case "INTERFACE":
return "interface"
case "ENUM":
return "enum"
case "PACKAGE":
return "package"
default:
return f.data.TypeExpression
// Constructs scope-level prefix which consists for classes, interfaces, enums (including constants),
// and methods (including constructors) from path elements after package name concatenated by "."
// - for class foo.bar.baz.Qux scope prefix is empty string
// - for method foo.bar.baz.Qux.norf() scope prefix is Qux.
// - for package foo.bar.baz scope prefix is empty string
// - for inner enum foo.bar.baz.Qux.Norf scope prefix is Qux.
// - for inner enum's constant foo.bar.baz.Qux.Norf.A scope prefix is Qux.Norf.
func (f defFormatter) scopePrefix() string {
switch f.data.JavaKind {
case "CLASS", "INTERFACE", "METHOD", "CONSTRUCTOR", "ENUM", "ENUM_CONSTANT":
pathComponents := strings.Split(strings.TrimPrefix(string(f.def.Path), strings.Replace(f.data.Package, ".", "/", -1)+"/"), "/")
l := len(pathComponents)
if l > 1 {
pathComponents = pathComponents[l-2 : l-1]
return prefix(pathComponents)
}
}
return ""
}

func (f defFormatter) NameAndTypeSeparator() string {
if f.data.JavaKind == "CONSTRUCTOR" || f.data.JavaKind == "METHOD" {
return ""
}
return " "
// Constructs wide-level prefix which consists for classes, interfaces, enums (including constants),
// and methods (including constructors) from path elements except the last one concatenated by "."
// - for class foo.bar.baz.Qux prefix is foo.bar.baz.
// - for method foo.bar.baz.Qux.norf() prefix is foo.bar.baz.Qux.
// - for package foo.bar.baz prefix is foo.bar.
// - for inner enum foo.bar.baz.Qux.Norf prefix is foo.bar.baz.Qux
// - for inner enum's constant foo.bar.baz.Qux.Norf.A prefix is foo.bar.baz.Qux.Norf.
func (f defFormatter) widePrefix() string {
switch f.data.JavaKind {
case "CLASS", "INTERFACE", "METHOD", "CONSTRUCTOR", "ENUM", "ENUM_CONSTANT":
pathComponents := strings.Split(string(f.def.Path), "/")
pathComponents = pathComponents[:len(pathComponents)-1]
return prefix(pathComponents)
}
return ""
}

// Concatenates path components by "." to form a prefix.
// Returns empty string if there are no path components available
func prefix(pathComponents []string) string {
for i, component := range pathComponents {
pathComponents[i] = strings.Replace(component, ":type", "", -1)
}
if len(pathComponents) > 0 {
return strings.Join(pathComponents, ".") + "."
}
return ""
}
173 changes: 173 additions & 0 deletions java_def/formatter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package java_def

import (
"encoding/json"
"testing"

"sourcegraph.com/sourcegraph/srclib/graph"
)

func TestName(t *testing.T) {

tests := map[string]struct {
def graph.Def
data DefData
expected map[graph.Qualification]string
}{
"package": {
def: graph.Def{
DefKey: graph.DefKey{
Repo: "https://foo.bar/baz",
CommitID: "abc",
UnitType: "JavaPackage",
Unit: ".",
Path: "baz/Qux",
},
Name: "mypkg",
Kind: "package",
},
data: DefData{
JavaKind: "PACKAGE",
Package: "mypkg",
},
expected: map[graph.Qualification]string{
graph.Unqualified: "mypkg",
graph.ScopeQualified: "mypkg",
graph.DepQualified: "mypkg",
graph.RepositoryWideQualified: "mypkg",
graph.LanguageWideQualified: "https://foo.bar/baz/mypkg",
},
},
"type": {
def: graph.Def{
DefKey: graph.DefKey{
Repo: "https://foo.bar/baz",
CommitID: "abc",
UnitType: "JavaPackage",
Unit: ".",
Path: "de/goddchen/android/gradle/helloworld/BuildConfig:type",
},
Name: "BuildConfig",
},
data: DefData{
JavaKind: "CLASS",
TypeExpression: "de.goddchen.android.gradle.helloworld.BuildConfig",
Package: "de.goddchen.android.gradle.helloworld",
},
expected: map[graph.Qualification]string{
graph.Unqualified: "BuildConfig",
graph.ScopeQualified: "BuildConfig",
graph.DepQualified: "de.goddchen.android.gradle.helloworld.BuildConfig",
graph.RepositoryWideQualified: "de.goddchen.android.gradle.helloworld.BuildConfig",
graph.LanguageWideQualified: "https://foo.bar/baz/de.goddchen.android.gradle.helloworld.BuildConfig",
},
},
"var": {
def: graph.Def{
DefKey: graph.DefKey{
Repo: "https://foo.bar/baz",
CommitID: "abc",
UnitType: "JavaPackage",
Unit: ".",
Path: "de/goddchen/android/gradle/helloworld/BuildConfig:type/APPLICATION_ID",
},
Name: "APPLICATION_ID",
},
data: DefData{
JavaKind: "CLASS",
TypeExpression: "java.lang.String",
Package: "de.goddchen.android.gradle.helloworld",
},
expected: map[graph.Qualification]string{
graph.Unqualified: "APPLICATION_ID",
graph.ScopeQualified: "BuildConfig.APPLICATION_ID",
graph.DepQualified: "de.goddchen.android.gradle.helloworld.BuildConfig.APPLICATION_ID",
graph.RepositoryWideQualified: "de.goddchen.android.gradle.helloworld.BuildConfig.APPLICATION_ID",
graph.LanguageWideQualified: "https://foo.bar/baz/de.goddchen.android.gradle.helloworld.BuildConfig.APPLICATION_ID",
},
},
"method": {
def: graph.Def{
DefKey: graph.DefKey{
Repo: "https://foo.bar/baz",
CommitID: "abc",
UnitType: "JavaPackage",
Unit: ".",
Path: "de/goddchen/android/gradle/helloworld/MainActivity:type/onCreate:android.os.Bundle",
},
Name: "onCreate",
},
data: DefData{
JavaKind: "METHOD",
TypeExpression: "(android.os.Bundle)void",
Package: "de.goddchen.android.gradle.helloworld",
},
expected: map[graph.Qualification]string{
graph.Unqualified: "onCreate",
graph.ScopeQualified: "MainActivity.onCreate",
graph.DepQualified: "de.goddchen.android.gradle.helloworld.MainActivity.onCreate",
graph.RepositoryWideQualified: "de.goddchen.android.gradle.helloworld.MainActivity.onCreate",
graph.LanguageWideQualified: "https://foo.bar/baz/de.goddchen.android.gradle.helloworld.MainActivity.onCreate",
},
},
"inner-enum": {
def: graph.Def{
DefKey: graph.DefKey{
Repo: "https://foo.bar/baz",
CommitID: "abc",
UnitType: "JavaPackage",
Unit: ".",
Path: "foo/bar/baz/Qux:type/Norf:type",
},
Name: "Norf",
},
data: DefData{
JavaKind: "ENUM",
TypeExpression: "foo.bar.baz.Qux.Norf",
Package: "foo.bar.baz",
},
expected: map[graph.Qualification]string{
graph.Unqualified: "Norf",
graph.ScopeQualified: "Qux.Norf",
graph.DepQualified: "foo.bar.baz.Qux.Norf",
graph.RepositoryWideQualified: "foo.bar.baz.Qux.Norf",
graph.LanguageWideQualified: "https://foo.bar/baz/foo.bar.baz.Qux.Norf",
},
},
"inner-enum-constant": {
def: graph.Def{
DefKey: graph.DefKey{
Repo: "https://foo.bar/baz",
CommitID: "abc",
UnitType: "JavaPackage",
Unit: ".",
Path: "foo/bar/baz/Qux:type/Norf:type/A",
},
Name: "A",
},
data: DefData{
JavaKind: "ENUM_CONSTANT",
TypeExpression: "foo.bar.baz.Qux.Norf",
Package: "foo.bar.baz",
},
expected: map[graph.Qualification]string{
graph.Unqualified: "A",
graph.ScopeQualified: "Norf.A",
graph.DepQualified: "foo.bar.baz.Qux.Norf.A",
graph.RepositoryWideQualified: "foo.bar.baz.Qux.Norf.A",
graph.LanguageWideQualified: "https://foo.bar/baz/foo.bar.baz.Qux.Norf.A",
},
},
}

for label, test := range tests {
test.def.Data, _ = json.Marshal(test.data)
formatter := newDefFormatter(&test.def)
for q, value := range test.expected {
actual := formatter.Name(q)
if actual != value {
t.Errorf("%s [%v]: expected %s but got %s", label, q, value, actual)
}
}
}
}

0 comments on commit cb1e5d1

Please sign in to comment.