Skip to content

Commit

Permalink
Merge pull request #17 from ckeditor/ck/11473
Browse files Browse the repository at this point in the history
Feature (eslint-plugin-ckeditor5-rules): Added fixer for the `license-header` rule. Closes ckeditor/ckeditor5#11473.

Tests (eslint-plugin-ckeditor5-rules): Added support for using fixtures in tests. Currently only implemented in the `license-header` rule tests. Closes ckeditor/ckeditor5#11473.
  • Loading branch information
pomek authored May 17, 2023
2 parents c2c1ad8 + 9a422f7 commit 2873ecc
Show file tree
Hide file tree
Showing 32 changed files with 391 additions and 253 deletions.
3 changes: 2 additions & 1 deletion packages/eslint-plugin-ckeditor5-rules/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ module.exports = {
},
rules: {
'no-console': 'off'
}
},
ignorePatterns: [ 'fixtures' ]
};
167 changes: 101 additions & 66 deletions packages/eslint-plugin-ckeditor5-rules/lib/rules/license-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module.exports = {
description: 'Enforce the presence of a @license header.',
category: 'CKEditor5'
},
fixable: 'code',
schema: [
{
type: 'object',
Expand All @@ -32,75 +33,109 @@ module.exports = {
console.error( 'The license-header rule is missing the "headerLines" configuration.' );
}

const headerHeight = headerLines.length;
const headerText = headerLines.join( '\n' );
const sourceCode = context.getSourceCode();

return {
Program( node ) {
const leadingComments = sourceCode.getComments( node.body[ 0 ] || node ).leading;
const leadingShebang = leadingComments.find( comment => comment.type === 'Shebang' );
const leadingComment = leadingComments.find( comment => comment.type === 'Block' );
const isLeadingCommentALicenseComment = leadingComment &&
sourceCode.getText( leadingComment ).toLowerCase().includes( '@license' );

if ( isLeadingCommentALicenseComment ) {
const leadingCommentText = sourceCode.getText( leadingComment );

if ( leadingCommentText !== headerText ) {
context.report( {
node: leadingComment,
message: 'The license header is incorrect.'
} );
}
Program() {
licenseHeaderRule( context, headerLines );
}
};
}
};

if ( !leadingShebang && leadingComment.loc.start.line > 1 ) {
context.report( {
loc: {
start: {
line: 0,
column: 0
},
end: {
line: 0,
column: 1
}
},
message: 'There is an extra new line before the license header.'
} );
}
function licenseHeaderRule( context, headerLines ) {
const headerText = headerLines.join( '\n' );
const sourceCode = context.getSourceCode();
const fullSourceString = sourceCode.lines.join( '\n' );

if ( sourceCode.lines[ leadingComment.loc.end.line ] != '' ) {
context.report( {
loc: {
start: {
line: headerHeight,
column: 0
},
end: {
line: headerHeight,
column: 0
}
},
message: 'There is a new line missing after the license header.'
} );
}
} else {
context.report( {
loc: {
start: {
line: 0,
column: 0
},
end: {
line: 0,
column: 0
}
},
message: 'The license header is missing.'
} );
const comments = sourceCode.getAllComments();
const shebang = comments.find( comment => comment.type === 'Shebang' );
const licenseComment = comments.find( comment => comment.type === 'Block' && comment.value.toLowerCase().includes( '@license' ) );

if ( !licenseComment ) {
const line = shebang ? 2 : 0;

context.report( {
loc: {
start: {
line,
column: 0
},
end: {
line,
column: 0
}
},
message: 'The license header is missing.',
fix: fixer => {
return shebang ?
fixer.insertTextAfter( shebang, '\n\n' + headerText + '\n\n' ) :
fixer.insertTextAfterRange( [ 0, 0 ], headerText + '\n\n' );
}
};
} );

// If there is no license header or we just created it, there is no need for other checks.
return;
}
};

if ( sourceCode.getText( licenseComment ) !== headerText ) {
context.report( {
node: licenseComment,
message: 'The license header is incorrect.',
fix: fixer => fixer.replaceTextRange( licenseComment.range, headerText )
} );
}

const contentBeforeStart = shebang ? shebang.range[ 1 ] : 0;
const contentBeforeRange = [ contentBeforeStart, licenseComment.range[ 0 ] ];
const contentBefore = fullSourceString.slice( ...contentBeforeRange );
const whitespaceOnly = /^\s+$/.test( contentBefore );
const expectedContentBefore = shebang ? '\n\n' : '';

const contentBeforeLoc = {
start: {
line: 0,
column: shebang ? shebang.loc.end.column : 0
},
end: {
line: licenseComment.loc.start.line,
column: licenseComment.loc.start.column
}
};

if ( contentBefore !== expectedContentBefore && whitespaceOnly ) {
context.report( {
loc: contentBeforeLoc,
message: 'Incorrect whitespace before the license header.',
fix: fixer => fixer.replaceTextRange( contentBeforeRange, expectedContentBefore )
} );
} else if ( contentBefore !== expectedContentBefore && !whitespaceOnly ) {
context.report( {
loc: contentBeforeLoc,
message: 'Unexpected content before the license header.'
} );
}

const followingToken = sourceCode.getTokenAfter( licenseComment, { includeComments: true } );

if ( !followingToken ) {
return;
}

const contentBetween = fullSourceString.slice( licenseComment.range[ 1 ], followingToken.range[ 0 ] );

if ( !contentBetween.startsWith( '\n\n' ) ) {
context.report( {
loc: {
start: {
line: licenseComment.loc.end.line,
column: licenseComment.loc.end.column
},
end: {
line: followingToken.loc.start.line,
column: followingToken.loc.start.column
}
},
message: 'Incorrect whitespace after the license header.',
fix: fixer => fixer.replaceTextRange( [ licenseComment.range[ 1 ], followingToken.range[ 0 ] ], '\n\n' )
} );
}
}
34 changes: 34 additions & 0 deletions packages/eslint-plugin-ckeditor5-rules/tests/fixture-loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md.
*/

const fs = require( 'fs' );
const path = require( 'path' );

const fixtureTypes = [
'valid',
'invalid'
];

module.exports = function fixtureLoader( ruleName ) {
const fixtures = {};

for ( const fixtureType of fixtureTypes ) {
const typeDir = path.join( __dirname, 'fixtures', ruleName, fixtureType );

fixtures[ fixtureType ] = fs.readdirSync( typeDir ).reduce( ( output, filename ) => {
const fixturePath = path.join( typeDir, filename );
const fixtureContent = fs.readFileSync( fixturePath, 'utf-8' );
const fixtureKey = filename
.replace( '.js', '' )
.replace( /-/g, '_' );

output[ fixtureKey ] = fixtureContent;

return output;
}, {} );
}

return fixtures;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* @LICENSE COPYRIGHT (C) 2003-2022, CKSOURCE HOLDING SP. Z O.O. ALL RIGHTS RESERVED.
* FOR LICENSING, SEE LICENSE.MD OR HTTPS://CKEDITOR.COM/LEGAL/CKEDITOR-OSS-LICENSE
*/

foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/** foo */
/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

foo()
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env node

foo();

/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env node

// Comment.

/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

/**
* @license TODO
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
// For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license

foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* missing license tag 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env node
/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

/**
* missing license tag 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

// @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
// For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license

foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env node

/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env node

/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
Loading

0 comments on commit 2873ecc

Please sign in to comment.