fast_method_source 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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