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

Reparse callers of copycodes after save #368

Merged
merged 2 commits into from
Sep 17, 2023
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 libs/natls/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies {
implementation project(':natlint')

testImplementation project(':testhelpers')
testImplementation libraries.slf4j_nop
}

shadowJar {
Expand All @@ -18,6 +19,10 @@ shadowJar {
archiveVersion.set('')
}

configurations.testImplementation {
exclude group: 'org.slf4j', module: libraries.slf4j_utillogging.split(':')[1]
}

jar {
manifest {
attributes(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,15 @@ public void parse()

private boolean hasToReparseCallers(String newSource)
{
var tooManyCallers = incomingReferences.size() > 20;
if (!tooManyCallers && module.file().getFiletype() == NaturalFileType.COPYCODE)
{
return true;
}

var newDefineDataHash = hashDefineData(newSource);
var defineDataChanged = !Arrays.equals(newDefineDataHash, defineDataHash);
defineDataHash = newDefineDataHash;
var tooManyCallers = incomingReferences.size() > 20;
// TODO: Add trace log?

return !tooManyCallers && defineDataChanged;
}
Expand Down
95 changes: 95 additions & 0 deletions libs/natls/src/test/java/org/amshove/natls/CallerReparseTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package org.amshove.natls;

import org.amshove.natls.testlifecycle.LanguageServerTest;
import org.amshove.natls.testlifecycle.LspProjectName;
import org.amshove.natls.testlifecycle.LspTestContext;
import org.amshove.natparse.lexing.LexerError;
import org.amshove.natparse.parsing.ParserError;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;

class CallerReparseTest extends LanguageServerTest
{
private static LspTestContext testContext;

@Override
protected LspTestContext getContext()
{
return testContext;
}

@Test
void savingACopyCodeShouldTriggerReparseOnCaller(@LspProjectName("emptyproject") LspTestContext context)
{
testContext = context;

createOrSaveFile("LIBONE", "MYCC.NSC", """
WRITE ''
""");

var subprog = createOrSaveFile("LIBONE", "MYSUB.NSN", """
DEFINE DATA LOCAL
END-DEFINE
INCLUDE MYCC
END
""");

var subprogramFile = findLanguageServerFile(subprog);

// Diagnostic from copy code is propagated to the subprogram
assertThat(subprogramFile.allDiagnostics())
.as("Expected diagnostic not found")
.anyMatch(d -> d.getCode().getLeft().equals(LexerError.INVALID_STRING_LENGTH.id()));

// Fix the diagnostic in the copy code
createOrSaveFile("LIBONE", "MYCC.NSC", """
WRITE 'Hi'
""");

// Diagnostic from copy code should not be present on subprogram anymore, because it was reparsed
assertThat(subprogramFile.allDiagnostics())
.as("Diagnostic shouldn't be present anymore")
.noneMatch(d -> d.getCode().getLeft().equals(LexerError.INVALID_STRING_LENGTH.id()));
}

@Test
void changingDefineDataShouldTriggerReparsing(@LspProjectName("emptyproject") LspTestContext context)
{
testContext = context;

createOrSaveFile("LIBONE", "MYLDA.NSL", """
DEFINE DATA
LOCAL
END-DEFINE
""");

var subprog = createOrSaveFile("LIBONE", "MYSUB.NSN", """
DEFINE DATA
LOCAL USING MYLDA
END-DEFINE
WRITE #HI
END
""");

var subprogramFile = findLanguageServerFile(subprog);

// Diagnostic from copy code is propagated to the subprogram
assertThat(subprogramFile.allDiagnostics())
.as("Expected diagnostic not found")
.anyMatch(d -> d.getCode().getLeft().equals(ParserError.UNRESOLVED_REFERENCE.id()));

// Adding the variable to the LDA to fix the diagnostic
createOrSaveFile("LIBONE", "MYLDA.NSL", """
DEFINE DATA
LOCAL
1 #HI (A10)
END-DEFINE
""");

// Diagnostic from copy code should not be present on subprogram anymore, because it was reparsed
assertThat(subprogramFile.allDiagnostics())
.as("Diagnostic shouldn't be present anymore")
.noneMatch(d -> d.getCode().getLeft().equals(ParserError.UNRESOLVED_REFERENCE.id()));
}
}