Changes to properties in yaml format from AI response

This commit is contained in:
aboyko
2024-10-08 21:04:11 -04:00
parent 084d3a9ad7
commit 9b1052bf0a
20 changed files with 259 additions and 80 deletions

View File

@@ -160,16 +160,20 @@ public class ORDocUtils {
}
WorkspaceEdit we = new WorkspaceEdit();
we.setDocumentChanges(new ArrayList<>());
addToWorkspaceEdit(documents, results, changeAnnotationId, we);
return Optional.of(we);
}
public static void addToWorkspaceEdit(SimpleTextDocumentService documents, List<Result> results, String changeAnnotationId, WorkspaceEdit we) {
for (Result result : results) {
String docUri = result.getBefore() == null ? result.getAfter().getSourcePath().toUri().toASCIIString() : result.getBefore().getSourcePath().toUri().toASCIIString();
String oldContent = result.getBefore() == null ? null : result.getBefore().printAll();
String newContent = result.getAfter() == null ? null : result.getAfter().printAll();
createWorkspaceEdit(documents, docUri, oldContent, newContent, changeAnnotationId, we);
addToWorkspaceEdit(documents, docUri, oldContent, newContent, changeAnnotationId, we);
}
return Optional.of(we);
}
public static void createWorkspaceEdit(SimpleTextDocumentService documents, String docUri, String oldContent, String newContent, String changeAnnotationId, WorkspaceEdit we) {
public static void addToWorkspaceEdit(SimpleTextDocumentService documents, String docUri, String oldContent, String newContent, String changeAnnotationId, WorkspaceEdit we) {
if(oldContent == null) {
createNewFileEdit(docUri, newContent, changeAnnotationId, we);
} else if (newContent == null) {

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.copilot;
import java.io.BufferedWriter;

View File

@@ -10,8 +10,6 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.copilot;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@@ -61,7 +59,7 @@ public class CopilotAgentCommandHandler {
return CompletableFuture.supplyAsync(() -> {
try {
return createLspEdits(params);
} catch (IOException e) {
} catch (Exception e) {
throw new CompletionException(e);
}
}).thenCompose(we -> {
@@ -86,7 +84,7 @@ public class CopilotAgentCommandHandler {
return CompletableFuture.completedFuture(modifiedResp);
}
private WorkspaceEdit createLspEdits(ExecuteCommandParams params) throws IOException {
private WorkspaceEdit createLspEdits(ExecuteCommandParams params) throws Exception {
log.info("Command Handler for lsp edits: ");
String docURI = ((JsonElement) params.getArguments().get(0)).getAsString();
String content = ((JsonElement) params.getArguments().get(1)).getAsString();
@@ -94,7 +92,7 @@ public class CopilotAgentCommandHandler {
IJavaProject project = this.projectFinder.find(new TextDocumentIdentifier(docURI)).get();
List<ProjectArtifact> projectArtifacts = computeProjectArtifacts(content);
ProjectArtifactEditGenerator editGenerator = new ProjectArtifactEditGenerator(server.getTextDocumentService(),
projectArtifacts, Paths.get(project.getLocationUri()), docURI);
projectArtifacts, project, docURI);
return editGenerator.process().getResult();
}

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.copilot;
import java.nio.file.Path;

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.copilot;
import java.util.Objects;

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.copilot;
import java.util.Objects;

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.copilot;
import java.util.Objects;

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.copilot;
import java.util.ArrayList;

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.copilot;
import java.util.ArrayList;

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.copilot;
import java.util.Objects;

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.copilot;
import java.util.List;

View File

@@ -1,33 +1,55 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.copilot;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.io.IOUtils;
import org.eclipse.lsp4j.ChangeAnnotation;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.openrewrite.InMemoryExecutionContext;
import org.openrewrite.Result;
import org.openrewrite.config.DeclarativeRecipe;
import org.openrewrite.internal.InMemoryLargeSourceSet;
import org.openrewrite.java.spring.AddSpringProperty;
import org.openrewrite.java.spring.ChangeSpringPropertyValue;
import org.openrewrite.properties.PropertiesParser;
import org.openrewrite.xml.tree.Xml;
import org.openrewrite.yaml.YamlParser;
import org.springframework.ide.vscode.boot.java.copilot.InjectMavenActionHandler.MavenDependencyMetadata;
import org.springframework.ide.vscode.boot.java.copilot.util.ClassNameExtractor;
import org.springframework.ide.vscode.boot.java.copilot.util.PropertyFileUtils;
import org.springframework.ide.vscode.boot.java.copilot.util.SpringCliException;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
import org.springframework.ide.vscode.commons.protocol.java.Classpath;
import org.springframework.ide.vscode.commons.rewrite.ORDocUtils;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -35,23 +57,23 @@ public class ProjectArtifactEditGenerator {
private final List<ProjectArtifact> projectArtifacts;
private final Path projectPath;
private final IJavaProject project;
private final SimpleTextDocumentService simpleTextDocumentService;
public ProjectArtifactEditGenerator(SimpleTextDocumentService simpleTextDocumentService,
List<ProjectArtifact> projectArtifacts, Path projectPath, String readmeFileName) {
List<ProjectArtifact> projectArtifacts, IJavaProject project, String readmeFileName) {
this.simpleTextDocumentService = simpleTextDocumentService;
this.projectArtifacts = projectArtifacts;
this.projectPath = projectPath;
this.project = project;
}
public ProcessArtifactResult<WorkspaceEdit> process() throws IOException {
return processArtifacts(projectArtifacts, projectPath);
public ProcessArtifactResult<WorkspaceEdit> process() throws Exception {
return processArtifacts(projectArtifacts, Paths.get(project.getLocationUri()));
}
private ProcessArtifactResult<WorkspaceEdit> processArtifacts(List<ProjectArtifact> projectArtifacts,
Path projectPath) throws IOException {
Path projectPath) throws Exception {
ProcessArtifactResult<WorkspaceEdit> processArtifactResult = new ProcessArtifactResult<>();
String changeAnnotationId = UUID.randomUUID().toString();
WorkspaceEdit we = new WorkspaceEdit();
@@ -96,7 +118,7 @@ public class ProjectArtifactEditGenerator {
Optional<String> className = classNameExtractor.extractClassName(projectArtifact.getText());
if (className.isPresent()) {
Path output = resolveSourceFile(projectPath, packageName, className.get() + ".java");
ORDocUtils.createWorkspaceEdit(simpleTextDocumentService, output.toUri().toASCIIString(),
ORDocUtils.addToWorkspaceEdit(simpleTextDocumentService, output.toUri().toASCIIString(),
getFileContent(output), projectArtifact.getText(), changeAnnotationId, we);
}
}
@@ -117,16 +139,16 @@ public class ProjectArtifactEditGenerator {
Optional<String> className = classNameExtractor.extractClassName(projectArtifact.getText());
if (className.isPresent()) {
Path output = resolveTestFile(projectPath, packageName, className.get() + ".java");
ORDocUtils.createWorkspaceEdit(simpleTextDocumentService, output.toUri().toASCIIString(),
ORDocUtils.addToWorkspaceEdit(simpleTextDocumentService, output.toUri().toASCIIString(),
getFileContent(output), projectArtifact.getText(), changeAnnotationId, we);
}
}
private void writeMavenDependencies(ProjectArtifact projectArtifact, Path projectPath, String changeAnnotationId,
WorkspaceEdit we) {
Path currentProjectPomPath = this.projectPath.resolve("pom.xml");
Path currentProjectPomPath = Paths.get(project.getLocationUri()).resolve("pom.xml");
if (Files.notExists(currentProjectPomPath)) {
throw new SpringCliException("Could not find pom.xml in " + this.projectPath
throw new SpringCliException("Could not find pom.xml in " + Paths.get(project.getLocationUri())
+ ". Make sure you are running the command in the project's root directory.");
}
@@ -149,24 +171,60 @@ public class ProjectArtifactEditGenerator {
}
private void writeApplicationProperties(ProjectArtifact projectArtifact, Path projectPath,
String changeAnnotationId, WorkspaceEdit we) throws IOException {
Path applicationPropertiesPath = projectPath.resolve("src").resolve("main").resolve("resources")
.resolve("application.properties");
String changeAnnotationId, WorkspaceEdit we) throws Exception {
List<Path> propFiles = new ArrayList<>();
List<Path> yamlFiles = new ArrayList<>();
AtomicReference<Path> sourceFolder = new AtomicReference<>();
project.getClasspath().getClasspathEntries().stream().filter(Classpath::isSource)
.filter(cpe -> !cpe.isSystem() && !cpe.isTest() && cpe.isOwn() && !cpe.isJavaContent())
.map(cpe -> new File(cpe.getPath()).toPath())
.flatMap(folder -> {
sourceFolder.compareAndSet(null, folder);
try {
return Files.list(folder);
} catch (IOException e) {
return Stream.empty();
}
}).forEach(p -> {
String fileName = p.getFileName().toString();
if (propFiles.isEmpty() && "application.properties".equals(fileName)) {
propFiles.add(p);
} else if (yamlFiles.isEmpty() && ("application.yml".equals(fileName) || "application.yaml".equals(fileName))) {
yamlFiles.add(p);
}
});
Properties srcProperties = new Properties();
Properties destProperties = new Properties();
srcProperties.load(IOUtils.toInputStream(projectArtifact.getText(), StandardCharsets.UTF_8));
if (Files.exists(applicationPropertiesPath)) {
destProperties.load(new FileInputStream(applicationPropertiesPath.toFile()));
if (propFiles.isEmpty() && yamlFiles.isEmpty()) {
Path propsFile = (sourceFolder.get() == null ? Paths.get(project.getLocationUri()).resolve("src/main/resources") : sourceFolder.get()).resolve("application.properties");
ORDocUtils.addToWorkspaceEdit(simpleTextDocumentService, propsFile.toUri().toASCIIString(),
null, projectArtifact.getText(), changeAnnotationId, we);
} else {
DeclarativeRecipe aggregateRecipe = new DeclarativeRecipe("spring-tools.ai.PropertiesUpdates",
"Add property files changes from AI", "", Collections.emptySet(), null, null, false, Collections.emptyList());
Properties srcProperties = new Properties();
srcProperties.load(IOUtils.toInputStream(projectArtifact.getText(), StandardCharsets.UTF_8));
for (Map.Entry<?, ?> e : srcProperties.entrySet()) {
aggregateRecipe.getRecipeList().add(new AddSpringProperty(e.getKey().toString(), e.getValue().toString(), null, List.of()));
aggregateRecipe.getRecipeList().add(new ChangeSpringPropertyValue(e.getKey().toString(), e.getValue().toString(), null, null, null));
}
ORDocUtils.addToWorkspaceEdit(
simpleTextDocumentService,
aggregateRecipe.run(
new InMemoryLargeSourceSet(PropertiesParser.builder().build().parse(propFiles, null, new InMemoryExecutionContext()).collect(Collectors.toList())),
new InMemoryExecutionContext())
.getChangeset().getAllResults(),
changeAnnotationId,
we);
ORDocUtils.addToWorkspaceEdit(
simpleTextDocumentService,
aggregateRecipe.run(
new InMemoryLargeSourceSet(YamlParser.builder().build().parse(yamlFiles, null, new InMemoryExecutionContext()).collect(Collectors.toList())),
new InMemoryExecutionContext())
.getChangeset().getAllResults(),
changeAnnotationId,
we);
}
Properties mergedProperties = PropertyFileUtils.mergeProperties(srcProperties, destProperties);
StringWriter sw = new StringWriter();
mergedProperties.store(sw, "updated by spring ai add");
sw.flush();
String newContent = sw.getBuffer().toString();
ORDocUtils.createWorkspaceEdit(simpleTextDocumentService, applicationPropertiesPath.toUri().toASCIIString(),
getFileContent(applicationPropertiesPath), newContent, changeAnnotationId, we);
}
private void updateMainApplicationClassAnnotations(ProjectArtifact projectArtifact, Path projectPath,
@@ -181,7 +239,7 @@ public class ProjectArtifactEditGenerator {
String fileName = extractFilenameFromComment(html);
if (fileName != null) {
Path htmlFile = projectPath.resolve(fileName);
ORDocUtils.createWorkspaceEdit(simpleTextDocumentService, fileName, getFileContent(htmlFile),
ORDocUtils.addToWorkspaceEdit(simpleTextDocumentService, fileName, getFileContent(htmlFile),
projectArtifact.getText(), changeAnnotationId, we);
}
}
@@ -195,7 +253,7 @@ public class ProjectArtifactEditGenerator {
Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
Matcher matcher = pattern.matcher(firstLine);
// Find the package statement and extract the package name
String packageName = "";
// String packageName = "";
if (matcher.find()) {
packageToUse = matcher.group(1);
}

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.copilot;
/**

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.copilot;
import java.util.Map;

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.copilot.util;
import java.util.ArrayList;

View File

@@ -1,41 +0,0 @@
package org.springframework.ide.vscode.boot.java.copilot.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import org.apache.commons.io.IOUtils;
public final class PropertyFileUtils {
private PropertyFileUtils() {
}
public static Properties getPropertyFile() {
File homeDir = new File(System.getProperty("user.home"));
File propertyFile = new File(homeDir, ".openai");
Properties props = new Properties();
FileInputStream in = null;
try {
in = new FileInputStream(propertyFile);
props.load(in);
return props;
}
catch (IOException ex) {
throw new SpringCliException("Could not load property file ~/.openai", ex);
}
finally {
IOUtils.closeQuietly(in);
}
}
public static Properties mergeProperties(Properties... properties) {
Properties mergedProperties = new Properties();
for (Properties property : properties) {
mergedProperties.putAll(property);
}
return mergedProperties;
}
}

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.copilot.util;
import java.time.LocalDateTime;

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.copilot.util;
@SuppressWarnings("serial")

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.cron;
import java.util.LinkedHashMap;

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.cron;
import java.util.Locale;