|
| 1 | +/** |
| 2 | + * Copyright (c) 2015-present, Facebook, Inc. |
| 3 | + * All rights reserved. |
| 4 | + * |
| 5 | + * This source code is licensed under the license found in the LICENSE file in |
| 6 | + * the root directory of this source tree. |
| 7 | + * |
| 8 | + * @flow |
| 9 | + * @format |
| 10 | + */ |
| 11 | + |
| 12 | +import type {TaskInfo} from '../../nuclide-buck/lib/types'; |
| 13 | +import type { |
| 14 | + AtomLanguageService, |
| 15 | + LanguageService, |
| 16 | +} from '../../nuclide-language-service'; |
| 17 | + |
| 18 | +import invariant from 'invariant'; |
| 19 | +import {getLogger} from 'log4js'; |
| 20 | +import fsPromise from 'nuclide-commons/fsPromise'; |
| 21 | +import nuclideUri from 'nuclide-commons/nuclideUri'; |
| 22 | +import {getRustInputs, getSaveAnalysisTargets, normalizeNameForBuckQuery} from './BuckUtils'; |
| 23 | + |
| 24 | +import * as BuckService from '../../nuclide-buck-rpc'; |
| 25 | + |
| 26 | +const logger = getLogger('nuclide-rust'); |
| 27 | + |
| 28 | +export async function updateRlsBuildForTask( |
| 29 | + task: TaskInfo, |
| 30 | + service: AtomLanguageService<LanguageService>, |
| 31 | +) { |
| 32 | + const buildTarget = normalizeNameForBuckQuery(task.buildTarget); |
| 33 | + |
| 34 | + const files = await getRustInputs(task.buckRoot, buildTarget); |
| 35 | + // Probably not a Rust build target, ignore |
| 36 | + if (files.length == 0) |
| 37 | + return; |
| 38 | + // We need only to pick a representative file to get a related lang service |
| 39 | + const fileUri = task.buckRoot + '/' + files[0]; |
| 40 | + atom.notifications.addInfo(`fileUri: ${fileUri}`); |
| 41 | + |
| 42 | + const langService = await service.getLanguageServiceForUri(fileUri); |
| 43 | + invariant(langService != null); |
| 44 | + |
| 45 | + // Since `buck` execution is not trivial - the command may be overriden, needs |
| 46 | + // to inherit the environment, passes internal FB USER to env etc. the RLS |
| 47 | + // can't just invoke that. |
| 48 | + // Instead, we build now, copy paths to resulting .json analysis artifacts to |
| 49 | + // a temp file and just use `cat $TMPFILE` as a dummy build command. |
| 50 | + const analysisTargets = await getSaveAnalysisTargets(task.buckRoot, buildTarget); |
| 51 | + logger.debug(`analysisTargets: ${analysisTargets.join('\n')}`); |
| 52 | + let artifacts: Array<string> = []; |
| 53 | + |
| 54 | + const buildReport = await BuckService.build(task.buckRoot, analysisTargets); |
| 55 | + if (buildReport.success === false) { |
| 56 | + atom.notifications.addError("save-analysis build failed"); |
| 57 | + return; |
| 58 | + } |
| 59 | + |
| 60 | + Object.values(buildReport.results) |
| 61 | + // TODO: https://buckbuild.com/command/build.html specifies that for |
| 62 | + // FETCHED_FROM_CACHE we might not get an output file - can we force it |
| 63 | + // somehow? Or we always locally produce a save-analysis .json file? |
| 64 | + .forEach((targetReport: any) => artifacts.push(targetReport.output)); |
| 65 | + |
| 66 | + const tempfile = await fsPromise.tempfile(); |
| 67 | + await fsPromise.writeFile(tempfile, artifacts.join('\n')); |
| 68 | + |
| 69 | + // TODO: Windows? |
| 70 | + const buildCommand = `cat ${tempfile}`; |
| 71 | + |
| 72 | + logger.debug(`Built SA artifacts: ${artifacts.join('\n')}`); |
| 73 | + logger.debug(`buildCommand: ${buildCommand}`); |
| 74 | + |
| 75 | + langService.sendLspNotification(fileUri, 'workspace/didChangeConfiguration', |
| 76 | + { |
| 77 | + settings: { |
| 78 | + rust: { |
| 79 | + unstable_features: true, // Required for build_command |
| 80 | + build_on_save: true, |
| 81 | + build_command: buildCommand, // TODO: Only in RLS branch: https://github.com/Xanewok/rls/tree/external-build |
| 82 | + } |
| 83 | + } |
| 84 | + }); |
| 85 | +} |
0 commit comments