@fimbul/wotan
Advanced tools
Comparing version 0.21.0-dev.20190322 to 0.21.0-dev.20190328
@@ -20,3 +20,7 @@ "use strict"; | ||
class LanguageServiceInterceptor { | ||
constructor(config, project, serverHost, languageService, require, log) { | ||
constructor(config, | ||
// tslint:disable:no-submodule-imports | ||
project, serverHost, | ||
// tslint:enable:no-submodule-imports | ||
languageService, require, log) { | ||
this.config = config; | ||
@@ -155,2 +159,3 @@ this.project = project; | ||
dispose() { | ||
// TODO clean up after ourselves | ||
return this.languageService.dispose(); | ||
@@ -157,0 +162,0 @@ } |
{ | ||
"name": "@fimbul/wotan", | ||
"version": "0.21.0-dev.20190322", | ||
"version": "0.21.0-dev.20190328", | ||
"description": "Pluggable TypeScript and JavaScript linter", | ||
@@ -59,3 +59,3 @@ "bin": "bin/main.js", | ||
"resolve": "^1.5.0", | ||
"semver": "^5.4.1", | ||
"semver": "^6.0.0", | ||
"stable": "^0.1.8", | ||
@@ -62,0 +62,0 @@ "tslib": "^1.8.1", |
@@ -7,2 +7,3 @@ "use strict"; | ||
const log = debug('wotan:argparse'); | ||
// @internal | ||
function parseArguments(args, globalOptions) { | ||
@@ -14,19 +15,19 @@ args = args.map(trimSingleQuotes); | ||
switch (commandName) { | ||
case "lint": | ||
command = parseLintCommand(args.slice(1), defaults = parseGlobalOptions(globalOptions), "lint"); | ||
case "lint" /* Lint */: | ||
command = parseLintCommand(args.slice(1), defaults = parseGlobalOptions(globalOptions), "lint" /* Lint */); | ||
break; | ||
case "save": | ||
command = parseLintCommand(args.slice(1), defaults = parseGlobalOptions(globalOptions), "save"); | ||
case "save" /* Save */: | ||
command = parseLintCommand(args.slice(1), defaults = parseGlobalOptions(globalOptions), "save" /* Save */); | ||
break; | ||
default: | ||
command = | ||
parseLintCommand(args, defaults = parseGlobalOptions(globalOptions), "lint"); | ||
parseLintCommand(args, defaults = parseGlobalOptions(globalOptions), "lint" /* Lint */); | ||
break; | ||
case "test": | ||
case "test" /* Test */: | ||
command = parseTestCommand(args.slice(1)); | ||
break; | ||
case "show": | ||
case "show" /* Show */: | ||
command = parseShowCommand(args.slice(1), defaults = parseGlobalOptions(globalOptions)); | ||
break; | ||
case "validate": | ||
case "validate" /* Validate */: | ||
command = parseValidateCommand(args.slice(1)); | ||
@@ -158,3 +159,3 @@ } | ||
modules, | ||
command: "test", | ||
command: "test" /* Test */, | ||
bail: false, | ||
@@ -236,3 +237,3 @@ files: [], | ||
modules: modules === undefined ? defaults.modules : modules, | ||
command: "show", | ||
command: "show" /* Show */, | ||
file: files[0], | ||
@@ -297,8 +298,8 @@ }; | ||
switch (arg) { | ||
case "json": | ||
case "json5": | ||
case "yaml": | ||
case "json" /* Json */: | ||
case "json5" /* Json5 */: | ||
case "yaml" /* Yaml */: | ||
return arg; | ||
default: | ||
return assertNever(arg, `Argument for option '${opt}' must be one of '${"json"}', '${"json5"}' or '${"yaml"}'.`); | ||
return assertNever(arg, `Argument for option '${opt}' must be one of '${"json" /* Json */}', '${"json5" /* Json5 */}' or '${"yaml" /* Yaml */}'.`); | ||
} | ||
@@ -305,0 +306,0 @@ } |
@@ -20,3 +20,3 @@ "use strict"; | ||
var { command: _command } = _a, config = tslib_1.__rest(_a, ["command"]); | ||
const newContent = utils_1.format(Object.assign({}, this.options, config, { fix: config.fix || undefined, reportUselessDirectives: config.reportUselessDirectives || undefined, references: config.references || undefined }), "yaml"); | ||
const newContent = utils_1.format(Object.assign({}, this.options, config, { fix: config.fix || undefined, reportUselessDirectives: config.reportUselessDirectives || undefined, references: config.references || undefined }), "yaml" /* Yaml */); | ||
const filePath = path.join(this.directories.getCurrentDirectory(), '.fimbullinter.yaml'); | ||
@@ -23,0 +23,0 @@ if (newContent.trim() === '{}') { |
@@ -55,3 +55,3 @@ "use strict"; | ||
throw new ymir_1.ConfigurationError(`Testing file '${file}' outside of '${root}'.`); | ||
const actual = kind === "fix" ? summary.content : baseline_1.createBaseline(summary); | ||
const actual = kind === "fix" /* Fix */ ? summary.content : baseline_1.createBaseline(summary); | ||
const baselineFile = `${path.resolve(baselineDir, relative)}.${kind}`; | ||
@@ -67,3 +67,3 @@ const end = (pass, text, baselineDiff) => { | ||
}; | ||
if (kind === "fix" && summary.fixes === 0) { | ||
if (kind === "fix" /* Fix */ && summary.fixes === 0) { | ||
if (!this.fs.isFile(baselineFile)) | ||
@@ -146,3 +146,3 @@ return true; | ||
for (const [fileName, summary] of lintResult) { | ||
if (!host.checkResult(fileName, "lint", summary)) | ||
if (!host.checkResult(fileName, "lint" /* Lint */, summary)) | ||
return false; | ||
@@ -152,6 +152,6 @@ containsFixes = containsFixes || summary.findings.some(isFixable); | ||
if (config.fix || config.fix === undefined) { | ||
lintOptions.fix = config.fix || true; | ||
lintOptions.fix = config.fix || true; // fix defaults to true if not specified | ||
const fixResult = containsFixes ? this.runner.lintCollection(lintOptions) : lintResult; | ||
for (const [fileName, summary] of fixResult) | ||
if (!host.checkResult(fileName, "fix", summary)) | ||
if (!host.checkResult(fileName, "fix" /* Fix */, summary)) | ||
return false; | ||
@@ -187,2 +187,3 @@ } | ||
} | ||
/** Removes everything related to prereleases and just returns MAJOR.MINOR.PATCH, thus treating prereleases like the stable release. */ | ||
function getNormalizedTypescriptVersion() { | ||
@@ -218,4 +219,4 @@ const v = new semver_1.SemVer(ts.version); | ||
return line | ||
.replace(/\t/g, '\u2409') | ||
.replace(/\r$/, '\u240d') | ||
.replace(/\t/g, '\u2409') // ␉ | ||
.replace(/\r$/, '\u240d') // ␍ | ||
.replace(/^\uFEFF/, '<BOM>'); | ||
@@ -222,0 +223,0 @@ } |
@@ -8,2 +8,9 @@ import * as ts from 'typescript'; | ||
} | ||
/** | ||
* Tries to apply all fixes. The replacements of all fixes are sorted by index ascending. | ||
* They are then applied in order. If a replacement overlaps (or touches) the range of the previous replacement, | ||
* the process rolls back to the state before the first replacement of the offending fix was applied. The replacements | ||
* of this fix are not applied again. | ||
* At least one fix will be applied. | ||
*/ | ||
export declare function applyFixes(source: string, fixes: Fix[]): FixResult; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const stableSort = require("stable"); | ||
/** | ||
* Tries to apply all fixes. The replacements of all fixes are sorted by index ascending. | ||
* They are then applied in order. If a replacement overlaps (or touches) the range of the previous replacement, | ||
* the process rolls back to the state before the first replacement of the offending fix was applied. The replacements | ||
* of this fix are not applied again. | ||
* At least one fix will be applied. | ||
*/ | ||
function applyFixes(source, fixes) { | ||
@@ -26,10 +33,16 @@ let fixed = fixes.length; | ||
if (fix.skip) | ||
continue; | ||
continue; // there was a conflict, don't use replacements of this fix | ||
if (replacement.start <= position) { | ||
// ranges overlap (or have touching boundaries) -> don't fix to prevent unspecified behavior | ||
if (fix.state !== undefined) { | ||
// rollback to state before the first replacement of the fix was applied | ||
const rollbackToIndex = fix.state.index; | ||
for (--i; i !== rollbackToIndex; --i) { | ||
for (--i; i !== rollbackToIndex; --i) { // this automatically resets `i` to the correct position | ||
const f = replacements[i].fix; | ||
// we need to reset all states of fixes that applied their first replacement after | ||
// the first replacement of the just rolled back fix | ||
if (f.state !== undefined && f.state.index === i) | ||
f.state = undefined; | ||
// retry all rolled back fixes, that applied their first replacement after the just rolled back fix | ||
// unfortunately this doesn't take conflicting fixes into account, so we may roll it back later | ||
if (f.state === undefined && f.skip) { | ||
@@ -47,5 +60,7 @@ ++fixed; | ||
} | ||
// save the current state to jump back if necessary | ||
if (fix.state === undefined && fix.replacements.length !== 1) | ||
fix.state = { position, index: i, length: output.length }; | ||
if (position === -1) { | ||
// we are about to apply the first fix | ||
range.span.start = replacement.start; | ||
@@ -73,5 +88,7 @@ output = source.substring(0, replacement.start); | ||
} | ||
/** Combine adjacent replacements to avoid sorting replacements of other fixes between them. */ | ||
function combineReplacements(replacements) { | ||
if (replacements.length === 1) | ||
return replacements; | ||
// use a stable sorting algorithm to avoid shuffling insertions at the same position as these have the same start and end values | ||
replacements = stableSort.inplace(replacements.slice(), compareReplacements); | ||
@@ -78,0 +95,0 @@ const result = []; |
@@ -7,6 +7,14 @@ import * as ts from 'typescript'; | ||
} | ||
/** This factory is used to lazily create or update the Program only when necessary. */ | ||
export interface ProgramFactory { | ||
/** Get the CompilerOptions used to create the Program. */ | ||
getCompilerOptions(): ts.CompilerOptions; | ||
/** This method is called to retrieve the Program on the first use. It should create or update the Program if necessary. */ | ||
getProgram(): ts.Program; | ||
} | ||
/** | ||
* Creates a new SourceFile from the updated source. | ||
* | ||
* @returns the new `SourceFile` on success or `undefined` to roll back the latest set of changes. | ||
*/ | ||
export declare type UpdateFileCallback = (content: string, range: ts.TextChangeRange) => ts.SourceFile | undefined; | ||
@@ -13,0 +21,0 @@ export declare class Linter { |
@@ -81,3 +81,3 @@ "use strict"; | ||
log('Rolling back latest fixes and abort linting'); | ||
if (processor !== undefined) | ||
if (processor !== undefined) // reset processor state | ||
processor.updateSource(content, utils_1.invertChangeRange(fixed.range)); | ||
@@ -97,4 +97,6 @@ break; | ||
} | ||
// @internal | ||
getFindings(sourceFile, config, programFactory, processor, options) { | ||
if (programFactory !== undefined) | ||
// make sure that all rules get the same Program and CompilerOptions for this run | ||
programFactory = new CachedProgramFactory(programFactory); | ||
@@ -137,3 +139,3 @@ let suppressMissingTypeInfoWarning = false; | ||
if (ctor.deprecated) | ||
this.deprecationHandler.handle("rule", ruleName, typeof ctor.deprecated === 'string' ? ctor.deprecated : undefined); | ||
this.deprecationHandler.handle("rule" /* Rule */, ruleName, typeof ctor.deprecated === 'string' ? ctor.deprecated : undefined); | ||
if (programFactory === undefined && ctor.requiresTypeInformation) { | ||
@@ -140,0 +142,0 @@ if (noWarn) { |
@@ -34,2 +34,7 @@ "use strict"; | ||
} | ||
/** | ||
* Try to find and load the configuration for a file. | ||
* If it fails, just continue as if there was no config. | ||
* This may happen during project setup if there is an invalid config file anywhere in a scanned folder. | ||
*/ | ||
tryFindConfig(file) { | ||
@@ -58,3 +63,3 @@ try { | ||
switch (entry.kind) { | ||
case 1: { | ||
case 1 /* File */: { | ||
if (!utils_1.hasSupportedExtension(fileName, additionalExtensions)) { | ||
@@ -82,3 +87,3 @@ const c = this.config || this.tryFindConfig(fileName); | ||
} | ||
case 2: | ||
case 2 /* Directory */: | ||
directories.push(fileName); | ||
@@ -91,6 +96,6 @@ } | ||
switch (this.fs.getKind(file)) { | ||
case 2: | ||
case 3: | ||
case 2 /* Directory */: | ||
case 3 /* Other */: | ||
return false; | ||
case 1: | ||
case 1 /* File */: | ||
return true; | ||
@@ -170,3 +175,3 @@ default: | ||
return cached.directories.map((d) => path.posix.basename(d)); | ||
return utils_1.mapDefined(this.fs.readDirectory(dir), (entry) => entry.kind === 2 ? path.join(dir, entry.name) : undefined); | ||
return utils_1.mapDefined(this.fs.readDirectory(dir), (entry) => entry.kind === 2 /* Directory */ ? path.join(dir, entry.name) : undefined); | ||
} | ||
@@ -189,2 +194,4 @@ getSourceFile(fileName, languageVersion) { | ||
onReleaseOldSourceFile(sourceFile) { | ||
// this is only called for paths that are no longer referenced | ||
// it's safe to remove the cache entry completely because it won't be called with updated SourceFiles | ||
this.uncacheFile(sourceFile.fileName); | ||
@@ -191,0 +198,0 @@ } |
@@ -84,2 +84,3 @@ "use strict"; | ||
} | ||
// either way we need to store the new SourceFile as the old one is now corrupted | ||
processorHost.updateSourceFile(sourceFile); | ||
@@ -125,3 +126,3 @@ return hasErrors ? undefined : sourceFile; | ||
} | ||
if (originalContent === undefined) | ||
if (originalContent === undefined) // might be initialized by the processor requesting the file content | ||
originalContent = this.fs.readFile(file); | ||
@@ -152,2 +153,3 @@ processor = new ctor({ | ||
log("Autofixing caused syntax errors in '%s', rolling back", sourceFile.fileName); | ||
// Note: 'sourceFile' shouldn't be used after this as it contains invalid code | ||
return; | ||
@@ -208,2 +210,3 @@ } | ||
} | ||
// uncache all files of the previous project if they are no longer needed | ||
if (filesOfPreviousProject !== undefined) | ||
@@ -224,5 +227,5 @@ for (const oldFile of filesOfPreviousProject) | ||
switch (this.fs.getKind(fileOrDirName)) { | ||
case 0: | ||
case 0 /* NonExistent */: | ||
throw new ymir_1.ConfigurationError(`The specified path does not exist: '${fileOrDirName}'`); | ||
case 2: { | ||
case 2 /* Directory */: { | ||
const file = utils_1.unixifyPath(path.join(fileOrDirName, 'tsconfig.json')); | ||
@@ -261,3 +264,3 @@ if (!this.fs.isFile(file)) | ||
if (resolvedReferences !== undefined) { | ||
program = undefined; | ||
program = undefined; // allow garbage collection | ||
yield* this.createPrograms(resolvedReferences, host, seen, true, isFileIncluded); | ||
@@ -317,3 +320,3 @@ } | ||
} | ||
return new Set(result.map(utils_1.unixifyPath)); | ||
return new Set(result.map(utils_1.unixifyPath)); // deduplicate files | ||
} | ||
@@ -320,0 +323,0 @@ function ensurePatternsMatch(include, exclude, files, projects) { |
@@ -27,6 +27,6 @@ "use strict"; | ||
isFile(file) { | ||
return utils_1.resolveCachedResult(this.fileKindCache, this.fs.normalizePath(file), this.doGetKind) === 1; | ||
return utils_1.resolveCachedResult(this.fileKindCache, this.fs.normalizePath(file), this.doGetKind) === 1 /* File */; | ||
} | ||
isDirectory(dir) { | ||
return utils_1.resolveCachedResult(this.fileKindCache, this.fs.normalizePath(dir), this.doGetKind) === 2; | ||
return utils_1.resolveCachedResult(this.fileKindCache, this.fs.normalizePath(dir), this.doGetKind) === 2 /* Directory */; | ||
} | ||
@@ -41,3 +41,3 @@ getKind(file) { | ||
catch (_a) { | ||
return 0; | ||
return 0 /* NonExistent */; | ||
} | ||
@@ -80,3 +80,3 @@ } | ||
this.fs.writeFile(file, content); | ||
this.updateCache(file, 1); | ||
this.updateCache(file, 1 /* File */); | ||
} | ||
@@ -86,7 +86,7 @@ remove(file) { | ||
this.fs.deleteFile(file); | ||
this.updateCache(file, 0); | ||
this.updateCache(file, 0 /* NonExistent */); | ||
} | ||
createDirectory(dir) { | ||
dir = this.fs.normalizePath(dir); | ||
if (this.fileKindCache.get(dir) === 2) | ||
if (this.fileKindCache.get(dir) === 2 /* Directory */) | ||
return; | ||
@@ -113,10 +113,12 @@ return this.doCreateDirectory(dir); | ||
} | ||
this.updateCache(dir, 2); | ||
this.updateCache(dir, 2 /* Directory */); | ||
} | ||
updateCache(file, kind) { | ||
// this currently doesn't handle directory removal as there is no API for that | ||
if (this.fileKindCache.get(file) === kind) | ||
return; | ||
this.fileKindCache.set(file, kind); | ||
if (kind === 0) | ||
this.realpathCache.delete(file); | ||
if (kind === 0 /* NonExistent */) | ||
this.realpathCache.delete(file); // only invalidate realpath cache on file removal | ||
// invalidate direntCache unconditionally as the new file's name might differ in case from the one we have here | ||
this.direntCache.delete(this.fs.normalizePath(path.dirname(file))); | ||
@@ -137,4 +139,4 @@ } | ||
function statsToKind(stats) { | ||
return stats.isFile() ? 1 : stats.isDirectory() ? 2 : 3; | ||
return stats.isFile() ? 1 /* File */ : stats.isDirectory() ? 2 /* Directory */ : 3 /* Other */; | ||
} | ||
//# sourceMappingURL=cached-file-system.js.map |
@@ -9,10 +9,29 @@ import { Configuration, CacheFactory, ReducedConfiguration, Settings, DirectoryService, ConfigurationProvider } from '@fimbul/ymir'; | ||
constructor(directories: DirectoryService, configProvider: ConfigurationProvider, fs: CachedFileSystem, cache: CacheFactory); | ||
/** Look up the location of the configuration file for the specified file name. */ | ||
findPath(file: string): string | undefined; | ||
/** Load the configuration for the specified file. */ | ||
find(file: string): Configuration | undefined; | ||
/** Load the given config from a local file if it exists or from the resolved path otherwise */ | ||
loadLocalOrResolved(pathOrName: string, basedir?: string): Configuration; | ||
/** | ||
* Resolve a configuration name to it's absolute path. | ||
* | ||
* @param name | ||
* - name of a builtin config | ||
* - package name in `node_modules` or a submodule thereof | ||
* - absolute path | ||
* - relative path starting with `./` or `../` | ||
*/ | ||
resolve(name: string, basedir: string): string; | ||
/** | ||
* Collects all matching configuration options for the given file. Flattens all base configs and matches overrides. | ||
* Returns `undefined` if the file is excluded in one of the configuraton files. | ||
*/ | ||
reduce(config: Configuration, file: string): ReducedConfiguration | undefined; | ||
/** Get the processor configuration for a given file. */ | ||
getProcessor(config: Configuration, fileName: string): string | undefined; | ||
/** Get the settings for a given file. */ | ||
getSettings(config: Configuration, fileName: string): Settings; | ||
/** Load a configuration from a resolved path using the ConfigurationProvider, recursively resolving and loading base configs. */ | ||
load(fileName: string): Configuration; | ||
} |
@@ -18,2 +18,3 @@ "use strict"; | ||
} | ||
/** Look up the location of the configuration file for the specified file name. */ | ||
findPath(file) { | ||
@@ -28,2 +29,3 @@ file = path.resolve(this.directories.getCurrentDirectory(), file); | ||
} | ||
/** Load the configuration for the specified file. */ | ||
find(file) { | ||
@@ -33,2 +35,3 @@ const config = this.findPath(file); | ||
} | ||
/** Load the given config from a local file if it exists or from the resolved path otherwise */ | ||
loadLocalOrResolved(pathOrName, basedir = this.directories.getCurrentDirectory()) { | ||
@@ -38,2 +41,11 @@ const absolute = path.resolve(basedir, pathOrName); | ||
} | ||
/** | ||
* Resolve a configuration name to it's absolute path. | ||
* | ||
* @param name | ||
* - name of a builtin config | ||
* - package name in `node_modules` or a submodule thereof | ||
* - absolute path | ||
* - relative path starting with `./` or `../` | ||
*/ | ||
resolve(name, basedir) { | ||
@@ -47,11 +59,18 @@ try { | ||
} | ||
/** | ||
* Collects all matching configuration options for the given file. Flattens all base configs and matches overrides. | ||
* Returns `undefined` if the file is excluded in one of the configuraton files. | ||
*/ | ||
reduce(config, file) { | ||
return reduceConfig(config, path.resolve(this.directories.getCurrentDirectory(), file), { rules: new Map(), settings: new Map(), processor: undefined }); | ||
} | ||
/** Get the processor configuration for a given file. */ | ||
getProcessor(config, fileName) { | ||
return findProcessorInConfig(config, path.resolve(this.directories.getCurrentDirectory(), fileName)) || undefined; | ||
} | ||
/** Get the settings for a given file. */ | ||
getSettings(config, fileName) { | ||
return reduceSettings(config, path.resolve(this.directories.getCurrentDirectory(), fileName), new Map()); | ||
} | ||
/** Load a configuration from a resolved path using the ConfigurationProvider, recursively resolving and loading base configs. */ | ||
load(fileName) { | ||
@@ -58,0 +77,0 @@ const stack = []; |
@@ -12,3 +12,3 @@ "use strict"; | ||
get builtinPackagePath() { | ||
const resolved = path.dirname(this.resolver.resolve('@fimbul/mimir', path.join(__dirname, '../'.repeat(3)), [])); | ||
const resolved = path.dirname(this.resolver.resolve('@fimbul/mimir', path.join(__dirname, '../'.repeat(/*offset to package root*/ 3)), [])); | ||
Object.defineProperty(this, 'builtinPackagePath', { value: resolved }); | ||
@@ -15,0 +15,0 @@ return resolved; |
@@ -26,2 +26,3 @@ "use strict"; | ||
let DefaultCacheFactory = class DefaultCacheFactory { | ||
// wotan-enable no-misused-generics | ||
create(weak) { | ||
@@ -28,0 +29,0 @@ return weak ? new WeakCache() : new Map(); |
@@ -205,3 +205,3 @@ "use strict"; | ||
throw new Error(`No rulesDirectories specified for '${rule.substr(0, slashIndex)}'.`); | ||
return { rule: rule.substr(slashIndex + 1), rulesDirectories }; | ||
return { rule: rule.substr(slashIndex + 1), rulesDirectories }; // tslint:disable-line:object-shorthand-properties-first | ||
} | ||
@@ -208,0 +208,0 @@ function mapRules(raw, aliases, rulesDirectoryMap) { |
@@ -35,5 +35,8 @@ "use strict"; | ||
return !fileName.endsWith('.json'); | ||
if (fileName.startsWith(this.libDirectory) || | ||
if ( | ||
// lib.xxx.d.ts | ||
fileName.startsWith(this.libDirectory) || | ||
// tslib implicitly gets added while linting a project where a dependency in node_modules contains typescript files | ||
fileName.endsWith('/node_modules/tslib/tslib.d.ts')) | ||
return false; | ||
return false; // lib.xxx.d.ts | ||
return !this.isInTypeRoot(fileName) && !this.isOutputOfReferencedProject(fileName); | ||
@@ -70,2 +73,3 @@ } | ||
else if (ref.commandLine.projectReferences !== undefined) { | ||
// for compatibility with typescript@<3.2.0 | ||
moreReferences.push(...ref.commandLine.projectReferences); | ||
@@ -78,2 +82,3 @@ } | ||
} | ||
// TODO unifiy with code in getOutputsOfProjectReferences once we can get rid of getOutputFileNamesOfProjectReferenceRecursive | ||
function getOutputFileNamesOfResolvedProjectReferencesRecursive(references, seen) { | ||
@@ -91,2 +96,3 @@ if (references === undefined) | ||
} | ||
/** recurse into every transitive project reference to exclude all of their outputs from linting */ | ||
function getOutputFileNamesOfProjectReferenceRecursive(reference, seen, host) { | ||
@@ -113,2 +119,3 @@ const referencePath = ts.resolveProjectReferencePath(reference); | ||
} | ||
// TODO remove once https://github.com/Microsoft/TypeScript/issues/26410 is resolved | ||
function getDeclarationOutputName(fileName, options, projectDirectory) { | ||
@@ -122,2 +129,3 @@ const extension = path.extname(fileName); | ||
break; | ||
// falls through: .d.ts files produce no output | ||
default: | ||
@@ -130,4 +138,5 @@ return; | ||
function getOutFileDeclarationName(outFile) { | ||
// outFile ignores declarationDir | ||
return outFile.slice(0, -path.extname(outFile).length) + '.d.ts'; | ||
} | ||
//# sourceMappingURL=file-filter.js.map |
@@ -24,2 +24,3 @@ "use strict"; | ||
const len = buf.length; | ||
// detect MPEG TS files and treat them as empty | ||
outer: while (len > 188 && buf[0] === 0x47) { | ||
@@ -33,10 +34,10 @@ for (let i = 188; i < len; i += 188) | ||
if (len >= 2) { | ||
if (buf[0] === 0xFE && buf[1] === 0xFF) | ||
if (buf[0] === 0xFE && buf[1] === 0xFF) // UTF16BE BOM | ||
return buf.swap16().toString('utf16le', 2); | ||
if (buf[0] === 0xFF && buf[1] === 0xFE) | ||
if (buf[0] === 0xFF && buf[1] === 0xFE) // UTF16LE BOM | ||
return buf.toString('utf16le', 2); | ||
if (len >= 3 && buf[0] === 0xEF && buf[1] === 0xBB && buf[2] === 0xBF) | ||
if (len >= 3 && buf[0] === 0xEF && buf[1] === 0xBB && buf[2] === 0xBF) // UTF8 with BOM | ||
return buf.toString('utf8'); | ||
} | ||
return buf.toString('utf8'); | ||
return buf.toString('utf8'); // default to UTF8 without BOM | ||
} | ||
@@ -43,0 +44,0 @@ readDirectory(dir) { |
@@ -18,2 +18,3 @@ "use strict"; | ||
getDisabledRanges(context) { | ||
// remove internal `switch` property from ranges | ||
return new Map(Array.from(this.parseLineSwitches(context).disables, (entry) => [ | ||
@@ -53,3 +54,3 @@ entry[0], | ||
fixLocation: rawRuleSwitch.fixLocation || rawRuleSwitch.location, | ||
state: 0, | ||
state: 0 /* NoMatch */, | ||
}; | ||
@@ -60,7 +61,7 @@ lineSwitch.rules.push(ruleSwitch); | ||
if (rulesToSwitch.has(rawRuleSwitch.predicate)) { | ||
ruleSwitch.state = 2; | ||
ruleSwitch.state = 2 /* Redundant */; | ||
} | ||
else { | ||
rulesToSwitch.set(rawRuleSwitch.predicate, ruleSwitch); | ||
ruleSwitch.state = 1; | ||
ruleSwitch.state = 1 /* NoChange */; | ||
} | ||
@@ -72,7 +73,7 @@ } | ||
if (matchingNames.length !== 0) { | ||
ruleSwitch.state = 2; | ||
ruleSwitch.state = 2 /* Redundant */; | ||
for (const rule of matchingNames) { | ||
if (!rulesToSwitch.has(rule)) { | ||
rulesToSwitch.set(rule, ruleSwitch); | ||
ruleSwitch.state = 1; | ||
ruleSwitch.state = 1 /* NoChange */; | ||
} | ||
@@ -87,3 +88,3 @@ } | ||
if (rawLineSwitch.enable) | ||
continue; | ||
continue; // rule is already enabled | ||
result.set(rule, [{ pos: rawLineSwitch.pos, end: rawLineSwitch.end === undefined ? Infinity : rawLineSwitch.end, switch: ruleSwitch }]); | ||
@@ -95,3 +96,3 @@ } | ||
if (!rawLineSwitch.enable) | ||
continue; | ||
continue; // rule is already disabled | ||
last.end = rawLineSwitch.pos; | ||
@@ -102,2 +103,4 @@ if (rawLineSwitch.end !== undefined) | ||
else if (rawLineSwitch.enable || rawLineSwitch.pos < last.end) { | ||
// rule is already enabled | ||
// or disabled range is nested inside the previous range | ||
continue; | ||
@@ -113,3 +116,3 @@ } | ||
} | ||
ruleSwitch.state = 3; | ||
ruleSwitch.state = 3 /* Unused */; | ||
} | ||
@@ -126,6 +129,6 @@ } | ||
const stateText = { | ||
[1](singular, mode) { return `${singular ? 'is' : 'are'} already ${mode}d`; }, | ||
[0](singular) { return `do${singular ? 'es' : ''}n't match any rules enabled for this file`; }, | ||
[3](singular) { return `${singular ? 'has' : 'have'} no failures to disable`; }, | ||
[2](singular, mode) { return singular ? `was already specified in this ${mode} switch` : 'are redundant'; }, | ||
[1 /* NoChange */](singular, mode) { return `${singular ? 'is' : 'are'} already ${mode}d`; }, | ||
[0 /* NoMatch */](singular) { return `do${singular ? 'es' : ''}n't match any rules enabled for this file`; }, | ||
[3 /* Unused */](singular) { return `${singular ? 'has' : 'have'} no failures to disable`; }, | ||
[2 /* Redundant */](singular, mode) { return singular ? `was already specified in this ${mode} switch` : 'are redundant'; }, | ||
}; | ||
@@ -144,3 +147,3 @@ class Filter { | ||
if (end > disabledRange.pos && pos < disabledRange.end) { | ||
disabledRange.switch.state = 4; | ||
disabledRange.switch.state = 4 /* Used */; | ||
return false; | ||
@@ -162,8 +165,8 @@ } | ||
} | ||
const counts = new Array(4 + 1).fill(0); | ||
const counts = new Array(4 /* Used */ + 1).fill(0); | ||
for (const rule of current.rules) | ||
++counts[rule.state]; | ||
if (counts[4] === 0 && (!current.enable || counts[3] === 0)) { | ||
if (counts[4 /* Used */] === 0 && (!current.enable || counts[3 /* Unused */] === 0)) { | ||
const errorStates = []; | ||
for (let state = 0; state !== 4; ++state) | ||
for (let state = 0 /* NoMatch */; state !== 4 /* Used */; ++state) | ||
if (counts[state] !== 0) | ||
@@ -176,4 +179,4 @@ errorStates.push(stateText[state](false, mode)); | ||
if (ruleSwitch.location !== undefined && | ||
ruleSwitch.state !== 4 && | ||
(!current.enable || ruleSwitch.state !== 3)) | ||
ruleSwitch.state !== 4 /* Used */ && | ||
(!current.enable || ruleSwitch.state !== 3 /* Unused */)) | ||
result.push(this.createFinding(`This rule ${stateText[ruleSwitch.state](true, mode)}.`, severity, ruleSwitch.location, ruleSwitch.fixLocation)); | ||
@@ -212,2 +215,3 @@ } | ||
const result = []; | ||
// tslint:disable-next-line:max-line-length | ||
const commentRegex = /(\/[/*] *wotan-(enable|disable)((?:-next)?-line)?)( +(?:(?:[\w-]+\/)*[\w-]+ *, *)*(?:[\w-]+\/)*[\w-]+)? *(?:$|\*\/)/mg; | ||
@@ -228,2 +232,3 @@ for (let match = commentRegex.exec(sourceFile.text); match !== null; match = commentRegex.exec(sourceFile.text)) { | ||
pos: lineStarts[line], | ||
// no need to switch back if there is no next line | ||
end: lineStarts.length === line + 1 ? undefined : lineStarts[line + 1], | ||
@@ -238,2 +243,3 @@ location: { pos: comment.pos, end: comment.end }, | ||
if (lineStarts.length === line) { | ||
// there is no next line, return an out-of-range switch that can be reported | ||
result.push({ | ||
@@ -252,2 +258,3 @@ rules, | ||
pos: lineStarts[line], | ||
// no need to switch back if there is no next line | ||
end: lineStarts.length === line + 1 ? undefined : lineStarts[line + 1], | ||
@@ -279,2 +286,3 @@ location: { pos: comment.pos, end: comment.end }, | ||
location: { pos: pos + offset, end: match.index + offset }, | ||
// fix of first rule needs to remove the comma after it, all other rule fixes need to remove the comma before it | ||
fixLocation: { pos: fixPos + offset, end: (result.length === 0 ? re.lastIndex : match.index) + offset }, | ||
@@ -285,3 +293,3 @@ }); | ||
pos = re.lastIndex; | ||
fixPos = match.index; | ||
fixPos = match.index; // fix always removes the preceeding comma | ||
} | ||
@@ -288,0 +296,0 @@ return result; |
@@ -6,2 +6,9 @@ "use strict"; | ||
const path = require("path"); | ||
/** | ||
* Number of .. until the containing node_modules. | ||
* __dirname -> src | ||
* .. -> project root | ||
* ../.. -> node_modules (or @scope) | ||
* ../../.. -> node_modules if @scoped package | ||
*/ | ||
exports.OFFSET_TO_NODE_MODULES = 3; | ||
@@ -29,10 +36,10 @@ function arrayify(maybeArr) { | ||
exports.unixifyPath = unixifyPath; | ||
function format(value, fmt = "yaml") { | ||
function format(value, fmt = "yaml" /* Yaml */) { | ||
value = convertToPrintable(value) || {}; | ||
switch (fmt) { | ||
case "json": | ||
case "json" /* Json */: | ||
return JSON.stringify(value, undefined, 2); | ||
case "json5": | ||
case "json5" /* Json5 */: | ||
return json5.stringify(value, undefined, 2); | ||
case "yaml": | ||
case "yaml" /* Yaml */: | ||
return yaml.safeDump(value, { | ||
@@ -124,2 +131,6 @@ indent: 2, | ||
exports.flatMap = flatMap; | ||
/** | ||
* Adds an item to an array if it's not already included. | ||
* @returns true if the item was not present in the array | ||
* */ | ||
function addUnique(arr, item) { | ||
@@ -126,0 +137,0 @@ if (arr.includes(item)) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
333687
4136
8
+ Addedsemver@6.3.1(transitive)
- Removedsemver@5.7.2(transitive)
Updatedsemver@^6.0.0