Skip to content

Commit

Permalink
Merge pull request #42234 from dulajdilshan/fix/class-def-symbol-by-node
Browse files Browse the repository at this point in the history
Fix throwing an exception if compilation-unit is not found
  • Loading branch information
dulajdilshan authored Mar 21, 2024
2 parents ad6109c + bf0f980 commit a842c79
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,11 @@ public List<Symbol> visibleSymbols(Document srcFile, LinePosition linePosition)

@Override
public List<Symbol> visibleSymbols(Document sourceFile, LinePosition position, DiagnosticState... states) {
BLangCompilationUnit compilationUnit = getCompilationUnit(sourceFile);
Optional<BLangCompilationUnit> optionalCompUnit = getCompilationUnit(sourceFile);
if (optionalCompUnit.isEmpty()) {
return Collections.emptyList();
}
BLangCompilationUnit compilationUnit = optionalCompUnit.get();
BPackageSymbol moduleSymbol = getModuleSymbol(compilationUnit);
SymbolTable symbolTable = SymbolTable.getInstance(this.compilerContext);
SymbolEnv pkgEnv = symbolTable.pkgEnvMap.get(moduleSymbol);
Expand Down Expand Up @@ -166,8 +170,11 @@ public List<Symbol> visibleSymbols(Document sourceFile, LinePosition position, D
*/
@Override
public Optional<Symbol> symbol(Document sourceDocument, LinePosition position) {
BLangCompilationUnit compilationUnit = getCompilationUnit(sourceDocument);
return lookupSymbol(compilationUnit, position);
Optional<BLangCompilationUnit> compilationUnit = getCompilationUnit(sourceDocument);
if (compilationUnit.isEmpty()) {
return Optional.empty();
}
return lookupSymbol(compilationUnit.get(), position);
}

@Override
Expand All @@ -178,8 +185,13 @@ public Optional<Symbol> symbol(Node node) {
return Optional.empty();
}

BLangCompilationUnit compilationUnit = getCompilationUnit(nodeIdentifierLocation.get().lineRange().fileName());
return lookupSymbol(compilationUnit, nodeIdentifierLocation.get().lineRange().startLine());
Optional<BLangCompilationUnit> compilationUnit =
getCompilationUnit(nodeIdentifierLocation.get().lineRange().fileName());

if (compilationUnit.isEmpty()) {
return Optional.empty();
}
return lookupSymbol(compilationUnit.get(), nodeIdentifierLocation.get().lineRange().startLine());
}

/**
Expand Down Expand Up @@ -256,8 +268,12 @@ public List<Location> references(Symbol symbol, Document targetDocument, boolean
if (symbolLocation.isEmpty()) {
return Collections.emptyList();
}
Optional<BLangCompilationUnit> compilationUnit = getCompilationUnit(targetDocument);
if (compilationUnit.isEmpty()) {
return Collections.emptyList();
}
BLangNode node = new NodeFinder(false)
.lookupEnclosingContainer(getCompilationUnit(targetDocument), symbolLocation.get().lineRange());
.lookupEnclosingContainer(compilationUnit.get(), symbolLocation.get().lineRange());

return getReferences(symbolAtCursor, node, withDefinition);
}
Expand All @@ -273,16 +289,25 @@ public List<Location> references(Document sourceDocument,
return Collections.emptyList();
}
Location symbolLocation = symbolAtCursor.getPosition();

Optional<BLangCompilationUnit> compilationUnit = getCompilationUnit(targetDocument);
if (compilationUnit.isEmpty()) {
return Collections.emptyList();
}

BLangNode node = new NodeFinder(false)
.lookupEnclosingContainer(getCompilationUnit(targetDocument), symbolLocation.lineRange());
.lookupEnclosingContainer(compilationUnit.get(), symbolLocation.lineRange());

return getReferences(symbolAtCursor, node, withDefinition);
}

private BSymbol findSymbolAtCursorPosition(Document sourceDocument, LinePosition linePosition) {
BLangCompilationUnit sourceCompilationUnit = getCompilationUnit(sourceDocument);
Optional<BLangCompilationUnit> sourceCompilationUnit = getCompilationUnit(sourceDocument);
if (sourceCompilationUnit.isEmpty()) {
return null;
}
SymbolFinder symbolFinder = new SymbolFinder();
return symbolFinder.lookup(sourceCompilationUnit, linePosition);
return symbolFinder.lookup(sourceCompilationUnit.get(), linePosition);
}

private List<Location> getReferences(BSymbol symbol, BLangNode node, boolean withDefinition) {
Expand All @@ -295,9 +320,12 @@ private List<Location> getReferences(BSymbol symbol, BLangNode node, boolean wit
*/
@Override
public Optional<TypeSymbol> type(LineRange range) {
BLangCompilationUnit compilationUnit = getCompilationUnit(range.fileName());
Optional<BLangCompilationUnit> compilationUnit = getCompilationUnit(range.fileName());
if (compilationUnit.isEmpty()) {
return Optional.empty();
}
NodeFinder nodeFinder = new NodeFinder(true);
BLangNode node = nodeFinder.lookup(compilationUnit, range);
BLangNode node = nodeFinder.lookup(compilationUnit.get(), range);

if (node == null) {
return Optional.empty();
Expand All @@ -308,9 +336,12 @@ public Optional<TypeSymbol> type(LineRange range) {

@Override
public Optional<TypeSymbol> typeOf(LineRange range) {
BLangCompilationUnit compilationUnit = getCompilationUnit(range.fileName());
Optional<BLangCompilationUnit> compilationUnit = getCompilationUnit(range.fileName());
if (compilationUnit.isEmpty()) {
return Optional.empty();
}
NodeFinder nodeFinder = new NodeFinder(false);
BLangNode node = nodeFinder.lookup(compilationUnit, range);
BLangNode node = nodeFinder.lookup(compilationUnit.get(), range);

if (!isNonNamedArgExprNode(node) && !isObjectConstructorExpr(node) && !isAnonFunctionExpr(node)) {
return Optional.empty();
Expand Down Expand Up @@ -395,10 +426,13 @@ public List<Diagnostic> diagnostics() {
@Override
public Optional<TypeSymbol> expectedType(Document sourceDocument, LinePosition linePosition) {
Optional<TypeSymbol> typeSymbol = null;
BLangCompilationUnit compilationUnit = getCompilationUnit(sourceDocument);
Optional<BLangCompilationUnit> compilationUnit = getCompilationUnit(sourceDocument);
if (compilationUnit.isEmpty()) {
return Optional.empty();
}
SyntaxTree syntaxTree = sourceDocument.syntaxTree();
Node node = findInnerMostNode(linePosition, syntaxTree);
ExpectedTypeFinder expectedTypeFinder = new ExpectedTypeFinder(this, compilationUnit,
ExpectedTypeFinder expectedTypeFinder = new ExpectedTypeFinder(this, compilationUnit.get(),
this.compilerContext, linePosition, sourceDocument);
while (node != null) {
try {
Expand Down Expand Up @@ -478,21 +512,18 @@ private boolean isImportedSymbol(BSymbol symbol) {
(Symbols.isFlagOn(symbol.flags, Flags.PUBLIC) || symbol.getKind() == SymbolKind.PACKAGE);
}

private BLangCompilationUnit getCompilationUnit(Document srcFile) {
private Optional<BLangCompilationUnit> getCompilationUnit(Document srcFile) {
return getCompilationUnit(srcFile.name());
}

private BLangCompilationUnit getCompilationUnit(String srcFile) {
private Optional<BLangCompilationUnit> getCompilationUnit(String srcFile) {
List<BLangCompilationUnit> testSrcs = new ArrayList<>();
for (BLangTestablePackage pkg : bLangPackage.testablePkgs) {
testSrcs.addAll(pkg.compUnits);
}

Stream<BLangCompilationUnit> units = Stream.concat(bLangPackage.compUnits.stream(), testSrcs.stream());
return units
.filter(unit -> unit.name.equals(srcFile))
.findFirst()
.get();
return units.filter(unit -> unit.name.equals(srcFile)).findFirst();
}

private boolean isCursorNotAtDefinition(BLangCompilationUnit compilationUnit, BSymbol symbolAtCursor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
import io.ballerina.compiler.api.symbols.Symbol;
import io.ballerina.compiler.api.symbols.TypeDescKind;
import io.ballerina.compiler.api.symbols.TypeSymbol;
import io.ballerina.compiler.syntax.tree.BasicLiteralNode;
import io.ballerina.compiler.syntax.tree.ConstantDeclarationNode;
import io.ballerina.compiler.syntax.tree.NodeVisitor;
import io.ballerina.compiler.syntax.tree.SyntaxTree;
import io.ballerina.projects.Document;
import io.ballerina.projects.DocumentId;
import io.ballerina.projects.Module;
Expand All @@ -43,6 +47,7 @@
import static io.ballerina.tools.text.LinePosition.from;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;

/**
* Test cases for the positions of symbols.
Expand All @@ -53,10 +58,11 @@ public class TestSourcesTest {

private SemanticModel model;
private Document srcFile;
private Project project;

@BeforeClass
public void setup() {
Project project = BCompileUtil.loadProject("test-src/test-project");
this.project = BCompileUtil.loadProject("test-src/test-project");
Module baz = getModule(project, "baz");
model = project.currentPackage().getCompilation().getSemanticModel(baz.moduleId());
DocumentId id = baz.testDocumentIds().iterator().next();
Expand Down Expand Up @@ -103,7 +109,7 @@ public void testVisibleSymbols(int line, int col, List<String> expSymbols) {
public Object[][] getVisibleSymbolPos() {
List<String> moduleSymbols = List.of("PI", "ZERO", "add", "concat", "newPerson", "Person", "Employee",
"BasicType", "PersonObj", "Digit", "FileNotFoundError", "EofError",
"Error", "Address");
"Error", "Address", "IV");
return new Object[][]{
{17, 0, getSymbolNames(moduleSymbols, "testConstUse", "testAdd", "test")},
{26, 31, getSymbolNames(moduleSymbols, "testConstUse", "testAdd", "test", "sum")},
Expand All @@ -126,4 +132,71 @@ public Object[][] getExprPos() {
{26, 22, 26, 25, INT},
};
}

@Test
public void testSemanticModelForWrongModule() {
Module foo = getModule(this.project, "foo");
SemanticModel fooSemanticModel = foo.getCompilation().getSemanticModel();

Module baz = getModule(this.project, "baz");
SemanticModel bazSemanticModel = baz.getCompilation().getSemanticModel();

DocumentId bazBalDocId = baz.documentIds().stream()
.filter(docId -> docId.toString().contains("baz.bal"))
.findFirst().get();
Document bazBalDoc = baz.document(bazBalDocId);
SyntaxTree bazSyntaxTree = bazBalDoc.syntaxTree();

// `symbol(Node node)`, `typeOf(Node node)` and `type(Node node)`
// use `fooSemanticModel` for `baz` module
bazSyntaxTree.rootNode().accept(getNodeVisitor(fooSemanticModel));

// `symbol(Document sourceDocument, LinePosition position)`
assertTrue(fooSemanticModel.symbol(bazBalDoc, from(16, 13)).isEmpty());

// `visibleSymbols(Document sourceFile, LinePosition position, DiagnosticState... states)`
assertTrue(fooSemanticModel.visibleSymbols(bazBalDoc, from(16, 23)).isEmpty());

// `references(Document sourceDocument, LinePosition position)`
assertTrue(fooSemanticModel.references(bazBalDoc, from(0, 0)).isEmpty());

// `references(Document sourceDocument, LinePosition position, boolean withDefinition)`
assertTrue(fooSemanticModel.references(bazBalDoc, from(0, 0), true).isEmpty());

// `references(Symbol symbol, Document targetDocument, boolean withDefinition)`
Optional<Symbol> constSym = bazSemanticModel.symbol(bazBalDoc, from(16, 13));
assertTrue(constSym.isPresent());
assertTrue(fooSemanticModel.references(constSym.get(), bazBalDoc, true).isEmpty());

// `references(Document sourceDocument, Document targetDocument, LinePosition position, boolean withDefinition)`
assertTrue(fooSemanticModel.references(bazBalDoc, bazBalDoc, from(16, 13), true).isEmpty());

DocumentId fooBalDocId = foo.documentIds().stream()
.filter(docId -> docId.toString().contains("constants.bal"))
.findFirst().get();
assertTrue(fooSemanticModel.references(foo.document(fooBalDocId), bazBalDoc, from(16, 13), true).isEmpty());

// `expectedType(Document sourceDocument, LinePosition linePosition)`
assertTrue(fooSemanticModel.expectedType(bazBalDoc, from(16, 18)).isEmpty());

// `type(LineRange lineRange)`
assertTrue(fooSemanticModel.type(LineRange.from("baz.bal",
from(16, 18), from(16, 21))).isEmpty());
}

private NodeVisitor getNodeVisitor(SemanticModel semanticModel) {
return new NodeVisitor() {
@Override
public void visit(ConstantDeclarationNode constantDeclarationNode) {
assertTrue(semanticModel.symbol(constantDeclarationNode).isEmpty());
constantDeclarationNode.initializer().accept(this);
}

@Override
public void visit(BasicLiteralNode basicLiteralNode) {
assertTrue(semanticModel.typeOf(basicLiteralNode).isEmpty());
assertTrue(semanticModel.type(basicLiteralNode).isEmpty());
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) 2024 WSO2 LLC. (http://www.wso2.org).
//
// WSO2 LLC. licenses this file to you 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.

public const IV = 255;

0 comments on commit a842c79

Please sign in to comment.