Skip to content

Commit

Permalink
Refactor old code
Browse files Browse the repository at this point in the history
  • Loading branch information
hudochenkov committed Jun 9, 2017
1 parent 67b8f50 commit 074d9f8
Showing 1 changed file with 45 additions and 12 deletions.
57 changes: 45 additions & 12 deletions lib/rules/indentation/index.js
Expand Up @@ -19,8 +19,8 @@ const messages = ruleMessages(ruleName, {
* keyword "tab" for single `\t`
* @param {object} [options]
*/
const rule = function (space) {
const options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}
const rule = function (space, options) {
options = options || {}

const isTab = space === "tab"
const indentChar = isTab ? "\t" : _.repeat(" ", space)
Expand Down Expand Up @@ -73,14 +73,19 @@ const rule = function (space) {
// there is no "indentation" to check.)
const inspectBefore = root.first === node || before.indexOf("\n") !== -1

// Cut out any * hacks from `before`
before = before[before.length - 1] === "*" || before[before.length - 1] === "_" ? before.slice(0, before.length - 1) : before
// Cut out any * and _ hacks from `before`
if (before[before.length - 1] === "*" || before[before.length - 1] === "_") {
before = before.slice(0, before.length - 1)
}

// Inspect whitespace in the `before` string that is
// *after* the *last* newline character,
// because anything besides that is not indentation for this node:
// it is some other kind of separation, checked by some separate rule
if (inspectBefore && before.slice(before.lastIndexOf("\n") + 1) !== expectedWhitespace) {
if (
inspectBefore
&& before.slice(before.lastIndexOf("\n") + 1) !== expectedWhitespace
) {
report({
message: messages.expected(legibleExpectation(nodeLevel)),
node,
Expand All @@ -94,7 +99,12 @@ const rule = function (space) {
// otherwise there's no indentation involved.
// And check `indentClosingBrace` to see if it should be indented an extra level.
const closingBraceLevel = options.indentClosingBrace ? nodeLevel + 1 : nodeLevel
if (hasBlock(node) && after && after.indexOf("\n") !== -1 && after.slice(after.lastIndexOf("\n") + 1) !== _.repeat(indentChar, closingBraceLevel)) {
if (
hasBlock(node)
&& after
&& after.indexOf("\n") !== -1
&& after.slice(after.lastIndexOf("\n") + 1) !== _.repeat(indentChar, closingBraceLevel)
) {
report({
message: messages.expected(legibleExpectation(closingBraceLevel)),
node,
Expand All @@ -120,8 +130,8 @@ const rule = function (space) {
}
})

function indentationLevel(node) {
const level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0
function indentationLevel(node, level) {
level = level || 0

if (node.parent.type === "root") {
return level
Expand All @@ -137,7 +147,11 @@ const rule = function (space) {
// If options.except includes "block",
// blocks are taken down one from their calculated level
// (all blocks are the same level as their parents)
if (optionsMatches(options, "except", "block") && (node.type === "rule" || node.type === "atrule") && hasBlock(node)) {
if (
optionsMatches(options, "except", "block")
&& (node.type === "rule" || node.type === "atrule")
&& hasBlock(node)
) {
calculatedLevel--
}

Expand Down Expand Up @@ -176,43 +190,59 @@ const rule = function (space) {

// @nest rules should be treated like regular rules, not expected
// to have their params (selectors) indented
const paramLevel = optionsMatches(options, "except", "param") || atRule.name === "nest" ? ruleLevel : ruleLevel + 1
const paramLevel = optionsMatches(options, "except", "param") || atRule.name === "nest"
? ruleLevel
: ruleLevel + 1

checkMultilineBit(beforeBlockString(atRule).trim(), paramLevel, atRule)
}

function checkMultilineBit(source, newlineIndentLevel, node) {
if (source.indexOf("\n") === -1) {
return
}

// `outsideParens` because function arguments and also non-standard parenthesized stuff like
// Sass maps are ignored to allow for arbitrary indentation
let parentheticalDepth = 0

styleSearch({
source,
target: "\n",
outsideParens: optionsMatches(options, "ignore", "inside-parens"),
}, (match, matchCount) => {
const precedesClosingParenthesis = /^[ \t]*\)/.test(source.slice(match.startIndex + 1))

if (optionsMatches(options, "ignore", "inside-parens") && (precedesClosingParenthesis || match.insideParens)) {
if (
optionsMatches(options, "ignore", "inside-parens")
&& (precedesClosingParenthesis || match.insideParens)
) {
return
}

let expectedIndentLevel = newlineIndentLevel

// Modififications for parenthetical content
if (!optionsMatches(options, "ignore", "inside-parens") && match.insideParens) {
if (
!optionsMatches(options, "ignore", "inside-parens")
&& match.insideParens
) {
// If the first match in is within parentheses, reduce the parenthesis penalty
if (matchCount === 1) parentheticalDepth -= 1

// Account for windows line endings
let newlineIndex = match.startIndex
if (source[match.startIndex - 1] === "\r") {
newlineIndex--
}

const followsOpeningParenthesis = /\([ \t]*$/.test(source.slice(0, newlineIndex))
if (followsOpeningParenthesis) {
parentheticalDepth += 1
}

expectedIndentLevel += parentheticalDepth

if (precedesClosingParenthesis) {
parentheticalDepth -= 1
}
Expand Down Expand Up @@ -245,9 +275,11 @@ const rule = function (space) {
// check that the whitespace characters (excluding newlines) before the first
// non-whitespace character equal the expected indentation
const afterNewlineSpaceMatches = /^([ \t]*)\S/.exec(source.slice(match.startIndex + 1))

if (!afterNewlineSpaceMatches) {
return
}

const afterNewlineSpace = afterNewlineSpaceMatches[1]

if (afterNewlineSpace !== _.repeat(indentChar, expectedIndentLevel)) {
Expand All @@ -266,6 +298,7 @@ const rule = function (space) {
function legibleExpectation(level) {
const count = isTab ? level : level * space
const quantifiedWarningWord = count === 1 ? warningWord : warningWord + "s"

return `${count} ${quantifiedWarningWord}`
}
}
Expand Down

0 comments on commit 074d9f8

Please sign in to comment.