Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@
**/mvnw.cmd
**/.yarn
**/.yarnrc.yml
**/*.jar
/extension/*.cjs
/extension/*.mjs
395 changes: 210 additions & 185 deletions c4-server/pom.xml

Large diffs are not rendered by default.

32 changes: 0 additions & 32 deletions c4-server/src/assembly/assembly.xml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,75 +16,38 @@

package ru.beeatlas.c4;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.channels.Channels;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.eclipse.lsp4j.jsonrpc.Launcher;
import org.eclipse.lsp4j.launch.LSPLauncher;
import org.eclipse.lsp4j.services.LanguageClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ru.beeatlas.c4.custom.Custom;
import ru.beeatlas.c4.service.C4LanguageServer;
import picocli.CommandLine;
import picocli.CommandLine.Option;

public class C4LanguageServerLauncher implements Callable<Integer> {

private static final Logger logger = LoggerFactory.getLogger(C4LanguageServerLauncher.class);

@Option(names = {"-e", "--echo"}, description = "Echo to the client, to inform that socket can now accept incoming connections")
private String echo = "READY_TO_CONNECT";

@Override
public Integer call() throws Exception {

try {

final AsynchronousServerSocketChannel serverSocket = AsynchronousServerSocketChannel.open();
if (serverSocket.isOpen()) {

serverSocket.setOption(StandardSocketOptions.SO_RCVBUF, 1024);
serverSocket.setOption(StandardSocketOptions.SO_REUSEADDR, true);
serverSocket.bind(new InetSocketAddress("127.0.0.1", 5008));
Future<AsynchronousSocketChannel> acceptFuture = serverSocket.accept();
// echo to the client, that server is ready to receive incoming connections
System.out.println(echo);
final AsynchronousSocketChannel socketChannel = acceptFuture.get();
serverSocket.close();
InputStream in = Channels.newInputStream(socketChannel);
OutputStream out = Channels.newOutputStream(socketChannel);
C4LanguageServer c4LanguageServer = new C4LanguageServer();
Launcher<LanguageClient> launcher = LSPLauncher.createServerLauncher(c4LanguageServer, in, out);
// Get the client that request to launch the LS.
LanguageClient client = launcher.getRemoteProxy();
// Set the client to language server
c4LanguageServer.connect(client);
Custom.getInstance().setClient(client);
// Start the listener for JsonRPC
Future<?> startListening = launcher.startListening();
// Get the computed result from LS.
startListening.get();
}
} catch (ExecutionException | InterruptedException | IOException e) {
logger.error(e.getMessage());
Thread.currentThread().interrupt();
}
return 1;
}
public class C4LanguageServerLauncher {

public static void main(String[] args) {
int exitCode = new CommandLine( new C4LanguageServerLauncher()).execute(args);
System.exit(exitCode);
InputStream in = System.in;
OutputStream out = System.out;
System.setOut(System.err);
C4LanguageServer c4LanguageServer = new C4LanguageServer();
Launcher<LanguageClient> launcher = LSPLauncher.createServerLauncher(c4LanguageServer, in, out);
// Get the client that request to launch the LS.
LanguageClient client = launcher.getRemoteProxy();
// Set the client to language server
c4LanguageServer.connect(client);
Custom.getInstance().setClient(client);
// Start the listener for JsonRPC
Future<?> startListening = launcher.startListening();
// Get the computed result from LS.
try {
startListening.get();
} catch (InterruptedException | ExecutionException e) {
System.exit(1);
}
System.exit(0);
}

}
41 changes: 34 additions & 7 deletions c4-server/src/main/java/ru/beeatlas/c4/custom/Custom.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
Expand Down Expand Up @@ -78,6 +79,7 @@
import ru.beeatlas.c4.dto.CodeLensCommandArgs;
import ru.beeatlas.c4.model.C4DocumentModel;
import ru.beeatlas.c4.model.C4ObjectWithContext;
import ru.beeatlas.c4.model.DecoratorRange;
import ru.beeatlas.c4.model.C4DocumentModel.C4CompletionScope;
import ru.beeatlas.c4.utils.LineToken;
import ru.beeatlas.c4.utils.LineTokenizer;
Expand Down Expand Up @@ -126,6 +128,7 @@ private boolean isValidURL(String url) {
new URL(url).toURI();
return true;
} catch (Exception e) {
logger.debug(e.getMessage());
return false;
}
}
Expand Down Expand Up @@ -278,6 +281,7 @@ public void checkServerTrusted(X509Certificate[] certs, String authType) {
allTrustingTrustManager = sc.getSocketFactory();
allTrustingHostnameVerifier = (String hostname, SSLSession session) -> true;
} catch (Exception e) {
logger.debug(e.getMessage());
}
}

Expand All @@ -296,7 +300,7 @@ private void updateTechCapabilities() {
URLConnection conn = archOpsApiConnection("GET", path, null, null);
try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
techCapabilities.set(Arrays.stream((new Gson()).fromJson(in, TechCapability[].class))
.collect(Collectors.toMap(TechCapability::code, Function.identity())));
.collect(Collectors.toMap(cap -> cap.code().toLowerCase(), Function.identity())));
} catch(IOException e) {
throw e;
}
Expand Down Expand Up @@ -330,7 +334,7 @@ private void updateCapabilities() {
URLConnection conn = archOpsApiConnection("GET", path, null, null);
try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
capabilities.set(Arrays.stream((new Gson()).fromJson(in, Capability[].class))
.collect(Collectors.toMap(Capability::code, Function.identity(), (existingCapability, newCapability) -> existingCapability)));
.collect(Collectors.toMap(c -> c.code().toLowerCase(), Function.identity(), (existingCapability, newCapability) -> existingCapability)));
} catch(IOException e) {
throw e;
}
Expand Down Expand Up @@ -416,6 +420,7 @@ public String loadFrom(String themeLocation, int timeoutInMilliseconds) {
return in.lines().collect(Collectors.joining());
}
} catch (IOException e) {
logger.debug(e.getMessage());
return "";
}
}
Expand Down Expand Up @@ -465,7 +470,7 @@ public List<CompletionItem> technologicalCapabilitiesCompletion() {
CompletionItemLabelDetails details = new CompletionItemLabelDetails();
details.setDetail(" " + e.getValue().name());
item.setKind(CompletionItemKind.Property);
item.setLabel(e.getKey());
item.setLabel(e.getValue().code());
item.setLabelDetails(details);
return item;
}).toList();
Expand All @@ -477,7 +482,7 @@ public List<CompletionItem> businessCapabilitiesCompletion() {
CompletionItemLabelDetails details = new CompletionItemLabelDetails();
details.setDetail(" " + e.getValue().name());
item.setKind(CompletionItemKind.Property);
item.setLabel(e.getKey());
item.setLabel(e.getValue().code());
item.setLabelDetails(details);
return item;
}).toList();
Expand Down Expand Up @@ -562,7 +567,7 @@ public List<CompletionItem> cloudFlavorsCompletion(String vegaProject) {
}

public Hover businessCapabilitiesHover(String code) {
Capability capability = capabilities.get().get(code);
Capability capability = capabilities.get().get(code.toLowerCase());
if (capability != null) {
String name = capability.name();
if (name != null) {
Expand All @@ -579,7 +584,7 @@ public Hover businessCapabilitiesHover(String code) {
}

public Hover technologicalCapabilitiesHover(String code) {
TechCapability capability = techCapabilities.get().get(code);
TechCapability capability = techCapabilities.get().get(code.toLowerCase());
if (capability != null) {
String name = capability.name();
if (name != null) {
Expand Down Expand Up @@ -659,7 +664,7 @@ public List<CompletionItem> dynamicViewCompletion(String destination, C4Document
container.getComponents().stream()
.filter(c -> c.getProperties().getOrDefault("type", "").equalsIgnoreCase("capability"))
.map(c -> c.getProperties().get("code")).filter(Objects::nonNull).forEach(c -> {
TechCapability capability = techCapabilities.get().get(c);
TechCapability capability = techCapabilities.get().get(c.toLowerCase());

CompletionItem item = new CompletionItem();
item.setLabel(c);
Expand Down Expand Up @@ -732,6 +737,27 @@ public Hover getPropertiesHover(List<LineToken> tokens, CursorLocation cursorAt,
return null;
}

public Stream<DecoratorRange> getDecorations(C4DocumentModel docModel) {
return isApiConfigured() ? docModel.getProperties().stream().<DecoratorRange>mapMulti( (p, consumer) -> {
List<LineToken> tokens = LineTokenizer.tokenize(p.line());
int character = tokens.get(1).end();
if(p.name().equalsIgnoreCase("tc")) {
TechCapability tc = techCapabilities.get().get(p.value().toLowerCase());
if(tc == null && cmdb != null) {
tc = techCapabilities.get().get(cmdb.toLowerCase() + "." + p.value().toLowerCase());
}
if(tc!= null) {
consumer.accept(new DecoratorRange("# " + tc.name(),new Range(new Position(p.lineNumber() - 1, character), new Position(p.lineNumber() - 1, character))));
}
} else if(p.name().equalsIgnoreCase("parents")) {
Capability c = capabilities.get().get(p.value().toLowerCase());
if(c!= null) {
consumer.accept(new DecoratorRange("# " + c.name(),new Range(new Position(p.lineNumber() - 1, character), new Position(p.lineNumber() - 1, character))));
}
}
}) : Stream.empty();
}

public List<CompletionItem> comleteProperties(List<LineToken> tokens, CursorLocation cursor, C4DocumentModel docModel, Position position) {
logger.info("completeProperties");
int lineNumberBackward = position.getLine();
Expand Down Expand Up @@ -1039,6 +1065,7 @@ private boolean sendTelemetry(String message) {
outStream.close();
return true;
} catch (Exception e) {
logger.debug(e.getMessage());
return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ public void onException(StructurizrDslParserException e) throws StructurizrDslPa
@Override
public void onParsedProperty(String name, String value) {
if(context != null) {
context.model.addProperty(new C4Property(context.line.number(), name, value));
context.model.addProperty(new C4Property(context.line.number(), context.line.source(), name, value));
} else {
logger.error("onParsedProperty() - Context is null");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ public void setValid(boolean valid) {
}

public List<DecoratorRange> calculateDecorations() {
return decorations;
return Stream.concat(decorations.stream(), Custom.getInstance().getDecorations(this)).toList();
}

public View findViewByKey(String viewKey) throws Exception {
Expand Down Expand Up @@ -251,6 +251,10 @@ public int getRelationshipsCount() {
return relationShipsToLineNumber.size();
}

public List<C4Property> getProperties() {
return properties;
}

public List<Integer> calculateTokens() {
List<C4SemanticToken> sorted = tokens.stream().sorted(Comparator.comparing(C4SemanticToken::lineNumber)).toList();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@

package ru.beeatlas.c4.model;

public record C4Property(int lineNumber, String name, String value) {
public record C4Property(int lineNumber, String line, String name, String value) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.UUID;
import java.util.stream.Collectors;

Expand Down
9 changes: 9 additions & 0 deletions extension/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Change Log

## 1.0.16

- Using stdin/stdout instead of sockets (during iteraction with lang server)
- Using maven shade (with minimizeJar) instead of maven assembly
- Removing picocli dependency
- Up lsp4j to 1.0.0
- Minor TypeScript code cleanup
- Some custom code decoration

## 1.0.15

- Updating JS dependencies
Expand Down
1 change: 1 addition & 0 deletions extension/esbuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ async function main() {
outfile: 'dist/extension.js',
external: ['vscode'],
logLevel: 'warning',
treeShaking: true,
plugins: [
/* add to the end of plugins array */
esbuildProblemMatcherPlugin
Expand Down
5 changes: 3 additions & 2 deletions extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
},
"license": "Apache-2.0",
"icon": "images/logo.png",
"version": "1.0.15",
"version": "1.0.16",
"engines": {
"vscode": "^1.73.0"
},
Expand Down Expand Up @@ -284,6 +284,7 @@
"activationEvents": [
"onLanguage:c4"
],
"browser": "./dist/extension",
"main": "./dist/extension",
"devDependencies": {
"@hpcc-js/wasm-graphviz": "^1.10.0",
Expand All @@ -303,7 +304,7 @@
"scripts": {
"check-types": "tsc --noEmit",
"prepare": "yarn run clean && yarn run build",
"clean": "rimraf lib pack",
"clean": "rimraf --glob \"*.jar\"",
"build": "npm run check-types && node esbuild.js --production",
"build-server": "cd ../c4-server && mvnw package -f ./pom.xml -Djps.track.ap.dependencies=false -DassembleDirectory=../extension/server -DoutputDirectory=../extension/",
"clean-server": "cd ../c4-server && mvnw clean -f ./pom.xml",
Expand Down
Loading