private readOptions()

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;
	}