• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

devonfw / IDEasy / 13772844222

10 Mar 2025 07:10PM UTC coverage: 68.619% (+0.1%) from 68.471%
13772844222

push

github

web-flow
#654: improved plugin suppport (#1085)

Co-authored-by: Jörg Hohwiller <hohwille@users.noreply.github.com>

3067 of 4915 branches covered (62.4%)

Branch coverage included in aggregate %.

7934 of 11117 relevant lines covered (71.37%)

3.11 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.46
cli/src/main/java/com/devonfw/tools/ide/tool/vscode/Vscode.java
1
package com.devonfw.tools.ide.tool.vscode;
2

3
import java.io.BufferedReader;
4
import java.io.IOException;
5
import java.nio.file.Files;
6
import java.nio.file.Path;
7
import java.util.ArrayList;
8
import java.util.Collection;
9
import java.util.HashMap;
10
import java.util.HashSet;
11
import java.util.List;
12
import java.util.Map;
13
import java.util.Set;
14

15
import com.devonfw.tools.ide.common.Tag;
16
import com.devonfw.tools.ide.context.IdeContext;
17
import com.devonfw.tools.ide.process.ProcessContext;
18
import com.devonfw.tools.ide.process.ProcessErrorHandling;
19
import com.devonfw.tools.ide.process.ProcessMode;
20
import com.devonfw.tools.ide.process.ProcessResult;
21
import com.devonfw.tools.ide.step.Step;
22
import com.devonfw.tools.ide.tool.ToolCommandlet;
23
import com.devonfw.tools.ide.tool.ide.IdeToolCommandlet;
24
import com.devonfw.tools.ide.tool.plugin.ToolPluginDescriptor;
25
import com.fasterxml.jackson.databind.ObjectMapper;
26

27
/**
28
 * {@link ToolCommandlet} for <a href="https://code.visualstudio.com/">vscode</a>.
29
 */
30
public class Vscode extends IdeToolCommandlet {
31

32
  /**
33
   * The constructor.
34
   *
35
   * @param context the {@link IdeContext}.
36
   */
37
  public Vscode(IdeContext context) {
38

39
    super(context, "vscode", Set.of(Tag.VS_CODE));
6✔
40
  }
1✔
41

42
  @Override
43
  protected String getBinaryName() {
44

45
    return "code";
2✔
46
  }
47

48
  @Override
49
  public boolean installPlugin(ToolPluginDescriptor plugin, Step step, ProcessContext pc) {
50

51
    List<String> extensionsCommands = new ArrayList<>();
4✔
52
    extensionsCommands.add("--force");
4✔
53
    extensionsCommands.add("--install-extension");
4✔
54
    extensionsCommands.add(plugin.id());
5✔
55
    ProcessResult result = runTool(ProcessMode.DEFAULT, ProcessErrorHandling.THROW_ERR, pc, extensionsCommands.toArray(String[]::new));
13✔
56
    if (result.isSuccessful()) {
3!
57
      this.context.success("Successfully installed plugin: {}", plugin.name());
11✔
58
      step.success();
2✔
59
      return true;
2✔
60
    } else {
61
      this.context.warning("An error occurred while installing plugin: {}", plugin.name());
×
62
      return false;
×
63
    }
64
  }
65

66
  @Override
67
  protected void installPlugins(Collection<ToolPluginDescriptor> plugins, ProcessContext pc) {
68

69
    List<ToolPluginDescriptor> pluginsToInstall = new ArrayList<>();
4✔
70
    List<ToolPluginDescriptor> pluginsToRecommend = new ArrayList<>();
4✔
71

72
    Step step = this.context.newStep(true, "Install plugins for " + this.tool);
10✔
73
    try {
74
      for (ToolPluginDescriptor plugin : plugins) {
10✔
75
        if (plugin.active()) {
3✔
76
          pluginsToInstall.add(plugin);
5✔
77
        } else {
78
          pluginsToRecommend.add(plugin);
4✔
79
        }
80
      }
1✔
81
      if (pluginsToInstall.isEmpty()) {
3!
82
        this.context.info("No plugins to be installed");
×
83
      } else {
84
        for (ToolPluginDescriptor plugin : pluginsToInstall) {
10✔
85
          boolean result = installPlugin(plugin, step, pc);
6✔
86
          if (result) {
2!
87
            createPluginMarkerFile(plugin);
3✔
88
          }
89
        }
1✔
90
      }
91
      doAddRecommendations(pluginsToRecommend);
3✔
92
    } catch (RuntimeException e) {
×
93
      step.error(e, true);
×
94
      throw e;
×
95
    } finally {
96
      step.close();
2✔
97
    }
98

99
  }
1✔
100

101
  private void doAddRecommendations(List<ToolPluginDescriptor> recommendations) {
102
    Path extensionsJsonPath = this.context.getWorkspacePath().resolve(".vscode/extensions.json");
6✔
103

104
    ObjectMapper objectMapper = new ObjectMapper();
4✔
105
    Map<String, Object> recommendationsMap;
106

107
    if (Files.exists(extensionsJsonPath)) {
5!
108
      try (BufferedReader reader = Files.newBufferedReader(extensionsJsonPath)) {
3✔
109
        recommendationsMap = objectMapper.readValue(reader, Map.class);
6✔
110
      } catch (IOException e) {
×
111
        throw new RuntimeException(e);
×
112
      }
1✔
113
    } else {
114
      recommendationsMap = new HashMap<>();
×
115
    }
116

117
    List<String> existingRecommendations = (List<String>) recommendationsMap.getOrDefault("recommendations", new ArrayList<>());
8✔
118

119
    try {
120
      int addedRecommendations = 0;
2✔
121
      Set<String> existingRecommendationsSet = new HashSet<>(existingRecommendations);
5✔
122
      for (ToolPluginDescriptor recommendation : recommendations) {
10✔
123
        String recommendationId = recommendation.id();
3✔
124
        if (existingRecommendationsSet.add(recommendationId)) {
4!
125
          existingRecommendations.add(recommendationId);
4✔
126
          addedRecommendations++;
1✔
127
        }
128
      }
1✔
129

130
      if (addedRecommendations > 0) {
2!
131
        objectMapper.writeValue(extensionsJsonPath.toFile(), recommendationsMap);
5✔
132
      }
133

134
    } catch (IOException e) {
×
135
      this.context.error(e);
×
136
    }
1✔
137
  }
1✔
138

139
  @Override
140
  protected void configureToolArgs(ProcessContext pc, ProcessMode processMode, ProcessErrorHandling errorHandling, String... args) {
141

142
    Path vsCodeConf = this.context.getWorkspacePath().resolve(".vscode/.userdata");
6✔
143
    pc.addArg("--new-window");
4✔
144
    pc.addArg("--user-data-dir=" + vsCodeConf);
6✔
145
    Path vsCodeExtensionFolder = this.context.getIdeHome().resolve("plugins/vscode");
6✔
146
    pc.addArg("--extensions-dir=" + vsCodeExtensionFolder);
6✔
147
    pc.addArg(this.context.getWorkspacePath());
6✔
148
    super.configureToolArgs(pc, processMode, errorHandling, args);
6✔
149
  }
1✔
150

151
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc