diff --git a/compiler/src/dotty/tools/MainGenericCompiler.scala b/compiler/src/dotty/tools/MainGenericCompiler.scala index 2c3f6f97e79e..98bd9078c397 100644 --- a/compiler/src/dotty/tools/MainGenericCompiler.scala +++ b/compiler/src/dotty/tools/MainGenericCompiler.scala @@ -85,7 +85,7 @@ case class CompileSettings( object MainGenericCompiler { - val classpathSeparator = File.pathSeparator + val classpathSeparator: String = File.pathSeparator @sharable val javaOption = raw"""-J(.*)""".r @sharable val javaPropOption = raw"""-D(.+?)=(.?)""".r diff --git a/compiler/src/dotty/tools/MainGenericRunner.scala b/compiler/src/dotty/tools/MainGenericRunner.scala index b32630a5d63b..9ff96f812bca 100644 --- a/compiler/src/dotty/tools/MainGenericRunner.scala +++ b/compiler/src/dotty/tools/MainGenericRunner.scala @@ -96,7 +96,7 @@ case class Settings( object MainGenericRunner { - val classpathSeparator = File.pathSeparator + val classpathSeparator: String = File.pathSeparator def processClasspath(cp: String, tail: List[String]): (List[String], List[String]) = val cpEntries = cp.split(classpathSeparator).toList diff --git a/compiler/src/dotty/tools/backend/jvm/CodeGen.scala b/compiler/src/dotty/tools/backend/jvm/CodeGen.scala index 1e2abbcff866..093d4f997aa7 100644 --- a/compiler/src/dotty/tools/backend/jvm/CodeGen.scala +++ b/compiler/src/dotty/tools/backend/jvm/CodeGen.scala @@ -152,7 +152,7 @@ class CodeGen(val int: DottyBackendInterface, val primitives: DottyPrimitives)( new interfaces.AbstractFile { override def name = absfile.name override def path = absfile.path - override def jfile = Optional.ofNullable(absfile.file) + override def jfile: Optional[java.io.File] = Optional.ofNullable(absfile.file) } private def genClass(cd: TypeDef, unit: CompilationUnit): ClassNode = { diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index d534db7df1ce..004fc39e1298 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -2959,7 +2959,7 @@ object SymDenotations { dependent = null } - protected def addDependent(dep: InheritedCache) = { + protected def addDependent(dep: InheritedCache): Unit = { if (dependent == null) dependent = new WeakHashMap dependent.nn.put(dep, ()) } diff --git a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala index 673874ae2769..40c6667fdd24 100644 --- a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala +++ b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala @@ -234,7 +234,7 @@ class InteractiveDriver(val settings: List[String]) extends Driver { private def classesFromDir(dir: Path, buffer: mutable.ListBuffer[TypeName]): Unit = try Files.walkFileTree(dir, new SimpleFileVisitor[Path] { - override def visitFile(path: Path, attrs: BasicFileAttributes) = { + override def visitFile(path: Path, attrs: BasicFileAttributes): FileVisitResult = { if (!attrs.isDirectory) { val name = path.getFileName.toString if name.endsWith(tastySuffix) then diff --git a/compiler/src/dotty/tools/dotc/sbt/APIUtils.scala b/compiler/src/dotty/tools/dotc/sbt/APIUtils.scala index 4ee1fd0f6b68..42843a89c0ab 100644 --- a/compiler/src/dotty/tools/dotc/sbt/APIUtils.scala +++ b/compiler/src/dotty/tools/dotc/sbt/APIUtils.scala @@ -17,10 +17,10 @@ import xsbti.api.SafeLazy.strict */ object APIUtils { private object Constants { - val PublicAccess = api.Public.create() - val EmptyModifiers = new api.Modifiers(false, false, false, false, false, false, false, false) - val EmptyStructure = api.Structure.of(strict(Array.empty), strict(Array.empty), strict(Array.empty)) - val EmptyType = api.EmptyType.of() + val PublicAccess: api.Public = api.Public.create() + val EmptyModifiers: api.Modifiers = new api.Modifiers(false, false, false, false, false, false, false, false) + val EmptyStructure: api.Structure = api.Structure.of(strict(Array.empty), strict(Array.empty), strict(Array.empty)) + val EmptyType: api.EmptyType = api.EmptyType.of() } import Constants.* diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 4d915b57df1b..5f3eeff91ff3 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -232,13 +232,13 @@ private class ExtractAPICollector(nonLocalClassSymbols: mutable.HashSet[Symbol]) private object Constants { val emptyStringArray = Array[String]() - val local = api.ThisQualifier.create() - val public = api.Public.create() - val privateLocal = api.Private.create(local) - val protectedLocal = api.Protected.create(local) - val unqualified = api.Unqualified.create() - val thisPath = api.This.create() - val emptyType = api.EmptyType.create() + val local: api.ThisQualifier = api.ThisQualifier.create() + val public: api.Public = api.Public.create() + val privateLocal: api.Private = api.Private.create(local) + val protectedLocal: api.Protected = api.Protected.create(local) + val unqualified: api.Unqualified = api.Unqualified.create() + val thisPath: api.This = api.This.create() + val emptyType: api.EmptyType = api.EmptyType.create() val emptyModifiers = new api.Modifiers(false, false, false, false, false,false, false, false) } diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 2d178e2f3773..ba472512a953 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -1194,6 +1194,18 @@ object RefChecks { report.warning(ExtensionNullifiedByMember(sym, target), sym.srcPos) end checkExtensionMethods + /** Check that public (and protected) methods/fields do not expose flexible types. */ + def checkPublicFlexibleTypes(sym: Symbol)(using Context): Unit = + if ctx.explicitNulls && !ctx.isJava + && sym.exists && !sym.is(Private) && sym.owner.isClass + && !sym.isOneOf(Synthetic | InlineProxy | Param | Exported) then + val resTp = sym.info.finalResultType + if resTp.existsPart(_.isInstanceOf[FlexibleType], StopAt.Static) then + report.warning( + em"${sym.show} exposes a flexible type in its inferred result type ${resTp}. Consider annotating the type explicitly", + sym.srcPos + ) + /** Verify that references in the user-defined `@implicitNotFound` message are valid. * (i.e. they refer to a type variable that really occurs in the signature of the annotated symbol.) */ @@ -1330,6 +1342,7 @@ class RefChecks extends MiniPhase { thisPhase => val sym = tree.symbol checkNoPrivateOverrides(sym) checkVolatile(sym) + checkPublicFlexibleTypes(sym) if (sym.exists && sym.owner.isTerm) { tree.rhs match { case Ident(nme.WILDCARD) => report.error(UnboundPlaceholderParameter(), sym.srcPos) @@ -1345,6 +1358,7 @@ class RefChecks extends MiniPhase { thisPhase => checkImplicitNotFoundAnnotation.defDef(sym.denot) checkUnaryMethods(sym) checkExtensionMethods(sym) + checkPublicFlexibleTypes(sym) tree } diff --git a/compiler/src/dotty/tools/io/Path.scala b/compiler/src/dotty/tools/io/Path.scala index 39665395c289..64137d691898 100644 --- a/compiler/src/dotty/tools/io/Path.scala +++ b/compiler/src/dotty/tools/io/Path.scala @@ -245,12 +245,12 @@ class Path private[io] (val jpath: JPath) { if (!exists) false else { Files.walkFileTree(jpath, new SimpleFileVisitor[JPath]() { - override def visitFile(file: JPath, attrs: BasicFileAttributes) = { + override def visitFile(file: JPath, attrs: BasicFileAttributes): FileVisitResult = { Files.delete(file) FileVisitResult.CONTINUE } - override def postVisitDirectory(dir: JPath, exc: IOException) = { + override def postVisitDirectory(dir: JPath, exc: IOException): FileVisitResult = { Files.delete(dir) FileVisitResult.CONTINUE } diff --git a/compiler/src/dotty/tools/repl/AbstractFileClassLoader.scala b/compiler/src/dotty/tools/repl/AbstractFileClassLoader.scala index 7a457a1d7546..1796a7dc68b5 100644 --- a/compiler/src/dotty/tools/repl/AbstractFileClassLoader.scala +++ b/compiler/src/dotty/tools/repl/AbstractFileClassLoader.scala @@ -26,7 +26,7 @@ class AbstractFileClassLoader(val root: AbstractFile, parent: ClassLoader) exten // on JDK 20 the URL constructor we're using is deprecated, // but the recommended replacement, URL.of, doesn't exist on JDK 8 @annotation.nowarn("cat=deprecation") - override protected def findResource(name: String) = + override protected def findResource(name: String): URL | Null = findAbstractFile(name) match case null => null case file => new URL(null, s"memory:${file.path}", new URLStreamHandler { @@ -35,13 +35,13 @@ class AbstractFileClassLoader(val root: AbstractFile, parent: ClassLoader) exten override def getInputStream = file.input } }) - override protected def findResources(name: String) = + override protected def findResources(name: String): java.util.Enumeration[URL] = findResource(name) match case null => Collections.enumeration(Collections.emptyList[URL]) //Collections.emptyEnumeration[URL] case url => Collections.enumeration(Collections.singleton(url)) override def findClass(name: String): Class[?] = { - var file: AbstractFile = root + var file: AbstractFile | Null = root val pathParts = name.split("[./]").toList for (dirPart <- pathParts.init) { file = file.lookupName(dirPart, true) diff --git a/compiler/src/dotty/tools/repl/JLineTerminal.scala b/compiler/src/dotty/tools/repl/JLineTerminal.scala index e4ac1626525e..2680704d326e 100644 --- a/compiler/src/dotty/tools/repl/JLineTerminal.scala +++ b/compiler/src/dotty/tools/repl/JLineTerminal.scala @@ -106,7 +106,7 @@ class JLineTerminal extends java.io.Closeable { ) extends reader.ParsedLine { // Using dummy values, not sure what they are used for def wordIndex = -1 - def words = java.util.Collections.emptyList[String] + def words: java.util.List[String] = java.util.Collections.emptyList[String] } def parse(input: String, cursor: Int, context: ParseContext): reader.ParsedLine = { diff --git a/compiler/src/dotty/tools/repl/ScriptEngine.scala b/compiler/src/dotty/tools/repl/ScriptEngine.scala index 7d385daa43e4..cce16000577f 100644 --- a/compiler/src/dotty/tools/repl/ScriptEngine.scala +++ b/compiler/src/dotty/tools/repl/ScriptEngine.scala @@ -64,20 +64,21 @@ class ScriptEngine extends AbstractScriptEngine { object ScriptEngine { import java.util.Arrays + import java.util.List import scala.util.Properties class Factory extends ScriptEngineFactory { def getEngineName = "Scala REPL" def getEngineVersion = "3.0" - def getExtensions = Arrays.asList("scala") + def getExtensions: List[String] = Arrays.asList("scala") def getLanguageName = "Scala" def getLanguageVersion = Properties.versionString - def getMimeTypes = Arrays.asList("application/x-scala") - def getNames = Arrays.asList("scala") + def getMimeTypes: List[String] = Arrays.asList("application/x-scala") + def getNames: List[String] = Arrays.asList("scala") - def getMethodCallSyntax(obj: String, m: String, args: String*) = s"$obj.$m(${args.mkString(", ")})" + def getMethodCallSyntax(obj: String, m: String, args: String*): String = s"$obj.$m(${args.mkString(", ")})" - def getOutputStatement(toDisplay: String) = s"""print("$toDisplay")""" + def getOutputStatement(toDisplay: String): String = s"""print("$toDisplay")""" def getParameter(key: String): Object = key match { case JScriptEngine.ENGINE => getEngineName @@ -88,7 +89,7 @@ object ScriptEngine { case _ => null } - def getProgram(statements: String*) = statements.mkString("; ") + def getProgram(statements: String*): String = statements.mkString("; ") def getScriptEngine: JScriptEngine = new ScriptEngine } diff --git a/compiler/src/dotty/tools/tasty/besteffort/BestEffortTastyFormat.scala b/compiler/src/dotty/tools/tasty/besteffort/BestEffortTastyFormat.scala index 99a24ce5f346..41876016b4ec 100644 --- a/compiler/src/dotty/tools/tasty/besteffort/BestEffortTastyFormat.scala +++ b/compiler/src/dotty/tools/tasty/besteffort/BestEffortTastyFormat.scala @@ -38,7 +38,7 @@ object BestEffortTastyFormat { // added AST tag - Best Effort TASTy only final val ERRORtype = 50 - def astTagToString(tag: Int) = tag match { + def astTagToString(tag: Int): String = tag match { case ERRORtype => "ERRORtype" case _ => TastyFormat.astTagToString(tag) } diff --git a/compiler/test/dotty/tools/dotc/TupleShowTests.scala b/compiler/test/dotty/tools/dotc/TupleShowTests.scala index 88e0587d7d71..3aa9d0d84b42 100644 --- a/compiler/test/dotty/tools/dotc/TupleShowTests.scala +++ b/compiler/test/dotty/tools/dotc/TupleShowTests.scala @@ -54,24 +54,28 @@ class TupleShowTests extends DottyTest: @Test def tup3_show10 = chkEq("(Int,\n Long,\n Short)".normEOL, tup3.toText(ctx.printer).mkString(10, false)) - val res21 = """|(Int, Int, Int, Int, Int, Long, Long, Long, Long, Long, Int, Int, Int, Int, - | Int, Long, Long, Long, Long, Long, Int)""".stripMargin.normEOL + val res21: String = + """|(Int, Int, Int, Int, Int, Long, Long, Long, Long, Long, Int, Int, Int, Int, + | Int, Long, Long, Long, Long, Long, Int)""".stripMargin.normEOL - val res22 = """|(Int, Int, Int, Int, Int, Long, Long, Long, Long, Long, Int, Int, Int, Int, - | Int, Long, Long, Long, Long, Long, Int, Long)""".stripMargin.normEOL + val res22: String = + """|(Int, Int, Int, Int, Int, Long, Long, Long, Long, Long, Int, Int, Int, Int, + | Int, Long, Long, Long, Long, Long, Int, Long)""".stripMargin.normEOL - val res23 = """|(Int, Int, Int, Int, Int, Long, Long, Long, Long, Long, Int, Int, Int, Int, - | Int, Long, Long, Long, Long, Long, Int, Long, Short)""".stripMargin.normEOL + val res23: String = + """|(Int, Int, Int, Int, Int, Long, Long, Long, Long, Long, Int, Int, Int, Int, + | Int, Long, Long, Long, Long, Long, Int, Long, Short)""".stripMargin.normEOL - val res24 = """|(Int, Int, Int, Int, Int, Long, Long, Long, Long, Long, Int, Int, Int, Int, - | Int, Long, Long, Long, Long, Long, Int, Long, Short, Short)""".stripMargin.normEOL + val res24: String = + """|(Int, Int, Int, Int, Int, Long, Long, Long, Long, Long, Int, Int, Int, Int, + | Int, Long, Long, Long, Long, Long, Int, Long, Short, Short)""".stripMargin.normEOL def chkEq[A](expected: A, obtained: A) = assert(expected == obtained, diff(s"$expected", s"$obtained")) /** On Windows the string literal in this test source file will be read with `\n` (b/c of "-encoding UTF8") * but the compiler will correctly emit \r\n as the line separator. * So we align the expected result to faithfully compare test results. */ - extension (str: String) def normEOL = if EOL == "\n" then str else str.replace("\n", EOL) + extension (str: String) def normEOL: String = if EOL == "\n" then str else str.replace("\n", EOL) def diff(exp: String, obt: String) = val min = math.min(exp.length, obt.length) diff --git a/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala b/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala index 827a997af14b..6df830905603 100644 --- a/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala +++ b/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala @@ -33,7 +33,7 @@ import dotty.tools.dotc.util.SourceFile * only 1 semanticdb file should be present * @param source the single source file producing the semanticdb */ -@main def metac(root: String, source: String) = +@main def metac(root: String, source: String): Unit = val rootSrc = Paths.get(root) val sourceSrc = Paths.get(source) val semanticFile = FileSystems.getDefault.getPathMatcher("glob:**.semanticdb") @@ -53,13 +53,13 @@ import dotty.tools.dotc.util.SourceFile @Category(Array(classOf[BootstrappedOnlyTests])) class SemanticdbTests: - val javaFile = FileSystems.getDefault.getPathMatcher("glob:**.java") - val scalaFile = FileSystems.getDefault.getPathMatcher("glob:**.scala") - val expectFile = FileSystems.getDefault.getPathMatcher("glob:**.expect.scala") - val rootSrc = Paths.get(System.getProperty("dotty.tools.dotc.semanticdb.test")) - val expectSrc = rootSrc.resolve("expect") - val javaRoot = rootSrc.resolve("javacp") - val metacExpectFile = rootSrc.resolve("metac.expect") + val javaFile: PathMatcher = FileSystems.getDefault.getPathMatcher("glob:**.java") + val scalaFile: PathMatcher = FileSystems.getDefault.getPathMatcher("glob:**.scala") + val expectFile: PathMatcher = FileSystems.getDefault.getPathMatcher("glob:**.expect.scala") + val rootSrc: Path = Paths.get(System.getProperty("dotty.tools.dotc.semanticdb.test")) + val expectSrc: Path = rootSrc.resolve("expect") + val javaRoot: Path = rootSrc.resolve("javacp") + val metacExpectFile: Path = rootSrc.resolve("metac.expect") @Category(Array(classOf[dotty.SlowTests])) @Test def expectTests: Unit = if (!scala.util.Properties.isWin) runExpectTest(updateExpectFiles = false) diff --git a/compiler/test/dotty/tools/repl/AbstractFileClassLoaderTest.scala b/compiler/test/dotty/tools/repl/AbstractFileClassLoaderTest.scala index 27796feb819b..44540629016e 100644 --- a/compiler/test/dotty/tools/repl/AbstractFileClassLoaderTest.scala +++ b/compiler/test/dotty/tools/repl/AbstractFileClassLoaderTest.scala @@ -29,7 +29,7 @@ class AbstractFileClassLoaderTest: // cf ScalaClassLoader#classBytes extension (loader: ClassLoader) // An InputStream representing the given class name, or null if not found. - def classAsStream(className: String) = loader.getResourceAsStream { + def classAsStream(className: String): InputStream = loader.getResourceAsStream { if className.endsWith(".class") then className else s"${className.replace('.', '/')}.class" // classNameToPath } diff --git a/compiler/test/dotty/tools/scripting/ScriptTestEnv.scala b/compiler/test/dotty/tools/scripting/ScriptTestEnv.scala index 771c3ba14af0..387e309f6aec 100644 --- a/compiler/test/dotty/tools/scripting/ScriptTestEnv.scala +++ b/compiler/test/dotty/tools/scripting/ScriptTestEnv.scala @@ -282,7 +282,7 @@ object ScriptTestEnv { } extension(f: File) { - def name = f.getName + def name: String = f.getName def norm: String = f.toPath.normalize.norm def absPath: String = f.getAbsolutePath.norm def relpath: Path = f.toPath.relpath @@ -305,7 +305,7 @@ object ScriptTestEnv { // dist[*]/target/universal/stage, if present // else, SCALA_HOME if defined // else, not defined - lazy val envScalaHome = + lazy val envScalaHome: String = printf("scalacPath: %s\n", scalacPath.norm) if scalacPath.isFile then scalacPath.replaceAll("/bin/scalac", "") else envOrElse("SCALA_HOME", "not-found").norm diff --git a/compiler/test/dotty/tools/utils.scala b/compiler/test/dotty/tools/utils.scala index 14981e001d38..5dd949643f7f 100644 --- a/compiler/test/dotty/tools/utils.scala +++ b/compiler/test/dotty/tools/utils.scala @@ -33,7 +33,7 @@ def scriptsDir(path: String): File = { dir } -extension (f: File) def absPath = +extension (f: File) def absPath: String = f.getAbsolutePath.replace('\\', '/') extension (str: String) def dropExtension = diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index 1bb3c6ae5370..b0b64316bfe7 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -353,8 +353,8 @@ trait ParallelTesting extends RunnerOrchestration: import summaryReport._ - protected final val realStdout = System.out - protected final val realStderr = System.err + protected final val realStdout: PrintStream = System.out + protected final val realStderr: PrintStream = System.err /** A runnable that logs its contents in a buffer */ trait LoggedRunnable extends Runnable { diff --git a/presentation-compiler/src/main/dotty/tools/pc/InferExpectedType.scala b/presentation-compiler/src/main/dotty/tools/pc/InferExpectedType.scala index 8640f518c0f1..2aecbb7b36b6 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/InferExpectedType.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/InferExpectedType.scala @@ -26,8 +26,8 @@ class InferExpectedType( driver: InteractiveDriver, params: OffsetParams )(implicit rc: ReportContext): - val uri = params.uri().nn - val code = params.text().nn + val uri: java.net.URI = params.uri() + val code: String = params.text() val sourceFile = SourceFile.virtual(uri, code) driver.run(uri, sourceFile) diff --git a/presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala index 29396a5c0d32..395548822d96 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala @@ -39,11 +39,11 @@ class PcInlayHintsProvider( symbolSearch: SymbolSearch, )(using ReportContext): - val uri = params.uri().nn - val filePath = Paths.get(uri).nn - val sourceText = params.text().nn - val text = sourceText.toCharArray().nn - val source = + val uri: java.net.URI = params.uri() + val filePath: java.nio.file.Path = Paths.get(uri) + val sourceText: String = params.text() + val text: Array[Char] = sourceText.toCharArray() + val source: SourceFile = SourceFile.virtual(filePath.toString, sourceText) driver.run(uri, source) given InlayHintsParams = params @@ -119,7 +119,7 @@ class PcInlayHintsProvider( InlayHintKind.Type, ) .addDefinition(adjustedPos.start) - case Parameters(isInfixFun, args) => + case Parameters(isInfixFun, args) => def isNamedParam(pos: SourcePosition): Boolean = val start = text.indexWhere(!_.isWhitespace, pos.start) val end = text.lastIndexWhere(!_.isWhitespace, pos.end - 1) @@ -142,9 +142,9 @@ class PcInlayHintsProvider( case (ih, (name, pos0, isByName)) => val pos = adjustPos(pos0) val isBlock = isBlockParam(pos) - val namedLabel = + val namedLabel = if params.namedParameters() && !isInfixFun && !isBlock && !isNamedParam(pos) then s"${name} = " else "" - val byNameLabel = + val byNameLabel = if params.byNameParameters() && isByName && (!isInfixFun || isBlock) then "=> " else "" val labelStr = s"${namedLabel}${byNameLabel}" @@ -432,19 +432,19 @@ object InferredType: end InferredType object Parameters: - def unapply(tree: Tree)(using params: InlayHintsParams, ctx: Context): Option[(Boolean, List[(Name, SourcePosition, Boolean)])] = - def shouldSkipFun(fun: Tree)(using Context): Boolean = + def unapply(tree: Tree)(using params: InlayHintsParams, ctx: Context): Option[(Boolean, List[(Name, SourcePosition, Boolean)])] = + def shouldSkipFun(fun: Tree)(using Context): Boolean = fun match case sel: Select => isForComprehensionMethod(sel) || sel.symbol.name == nme.unapply || sel.symbol.is(Flags.JavaDefined) case _ => false - def isInfixFun(fun: Tree, args: List[Tree])(using Context): Boolean = + def isInfixFun(fun: Tree, args: List[Tree])(using Context): Boolean = val isInfixSelect = fun match case Select(sel, _) => sel.isInfix case _ => false val source = fun.source if args.isEmpty then isInfixSelect - else + else (!(fun.span.end until args.head.span.start) .map(source.apply) .contains('.') && fun.symbol.is(Flags.ExtensionMethod)) || isInfixSelect @@ -467,7 +467,7 @@ object Parameters: if (params.namedParameters() || params.byNameParameters()) then tree match - case Apply(fun, args) if isRealApply(fun) => + case Apply(fun, args) if isRealApply(fun) => val underlyingFun = getUnderlyingFun(fun) if shouldSkipFun(underlyingFun) then None @@ -475,7 +475,7 @@ object Parameters: val funTp = fun.typeOpt.widenTermRefExpr val paramNames = funTp.paramNamess.flatten val paramInfos = funTp.paramInfoss.flatten - + Some( isInfixFun(fun, args) || underlyingFun.isInfix, ( @@ -483,7 +483,7 @@ object Parameters: .zip(paramNames) .zip(paramInfos) .collect { - case ((arg, paramName), paramInfo) if !arg.span.isZeroExtent && !isDefaultArg(arg) => + case ((arg, paramName), paramInfo) if !arg.span.isZeroExtent && !isDefaultArg(arg) => (paramName.fieldName, arg.sourcePos, paramInfo.isByName) } ) diff --git a/presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala b/presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala index 18311d1b7853..81517524e3a6 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala @@ -119,7 +119,7 @@ case class ScalaPresentationCompiler( ): PresentationCompiler = copy(completionItemPriority = priority) - override def withBuildTargetName(buildTargetName: String) = + override def withBuildTargetName(buildTargetName: String): PresentationCompiler = copy(buildTargetName = Some(buildTargetName)) override def withReportsLoggerLevel(level: String): PresentationCompiler = diff --git a/presentation-compiler/src/main/dotty/tools/pc/WithCompilationUnit.scala b/presentation-compiler/src/main/dotty/tools/pc/WithCompilationUnit.scala index 56be6614bbd4..5ba89324fca8 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/WithCompilationUnit.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/WithCompilationUnit.scala @@ -22,11 +22,11 @@ class WithCompilationUnit( val driver: InteractiveDriver, params: VirtualFileParams, ): - val uri = params.uri() - val filePath = Paths.get(uri) - val sourceText = params.text - val text = sourceText.toCharArray() - val source = + val uri: java.net.URI = params.uri() + val filePath: java.nio.file.Path = Paths.get(uri) + val sourceText: String = params.text + val text: Array[Char] = sourceText.toCharArray() + val source: SourceFile = SourceFile.virtual(filePath.toString, sourceText) driver.run(uri, source) given ctx: Context = driver.currentCtx diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala index ea3565574ce3..61a93dc1bccb 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala @@ -76,7 +76,7 @@ class Completions( if appl.fun == funSel && sel == fun => false case _ => true) && (adjustedPath match - /* In case of `class X derives TC@@` we shouldn't add `[]` + /* In case of `class X derives TC@@` we shouldn't add `[]` */ case Ident(_) :: (templ: untpd.DerivingTemplate) :: _ => val pos = completionPos.toSourcePosition @@ -215,9 +215,9 @@ class Completions( case mt@MethodType(termNames) if app.symbol.paramSymss.last.exists(_.is(Given)) && !text.substring(app.fun.span.start, arg.span.end).contains("using") => suffix.withNewPrefix(Affix(PrefixKind.Using)) - case _ => suffix + case _ => suffix case _ => suffix - + } .chain { suffix => // for () suffix if shouldAddSuffix && symbol.is(Flags.Method) then @@ -907,7 +907,7 @@ class Completions( application: CompletionApplication ): Ordering[CompletionValue] = new Ordering[CompletionValue]: - val queryLower = completionPos.query.toLowerCase() + val queryLower: String = completionPos.query.toLowerCase() val fuzzyCache = mutable.Map.empty[CompletionValue, Int] def compareLocalSymbols(s1: Symbol, s2: Symbol): Int = diff --git a/presentation-compiler/test/dotty/tools/pc/base/BasePCSuite.scala b/presentation-compiler/test/dotty/tools/pc/base/BasePCSuite.scala index a26c31ef084d..5128303d105f 100644 --- a/presentation-compiler/test/dotty/tools/pc/base/BasePCSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/base/BasePCSuite.scala @@ -25,7 +25,7 @@ import org.junit.runner.RunWith import scala.meta.pc.CompletionItemPriority object TestResources: - val classpath = BuildInfo.ideTestsDependencyClasspath.map(_.toPath).toSeq + val classpath: Seq[Path] = BuildInfo.ideTestsDependencyClasspath.map(_.toPath).toSeq val classpathSearch = ClasspathSearch.fromClasspath(classpath, ExcludedPackagesHandler.default) @@ -34,7 +34,7 @@ abstract class BasePCSuite extends PcAssertions: val completionItemPriority: CompletionItemPriority = (_: String) => 0 private val isDebug = ManagementFactory.getRuntimeMXBean.getInputArguments.toString.contains("-agentlib:jdwp") - val tmp = Files.createTempDirectory("stable-pc-tests") + val tmp: Path = Files.createTempDirectory("stable-pc-tests") val executorService: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor() val testingWorkspaceSearch = TestingWorkspaceSearch( diff --git a/presentation-compiler/test/dotty/tools/pc/utils/MockSymbolSearch.scala b/presentation-compiler/test/dotty/tools/pc/utils/MockSymbolSearch.scala index 459c41e3c8e5..735ee846be2d 100644 --- a/presentation-compiler/test/dotty/tools/pc/utils/MockSymbolSearch.scala +++ b/presentation-compiler/test/dotty/tools/pc/utils/MockSymbolSearch.scala @@ -66,7 +66,7 @@ class MockSymbolSearch( override def documentation( symbol: String, parents: ParentSymbols - ) = documentation(symbol, parents, ContentType.MARKDOWN) + ): Optional[SymbolDocumentation] = documentation(symbol, parents, ContentType.MARKDOWN) override def documentation( symbol: String, diff --git a/tests/explicit-nulls/warn/expose-flexible-types.check b/tests/explicit-nulls/warn/expose-flexible-types.check new file mode 100644 index 000000000000..5e0f8519b7e7 --- /dev/null +++ b/tests/explicit-nulls/warn/expose-flexible-types.check @@ -0,0 +1,56 @@ +-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:4:6 -------------------------------------------------- +4 | def f = s.trim // warn + | ^ + | method f exposes a flexible type in its inferred result type (String)?. Consider annotating the type explicitly +-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:8:6 -------------------------------------------------- +8 | def h = (s.trim, s.length) // warn + | ^ + |method h exposes a flexible type in its inferred result type ((String)?, Int). Consider annotating the type explicitly +-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:9:16 ------------------------------------------------- +9 | protected def i = s.trim // warn + | ^ + | method i exposes a flexible type in its inferred result type (String)?. Consider annotating the type explicitly +-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:11:19 ------------------------------------------------ +11 | private[foo] def k = s.trim // warn + | ^ + | method k exposes a flexible type in its inferred result type (String)?. Consider annotating the type explicitly +-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:12:6 ------------------------------------------------- +12 | val ss = s.replace("a", "A") // warn + | ^ + | value ss exposes a flexible type in its inferred result type (String)?. Consider annotating the type explicitly +-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:13:6 ------------------------------------------------- +13 | val ss2 = Seq(s.trim) // warn + | ^ + |value ss2 exposes a flexible type in its inferred result type Seq[(String)?]. Consider annotating the type explicitly +-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:21:6 ------------------------------------------------- +21 | def f = s2.trim // warn + | ^ + | method f exposes a flexible type in its inferred result type (String)?. Consider annotating the type explicitly +-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:25:6 ------------------------------------------------- +25 | def h = (s2.trim, s2.length) // warn + | ^ + |method h exposes a flexible type in its inferred result type ((String)?, Int). Consider annotating the type explicitly +-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:26:6 ------------------------------------------------- +26 | val ss = s2.replace("a", "A") // warn + | ^ + | value ss exposes a flexible type in its inferred result type (String)?. Consider annotating the type explicitly +-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:27:6 ------------------------------------------------- +27 | val ss2 = Seq(s2.trim) // warn + | ^ + |value ss2 exposes a flexible type in its inferred result type Seq[(String)?]. Consider annotating the type explicitly +-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:32:4 ------------------------------------------------- +32 |def f = s2.trim // warn + | ^ + | method f exposes a flexible type in its inferred result type (String)?. Consider annotating the type explicitly +-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:36:4 ------------------------------------------------- +36 |def h = (s2.trim, s2.length) // warn + | ^ + |method h exposes a flexible type in its inferred result type ((String)?, Int). Consider annotating the type explicitly +-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:37:4 ------------------------------------------------- +37 |val ss = s2.replace("a", "A") // warn + | ^ + | value ss exposes a flexible type in its inferred result type (String)?. Consider annotating the type explicitly +-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:38:4 ------------------------------------------------- +38 |val ss2 = Seq(s2.trim) // warn + | ^ + |value ss2 exposes a flexible type in its inferred result type Seq[(String)?]. Consider annotating the type explicitly diff --git a/tests/explicit-nulls/warn/expose-flexible-types.scala b/tests/explicit-nulls/warn/expose-flexible-types.scala new file mode 100644 index 000000000000..9908e6228cd4 --- /dev/null +++ b/tests/explicit-nulls/warn/expose-flexible-types.scala @@ -0,0 +1,41 @@ +package foo + +class C(s: String): + def f = s.trim // warn + def g: String = + val s2 = s.trim + s2 + def h = (s.trim, s.length) // warn + protected def i = s.trim // warn + private def j = s.trim + private[foo] def k = s.trim // warn + val ss = s.replace("a", "A") // warn + val ss2 = Seq(s.trim) // warn + val ss3: Seq[String] = + val s3 = s.trim + Seq(s3) + +val s2: String = "" + +object O: + def f = s2.trim // warn + def g: String = + val s3 = s2.trim + s3 + def h = (s2.trim, s2.length) // warn + val ss = s2.replace("a", "A") // warn + val ss2 = Seq(s2.trim) // warn + val ss3: Seq[String] = + val s3 = s2.trim + Seq(s3) + +def f = s2.trim // warn +def g: String = + val s3 = s2.trim + s3 +def h = (s2.trim, s2.length) // warn +val ss = s2.replace("a", "A") // warn +val ss2 = Seq(s2.trim) // warn +val ss3: Seq[String] = + val s3 = s2.trim + Seq(s3) \ No newline at end of file diff --git a/tests/explicit-nulls/warn/unnecessary-nn.scala b/tests/explicit-nulls/warn/unnecessary-nn.scala index 0e93b61fb408..82d87e75c0a5 100644 --- a/tests/explicit-nulls/warn/unnecessary-nn.scala +++ b/tests/explicit-nulls/warn/unnecessary-nn.scala @@ -9,7 +9,7 @@ def f6[T >: String|Null](s: String|Null): T = s.nn // warn def f5a[T <: String](s: T): String = s.nn // warn // flexible types -def f7(s: String|Null) = "".concat(s.nn) // warn +def f7(s: String|Null): String = "".concat(s.nn) // warn def f8(s: String): String = s.trim().nn // OK because the .nn could be useful as a dynamic null check