You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by vi...@apache.org on 2022/02/19 08:15:54 UTC
[netbeans] branch cnd updated: [cnd] 3.1 makeproject compile_commands.json
This is an automated email from the ASF dual-hosted git repository.
vieiro pushed a commit to branch cnd
in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/cnd by this push:
new ae52a9b [cnd] 3.1 makeproject compile_commands.json
new 8115eec Merge pull request #3553 from vieiro/feature/cnd-lsp
ae52a9b is described below
commit ae52a9b9ce28984a9fa7f223f79193c76966d78f
Author: Antonio Vieiro <vi...@apache.org>
AuthorDate: Tue Feb 1 21:39:38 2022 +0100
[cnd] 3.1 makeproject compile_commands.json
Automatically generate compile_commands.json for make based projects.
---
cnd/cnd.api.project/nbproject/project.xml | 3 +-
cnd/cnd.lsp/build.xml | 25 ++
cnd/cnd.lsp/manifest.mf | 6 +
cnd/cnd.lsp/nbproject/project.properties | 20 ++
cnd/cnd.lsp/nbproject/project.xml | 141 +++++++++
.../lsp/compilationdb/ClangCDBGenerationCause.java | 53 ++++
.../lsp/compilationdb/ClangCDBGenerationTask.java | 341 +++++++++++++++++++++
.../cnd/lsp/compilationdb/ClangCDBSupport.java | 219 +++++++++++++
.../lsp/compilationdb/CommandObjectBuilder.java | 131 ++++++++
.../makeproject/LSPMakeProjectLookupProvider.java | 40 +++
.../modules/cnd/lsp/resources/Bundle.properties | 22 ++
cnd/cnd.makeproject/nbproject/project.xml | 1 +
cnd/cnd.toolchain/nbproject/project.xml | 3 +-
ide/dlight.nativeexecution/nbproject/project.xml | 1 +
nbbuild/cluster.properties | 1 +
15 files changed, 1005 insertions(+), 2 deletions(-)
diff --git a/cnd/cnd.api.project/nbproject/project.xml b/cnd/cnd.api.project/nbproject/project.xml
index 0d1cdd8..c78efff 100644
--- a/cnd/cnd.api.project/nbproject/project.xml
+++ b/cnd/cnd.api.project/nbproject/project.xml
@@ -111,7 +111,6 @@
<friend>org.netbeans.modules.cnd.analysis.impl</friend>
<friend>org.netbeans.modules.cnd.apt</friend>
<friend>org.netbeans.modules.cnd.audit</friend>
- <friend>org.netbeans.modules.cnd.jconvertwizard</friend>
<friend>org.netbeans.modules.cnd.classview</friend>
<friend>org.netbeans.modules.cnd.codemodel.bridge</friend>
<friend>org.netbeans.modules.cnd.codemodel.utils</friend>
@@ -122,6 +121,8 @@
<friend>org.netbeans.modules.cnd.gizmo</friend>
<friend>org.netbeans.modules.cnd.gotodeclaration</friend>
<friend>org.netbeans.modules.cnd.highlight</friend>
+ <friend>org.netbeans.modules.cnd.jconvertwizard</friend>
+ <friend>org.netbeans.modules.cnd.lsp</friend>
<friend>org.netbeans.modules.cnd.makeproject</friend>
<friend>org.netbeans.modules.cnd.makeproject.source.bridge</friend>
<friend>org.netbeans.modules.cnd.makeproject.ui</friend>
diff --git a/cnd/cnd.lsp/build.xml b/cnd/cnd.lsp/build.xml
new file mode 100644
index 0000000..9f9e3c3
--- /dev/null
+++ b/cnd/cnd.lsp/build.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<project basedir="." default="netbeans" name="cnd/cnd.lsp">
+ <description>Builds, tests, and runs the project org.netbeans.modules.cnd.lsp</description>
+ <import file="../../nbbuild/templates/projectized.xml"/>
+</project>
diff --git a/cnd/cnd.lsp/manifest.mf b/cnd/cnd.lsp/manifest.mf
new file mode 100644
index 0000000..ad635bf
--- /dev/null
+++ b/cnd/cnd.lsp/manifest.mf
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+AutoUpdate-Show-In-Client: false
+OpenIDE-Module: org.netbeans.modules.cnd.lsp
+OpenIDE-Module-Implementation-Version: 1
+OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/cnd/lsp/resources/Bundle.properties
+
diff --git a/cnd/cnd.lsp/nbproject/project.properties b/cnd/cnd.lsp/nbproject/project.properties
new file mode 100644
index 0000000..355b38a
--- /dev/null
+++ b/cnd/cnd.lsp/nbproject/project.properties
@@ -0,0 +1,20 @@
+# 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.
+is.eager=true
+javac.source=1.8
+javac.compilerargs=-Xlint -Xlint:-serial
+spec.version.base=1.0.0
diff --git a/cnd/cnd.lsp/nbproject/project.xml b/cnd/cnd.lsp/nbproject/project.xml
new file mode 100644
index 0000000..adfac30
--- /dev/null
+++ b/cnd/cnd.lsp/nbproject/project.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+ <type>org.netbeans.modules.apisupport.project</type>
+ <configuration>
+ <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+ <code-name-base>org.netbeans.modules.cnd.lsp</code-name-base>
+ <module-dependencies>
+ <dependency>
+ <code-name-base>org.netbeans.libs.json_simple</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <release-version>1</release-version>
+ <specification-version>0.27</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.netbeans.modules.cnd.api.project</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <release-version>1</release-version>
+ <specification-version>1.37.9</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.netbeans.modules.cnd.makeproject</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <release-version>2</release-version>
+ <specification-version>2.59.20</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.netbeans.modules.cnd.makeproject.ui</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>1.1.8</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.netbeans.modules.cnd.toolchain</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>1.35.14</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.netbeans.modules.dlight.nativeexecution</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>1.54</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.netbeans.modules.projectapi</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <release-version>1</release-version>
+ <specification-version>1.85</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.netbeans.modules.projectuiapi.base</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <release-version>1</release-version>
+ <specification-version>1.101</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.awt</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>7.83</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.filesystems</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>9.27</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.nodes</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>7.60</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.util</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>9.23</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.util.lookup</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>8.49</specification-version>
+ </run-dependency>
+ </dependency>
+ </module-dependencies>
+ <public-packages/>
+ </data>
+ </configuration>
+</project>
diff --git a/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/compilationdb/ClangCDBGenerationCause.java b/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/compilationdb/ClangCDBGenerationCause.java
new file mode 100644
index 0000000..fa963e2
--- /dev/null
+++ b/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/compilationdb/ClangCDBGenerationCause.java
@@ -0,0 +1,53 @@
+/*
+ * 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.cnd.lsp.compilationdb;
+
+/**
+ * ClangCDBGenerationCause represents possible causes that require a Clang
+ * compilation database to be regenerated.
+ *
+ * @author antonio
+ */
+enum ClangCDBGenerationCause {
+ /**
+ * Some files were added to the project
+ */
+ FILES_ADDED,
+ /**
+ * Some files were removed from the project
+ */
+ FILES_REMOVED,
+ /**
+ * Some files were renamed in the project
+ */
+ FILES_RENAMED,
+ /**
+ * Project configuration changed
+ */
+ PROJECT_CONFIGURATION_CHANGED,
+ /**
+ * Project is opened.
+ */
+ PROJECT_OPENED,
+ /**
+ * Include paths or macro defintions have changed for
+ * some files or for the whole project.
+ */
+ INCLUDES_MACROS_CHANGED
+}
diff --git a/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/compilationdb/ClangCDBGenerationTask.java b/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/compilationdb/ClangCDBGenerationTask.java
new file mode 100644
index 0000000..04739cc
--- /dev/null
+++ b/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/compilationdb/ClangCDBGenerationTask.java
@@ -0,0 +1,341 @@
+/*
+ * 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.cnd.lsp.compilationdb;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.json.simple.JSONObject;
+import org.netbeans.modules.cnd.api.project.NativeFileItem.Language;
+import static org.netbeans.modules.cnd.api.project.NativeFileItem.Language.CPP;
+import static org.netbeans.modules.cnd.api.project.NativeFileItem.Language.C_HEADER;
+import static org.netbeans.modules.cnd.api.project.NativeFileItem.Language.FORTRAN;
+import static org.netbeans.modules.cnd.api.project.NativeFileItem.Language.OTHER;
+import org.netbeans.modules.cnd.api.project.NativeProject;
+import org.netbeans.modules.cnd.api.toolchain.AbstractCompiler;
+import org.netbeans.modules.cnd.api.toolchain.CompilerSet;
+import org.netbeans.modules.cnd.api.toolchain.PredefinedToolKind;
+import org.netbeans.modules.cnd.api.toolchain.Tool;
+import org.netbeans.modules.cnd.makeproject.api.MakeProject;
+import org.netbeans.modules.cnd.makeproject.api.configurations.BasicCompilerConfiguration;
+import org.netbeans.modules.cnd.makeproject.api.configurations.CCCompilerConfiguration;
+import org.netbeans.modules.cnd.makeproject.api.configurations.CCompilerConfiguration;
+import org.netbeans.modules.cnd.makeproject.api.configurations.ConfigurationDescriptorProvider;
+import org.netbeans.modules.cnd.makeproject.api.configurations.Item;
+import org.netbeans.modules.cnd.makeproject.api.configurations.ItemConfiguration;
+import org.netbeans.modules.cnd.makeproject.api.configurations.MakeConfiguration;
+import org.netbeans.modules.cnd.makeproject.api.configurations.MakeConfigurationDescriptor;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Cancellable;
+
+/**
+ * ClangCDBGenerationTask creates/updates a Clang compilation database as
+ * defined https://clang.llvm.org/docs/JSONCompilationDatabase.html
+ *
+ * @author antonio
+ */
+final class ClangCDBGenerationTask implements Callable<Void>, Cancellable {
+
+ private static final String CDB_NAME = "compile_commands.json"; // NOI18N
+ private static final Logger LOG
+ = Logger.getLogger(ClangCDBGenerationTask.class.getName());
+
+ protected boolean cancelled;
+ private final ClangCDBSupport support;
+ private final BlockingQueue<ClangCDBGenerationCause> pendingCauses;
+ private final MakeProject makeProject;
+ private final NativeProject nativeProject;
+ private final MakeConfiguration activeMakeConfiguration;
+ private final CompilerSet compilerSet;
+ private final ConfigurationDescriptorProvider configurationDescriptorProvider;
+ private final MakeConfigurationDescriptor makeConfigurationDescriptor;
+
+ ClangCDBGenerationTask(ClangCDBSupport support, BlockingQueue<ClangCDBGenerationCause> pendingCauses)
+ throws IllegalArgumentException {
+ this.support = support;
+ this.makeProject = support.getMakeProject();
+ this.pendingCauses = pendingCauses;
+ this.cancelled = false;
+
+ // Prepare some required objects
+ nativeProject = makeProject.getLookup().lookup(NativeProject.class);
+ if (nativeProject == null) {
+ throw new IllegalArgumentException("No native project found");
+ }
+
+ if (makeProject.getDevelopmentHost() != null && !makeProject.getDevelopmentHost().isLocal()) {
+ throw new IllegalArgumentException("Not a local project");
+ }
+
+ activeMakeConfiguration = makeProject.getActiveConfiguration();
+ if (activeMakeConfiguration == null) {
+ throw new IllegalArgumentException("No active make configuration");
+ }
+
+ compilerSet = activeMakeConfiguration.getCompilerSet().getCompilerSet();
+ if (compilerSet == null) {
+ throw new IllegalArgumentException("No compilerset defined");
+ }
+
+ configurationDescriptorProvider
+ = makeProject.getLookup().lookup(ConfigurationDescriptorProvider.class);
+ if (configurationDescriptorProvider == null) {
+ throw new IllegalArgumentException("No configuration descriptor found");
+ }
+
+ makeConfigurationDescriptor = configurationDescriptorProvider.getConfigurationDescriptor();
+ if (makeConfigurationDescriptor == null) {
+ throw new IllegalArgumentException("No MakeConfigurationDescriptor");
+ }
+
+ }
+
+ @Override
+ public Void call() throws Exception {
+
+ try {
+ updateCompilationDatabase();
+ } catch (Exception e) {
+ LOG.log(Level.SEVERE, String.format("Error updating compilation database:%s:%s", e.getMessage(), e.getClass().getName()), e);
+ throw e;
+ }
+ return null;
+ }
+
+ public void updateCompilationDatabase() throws Exception {
+ LOG.log(Level.FINE, "Updating compilation database");
+
+ if (cancelled) {
+ LOG.log(Level.FINE, "Task was cancelled.");
+ return;
+ }
+
+ if (!support.isOpen()) {
+ LOG.log(Level.FINE, "Project is not open, bailing out.");
+ return;
+ }
+
+ if (pendingCauses.isEmpty()) {
+ LOG.log(Level.FINE, "No pending causes, bailing out");
+ return;
+ }
+
+ ArrayList<ClangCDBGenerationCause> coalescedCauses = new ArrayList<>(pendingCauses.size());
+ pendingCauses.drainTo(coalescedCauses);
+
+ File projectDirectory = FileUtil.toFile(makeProject.getProjectDirectory());
+ File compilationDatabase = new File(projectDirectory, CDB_NAME);
+ LOG.log(Level.FINE, "Updating compilation database {0} because {1}",
+ new Object[]{compilationDatabase.getPath(), coalescedCauses.toString()});
+
+ // Get the project items,
+ Item[] items = makeConfigurationDescriptor.getProjectItems();
+ if (items == null || items.length == 0) {
+ LOG.log(Level.FINE, "No items in project.");
+ return;
+ }
+
+ if (cancelled) {
+ LOG.log(Level.FINE, "Task cancelled");
+ return;
+ }
+
+ long startTime = System.currentTimeMillis();
+
+ // Use a temporary file to create the compilation database.
+ File tempFile = Files.createTempFile("CDB", ".json").toFile(); // NOI18N
+
+ try ( FileOutputStream outputStream = new FileOutputStream(tempFile); //
+ PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8))) {
+ FileChannel channel = outputStream.getChannel();
+ FileLock lock = channel.lock();
+ writeCompilationDatabase(writer, lock, items);
+ }
+
+ // Only update the compilation database if we're done with all items.
+ if (!cancelled) {
+ try {
+ Files.move(tempFile.toPath(), compilationDatabase.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ } catch (Throwable e) {
+ LOG.log(Level.SEVERE, String.format("Error updating compilation database %s:%s", e.getMessage(), e.getClass().getName()), e);
+ }
+ }
+
+ // And delete the temporary file
+ tempFile.delete();
+
+ long endTime = System.currentTimeMillis();
+ LOG.log(Level.INFO, "Regeneration of {0} took {1} ms.", new Object[]{
+ compilationDatabase.getAbsolutePath(),
+ endTime - startTime
+ });
+ }
+
+ private void writeCompilationDatabase(PrintWriter writer, FileLock lock, Item[] items)
+ throws Exception {
+
+ // We don't want to hold all command objects in memory, but write
+ // them sequentially.
+ writer.println("[");
+ boolean firstItem = true;
+ for (Item item : items) {
+ if (cancelled) {
+ return;
+ }
+ LOG.log(Level.FINE, "Updating compilation db for item {0}", item.getName());
+ Language language = item.getLanguage();
+ ItemConfiguration itemConfiguration = item.getItemConfiguration(activeMakeConfiguration);
+ JSONObject commandObject = null;
+ switch (language) {
+ case C_HEADER:
+ // C headers are not included in compilation databases
+ continue;
+ case C:
+ case CPP:
+ case OTHER: // Assembler?
+ // C and C++ files (and possibly assembler) are included in the compilation database
+ commandObject = getCommandObjectForItem(
+ language, item, itemConfiguration);
+ break;
+ case FORTRAN:
+ // Fortran is not supported in clang-style compilation databases, AFAIK
+ break;
+ }
+ if (commandObject != null) {
+ if (firstItem) {
+ firstItem = false;
+ } else {
+ writer.print(",");
+ }
+ commandObject.writeJSONString(writer);
+ writer.println();
+ }
+ }
+ writer.println("]");
+ }
+
+ /**
+ * Returns a Command Object required to compile an item.
+ *
+ * @param makeProject The project
+ * @param activeMakeConfiguration The active make configuration.
+ * @param compilerSet The compiler set.
+ * @param item The item being compiled.
+ * @param itemConfiguration The item configuration of the item.
+ * @return A JSON String with this command object.
+ * @throws Exception If an I/O error happens.
+ */
+ private JSONObject getCommandObjectForItem(
+ Language language, Item item, ItemConfiguration itemConfiguration)
+ throws Exception {
+
+ if (itemConfiguration.getExcluded().getValue()) {
+ LOG.log(Level.FINE, "Skipping excluded item {0}",
+ item.getName());
+ return null;
+ }
+
+ CommandObjectBuilder builder = new CommandObjectBuilder(makeProject);
+
+ // 0. 'directory' entry in the command object is automatically added.
+ // 1. 'file' entry in the command object.
+ LOG.log(Level.FINE, "Creating command object for item: {0} in file: {1}", new Object[]{item.getName(), item.getAbsolutePath()});
+ builder.setFile(item.getAbsolutePath());
+
+ // 2. 'command' entry in the command object
+ PredefinedToolKind toolKind = itemConfiguration.getTool();
+ Tool compilerTool = compilerSet.getTool(toolKind);
+ if (!(compilerTool instanceof AbstractCompiler)) {
+ LOG.log(Level.FINE, "Cannot find an AbstractCompiler for item {0}",
+ item.getName());
+ return null;
+ }
+ AbstractCompiler compiler = (AbstractCompiler) compilerTool;
+ // 2.1 compiler path ("/usr/bin/gcc", for instance).
+ builder.addCommandItem(compiler.getPath());
+
+ // 2.2 "-c" flag. This is currently hardcoded in NetBeans CND... :-(
+ builder.addCommandItem("-c");
+
+ // 2.3 The full path of the file to compile ("/home/users/user/project/myfile.c")
+ builder.addCommandItem(builder.getFile());
+
+ // 2.3 language specific flags
+ // C Options
+ {
+ CCompilerConfiguration cConfiguration = itemConfiguration.getCCompilerConfiguration();
+ if (cConfiguration != null) {
+ String cFlags = cConfiguration.getCFlags(compiler);
+ builder.addCommandItem(cFlags);
+ String allOptions = cConfiguration.getAllOptions2(compiler);
+ builder.addCommandItem(allOptions);
+ LOG.log(Level.FINE, "C: CFLAGS {0} options {1}", new Object[]{cFlags, allOptions});
+ }
+ }
+
+ // C++ options
+ {
+ CCCompilerConfiguration cppConfiguration = itemConfiguration.getCCCompilerConfiguration();
+ if (cppConfiguration != null) {
+ String cppFlags = cppConfiguration.getCCFlags(compiler);
+ builder.addCommandItem(cppFlags);
+ String allOptions = cppConfiguration.getAllOptions2(compiler);
+ builder.addCommandItem(allOptions);
+ LOG.log(Level.FINE, "C++: CFLAGS {0} options {1}", new Object[]{cppFlags, allOptions});
+ }
+ }
+
+ // 3. output file ("/home/users/user/project/build/Linux/X86/myfile.o", for instance)
+ // Note that "output" is optional in CommandObjects
+ BasicCompilerConfiguration basicCompilerConfiguration = itemConfiguration.getCompilerConfiguration();
+ String outputFile = basicCompilerConfiguration.getOutputFile(item, activeMakeConfiguration, true);
+
+ if (outputFile != null) {
+ // outputFile is constructed with Makefile macros, like these:
+ // "/home/antonio/tmp/${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/main.o
+ // We want to expand these
+ outputFile = activeMakeConfiguration.expandMacros(outputFile);
+ builder.setOutput(outputFile);
+
+ // We also include a '-o outputfile' to the command
+ builder.addCommandItem("-o");
+ builder.addCommandItem(outputFile);
+ }
+
+ return builder.build();
+ }
+
+ @Override
+ public boolean cancel() {
+ this.cancelled = true;
+ return true;
+ }
+
+}
diff --git a/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/compilationdb/ClangCDBSupport.java b/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/compilationdb/ClangCDBSupport.java
new file mode 100644
index 0000000..e7ca389
--- /dev/null
+++ b/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/compilationdb/ClangCDBSupport.java
@@ -0,0 +1,219 @@
+/*
+ * 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.cnd.lsp.compilationdb;
+
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.netbeans.modules.cnd.api.project.NativeFileItem;
+import org.netbeans.modules.cnd.api.project.NativeProject;
+import org.netbeans.modules.cnd.api.project.NativeProjectItemsListener;
+import org.netbeans.modules.cnd.makeproject.api.MakeProject;
+import org.netbeans.modules.cnd.makeproject.api.support.MakeProjectEvent;
+import org.netbeans.modules.cnd.makeproject.api.support.MakeProjectListener;
+import org.netbeans.spi.project.ui.ProjectOpenedHook;
+import org.openide.util.RequestProcessor;
+
+/**
+ * ClangCDBSupport is responsible for detecting and generating a JSON
+ * compilation database, as defined in
+ * https://clang.llvm.org/docs/JSONCompilationDatabase.html
+ *
+ * When "ProjectOpenedHook.projectOpened" is fired, i.e., when the project is
+ * opened, we start listening to NativeProjectItemsListener and
+ * MakeProjectListener.
+ *
+ * We remove these listeners when the project is closed or deleted.
+ *
+ * The compilation database is regenerated after COALESCING_DELAY_MS
+ * milliseconds. Requests are coalesced using a "pendingCauses" blocking queue.
+ */
+public final class ClangCDBSupport
+ extends ProjectOpenedHook
+ implements
+ NativeProjectItemsListener, MakeProjectListener {
+
+ private static final Logger LOG = Logger.getLogger(ClangCDBSupport.class.getName());
+ private static final RequestProcessor CLANG_CDB_PROCESSOR = new RequestProcessor(ClangCDBSupport.class.getName());
+ private static final long COALESCING_DELAY_MS = 1000;
+ private final MakeProject makeProject;
+ private final BlockingQueue<ClangCDBGenerationCause> pendingCauses;
+ private boolean projectOpen;
+
+ public ClangCDBSupport(final MakeProject makeProject) {
+ this.makeProject = makeProject;
+ this.projectOpen = false;
+ this.pendingCauses = new LinkedBlockingQueue<>();
+ }
+
+ /**
+ * Called when multiple files are added to the project.
+ *
+ * @param fileItems the list of file items that was added.
+ */
+ @Override
+ public void filesAdded(List<NativeFileItem> fileItems) {
+ updateCompilationDatabase(ClangCDBGenerationCause.FILES_ADDED);
+ }
+
+ /**
+ * Called when multiple files are removed from the project.
+ *
+ * @param fileItems the list of file items that was added.
+ */
+ @Override
+ public void filesRemoved(List<NativeFileItem> fileItems) {
+ updateCompilationDatabase(ClangCDBGenerationCause.FILES_REMOVED);
+ }
+
+ /**
+ * Called when include paths or macro definitions have changed (and files
+ * needs to be re-parsed) for multiple files.
+ *
+ * @param fileItems the list of file items that has changed.
+ */
+ @Override
+ public void filesPropertiesChanged(List<NativeFileItem> fileItems) {
+ updateCompilationDatabase(ClangCDBGenerationCause.INCLUDES_MACROS_CHANGED);
+ }
+
+ /**
+ * Called when include paths or macro definitions have changed (and files
+ * needs to be re-parsed) for all files in project.
+ *
+ * @param nativeProject project whose properties have changed
+ */
+ @Override
+ public void filesPropertiesChanged(NativeProject nativeProject) {
+ updateCompilationDatabase(ClangCDBGenerationCause.INCLUDES_MACROS_CHANGED);
+ }
+
+ @Override
+ public void fileRenamed(String oldPath, NativeFileItem newFileIetm) {
+ updateCompilationDatabase(ClangCDBGenerationCause.FILES_RENAMED);
+ }
+
+ /**
+ * notifies about intensive file operations to be started. We ignore these.
+ *
+ * @param nativeProject
+ */
+ @Override
+ public void fileOperationsStarted(NativeProject nativeProject) {
+ LOG.log(Level.FINE, "File operations started.");
+ }
+
+ /**
+ * notifies about intensive file operations finished. We ignore these
+ *
+ * @param nativeProject
+ */
+ @Override
+ public void fileOperationsFinished(NativeProject nativeProject) {
+ LOG.log(Level.FINE, "File operations finished.");
+ }
+
+ @Override
+ public void configurationXmlChanged(MakeProjectEvent ev) {
+ updateCompilationDatabase(ClangCDBGenerationCause.PROJECT_CONFIGURATION_CHANGED);
+ }
+
+ /**
+ * Ignored. See javadoc
+ * @param ev
+ */
+ @Override
+ public void propertiesChanged(MakeProjectEvent ev) {
+ LOG.log(Level.FINE, "Some project properties changed {0}",
+ ev.getPath());
+ }
+
+ @Override
+ protected void projectOpened() {
+ LOG.log(Level.FINE, "Project opened");
+ projectOpen = true;
+ makeProject.getHelper().addMakeProjectListener(this);
+ NativeProject nativeProject = makeProject.getLookup().lookup(NativeProject.class);
+ if (nativeProject != null) {
+ nativeProject.addProjectItemsListener(this);
+ } else {
+ LOG.log(Level.FINE, "Cannot attach to native project events.");
+ }
+ updateCompilationDatabase(ClangCDBGenerationCause.PROJECT_OPENED);
+ }
+
+ @Override
+ protected void projectClosed() {
+ LOG.log(Level.FINE, "Project closed");
+ removeListenersOnCloseOrDelete();
+ }
+
+ @Override
+ public void projectDeleted(NativeProject nativeProject) {
+ LOG.log(Level.FINE, "Project deleted");
+ removeListenersOnCloseOrDelete();
+ }
+
+ private void removeListenersOnCloseOrDelete() {
+ projectOpen = false;
+ makeProject.getHelper().removeMakeProjectListener(this);
+ NativeProject nativeProject = makeProject.getLookup().lookup(NativeProject.class);
+ if (nativeProject != null) {
+ nativeProject.removeProjectItemsListener(this);
+ } else {
+ LOG.log(Level.FINE, "Cannot detach from native project events.");
+ }
+ }
+
+ /**
+ * Updates the compilation database "[project]/compile_commands.json". If a
+ * task is already running then the request is silently ignored.
+ *
+ * @param cause The cause that originated the need to recreate the
+ * compilation database.
+ */
+ private void updateCompilationDatabase(ClangCDBGenerationCause cause) {
+ LOG.log(Level.FINE, "Update compilation database project is open: {0}", projectOpen);
+ if (projectOpen) {
+ pendingCauses.add(cause);
+ ClangCDBGenerationTask task = null;
+ try {
+ task = new ClangCDBGenerationTask(this, pendingCauses);
+ } catch (IllegalArgumentException iae) {
+ LOG.log(Level.SEVERE, "Unable to create ClangCDBGenerationTask: {0}", iae.getMessage());
+ return;
+ }
+ // We fire the regeneration task after a COALESCING_DELAY_MS milliseconds, to
+ // coalesce requests (for instance, when many files are added or removed).
+ CLANG_CDB_PROCESSOR.schedule(task, COALESCING_DELAY_MS, TimeUnit.MILLISECONDS);
+ }
+ }
+
+ MakeProject getMakeProject() {
+ return makeProject;
+ }
+
+ boolean isOpen() {
+ return projectOpen;
+ }
+
+}
diff --git a/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/compilationdb/CommandObjectBuilder.java b/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/compilationdb/CommandObjectBuilder.java
new file mode 100644
index 0000000..10d0a4d
--- /dev/null
+++ b/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/compilationdb/CommandObjectBuilder.java
@@ -0,0 +1,131 @@
+/*
+ * 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.cnd.lsp.compilationdb;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.json.simple.JSONObject;
+import org.netbeans.api.project.Project;
+import org.openide.filesystems.FileObject;
+
+/**
+ * CommandObjectBuilder builds a JSONObject representing a CommandObject as
+ * defined in https://clang.llvm.org/docs/JSONCompilationDatabase.html
+ */
+final class CommandObjectBuilder {
+
+ private static final Logger LOG = Logger.getLogger(CommandObjectBuilder.class.getName());
+
+ private final Project project;
+ private final StringBuilder command;
+ private String file;
+ private String output;
+
+ CommandObjectBuilder(Project project) {
+ this.project = project;
+ this.command = new StringBuilder();
+ }
+
+ /**
+ * Appends another piece of the 'command' entry in the command object. For
+ * instance, you can add "-strip" or "-std=ansi".
+ *
+ * @param part The part to append at the end of the command line.
+ * @return this
+ */
+ CommandObjectBuilder addCommandItem(String part) {
+ if (part != null) {
+ command.append(' ').append(part).append(' ');
+ }
+ return this;
+ }
+
+ /**
+ * Sets the 'file' entry in the command object. For instance,
+ * "/usr/home/user/project/folder/file.c"
+ *
+ * @param file The file. Absolute paths are recommended, but can be relative
+ * to the project.getProjectDirectory().
+ * @return this
+ */
+ CommandObjectBuilder setFile(String file) {
+ this.file = Paths.get(file).toAbsolutePath().toString();
+ return this;
+ }
+
+ /**
+ * Sets the 'output' entry in the command object. For instance,
+ * "/usr/home/user/project/build/platform/file.o"
+ *
+ * @param output The file. Absolute paths are recommended, but can be
+ * relative to the project.getProjectDirectory().
+ * @return this.
+ */
+ CommandObjectBuilder setOutput(String output) {
+ this.output = Paths.get(output).toAbsolutePath().toString();
+ return this;
+ }
+
+ String getFile() {
+ return file;
+ }
+
+ /**
+ * Builds a JSONObject representing this command object. NOTE: 'directory'
+ * entry is automatically set to project.getProjectDirectory().
+ *
+ * @return The JSONObject representing this command object.
+ * @throws IllegalStateException if a mandatory entri in the command object
+ * is not present.
+ */
+ JSONObject build() throws IllegalStateException {
+ if (file == null) {
+ throw new IllegalStateException("Missing file");
+ }
+ if (command.length() == 0) {
+ throw new IllegalStateException("No command");
+ }
+
+ JSONObject object = new JSONObject();
+
+ // directory
+ FileObject projectDirectory = project.getProjectDirectory();
+ Path directory = Paths.get(projectDirectory.toURI());
+ directory = directory.toAbsolutePath();
+ LOG.log(Level.FINE, "Directory {0}", directory.toString());
+ object.put("directory", directory.toString());
+
+ // file
+ LOG.log(Level.FINE, "File {0}", file);
+ object.put("file", file);
+
+ // command
+ object.put("command", command.toString().trim());
+ LOG.log(Level.FINE, "Command {0}", command.toString());
+
+ // output (this one is optional)
+ if (output != null) {
+ object.put("output", output);
+ }
+ return object;
+ }
+
+}
diff --git a/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/makeproject/LSPMakeProjectLookupProvider.java b/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/makeproject/LSPMakeProjectLookupProvider.java
new file mode 100644
index 0000000..0913516
--- /dev/null
+++ b/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/makeproject/LSPMakeProjectLookupProvider.java
@@ -0,0 +1,40 @@
+/*
+ * 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.cnd.lsp.makeproject;
+
+import java.util.ArrayList;
+import org.netbeans.modules.cnd.lsp.compilationdb.ClangCDBSupport;
+import org.netbeans.modules.cnd.makeproject.api.MakeProject;
+import org.netbeans.modules.cnd.makeproject.api.MakeProjectLookupProvider;
+import org.openide.util.lookup.ServiceProvider;
+
+/**
+ * Adds stuff to MakeProject Lookup.
+ * @author antonio
+ */
+@ServiceProvider(service = MakeProjectLookupProvider.class)
+public class LSPMakeProjectLookupProvider implements MakeProjectLookupProvider {
+
+ @Override
+ public void addLookup(MakeProject owner, ArrayList<Object> ic) {
+ ClangCDBSupport support = new ClangCDBSupport(owner);
+ ic.add(support);
+ }
+
+}
diff --git a/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/resources/Bundle.properties b/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/resources/Bundle.properties
new file mode 100644
index 0000000..caf1327
--- /dev/null
+++ b/cnd/cnd.lsp/src/org/netbeans/modules/cnd/lsp/resources/Bundle.properties
@@ -0,0 +1,22 @@
+# 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.
+OpenIDE-Module-Display-Category=C/C++
+# Should not be translated
+OpenIDE-Module-Long-Description=\
+ C/C++ Language Server Protocol support
+OpenIDE-Module-Name=C/C++ LSP
+OpenIDE-Module-Short-Description=Language Server Protocol Support for C/C++
diff --git a/cnd/cnd.makeproject/nbproject/project.xml b/cnd/cnd.makeproject/nbproject/project.xml
index 8bb88b4..17d2750 100644
--- a/cnd/cnd.makeproject/nbproject/project.xml
+++ b/cnd/cnd.makeproject/nbproject/project.xml
@@ -345,6 +345,7 @@
<friend>org.netbeans.modules.cnd.gizmo</friend>
<friend>org.netbeans.modules.cnd.highlight</friend>
<friend>org.netbeans.modules.cnd.jconvertwizard</friend>
+ <friend>org.netbeans.modules.cnd.lsp</friend>
<friend>org.netbeans.modules.cnd.make2netbeans</friend>
<friend>org.netbeans.modules.cnd.makeproject.source.bridge</friend>
<friend>org.netbeans.modules.cnd.makeproject.ui</friend>
diff --git a/cnd/cnd.toolchain/nbproject/project.xml b/cnd/cnd.toolchain/nbproject/project.xml
index f3088b5..aece047 100644
--- a/cnd/cnd.toolchain/nbproject/project.xml
+++ b/cnd/cnd.toolchain/nbproject/project.xml
@@ -246,7 +246,6 @@
<friend>org.netbeans.modules.cnd.analysis.impl</friend>
<friend>org.netbeans.modules.cnd.api.remote</friend>
<friend>org.netbeans.modules.cnd.audit</friend>
- <friend>org.netbeans.modules.cnd.jconvertwizard</friend>
<friend>org.netbeans.modules.cnd.classview</friend>
<friend>org.netbeans.modules.cnd.cncppunit</friend>
<friend>org.netbeans.modules.cnd.completion</friend>
@@ -259,6 +258,8 @@
<friend>org.netbeans.modules.cnd.dwarfdiscovery</friend>
<friend>org.netbeans.modules.cnd.gizmo</friend>
<friend>org.netbeans.modules.cnd.highlight</friend>
+ <friend>org.netbeans.modules.cnd.jconvertwizard</friend>
+ <friend>org.netbeans.modules.cnd.lsp</friend>
<friend>org.netbeans.modules.cnd.make2netbeans</friend>
<friend>org.netbeans.modules.cnd.makeproject</friend>
<friend>org.netbeans.modules.cnd.makeproject.ui</friend>
diff --git a/ide/dlight.nativeexecution/nbproject/project.xml b/ide/dlight.nativeexecution/nbproject/project.xml
index db4cb91..885590a 100644
--- a/ide/dlight.nativeexecution/nbproject/project.xml
+++ b/ide/dlight.nativeexecution/nbproject/project.xml
@@ -259,6 +259,7 @@
<friend>org.netbeans.modules.cnd.dwarfdiscovery</friend>
<friend>org.netbeans.modules.cnd.gizmo</friend>
<friend>org.netbeans.modules.cnd.highlight</friend>
+ <friend>org.netbeans.modules.cnd.lsp</friend>
<friend>org.netbeans.modules.cnd.makeproject</friend>
<friend>org.netbeans.modules.cnd.makeproject.ui</friend>
<friend>org.netbeans.modules.cnd.mixeddev</friend>
diff --git a/nbbuild/cluster.properties b/nbbuild/cluster.properties
index 9120a242..97aabf4 100644
--- a/nbbuild/cluster.properties
+++ b/nbbuild/cluster.properties
@@ -1089,6 +1089,7 @@ nb.cluster.cnd=\
cnd.editor,\
cnd.kit,\
cnd.lexer,\
+ cnd.lsp,\
cnd.makeproject,\
cnd.makeproject.source.bridge,\
cnd.makeproject.ui,\
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists