summaryrefslogtreecommitdiff
path: root/spec/ruby/language/reserved_keywords.rb
blob: 6c40e34cccc92e8608111baf8f02d8c5c9786e1a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
require_relative '../spec_helper'

describe "Ruby's reserved keywords" do
  # Copied from https://github.com/ruby/ruby/blob/master/defs/keywords
  keywords = %w[
    alias
    and
    begin
    BEGIN
    break
    case
    class
    def
    defined?
    do
    else
    elsif
    end
    END
    ensure
    false
    for
    if
    in
    module
    next
    nil
    not
    or
    redo
    rescue
    retry
    return
    self
    super
    then
    true
    undef
    unless
    until
    when
    while
    yield
    __ENCODING__
    __FILE__
    __LINE__
  ]

  keywords.each do |name|
    describe "keyword '#{name}'" do
      it "can't be used as local variable name" do
        -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
            #{name} = :local_variable
        RUBY
      end

      if name == "defined?"
        it "can't be used as an instance variable name" do
          -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
            @#{name} = :instance_variable
          RUBY
        end

        it "can't be used as a class variable name" do
          -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
            class C
              @@#{name} = :class_variable
            end
          RUBY
        end

        it "can't be used as a global variable name" do
          -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
            $#{name} = :global_variable
          RUBY
        end
      else
        it "can be used as an instance variable name" do
          result = eval <<~RUBY
            @#{name} = :instance_variable
            @#{name}
          RUBY

          result.should == :instance_variable
        end

        it "can be used as a class variable name" do
          result = eval <<~RUBY
            class C
              @@#{name} = :class_variable
              @@#{name}
            end
          RUBY

          result.should == :class_variable
        end

        it "can be used as a global variable name" do
          result = eval <<~RUBY
            $#{name} = :global_variable
            $#{name}
          RUBY

          result.should == :global_variable
        end
      end

      it "can't be used as a positional parameter name" do
        -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
          def x(#{name}); end
        RUBY
      end

      invalid_kw_param_names = ["BEGIN","END","defined?"]

      if invalid_kw_param_names.include?(name)
        it "can't be used a keyword parameter name" do
          -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
            def m(#{name}:); end
          RUBY
        end
      else
        it "can be used a keyword parameter name" do
          result = instance_eval <<~RUBY
            def m(#{name}:)
              binding.local_variable_get(:#{name})
            end

            m(#{name}: :argument)
          RUBY

          result.should == :argument
        end
      end

      it "can be used as a method name" do
        result = instance_eval <<~RUBY
          def #{name}
            :method_return_value
          end

          send(:#{name})
        RUBY

        result.should == :method_return_value
      end
    end
  end
end