diff --git a/package.json b/package.json index 8cca44bf7..fa8844a92 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "deprecation-cop": "0.53.0", "dev-live-reload": "0.46.0", "encoding-selector": "0.20.0", - "exception-reporting": "0.25.0", + "exception-reporting": "0.31.0", "find-and-replace": "0.174.1", "fuzzy-finder": "0.87.0", "git-diff": "0.55.0", @@ -103,7 +103,7 @@ "link": "0.30.0", "markdown-preview": "0.150.0", "metrics": "0.51.0", - "notifications": "0.56.0", + "notifications": "0.57.0", "open-on-github": "0.37.0", "package-generator": "0.39.0", "release-notes": "0.53.0", diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index 99a7f432e..d2d1d68ae 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -127,6 +127,39 @@ describe "the `atom` global", -> column: 3 originalError: error + describe ".assert(condition, message, metadata)", -> + errors = null + + beforeEach -> + errors = [] + atom.onDidFailAssertion (error) -> errors.push(error) + + describe "if the condition is false", -> + it "notifies onDidFailAssertion handlers with an error object based on the call site of the assertion", -> + result = atom.assert(false, "a == b") + expect(result).toBe false + expect(errors.length).toBe 1 + expect(errors[0].message).toBe "Assertion failed: a == b" + expect(errors[0].stack).toContain('atom-spec') + + describe "if metadata is an object", -> + it "assigns the object on the error as `metadata`", -> + metadata = {foo: 'bar'} + atom.assert(false, "a == b", metadata) + expect(errors[0].metadata).toBe metadata + + describe "if metadata is a function", -> + it "assigns the function's return value on the error as `metadata`", -> + metadata = {foo: 'bar'} + atom.assert(false, "a == b", -> metadata) + expect(errors[0].metadata).toBe metadata + + describe "if the condition is true", -> + it "does nothing", -> + result = atom.assert(true, "a == b") + expect(result).toBe true + expect(errors).toEqual [] + describe "saving and loading", -> afterEach -> atom.mode = "spec" diff --git a/src/atom.coffee b/src/atom.coffee index 316c51e29..03525df68 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -333,6 +333,12 @@ class Atom extends Model onDidThrowError: (callback) -> @emitter.on 'did-throw-error', callback + # TODO: Make this part of the public API. We should make onDidThrowError + # match the interface by only yielding an exception object to the handler + # and deprecating the old behavior. + onDidFailAssertion: (callback) -> + @emitter.on 'did-fail-assertion', callback + ### Section: Atom Details ### @@ -715,6 +721,22 @@ class Atom extends Model Section: Private ### + assert: (condition, message, metadata) -> + return true if condition + + error = new Error("Assertion failed: #{message}") + Error.captureStackTrace(error, @assert) + + if metadata? + if typeof metadata is 'function' + error.metadata = metadata() + else + error.metadata = metadata + + @emitter.emit 'did-fail-assertion', error + + false + deserializeProject: -> Project = require './project' diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index c764c1a1f..5919841f5 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -292,7 +292,17 @@ class TokenizedBuffer extends Model # Returns a {Boolean} indicating whether the given buffer row starts # a a foldable row range due to the code's indentation patterns. isFoldableCodeAtRow: (row) -> - return false if @buffer.isRowBlank(row) or @tokenizedLineForRow(row).isComment() + # Investigating an exception that's occurring here due to the line being + # undefined. This should paper over the problem but we want to figure out + # what is happening: + tokenizedLine = @tokenizedLineForRow(row) + atom.assert tokenizedLine?, "TokenizedLine is defined", => + metadata: + row: row + rowCount: @tokenizedLines.length + return false unless tokenizedLine? + + return false if @buffer.isRowBlank(row) or tokenizedLine.isComment() nextRow = @buffer.nextNonBlankRow(row) return false unless nextRow?