Skip to content

Commit

Permalink
Non-reactive RuleSet file matching
Browse files Browse the repository at this point in the history
  • Loading branch information
andreyvit committed Dec 5, 2012
1 parent a352c77 commit f5d0bda
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 37 deletions.
16 changes: 15 additions & 1 deletion lib/projects/project.iced
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ abspath = (path) ->
Path.resolve(path)


class Rule_Project

schema:
project: { type: Object }

'get files': ->
for path in @project.tree.findMatchingPaths(@action.compiler.sourceFilter)
@project.fileAt(path)


class Project extends R.Model

schema:
Expand Down Expand Up @@ -69,6 +79,10 @@ class Project extends R.Model

compilableFilesFilter: { computed: yes }

_mixins: [
[require('../rules/rule').FileToFileRule, [Rule_Project]]
]


initialize: ({ @session, @vfs, @path }) ->
@name = Path.basename(@path)
Expand All @@ -86,7 +100,7 @@ class Project extends R.Model
actions =
for compiler in @session.pluginManager?.allCompilers or []
new CompilationAction(compiler)
@ruleSet = new RuleSet(actions)
@ruleSet = @universe.create(RuleSet, { actions, project: this })

await @watcher.on 'complete', defer()
debug "Tree scan complete for #{@fullPath}"
Expand Down
4 changes: 2 additions & 2 deletions lib/rules/rule.iced
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ R = require 'reactive'

class Rule extends R.Model

constructor: (@action, info) ->
@setInfo(info)
initialize: (options) ->
@setInfo(options)

memento: ->
memento = @getInfo()
Expand Down
5 changes: 3 additions & 2 deletions lib/rules/ruleset.iced
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ module.exports =
class RuleSet extends R.Model

schema:
project: { type: Object }
rules: { type: Array }

constructor: (@actions) ->
initialize: ({ @actions }) ->
@rules = @createDefaultRules()

setMemento: (memento) ->
Expand All @@ -25,7 +26,7 @@ class RuleSet extends R.Model
createRule: (action, info) ->
# TODO: check that action is one of @actions
ruleClass = @_getRuleClassForAction(action)
return new ruleClass(action, info)
return @universe.create(ruleClass, _.extend({}, { action, @project }, info))

addRule: (action, info) ->
@rules.push @createRule(action, info)
Expand Down
1 change: 1 addition & 0 deletions lib/session.iced
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ R = require 'reactive'

JobQueue = require 'jobqueue'


class Session extends R.Model

schema:
Expand Down
114 changes: 87 additions & 27 deletions test/project_test.iced
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ assert = require 'assert'
Path = require 'path'
fs = require 'fs'
R = require 'reactive'
scopedfs = require 'scopedfs'
{RelPathList} = require 'pathspec'
JobQueue = require 'jobqueue'

{ ok, equal, deepEqual } = require 'assert'

{ EventEmitter } = require 'events'

{ R, Project } = require "../#{process.env.JSLIB or 'lib'}/session"
{ Session, R, Project } = require "../#{process.env.JSLIB or 'lib'}/session"
TestVFS = require 'vfs-test'

DataDir = Path.join(__dirname, 'data')
Expand All @@ -17,44 +20,44 @@ readMementoSync = (name) -> JSON.parse(fs.readFileSync(Path.join(DataDir, name),
class FakeSession
constructor: ->
@plugins = []
@queue =
register: ->
add: ->
once: ->
after: (func) -> process.nextTick func
@queue = new JobQueue()

@pluginManager =
allCompilers: []

after: (func) -> process.nextTick func
after: (func, description) ->
@queue.after (=> process.nextTick func), description

findCompilerById: (compilerId) ->
{ id: compilerId }


describe "Project", ->

it "should report basic info about itself", ->
it "should report basic info about itself", (done) ->
vfs = new TestVFS()
session = new FakeSession()

universe = new R.Universe()
project = universe.create(Project, { session, vfs, path: "/foo/bar" })
assert.equal project.name, 'bar'
assert.equal project.path, '/foo/bar'
assert.ok project.id =~ /^P\d+_bar$/
assert.ok project.id.match /^P\d+_bar$/
project.once 'complete', done


it "should be able to load an empty memento", ->
it "should be able to load an empty memento", (done) ->
vfs = new TestVFS()
session = new FakeSession()

universe = new R.Universe()
project = universe.create(Project, { session, vfs, path: "/foo/bar" })
project.setMemento {}

project.once 'complete', done

it "should be able to load a simple memento", ->

it "should be able to load a simple memento", (done) ->
vfs = new TestVFS()

session = new FakeSession()
Expand All @@ -63,8 +66,10 @@ describe "Project", ->
project = universe.create(Project, { session, vfs, path: "/foo/bar" })
project.setMemento { disableLiveRefresh: 1, compilationEnabled: 1 }

project.once 'complete', done


it "should be able to load a real memento", ->
it "should be able to load a real memento", (done) ->
vfs = new TestVFS()

session = new FakeSession()
Expand All @@ -76,6 +81,8 @@ describe "Project", ->
assert.equal project.compilationEnabled, true
assert.equal project.rubyVersionId, 'system'

project.once 'complete', done


it "should save CSS files edited in Chrome Web Inspector", (done) ->
vfs = new TestVFS()
Expand All @@ -85,12 +92,12 @@ describe "Project", ->

universe = new R.Universe()
project = universe.create(Project, { session, vfs, path: "/foo/bar" })
project.saveResourceFromWebInspector 'http://example.com/static/test.css', "h1 { color: green }\n", (err, saved) ->
assert.ifError err
assert.ok saved
assert.equal vfs.get('/foo/bar/app/static/test.css'), "h1 { color: green }\n"
await project.saveResourceFromWebInspector 'http://example.com/static/test.css', "h1 { color: green }\n", defer(err, saved)
assert.ifError err
assert.ok saved
assert.equal vfs.get('/foo/bar/app/static/test.css'), "h1 { color: green }\n"

done()
project.once 'complete', done


it "should patch source SCSS/Stylus files when a compiled CSS is edited in Chrome Web Inspector", (done) ->
Expand All @@ -107,13 +114,13 @@ describe "Project", ->

universe = new R.Universe()
project = universe.create(Project, { session, vfs, path: "/foo/bar" })
project.saveResourceFromWebInspector 'http://example.com/static/test.css', css2, (err, saved) ->
assert.ifError err
assert.ok saved
assert.equal vfs.get('/foo/bar/app/static/test.css'), css2
assert.equal vfs.get('/foo/bar/app/static/test.styl'), styl2
await project.saveResourceFromWebInspector 'http://example.com/static/test.css', css2, defer(err, saved)
assert.ifError err
assert.ok saved
assert.equal vfs.get('/foo/bar/app/static/test.css'), css2
assert.equal vfs.get('/foo/bar/app/static/test.styl'), styl2

done()
project.once 'complete', done


it "should be reactive", (done) ->
Expand All @@ -124,13 +131,17 @@ describe "Project", ->

project = universe.create(Project, { session, vfs, path: "/foo/bar" })

universe.once 'change', -> done()
project.setMemento { disableLiveRefresh: 1, compilationEnabled: 1 }
await
project.once 'complete', defer()
universe.once 'change', defer()
project.setMemento { disableLiveRefresh: 1, compilationEnabled: 1 }

done()


describe "plugin support", ->

it "should run plugin.loadProject on setMemento", ->
it "should run plugin.loadProject on setMemento", (done) ->
vfs = new TestVFS()

session = new FakeSession()
Expand All @@ -144,10 +155,15 @@ describe "Project", ->

assert.equal project.foo, 42

project.once 'complete', done


describe "rule system", ->

it "should start new projects with a full set of supported rules", ->
class TestContext
constructor: ->

it "should start new projects with a full set of supported rules", (done) ->
universe = new R.Universe()
vfs = new TestVFS()
session = new FakeSession()
Expand All @@ -158,17 +174,61 @@ describe "Project", ->
extensions: ['less']
destinationExt: 'css'
sourceSpecs: ["*.less"]
sourceFilter: RelPathList.parse("*.less")
}
session.pluginManager.allCompilers.push {
name: 'CoffeeScript'
id: 'coffeescript'
extensions: ['coffee']
destinationExt: 'js'
sourceSpecs: ["*.coffee"]
sourceFilter: RelPathList.parse("*.less")
sourceFilter: RelPathList.parse("*.coffee")
}

project = universe.create(Project, { session, vfs, path: "/foo/bar" })
project.setMemento {}
await project.once 'complete', defer()
deepEqual project.ruleSet.memento(), [{ action: 'compile-less', src: '**/*.less', dst: '**/*.css' }, { action: 'compile-coffeescript', src: '**/*.coffee', dst: '**/*.js' }]
done()

it "should resolve the list of files matched by each rule", (done) ->
universe = new R.Universe()
vfs = new TestVFS()
session = new FakeSession()
# TODO: add some kind of fuzzy dependency injection to collapse these stupid chains
session.pluginManager.allCompilers.push {
name: 'LESS'
id: 'less'
extensions: ['less']
destinationExt: 'css'
sourceSpecs: ["*.less"]
sourceFilter: RelPathList.parse("*.less")
}
session.pluginManager.allCompilers.push {
name: 'CoffeeScript'
id: 'coffeescript'
extensions: ['coffee']
destinationExt: 'js'
sourceSpecs: ["*.coffee"]
sourceFilter: RelPathList.parse("*.coffee")
}

tempfs = scopedfs.createTempFS('livereload-test-')
tempfs.applySync
'foo.less': "h1 { span { color: red } }\n"
'bar.coffee': "alert 42\n"

project = universe.create(Project, { session, vfs, path: tempfs.path })
project.setMemento {}
await project.once 'complete', defer()

equal project.ruleSet.rules[0].action.id, 'compile-less'
deepEqual (f.relpath for f in project.ruleSet.rules[0].files).sort(), ['foo.less']

equal project.ruleSet.rules[1].action.id, 'compile-coffeescript'
deepEqual (f.relpath for f in project.ruleSet.rules[1].files).sort(), ['bar.coffee']
done()

it "should use rules to determine compiler and output path"
it "should allow rules to be modified in the UI"
14 changes: 9 additions & 5 deletions test/ruleset_test.iced
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{ ok, equal, deepEqual } = require 'assert'

{ Action, CompilationAction, RuleSet } = require "../#{process.env.JSLIB or 'lib'}/session"
{ Action, CompilationAction, RuleSet, R } = require "../#{process.env.JSLIB or 'lib'}/session"


class MockAction extends Action
Expand All @@ -14,27 +14,31 @@ class MockAction extends Action
describe "RuleSet", ->

it "should be creatable", ->
ruleSet = new RuleSet([new MockAction()])
universe = new R.Universe()
ruleSet = universe.create(RuleSet, actions: [new MockAction()])
deepEqual ruleSet.rules, []

it "should export a memento", ->
universe = new R.Universe()
action = new MockAction()
ruleSet = new RuleSet([action])
ruleSet = universe.create(RuleSet, actions: [action])
ruleSet.addRule action, { src: '*.less', dst: '*.css' }
deepEqual ruleSet.memento(), [{ action: "mock-A", src: "*.less", dst: "*.css" }]

it "should import a memento", ->
universe = new R.Universe()
action = new MockAction()
ruleSet = new RuleSet([action])
ruleSet = universe.create(RuleSet, actions: [action])
ruleSet.setMemento [{ action: "mock-A", src: "*.less", dst: "*.css" }]
equal ruleSet.rules.length, 1
equal ruleSet.rules[0].sourceSpec, '*.less'
equal ruleSet.rules[0].destSpec, '*.css'

it "should set up initial rules", ->
universe = new R.Universe()
compiler = { id: 'more', name: 'More', extensions: ['more'], destinationExt: 'css' }
action = new CompilationAction(compiler)
ruleSet = new RuleSet([action])
ruleSet = universe.create(RuleSet, actions: [action])
equal ruleSet.rules.length, 1
equal ruleSet.rules[0].sourceSpec, '**/*.more'
equal ruleSet.rules[0].destSpec, '**/*.css'

0 comments on commit f5d0bda

Please sign in to comment.