squizlabs / PHP_CodeSniffer

PHP_CodeSniffer tokenizes PHP files and detects violations of a defined set of coding standards.
BSD 3-Clause "New" or "Revised" License
10.67k stars 1.48k forks source link

Exclude files relative to the root of the project #981

Open glen-84 opened 8 years ago

glen-84 commented 8 years ago

I want to be able to exclude everything under the /data folder. There appear to be two options here, neither of which solve the problem:

  1. <exclude-pattern>*/data/*</exclude-pattern> – this will exclude files under any data folder, not just the one in the root of the project.
  2. <exclude-pattern type="relative">^/data/*</exclude-pattern> – this will exclude files under the data folder, but it won't work if you run phpcs for a specific file (which is how I assume most editor extensions work).

Is it somehow possible to have an exclusion of /data/* that works relative to the root of the project?

gsherwood commented 8 years ago

I can't think of a way you'll be able to do this, or even an easy PHPCS change that would make it possible. PHPCS doesn't know where your project root is, and it has even less information when an IDE is giving it a very specific file location, or a chunk of content on STDIN.

Something that might be possible is to add a new type of exclude-pattern that works relative to the coding standard ruleset.xml file it is defined in. If you then used a phpcs.xml file in your project's root directory, and you let PHPCS auto-detect this (or specify the location in an IDE) then any paths that are checked under that root location could be made relative to the root.

Maybe something like:

<exclude-pattern type="relative-root">^/Tests/*</exclude-pattern>
aik099 commented 8 years ago

If standard is included through composer and folder structure is like this, then this won't be much helpful:

/path/to/project
/path/to/project/vendor/aik099/coding-standard/CodingStandard/ruleset.xml
glen-84 commented 8 years ago

@gsherwood,

root-relative might sound better than relative-root (similar to root-relative URLs). Although, it might be considered standard-relative.

The only other option would be for linting extensions to read the phpcs.xml file, and ignore everything that is not defined in a <file> element.

@aik099,

You could just create a phpcs.xml file in the root of your project that references the standard in the vendor directory. This is usually a good idea anyway, to define other project-specific settings like encoding, extensions, files, etc.

aik099 commented 8 years ago

I'll try that sometime, thanks. As a good developer I try to follow the rule: if it works, then don't change it. Currently I specify command line arguments in the ruleset.xml of custom standard I'm using and not using exclusion rules based on relative paths.

gsherwood commented 8 years ago

root-relative might sound better than relative-root (similar to root-relative URLs).

I think you're right.

Although, it might be considered standard-relative.

Good point. It is certainly relative to the location of the ruleset and not the location of any project "root" directory.

I've turned this into a feature request. I have no idea when I can get around to it yet, but it feels like something that will be helpful, or at least needs more thought.

oligriffiths commented 6 years ago

I am also encountering this problem and it's pretty irritating not being able to filter a file/directory out in relative move. This recently bit me as the OP suggests that */data/* is overly greedy. Can we use the basepath config parameter to determine the root? It seems that https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Filters/Filter.php#L219 needs to be aware of the basepath rather than the folder root that the file was loaded from. Could this work instead?

$basepath = $this->config->basepath ?: $this->basedir;
if (strpos($path, $basepath) === 0) {
    // The +1 cuts off the directory separator as well.
    $relativePath = substr($path, (strlen($basepath) + 1));
}

This would allow for a basepath override by CLI or by phpcs.xml

gsherwood commented 6 years ago

Could this work instead?

I don't think so. It would be a significant change of behaviour and would promote the basepath setting from a cosmetic setting (simplifies report output) to a core setting that allows you to change the cwd for (at least) filtering.

oliwierptak commented 6 years ago

hey guys, I think I kinda solved that.

I needed to exclude some directories from updaging the FQCNs and came up with this: https://github.com/oliwierptak/coding-standard/blob/master/coding-standard/Everon/Sniffs/Files/TypeNameMatchesFileNameSniff.php

Configuration example in project: https://github.com/oliwierptak/popo/blob/master/coding-standard/EveronCodingStandard/ruleset.xml

It works for me, so maybe it will be helpful to somebody else as well.

C-Duv commented 4 years ago

So, there is, currently, no way of ignoring a folder located at the root of our project using a <exclude-pattern> without using absolute path (which changes between users/computers/servers)? The following documentation example is then invalid:

<!--
    Patterns can be specified as relative if you would
    like the relative path of the file checked instead of the
    full path. This can sometimes help with portability.

    The relative path is determined based on the paths you
    pass into PHP_CodeSniffer on the command line.
 -->
 <exclude-pattern type="relative">^/tests/*</exclude-pattern>
 <exclude-pattern type="relative">^/data/*</exclude-pattern>

Is it related to https://github.com/squizlabs/PHP_CodeSniffer/blob/278b643f2a5ec1b92fd60b2d7dac034f3a52ea4e/src/Files/File.php#L445-L461 which states While there is support for a type of each pattern (absolute or relative) we don't actually support it here.?

weitzman commented 4 years ago

FYI there is a way in the documentation now. It didn't work for me but might for you.

 <exclude-pattern type="relative">^/tests/*</exclude-pattern>
 <exclude-pattern type="relative">^/data/*</exclude-pattern>
danepowell commented 3 years ago

<exclude-pattern type="relative"> didn't work for me either. Is there any way to create a truly portable ruleset right now? It seems like you either have to hardcode a full absolute path, which is obviously not portable, or you have to use bare exclude patterns and just hope that some poor unsuspecting user doesn't have them in their base path.