Ignore transform functions in usage name linter

The `UsageNameLinter` was incorrectly reporting lints for
transform-related functions like `scaleX` or `rotateZ`, as these
characters contain uppercase letters.

Add a whitelist so that these particular functions are ignored.

Fixes #30

Change-Id: I79dd481f8784182c535d76318839baefeb9cdd1d
Reviewed-on: https://gerrit.causes.com/27813
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Greg Hurrell <greg@causes.com>
Add count option to report_lint matcher

In order to writes tests that ensure multiple lints are reported for a
single line, add a `count` option to the `report_lint` matcher so that
one can write:

    it { should report_lint count: 4, line: 2 }

...to indicate that four lints are expected to be reported for line 2.

This also changes the behaviour of `report_lint` to now check if at
least one lint was reported, rather than exactly one. This makes more
sense, since otherwise the `should_not` case would only tell you that
the linter didn't report exactly one lint (it reported zero or more than
one).

Change-Id: I1dca4349bc938332c427c35fb46954fcc4a5458d
Reviewed-on: https://gerrit.causes.com/27811
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Shane da Silva <shane@causes.com>
Add NoZeroBeforeDecimalLinter

Add a linter that checks for unnecessary leading zeros in numbers with a
fractional component. In other words, prefer `.5` over `0.5`.

This is unfortunately not a complete implementation, as numbers inside
Sass Script will not be detected in this way due to the way the Sass
parser replaces the original string with the resultant
`Sass::Script::Literal`. For example, '.5' will become the Float `0.5`,
so we can't detect after the fact whether the value was written with an
unnecessary leading zero. Concretely, values inside function or mixin
arguments will not be linted.

Luckily, this implementation handles a significant number of cases.

Perhaps one day we will contribute a commit to the upstream `sass` gem
to be able to handle the general case.

Change-Id: I069a4bd3095ddd02a5c31d1f5dfbe5c1b7ce77fa
Reviewed-on: https://gerrit.causes.com/27812
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Shane da Silva <shane@causes.com>
Add capitalization in selector linter

Change-Id: Iccf57da46a8ff12ba43d7fe4534e766f11d934b8
Reviewed-on: https://gerrit.causes.com/27814
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Shane da Silva <shane@causes.com>
Remove unnecessary Linter suffix from linters

Linters have historically always had the suffix `Linter` at the end of
their name. However, it appears that over time this pattern has not been
consistent.

This also turns out to be annoying when you want to include/exclude a
linter via a flag, since you always have to write the `Linter` suffix.

To simplify things, remove all `Linter` suffixes from linters and rename
their respective files. I also renamed some of the resultant linters
(e.g. `Debug` -> `DebugStatement`) since their name was too short to be
descriptive.

Change-Id: I9f274abaf7c94d8a5729245036f25f13b99aeb84
Reviewed-on: https://gerrit.causes.com/27817
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Lann Martin <lann@causes.com>
Add PlaceholderInExtend linter

The functionality provided by the `@extend` feature of Sass can be a bit
tricky and misleading. Placeholder selectors (e.g. `%some-name`) were
created as a way to make working with extend easier. For more
information read:

    http://8gramgorilla.com/mastering-sass-extends-and-placeholders/

Add a linter that detects the use of anything other than a placeholder
in an `@extend` statement to encourage the correct usage.

Closes #24

Change-Id: I86a5da4f4089e688522ab116a96ec9752e401bc5
Reviewed-on: https://gerrit.causes.com/27818
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Lann Martin <lann@causes.com>
Don't report usage lint for hyphenated keyword args

There was a bug where any time a user used keyword arguments, e.g.

    @include line-clamp($line-count: 3, $line-height: 1.5em);

...lints would be incorrectly reported for each hyphenated keyword
argument.

This was due to the Sass parser treating variables with underscores as
canonical. Since the `Sass::Script::Variable` `underscored_name`
attribute was used to get the name of the variable under the hood, even
if a variable was written as `$some-var`, the linter would see it as
`$some_var` and report a lint.

The easy solution for this was to monkey-patch
`Sass::Script::Variable#underscored_name` to return the original name.
A more proper fix would have been to contribute upstream to the `sass`
gem, but that potentially requires us to maintain a separate fork in the
event that patch isn't accepted.

Fixes #27

Change-Id: I27b539c2f68035284d22bacd2638e7487cab5254
Reviewed-on: https://gerrit.causes.com/27819
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Lann Martin <lann@causes.com>
Handle sorting of vendor-prefixed properties

Previously, the `SortedProperties` linter would not handle
vendor-prefixed properties in any special way, resulting in them always
being required to be at the beginning of the list of properties (since
they all start with a hyphen).

A more appropriate solution would be to enforce an ordering where
vendor-prefixed properties are sorted by vendor, and placed before the
associated non-prefixed property. For example:

    border: 0;
    -moz-border-radius: 3px;
    -o-border-radius: 3px;
    -webkit-border-radius: 3px;
    border-radius: 3px;
    color: #ccc;

This commit adds support for this kind of ordering.

In the process, the line being reported is now the line of the first
property that is out of order (rather than just the first property in
the list of properties, as was previously the case).

Note that this implementation still ignores interpolated variables.

Closes #22

Change-Id: I1d3d38d11eaf8a13c79b7cfacb0130f5c6e3873a
Reviewed-on: https://gerrit.causes.com/27824
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Lann Martin <lann@causes.com>
Add TravisCI integration

Add `.travis.yml` and the corresponding badge to the README file.

Currently supported Ruby versions are 1.9.3 and 2.0.0. The README was
updated from saying "1.9+" to "1.9.3+".

Change-Id: Ia98725947fd6618f050adfa7a1e162f939cbf585
Reviewed-on: https://gerrit.causes.com/27826
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Lann Martin <lann@causes.com>
Bump version to 0.9.0

In the process of updating the version, it was discovered that we were
adding a number of updates to the changelog under the 0.8.0 heading,
when we had technically already released that version.

Shuffle the new features as of 0.8.0 under the heading 0.9.0.

Change-Id: I7cea5fa5b5c5c6af46163b0538e48a1a3ac51ddf
Reviewed-on: https://gerrit.causes.com/27827
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Lann Martin <lann@causes.com>
Update Gemfile.lock to fix TravisCI build

Normally we haven't had to update the `Gemfile.lock` file since when we
run tests locally they work as expected.

However, going forward we need to ensure we update this file by running
`bundle install` locally when we bump the gem version, otherwise the
TravisCI build will fail trying to find to find the outdated version of
`scss-lint`.

Change-Id: I8cacfd7f8b98558a1afe22d39a4878c58fdaf03f
Reviewed-on: https://gerrit.causes.com/27862
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Shane da Silva <shane@causes.com>
Add ColorKeyword linter

Add a linter to detect when using one of the extended color keywords
instead of a hexadecimal value.

The representation of these colors usually require more bytes than a 4-7
character hex code.

Change-Id: I2ef7b28fa28afc5c09b1b68a65305bec144ea878
Reviewed-on: https://gerrit.causes.com/27825
Reviewed-by: Shane da Silva <shane@causes.com>
Tested-by: jenkins <jenkins@causes.com>
Allow Linters to visit selectors

One problem that linters frequently face is the challenge of finding
lints based on the CSS selector of a rule set declaration.

Previously linters had to manually inspect the `rule` of a
`Sass::Tree::RuleNode` in order to check for lints. However, this
involved a lot of repeated code, and was usually hard to understand.

To DRY up some of these areas, introduce support for `Linter`s to define
`visit_*` methods for various selectors they are interested in visiting.

For example, to visit all ID selectors, define something like:

    def visit_id(id)
      ...
    end

There are some gotchas to this, however. If a selector contains any
interpolation, this won't work. This is because interpolation could
potentially change the type of selector. Consider the following:

    p #{$some-value} span { ... }

If `$some-value` = '+', then the selector will be `p + span`: a
`CommaSequence` containing a single `Sequence`. However, if
`$some-value` is a ',' then the selector will be `p , span`: a
`CommaSequence` containing two `SimpleSequence`s.

Thus the visitor can work only with selectors containing no
interpolation, as those are the only ones the Sass parser will parse
for us ahead of time. This should still cover a majority of cases.

Change-Id: Ic0c5728ce5a4c993da12de27a34aa91b61b20e65
Reviewed-on: https://gerrit.causes.com/28828
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Greg Hurrell <greg@causes.com>
Allow linters to define custom descriptions

Previously `Linter`s could only have exactly one description which was
defined by implementing the `description` method on the `Linter`.

There are some cases where an individual linter can provide additional
context as part of its description for the lint. Allow for this case by
adding an optional `description` argument to `Linter#add_lint`.

Change-Id: I88058f05a8c626a14d6cc3e7879f5a99ddc510ae
Reviewed-on: https://gerrit.causes.com/28829
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Greg Hurrell <greg@causes.com>
Change CapitalizationInSelector to use SelectorVisitor

The previous implementation of `CapitalizationInSelector` was flawed in
that it would incorrectly report a lint for a selector like:

    [data-text=someText] { ... }

This was due to the fact that we were not differentiating between the
attribute name and its value in the selector.

Changing the linter to use the new selector-based `visit_*` methods
allows us to get around this problem.

Fixes #40

Change-Id: Id5ec24121b44d98376f3e231caf5c4b95356e337
Reviewed-on: https://gerrit.causes.com/28830
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Greg Hurrell <greg@causes.com>
Remove placeholder check from DeclaredName linter

The `CapitalizationInSelector` linter now checks for improper
capitalization for placeholder selectors. Thus we can remove the
placeholder-related checks from the `DeclardName` linter (or else we'll
get double-reporting on the error).

Change-Id: If964bcc8cbc1b98f192c04d35c435c9ebe64c8be
Reviewed-on: https://gerrit.causes.com/28831
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Greg Hurrell <greg@causes.com>
Make DeclaredName lints more specific

Change the descriptions of lints reported by `DeclaredName` to be
relevant to the particular context (e.g. whether the incorrectly named
thing was a function, mixin, or variable).

Change-Id: I2191c1a3bb4f512b7d28e377eaedce4c0ec0a849
Reviewed-on: https://gerrit.causes.com/28832
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Greg Hurrell <greg@causes.com>
Make UsageName lints more specific

Change the descriptions of lints reported by the `UsageName` linter to
be more-specific to the context of the problem (e.g. specify whether the
problematic name is for a function, variable, mixin, etc.).

In the process I was able to remove a method in the `Utils` module into
the only location it was used (the `UsageName` linter).

Change-Id: Id1fff3a523cc252c78023fb9b2391d55f490a836
Reviewed-on: https://gerrit.causes.com/28833
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Greg Hurrell <greg@causes.com>
Enhance TypeInIdSelector linter

This linter previously used regexes to perform its check. This has now
been changed to use the new selector-based `visit_simple_sequence`
method, and in the process can now detect the use of an ID with any
other simple selector (e.g. p#id, #id[href], #id.class, etc.).

Since it's now more generalized, I've renamed it to
`IdWithExtraneousSelector`.

Change-Id: Id8a87e4fa0a724746df28b2d0b1f0d2fb90b34cc
Reviewed-on: https://gerrit.causes.com/28834
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Shane da Silva <shane@causes.com>
Address code review comments

Address some comments that were left in code review. This is done
separately to avoid sending the entire chain through Gerrit again.

The changes made were:

  * Add a comment describing a method of the `SelectorVisitor`

  * Removed an unnecessary `protected` from `Linter`

  * Changed parameter name in `Linter#add_lint` so it wouldn't shadow a
    method

  * Removed dead `description` method from `CapitalizationInSelector`

Change-Id: I75edfcfddc703e419dd9f9e0bbd2b274954dad7e
Reviewed-on: https://gerrit.causes.com/28845
Tested-by: jenkins <jenkins@causes.com>
Reviewed-by: Shane da Silva <shane@causes.com>