2017-08-14 05:01:11 +02:00
"use strict" ;
/ * *
* @ license
* Copyright 2017 Palantir Technologies , Inc .
*
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
var tslib _1 = require ( "tslib" ) ;
var tsutils _1 = require ( "tsutils" ) ;
var ts = require ( "typescript" ) ;
var Lint = require ( "../index" ) ;
var OPTION _ALWAYS = "always" ;
2017-10-14 18:40:54 +02:00
var Rule = /** @class */ ( function ( _super ) {
2017-08-14 05:01:11 +02:00
tslib _1 . _ _extends ( Rule , _super ) ;
function Rule ( ) {
return _super !== null && _super . apply ( this , arguments ) || this ;
}
Rule . prototype . apply = function ( sourceFile ) {
return this . applyWithFunction ( sourceFile , walk , { always : this . ruleArguments . indexOf ( OPTION _ALWAYS ) !== - 1 } ) ;
} ;
/* tslint:disable:object-literal-sort-keys */
Rule . metadata = {
ruleName : "switch-final-break" ,
description : "Checks whether the final clause of a switch statement ends in \`break;\`." ,
2018-09-20 02:56:13 +02:00
hasFix : true ,
optionsDescription : Lint . Utils . dedent ( templateObject _1 || ( templateObject _1 = tslib _1 . _ _makeTemplateObject ( [ "\n If no options are passed, a final 'break;' is forbidden.\n If the \"always\" option is passed this will require a 'break;' to always be present\n unless control flow is escaped in some other way." ] , [ "\n If no options are passed, a final 'break;' is forbidden.\n If the \"always\" option is passed this will require a 'break;' to always be present\n unless control flow is escaped in some other way." ] ) ) ) ,
2017-08-14 05:01:11 +02:00
options : {
type : "string" ,
enum : [
OPTION _ALWAYS ,
] ,
} ,
optionExamples : [ true , [ true , OPTION _ALWAYS ] ] ,
type : "style" ,
typescriptOnly : false ,
} ;
/* tslint:enable:object-literal-sort-keys */
Rule . FAILURE _STRING _ALWAYS = "Final clause in 'switch' statement should end with 'break;'." ;
Rule . FAILURE _STRING _NEVER = "Final clause in 'switch' statement should not end with 'break;'." ;
return Rule ;
} ( Lint . Rules . AbstractRule ) ) ;
exports . Rule = Rule ;
function walk ( ctx ) {
var sourceFile = ctx . sourceFile , always = ctx . options . always ;
ts . forEachChild ( sourceFile , function cb ( node ) {
if ( tsutils _1 . isSwitchStatement ( node ) ) {
check ( node ) ;
}
ts . forEachChild ( node , cb ) ;
} ) ;
function check ( node ) {
var clause = last ( node . caseBlock . clauses ) ;
if ( clause === undefined ) {
return ;
}
if ( always ) {
if ( ! tsutils _1 . endsControlFlow ( clause ) ) {
2018-09-20 02:56:13 +02:00
ctx . addFailureAtNode ( clause . getChildAt ( 0 ) , Rule . FAILURE _STRING _ALWAYS , createAddFix ( clause ) ) ;
2017-08-14 05:01:11 +02:00
}
return ;
}
2018-09-20 02:56:13 +02:00
var lastStatement = getLastStatement ( clause ) ;
if ( lastStatement === undefined || ! tsutils _1 . isBreakStatement ( lastStatement ) ) {
2017-08-14 05:01:11 +02:00
return ;
}
2018-09-20 02:56:13 +02:00
if ( lastStatement . label !== undefined ) {
var parent = node . parent ;
if ( ! tsutils _1 . isLabeledStatement ( parent ) || parent . label === lastStatement . label ) {
// break jumps somewhere else, don't complain
return ;
2017-08-14 05:01:11 +02:00
}
}
2018-09-20 02:56:13 +02:00
ctx . addFailureAtNode ( lastStatement , Rule . FAILURE _STRING _NEVER , createRemoveFix ( lastStatement ) ) ;
2017-08-14 05:01:11 +02:00
}
2018-09-20 02:56:13 +02:00
function createAddFix ( clause ) {
var lastStatement = getLastStatement ( clause ) ;
if ( lastStatement === undefined ) {
return Lint . Replacement . appendText ( clause . end , " break;" ) ;
}
var fullText = lastStatement . getFullText ( ctx . sourceFile ) ;
var indentation = fullText . slice ( 0 , fullText . search ( /\S+/ ) ) ;
return Lint . Replacement . appendText ( lastStatement . end , indentation + "break;" ) ;
}
function createRemoveFix ( lastStatement ) {
return Lint . Replacement . replaceFromTo ( lastStatement . getFullStart ( ) , lastStatement . end , "" ) ;
}
}
function getLastStatement ( clause ) {
if ( clause . statements . length === 0 ) {
return undefined ;
}
var block = clause . statements [ 0 ] ;
var statements = clause . statements . length === 1 && tsutils _1 . isBlock ( block ) ? block . statements : clause . statements ;
return last ( statements ) ;
2017-08-14 05:01:11 +02:00
}
function last ( arr ) {
return arr [ arr . length - 1 ] ;
}
2018-09-20 02:56:13 +02:00
var templateObject _1 ;