{Task} = require 'atom'
ctags = require 'ctags'
async = require 'async'
getTagsFile = require "./get-tags-file"

handlerPath = require.resolve './load-tags-handler'

module.exports =
  find: (editor, callback) ->
    symbol = editor.getSelectedText()

    unless symbol
      cursor = editor.getLastCursor()
      scopes = cursor.getScopeDescriptor().getScopesArray()
      rubyScopes = scopes.filter (scope) -> /^source\.ruby($|\.)/.test(scope)
      wordRegex = /[a-zA-Z_][\w!?]*/g if rubyScopes.length

      range = cursor.getCurrentWordBufferRange({wordRegex})
      symbol = editor.getTextInRange(range)

    unless symbol
      return process.nextTick -> callback(null, [])

    allTags = []

    async.each(
      atom.project.getPaths(),
      (projectPath, done) ->
        tagsFile = getTagsFile(projectPath)
        return done() unless tagsFile?
        ctags.findTags tagsFile, symbol, (err, tags=[]) ->
          tag.directory = projectPath for tag in tags
          allTags = allTags.concat(tags)
          done(err)
      (err) -> callback(err, allTags)
    )

  getAllTags: (callback) ->
    projectTags = []
    task = Task.once handlerPath, atom.project.getPaths(), -> callback(projectTags)
    task.on 'tags', (tags) -> projectTags.push(tags...)
    task

{Task} = require 'atom'
ctags = require 'ctags'
async = require 'async'
getTagsFile = require "./get-tags-file"

handlerPath = require.resolve './load-tags-handler'

module.exports =
  find: (editor, callback) ->
    symbol = editor.getSelectedText()

    unless symbol
      cursor = editor.getLastCursor()
      scopes = cursor.getScopeDescriptor().getScopesArray()
      rubyScopes = scopes.filter (scope) -> /^source\.ruby($|\.)/.test(scope)
      wordRegex = /[\w!?]*/g if rubyScopes.length

      range = cursor.getCurrentWordBufferRange({wordRegex})
      symbol = editor.getTextInRange(range)

    unless symbol
      return process.nextTick -> callback(null, [])

    allTags = []

    async.each(
      atom.project.getPaths(),
      (projectPath, done) ->
        tagsFile = getTagsFile(projectPath)
        return done() unless tagsFile?
        ctags.findTags tagsFile, symbol, (err, tags=[]) ->
          tag.directory = projectPath for tag in tags
          allTags = allTags.concat(tags)
          done(err)
      (err) -> callback(err, allTags)
    )

  getAllTags: (callback) ->
    projectTags = []
    task = Task.once handlerPath, atom.project.getPaths(), -> callback(projectTags)
    task.on 'tags', (tags) -> projectTags.push(tags...)
    task

Fix go-to-declaration for various cursor position within Ruby identifier
Fix go-to-declaration for various cursor position within Ruby identifier

Even though technically the Ruby "word" can only start with a letter or
underscore, in practice it's not a good idea to define such regexp here,
because due to Atom's implementation of `editor.scanInBufferRange`, the
"word" under cursor will be looked up twice: once considering everything
up to the cursor position, and the second time considering everything
from the cursor position to the end of file.

So, if the cursor was positioned between "c" and "!" in `abc!`
identifier, the go-to-declaration for `abc!` symbol would fail.
