(configOptions: ConfigOptions)
| 249 | // (or at least cancel) prior to calling again. It returns true if a parse |
| 250 | // was required and false if the parse information was up to date already. |
| 251 | parse(configOptions: ConfigOptions): boolean { |
| 252 | // If the file is already parsed, we can skip. |
| 253 | if (!this.isParseRequired()) { |
| 254 | return false; |
| 255 | } |
| 256 | |
| 257 | let diagSink = new DiagnosticSink(); |
| 258 | let fileContents = this._fileContents; |
| 259 | if (this._clientVersion === null) { |
| 260 | try { |
| 261 | timingStats.readFileTime.timeOperation(() => { |
| 262 | // Read the file's contents. |
| 263 | fileContents = fs.readFileSync(this._filePath, { encoding: 'utf8' }); |
| 264 | }); |
| 265 | } catch (error) { |
| 266 | diagSink.addError(`Source file could not be read`); |
| 267 | fileContents = ''; |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | // Use the configuration options to determine the environment in which |
| 272 | // this source file will be executed. |
| 273 | let execEnvironment = configOptions.findExecEnvironment(this._filePath); |
| 274 | |
| 275 | let parseOptions = new ParseOptions(); |
| 276 | if (this._filePath.endsWith('pyi')) { |
| 277 | parseOptions.isStubFile = true; |
| 278 | } |
| 279 | parseOptions.pythonVersion = execEnvironment.pythonVersion; |
| 280 | |
| 281 | try { |
| 282 | // Parse the token stream, building the abstract syntax tree. |
| 283 | let parser = new Parser(); |
| 284 | let parseResults = parser.parseSourceFile(fileContents!, parseOptions, diagSink); |
| 285 | |
| 286 | // Convert the diagnostic sink into one that knows how to convert |
| 287 | // to line numbers. |
| 288 | let textRangeDiagSink = new TextRangeDiagnosticSink(parseResults.lines, diagSink.diagnostics); |
| 289 | |
| 290 | // Fill in the parent links and get the list of imports. |
| 291 | let walker = new PostParseWalker(textRangeDiagSink, parseResults.parseTree, this._isStubFile); |
| 292 | timingStats.postParseWalkerTime.timeOperation(() => { |
| 293 | walker.analyze(); |
| 294 | }); |
| 295 | |
| 296 | // Save information in the analysis job. |
| 297 | this._analysisJob.fileContentsVersion = this._fileContentsVersion; |
| 298 | this._analysisJob.nextPhaseToRun = AnalysisPhase.SemanticAnalysis; |
| 299 | this._analysisJob.parseTreeNeedsCleaning = false; |
| 300 | this._analysisJob.parseResults = parseResults; |
| 301 | [this._analysisJob.imports, this._analysisJob.builtinsImport] = |
| 302 | this._resolveImports(parseResults.parseTree, |
| 303 | walker.getImportedModules(), configOptions, execEnvironment); |
| 304 | |
| 305 | this._analysisJob.parseDiagnostics = diagSink.diagnostics; |
| 306 | this._diagnosticVersion++; |
| 307 | } catch (e) { |
| 308 | let message: string; |
no test coverage detected