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 #2907

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2020 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 Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2020 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 Down Expand Up @@ -32,60 +32,64 @@
public class PerlHeredocElementManipulator extends AbstractElementManipulator<PerlHeredocElementImpl> {

@Override
public PerlHeredocElementImpl handleContentChange(@NotNull PerlHeredocElementImpl element, @NotNull TextRange range, String newContent)
public PerlHeredocElementImpl handleContentChange(final @NotNull PerlHeredocElementImpl element,
final @NotNull TextRange range,
final String newContent)
throws IncorrectOperationException {
StringBuilder sb = new StringBuilder(newContent);
if (element.getTextLength() == range.getEndOffset() && !StringUtil.endsWith(newContent, "\n")) {
sb.append("\n");
var contentRemoval = newContent.isEmpty();
var replacementContent = newContent;
var effectiveRange = range;
if (range.isEmpty()) {
// this handles empty heredoc update. We have a single empty shred pointing to the offset of closing \n
effectiveRange = TextRange.create(range.getStartOffset(), element.getTextLength() - 1);
}

Project project = element.getProject();
if (range.getStartOffset() > 0) {
sb.insert(0, getIndenter(project, range.getStartOffset()));
range = TextRange.from(0, range.getEndOffset());
var elementText = element.getText();
if (effectiveRange.getStartOffset() > 0) {
var lineStart = getLineStartOffset(elementText, effectiveRange);
if (lineStart < effectiveRange.getStartOffset()) {
if (!contentRemoval) {
var indent = elementText.substring(lineStart, effectiveRange.getStartOffset());
replacementContent = prependLines(replacementContent, indent);
}
effectiveRange = TextRange.create(lineStart, effectiveRange.getEndOffset());
}
}
else if (effectiveRange.getStartOffset() == 0) {
replacementContent = prependLines(newContent, getIndenter(element.getProject(), element.getRealIndentSize()));
}

normalizeIndentation(project, sb, element.getRealIndentSize());

String newElementText = range.replace(element.getText(), sb.toString());
String newElementText = effectiveRange.replace(elementText, replacementContent);
PerlHeredocElementImpl replacement = PerlElementFactory.createHeredocBodyReplacement(element, newElementText);

return (PerlHeredocElementImpl)element.replace(replacement);
}

private static int getLineStartOffset(@NotNull String elementText, @NotNull TextRange effectiveRange) {
var startOffset = effectiveRange.getStartOffset();
if (startOffset == 0) {
return startOffset;
}
if (elementText.charAt(startOffset - 1) == '\n') {
return startOffset;
}
return StringUtil.skipWhitespaceBackward(elementText, startOffset - 1);
}

private static @NotNull String getIndenter(@NotNull Project project, int indentSize) {
CommonCodeStyleSettings.IndentOptions indentOptions =
CodeStyle.getSettings(project).getCommonSettings(PerlLanguage.INSTANCE).getIndentOptions();

return StringUtil.repeat(indentOptions != null && indentOptions.USE_TAB_CHARACTER ? "\t" : " ", indentSize);
}

private static void normalizeIndentation(@NotNull Project project, @NotNull StringBuilder sb, int indentSize) {
int offset = 0;
int currentLineStart = 0;
int currentLineIndentSize = 0;
boolean hasNonSpaces = false;

while (offset < sb.length()) {
char currentChar = sb.charAt(offset++);
if (currentChar == '\n') {
if (hasNonSpaces && currentLineIndentSize < indentSize) {
int indentAdjustment = indentSize - currentLineIndentSize;
sb.insert(currentLineStart, getIndenter(project, indentAdjustment));
offset += indentAdjustment;
}
currentLineStart = offset;
hasNonSpaces = false;
currentLineIndentSize = 0;
}
else if (!hasNonSpaces) {
if (Character.isWhitespace(currentChar)) {
currentLineIndentSize++;
}
else {
hasNonSpaces = true;
}
}
}
private static @NotNull String prependLines(@NotNull String newContent, @NotNull String prefix) {
var result = new StringBuilder();
StringUtil.split(newContent, "\n", false, true)
.forEach(line -> {
result.append(prefix);
result.append(line);
});
return result.toString();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2022 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 Down Expand Up @@ -94,7 +94,8 @@ public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull
private void addPlace(@NotNull PerlHeredocElementImpl heredocElement, @NotNull MultiHostRegistrar registrar) {
int indentSize = heredocElement.getRealIndentSize();
if (indentSize == 0) {
registrar.addPlace(null, null, heredocElement, ElementManipulators.getValueTextRange(heredocElement));
var elementRange = ElementManipulators.getValueTextRange(heredocElement);
registrar.addPlace(null, null, heredocElement, TextRange.create(elementRange.getStartOffset(), elementRange.getEndOffset() - 1));
return;
}

Expand All @@ -107,7 +108,13 @@ private void addPlace(@NotNull PerlHeredocElementImpl heredocElement, @NotNull M
while (sourceOffset < sourceLength) {
char currentChar = sourceText.charAt(sourceOffset);
if (currentChar == '\n') {
registrar.addPlace(null, null, heredocElement, TextRange.from(sourceOffset, 1));
String suffix = null;
int endOffset = sourceOffset + 1;
if (endOffset == sourceLength) {
suffix = "\n";
endOffset--;
}
registrar.addPlace(null, suffix, heredocElement, TextRange.create(sourceOffset, endOffset));
currentLineIndent = 0;
}
else if (Character.isWhitespace(currentChar) && currentLineIndent < indentSize) {
Expand All @@ -124,7 +131,13 @@ else if (Character.isWhitespace(currentChar) && currentLineIndent < indentSize)
}
}

registrar.addPlace(null, null, heredocElement, TextRange.create(sourceOffset, sourceEnd));
String suffix = null;
if (sourceEnd == sourceLength) {
suffix = "\n";
sourceEnd--;
}

registrar.addPlace(null, suffix, heredocElement, TextRange.create(sourceOffset, sourceEnd));
sourceOffset = sourceEnd;
currentLineIndent = 0;
continue;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@
<injectionConfig config="perlInjections.xml"/>
</extensions>
<extensions defaultExtensionNs="com.intellij">
<editor.injectedFileChangesHandlerProvider language="Perl5"
implementationClass="com.perl5.lang.perl.intellilang.PerlInjectedFileChangesHandlerFactory"/>
<multiHostInjector implementation="com.perl5.lang.perl.intellilang.PerlDataLanguageInjector"/>
<multiHostInjector implementation="com.perl5.lang.perl.intellilang.PerlStringLanguageInjector"/>
<multiHostInjector implementation="com.perl5.lang.perl.intellilang.PerlHeredocLanguageInjector"
Expand Down
Loading
Loading