Skip to content
This repository has been archived by the owner on Mar 8, 2020. It is now read-only.

Commit

Permalink
update positioner and annotater; related to #240 and #244
Browse files Browse the repository at this point in the history
Signed-off-by: Denys Smirnov <denys@sourced.tech>
  • Loading branch information
Denys Smirnov committed Mar 15, 2018
1 parent 0aedded commit 9f16a30
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 102 deletions.
75 changes: 43 additions & 32 deletions uast/ann/ann.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"

"gopkg.in/bblfsh/sdk.v1/uast"
"gopkg.in/bblfsh/sdk.v1/uast/role"
)

type axis int
Expand Down Expand Up @@ -42,7 +43,7 @@ func (a axis) String() string {
// predicate in a syntax similar to XPath.
type Predicate interface {
fmt.Stringer
Eval(n *uast.Node) bool
Eval(n uast.Node) bool
}

// Rule is a conversion rule that can visit a tree, match nodes against
Expand Down Expand Up @@ -108,7 +109,7 @@ func (r *Rule) addRules(axis axis, rules []*Rule) *Rule {
}

// Apply applies the rule to the given node.
func (r *Rule) Apply(n *uast.Node) (err error) {
func (r *Rule) Apply(n uast.Node) (err error) {
// recover from panics and returns them as errors.
defer func() {
if rec := recover(); rec != nil {
Expand Down Expand Up @@ -139,7 +140,7 @@ func (r *Rule) Apply(n *uast.Node) (err error) {
}

// Roles attaches an action to the rule that adds the given roles.
func (r *Rule) Roles(roles ...uast.Role) *Rule {
func (r *Rule) Roles(roles ...role.Role) *Rule {
return r.Do(AddRoles(roles...))
}

Expand All @@ -157,7 +158,7 @@ type RuleError interface {

type ruleError struct {
error
node *uast.Node
node uast.Node
}

// implements RuleError.
Expand All @@ -166,7 +167,7 @@ func (e *ruleError) Inner() error {
}

// implements RuleError.
func (e *ruleError) Node() *uast.Node {
func (e *ruleError) Node() uast.Node {
return e.node
}

Expand All @@ -193,32 +194,37 @@ func (p *hasInternalType) String() string {
return fmt.Sprintf("@InternalType='%s'", string(*p))
}

func (p *hasInternalType) Eval(n *uast.Node) bool {
func (p *hasInternalType) Eval(n uast.Node) bool {
o, _ := n.(uast.Object)
if n == nil {
return false
}
return n.InternalType == string(*p)
return o.Type() == string(*p)
}

// HasProperty matches a node if it has a property matching the given key and value.
func HasProperty(k, v string) Predicate { return &hasProperty{k, v} }
func HasProperty(k, v string) Predicate { return &hasProperty{k: k, v: uast.String(v)} }

type hasProperty struct{ k, v string }
type hasProperty struct {
k string
v uast.String
}

func (p *hasProperty) String() string {
return fmt.Sprintf("@%s][@%[1]s='%s'", p.k, p.v)
}

func (p *hasProperty) Eval(n *uast.Node) bool {
func (p *hasProperty) Eval(n uast.Node) bool {
if n == nil {
return false
}

if n.Properties == nil {
obj, _ := n.(uast.Object)
if obj == nil {
return false
}

prop, ok := n.Properties[p.k]
prop, ok := obj[p.k]
return ok && prop == p.v
}

Expand All @@ -239,12 +245,13 @@ func (p *hasChild) String() string {
return fmt.Sprintf("child::%s", p.Predicate)
}

func (p *hasChild) Eval(n *uast.Node) bool {
func (p *hasChild) Eval(n uast.Node) bool {
if n == nil {
return false
}

for _, c := range n.Children {
obj, _ := n.(uast.Object)
for _, c := range obj.Children() {
if p.Predicate.Eval(c) {
return true
}
Expand All @@ -265,12 +272,12 @@ func (p *hasToken) String() string {
return fmt.Sprintf("@Token='%s'", string(*p))
}

func (p *hasToken) Eval(n *uast.Node) bool {
func (p *hasToken) Eval(n uast.Node) bool {
if n == nil {
return false
}

return n.Token == string(*p)
obj, _ := n.(uast.Object)
return obj.Token() == string(*p)
}

// Any matches any path.
Expand Down Expand Up @@ -303,7 +310,7 @@ const andGlue = " and "

func (p *and) String() string { return joinPredicates(p.data, andGlue) }

func (p *and) Eval(n *uast.Node) bool {
func (p *and) Eval(n uast.Node) bool {
for _, p := range p.data {
if !p.Eval(n) {
return false
Expand Down Expand Up @@ -333,7 +340,7 @@ const orGlue = " or "

func (p *or) String() string { return joinPredicates(p.data, orGlue) }

func (p *or) Eval(n *uast.Node) bool {
func (p *or) Eval(n uast.Node) bool {
for _, p := range p.data {
if p.Eval(n) {
return true
Expand All @@ -349,59 +356,63 @@ func (p *or) Eval(n *uast.Node) bool {
// string method returns a string describing the operation.
type Action interface {
fmt.Stringer
Do(n *uast.Node) error
Do(n uast.Node) error
}

// action implements Action by returning desc when String is called.
type action struct {
do func(n *uast.Node) error
do func(n uast.Node) error
desc string
}

func (a *action) Do(n *uast.Node) error { return a.do(n) }
func (a *action) Do(n uast.Node) error { return a.do(n) }

func (a *action) String() string { return a.desc }

// AddRoles creates an action to add the given roles to a node.
func AddRoles(roles ...uast.Role) Action {
func AddRoles(roles ...role.Role) Action {
descs := make([]string, len(roles))
for i, role := range roles {
descs[i] = role.String()
}
return &action{
do: func(n *uast.Node) error {
if len(n.Roles) > 0 && n.Roles[0] == uast.Unannotated {
n.Roles = n.Roles[:0]
do: func(n uast.Node) error {
obj, _ := n.(uast.Object)
roles := obj.Roles()
if len(roles) > 0 && roles[0] == role.Unannotated {
roles = roles[:0]
}
appendUniqueRoles(n, roles...)
appendUniqueRoles(obj, roles...)
return nil
},
desc: strings.Join(descs, ", "),
}
}

func appendUniqueRoles(n *uast.Node, roles ...uast.Role) {
func appendUniqueRoles(n uast.Object, roles ...role.Role) {
addedRoles := make(map[string]bool)

for _, role := range n.Roles {
cur := n.Roles()
for _, role := range cur {
if _, ok := addedRoles[role.String()]; !ok {
addedRoles[role.String()] = true
}
}

for _, role := range roles {
if _, ok := addedRoles[role.String()]; !ok {
n.Roles = append(n.Roles, role)
cur = append(cur, role)
addedRoles[role.String()] = true
}
}
n[uast.KeyRoles] = uast.RoleList(cur...)
}

// ReturnError creates an action that always returns a RuleError
// wrapping the given error with the offending node information.
func ReturnError(err error) Action {
return &action{
do: func(n *uast.Node) error {
do: func(n uast.Node) error {
return &ruleError{
error: err,
node: n,
Expand All @@ -417,7 +428,7 @@ type matchPathIter struct {
iter uast.PathStepIter
}

func newMatchPathIter(n *uast.Node, axis axis, predicates []Predicate) uast.PathIter {
func newMatchPathIter(n uast.Node, axis axis, predicates []Predicate) uast.PathIter {
return &matchPathIter{
axis: axis,
predicates: predicates,
Expand Down
4 changes: 2 additions & 2 deletions uast/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,13 @@ func (m Object) Roles() []role.Role {
}

// StartPosition returns start position of the node in source file.
func (m Object) StartPosition() Position {
func (m Object) StartPosition() *Position {
o, _ := m[KeyStart].(Object)
return AsPosition(o)
}

// EndPosition returns start position of the node in source file.
func (m Object) EndPosition() Position {
func (m Object) EndPosition() *Position {
o, _ := m[KeyEnd].(Object)
return AsPosition(o)
}
Expand Down
3 changes: 1 addition & 2 deletions uast/transformer/annotatter/annotater.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package annotatter

import (
"gopkg.in/bblfsh/sdk.v1/protocol"
"gopkg.in/bblfsh/sdk.v1/uast"
"gopkg.in/bblfsh/sdk.v1/uast/ann"
)
Expand All @@ -14,6 +13,6 @@ func NewAnnotatter(r *ann.Rule) *Annotatter {
return &Annotatter{r: r}
}

func (t *Annotatter) Do(code string, e protocol.Encoding, n *uast.Node) error {
func (t *Annotatter) Do(n uast.Node) error {
return t.r.Apply(n)
}
30 changes: 21 additions & 9 deletions uast/transformer/positioner/positions.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"sort"

"gopkg.in/bblfsh/sdk.v1/protocol"
"gopkg.in/bblfsh/sdk.v1/uast"
)

Expand All @@ -21,10 +20,10 @@ func NewFillLineColFromOffset() *Positioner {
}

type Positioner struct {
method func(*positionIndex, *uast.Position) error
method func(*positionIndex, uast.Object) error
}

func (t *Positioner) Do(data string, e protocol.Encoding, n *uast.Node) error {
func (t *Positioner) Do(data string, n uast.Node) error {
idx := newPositionIndex([]byte(data))
iter := uast.NewOrderPathIter(uast.NewPath(n))
for {
Expand All @@ -33,20 +32,24 @@ func (t *Positioner) Do(data string, e protocol.Encoding, n *uast.Node) error {
break
}

n := p.Node()
if err := t.method(idx, n.StartPosition); err != nil {
n, ok := p.Node().(uast.Object)
if !ok {
continue
}
if err := t.method(idx, n); err != nil {
return err
}

if err := t.method(idx, n.EndPosition); err != nil {
if err := t.method(idx, n); err != nil {
return err
}
}

return nil
}

func fillOffsetFromLineCol(idx *positionIndex, pos *uast.Position) error {
func fillOffsetFromLineCol(idx *positionIndex, o uast.Object) error {
pos := uast.AsPosition(o)
if pos == nil {
return nil
}
Expand All @@ -57,10 +60,15 @@ func fillOffsetFromLineCol(idx *positionIndex, pos *uast.Position) error {
}

pos.Offset = uint32(offset)

for k, v := range pos.ToObject() {
o[k] = v
}
return nil
}

func fillLineColFromOffset(idx *positionIndex, pos *uast.Position) error {
func fillLineColFromOffset(idx *positionIndex, o uast.Object) error {
pos := uast.AsPosition(o)
if pos == nil {
return nil
}
Expand All @@ -72,6 +80,10 @@ func fillLineColFromOffset(idx *positionIndex, pos *uast.Position) error {

pos.Line = uint32(line)
pos.Col = uint32(col)

for k, v := range pos.ToObject() {
o[k] = v
}
return nil
}

Expand Down Expand Up @@ -147,7 +159,7 @@ func (idx *positionIndex) Offset(line, col int) (int, error) {
maxCol := maxOffset - idx.offsetByLine[line] + 1

// For empty files with 1-indexed drivers, set maxCol to 1
if (maxCol == 0 && col == 1) {
if maxCol == 0 && col == 1 {
maxCol = 1
}

Expand Down
Loading

0 comments on commit 9f16a30

Please sign in to comment.