Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hurricup/bugfixes #2891

Merged
merged 2 commits into from
Sep 1, 2024
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2023 Alexandr Evstigneev
* Copyright 2015-2024 Alexandr Evstigneev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,6 +19,7 @@
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
Expand Down Expand Up @@ -236,6 +237,24 @@ public static String getCanonicalNamespaceName(@NotNull String name) {
return packageName == null ? Collections.emptyList() : StringUtil.split(getCanonicalNamespaceName(packageName), NAMESPACE_SEPARATOR);
}

@Contract("null -> null")
public static @Nullable @NlsSafe Pair<@Nullable String, @Nullable String> splitNames(@Nullable @NlsSafe String fqn) {
if (fqn == null || fqn.isEmpty()) {
return null;
}
if (fqn.endsWith(NAMESPACE_SEPARATOR)) {
return Pair.create(getCanonicalName(fqn), null);
}
var sepIndex = fqn.lastIndexOf(NAMESPACE_SEPARATOR);
if (sepIndex < 0) {
return Pair.create(null, fqn);
}
if (sepIndex == 0) {
return Pair.create(MAIN_NAMESPACE_NAME, fqn.substring(NAMESPACE_SEPARATOR.length()));
}
return Pair.create(fqn.substring(0, sepIndex), fqn.substring(sepIndex + NAMESPACE_SEPARATOR.length()));
}

/**
* Searching of namespace element is in. If no explicit namespaces defined, main is returned
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -674,3 +674,4 @@ tooltip.comma.separated.list.modules.required.to.run.configuration=Comma-separat
dialog.message.are.missing.in.would.you.like.to.install=Modules missing: {0}.\nWould you like to install?
dialog.title.missing.modules=Missing Modules
mark.as.action.group=Mark as:
dialog.message.something.bad.happened.on.perl.side.report.to.plugin.devs=Something bad happened on Perl side. Report to plugin devs.
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,17 @@
import com.intellij.xdebugger.frame.XStackFrame;
import com.intellij.xdebugger.frame.XValueChildrenList;
import com.intellij.xdebugger.impl.XSourcePositionImpl;
import com.perl5.PerlBundle;
import com.perl5.PerlIcons;
import com.perl5.lang.perl.debugger.protocol.*;
import com.perl5.lang.perl.debugger.values.PerlXMainGroup;
import com.perl5.lang.perl.debugger.values.PerlXNamedValue;
import com.perl5.lang.perl.debugger.values.PerlXValueGroup;
import com.perl5.lang.perl.util.PerlPackageUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.annotations.VisibleForTesting;

import java.io.File;

Expand Down Expand Up @@ -84,9 +87,27 @@ public PerlStackFrame(@NotNull PerlStackFrameDescriptor frameDescriptor, @NotNul

@Override
public void customizePresentation(@NotNull ColoredTextContainer component) {
doCustomizePresentation(myFrameDescriptor, component);
}

@VisibleForTesting
public static void doCustomizePresentation(@NotNull PerlStackFrameDescriptor frameDescriptor, @NotNull ColoredTextContainer component) {
var fileDescriptor = frameDescriptor.getFileDescriptor();
var fqn = fileDescriptor.getName();
var nameChunks = PerlPackageUtil.splitNames(fqn);
var filePath = fileDescriptor.getPath();
@NlsSafe var namespaceName = nameChunks == null ? null : nameChunks.getFirst();
var subName = nameChunks == null ? null : nameChunks.getSecond();
var firstName = subName == null ? filePath : subName;
@NlsSafe var frameName =
String.join(":", myFrameDescriptor.getFileDescriptor().getNameOrPath(), String.valueOf(myFrameDescriptor.getOneBasedLine()));
String.join(":", firstName, String.valueOf(frameDescriptor.getOneBasedLine()));
component.append(frameName, SimpleTextAttributes.REGULAR_ATTRIBUTES);
if (namespaceName != null) {
component.append(", " + namespaceName, SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
if (subName != null) {
component.append(" (" + filePath + ")", SimpleTextAttributes.GRAYED_ATTRIBUTES);
}
component.setIcon(AllIcons.Debugger.Frame);
}

Expand Down Expand Up @@ -136,12 +157,12 @@ public void computeChildren(@NotNull XCompositeNode node) {
}
}

public PerlExecutionStack getPerlExecutionStack() {
public @NotNull PerlExecutionStack getPerlExecutionStack() {
return myPerlExecutionStack;
}

@TestOnly
public PerlStackFrameDescriptor getFrameDescriptor() {
public @NotNull PerlStackFrameDescriptor getFrameDescriptor() {
return myFrameDescriptor;
}

Expand All @@ -162,7 +183,7 @@ public void run(JsonObject jsonObject, JsonDeserializationContext jsonDeserializ
);

if (descriptor == null) {
callback.errorOccurred("Something bad happened on Perl side. Report to plugin devs.");
callback.errorOccurred(PerlBundle.message("dialog.message.something.bad.happened.on.perl.side.report.to.plugin.devs"));
}
else if (descriptor.isError()) {
callback.errorOccurred(descriptor.getResult().getValue());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2023 Alexandr Evstigneev
* Copyright 2015-2024 Alexandr Evstigneev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,22 +19,28 @@
import com.intellij.openapi.util.NlsSafe;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.VisibleForTesting;


public class PerlLoadedFileDescriptor {
@SuppressWarnings("unused") private @NlsSafe String path;
@SuppressWarnings("unused") private @NlsSafe String name;
@SuppressWarnings({"unused", "NotNullFieldNotInitialized"}) private @NlsSafe @NotNull String path;
@SuppressWarnings("unused") private @NlsSafe @Nullable String name;

public @NotNull String getPath() {
return path;
public PerlLoadedFileDescriptor() {

Check warning

Code scanning / QDJVM

Unused declaration Warning

Constructor is never used.
}

public @Nullable String getName() {
return name;
@VisibleForTesting
public PerlLoadedFileDescriptor(@NotNull String path, @Nullable String name) {
this.path = path;
this.name = name;
}

public @NotNull @NlsSafe String getPath() {
return path;
}

public @NotNull @NlsSafe String getNameOrPath() {
return name == null ? path : name;
public @Nullable @NlsSafe String getName() {
return name;
}

public @NotNull String getPresentableName() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2023 Alexandr Evstigneev
* Copyright 2015-2024 Alexandr Evstigneev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -17,18 +17,30 @@
package com.perl5.lang.perl.debugger.protocol;


import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.VisibleForTesting;

import java.util.Arrays;

public class PerlStackFrameDescriptor {
public static final transient String EVAL_PREFIX = "(eval ";

@SuppressWarnings("unused") PerlLoadedFileDescriptor file;
@SuppressWarnings({"unused", "NotNullFieldNotInitialized"}) @NotNull PerlLoadedFileDescriptor file;
@SuppressWarnings("unused") private int line;
@SuppressWarnings("unused") private int main_size;
@SuppressWarnings("unused") private PerlValueDescriptor[] lexicals;
@SuppressWarnings("unused") private PerlValueDescriptor[] globals;
@SuppressWarnings("unused") private PerlValueDescriptor[] args;

public PerlStackFrameDescriptor() {

Check warning

Code scanning / QDJVM

Unused declaration Warning

Constructor is never used.
}

@VisibleForTesting
public PerlStackFrameDescriptor(@NotNull PerlLoadedFileDescriptor file, int line) {
this.file = file;
this.line = line;
}

public PerlLoadedFileDescriptor getFileDescriptor() {
return file;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2023 Alexandr Evstigneev
* Copyright 2015-2024 Alexandr Evstigneev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,7 @@

package com.perl5.lang.perl.debugger.protocol;

import com.intellij.openapi.util.NlsSafe;
import org.jetbrains.annotations.Nullable;


Expand Down Expand Up @@ -47,7 +48,7 @@ public String getType() {
return type;
}

public String getValue() {
public @NlsSafe String getValue() {
return value;
}

Expand Down
70 changes: 70 additions & 0 deletions plugin/src/test/java/unit/perl/PerlPackageUtilTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright 2015-2024 Alexandr Evstigneev
*
* Licensed 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 unit.perl;

import base.PerlLightTestCase;
import com.intellij.testFramework.Parameterized;
import com.perl5.lang.perl.util.PerlPackageUtil;
import org.jetbrains.annotations.Nullable;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.Arrays;
import java.util.Collections;

@SuppressWarnings("Junit4RunWithInspection")
@RunWith(Parameterized.class)
public class PerlPackageUtilTest extends PerlLightTestCase {
private final @Nullable String myFqn;
private final @Nullable String myPackageName;
private final @Nullable String mySubName;

public PerlPackageUtilTest(@Nullable String fqn, @Nullable String packageName, @Nullable String subName) {
myFqn = fqn;
myPackageName = packageName;
mySubName = subName;
}

@Test
public void test() {
var result = PerlPackageUtil.splitNames(myFqn);
if (myFqn == null || myFqn.isEmpty()) {
assertNull(result);
}
else {
assertNotNull(result);
assertEquals(myPackageName, result.getFirst());
assertEquals(mySubName, result.getSecond());
}
}

@org.junit.runners.Parameterized.Parameters(name = "{0}")
public static Iterable<Object[]> fakeData() {
return Collections.emptyList();
}

@Parameterized.Parameters(name = "{0}")
public static Iterable<Object[]> realData(Class<?> clazz) {
return Arrays.asList(new Object[][]{
{null, null, null},
{"", null, null},
{"::subname", "main", "subname"},
{"Foo::", "Foo", null},
{"Foo::subname", "Foo", "subname"},
});
}
}
90 changes: 90 additions & 0 deletions plugin/src/test/java/unit/perl/PerlStackFrameRenderingTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright 2015-2024 Alexandr Evstigneev
*
* Licensed 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 unit.perl;

import base.PerlLightTestCase;
import com.intellij.testFramework.Parameterized;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.ui.SimpleTextAttributes;
import com.perl5.lang.perl.debugger.PerlStackFrame;
import com.perl5.lang.perl.debugger.protocol.PerlLoadedFileDescriptor;
import com.perl5.lang.perl.debugger.protocol.PerlStackFrameDescriptor;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.Arrays;
import java.util.Collections;

@SuppressWarnings("Junit4RunWithInspection")
@RunWith(Parameterized.class)
public class PerlStackFrameRenderingTest extends PerlLightTestCase {
private final @NotNull String myName;
private final @NotNull PerlStackFrameDescriptor myFrameDescriptor;

public PerlStackFrameRenderingTest(@NotNull String name, @NotNull PerlStackFrameDescriptor frameDescriptor) {
myName = name;
myFrameDescriptor = frameDescriptor;
}

@Override
protected String getBaseDataPath() {
return "unit/perl/stackframerendering";
}

@Test
public void test() {
var result = new StringBuilder();
PerlStackFrame.doCustomizePresentation(myFrameDescriptor, (fragment, attributes) -> {

Check warning

Code scanning / QDJVM

Statement lambda can be replaced with expression lambda Warning test

Statement lambda can be replaced with expression lambda
result.append(protectSpaces(fragment)).append(" - ").append(serialize(attributes)).append("\n");
});
UsefulTestCase.assertSameLinesWithFile(getTestResultsFilePath(), result.toString());
}

protected static @NotNull String serialize(@NotNull SimpleTextAttributes attributes) {
if (attributes == SimpleTextAttributes.REGULAR_ATTRIBUTES) {
return "REGULAR_ATTRIBUTES";
}
else if (attributes == SimpleTextAttributes.GRAYED_ATTRIBUTES) {
return "GRAYED_ATTRIBUTES";
}
return attributes.toString();
}

@Override
protected @NotNull String computeAnswerFileNameWithoutExtension(@NotNull String appendix) {
return myName.replaceAll("\\W+", "_").toLowerCase() + appendix;
}

@org.junit.runners.Parameterized.Parameters(name = "{0}")
public static Iterable<Object[]> fakeData() {
return Collections.emptyList();
}

@Parameterized.Parameters(name = "{0}")
public static Iterable<Object[]> realData(Class<?> clazz) {
return Arrays.asList(new Object[][]{
{"File, fqn and line", new PerlStackFrameDescriptor(new PerlLoadedFileDescriptor("/path/to/file", "Proper::Fqn"), 42)},
{"File, main fqn and line", new PerlStackFrameDescriptor(new PerlLoadedFileDescriptor("/path/to/file", "::Fqn"), 42)},
{"fqn and line", new PerlStackFrameDescriptor(new PerlLoadedFileDescriptor("", "Proper::Fqn"), 42)},
{"File and line", new PerlStackFrameDescriptor(new PerlLoadedFileDescriptor("/path/to/file", null), 42)},
{"Eval file, fqn and line",
new PerlStackFrameDescriptor(new PerlLoadedFileDescriptor("(eval 26)[eval/path/to/file:7]", "Proper::Fqn"), 42)},
{"Eval file and line", new PerlStackFrameDescriptor(new PerlLoadedFileDescriptor("(eval 26)[eval/path/to/file:7]", null), 42)},
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(eval␣26)[eval/path/to/file:7]:43 - REGULAR_ATTRIBUTES
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fqn:43 - REGULAR_ATTRIBUTES
,␣Proper - REGULAR_ATTRIBUTES
␣((eval␣26)[eval/path/to/file:7]) - GRAYED_ATTRIBUTES
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/path/to/file:43 - REGULAR_ATTRIBUTES
Loading
Loading