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
5 changes: 5 additions & 0 deletions DeveloperGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@
- Check if java is correctly installed (and your java version) with `java -version` command;
- Place `java-client-{X.X.X}-all.jar` into `..\libs` dir (see [java-client](https://github.com/DeepCodeAI/java-client) repository for instruction how to build it);
- At `build.gradle` file inside `intellij` block: uncomment `version` line and comment `localPath` line (or change `localPath` to pointing your locally installed Intellij Idea `2019.2` version instance);
**Important note: For backward compatibility build MUST be run against Intellij Idea 2019.2 instance!**
- Run `source gradlew buildPlugin`
- Look for resulting ZIP file at `..\build\distributions`

### Run tests

- Run gradle test task: `source gradlew test --stacktrace --scan`

### Useful links
- IntelliJ Platform SDK [documentation](https://www.jetbrains.org/intellij/sdk/docs/intro/welcome.html)
- JetBrains Marketplace [documentation](https://plugins.jetbrains.com/docs/marketplace/about-marketplace.html)
Expand Down
12 changes: 9 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {

//group 'org.example'

version '1.0.1'
version '1.0.2'
sourceCompatibility = 1.8

repositories {
Expand All @@ -27,8 +27,7 @@ intellij {
// localPath '/Users/arvid/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/201.7223.91/IntelliJ IDEA CE.app/Contents'
// localPath 'C:\\Users\\artem\\AppData\\Local\\JetBrains\\Toolbox\\apps\\PyCharm-C\\ch-0\\193.5233.109'
// plugins += 'java'
// plugins += 'PsiViewer:201-SNAPSHOT'
plugins += 'PsiViewer:192-SNAPSHOT'
// plugins += 'PsiViewer:192-SNAPSHOT'

}
patchPluginXml {
Expand Down Expand Up @@ -91,7 +90,14 @@ task run_PC_193(type: RunIdeTask){

task run_AS_40(type: RunIdeTask){
jvmArgs '-Xmx2G'
jbrVersion '8u202b1483.24'
ideDirectory 'C:\\Users\\artem\\AppData\\Local\\JetBrains\\Toolbox\\apps\\AndroidStudio\\ch-0\\193.6453388'
}

task run_AS_36(type: RunIdeTask){
jvmArgs '-Xmx2G'
jbrVersion '8u202b1483.24'
ideDirectory 'C:\\Users\\artem\\AppData\\Local\\JetBrains\\Toolbox\\apps\\AndroidStudio\\ch-1\\192.6392135'
}

tasks.withType(RunIdeTask).forEach {task -> task.dependsOn(prepareSandbox)}
10 changes: 4 additions & 6 deletions src/main/java/ai/deepcode/jbplugin/DeepCodeNotifications.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public static void showLoginLink(@Nullable Project project, @NotNull String mess
new Notification(groupNeedAction, title, message, NotificationType.WARNING)
.addAction(
new ShowClickableLinkAction(
"Login", () -> LoginUtils.requestNewLogin(prj), true));
"Login", () -> LoginUtils.requestNewLogin(prj, true), true));
lastNotifications.add(notification);
notification.notify(prj);
}
Expand All @@ -58,10 +58,8 @@ public static void showLoginLink(@Nullable Project project, @NotNull String mess
public static void showConsentRequest(@NotNull Project project, boolean userActionNeeded) {
if (!userActionNeeded && consentRequestShown) return;
lastNotificationRunnable = () -> showConsentRequest(project, userActionNeeded);
final String message =
"Confirm remote analysis of "
+ project.getBasePath();
// + " (<a href=\"https://www.deepcode.ai/tc\">Terms & Conditions</a>)";
final String message = "Confirm remote analysis of " + project.getBasePath();
// + " (<a href=\"https://www.deepcode.ai/tc\">Terms & Conditions</a>)";
final Notification notification =
new ConsentNotification(
groupNeedAction,
Expand Down Expand Up @@ -109,7 +107,7 @@ public void actionPerformed(@NotNull AnActionEvent e) {
}
}

private static void expireNotification(@NotNull Notification notification){
private static void expireNotification(@NotNull Notification notification) {
if (notification instanceof ConsentNotification) {
((ConsentNotification) notification).consentExpired();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,24 @@
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;

public class SeeResultsInBrowserAction extends AnAction {

@Override
public void update(@NotNull AnActionEvent e) {
e.getPresentation().setEnabled(!AnalysisData.getAnalysisUrl().isEmpty());
final Project project = e.getProject();
if (project==null) return;
final boolean urlExist = !AnalysisData.getAnalysisUrl(project).isEmpty();
e.getPresentation().setEnabled(urlExist);
}

@Override
public void actionPerformed(@NotNull AnActionEvent e) {
final String analysisUrl = AnalysisData.getAnalysisUrl();
final Project project = e.getProject();
if (project==null) return;
final String analysisUrl = AnalysisData.getAnalysisUrl(project);
if (!analysisUrl.isEmpty()) BrowserUtil.open(analysisUrl);
}
}
56 changes: 40 additions & 16 deletions src/main/java/ai/deepcode/jbplugin/core/AnalysisData.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ private AnalysisData() {}

private static final Logger LOG = LoggerFactory.getLogger("DeepCode.AnalysisData");
private static final Map<PsiFile, List<SuggestionForFile>> EMPTY_MAP = Collections.emptyMap();
private static String analysisUrl = "";
private static Map<Project, String> mapProject2analysisUrl = new ConcurrentHashMap<>();

// todo: keep few latest file versions (Guava com.google.common.cache.CacheBuilder ?)
private static final Map<PsiFile, List<SuggestionForFile>> mapFile2Suggestions =
Expand Down Expand Up @@ -94,8 +94,8 @@ public static Map<PsiFile, List<SuggestionForFile>> getAnalysis(
return result;
}

public static String getAnalysisUrl() {
return analysisUrl;
public static String getAnalysisUrl(@NotNull Project project) {
return mapProject2analysisUrl.computeIfAbsent(project, p -> "");
}

static boolean addProjectToCache(@NotNull Project project) {
Expand Down Expand Up @@ -184,11 +184,17 @@ public static void updateCachedResultsForFiles(
.filter(file -> !mapFile2Suggestions.containsKey(file))
.collect(Collectors.toSet());
if (!filesToProceed.isEmpty()) {
info("Files to proceed (not found in cache): " + filesToProceed.size());
// fixme debug only
// deepcode ignore checkIsPresent~Optional: collection already checked to be not empty
final PsiFile firstFile = filesToProceed.stream().findFirst().get();
info("Hash for first file " + firstFile.getName() + " [" + getHash(firstFile) + "]");
info(
"Files to proceed (not found in cache): "
+ filesToProceed.size()
// fixme debug only
+ "\nHash for first file "
+ firstFile.getName()
+ " ["
+ getHash(firstFile)
+ "]");

mapFile2Suggestions.putAll(retrieveSuggestions(project, filesToProceed, filesToRemove));

Expand Down Expand Up @@ -251,10 +257,6 @@ private static Map<PsiFile, List<SuggestionForFile>> retrieveSuggestions(
info(PREPARE_FILES_TEXT);
ProgressManager.checkCanceled();
mapPsiFile2Content.clear();
List<String> removedFiles =
filesToRemove.stream()
.map(DeepCodeUtils::getDeepCodedFilePath)
.collect(Collectors.toList());
Map<String, String> mapPath2Hash = new HashMap<>();
long sizePath2Hash = 0;
int fileCounter = 0;
Expand All @@ -280,7 +282,7 @@ private static Map<PsiFile, List<SuggestionForFile>> retrieveSuggestions(
}
}
// todo break removeFiles in chunks less then MAX_BANDLE_SIZE
CreateBundleResponse createBundleResponse = makeNewBundle(project, mapPath2Hash, removedFiles);
CreateBundleResponse createBundleResponse = makeNewBundle(project, mapPath2Hash, filesToRemove);
if (isNotSucceed(project, createBundleResponse, "Bad Create/Extend Bundle request: "))
return EMPTY_MAP;
info(
Expand Down Expand Up @@ -353,7 +355,7 @@ private static Map<PsiFile, List<SuggestionForFile>> retrieveSuggestions(
progress.setText(WAITING_FOR_ANALYSIS_TEXT);
ProgressManager.checkCanceled();
GetAnalysisResponse getAnalysisResponse = doRetrieveSuggestions(project, bundleId, progress);
result = parseGetAnalysisResponse(psiFiles, getAnalysisResponse, progress);
result = parseGetAnalysisResponse(project, psiFiles, getAnalysisResponse, progress);
info("--- Get Analysis took: " + (System.currentTimeMillis() - startTime) + " milliseconds");
// progress.stop();
return result;
Expand All @@ -362,9 +364,21 @@ private static Map<PsiFile, List<SuggestionForFile>> retrieveSuggestions(
private static CreateBundleResponse makeNewBundle(
@NotNull Project project,
@NotNull Map<String, String> mapPath2Hash,
@NotNull List<String> removedFiles) {
@NotNull Collection<PsiFile> filesToRemove) {
final FileHashRequest fileHashRequest = new FileHashRequest(mapPath2Hash);
final String parentBundleId = mapProject2BundleId.getOrDefault(project, "");
if (!parentBundleId.isEmpty()
&& !filesToRemove.isEmpty()
&& mapPath2Hash.isEmpty()
&& filesToRemove.containsAll(cachedFilesOfProject(project))) {
warn(
"Attempt to Extending a bundle by removing all the parent bundle's files: "
+ filesToRemove);
}
List<String> removedFiles =
filesToRemove.stream()
.map(DeepCodeUtils::getDeepCodedFilePath)
.collect(Collectors.toList());
String message =
(parentBundleId.isEmpty()
? "Creating new Bundle with "
Expand All @@ -385,10 +399,19 @@ private static CreateBundleResponse makeNewBundle(
parentBundleId,
new ExtendBundleRequest(fileHashRequest.getFiles(), removedFiles));
}
mapProject2BundleId.put(project, bundleResponse.getBundleId());
String newBundleId = bundleResponse.getBundleId();
// By man: "Extending a bundle by removing all the parent bundle's files is not allowed."
// In reality new bundle returned with next bundleID:
// gh/ArtsiomCh/DEEPCODE_PRIVATE_BUNDLE/0000000000000000000000000000000000000000000000000000000000000000
if (newBundleId.equals(
"gh/ArtsiomCh/DEEPCODE_PRIVATE_BUNDLE/0000000000000000000000000000000000000000000000000000000000000000")) {
newBundleId = "";
}
mapProject2BundleId.put(project, newBundleId);
return bundleResponse;
}

// ?? com.intellij.openapi.util.text.StringUtil.toHexString
// https://www.baeldung.com/sha-256-hashing-java#message-digest
private static String bytesToHex(byte[] hash) {
StringBuilder hexString = new StringBuilder();
Expand Down Expand Up @@ -512,13 +535,14 @@ private static GetAnalysisResponse doRetrieveSuggestions(

@NotNull
private static Map<PsiFile, List<SuggestionForFile>> parseGetAnalysisResponse(
@NotNull Project project,
@NotNull Collection<PsiFile> psiFiles,
GetAnalysisResponse response,
@NotNull ProgressIndicator progressIndicator) {
Map<PsiFile, List<SuggestionForFile>> result = new HashMap<>();
if (!response.getStatus().equals("DONE")) return EMPTY_MAP;
AnalysisResults analysisResults = response.getAnalysisResults();
analysisUrl = response.getAnalysisURL();
mapProject2analysisUrl.put(project, response.getAnalysisURL());
if (analysisResults == null) {
LOG.error("AnalysisResults is null for: {}", response);
return EMPTY_MAP;
Expand Down Expand Up @@ -603,7 +627,7 @@ public static void clearCache(@Nullable final Project project) {
for (Project prj : projects) {
removeProjectFromCache(prj);
ServiceManager.getService(prj, myTodoView.class).refresh();
mapProject2analysisUrl.put(prj, "");
}
analysisUrl = "";
}
}
10 changes: 6 additions & 4 deletions src/main/java/ai/deepcode/jbplugin/core/LoginUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class LoginUtils {
private LoginUtils() {}

private static final String userAgent =
"JetBrains-plugin-"
"JetBrains-"
+ ApplicationNamesInfo.getInstance().getProductName()
+ "-"
+ ApplicationInfo.getInstance().getFullVersion();
Expand Down Expand Up @@ -54,15 +54,17 @@ public static boolean isLogged(@Nullable Project project, boolean userActionNeed
}

/** network request! */
public static void requestNewLogin(@NotNull Project project) {
public static void requestNewLogin(@NotNull Project project, boolean openBrowser) {
DCLogger.info("New Login requested.");
DeepCodeParams.clearLoginParams();
LoginResponse response = DeepCodeRestApi.newLogin(userAgent);
if (response.getStatusCode() == 200) {
DCLogger.info("New Login request succeed. New Token: " + response.getSessionToken());
DCLogger.info("New Login request succeed. New Token: " + response.getSessionToken());
DeepCodeParams.setSessionToken(response.getSessionToken());
DeepCodeParams.setLoginUrl(response.getLoginURL());
BrowserUtil.open(DeepCodeParams.getLoginUrl());
if (openBrowser) {
BrowserUtil.open(DeepCodeParams.getLoginUrl());
}
if (!isLoginCheckLoopStarted) {
ReadAction.nonBlocking(() -> startLoginCheckLoop(project))
.submit(NonUrgentExecutor.getInstance());
Expand Down
19 changes: 12 additions & 7 deletions src/main/java/ai/deepcode/jbplugin/core/MyBulkFileListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class MyBulkFileListener implements BulkFileListener {
@Override
public void after(@NotNull List<? extends VFileEvent> events) {
// fixme debug only
DCLogger.info("MyBulkFileListener.after begins");
DCLogger.info("MyBulkFileListener.after begins for: " + events);
for (Project project : AnalysisData.getAllCachedProject()) {
RunUtils.runInBackground(
project,
Expand All @@ -48,11 +48,16 @@ public void after(@NotNull List<? extends VFileEvent> events) {
// fixme doen't work for copy-past file ( VFileMoveEvent ?)
VFileCreateEvent.class));
if (!filesChangedOrCreated.isEmpty()) {
// fixme debug only
DCLogger.info(
filesChangedOrCreated.size() + " files changed: " + filesChangedOrCreated);
AnalysisData.removeFilesFromCache(filesChangedOrCreated);
RunUtils.asyncAnalyseAndUpdatePanel(project, filesChangedOrCreated);
for (PsiFile psiFile : filesChangedOrCreated) {
RunUtils.runInBackgroundCancellable(
psiFile,
() -> {
AnalysisData.removeFilesFromCache(Collections.singleton(psiFile));
RunUtils.asyncAnalyseAndUpdatePanel(project, Collections.singleton(psiFile));
});
}
}
});

Expand All @@ -74,12 +79,12 @@ public void after(@NotNull List<? extends VFileEvent> events) {
}
}
// fixme debug only
DCLogger.info("MyBulkFileListener.after ends");
DCLogger.info("MyBulkFileListener.after ends for: " + events);
}

@Override
public void before(@NotNull List<? extends VFileEvent> events) {
DCLogger.info("MyBulkFileListener.before begins");
DCLogger.info("MyBulkFileListener.before begins for: " + events);
for (Project project : AnalysisData.getAllCachedProject()) {
if (project.isDisposed()) continue;
Set<PsiFile> filesRemoved =
Expand Down Expand Up @@ -107,7 +112,7 @@ public void before(@NotNull List<? extends VFileEvent> events) {
});
}
}
DCLogger.info("MyBulkFileListener.before ends");
DCLogger.info("MyBulkFileListener.before ends for: " + events);
}

private Set<PsiFile> getFilteredFilesByEventTypes(
Expand Down
1 change: 1 addition & 0 deletions src/test/.dcignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
testData
28 changes: 28 additions & 0 deletions src/test/java/ai/deepcode/jbplugin/MyBasePlatformTestCase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package ai.deepcode.jbplugin;

import ai.deepcode.jbplugin.core.DeepCodeParams;
import com.intellij.openapi.project.Project;
import com.intellij.testFramework.fixtures.BasePlatformTestCase;

/**
* See: https://www.jetbrains.org/intellij/sdk/docs/basics/testing_plugins/testing_plugins.html See:
* https://www.jetbrains.org/intellij/sdk/docs/tutorials/writing_tests_for_plugins.html
*/
public abstract class MyBasePlatformTestCase extends BasePlatformTestCase {
protected Project project;

@Override
protected void setUp() throws Exception {
super.setUp();
project = myFixture.getProject();
}

// !!! Will works only with already logged sessionToken
protected static final String loggedToken =
"aeedc7d1c2656ea4b0adb1e215999f588b457cedf415c832a0209c9429c7636e";

@Override
protected String getTestDataPath() {
return "src/test/testData";
}
}
15 changes: 15 additions & 0 deletions src/test/java/ai/deepcode/jbplugin/MyPlatformTestCase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package ai.deepcode.jbplugin;

import com.intellij.testFramework.PlatformTestCase;

/**
* See: https://www.jetbrains.org/intellij/sdk/docs/basics/testing_plugins/testing_plugins.html See:
* https://www.jetbrains.org/intellij/sdk/docs/tutorials/writing_tests_for_plugins.html
*/
public abstract class MyPlatformTestCase extends PlatformTestCase {

// !!! Will works only with already logged sessionToken
protected static final String loggedToken =
"aeedc7d1c2656ea4b0adb1e215999f588b457cedf415c832a0209c9429c7636e";

}
17 changes: 17 additions & 0 deletions src/test/java/ai/deepcode/jbplugin/TestAnnotatorForCPP.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package ai.deepcode.jbplugin;

import ai.deepcode.jbplugin.core.DeepCodeParams;
import ai.deepcode.jbplugin.core.RunUtils;

public class TestAnnotatorForCPP extends MyBasePlatformTestCase {

public void testHighlighting_CPP() {
DeepCodeParams.setSessionToken(loggedToken);
DeepCodeParams.setConsentGiven(project);
myFixture.configureByFile("AnnotatorTest.cpp");
//fixme: delay to let annotators do the job
RunUtils.delay(2000);
myFixture.checkHighlighting(true, true, true, false);
}

}
Loading