Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 53 |
|
0.00% |
0 / 2 |
CRAP | |
0.00% |
0 / 1 |
ClassLevelLicenseSniff | |
0.00% |
0 / 53 |
|
0.00% |
0 / 2 |
240 | |
0.00% |
0 / 1 |
register | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
process | |
0.00% |
0 / 52 |
|
0.00% |
0 / 1 |
210 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Sniffs\Commenting; |
4 | |
5 | use PHP_CodeSniffer\Files\File; |
6 | use PHP_CodeSniffer\Sniffs\Sniff; |
7 | use PHP_CodeSniffer\Util\Tokens; |
8 | |
9 | /** |
10 | * Custom sniff that requires all classes, interfaces, traits, and enums in a codebase to have the same |
11 | * license doc tag. Note this sniff doesn't do anything by default. You need to enable it in your |
12 | * .phpcs.xml if you want to use it: |
13 | * <rule ref="MediaWiki.Commenting.ClassLevelLicense"> |
14 | * <properties> |
15 | * <property name="license" value="GPL-2.0-or-later" /> |
16 | * </properties> |
17 | * </rule> |
18 | * |
19 | * Doing so makes the LicenseComment sniff obsolete. You might want to disable it: |
20 | * <exclude name="MediaWiki.Commenting.LicenseComment" /> |
21 | * |
22 | * @license GPL-2.0-or-later |
23 | * @author Thiemo Kreuz |
24 | */ |
25 | class ClassLevelLicenseSniff implements Sniff { |
26 | |
27 | /** |
28 | * @var string Typically "GPL-2.0-or-later", empty by default |
29 | */ |
30 | public string $license = ''; |
31 | |
32 | /** |
33 | * @inheritDoc |
34 | */ |
35 | public function register(): array { |
36 | return [ T_CLASS, T_INTERFACE, T_TRAIT, T_ENUM ]; |
37 | } |
38 | |
39 | /** |
40 | * @inheritDoc |
41 | */ |
42 | public function process( File $phpcsFile, $stackPtr ) { |
43 | // This sniff requires you to set a <property name="license" …> in your .phpcs.xml |
44 | if ( !$this->license ) { |
45 | return $phpcsFile->numTokens; |
46 | } |
47 | |
48 | $tokens = $phpcsFile->getTokens(); |
49 | |
50 | // All auto-fixes below assume we are on the top level |
51 | if ( $tokens[$stackPtr]['level'] !== 0 ) { |
52 | // @codeCoverageIgnoreStart |
53 | return; |
54 | // @codeCoverageIgnoreEnd |
55 | } |
56 | |
57 | $skip = Tokens::$methodPrefixes; |
58 | $skip[] = T_WHITESPACE; |
59 | $closer = $phpcsFile->findPrevious( $skip, $stackPtr - 1, null, true ); |
60 | |
61 | if ( $tokens[$closer]['code'] !== T_DOC_COMMENT_CLOSE_TAG ) { |
62 | $fix = $phpcsFile->addFixableError( |
63 | 'All code in this codebase should have a @license tag', |
64 | $stackPtr, |
65 | 'Missing' |
66 | ); |
67 | if ( $fix ) { |
68 | $phpcsFile->fixer->addContentBefore( |
69 | $stackPtr, |
70 | "/**\n * @license $this->license\n */\n" |
71 | ); |
72 | } |
73 | return; |
74 | } |
75 | |
76 | if ( !isset( $tokens[$closer]['comment_opener'] ) ) { |
77 | // @codeCoverageIgnoreStart |
78 | // Live coding |
79 | return; |
80 | // @codeCoverageIgnoreEnd |
81 | } |
82 | |
83 | $opener = $tokens[$closer]['comment_opener']; |
84 | foreach ( $tokens[$opener]['comment_tags'] as $ptr ) { |
85 | $tag = $tokens[$ptr]['content']; |
86 | if ( strncasecmp( $tag, '@licen', 6 ) !== 0 ) { |
87 | continue; |
88 | } |
89 | |
90 | if ( !isset( $tokens[$ptr + 2] ) |
91 | || $tokens[$ptr + 2]['code'] !== T_DOC_COMMENT_STRING |
92 | ) { |
93 | $fix = $phpcsFile->addFixableError( |
94 | 'All code in this codebase should be tagged with "%s %s", found empty "%s" instead', |
95 | $ptr, |
96 | 'Empty', |
97 | [ $tag, $this->license, $tag ] |
98 | ); |
99 | if ( $fix ) { |
100 | $phpcsFile->fixer->addContent( $ptr, " $this->license" ); |
101 | } |
102 | } elseif ( $tokens[$ptr + 2]['content'] !== $this->license ) { |
103 | $fix = $phpcsFile->addFixableError( |
104 | 'All code in this codebase should be tagged with "%s %s", found "%s %s" instead', |
105 | $ptr + 2, |
106 | 'WrongLicense', |
107 | [ $tag, $this->license, $tag, $tokens[$ptr + 2]['content'] ] |
108 | ); |
109 | if ( $fix ) { |
110 | $phpcsFile->fixer->replaceToken( $ptr + 2, $this->license ); |
111 | } |
112 | } |
113 | |
114 | // This sniff intentionally checks the first @license tag only |
115 | return; |
116 | } |
117 | |
118 | $fix = $phpcsFile->addFixableError( |
119 | 'All code in this codebase should have a @license tag', |
120 | $opener, |
121 | 'Missing' |
122 | ); |
123 | if ( $fix ) { |
124 | $phpcsFile->fixer->addContentBefore( $closer, "* @license $this->license\n " ); |
125 | } |
126 | } |
127 | |
128 | } |