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" ) ;
var tsutils _1 = require ( "tsutils" ) ;
var ts = require ( "typescript" ) ;
2017-08-14 05:01:11 +02:00
var error _1 = require ( "../error" ) ;
2017-05-28 00:38:50 +02:00
var Lint = require ( "../index" ) ;
var OPTION _SINGLE = "single" ;
var OPTION _DOUBLE = "double" ;
var OPTION _JSX _SINGLE = "jsx-single" ;
var OPTION _JSX _DOUBLE = "jsx-double" ;
var OPTION _AVOID _TEMPLATE = "avoid-template" ;
var OPTION _AVOID _ESCAPE = "avoid-escape" ;
var Rule = ( function ( _super ) {
tslib _1 . _ _extends ( Rule , _super ) ;
function Rule ( ) {
return _super !== null && _super . apply ( this , arguments ) || this ;
}
/* tslint:enable:object-literal-sort-keys */
Rule . FAILURE _STRING = function ( actual , expected ) {
return actual + " should be " + expected ;
} ;
Rule . prototype . isEnabled = function ( ) {
return _super . prototype . isEnabled . call ( this ) && ( this . ruleArguments [ 0 ] === OPTION _SINGLE || this . ruleArguments [ 0 ] === OPTION _DOUBLE ) ;
} ;
Rule . prototype . apply = function ( sourceFile ) {
var args = this . ruleArguments ;
if ( args . length > 0 ) {
if ( args [ 0 ] !== OPTION _SINGLE && args [ 0 ] !== OPTION _DOUBLE ) {
2017-08-14 05:01:11 +02:00
error _1 . showWarningOnce ( "Warning: First argument to 'quotemark' rule should be \"" + OPTION _SINGLE + "\" or \"" + OPTION _DOUBLE + "\"" ) ;
return [ ] ;
2017-05-28 00:38:50 +02:00
}
}
var quoteMark = args [ 0 ] === OPTION _SINGLE ? "'" : '"' ;
return this . applyWithFunction ( sourceFile , walk , {
avoidEscape : hasArg ( OPTION _AVOID _ESCAPE ) ,
avoidTemplate : hasArg ( OPTION _AVOID _TEMPLATE ) ,
jsxQuoteMark : hasArg ( OPTION _JSX _SINGLE ) ? "'" : hasArg ( OPTION _JSX _DOUBLE ) ? '"' : quoteMark ,
quoteMark : quoteMark ,
} ) ;
function hasArg ( name ) {
return args . indexOf ( name ) !== - 1 ;
}
} ;
2017-08-14 05:01:11 +02:00
/* tslint:disable:object-literal-sort-keys */
Rule . metadata = {
ruleName : "quotemark" ,
description : "Requires single or double quotes for string literals." ,
hasFix : true ,
optionsDescription : ( _a = [ "\n Five arguments may be optionally provided:\n\n * `\"" , "\"` enforces single quotes.\n * `\"" , "\"` enforces double quotes.\n * `\"" , "\"` enforces single quotes for JSX attributes.\n * `\"" , "\"` enforces double quotes for JSX attributes.\n * `\"" , "\"` forbids single-line untagged template strings that do not contain string interpolations.\n * `\"" , "\"` allows you to use the \"other\" quotemark in cases where escaping would normally be required.\n For example, `[true, \"" , "\", \"" , "\"]` would not report a failure on the string literal\n `'Hello \"World\"'`." ] , _a . raw = [ "\n Five arguments may be optionally provided:\n\n * \\`\"" , "\"\\` enforces single quotes.\n * \\`\"" , "\"\\` enforces double quotes.\n * \\`\"" , "\"\\` enforces single quotes for JSX attributes.\n * \\`\"" , "\"\\` enforces double quotes for JSX attributes.\n * \\`\"" , "\"\\` forbids single-line untagged template strings that do not contain string interpolations.\n * \\`\"" , "\"\\` allows you to use the \"other\" quotemark in cases where escaping would normally be required.\n For example, \\`[true, \"" , "\", \"" , "\"]\\` would not report a failure on the string literal\n \\`'Hello \"World\"'\\`." ] , Lint . Utils . dedent ( _a , OPTION _SINGLE , OPTION _DOUBLE , OPTION _JSX _SINGLE , OPTION _JSX _DOUBLE , OPTION _AVOID _TEMPLATE , OPTION _AVOID _ESCAPE , OPTION _DOUBLE , OPTION _AVOID _ESCAPE ) ) ,
options : {
type : "array" ,
items : {
type : "string" ,
enum : [ OPTION _SINGLE , OPTION _DOUBLE , OPTION _JSX _SINGLE , OPTION _JSX _DOUBLE , OPTION _AVOID _ESCAPE ] ,
} ,
minLength : 0 ,
maxLength : 5 ,
} ,
optionExamples : [
[ true , OPTION _SINGLE , OPTION _AVOID _ESCAPE , OPTION _AVOID _TEMPLATE ] ,
[ true , OPTION _SINGLE , OPTION _JSX _DOUBLE ] ,
] ,
type : "style" ,
typescriptOnly : false ,
} ;
2017-05-28 00:38:50 +02:00
return Rule ;
} ( Lint . Rules . AbstractRule ) ) ;
exports . Rule = Rule ;
function walk ( ctx ) {
var sourceFile = ctx . sourceFile , options = ctx . options ;
ts . forEachChild ( sourceFile , function cb ( node ) {
if ( tsutils _1 . isStringLiteral ( node )
|| options . avoidTemplate && tsutils _1 . isNoSubstitutionTemplateLiteral ( node )
&& node . parent . kind !== ts . SyntaxKind . TaggedTemplateExpression
&& tsutils _1 . isSameLine ( sourceFile , node . getStart ( sourceFile ) , node . end ) ) {
var expectedQuoteMark = node . parent . kind === ts . SyntaxKind . JsxAttribute ? options . jsxQuoteMark : options . quoteMark ;
var actualQuoteMark = sourceFile . text [ node . end - 1 ] ;
if ( actualQuoteMark === expectedQuoteMark ) {
return ;
}
var fixQuoteMark = expectedQuoteMark ;
var needsQuoteEscapes = node . text . includes ( expectedQuoteMark ) ;
if ( needsQuoteEscapes && options . avoidEscape ) {
if ( node . kind === ts . SyntaxKind . StringLiteral ) {
return ;
}
// If expecting double quotes, fix a template `a "quote"` to `a 'quote'` anyway,
// always preferring *some* quote mark over a template.
fixQuoteMark = expectedQuoteMark === '"' ? "'" : '"' ;
if ( node . text . includes ( fixQuoteMark ) ) {
return ;
}
}
var start = node . getStart ( sourceFile ) ;
var text = sourceFile . text . substring ( start + 1 , node . end - 1 ) ;
if ( needsQuoteEscapes ) {
text = text . replace ( new RegExp ( fixQuoteMark , "g" ) , "\\" + fixQuoteMark ) ;
}
text = text . replace ( new RegExp ( "\\\\" + actualQuoteMark , "g" ) , actualQuoteMark ) ;
return ctx . addFailure ( start , node . end , Rule . FAILURE _STRING ( actualQuoteMark , fixQuoteMark ) , new Lint . Replacement ( start , node . end - start , fixQuoteMark + text + fixQuoteMark ) ) ;
}
ts . forEachChild ( node , cb ) ;
} ) ;
}
var _a ;