fast_method_source 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d73c77ef828261b4ad145f88bd1d78682133b215
4
- data.tar.gz: 3fa8f4dc7471bd3e2b78f6c479bc795d38972f13
3
+ metadata.gz: c0cd70578b6aaaef59d7671494865a18c5e86de0
4
+ data.tar.gz: 247ab14fe91beb917dd9d136682707594c3d3e47
5
5
  SHA512:
6
- metadata.gz: 5d3ab1de1d9a55e1c681e684c85cbc92f349e77927cbfb0999ce59419c35a6120d588286133399e0484ff60258fb4313f02145de33a0f71419db504b98f24054
7
- data.tar.gz: 4426e0c403f8de0b80bed5264cd91495a06d5468ba73912b5b5a4511ef0a4942915c7d1b19f7a64bb67d2e65d055922a6c1a6d4f298b53fff8ab3ca5f094c871
6
+ metadata.gz: b799a52825b9e85e26a8084138240e37f5cf75db475d72935b6f0eb63464293685a89bf2e783f549a87666568bf086a9ea2a3afc536c218c9dddd6afedf62ab8
7
+ data.tar.gz: 385239928c2a382550889de7dfdcb3547f44b5e8b11c0c63cafc061887bd6b6a64d095a96af2e817d84f56716b18db5f0146143b0437989b183f405e483cfd49
@@ -1,6 +1,12 @@
1
1
  Fast Method Source changelog
2
2
  ============================
3
3
 
4
+ ### v0.4.0 (June 18, 2015)
5
+
6
+ * _Significantly_ improve speed of both `#soruce` and `#comment`. The trade-off
7
+ is that you must indent methods properly.
8
+ * Decrease memeory consumption
9
+
4
10
  ### v0.3.1 (June 11, 2015)
5
11
 
6
12
  * Considerable speed improvements
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  <a name="Back_to_top">
2
2
  # Fast Method Source
3
3
 
4
+ [![Build Status](https://travis-ci.org/kyrylo/fast_method_source.svg?branch=master)](https://travis-ci.org/kyrylo/fast_method_source)
5
+
4
6
  * Repository: [https://github.com/kyrylo/fast_method_source/][repo]
5
7
 
6
8
  Table of Contents
@@ -24,7 +26,6 @@ Table of Contents
24
26
  * <a href="#rubies">Rubies</a>
25
27
  * <a href="#operation-systems">Operation Systems</a>
26
28
  * <a href="#roadmap">Roadmap</a>
27
- * <a href="#further-speed-improvements">Further Speed Improvements</a>
28
29
  * <a href="#optional-memoization">Optional Memoization</a>
29
30
  * <a href="#licence">Licence</a>
30
31
 
@@ -91,15 +92,15 @@ does not support it at the moment.
91
92
  Processor: Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz
92
93
  Platform: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
93
94
  Counting the number of sample methods...
94
- Sample methods: 18970
95
+ Sample methods: 19280
95
96
  Rehearsal -----------------------------------------------------------
96
- FastMethodSource#source 6.340000 0.460000 6.800000 ( 7.616361)
97
- MethodSource#source 86.030000 0.500000 86.530000 (104.094356)
98
- ------------------------------------------------- total: 93.330000sec
97
+ FastMethodSource#source 0.760000 0.240000 1.000000 ( 1.104455)
98
+ MethodSource#source 53.240000 0.250000 53.490000 ( 59.304424)
99
+ ------------------------------------------------- total: 54.490000sec
99
100
 
100
101
  user system total real
101
- FastMethodSource#source 6.830000 0.590000 7.420000 ( 8.258469)
102
- MethodSource#source 80.470000 0.310000 80.780000 ( 89.864366)
102
+ FastMethodSource#source 0.610000 0.190000 0.800000 ( 0.890971)
103
+ MethodSource#source 51.770000 0.230000 52.000000 ( 57.640986)
103
104
  ```
104
105
 
105
106
  #### #comment
@@ -109,15 +110,15 @@ MethodSource#source 80.470000 0.310000 80.780000 ( 89.864366)
109
110
  Processor: Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz
110
111
  Platform: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
111
112
  Counting the number of sample methods...
112
- Sample methods: 19596
113
+ Sample methods: 19437
113
114
  Rehearsal ------------------------------------------------------------
114
- FastMethodSource#comment 1.820000 0.240000 2.060000 ( 2.300117)
115
- MethodSource#comment 77.020000 0.360000 77.380000 ( 94.672830)
116
- -------------------------------------------------- total: 79.440000sec
115
+ FastMethodSource#comment 0.180000 0.170000 0.350000 ( 0.395569)
116
+ MethodSource#comment 19.860000 0.230000 20.090000 ( 36.373289)
117
+ -------------------------------------------------- total: 20.440000sec
117
118
 
118
119
  user system total real
119
- FastMethodSource#comment 1.570000 0.230000 1.800000 ( 1.997811)
120
- MethodSource#comment 71.410000 0.160000 71.570000 ( 79.657388)
120
+ FastMethodSource#comment 0.270000 0.190000 0.460000 ( 0.520414)
121
+ MethodSource#comment 19.360000 0.020000 19.380000 ( 21.726528)
121
122
  ```
122
123
 
123
124
  #### #comment_and_source
@@ -129,9 +130,9 @@ This is a convenience method, and method_source doesn't have it.
129
130
  Processor: Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz
130
131
  Platform: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
131
132
  Counting the number of sample methods...
132
- Sample methods: 18970
133
+ Sample methods: 19435
133
134
  user system total real
134
- FastMethodSource#comment_and_source_for 8.240000 0.750000 8.990000 ( 10.036892)
135
+ FastMethodSource#comment_and_source_for 0.810000 0.420000 1.230000 ( 1.374435)
135
136
  ```
136
137
 
137
138
  ### Correctness Of Output
@@ -163,8 +164,9 @@ expected. Feel free to file issues.
163
164
  ### RAM Consumption
164
165
 
165
166
  The [`comment_and_source`](/benchmarks/comment_and_source_for.rb) benchmark
166
- shows that the library uses about 80-140 MB of RES RAM for computing information
167
- for 19K methods.
167
+ shows that the library uses about 10 MB of RES RAM for computing information for
168
+ 19K methods. I measure with `htop`, manually. If you know a better way to
169
+ measure RAM, please drop a letter here: `silin@kyrylo.org`.
168
170
 
169
171
  API
170
172
  ---
@@ -247,7 +249,8 @@ Limitations
247
249
 
248
250
  ### Rubies
249
251
 
250
- * CRuby 2.2.2
252
+ * CRuby 2.1.x
253
+ * CRuby 2.2.x
251
254
  * CRuby 2.3.0dev and higher
252
255
 
253
256
  Rubies below 2.2.2 were not tested, so in theory if it quacks like Ruby 2, it
@@ -261,13 +264,6 @@ may work.
261
264
  Roadmap
262
265
  -------
263
266
 
264
- ### Further Speed Improvements
265
-
266
- Although Fast Method Source is faster than any of its competitors, it's still
267
- very slow. On average, a mature Rails 4 application has at least 45K
268
- methods. The goal of the project is to be able to query 50K methods in less than
269
- 15 seconds.
270
-
271
267
  ### Optional Memoization
272
268
 
273
269
  I'm not sure about this, if it's really needed, but it will speed up further
@@ -278,6 +274,8 @@ should be optional and configurable like this:
278
274
  FastMethodSource.memoization = true # or `false`
279
275
  ```
280
276
 
277
+ So far I'm happy about the speed of the library.
278
+
281
279
  Licence
282
280
  -------
283
281
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
1
+ 0.4.0
@@ -1,5 +1,7 @@
1
1
  require 'mkmf'
2
2
 
3
- $CFLAGS << ' -std=c99 -Wno-declaration-after-statement -O3'
3
+ $CFLAGS << ' -std=c99 -Wno-declaration-after-statement'
4
+
5
+ have_func('rb_sym2str', 'ruby.h')
4
6
 
5
7
  create_makefile('fast_method_source/fast_method_source')
@@ -3,6 +3,9 @@
3
3
 
4
4
  #include <stdio.h>
5
5
  #include <stdlib.h>
6
+ #include <sys/mman.h>
7
+ #include <sys/stat.h>
8
+ #include <fcntl.h>
6
9
  #include <ruby.h>
7
10
 
8
11
  #include "node.h"
@@ -19,9 +22,28 @@ static const char *null_filename = "/dev/null";
19
22
  #define DUP2(fd, newfd) dup2(fd, newfd)
20
23
  #endif
21
24
 
22
- #define EXPRESSION_SIZE 80 * 50
25
+ #ifndef HAVE_RB_SYM2STR
26
+ # define rb_sym2str(obj) rb_id2str(SYM2ID(obj))
27
+ #endif
23
28
 
24
- #define SAFE_CHAR 'z'
29
+ #ifdef __APPLE__
30
+ void *
31
+ memrchr(const void *s, int c, size_t n)
32
+ {
33
+ const unsigned char *cp;
34
+
35
+ if (n != 0) {
36
+ cp = (unsigned char *)s + n;
37
+ do {
38
+ if (*(--cp) == (unsigned char)c)
39
+ return((void *)cp);
40
+ } while (--n != 0);
41
+ }
42
+ return NULL;
43
+ }
44
+ #else
45
+ void *memrchr(const void *s, int c, size_t n);
46
+ #endif
25
47
 
26
48
  typedef struct {
27
49
  int source : 1;
@@ -39,18 +61,19 @@ static VALUE read_lines_before(struct method_data *data);
39
61
  static VALUE read_lines_after(struct method_data *data);
40
62
  static VALUE find_method_comment(struct method_data *data);
41
63
  static VALUE find_method_source(struct method_data *data);
64
+ static VALUE find_comment_expression(struct method_data *data);
65
+ static VALUE find_source_expression(struct method_data *data);
42
66
  static NODE *parse_expr(VALUE rb_str);
43
67
  static NODE *parse_with_silenced_stderr(VALUE rb_str);
44
- static void filter_interp(char *line);
45
- static int contains_skippables(const char *line);
68
+ static void restore_ch(char *line, char ch, int last_ch_idx);
69
+ static void close_map(int fd, char *map, size_t map_size, const char *filename);
70
+ static void nulify_ch(char *line, char *ch, int last_ch_idx);
46
71
  static int contains_end_kw(const char *line);
47
72
  static int is_comment(const char *line, const size_t line_len);
48
- static int is_static_definition(const char *line);
49
- static int is_accessor(const char *line);
50
- static int is_dangling_literal_end(const char *line);
51
- static int is_dangling_literal_begin(const char *line);
73
+ static int is_definition_end(const char *line);
74
+ static int is_static_definition_start(const char *line);
75
+ static size_t count_prefix_spaces(const char *line);
52
76
  static void raise_if_nil(VALUE val, VALUE method_name);
53
- static void realloc_expression(char **expression, size_t len);
54
77
  static void method_data_init(VALUE self, struct method_data *data);
55
78
  static VALUE mMethodExtensions_source(VALUE self);
56
79
 
@@ -83,118 +106,192 @@ read_lines_before(struct method_data *data)
83
106
  }
84
107
 
85
108
  static VALUE
86
- read_lines(finder finder, struct method_data *data)
109
+ find_comment_expression(struct method_data *data)
87
110
  {
88
- FILE *fp;
111
+ struct stat filestat;
112
+ int fd;
113
+ char *map;
114
+
115
+ VALUE comment = Qnil;
89
116
 
90
- if ((fp = fopen(data->filename, "r")) == NULL) {
91
- rb_raise(rb_eIOError, "No such file or directory - %s", data->filename);
117
+ if ((fd = open(data->filename, O_RDONLY)) == -1) {
118
+ rb_raise(rb_eIOError, "failed to read - %s", data->filename);
92
119
  }
93
120
 
94
- ssize_t cl_len;
95
- VALUE rb_expr;
121
+ if (fstat(fd, &filestat) == -1) {
122
+ rb_raise(rb_eIOError, "filestat failed for %s", data->filename);
123
+ }
124
+
125
+ map = mmap(NULL, filestat.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
126
+ if (map == MAP_FAILED) {
127
+ rb_raise(rb_eIOError, "mmap failed for %s", data->filename);
128
+ }
96
129
 
97
- size_t bufsize, parse_bufsize, future_bufsize, future_parse_bufsize,
98
- current_linebuf_size, line_count;
130
+ char *rest = map;
131
+ unsigned line_count = 0;
99
132
 
100
- bufsize = parse_bufsize = EXPRESSION_SIZE;
101
- line_count = current_linebuf_size = 0;
133
+ while (line_count++ != data->method_location - 1) {
134
+ rest = (char *) memchr(rest, '\n', filestat.st_size) + 1;
135
+ }
102
136
 
103
- int should_parse, dangling_literal, found_expression;
104
- should_parse = dangling_literal = found_expression = 0;
137
+ size_t end = filestat.st_size - strlen(rest);
138
+ map[end] = '\0';
105
139
 
106
- char *expression = ALLOC_N(char, bufsize);
107
- expression[0] = '\0';
140
+ size_t offset = end;
141
+ char *prev = NULL;
108
142
 
109
- char *parse_expression = ALLOC_N(char, bufsize);
110
- parse_expression[0] = '\0';
143
+ while (line_count-- != 0) {
144
+ rest = memrchr(map, '\n', offset - 2);
111
145
 
112
- char *current_line = NULL;
146
+ if (rest == NULL) {
147
+ rest = memrchr(map, '\n', offset);
148
+ } else {
149
+ rest++;
150
+ }
113
151
 
114
- while ((cl_len = getline(&current_line, &current_linebuf_size, fp)) != -1) {
115
- line_count++;
152
+ offset = end - strlen(rest);
116
153
 
117
- if (finder.source && line_count >= data->method_location) {
118
- future_bufsize = strlen(expression) + cl_len;
119
- if (future_bufsize >= bufsize) {
120
- bufsize = future_bufsize + EXPRESSION_SIZE + 1;
121
- realloc_expression(&expression, bufsize);
154
+ if (is_comment(rest, offset)) {
155
+ prev = rest;
156
+ } else {
157
+ if (prev == NULL) {
158
+ comment = rb_str_new("", 0);
159
+ } else {
160
+ comment = rb_str_new2(prev);
122
161
  }
123
- strncat(expression, current_line, cl_len);
124
162
 
125
- if (current_line[0] == '\n' ||
126
- is_comment(current_line, cl_len))
127
- continue;
163
+ break;
164
+ }
165
+ }
166
+
167
+ if (munmap (map, filestat.st_size) == -1) {
168
+ rb_raise(rb_eIOError, "munmap failed for %s", data->filename);
169
+ }
170
+ close(fd);
171
+
172
+ return comment;
173
+ }
174
+
175
+ static VALUE
176
+ find_source_expression(struct method_data *data)
177
+ {
178
+ struct stat filestat;
179
+ int fd;
180
+ char *map;
181
+
182
+ VALUE source = Qnil;
183
+
184
+ if ((fd = open(data->filename, O_RDONLY)) == -1) {
185
+ rb_raise(rb_eIOError, "failed to read - %s", data->filename);
186
+ }
187
+
188
+ if (fstat(fd, &filestat) == -1) {
189
+ rb_raise(rb_eIOError, "filestat failed for %s", data->filename);
190
+ }
191
+
192
+ map = mmap(NULL, filestat.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
193
+ if (map == MAP_FAILED) {
194
+ rb_raise(rb_eIOError, "mmap failed for %s", data->filename);
195
+ }
196
+
197
+ char *expr_start = map;
198
+ char *expr_end, *next_expr, *line;
199
+ unsigned line_count = 0;
200
+
201
+ while (line_count++ != data->method_location - 1) {
202
+ expr_start = (char *) memchr(expr_start, '\n', filestat.st_size) + 1;
203
+ }
204
+
205
+ size_t last_ch_idx;
206
+ char ch, next_ch;
207
+ next_expr = expr_end = expr_start;
208
+ size_t leftover_size = filestat.st_size - strlen(expr_end);
209
+ size_t offset = filestat.st_size - leftover_size;
210
+ size_t next_offset;
211
+ size_t prefix_len = 0;
212
+ int inside_static_def = 0;
213
+ int should_parse = 0;
214
+ VALUE rb_expr;
215
+
216
+ while (offset != 0) {
217
+ next_expr = (char *) memchr(expr_end, '\n', offset) + 1;
218
+ next_offset = strlen(next_expr);
219
+ line = expr_end;
220
+
221
+ last_ch_idx = offset - next_offset - 1;
222
+
223
+ nulify_ch(line, &ch, last_ch_idx);
224
+
225
+ expr_end = next_expr;
226
+ offset = next_offset;
227
+
228
+ if (is_static_definition_start(line) && !inside_static_def) {
229
+ inside_static_def = 1;
230
+ prefix_len = count_prefix_spaces(line);
128
231
 
129
- if (line_count == data->method_location) {
130
- if (is_static_definition(current_line) || is_accessor(current_line)) {
131
- should_parse = 1;
232
+ if (contains_end_kw(line)) {
233
+ if (parse_expr(rb_str_new2(line)) != NULL) {
234
+ restore_ch(line, ch, last_ch_idx);
235
+ rb_expr = rb_str_new2(expr_start);
236
+
237
+ close_map(fd, map, filestat.st_size, data->filename);
238
+ return rb_expr;
132
239
  }
133
240
  }
241
+ }
134
242
 
135
- if (is_dangling_literal_end(current_line)) {
136
- dangling_literal = 0;
137
- } else if (is_dangling_literal_begin(current_line)) {
138
- dangling_literal = 1;
139
- } else if (dangling_literal) {
140
- continue;
141
- }
243
+ if (line[0] == '\n' || is_comment(line, strlen(line))) {
244
+ line[last_ch_idx] = ch;
245
+ continue;
246
+ }
142
247
 
143
- filter_interp(current_line);
144
- future_parse_bufsize = strlen(parse_expression) + cl_len;
145
- if (future_parse_bufsize >= parse_bufsize) {
146
- parse_bufsize = future_parse_bufsize + EXPRESSION_SIZE + 1;
147
- realloc_expression(&parse_expression, parse_bufsize);
248
+ if (inside_static_def) {
249
+ if (is_definition_end(line) &&
250
+ count_prefix_spaces(line) == prefix_len)
251
+ {
252
+ restore_ch(line, ch, last_ch_idx);
253
+ rb_expr = rb_str_new2(expr_start);
254
+
255
+ close_map(fd, map, filestat.st_size, data->filename);
256
+ return rb_expr;
257
+ } else {
258
+ line[last_ch_idx] = ch;
259
+ continue;
148
260
  }
149
- strncat(parse_expression, current_line, cl_len);
261
+ } else {
262
+ should_parse = 1;
263
+ }
150
264
 
151
- if (contains_skippables(current_line))
152
- continue;
265
+ if (should_parse) {
266
+ line[last_ch_idx] = ch;
267
+ nulify_ch(line, &next_ch, last_ch_idx + 1);
153
268
 
154
- if (should_parse || contains_end_kw(current_line)) {
155
- if (parse_expr(rb_str_new2(parse_expression)) != NULL) {
156
- found_expression = 1;
157
- break;
158
- }
159
- }
160
- } else if (finder.comment) {
161
- if (line_count < data->method_location) {
162
- if (is_comment(current_line, cl_len)) {
163
- future_bufsize = strlen(expression) + cl_len;
164
- if (future_bufsize >= bufsize) {
165
- bufsize = future_bufsize + EXPRESSION_SIZE + 1;
166
- realloc_expression(&expression, bufsize);
167
- }
168
- strncat(expression, current_line, cl_len);
169
- } else {
170
- expression[0] = '\0';
171
- bufsize = EXPRESSION_SIZE;
172
- }
173
- } else if (line_count == data->method_location) {
174
- found_expression = 1;
175
- break;
269
+ if (parse_expr(rb_str_new2(expr_start)) != NULL) {
270
+ rb_expr = rb_str_new2(expr_start);
271
+ close_map(fd, map, filestat.st_size, data->filename);
272
+ return rb_expr;
273
+ } else {
274
+ line[last_ch_idx+1] = next_ch;
176
275
  }
177
276
  }
178
- }
179
277
 
180
- if (found_expression) {
181
- rb_expr = rb_str_new2(expression);
182
- } else {
183
- rb_expr = Qnil;
278
+ line[last_ch_idx] = ch;
184
279
  }
280
+ close_map(fd, map, filestat.st_size, data->filename);
185
281
 
186
- xfree(parse_expression);
187
- xfree(expression);
188
- free(current_line);
189
- fclose(fp);
190
- return (rb_expr);
282
+ return source;
191
283
  }
192
284
 
193
- static void
194
- realloc_expression(char **expression, size_t len)
285
+ static VALUE
286
+ read_lines(finder finder, struct method_data *data)
195
287
  {
196
- char *tmp_comment = REALLOC_N(*expression, char, len);
197
- *expression = tmp_comment;
288
+ if (finder.comment) {
289
+ return find_comment_expression(data);
290
+ } else if (finder.source) {
291
+ return find_source_expression(data);
292
+ }
293
+
294
+ return Qnil;
198
295
  }
199
296
 
200
297
  static NODE *
@@ -228,52 +325,59 @@ parse_expr(VALUE rb_str) {
228
325
  }
229
326
 
230
327
  static void
231
- filter_interp(char *line)
328
+ restore_ch(char *line, char ch, int last_ch_idx)
232
329
  {
233
- int brackets = 0;
330
+ line[last_ch_idx] = ch;
331
+ line[last_ch_idx + 1] = '\0';
332
+ }
234
333
 
235
- for (int i = 0; line[i] != '\0'; i++) {
236
- if (line[i] == '#') {
237
- if (line[i + 1] == '{') {
238
- brackets++;
334
+ static void
335
+ close_map(int fd, char *map, size_t map_size, const char *filename)
336
+ {
337
+ close(fd);
338
+ if (munmap(map, map_size) == -1) {
339
+ rb_raise(rb_eIOError, "munmap failed for %s", filename);
340
+ }
341
+ }
239
342
 
240
- line[i] = SAFE_CHAR;
343
+ static void
344
+ nulify_ch(char *line, char *ch, int last_ch_idx)
345
+ {
346
+ *ch = line[last_ch_idx];
347
+ line[last_ch_idx] = '\0';
348
+ }
241
349
 
242
- if (line[i - 1] == '\\')
243
- line[i - 1] = SAFE_CHAR;
244
- }
350
+ static size_t
351
+ count_prefix_spaces(const char *line)
352
+ {
353
+ int i = 0;
354
+ size_t spaces = 0;
355
+
356
+ do {
357
+ if (line[i] == ' ') {
358
+ spaces++;
359
+ } else {
360
+ break;
245
361
  }
362
+ } while (line[i++] != '\n');
246
363
 
247
- if (line[i] == '}') {
248
- brackets--;
249
-
250
- if (brackets == 0) {
251
- line[i] = SAFE_CHAR;
252
- }
253
- } else if (brackets > 0) {
254
- line[i] = SAFE_CHAR;
255
- }
256
- }
364
+ return spaces;
257
365
  }
258
366
 
259
367
  static int
260
- contains_skippables(const char *line)
368
+ is_definition_end(const char *line)
261
369
  {
370
+ int i = 0;
262
371
 
263
- static unsigned short len = 57;
264
- static const char *skippables[57] = {
265
- " if ", " else ", " then ", " case ", " for ", " in ", " loop ",
266
- " unless ", "||", "||=", "&&", " and ", " or ", " do ", " not ",
267
- " while ", " = ", " == ", " === ", " > ", " < ", " >= ", " <= ",
268
- " << ", " += ", "\"", "'", ":", ",", ".", " % ", "!", "?",
269
- " until ", "(&", "|", "(", ")", "~", " * ", " - ", " + ", " / ",
270
- " {", " raise ", " fail ", " begin ", " rescue ", " ensure ",
271
- ".new", "@", " lambda", " proc", " ->", "[", "]", "$"};
272
-
273
- for (unsigned short i = 0; i < len; i++) {
274
- if (strstr(line, skippables[i]) != NULL)
372
+ do {
373
+ if (line[i] == ' ') {
374
+ continue;
375
+ } else if (strncmp((line + i), "end", 3) == 0) {
275
376
  return 1;
276
- }
377
+ } else {
378
+ return 0;
379
+ }
380
+ } while (line[i++] != '\0');
277
381
 
278
382
  return 0;
279
383
  }
@@ -292,20 +396,13 @@ contains_end_kw(const char *line)
292
396
  }
293
397
  }
294
398
 
295
- static int
296
- is_accessor(const char *line)
297
- {
298
- return strstr(line, "attr_reader") != NULL ||
299
- strstr(line, "attr_writer") != NULL ||
300
- strstr(line, "attr_accessor") != NULL;
301
- }
302
-
303
399
  static int
304
400
  is_comment(const char *line, const size_t line_len)
305
401
  {
306
402
  for (size_t i = 0; i < line_len; i++) {
307
403
  if (line[i] == ' ')
308
404
  continue;
405
+
309
406
  return line[i] == '#' && line[i + 1] != '{';
310
407
  }
311
408
 
@@ -313,29 +410,36 @@ is_comment(const char *line, const size_t line_len)
313
410
  }
314
411
 
315
412
  static int
316
- is_static_definition(const char *line)
413
+ is_static_definition_start(const char *line)
317
414
  {
318
- return strstr(line, " def ") != NULL || strncmp(line, "def ", 4);
319
- }
415
+ int i = 0;
320
416
 
321
- static int
322
- is_dangling_literal_end(const char *line)
323
- {
324
- return strstr(line, "}") != NULL && strstr(line, "{") == NULL;
325
- }
417
+ do {
418
+ if (line[i] == ' ') {
419
+ continue;
420
+ } else if (strncmp((line + i), "def ", 4) == 0) {
421
+ return 1;
422
+ } else if (strncmp((line + i), "class ", 6) == 0) {
423
+ return 1;
424
+ } else {
425
+ return 0;
426
+ }
427
+ } while (line[i++] != '\0');
326
428
 
327
- static int
328
- is_dangling_literal_begin(const char *line)
329
- {
330
- return strstr(line, "%{") != NULL && strstr(line, "}") == NULL;
429
+ return 0;
331
430
  }
332
431
 
333
432
  static void
334
433
  raise_if_nil(VALUE val, VALUE method_name)
335
434
  {
336
435
  if (NIL_P(val)) {
337
- rb_raise(rb_eSourceNotFoundError, "could not locate source for %s",
338
- RSTRING_PTR(rb_sym2str(method_name)));
436
+ if (SYMBOL_P(method_name)) {
437
+ rb_raise(rb_eSourceNotFoundError, "could not locate source for %s",
438
+ RSTRING_PTR(rb_sym2str(method_name)));
439
+ } else {
440
+ rb_raise(rb_eSourceNotFoundError, "could not locate source for %s",
441
+ RSTRING_PTR(method_name));
442
+ }
339
443
  }
340
444
  }
341
445
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fast_method_source
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kyrylo Silin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-11 00:00:00.000000000 Z
11
+ date: 2015-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.9'
19
+ version: '1.0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.9'
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement