2017-05-28 00:38:50 +02:00
"use strict" ;
/ * *
* @ license
* Copyright 2013 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" ) ;
2017-08-14 05:01:11 +02:00
var tsutils _1 = require ( "tsutils" ) ;
2017-05-28 00:38:50 +02:00
var ts = require ( "typescript" ) ;
var Lint = require ( "../index" ) ;
var OPTION _USE _TABS = "tabs" ;
var OPTION _USE _SPACES = "spaces" ;
var OPTION _INDENT _SIZE _2 = 2 ;
var OPTION _INDENT _SIZE _4 = 4 ;
var Rule = ( function ( _super ) {
tslib _1 . _ _extends ( Rule , _super ) ;
function Rule ( ) {
return _super !== null && _super . apply ( this , arguments ) || this ;
}
2017-08-14 05:01:11 +02:00
/* tslint:enable:object-literal-sort-keys */
Rule . FAILURE _STRING = function ( expected ) {
return expected + " indentation expected" ;
} ;
2017-05-28 00:38:50 +02:00
Rule . prototype . apply = function ( sourceFile ) {
2017-08-14 05:01:11 +02:00
var options = parseOptions ( this . ruleArguments ) ;
return options === undefined ? [ ] : this . applyWithFunction ( sourceFile , walk , options ) ;
} ;
/* tslint:disable:object-literal-sort-keys */
Rule . metadata = {
ruleName : "indent" ,
description : "Enforces indentation with tabs or spaces." ,
rationale : ( _a = [ "\n Using only one of tabs or spaces for indentation leads to more consistent editor behavior,\n cleaner diffs in version control, and easier programmatic manipulation." ] , _a . raw = [ "\n Using only one of tabs or spaces for indentation leads to more consistent editor behavior,\n cleaner diffs in version control, and easier programmatic manipulation." ] , Lint . Utils . dedent ( _a ) ) ,
optionsDescription : ( _b = [ "\n One of the following arguments must be provided:\n\n * `" , "` enforces consistent spaces.\n * `" , "` enforces consistent tabs.\n\n A second optional argument specifies indentation size:\n\n * `" , "` enforces 2 space indentation.\n * `" , "` enforces 4 space indentation.\n\n Indentation size is required for auto-fixing, but not for rule checking.\n " ] , _b . raw = [ "\n One of the following arguments must be provided:\n\n * \\`" , "\\` enforces consistent spaces.\n * \\`" , "\\` enforces consistent tabs.\n\n A second optional argument specifies indentation size:\n\n * \\`" , "\\` enforces 2 space indentation.\n * \\`" , "\\` enforces 4 space indentation.\n\n Indentation size is required for auto-fixing, but not for rule checking.\n " ] , Lint . Utils . dedent ( _b , OPTION _USE _SPACES , OPTION _USE _TABS , OPTION _INDENT _SIZE _2 . toString ( ) , OPTION _INDENT _SIZE _4 . toString ( ) ) ) ,
options : {
type : "array" ,
items : [
{
type : "string" ,
enum : [ OPTION _USE _TABS , OPTION _USE _SPACES ] ,
} ,
{
type : "number" ,
enum : [ OPTION _INDENT _SIZE _2 , OPTION _INDENT _SIZE _4 ] ,
} ,
] ,
minLength : 0 ,
maxLength : 5 ,
} ,
optionExamples : [
[ true , OPTION _USE _SPACES ] ,
[ true , OPTION _USE _SPACES , OPTION _INDENT _SIZE _4 ] ,
[ true , OPTION _USE _TABS , OPTION _INDENT _SIZE _2 ] ,
] ,
type : "maintainability" ,
typescriptOnly : false ,
2017-05-28 00:38:50 +02:00
} ;
return Rule ;
} ( Lint . Rules . AbstractRule ) ) ;
exports . Rule = Rule ;
2017-08-14 05:01:11 +02:00
function parseOptions ( ruleArguments ) {
var type = ruleArguments [ 0 ] ;
if ( type !== OPTION _USE _TABS && type !== OPTION _USE _SPACES ) {
return undefined ;
}
var size = ruleArguments [ 1 ] ;
return {
size : size === OPTION _INDENT _SIZE _2 || size === OPTION _INDENT _SIZE _4 ? size : undefined ,
tabs : type === OPTION _USE _TABS ,
} ;
}
function walk ( ctx ) {
var sourceFile = ctx . sourceFile , _a = ctx . options , tabs = _a . tabs , size = _a . size ;
var regExp = tabs ? new RegExp ( " " . repeat ( size === undefined ? 1 : size ) ) : /\t/ ;
var failure = Rule . FAILURE _STRING ( tabs ? "tab" : size === undefined ? "space" : size + " space" ) ;
for ( var _i = 0 , _b = tsutils _1 . getLineRanges ( sourceFile ) ; _i < _b . length ; _i ++ ) {
var _c = _b [ _i ] , pos = _c . pos , contentLength = _c . contentLength ;
if ( contentLength === 0 ) {
continue ;
2017-05-28 00:38:50 +02:00
}
2017-08-14 05:01:11 +02:00
var line = sourceFile . text . substr ( pos , contentLength ) ;
var indentEnd = line . search ( /\S/ ) ;
if ( indentEnd === 0 ) {
continue ;
2017-05-28 00:38:50 +02:00
}
2017-08-14 05:01:11 +02:00
if ( indentEnd === - 1 ) {
indentEnd = contentLength ;
2017-05-28 00:38:50 +02:00
}
2017-08-14 05:01:11 +02:00
var whitespace = line . slice ( 0 , indentEnd ) ;
if ( ! regExp . test ( whitespace ) ) {
continue ;
2017-05-28 00:38:50 +02:00
}
2017-08-14 05:01:11 +02:00
var token = tsutils _1 . getTokenAtPosition ( sourceFile , pos ) ;
if ( token . kind !== ts . SyntaxKind . JsxText &&
( pos >= token . getStart ( sourceFile ) || tsutils _1 . isPositionInComment ( sourceFile , pos , token ) ) ) {
continue ;
}
ctx . addFailureAt ( pos , indentEnd , failure , createFix ( pos , whitespace , tabs , size ) ) ;
}
}
function createFix ( lineStart , fullLeadingWhitespace , tabs , size ) {
if ( size === undefined ) {
return undefined ;
}
var replaceRegExp = tabs
? new RegExp ( "^( {" + size + "})+( {1," + ( size - 1 ) + "})?" , "g" )
: /\t/g ;
var replacement = fullLeadingWhitespace . replace ( replaceRegExp , function ( match ) {
return ( tabs ? "\t" : " " . repeat ( size ) ) . repeat ( Math . ceil ( match . length / size ) ) ;
} ) ;
return new Lint . Replacement ( lineStart , fullLeadingWhitespace . length , replacement ) ;
}
2017-05-28 00:38:50 +02:00
var _a , _b ;