9

私の目標は、clang-format を実行する拡張機能を作成することです。私のコードは次のようになります。

- (void)performCommandWithInvocation:(XCSourceEditorCommandInvocation *)invocation completionHandler:(void (^)(NSError * _Nullable nilOrError))completionHandler
{
    NSError *error = nil;

    NSURL *executableURL = [[self class] executableURL];

    if (!executableURL)
    {
          NSString *errorDescription = [NSString stringWithFormat:@"Failed to find clang-format. Ensure it is installed at any of these locations\n%@", [[self class] clangFormatUrls]];
              completionHandler([NSError errorWithDomain:SourceEditorCommandErrorDomain
              code:1
              userInfo:@{NSLocalizedDescriptionKey: errorDescription}]);
          return;
    }

    NSMutableArray *args = [NSMutableArray array];
    [args addObject:@"-style=LLVM"];
    [args addObject:@"someFile.m"];
    NSPipe *outputPipe = [NSPipe pipe];
    NSPipe *errorPipe = [NSPipe pipe];

    NSTask *task = [[NSTask alloc] init];
    task.launchPath = executableURL.path;
    task.arguments = args;

    task.standardOutput = outputPipe;
    task.standardError = errorPipe;

    @try
    {
          [task launch];
    }
    @catch (NSException *exception)
    {
          completionHandler([NSError errorWithDomain:SourceEditorCommandErrorDomain
              code:2
              userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Failed to run clang-format: %@", exception.reason]}]);
          return;
    }

    [task waitUntilExit];

    NSString *output = [[NSString alloc] initWithData:[[outputPipe fileHandleForReading] readDataToEndOfFile]
          encoding:NSUTF8StringEncoding];
    NSString *errorOutput = [[NSString alloc] initWithData:[[errorPipe fileHandleForReading] readDataToEndOfFile]
          encoding:NSUTF8StringEncoding];
    [[outputPipe fileHandleForReading] closeFile];
    [[errorPipe fileHandleForReading] closeFile];

    int status = [task terminationStatus];
    if (status == 0)
    {
          NSLog(@"Success: %@", output);
    }
    else
    {
          error = [NSError errorWithDomain:SourceEditorCommandErrorDomain
              code:3
              userInfo:@{NSLocalizedDescriptionKey: errorOutput}];
    }

    completionHandler(error);
}

この try-catch ブロックが必要な理由は、このコードを実行しようとすると例外がスローされるためです。例外の理由は次のとおりです。

エラー: 起動パスにアクセスできません

私のclang-formatのパスは/usr/local/bin/clang-formatです。私が発見したのは、/usr/local/bin にあるアプリケーションにアクセスしようとしても、/bin は問題ないということです (たとえば、/bin/ls を実行しようとしても問題ありません)。

私が試した別の解決策は、次のように起動パスと引数を設定して /bin/bash を実行することでした。

task.launchPath = [[[NSProcessInfo processInfo] environment] objectForKey:@"SHELL"];
task.arguments = @[@"-l", @"-c", @"/usr/local/bin/clang-format -style=LLVM someFile.m"];

これにより、タスクが正常に起動されますが、次のエラー出力で失敗します。

/bin/bash: /etc/profile: 操作は許可されていません /bin/bash: /usr/local/bin/clang-format: 操作は許可されていません

最初のエラー メッセージは、ユーザーとしてログインしようとする bash で -l パラメータを呼び出そうとしたことが原因です。

これらの他のフォルダーへのアクセスを有効にする方法はありますか? 有効にする必要がある何らかのサンドボックス環境設定はありますか?

4

2 に答える 2

1

サンドボックス化のため、これは不可能だと思います。clang 形式の実行可能ファイルをバンドルして、そこから使用できます。

于 2016-09-16T15:34:39.617 に答える
0

個人的には、あなたはすべて間違っていると思います。拡張機能は迅速である必要があります (Xcode 拡張機能に関するビデオを見ると、彼は出入りを何度も繰り返します)。そして、それらは厳しく制限されています。

ただし、別の方法があります。コンテナー アプリは、すべてのハッキングなしで、拡張機能に対してこの処理を実行できる場合があります。欠点は、拡張機能との間でバッファを渡す必要があることです。

簡単ではありませんが、それは可能です。コンテナを実行するための簡単な方法。最初に、コンテナー アプリの Info.plist (拡張子 Info.plist ではありません) を変更して、URL タイプを指定します。

Info.plist

拡張機能では、次のコマンドを実行してコンテナー アプリを「起動」できます。

let customurl = NSURL.init(string: “yoururlschemehere://")
NSWorkspace.shared().open(customurl as! URL)

この 2 つの間の通信に関しては、Apple には多くの方法があります。私、私は古い学校なので、DistributedNotificationCenter を使用しています。

試したことはありませんが、コンテナー アプリで clang とのチャットに問題が発生する理由がわかりません (設定にはコンテナー アプリを使用しています)。

于 2016-09-22T18:13:47.437 に答える