diff --git a/presentation-compiler/src/main/scala/org/alephium/ralph/lsp/pc/sourcecode/SourceCodeSearcher.scala b/presentation-compiler/src/main/scala/org/alephium/ralph/lsp/pc/sourcecode/SourceCodeSearcher.scala index bf53b1cf..13b71bde 100644 --- a/presentation-compiler/src/main/scala/org/alephium/ralph/lsp/pc/sourcecode/SourceCodeSearcher.scala +++ b/presentation-compiler/src/main/scala/org/alephium/ralph/lsp/pc/sourcecode/SourceCodeSearcher.scala @@ -103,8 +103,8 @@ object SourceCodeSearcher extends StrictImplicitLogging { /** * Collects all source files with valid parsed syntax. * - * @param sourceCode The source files to filter. - * @return An array sequence containing parsed source code files. + * @param sourceCode The source files to be filtered + * @return Source files that are successfully parsed. */ def collectParsed(sourceCode: ArraySeq[SourceCodeState]): ArraySeq[SourceCodeState.Parsed] = sourceCode collect { @@ -118,6 +118,24 @@ object SourceCodeSearcher extends StrictImplicitLogging { errored.parsed } + /** + * Collects all source files that were parsed and may contain syntax errors. + * + * @param sourceCode The source files to be filtered. + * @return Source files that were parsed at least once. + */ + def collectIsParsed(sourceCode: ArraySeq[SourceCodeState]): ArraySeq[SourceCodeState.IsParsed] = + sourceCode collect { + case parsed: SourceCodeState.IsParsed => + parsed + + case compiled: SourceCodeState.Compiled => + compiled.parsed + + case errored: SourceCodeState.ErrorCompilation => + errored.parsed + } + /** * Collect all unique import statements from source code. * diff --git a/presentation-compiler/src/test/scala/org/alephium/ralph/lsp/pc/sourcecode/SourceCodeSearcherCollectIsParsedSpec.scala b/presentation-compiler/src/test/scala/org/alephium/ralph/lsp/pc/sourcecode/SourceCodeSearcherCollectIsParsedSpec.scala new file mode 100644 index 00000000..133a6cb7 --- /dev/null +++ b/presentation-compiler/src/test/scala/org/alephium/ralph/lsp/pc/sourcecode/SourceCodeSearcherCollectIsParsedSpec.scala @@ -0,0 +1,110 @@ +// Copyright 2024 The Alephium Authors +// This file is part of the alephium project. +// +// The library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the library. If not, see http://www.gnu.org/licenses/. + +package org.alephium.ralph.lsp.pc.sourcecode + +import org.alephium.ralph.lsp.access.compiler.CompilerAccess +import org.alephium.ralph.lsp.access.file.FileAccess +import org.alephium.ralph.lsp.pc.client.TestClientLogger +import org.alephium.ralph.lsp.utils.log.ClientLogger +import org.scalatest.matchers.should.Matchers +import org.scalatest.wordspec.AnyWordSpec + +import scala.collection.immutable.ArraySeq + +class SourceCodeSearcherCollectIsParsedSpec extends AnyWordSpec with Matchers { + + implicit val file: FileAccess = FileAccess.disk + implicit val compiler: CompilerAccess = CompilerAccess.ralphc + implicit val logger: ClientLogger = TestClientLogger + + "return empty" when { + "input is empty" in { + SourceCodeSearcher.collectIsParsed(ArraySeq.empty) shouldBe empty + } + } + + "collect parsed source code even if it contains compiler errors" in { + val onDisk = + TestSourceCode.genOnDisk().sample.get + + val unCompiled = + TestSourceCode.genUnCompiled().sample.get + + val strictParserError = + TestSourceCode + .genParsed( + """ + |Contract MyContract() { + | blah + |} + |""".stripMargin + ) + .sample + .get + .asInstanceOf[SourceCodeState.ErrorParser] + + val goodCodeParsed = + TestSourceCode + .genParsedOK( + """ + |Contract MyContract() { + | fn function1() -> () {} + |} + |""".stripMargin + ) + .sample + .get + + val syntaxError = + TestSourceCode + .genParsedErr( + """ + |Abstract Contract AbstractContract() { + | + |contract MyContract( extends AbstractContract() { + | f function1() -> () {} + |} + |""".stripMargin + ) + .sample + .get + + val errorCompilation = + TestSourceCode + .genCompiled( + """ + |Contract MyContract() extends DoesNotExist() { + | fn function1() -> () {} + |} + |""".stripMargin + ) + .sample + .get + .asInstanceOf[SourceCodeState.ErrorCompilation] + + val allCode = + ArraySeq(onDisk, unCompiled, strictParserError, goodCodeParsed, syntaxError, errorCompilation) + + val result = + SourceCodeSearcher.collectIsParsed(allCode) + + result should contain only (strictParserError, goodCodeParsed, syntaxError, errorCompilation.parsed) + + TestSourceCode deleteAllIfExists allCode + } + +}