blob: dd835214055678237dee58241b4a97e6197605c5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.cpplite.project;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.netbeans.api.extexecution.ExecutionDescriptor;
import org.netbeans.api.extexecution.ExecutionService;
import org.netbeans.api.extexecution.print.ConvertedLine;
import org.netbeans.api.extexecution.print.LineConvertor;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.modules.cpplite.debugger.api.Debugger;
import org.netbeans.modules.cpplite.project.runner.Runner;
import org.netbeans.spi.project.ActionProvider;
import org.openide.LifecycleManager;
import org.openide.cookies.LineCookie;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.modules.InstalledFileLocator;
import org.openide.text.Line;
import org.openide.util.Lookup;
import org.openide.windows.OutputEvent;
import org.openide.windows.OutputListener;
/**
*
* @author lahvac
*/
public class ActionProviderImpl implements ActionProvider {
private static final String[] SUPPORTED_ACTIONS = {
COMMAND_BUILD,
COMMAND_CLEAN,
COMMAND_REBUILD,
COMMAND_RUN,
COMMAND_DEBUG,
};
private final CPPLiteProject prj;
public ActionProviderImpl(CPPLiteProject prj) {
this.prj = prj;
}
@Override
@SuppressWarnings("ReturnOfCollectionOrArrayField")
public String[] getSupportedActions() {
return SUPPORTED_ACTIONS;
}
private static final Pattern ERROR_LINE = Pattern.compile("(.*):(\\d+):(\\d+):.*");
@Override
public void invokeAction(String command, Lookup context) throws IllegalArgumentException {
BuildConfiguration config = prj.getActiveBuildConfiguration();
File module = InstalledFileLocator.getDefault().locate("modules/org-netbeans-modules-cpplite-project.jar", "org.netbeans.modules.cpplite.project", false);
ExecutionDescriptor executionDescriptor = new ExecutionDescriptor()
.showProgress(true)
.showSuspended(true)
.frontWindowOnError(true)
.controllable(true)
.errConvertorFactory(() -> new ErrorLineConvertor())
.outConvertorFactory(() -> new ErrorLineConvertor());
ExecutionService.newService(() -> {
LifecycleManager.getDefault().saveAll();
if (COMMAND_DEBUG.equals(command)) {
List<List<String>> executablesFor = config.executablesFor(COMMAND_RUN);
return Debugger.startInDebugger(executablesFor.get(0), FileUtil.toFile(prj.getProjectDirectory()));
}
List<List<String>> executablesFor;
if (COMMAND_REBUILD.equals(command)) {
executablesFor = new ArrayList<>();
executablesFor.addAll(config.executablesFor(COMMAND_CLEAN));
executablesFor.addAll(config.executablesFor(COMMAND_BUILD));
} else {
executablesFor = config.executablesFor(command);
}
String arg = executablesFor.stream().map(c -> quote(c.stream().map(p -> quote(p)).collect(Collectors.joining(" ")))).collect(Collectors.joining(" "));
return new ProcessBuilder("java", "-classpath", module.getAbsolutePath(), Runner.class.getName(), arg).directory(FileUtil.toFile(prj.getProjectDirectory())).start();
}, executionDescriptor, ProjectUtils.getInformation(prj).getDisplayName() + " - " + command).run();
}
private static String quote(String s) {
return s.replace("_", "_u_").replace(" ", "_s_");
}
@Override
public boolean isActionEnabled(String command, Lookup context) throws IllegalArgumentException {
if (COMMAND_DEBUG.equals(command)) {
return isActionEnabled(COMMAND_RUN, context);
} else if (COMMAND_REBUILD.equals(command)) {
return isActionEnabled(COMMAND_CLEAN, context) && isActionEnabled(COMMAND_BUILD, context);
} else {
return prj.getActiveBuildConfiguration().executablesFor(command) != null;
}
}
private static class ErrorLineConvertor implements LineConvertor {
@Override
public List<ConvertedLine> convert(String line) {
Matcher matcher = ERROR_LINE.matcher(line);
if (matcher.matches()) {
String fileName = matcher.group(1);
int lineNum = Integer.parseInt(matcher.group(2)) - 1;
int columnNum = Integer.parseInt(matcher.group(3)) - 1;
return Collections.singletonList(ConvertedLine.forText(line, new OutputListener() {
@Override
public void outputLineSelected(OutputEvent ev) {}
@Override
public void outputLineAction(OutputEvent ev) {
FileObject file = FileUtil.toFileObject(new File(fileName));
if (file == null) {
//TODO
return;
}
LineCookie lc = file.getLookup().lookup(LineCookie.class);
lc.getLineSet().getCurrent(lineNum).show(Line.ShowOpenType.OPEN, Line.ShowVisibilityType.FOCUS, columnNum);
}
@Override
public void outputLineCleared(OutputEvent ev) {}
}));
}
return Collections.singletonList(ConvertedLine.forText(line, null));
}
}
}