Buffers are memoized on project by path

This commit is contained in:
Corey Johnson & Nathan Sobo 2012-07-18 12:49:18 -07:00
parent 72750fd4a2
commit b959d5aa37
5 changed files with 54 additions and 34 deletions

View File

@ -11,11 +11,11 @@ describe 'Buffer', ->
buffer = new Buffer(filePath)
afterEach ->
buffer?.destroy()
buffer?.release()
describe 'constructor', ->
beforeEach ->
buffer.destroy()
buffer.release()
describe "when given a path", ->
describe "when a file exists for the path", ->
@ -56,8 +56,8 @@ describe 'Buffer', ->
beforeEach ->
path = "/tmp/tmp.txt"
fs.write(path, "first")
buffer.destroy()
buffer = new Buffer(path)
buffer.release()
buffer = new Buffer(path).retain()
afterEach ->
fs.remove(path)
@ -99,7 +99,7 @@ describe 'Buffer', ->
it "returns false after modified buffer is saved", ->
filePath = "/tmp/atom-tmp-file"
fs.write(filePath, '')
buffer.destroy()
buffer.release()
buffer = new Buffer(filePath)
expect(buffer.isModified()).toBe false
@ -243,7 +243,7 @@ describe 'Buffer', ->
describe ".save()", ->
beforeEach ->
buffer.destroy()
buffer.release()
describe "when the buffer has a path", ->
filePath = null
@ -283,33 +283,34 @@ describe 'Buffer', ->
expect(-> buffer.save()).toThrow()
describe ".saveAs(path)", ->
filePath = null
[filePath, saveAsBuffer] = []
beforeEach ->
buffer.destroy()
afterEach ->
saveAsBuffer.release()
it "saves the contents of the buffer to the path", ->
filePath = '/tmp/temp.txt'
fs.remove filePath if fs.exists(filePath)
buffer = new Buffer()
saveAsBuffer = new Buffer().retain()
eventHandler = jasmine.createSpy('eventHandler')
buffer.on 'path-change', eventHandler
saveAsBuffer.on 'path-change', eventHandler
buffer.setText 'Buffer contents!'
buffer.saveAs(filePath)
saveAsBuffer.setText 'Buffer contents!'
saveAsBuffer.saveAs(filePath)
expect(fs.read(filePath)).toEqual 'Buffer contents!'
expect(eventHandler).toHaveBeenCalledWith(buffer)
expect(eventHandler).toHaveBeenCalledWith(saveAsBuffer)
it "stops listening to events on previous path and begins listening to events on new path", ->
originalPath = "/tmp/original.txt"
newPath = "/tmp/new.txt"
fs.write(originalPath, "")
buffer = new Buffer(originalPath)
saveAsBuffer = new Buffer(originalPath).retain()
changeHandler = jasmine.createSpy('changeHandler')
buffer.on 'change', changeHandler
buffer.saveAs(newPath)
saveAsBuffer.on 'change', changeHandler
saveAsBuffer.saveAs(newPath)
expect(changeHandler).not.toHaveBeenCalled()
fs.write(originalPath, "should not trigger buffer event")

View File

@ -13,18 +13,14 @@ describe "Project", ->
it "removes edit session and calls destroy on buffer (if buffer is not referenced by other edit sessions)", ->
editSession = project.buildEditSessionForPath("a")
anotherEditSession = project.buildEditSessionForPath("a")
buffer = editSession.buffer
spyOn(buffer, 'destroy').andCallThrough()
expect(project.editSessions.length).toBe 2
expect(editSession.buffer).toBe anotherEditSession.buffer
editSession.destroy()
expect(buffer.destroy).not.toHaveBeenCalled()
expect(project.editSessions.length).toBe 1
anotherEditSession.destroy()
expect(buffer.destroy).toHaveBeenCalled()
expect(project.editSessions.length).toBe 0
describe ".buildEditSessionForPath(path)", ->
@ -66,6 +62,20 @@ describe "Project", ->
expect(newBufferHandler).toHaveBeenCalledWith(editSession.buffer)
expect(newEditSessionHandler).toHaveBeenCalledWith editSession
describe ".bufferForPath(path)", ->
describe "when opening a previously opened path", ->
it "does not create a new buffer", ->
buffer = project.bufferForPath("a").retain()
expect(project.bufferForPath("a")).toBe buffer
alternativeBuffer = project.bufferForPath("b").retain().release()
expect(alternativeBuffer).not.toBe buffer
buffer.release()
it "creates a new buffer if the previous buffer was destroyed", ->
buffer = project.bufferForPath("a").retain().release()
expect(project.bufferForPath("a").retain().release()).not.toBe buffer
describe ".resolve(path)", ->
it "returns an absolute path based on the project's root", ->
absolutePath = require.resolve('fixtures/dir/a')

View File

@ -26,6 +26,7 @@ afterEach ->
$('#jasmine-content').empty()
document.title = defaultTitle
ensureNoPathSubscriptions()
window.fixturesProject.destroy()
window.keymap.bindKeys '*', 'meta-w': 'close'
$(document).on 'close', -> window.close()

View File

@ -20,7 +20,7 @@ class Buffer
anchorRanges: null
refcount: 0
constructor: (path) ->
constructor: (path, @project) ->
@id = @constructor.idCounter++
@anchors = []
@anchorRanges = []
@ -38,8 +38,9 @@ class Buffer
destroy: ->
throw new Error("Destroying buffer twice with path '#{@getPath()}'") if @destroyed
@destroyed = true
@file?.off()
@destroyed = true
@project?.removeBuffer(this)
retain: ->
@refcount++
@ -50,6 +51,12 @@ class Buffer
@destroy() if @refcount <= 0
this
subscribeToFile: ->
@file?.on "contents-change", =>
unless @isModified()
@setText(fs.read(@file.getPath()))
@modified = false
getPath: ->
@file?.getPath()
@ -58,10 +65,7 @@ class Buffer
@file?.off()
@file = new File(path)
@file.on "contents-change", =>
unless @isModified()
@setText(fs.read(@file.getPath()))
@modified = false
@subscribeToFile()
@trigger "path-change", this
getExtension: ->

View File

@ -21,7 +21,7 @@ class Project
constructor: (path) ->
@setPath(path)
@editSessions = []
@buffer = []
@buffers = []
@setTabText(' ')
@setAutoIndent(true)
@setSoftTabs(true)
@ -30,6 +30,9 @@ class Project
/(^|\/)\.git(\/|$)/
]
destroy: ->
editSession.destroy() for editSession in @getEditSessions()
getPath: ->
@rootDirectory?.path
@ -106,9 +109,6 @@ class Project
getEditSessions: ->
new Array(@editSessions...)
destroy: ->
editSession.destroy() for editSession in @getEditSessions()
removeEditSession: (editSession) ->
_.remove(@editSessions, editSession)
@ -122,16 +122,20 @@ class Project
bufferForPath: (filePath) ->
if filePath?
filePath = @resolve(filePath)
return editSession.buffer for editSession in @editSessions when editSession.buffer.getPath() == filePath
@buildBuffer(filePath)
buffer = _.find @buffers, (buffer) -> buffer.getPath() == filePath
buffer or @buildBuffer(filePath)
else
@buildBuffer()
buildBuffer: (filePath) ->
buffer = new Buffer(filePath)
buffer = new Buffer(filePath, this)
@buffers.push buffer
@trigger 'new-buffer', buffer
buffer
removeBuffer: (buffer) ->
_.remove(@buffers, buffer)
scan: (regex, iterator) ->
regex = new RegExp(regex.source, 'g')
commands = [