addTask: function (task, config) {
		// @todo Quote task name if needed.
		// @todo Do not insert comma to empty properties list.

		if ( !_.isString(task) || this.tasks[task] ) {
			return this;
		}

		if ( config === undefined ) {
			config = {};
		}

		if ( !_.isString(config) ) {
			config = stringifyObject(config, {
				indent: this.indent,
				singleQuotes: true
			});
		}

		var props = this._configObject.properties,
			lastProp = props[props.length - 1];

		// Indent block
		var level = lastProp.endToken.loc.start.column,
			blockIndent = _str.repeat(this.indent, level);
		config = blockIndent + config.replace(/\n/g, '\n' + blockIndent);

		var configExpression = '({' + task + ': ' + config + '})',  // @todo Simplify?
			configTree = rocambole.parse(configExpression, {
				loc: true
			}),
			newProp = configTree.body[0].expression.properties[0];

		// Append new property
		var prefix = {
			value: ',\n\n' + blockIndent + task + ': '
		};
		tk.after(lastProp.endToken, prefix);
		tk.after(prefix, newProp);

		// Save results
		if ( this.autosave ) {
			this.save();
		}

		this.reparse();
		return this;
	},
示例#2
0
  node.properties.forEach(function(prop) {
    // convert comma-first to comma-last
    var comma = _tk.findNext(prop.value.endToken, [',', '}']);
    if (_tk.isComma(comma)) {
      var br = _tk.findInBetween(prop.value.endToken, comma, _tk.isBr);
      if (br) {
        _tk.remove(br);
      }
      _tk.remove(comma);
      _tk.after(prop.value.endToken, comma);
    }

    if (!shouldBeSingleLine) {
      _br.limitBefore(prop.key.startToken, 'PropertyName');
      _br.limitAfter(prop.key.endToken, 'PropertyName');
      _br.limitBefore(prop.value.startToken, 'PropertyValue');
      _br.limitAfter(prop.value.endToken, 'PropertyValue');
    } else if (prop.key.startToken.prev.value !== '{') {
      _ws.limitBefore(prop.key.startToken, 'Property');
    }

    _ws.limitBefore(prop.key.startToken, 'PropertyName');
    _ws.limitAfter(prop.key.endToken, 'PropertyName');
    _ws.limitBefore(prop.value.startToken, 'PropertyValue');
    _ws.limitAfter(prop.value.endToken, 'PropertyValue');
  });
  node.declarations.forEach(function(declarator, i) {
    var idStartToken = declarator.id.startToken;

    // need to swap comma-first line break
    var prevNonEmpty = _tk.findPrevNonEmpty(idStartToken);
    if (i && prevNonEmpty.value === ',') {
      if (_tk.isBr(prevNonEmpty.prev) || _tk.isBr(prevNonEmpty.prev.prev)) {
        var beforeComma = _tk.findPrev(prevNonEmpty, function(t) {
          return !_tk.isEmpty(t) && !_tk.isComment(t);
        });
        _ws.limit(prevNonEmpty, 0);
        _tk.remove(prevNonEmpty);
        _tk.after(beforeComma, prevNonEmpty);
      }
    }

    if (!i && !_tk.isComment(_tk.findPrevNonEmpty(idStartToken))) {
      // XXX: we don't allow line breaks or multiple spaces after "var"
      // keyword for now (might change in the future)
      _tk.removeEmptyAdjacentBefore(idStartToken);
    } else if (!insideFor && declarator.init) {
      _br.limit(idStartToken, 'VariableName');
    }
    _ws.limitBefore(idStartToken, 'VariableName');

    if (declarator.init) {
      _ws.limitAfter(declarator.id.endToken, 'VariableName');
      var equalSign = _tk.findNext(declarator.id.endToken, '=');
      var valueStart = _tk.findNextNonEmpty(equalSign);
      _br.limitBefore(valueStart, 'VariableValue');
      _ws.limitBefore(valueStart, 'VariableValue');
      _br.limitAfter(declarator.endToken, 'VariableValue');
      _ws.limitAfter(declarator.endToken, 'VariableValue');
    }
  });
exports.limitBeforeEndOfFile = function(ast, amount) {
  var typeOrValue = amount != null ? amount : 'EndOfFile';
  var expected = getExpect('before', typeOrValue);

  if (expected < 0) return; // noop

  var lastNonEmpty = _tk.isEmpty(ast.endToken) ?
    _tk.findPrevNonEmpty(ast.endToken) :
    ast.endToken;

  if (lastNonEmpty) {
    limitInBetween('after', lastNonEmpty, null, expected, true);
  } else {
    do {
      var br = {
        type: 'LineBreak',
        value: _curOpts.value
      };
      if (ast.startToken) {
        _tk.after(ast.startToken, br);
      } else {
        ast.startToken = ast.endToken = br;
      }
    } while (--expected);
  }
};
  node.properties.forEach(function(prop) {
    // we need to grab first/last "executable" token to avoid issues (see #191)
    var valueStart = _tk.findNextNonEmpty(_tk.findPrev(prop.value.startToken, ':'));
    var eol = _tk.findNext(prop.value.endToken, ['LineBreak', ',', '}']);
    var valueEnd = _tk.findPrev(eol, function(token) {
      return !_tk.isEmpty(token) && !_tk.isComment(token);
    });

    // convert comma-first to comma-last
    var comma = _tk.findNext(prop.value.endToken, [',', '}']);
    if (_tk.isComma(comma)) {
      var br = _tk.findInBetween(prop.value.endToken, comma, _tk.isBr);
      if (br) {
        _tk.remove(br);
      }
      _tk.remove(comma);
      _tk.after(valueEnd, comma);
    }

    if (!shouldBeSingleLine) {
      _br.limitBefore(prop.key.startToken, 'PropertyName');
      _br.limitAfter(prop.key.endToken, 'PropertyName');
      _br.limitBefore(prop.value.startToken, 'PropertyValue');
      _br.limitAfter(prop.value.endToken, 'PropertyValue');
    } else if (prop.key.startToken.prev.value !== '{') {
      _ws.limitBefore(prop.key.startToken, 'Property');
    }

    _ws.limitBefore(prop.key.startToken, 'PropertyName');
    _ws.limitAfter(prop.key.endToken, 'PropertyName');
    _ws.limitBefore(valueStart, 'PropertyValue');
    _ws.limitAfter(valueEnd, 'PropertyValue');
  });
示例#6
0
function after(token, value) {
  value = !value ? _curOpts.value : value;
  var ws = {
    type: 'WhiteSpace',
    value: value
  };
  _tk.after(token, ws);
  return ws;
}
示例#7
0
var wrapWithBraces = function (node, prop) {
    var old = node[prop];
    var block = {
        type: 'BlockStatement',
        parent: old.parent,
        root: old.root,
        body: [old],
        startToken: tk.before(old.startToken, {
            type: 'Punctuator',
            value: '{'
        }),
        endToken: tk.after(old.endToken, {
            type: 'Punctuator',
            value: '}'
        })
    };
    old.parent = block;
    node[prop] = block;
};
	registerTask: function(name, tasks) {
		if ( !_.isArray(tasks) ) {
			tasks = [tasks];
		}

		var expression;
		visit(this.tree, {
			visitMemberExpression: function(path) {
				var node = path.node;
				if ( node.object.name === 'grunt' && node.property.name === 'registerTask' &&
						node.parent.arguments && node.parent.arguments[0].value === name ) {
					expression = node.parent;
				}
				this.traverse(path);
			}
		});

		if (expression) {
			// Task group already exists
			var listExpression = expression.arguments[1];
			if ( !listExpression ) {
				throw new Error('grunt.registerTask requires second argument');
			}
			var list = listExpression.elements;

			var items, newToken;
			if ( list.length ) {
				// Filter already existent items
				var existentTasks = _.map(list, 'value');
				tasks = _.filter(tasks, function(taskName) {
					return existentTasks.indexOf(taskName) === -1;
				});

				if ( !tasks.length ) {
					// All tasks already existent
					return this;
				}

				// Append new items
				var quote = util.detectQuoteStyle(list[0]);
				items = _.map(tasks, util.quote.bind(util, quote));
				newToken = {
					value: ', ' + items.join(', ')
				};
				tk.after(list[list.length - 1].endToken, newToken);
			}
			else {
				// @todo Try to detect quotes somewhere else in a file.
				items = _.map(tasks, util.quote.bind(util, '\''));
				newToken = {
					value: items.join(', ')
				};
				tk.before(listExpression.endToken, newToken);
			}
		}
		else {
			// @todo
		}

		if ( this.autosave ) {
			this.save();
		}

		this.reparse();
		return this;
	},