in jshint-server/src/server.ts [136:266]
private readOptions(fsPath: string = null): any {
let that = this;
function stripComments(content: string): string {
/**
* First capturing group matches double quoted string
* Second matches single quotes string
* Third matches block comments
* Fourth matches line comments
*/
var regexp: RegExp = /("(?:[^\\\"]*(?:\\.)?)*")|('(?:[^\\\']*(?:\\.)?)*')|(\/\*(?:\r?\n|.)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))/g;
let result = content.replace(regexp, (match, m1, m2, m3, m4) => {
// Only one of m1, m2, m3, m4 matches
if (m3) {
// A block comment. Replace with nothing
return "";
} else if (m4) {
// A line comment. If it ends in \r?\n then keep it.
let length = m4.length;
if (length > 2 && m4[length - 1] === '\n') {
return m4[length - 2] === '\r' ? '\r\n' : '\n';
} else {
return "";
}
} else {
// We match a string
return match;
}
});
return result;
}
function readJsonFile(file: string, extendedFrom?: string): any {
try {
return JSON.parse(stripComments(fs.readFileSync(file).toString()));
}
catch (err) {
let location = extendedFrom ? `${file} extended from ${extendedFrom}` : file;
that.connection.window.showErrorMessage(`Can't load JSHint configuration from file ${location}. Please check the file for syntax errors.`);
return {};
}
}
function readJSHintFile(file: string, extendedFrom?: string): any {
that.connection.console.info(extendedFrom ? `Reading jshint configuration from ${file}, which was extended from ${extendedFrom}` : `Reading jshint configuration from ${file}`);
let content = readJsonFile(file, extendedFrom);
if (content.extends) {
let baseFile = path.resolve(path.dirname(file), content.extends);
if (fs.existsSync(baseFile)) {
content = _.mergeWith(readJSHintFile(baseFile, file), content, (baseValue, contentValue) => {
if (_.isArray(baseValue)) {
return baseValue.concat(contentValue);
}
});
} else {
that.connection.window.showErrorMessage(`Can't find JSHint file ${baseFile} extended from ${file}`);
}
delete content.extends;
}
if (content.overrides) {
Object.keys(content.overrides).forEach(pathPattern => {
if (minimatch(fsPath, pathPattern)) {
const optionsToOverride = content.overrides[pathPattern];
if (optionsToOverride.globals) {
content.globals = _.extend(content.globals || {}, optionsToOverride.globals);
delete optionsToOverride.globals;
}
Object.keys(optionsToOverride).forEach(optionKey => {
content[optionKey] = optionsToOverride[optionKey];
});
}
});
delete content.overrides;
}
return content;
}
function isWindows(): boolean {
return process.platform === 'win32';
}
function getUserHome() {
return process.env[isWindows() ? 'USERPROFILE' : 'HOME'];
}
if (this.configPath && fs.existsSync(this.configPath)) {
return readJsonFile(this.configPath);
}
let jshintOptions = this.jshintOptions;
// backward compatibility
if (jshintOptions && jshintOptions.config && fs.existsSync(jshintOptions.config)) {
this.connection.console.info(`Reading configuration from ${jshintOptions.config}`);
return readJsonFile(jshintOptions.config);
}
if (fsPath) {
let packageFile = locateFile(fsPath, 'package.json');
if (packageFile) {
let content = readJsonFile(packageFile);
if (content.jshintConfig) {
this.connection.console.info(`Reading configuration from ${packageFile}`);
return content.jshintConfig;
}
}
let configFile = locateFile(fsPath, JSHINTRC);
if (configFile) {
return readJSHintFile(configFile);
}
}
let home = getUserHome();
if (home) {
let file = path.join(home, JSHINTRC);
if (fs.existsSync(file)) {
return readJSHintFile(file);
}
}
// No file found, using jshint.options setting
this.connection.console.info(`Reading configuration from 'jshint.options' setting`);
return jshintOptions;
}