AtomLinter / linter-phpcs

Linter plugin for PHP, using PHP_CodeSniffer.
63 stars 31 forks source link

Per-project phpcs path & standard #26

Closed davidbarratt closed 9 years ago

davidbarratt commented 9 years ago

I have Drupal projects and PSR-2 projects and right now I have to manually go in and change the standard, also, I have to update the path since each project includes phpcs.

It would be really helpful to have a per-project phpcs path and a per-project standard. If one is not available for the project, it should fall back to the global.

cconover commented 9 years ago

Agreed. Support for ruleset.xml or a custom-named XML file supported by CodeSniffer would be hugely helpful. I basically have to ignore my linter errors whenever I'm developing for WordPress.

steelbrain commented 9 years ago

Fixed by https://github.com/AtomLinter/linter-phpcs/pull/30

aendra-rininsland commented 9 years ago

For anyone who was trying to figure out how to make this work, the key is to have a phpcs.xml file in your project directory.

Devs, some documentation would be helpful, this is a really useful feature (Thanks for adding it! I switch between WordPress, Laravel and PSR2 on a weekly basis). :+1:

Arcanemagus commented 9 years ago

@aendrew it already is documented in the phpcs documentation. This is just a wrapper around that that allows its output to be used in Atom through the linter package :wink:.

We do support the non-standard phpcs.ruleset.xml since apparently that is common in the WordPress community (https://github.com/AtomLinter/linter-phpcs/pull/50). That isn't documented anywhere, although as it isn't standard in the first place I don't really see that as an issue.

aendra-rininsland commented 9 years ago

@Arcanemagus Ah! I didn't realise it was a PHPCS functionality and not linter-phpcs. I stand corrected!

Might still be worth adding to the docs though, for those not super well-versed in the intricacies of phpcs. I've been using phpcs for ages and didn't know about that feature.

Arcanemagus commented 9 years ago

We default phpcs to the PSR2 standard if no phpcs.xml file is found, so it should already work without any configuration. You should only need to create a phpcs.xml file if you need to customize it.

More documentation can't hurt though, feel free to submit a PR for it :wink:.

aendra-rininsland commented 9 years ago

@Arcanemagus Happy to submit a documentation PR, but I kind of need to get this working first... :sweat_smile:

I have a file called phpcs.xml in my project root containing:

<?xml version="1.0"?>
<ruleset name="MyProject">
 <description>Custom ruleset</description>

 <exclude-pattern>*/tests/*</exclude-pattern>

 <rule ref="WordPress" />
</ruleset>

However, it's still picking up the PSR2 standard (AFAICT; it's throwing errors for spaces after opening function parenthesis, which WordPress standards require). Also tried naming it phpcs.ruleset.xml, same issue.

Any help?

Edit: Hmm, I moved it into my theme's parent directory and it's working now. Any idea why I can't just put it in my project root?

Edit2: Actually, I have a second Git repo inside my project, and it seems anywhere in the root of the second repo works too. Is it just that Atom defines projects in terms less of where Atom is spawned and more in terms of where the .git folder resides?

Arcanemagus commented 9 years ago

Actually it should start at the current directory of the editing for and search all parent directories for the named files until it finds one.

https://github.com/AtomLinter/atom-linter/blob/master/lib/helpers.coffee#L112-L125

So I'm not sure why it wasn't working in the same directory, any ideas @steelbrain?

frytyler commented 8 years ago

@Arcanemagus Just wondering if I'm missing something to be able to extend the default phpcs linting by adding a phpcs.xml file in my project root.

<?xml version="1.0"?>
<ruleset name="Selective Standard">

 <!--
    Exclude some files from being fixed.
 -->
 <exclude-pattern phpcs-only="true">/database/*</exclude-pattern>

</ruleset>

Do I need to put a <rule ref...> in there to pull the standard back in?

The above example causes the entire linter not to work in Atom.

Arcanemagus commented 8 years ago

Does that file work with PHPCS on the CLI?

frytyler commented 8 years ago

@Arcanemagus No I don't think so I got this the "/phpcs.xml" coding standard is not installed. The installed coding standards are MySource, PEAR, PHPCS, PSR1, PSR2, Squiz and Zend However I am not even sure I called it correctly.

I called phpcs --standard=/phpcs.xml TestCase.php in my tests folder

Arcanemagus commented 8 years ago

You would want phpcs --standard=phpcs.xml TestCase.php, assuming it is in the same folder and not really at the root of your drive.

By the way, this package should be finding that for you...

frytyler commented 8 years ago

@Arcanemagus Okay so if I remove that file completely I get the cli output but I add it back in and I get no response, command just completes immediately no errors.

Arcanemagus commented 8 years ago

Looking over the documentation, you'll definitely need to tell it what rules to run if you are using a custom file. This package is merely a translation between the output of phpcs and the Linter package, so if you aren't getting what you expect from phpcs on the CLI, you shouldn't be getting anything different from here.

If you want an example, here is what I've got in one project:

<?xml version="1.0"?>
<ruleset name="PSR2">
  <description>The PSR-2 coding standard.</description>
  <arg name="tab-width" value="4"/>

<!-- 2. General -->

<!-- 2.1 Basic Coding Standard -->

<!-- Include the whole PSR-1 standard, except the side effects sniff -->
  <rule ref="PSR1">
    <exclude name="PSR1.Files.SideEffects" />
  </rule>

<!-- 2.2 Files -->

<!-- All PHP files MUST use the Unix LF (linefeed) line ending. -->
  <rule ref="Generic.Files.LineEndings">
    <properties>
      <property name="eolChar" value="\n"/>
    </properties>
  </rule>

<!-- All PHP files MUST end with a single blank line. -->
<!-- checked in Files/EndFileNewlineSniff -->

<!-- The closing ?> tag MUST be omitted from files containing only PHP. -->
<!-- checked in Files/ClosingTagSniff -->

<!-- 2.3 Lines -->

<!-- The soft limit on line length MUST be 120 characters; automated style checkers MUST warn but MUST NOT error at the soft limit. -->
  <rule ref="Generic.Files.LineLength">
    <properties>
      <property name="lineLimit" value="120"/>
      <property name="absoluteLineLimit" value="0"/>
    </properties>
  </rule>

<!-- There MUST NOT be trailing whitespace at the end of non-blank lines. -->
  <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace">
    <properties>
      <property name="ignoreBlankLines" value="true"/>
    </properties>
  </rule>
  <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace.StartFile">
    <severity>0</severity>
  </rule>
  <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace.EndFile">
    <severity>0</severity>
  </rule>
  <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace.EmptyLines">
    <severity>0</severity>
  </rule>

<!-- There MUST NOT be more than one statement per line. -->
  <rule ref="Generic.Formatting.DisallowMultipleStatements"/>

<!-- 2.4 Indenting -->

<!-- Code MUST use an indent of 4 spaces, and MUST NOT use tabs for indenting. -->
  <rule ref="Generic.WhiteSpace.ScopeIndent">
    <properties>
      <property name="ignoreIndentationTokens" type="array" value="T_COMMENT,T_DOC_COMMENT_OPEN_TAG"/>
      <property name="indent" type="int" value="2"/>
    </properties>
  </rule>
  <rule ref="Generic.WhiteSpace.DisallowTabIndent"/>

<!-- 2.5 Keywords and True/False/Null -->

<!-- PHP keywords MUST be in lower case. -->
  <rule ref="Generic.PHP.LowerCaseKeyword"/>

<!-- The PHP constants true, false, and null MUST be in lower case. -->
  <rule ref="Generic.PHP.LowerCaseConstant"/>

<!-- 3. Namespace and Use Declarations -->

<!-- When present, there MUST be one blank line after the namespace declaration. -->
<!-- checked in Namespaces/NamespaceDeclarationSniff -->

<!-- When present, all use declarations MUST go after the namespace declaration.
      There MUST be one use keyword per declaration.
      There MUST be one blank line after the use block. -->
<!-- checked in Namespaces/UseDeclarationSniff -->

<!-- 4. Classes, Properties, and Methods -->

<!-- 4.1. Extends and Implements -->

<!-- The extends and implements keywords MUST be declared on the same line as the class name.
      The opening brace for the class go MUST go on its own line; the closing brace for the class MUST go on the next line after the body.
      Lists of implements MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one interface per line. -->
<!-- checked in Classes/ClassDeclarationSniff -->

<!-- 4.2. Properties -->

<!-- Visibility MUST be declared on all properties.
      The var keyword MUST NOT be used to declare a property.
      There MUST NOT be more than one property declared per statement.
      Property names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility. -->
<!-- checked in Classes/PropertyDeclarationSniff -->

<!-- 4.3 Methods -->

<!-- Visibility MUST be declared on all methods. -->
  <rule ref="Squiz.Scope.MethodScope"/>
  <rule ref="Squiz.WhiteSpace.ScopeKeywordSpacing"/>

<!-- Method names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility. -->
<!-- checked in Methods/MethodDeclarationSniff -->

<!-- Method names MUST NOT be declared with a space after the method name. The opening brace MUST go on its own line, and the closing brace MUST go on the next line following the body. There MUST NOT be a space after the opening parenthesis, and there MUST NOT be a space before the closing parenthesis. -->
  <rule ref="Squiz.Functions.FunctionDeclaration"/>
  <rule ref="Squiz.Functions.LowercaseFunctionKeywords"/>

<!-- 4.4 Method Arguments -->

<!-- In the argument list, there MUST NOT be a space before each comma, and there MUST be one space after each comma. -->
  <rule ref="Squiz.Functions.FunctionDeclarationArgumentSpacing">
    <properties>
      <property name="equalsSpacing" value="1"/>
    </properties>
  </rule>
  <rule ref="Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterHint">
    <severity>0</severity>
  </rule>

<!-- Method arguments with default values MUST go at the end of the argument list. -->
  <rule ref="PEAR.Functions.ValidDefaultValue"/>

<!-- Argument lists MAY be split across multiple lines, where each subsequent
  line is indented once. When doing so, the first item in the list MUST be on
  the next line, and there MUST be only one argument per line. When the argument
  list is split across multiple lines, the closing parenthesis and opening brace
  MUST be placed together on their own line with one space between them. -->
  <rule ref="Squiz.Functions.MultiLineFunctionDeclaration">
    <exclude name="Squiz.Functions.MultiLineFunctionDeclaration.OneParamPerLine"/>
  </rule>

<!-- 4.5 abstract, final, and static -->

<!-- When present, the abstract and final declarations MUST precede the
  visibility declaration.
  When present, the static declaration MUST come after the visibility declaration. -->
<!-- checked in Methods/MethodDeclarationSniff -->

<!-- 4.6 Method and Function Calls -->

<!-- When making a method or function call, there MUST NOT be a space between
 the method or function name and the opening parenthesis, there MUST NOT be a
 space after the opening parenthesis, and there MUST NOT be a space before the
 closing parenthesis. In the argument list, there MUST NOT be a space before
 each comma, and there MUST be one space after each comma.
 Argument lists MAY be split across multiple lines, where each subsequent line
 is indented once. When doing so, the first item in the list MUST be on the
 next line, and there MUST be only one argument per line. -->
  <rule ref="Generic.Functions.FunctionCallArgumentSpacing"/>
  <!-- <rule ref="PSR2.Methods.FunctionCallSignature.SpaceAfterCloseBracket">
    <severity>0</severity>
    <properties>
      <property name="indent" value="4"/>
    </properties>
  </rule> -->

<!-- 5. Control Structures -->

<!-- The general style rules for control structures are as follows:
 There MUST be one space after the control structure keyword
 There MUST NOT be a space after the opening parenthesis
 There MUST NOT be a space before the closing parenthesis
 There MUST be one space between the closing parenthesis and the opening brace
 The structure body MUST be indented once
 The closing brace MUST be on the next line after the body -->
  <rule ref="Squiz.ControlStructures.ControlSignature"/>
  <rule ref="Squiz.WhiteSpace.ScopeClosingBrace"/>
  <rule ref="Squiz.ControlStructures.ForEachLoopDeclaration"/>
  <rule ref="Squiz.ControlStructures.ForLoopDeclaration"/>
  <rule ref="Squiz.ControlStructures.LowercaseDeclaration"/>
<!-- checked in ControlStructures/ControlStructureSpacingSniff -->

<!-- The body of each structure MUST be enclosed by braces. This standardizes how the structures look, and reduces the likelihood of introducing errors as new lines get added to the body. -->
  <rule ref="Generic.ControlStructures.InlineControlStructure"/>

<!-- 5.1. if, elseif, else -->

<!-- The keyword elseif SHOULD be used instead of else if so that all control keywords look like single words. -->
<!-- checked in ControlStructures/ElseIfDeclarationSniff -->

<!-- 5.2. switch, case -->

<!-- The case statement MUST be indented once from switch, and the break keyword (or other terminating keyword) MUST be indented at the same level as the case body. There MUST be a comment such as // no break when fall-through is intentional in a non-empty case body. -->
<!-- checked in ControlStructures/SwitchDeclarationSniff -->

<!-- 6. Closures -->

<!-- Closures MUST be declared with a space after the function keyword, and a space before and after the use keyword.
 The opening brace MUST go on the same line, and the closing brace MUST go on the next line following the body.
 There MUST NOT be a space after the opening parenthesis of the argument list or variable list, and there MUST NOT be a space before the closing parenthesis of the argument list or variable list.
 In the argument list and variable list, there MUST NOT be a space before each comma, and there MUST be one space after each comma.
 Closure arguments with default values MUST go at the end of the argument list.
 Argument lists and variable lists MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one argument or variable per line.
 When the ending list (whether or arguments or variables) is split across multiple lines, the closing parenthesis and opening brace MUST be placed together on their own line with one space between them. -->
<!-- checked in Squiz.Functions.MultiLineFunctionDeclaration -->
</ruleset>

It looks like I customized the PSR2 ruleset a little bit, I'm not entirely sure though... 😛.

frytyler commented 8 years ago

@Arcanemagus so it seems like you have to define all the rules in there instead of just the ones you want to override. Even if the rule is just pointing to the default Squiz library etc.

How close is that above example to the standard or are you not sure.

PS. Thanks a lot for your quick responses.

Arcanemagus commented 8 years ago

The PSR2 standard is available here: https://github.com/squizlabs/PHP_CodeSniffer/blob/master/CodeSniffer/Standards/PSR2/ruleset.xml

As for how close that is, I have no idea as I haven't touched that in a year or so 😛.