Permalink
Browse files

Initial commit.

Signed-off-by: Yorick Peterse <yorickpeterse@gmail.com>
  • Loading branch information...
0 parents commit d089b5293dbf09fc092f173526e543b718e576d5 @YorickPeterse committed Jul 29, 2012
2 .gitignore
@@ -0,0 +1,2 @@
+pkg
+Gemfile.lock
1 .ruby-version
@@ -0,0 +1 @@
+1.9.3-p194
3 Gemfile
@@ -0,0 +1,3 @@
+source :rubygems
+
+gemspec
19 LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2012, Yorick Peterse
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
0 MANIFEST
No changes.
1 README.md
@@ -0,0 +1 @@
+# README
12 Rakefile
@@ -0,0 +1,12 @@
+require 'rubygems/package_task'
+
+GEMSPEC = Gem::Specification.load('rlint.gemspec')
+
+Dir['./task/*.rake'].each do |task|
+ import(task)
+end
+
+Gem::PackageTask.new(GEMSPEC) do |pkg|
+ pkg.need_tar = false
+ pkg.need_zip = false
+end
3 bin/rlint
@@ -0,0 +1,3 @@
+#!/usr/bin/env ruby
+
+require File.expand_path('../../lib/rlint', __FILE__)
21 lib/rlint.rb
@@ -0,0 +1,21 @@
+require 'ripper'
+
+unless $:.include?(File.expand_path('../', __FILE__))
+ $:.unshift(File.expand_path('../', __FILE__))
+end
+
+require 'rlint/parser'
+#require 'rlint/scope'
+require 'rlint/token/token'
+require 'rlint/token/variable_token'
+require 'rlint/token/method_token'
+require 'rlint/token/class_token'
+require 'rlint/token/value_token'
+require 'rlint/token/operator_token'
+
+module Rlint
+ def self.lint(code, file = nil)
+ parser = Parser.new(code)
+ tokens = parser.parse
+ end
+end # Rlint
353 lib/rlint/parser.rb
@@ -0,0 +1,353 @@
+module Rlint
+ ##
+ #
+ # @since 2012-07-29
+ #
+ class Parser < Ripper::SexpBuilderPP
+ ##
+ # Creates a new instance of the parser class and stores the lines of the
+ # code block as an array.
+ #
+ # @since 2012-07-29
+ # @see  Ripper::SexpBuilderPP#initialize
+ #
+ def initialize(code, file = '(ripper)', line = 1)
+ @lines = code.lines.to_a
+ @parameters = nil
+
+ super
+ end
+
+ ##
+ # Called when the program starts.
+ #
+ # @since 2012-07-29
+ # @param [Array] program Array containing the body of a block of code.
+ # @return [Array]
+ #
+ def on_program(program)
+ return program
+ end
+
+ ##
+ # Called when the body of a method or class is found.
+ #
+ # @since 2012-07-29
+ # @param [Array] args Array containing the method arguments.
+ # @return [Array]
+ #
+ def on_bodystmt(*args)
+ return args[0]
+ end
+
+ ##
+ # Called when a set of arguments are added to a method call.
+ #
+ # @since 2012-07-29
+ # @param [Array] args Array of arguments passed to the method.
+ # @return [Array]
+ #
+ def on_args_add_block(*args)
+ return args[0]
+ end
+
+ ##
+ # Called when a set of method arguments are defined using a parenthesis.
+ #
+ # Instead of returning the tokens this method stores them in the
+ # `@parameters` instance variable. This variable is used to properly assign
+ # the parameters when calling methods using parenthesis.
+ #
+ # @since 2012-07-29
+ # @param [Array] args Array containing the details of the arguments.
+ # @return [NilClass]
+ #
+ def on_arg_paren(args)
+ @parameters = args
+
+ return nil
+ end
+
+ ##
+ # Called when a set of arguments are added to a method call.
+ #
+ # @since 2012-07-29
+ # @see Rlint::Parser#on_args_add_block
+ #
+ def on_method_add_arg(*args)
+ return args[0]
+ end
+
+ ##
+ # Called for a set of method parameters.
+ #
+ # @since 2012-07-29
+ # @param [Array] args Array of arguments passed to this method.
+ # @return [Array]
+ #
+ def on_params(*args)
+ retval = []
+
+ args.each do |arg|
+ next unless arg.is_a?(Array)
+
+ arg = arg[0]
+
+ if arg.length == 3
+ name = arg[1]
+ value = nil
+ line = arg[2][0]
+ col = arg[2][1]
+ else
+ name = arg[0][1]
+ value = arg[1]
+ line = arg[0][2][0]
+ col = arg[0][2][1]
+ end
+
+ retval << Token::Token.new(
+ :name => name,
+ :type => :parameter,
+ :value => value,
+ :line => line,
+ :column => col,
+ :code => code(line)
+ )
+ end
+
+ return retval
+ end
+
+ ##
+ # Called when a parenthesis is found.
+ #
+ # @since 2012-07-29
+ # @param [Array] args The arguments passed to this method.
+ # @return [Array]
+ #
+ def on_paren(args)
+ return args
+ end
+
+ ##
+ # Called when a new method is defined.
+ #
+ # @since 2012-07-29
+ # @param [Array] name Array containing details about the method name.
+ # @param [Array] params Array containing the method parameters.
+ # @param [Array] body Array containing the body of the method.
+ # @return [Rlint::Token::MethodToken]
+ #
+ def on_def(name, params, body)
+ return Token::MethodToken.new(
+ :name => name[1],
+ :type => :def,
+ :value => body,
+ :parameters => params,
+ :line => name[2][0],
+ :column => name[2][1],
+ :code => code(name[2][0])
+ )
+ end
+
+ ##
+ # Called when a new class is defined.
+ #
+ # @since 2012-07-29
+ # @param [Rlint::Token::VariableToken] klass Token for the class' name.
+ # @param [Rlint::Token::VariableToken] parent Token for the parent class.
+ # @param [Array] body Array containing the body of the class.
+ # @return [Rlint::Token::ClassToken]
+ #
+ def on_class(klass, parent, body)
+ return Token::ClassToken.new(
+ :name => klass.name,
+ :type => :class,
+ :line => klass.line,
+ :column => klass.column,
+ :parent => parent.name,
+ :value => body
+ )
+ end
+
+ ##
+ # Called when a method is called.
+ #
+ # @since 2012-07-29
+ # @param [Array] method Array containing details about the method name.
+ # @return [Rlint::Token::MethodToken]
+ #
+ def on_fcall(method)
+ token = Token::MethodToken.new(
+ :name => method[1],
+ :type => :method,
+ :line => method[2][0],
+ :column => method[2][1],
+ :code => code(lineno),
+ :parameters => @parameters
+ )
+
+ @parameters = nil
+
+ return token
+ end
+
+ ##
+ # Called when a method is called without any parenthesis.
+ #
+ # @since 2012-07-29
+ # @param [Array] method Array containing details about the method name.
+ # @param [Array] args Array containing details about the method arguments.
+ # @return [Rlint::Token::MethodToken]
+ #
+ def on_command(method, args)
+ return Token::MethodToken.new(
+ :name => method[1],
+ :type => :method,
+ :line => method[2][0],
+ :column => method[2][1],
+ :code => code(method[2][0]),
+ :parameters => args
+ )
+ end
+
+ ##
+ # Called when an operator (`*` and `<<` for example) is used.
+ #
+ # @since 2012-07-29
+ # @param [Rlint::Token::Token] left The token to the left of the operator.
+ # @param [Symbol] operator The operator that was used.
+ # @param [Rlint::Token::Token] right The token to the right of the
+ # operator.
+ # @return [Rlint::Token::OperatorToken]
+ #
+ def on_binary(left, operator, right)
+ return Token::OperatorToken.new(
+ :name => operator,
+ :left => left,
+ :right => right
+ )
+ end
+
+ ##
+ # Called when a `return` statement is found.
+ #
+ # @since 2012-07-29
+ # @param [Array] retval Array containing details about the return value.
+ # @return [Rlint::Token::Token]
+ #
+ def on_return(retval)
+ return Token::Token.new(
+ :name => 'return',
+ :type => :statement,
+ :parameters => retval,
+ :line => lineno,
+ :column => column,
+ :code => code(lineno)
+ )
+ end
+
+ ##
+ # Called when a new variable is defined.
+ #
+ # @since 2012-07-29
+ # @param [Array] variable Array containing details about the variable.
+ # @param [Array] value Array containing details about the variable's
+ # value.
+ # @return [Rlint::Token::VariableToken]
+ #
+ def on_assign(variable, value)
+ line_number = variable[1][2][0]
+
+ return Token::VariableToken.new(
+ :name => variable[1][1],
+ :type => variable[1][0],
+ :value => value,
+ :line => line_number,
+ :column => variable[1][2][1],
+ :code => code(line_number)
+ )
+ end
+
+ ##
+ # Called when a defined variable is referenced. This method is **not**
+ # called when an undefined variable is referenced.
+ #
+ # @since 2012-07-29
+ # @param [Array] variable Array containing details about the variable.
+ # @return [Rlint::Token::VariableToken]
+ #
+ def on_var_ref(variable)
+ type = variable[0]
+ var = variable[1]
+
+ return Token::VariableToken.new(
+ :name => var,
+ :type => type,
+ :line => variable[2][0],
+ :column => variable[2][1],
+ :code => code(lineno)
+ )
+ end
+
+ ##
+ # Called when a constant is referenced.
+ #
+ # @since 2012-07-29
+ # @return [Rlint::Token::VariableToken]
+ #
+ def on_const_ref(const)
+ return on_var_ref(const)
+ end
+
+ ##
+ # Called when an integer is found.
+ #
+ # @since 2012-07-29
+ # @param [Array] int Array containing details about the integer.
+ # @return [Rlint::Token::Token]
+ #
+ def on_int(int)
+ return Token::ValueToken.new(
+ :type => :integer,
+ :value => int,
+ :line => lineno,
+ :column => column,
+ :code => code(lineno)
+ )
+ end
+
+ ##
+ # Called when a string literal was found.
+ #
+ # @since 2012-07-29
+ # @param [Array] string Array containing details about the string.
+ # @return [Rlint::Token::Token]
+ #
+ def on_string_literal(string)
+ string = string[1]
+
+ return Token::Token.new(
+ :type => :string,
+ :value => string[1],
+ :line => string[2][0],
+ :column => string[2][1],
+ :code => code(string[2][0])
+ )
+ end
+
+ private
+
+ ##
+ # Returns the line of code for a given line number.
+ #
+ # @since 2012-07-29
+ # @param [Fixnum|Bignum] line The line number as returned by Ripper. Unlike
+ # Array indexes these line numbers start with 1 instead of 0.
+ # @return [String]
+ #
+ def code(line)
+ return @lines[line - 1]
+ end
+ end # Parser
+end # Rlint
74 lib/rlint/scope.rb
@@ -0,0 +1,74 @@
+module Rlint
+ class Scope
+ VARIABLE_MAPPING = {
+ :@ident => :local_variables,
+ :@gvar => :global_variables,
+ :@ivar => :instance_variables,
+ :@cvar => :class_variables,
+ :@const => :constants
+ }
+
+ LOOKUP_PARENT = [:global_variables, :class_variables, :constants, :methods]
+
+ attr_accessor :parent
+ attr_accessor :local_variables
+ attr_accessor :global_variables
+ attr_accessor :instance_variables
+ attr_accessor :class_variables
+ attr_accessor :constants
+ attr_accessor :methods
+
+ def initialize(parent = nil)
+ @parent = parent
+ @local_variables = {}
+ @global_variables = {}
+ @instance_variables = {}
+ @class_variables = {}
+ @constants = {}
+ @methods = {}
+ end
+
+ def lookup(type, name)
+ type, name = type.to_sym, name
+
+ if VARIABLE_MAPPING[type]
+ type = VARIABLE_MAPPING[type]
+ end
+
+ found = instance_variable_get("@#{type}")[name]
+
+ # Look for the variable in the parent scope (if there is any).
+ if lookup_parent?(type)
+ found = @parent.lookup(type, name)
+ end
+
+ return found
+ end
+
+ def get(type, variable)
+ if VARIABLE_MAPPING[type]
+ type = VARIABLE_MAPPING[type]
+ end
+
+ found = instance_variable_get("@#{type}")[variable]
+
+ if lookup_parent?(type)
+ found = @parent.lookup(type, name)
+ end
+
+ return found
+ end
+
+ def set(type, variable)
+ if VARIABLE_MAPPING[type]
+ type = VARIABLE_MAPPING[type]
+ end
+
+ instance_variable_get("@#{type}")[variable.name] = variable
+ end
+
+ def lookup_parent?(type)
+ return !@parent.nil? && LOOKUP_PARENT.include?(type)
+ end
+ end # Scope
+end # Rlint
17 lib/rlint/token/class_token.rb
@@ -0,0 +1,17 @@
+module Rlint
+ module Token
+ ##
+ # Token class used for storing data about classes.
+ #
+ # @since 2012-07-29
+ #
+ class ClassToken < Token
+ ##
+ # The parent class, if any.
+ #
+ # @since 2012-07-29
+ #
+ attr_reader :parent
+ end # ClassToken
+ end # Token
+end # Rlint
27 lib/rlint/token/method_token.rb
@@ -0,0 +1,27 @@
+module Rlint
+ module Token
+ ##
+ # Token class used for storing methods, their parameters, body, etc.
+ #
+ # @since 2012-07-29
+ #
+ class MethodToken < Token
+ ##
+ # Array of tokens for the method parameters.
+ #
+ # @since 2012-07-29
+ # @return [Array]
+ #
+ attr_reader :parameters
+
+ ##
+ # The scope for this method. Note that this attribute is only set when
+ # the token is used for defining a method, not when calling one.
+ #
+ # @since 2012-07-29
+ # @return [Rlint::Scope]
+ #
+ attr_reader :scope
+ end # MethodToken
+ end # Token
+end # Rlint
31 lib/rlint/token/operator_token.rb
@@ -0,0 +1,31 @@
+module Rlint
+ module Token
+ ##
+ # Token class used for storing data of operators and the values used for
+ # the operation.
+ #
+ # The operator that was used is stored in the `name` attribute. This token
+ # class also doesn't store the line number, column number or source code as
+ # this is already stored in the tokens used for the operation.
+ #
+ # @since 2012-07-29
+ #
+ class OperatorToken < Token
+ ##
+ # The token to the left of the operator.
+ #
+ # @since 2012-07-29
+ # @return [Rlint::Token::Token]
+ #
+ attr_reader :left
+
+ ##
+ # The token to the right of the operator.
+ #
+ # @since 2012-07-29
+ # @return [Rlint::Token::Token]
+ #
+ attr_reader :right
+ end # OperatorToken
+ end # Token
+end # Rlint
93 lib/rlint/token/token.rb
@@ -0,0 +1,93 @@
+module Rlint
+ module Token
+ ##
+ # Generic token class used for data that doesn't require its own specific
+ # token.
+ #
+ # @since 2012-07-29
+ #
+ class Token
+ ##
+ # Hash containing various Ripper tokens and the Rlint tokens to use
+ # instead.
+ #
+ # @since 2012-07-29
+ # @return [Hash]
+ #
+ TOKEN_MAPPING = {
+ :@ident => :identifier,
+ :@gvar => :global_variable,
+ :@ivar => :instance_variable,
+ :@cvar => :class_variable,
+ :@const => :constant
+ }
+
+ ##
+ # The name of the token. For example, when the token is a variable this
+ # is set to the name of the variable.
+ #
+ # @since 2012-07-29
+ # @return [String]
+ #
+ attr_reader :name
+
+ ##
+ # The value of the token. For example, if the token is a variable this
+ # attribute is set to the token for the variable's value.
+ #
+ # @since 2012-07-29
+ # @return [Rlint::Token::Token]
+ #
+ attr_reader :value
+
+ ##
+ # The line number on which the token was defined.
+ #
+ # @since 2012-07-29
+ # @return [Fixnum|Bignum]
+ #
+ attr_reader :line
+
+ ##
+ # The column number on which the token was defined.
+ #
+ # @since 2012-07-29
+ # @return [Fixnum|Bignum]
+ #
+ attr_reader :column
+
+ ##
+ # The source code of the line on which the token was defined. Due to
+ # these values being references to a single list of lines these values
+ # should never be modified directly (e.g. by using `#gsub!()`).
+ #
+ # @since 2012-07-29
+ # @return [String]
+ #
+ attr_reader :code
+
+ ##
+ # Creates a new instance of the token and sets various instance variables
+ # based on the specified hash.
+ #
+ # @since 2012-07-29
+ # @param [Hash] options A hash containing various instance variables to
+ # set and their values. For a variable to be set it requires a
+ # corresponding public getter mehtod to be set.
+ #
+ def initialize(options = {})
+ options.each do |key, value|
+ if respond_to?(key)
+ instance_variable_set("@#{key}", value)
+ end
+ end
+
+ # If the token class has a `type` attribute it should be mapped to a
+ # nicer version of the token as stored in TOKEN_MAPPING.
+ if TOKEN_MAPPING[@type]
+ @type = TOKEN_MAPPING[@type]
+ end
+ end
+ end # Token
+ end # Token
+end # Rlint
43 lib/rlint/token/value_token.rb
@@ -0,0 +1,43 @@
+module Rlint
+ module Token
+ ##
+ # Token class used for storing data of values (integers, strings, etc).
+ #
+ # @since 2012-07-29
+ #
+ class ValueToken < Token
+ ##
+ # Hash containing various Ripper names for value types and the Rlint
+ # names to use instead.
+ #
+ # @since 2012-07-29
+ # @return [Hash]
+ #
+ TYPE_MAPPING = {
+ :@int => :integer,
+ :@float => :float,
+ }
+
+ ##
+ # The type of value, e.g. `:integer`.
+ #
+ # @since 2012-07-29
+ # @return [Symbol]
+ #
+ attr_reader :type
+
+ ##
+ # Override {Rlint::Token::Token#initialize} so that the variable type can
+ # be set properly.
+ #
+ # @since 2012-07-29
+ # @see Rlint::Token::Token#initialize
+ #
+ def initialize(*args)
+ super
+
+ @type = TYPE_MAPPING[@type] if TYPE_MAPPING[@type]
+ end
+ end # ValueToken
+ end # Token
+end # Rlint
39 lib/rlint/token/variable_token.rb
@@ -0,0 +1,39 @@
+module Rlint
+ module Token
+ ##
+ # Token class used for storing information about variables.
+ #
+ # @since 2012-07-29
+ #
+ class VariableToken < Token
+ ##
+ # The type of variable that was defined.
+ #
+ # @since 2012-07-29
+ # @return [Symbol]
+ #
+ attr_reader :type
+
+ ##
+ # Boolean that indicates if the variable is used or not.
+ #
+ # @since 2012-07-29
+ # @return [TrueClass|FalseClass]
+ #
+ attr_accessor :used
+
+ ##
+ # Override {Rlint::Token::Token#initialize} so that the type can be set
+ # to `:local_variable` for local variables instead of `:identifier`.
+ #
+ # @since 2012-07-29
+ # @see Rlint::Token::Token#initialize
+ #
+ def initialize(*args)
+ super
+
+ @type = :local_variable if @type == :identifier
+ end
+ end # VariableToken
+ end # Token
+end # Rlint
3 lib/rlint/version.rb
@@ -0,0 +1,3 @@
+module Rlint
+ VERSION = '0.0.1'
+end # Rlint
22 rlint.gemspec
@@ -0,0 +1,22 @@
+require File.expand_path('../lib/rlint/version', __FILE__)
+
+Gem::Specification.new do |s|
+ s.name = 'rlint'
+ s.version = Rlint::VERSION
+ s.date = '2012-12-01'
+ s.authors = ['Yorick Peterse']
+ s.email = 'yorickpeterse@gmail.com'
+ s.summary = 'Static code analysis tool for validating Ruby source code.'
+ s.homepage = 'https://github.com/yorickpeterse/rlint/'
+ s.description = s.summary
+
+ s.files = File.read(File.expand_path('../MANIFEST', __FILE__)).split("\n")
+
+ s.has_rdoc = 'yard'
+ s.required_ruby_version = '>= 1.9.2'
+
+ s.add_development_dependency('rake', ['>= 0.9.2.2'])
+ s.add_development_dependency('redcarpet', ['>= 2.1.1'])
+ s.add_development_dependency('bacon', ['>= 1.1.0'])
+ s.add_development_dependency('yard', ['>= 0.8.2.1'])
+end
5 spec/helper.rb
@@ -0,0 +1,5 @@
+require File.expand_path('../../lib/rlint', __FILE__)
+require 'bacon'
+
+Bacon.extend(Bacon::TapOutput)
+Bacon.summary_on_exit
126 spec/rlint/parser.rb
@@ -0,0 +1,126 @@
+require File.expand_path('../../helper', __FILE__)
+
+describe 'Rlint::Parser' do
+ it 'Parse the assignment of a variable' do
+ parser = Rlint::Parser.new('number = 10')
+ tokens = parser.parse
+
+ var = tokens[0]
+
+ # Check the variable itself.
+ var.is_a?(Rlint::Token::VariableToken).should == true
+
+ var.name.should == 'number'
+ var.line.should == 1
+ var.column.should == 0
+ var.type.should == :local_variable
+ var.code.should == 'number = 10'
+
+ # Check the value
+ var.value.is_a?(Rlint::Token::ValueToken).should == true
+
+ var.value.line.should == 1
+ var.value.column.should == 9
+ var.value.type.should == :integer
+ var.value.code.should == 'number = 10'
+ end
+
+ it 'Parse the assignment and reference of a variable' do
+ parser = Rlint::Parser.new("number = 10\nnumber")
+ tokens = parser.parse
+
+ tokens.length.should == 2
+
+ ref = tokens[1]
+
+ ref.is_a?(Rlint::Token::VariableToken).should == true
+
+ ref.name.should == 'number'
+ ref.line.should == 2
+ ref.column.should == 0
+ ref.code.should == 'number'
+ end
+
+ it 'Parse basic operator usage' do
+ # Parse the * operator.
+ parser = Rlint::Parser.new('10 * 2')
+ tokens = parser.parse
+
+ tokens[0].name.should == :*
+
+ tokens[0].left.is_a?(Rlint::Token::ValueToken).should == true
+ tokens[0].right.is_a?(Rlint::Token::ValueToken).should == true
+
+ tokens[0].left.value.should == '10'
+ tokens[0].right.value.should == '2'
+
+ # Parse the << operator.
+ parser = Rlint::Parser.new('[] << 10')
+ tokens = parser.parse
+
+ tokens[0].name.should == :<<
+
+ tokens[0].left.is_a?(Rlint::Token::ValueToken).should == true
+ tokens[0].right.is_a?(Rlint::Token::ValueToken).should == true
+ end
+
+ it 'Parse a method call without parenthesis' do
+ parser = Rlint::Parser.new('puts 10, 15')
+ tokens = parser.parse
+
+ tokens.length.should == 1
+
+ method = tokens[0]
+
+ method.name.should == 'puts'
+ method.line.should == 1
+ method.column.should == 0
+
+ method.parameters.length.should == 2
+
+ param1 = method.parameters[0]
+ param2 = method.parameters[1]
+
+ param1.is_a?(Rlint::Token::ValueToken).should == true
+ param2.is_a?(Rlint::Token::ValueToken).should == true
+
+ param1.type.should == :integer
+ param2.type.should == :integer
+
+ param1.line.should == 1
+ param2.line.should == 1
+
+ param1.column.should == 5
+ param2.column.should == 9
+ end
+
+ it 'Parse a method call with parenthesis' do
+ parser = Rlint::Parser.new('puts(10, 15)')
+ tokens = parser.parse
+
+ tokens.length.should == 1
+
+ method = tokens[0]
+
+ method.name.should == 'puts'
+ method.line.should == 1
+ method.column.should == 0
+
+ method.parameters.length.should == 2
+
+ param1 = method.parameters[0]
+ param2 = method.parameters[1]
+
+ param1.is_a?(Rlint::Token::ValueToken).should == true
+ param2.is_a?(Rlint::Token::ValueToken).should == true
+
+ param1.type.should == :integer
+ param2.type.should == :integer
+
+ param1.line.should == 1
+ param2.line.should == 1
+
+ param1.column.should == 5
+ param2.column.should == 9
+ end
+end
6 task/test.rake
@@ -0,0 +1,6 @@
+desc 'Runs all the tests'
+task :test do
+ glob = File.expand_path('../../spec/rlint/**/*.rb', __FILE__)
+
+ Dir[glob].each { |file| require(file) }
+end

0 comments on commit d089b52

Please sign in to comment.