Class: JsDuck::TypeParser

Inherits:
Object
  • Object
show all
Defined in:
lib/jsduck/type_parser.rb

Overview

Validates the syntax of type definitions

Quick summary of supported types:

  • SomeType

  • Name.spaced.Type

  • Number[]

  • String/RegExp

  • Type…

Details are covered in spec.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(relations = {}, formatter = {}) ⇒ TypeParser

Initializes the parser with hash of valid type names and doc_formatter.



29
30
31
32
# File 'lib/jsduck/type_parser.rb', line 29

def initialize(relations={}, formatter={})
  @relations = relations
  @formatter = formatter
end

Instance Attribute Details

#errorObject (readonly)

Allows to check the type of error that was encountered. It will be either of the two:

  • :syntax - type definition syntax is incorrect

  • :name - one of the names of the types is unknown



22
23
24
# File 'lib/jsduck/type_parser.rb', line 22

def error
  @error
end

#outObject (readonly)

When parsing was successful, then contains the output HTML - the input type-definition with types themselves replaced with links.



26
27
28
# File 'lib/jsduck/type_parser.rb', line 26

def out
  @out
end

Instance Method Details

#base_typeObject

The basic type

<ident> [ "." <ident> ]* [ "[]" ]* [ "..." ]

dot-separated identifiers followed by optional “[]”



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/jsduck/type_parser.rb', line 61

def base_type
  type = @input.scan(/[a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)*/)

  if !type
    return false
  elsif @relations[type]
    @out << @formatter.link(type, nil, type)
  elsif @relations.ignore?(type) || type == "undefined"
    @out << type
  else
    @error = :name
    return false
  end

  while @input.scan(/\[\]/)
    @out << "[]"
  end

  @out << "..." if @input.scan(/\.\.\./)

  true
end

#parse(str) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/jsduck/type_parser.rb', line 34

def parse(str)
  @input = StringScanner.new(str)
  @error = :syntax
  @out = []

  # Return immediately if base type doesn't match
  return false unless base_type

  # Go through enumeration of types, separated with "/"
  while @input.check(/\//)
    @out << @input.scan(/\//)
    # Fail if there's no base type after "/"
    return false unless base_type
  end

  # Concatenate all output
  @out = @out.join

  # Success if we have reached the end of input
  return @input.eos?
end