<commit_before>path = require 'path'
_ = require 'underscore-plus'
{convertStackTrace} = require 'coffeestack'
{View, $, $$} = require '../src/space-pen-extensions'
grim = require 'grim'
marked = require 'marked'

sourceMaps = {}
formatStackTrace = (spec, message='', stackTrace) ->
  return stackTrace unless stackTrace

  jasminePattern = /^\s*at\s+.*\(?.*[/\\]jasmine(-[^/\\]*)?\.js:\d+:\d+\)?\s*$/
  firstJasmineLinePattern = /^\s*at [/\\].*[/\\]jasmine(-[^/\\]*)?\.js:\d+:\d+\)?\s*$/
  convertedLines = []
  for line in stackTrace.split('\n')
    convertedLines.push(line) unless jasminePattern.test(line)
    break if firstJasmineLinePattern.test(line)

  stackTrace = convertStackTrace(convertedLines.join('\n'), sourceMaps)
  lines = stackTrace.split('\n')

  # Remove first line of stack when it is the same as the error message
  errorMatch = lines[0]?.match(/^Error: (.*)/)
  lines.shift() if message.trim() is errorMatch?[1]?.trim()

  for line, index in lines
    # Remove prefix of lines matching: at [object Object].<anonymous> (path:1:2)
    prefixMatch = line.match(/at \[object Object\]\.<anonymous> \(([^)]+)\)/)
    line = "at #{prefixMatch[1]}" if prefixMatch

    # Relativize locations to spec directory
    lines[index] = line.replace("at #{spec.specDirectory}#{path.sep}", 'at ')

  lines = lines.map (line) -> line.trim()
  lines.join('\n').trim()

module.exports =
class AtomReporter extends View
  @content: ->
    @div class: 'spec-reporter', =>
      @div class: 'padded pull-right', =>
        @button outlet: 'reloadButton', class: 'btn btn-small reload-button', 'Reload Specs'
      @div outlet: 'coreArea', class: 'symbol-area', =>
        @div outlet: 'coreHeader', class: 'symbol-header'
        @ul outlet: 'coreSummary', class: 'symbol-summary list-unstyled'
      @div outlet: 'bundledArea', class: 'symbol-area', =>
        @div outlet: 'bundledHeader', class: 'symbol-header'
        @ul outlet: 'bundledSummary', class: 'symbol-summary list-unstyled'
      @div outlet: 'userArea', class: 'symbol-area', =>
        @div outlet: 'userHeader', class: 'symbol-header'
        @ul outlet: 'userSummary', class: 'symbol-summary list-unstyled'
      @div outlet: "status", class: 'status alert alert-info', =>
        @div outlet: "time", class: 'time'
        @div outlet: "specCount", class: 'spec-count'
        @div outlet: "message", class: 'message'
      @div outlet: "results", class: 'results'

      @div outlet: "deprecations", class: 'status alert alert-warning', style: 'display: none', =>
        @span outlet: 'deprecationStatus', '0 deprecations'
        @div class: 'deprecation-toggle'
      @div outlet: 'deprecationList', class: 'deprecation-list'

  startedAt: null
  runningSpecCount: 0
  completeSpecCount: 0
  passedCount: 0
  failedCount: 0
  skippedCount: 0
  totalSpecCount: 0
  deprecationCount: 0
  @timeoutId: 0

  reportRunnerStarting: (runner) ->
    @handleEvents()
    @startedAt = Date.now()
    specs = runner.specs()
    @totalSpecCount = specs.length
    @addSpecs(specs)
    $(document.body).append this

    @on 'click', '.stack-trace', ->
      $(this).toggleClass('expanded')

    @reloadButton.on 'click', -> require('ipc').send('call-window-method', 'restart')

  reportRunnerResults: (runner) ->
    @updateSpecCounts()
    @status.addClass('alert-success').removeClass('alert-info') if @failedCount is 0
    if @failedCount is 1
      @message.text "#{@failedCount} failure"
    else
      @message.text "#{@failedCount} failures"

  reportSuiteResults: (suite) ->

  reportSpecResults: (spec) ->
    @completeSpecCount++
    spec.endedAt = Date.now()
    @specComplete(spec)
    @updateStatusView(spec)

  reportSpecStarting: (spec) ->
    @specStarted(spec)

  addDeprecations: (spec) ->
    deprecations = grim.getDeprecations()
    @deprecationCount += deprecations.length
    @deprecations.show() if @deprecationCount > 0
    if @deprecationCount is 1
      @deprecationStatus.text("1 deprecation")
    else
      @deprecationStatus.text("#{@deprecationCount} deprecations")

    for deprecation in deprecations
      @deprecationList.append $$ ->
        @div class: 'padded', =>
          @div class: 'result-message fail deprecation-message', =>
            @raw marked(deprecation.message)

          for stack in deprecation.stacks
            fullStack = stack.map ({functionName, location}) ->
              if functionName is '<unknown>'
                "  at #{location}"
              else
                "  at #{functionName} (#{location})"
            @pre class: 'stack-trace padded', formatStackTrace(spec, deprecation.message, fullStack.join('\n'))
    grim.clearDeprecations()

  handleEvents: -><commit_msg>Fix deprecation location reporting in spec runner<commit_after>path = require 'path'
_ = require 'underscore-plus'
{convertStackTrace} = require 'coffeestack'
{View, $, $$} = require '../src/space-pen-extensions'
grim = require 'grim'
marked = require 'marked'

sourceMaps = {}
formatStackTrace = (spec, message='', stackTrace) ->
  return stackTrace unless stackTrace

  jasminePattern = /^\s*at\s+.*\(?.*[/\\]jasmine(-[^/\\]*)?\.js:\d+:\d+\)?\s*$/
  firstJasmineLinePattern = /^\s*at [/\\].*[/\\]jasmine(-[^/\\]*)?\.js:\d+:\d+\)?\s*$/
  convertedLines = []
  for line in stackTrace.split('\n')
    convertedLines.push(line) unless jasminePattern.test(line)
    break if firstJasmineLinePattern.test(line)

  stackTrace = convertStackTrace(convertedLines.join('\n'), sourceMaps)
  lines = stackTrace.split('\n')

  # Remove first line of stack when it is the same as the error message
  errorMatch = lines[0]?.match(/^Error: (.*)/)
  lines.shift() if message.trim() is errorMatch?[1]?.trim()

  for line, index in lines
    # Remove prefix of lines matching: at [object Object].<anonymous> (path:1:2)
    prefixMatch = line.match(/at \[object Object\]\.<anonymous> \(([^)]+)\)/)
    line = "at #{prefixMatch[1]}" if prefixMatch

    # Relativize locations to spec directory
    lines[index] = line.replace("at #{spec.specDirectory}#{path.sep}", 'at ')

  lines = lines.map (line) -> line.trim()
  lines.join('\n').trim()

module.exports =
class AtomReporter extends View
  @content: ->
    @div class: 'spec-reporter', =>
      @div class: 'padded pull-right', =>
        @button outlet: 'reloadButton', class: 'btn btn-small reload-button', 'Reload Specs'
      @div outlet: 'coreArea', class: 'symbol-area', =>
        @div outlet: 'coreHeader', class: 'symbol-header'
        @ul outlet: 'coreSummary', class: 'symbol-summary list-unstyled'
      @div outlet: 'bundledArea', class: 'symbol-area', =>
        @div outlet: 'bundledHeader', class: 'symbol-header'
        @ul outlet: 'bundledSummary', class: 'symbol-summary list-unstyled'
      @div outlet: 'userArea', class: 'symbol-area', =>
        @div outlet: 'userHeader', class: 'symbol-header'
        @ul outlet: 'userSummary', class: 'symbol-summary list-unstyled'
      @div outlet: "status", class: 'status alert alert-info', =>
        @div outlet: "time", class: 'time'
        @div outlet: "specCount", class: 'spec-count'
        @div outlet: "message", class: 'message'
      @div outlet: "results", class: 'results'

      @div outlet: "deprecations", class: 'status alert alert-warning', style: 'display: none', =>
        @span outlet: 'deprecationStatus', '0 deprecations'
        @div class: 'deprecation-toggle'
      @div outlet: 'deprecationList', class: 'deprecation-list'

  startedAt: null
  runningSpecCount: 0
  completeSpecCount: 0
  passedCount: 0
  failedCount: 0
  skippedCount: 0
  totalSpecCount: 0
  deprecationCount: 0
  @timeoutId: 0

  reportRunnerStarting: (runner) ->
    @handleEvents()
    @startedAt = Date.now()
    specs = runner.specs()
    @totalSpecCount = specs.length
    @addSpecs(specs)
    $(document.body).append this

    @on 'click', '.stack-trace', ->
      $(this).toggleClass('expanded')

    @reloadButton.on 'click', -> require('ipc').send('call-window-method', 'restart')

  reportRunnerResults: (runner) ->
    @updateSpecCounts()
    @status.addClass('alert-success').removeClass('alert-info') if @failedCount is 0
    if @failedCount is 1
      @message.text "#{@failedCount} failure"
    else
      @message.text "#{@failedCount} failures"

  reportSuiteResults: (suite) ->

  reportSpecResults: (spec) ->
    @completeSpecCount++
    spec.endedAt = Date.now()
    @specComplete(spec)
    @updateStatusView(spec)

  reportSpecStarting: (spec) ->
    @specStarted(spec)

  addDeprecations: (spec) ->
    deprecations = grim.getDeprecations()
    @deprecationCount += deprecations.length
    @deprecations.show() if @deprecationCount > 0
    if @deprecationCount is 1
      @deprecationStatus.text("1 deprecation")
    else
      @deprecationStatus.text("#{@deprecationCount} deprecations")

    for deprecation in deprecations
      @deprecationList.append $$ ->
        @div class: 'padded', =>
          @div class: 'result-message fail deprecation-message', =>
            @raw marked(deprecation.message)

          for stack in deprecation.getStacks()
            fullStack = stack.map ({functionName, location}) ->
              if functionName is '<unknown>'
                "  at #{location}"
              else
                "  at #{functionName} (#{location})"
            @pre class: 'stack-trace padded', formatStackTrace(spec, deprecation.message, fullStack.join('\n'))
    grim.clearDeprecations()

  handleEvents: ->
{'fraction_non_alphanumeric': 0.16059165346011622, 'fraction_numerical': 0.004014791336502906, 'mean_word_length': 3.3441945846718677, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5417212', 'n_tokens_mistral': 3103, 'n_tokens_neox': 2945, 'n_words': 716}