diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index 53c4be27d8ce..96c9a647b960 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -7,7 +7,8 @@ import Periods._ import Symbols._ import Types._ import Scopes._ -import typer.{ImportInfo, Typer} +import typer.Typer +import typer.ImportInfo._ import Decorators._ import io.{AbstractFile, PlainFile} import Phases.unfusedPhases @@ -74,9 +75,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint .addMode(Mode.ImplicitsEnabled) .setTyperState(ctx.typerState.fresh(ctx.reporter)) ctx.initialize()(using start) // re-initialize the base context with start - def addImport(ctx: Context, rootRef: ImportInfo.RootRef) = - ctx.fresh.setImportInfo(ImportInfo.rootImport(rootRef)) - defn.RootImportFns.foldLeft(start.setRun(this))(addImport) + start.setRun(this) } private var compiling = false @@ -92,8 +91,8 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint private var myFiles: Set[AbstractFile] = _ /** The compilation units currently being compiled, this may return different - * results over time. - */ + * results over time. + */ def units: List[CompilationUnit] = myUnits var suspendedUnits: mutable.ListBuffer[CompilationUnit] = mutable.ListBuffer() @@ -205,7 +204,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint compiling = false } - /** Enter top-level definitions of classes and objects contain in Scala source file `file`. + /** Enter top-level definitions of classes and objects contained in source file `file`. * The newly added symbols replace any previously entered symbols. * If `typeCheck = true`, also run typer on the compilation unit, and set * `rootTreeOrProvider`. @@ -213,7 +212,12 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint def lateCompile(file: AbstractFile, typeCheck: Boolean)(using Context): Unit = if (!files.contains(file) && !lateFiles.contains(file)) { lateFiles += file + val unit = CompilationUnit(ctx.getSource(file.path)) + val unitCtx = runContext.fresh + .setCompilationUnit(unit) + .withRootImports + def process()(using Context) = { unit.untpdTree = if (unit.isJava) new JavaParser(unit.source).parse() @@ -227,7 +231,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint if (typeCheck) if (compiling) finalizeActions += (() => processUnit()) else processUnit() } - process()(using runContext.fresh.setCompilationUnit(unit)) + process()(using unitCtx) } private sealed trait PrintedTree diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 1f7b51bf78e7..8d88ba1138e6 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -1140,28 +1140,61 @@ class Definitions { def isPredefClass(cls: Symbol): Boolean = (cls.owner eq ScalaPackageClass) && predefClassNames.contains(cls.name) - val StaticRootImportFns: List[RootRef] = List[RootRef]( - (() => JavaLangPackageVal.termRef, false), - (() => ScalaPackageVal.termRef, false) + private val JavaImportFns: List[RootRef] = List( + RootRef(() => JavaLangPackageVal.termRef) ) - val PredefImportFns: List[RootRef] = List[RootRef]( - (() => ScalaPredefModule.termRef, true), - (() => DottyPredefModule.termRef, false) + private val ScalaImportFns: List[RootRef] = + JavaImportFns :+ + RootRef(() => ScalaPackageVal.termRef) + + private val PredefImportFns: List[RootRef] = List( + RootRef(() => ScalaPredefModule.termRef, isPredef=true), + RootRef(() => DottyPredefModule.termRef) ) - @tu lazy val RootImportFns: List[RootRef] = - if (ctx.settings.YnoImports.value) Nil - else if (ctx.settings.YnoPredef.value) StaticRootImportFns - else StaticRootImportFns ++ PredefImportFns + @tu private lazy val JavaRootImportFns: List[RootRef] = + if ctx.settings.YnoImports.value then Nil + else JavaImportFns - @tu lazy val ShadowableImportNames: Set[TermName] = Set("Predef", "DottyPredef").map(_.toTermName) - @tu lazy val RootImportTypes: List[TermRef] = RootImportFns.map(_._1()) + @tu private lazy val ScalaRootImportFns: List[RootRef] = + if ctx.settings.YnoImports.value then Nil + else if ctx.settings.YnoPredef.value then ScalaImportFns + else ScalaImportFns ++ PredefImportFns + + @tu private lazy val JavaRootImportTypes: List[TermRef] = JavaRootImportFns.map(_.refFn()) + @tu private lazy val ScalaRootImportTypes: List[TermRef] = ScalaRootImportFns.map(_.refFn()) + @tu private lazy val JavaUnqualifiedOwnerTypes: Set[NamedType] = unqualifiedTypes(JavaRootImportTypes) + @tu private lazy val ScalaUnqualifiedOwnerTypes: Set[NamedType] = unqualifiedTypes(ScalaRootImportTypes) + + /** Are we compiling a java source file? */ + private def isJavaContext(using Context): Boolean = + val unit = ctx.compilationUnit + unit != null && unit.isJava + + private def unqualifiedTypes(refs: List[TermRef]) = + val types = refs.toSet[NamedType] + types ++ types.map(_.symbol.moduleClass.typeRef) + + /** Lazy references to the root imports */ + def rootImportFns(using Context): List[RootRef] = + if isJavaContext then JavaRootImportFns + else ScalaRootImportFns + + /** Root types imported by default */ + def rootImportTypes(using Context): List[TermRef] = + if isJavaContext then JavaRootImportTypes + else ScalaRootImportTypes /** Modules whose members are in the default namespace and their module classes */ - @tu lazy val UnqualifiedOwnerTypes: Set[NamedType] = - RootImportTypes.toSet[NamedType] ++ RootImportTypes.map(_.symbol.moduleClass.typeRef) + def unqualifiedOwnerTypes(using Context): Set[NamedType] = + if isJavaContext then JavaUnqualifiedOwnerTypes + else ScalaUnqualifiedOwnerTypes + + /** Names of the root import symbols that can be hidden by other imports */ + @tu lazy val ShadowableImportNames: Set[TermName] = Set("Predef", "DottyPredef").map(_.toTermName) + /** Class symbols for which no class exist at runtime */ @tu lazy val NotRuntimeClasses: Set[Symbol] = Set(AnyClass, AnyValClass, NullClass, NothingClass) /** Classes that are known not to have an initializer irrespective of diff --git a/compiler/src/dotty/tools/dotc/core/Phases.scala b/compiler/src/dotty/tools/dotc/core/Phases.scala index 994cc3ff05a3..1106f3fcf199 100644 --- a/compiler/src/dotty/tools/dotc/core/Phases.scala +++ b/compiler/src/dotty/tools/dotc/core/Phases.scala @@ -14,6 +14,7 @@ import dotty.tools.dotc.transform.MegaPhase._ import dotty.tools.dotc.transform._ import Periods._ import typer.{FrontEnd, RefChecks} +import typer.ImportInfo.withRootImports import ast.tpd object Phases { @@ -291,7 +292,7 @@ object Phases { /** @pre `isRunnable` returns true */ def runOn(units: List[CompilationUnit])(using Context): List[CompilationUnit] = units.map { unit => - val unitCtx = ctx.fresh.setPhase(this.start).setCompilationUnit(unit) + val unitCtx = ctx.fresh.setPhase(this.start).setCompilationUnit(unit).withRootImports run(using unitCtx) unitCtx.compilationUnit } diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala index 467228ded06b..3c226cd5d792 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -101,7 +101,7 @@ object JavaParsers { def javaLangObject(): Tree = javaLangDot(tpnme.Object) def arrayOf(tpt: Tree): AppliedTypeTree = - AppliedTypeTree(Ident(nme.Array.toTypeName), List(tpt)) + AppliedTypeTree(scalaDot(tpnme.Array), List(tpt)) def makeTemplate(parents: List[Tree], stats: List[Tree], tparams: List[TypeDef], needsDummyConstr: Boolean): Template = { def pullOutFirstConstr(stats: List[Tree]): (Tree, List[Tree]) = stats match { diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 668ed1d9c3a6..8b41983bad27 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -321,7 +321,7 @@ class PlainPrinter(_ctx: Context) extends Printer { } protected def isOmittablePrefix(sym: Symbol): Boolean = - defn.UnqualifiedOwnerTypes.exists(_.symbol == sym) || isEmptyPrefix(sym) + defn.unqualifiedOwnerTypes.exists(_.symbol == sym) || isEmptyPrefix(sym) protected def isEmptyPrefix(sym: Symbol): Boolean = sym.isEffectiveRoot || sym.isAnonymousClass || sym.name.isReplWrapperName diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 0ac620b804c4..584909eb8776 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -664,7 +664,7 @@ class SpaceEngine(using Context) extends SpaceLogic { def isOmittable(sym: Symbol) = sym.isEffectiveRoot || sym.isAnonymousClass || sym.name.isReplWrapperName || - ctx.definitions.UnqualifiedOwnerTypes.exists(_.symbol == sym) || + ctx.definitions.unqualifiedOwnerTypes.exists(_.symbol == sym) || sym.showFullName.startsWith("scala.") || sym == enclosingCls || sym == enclosingCls.sourceModule diff --git a/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala b/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala index 774cac41cecd..987af1c89774 100644 --- a/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala +++ b/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala @@ -7,7 +7,8 @@ import Phases._ import Contexts._ import Symbols._ import Decorators._ -import dotty.tools.dotc.parsing.JavaParsers.JavaParser +import ImportInfo.withRootImports +import parsing.JavaParsers.JavaParser import parsing.Parsers.Parser import config.Config import config.Printers.{typr, default} @@ -98,7 +99,7 @@ class FrontEnd extends Phase { val unitContexts = for unit <- units yield report.inform(s"compiling ${unit.source}") - ctx.fresh.setCompilationUnit(unit) + ctx.fresh.setCompilationUnit(unit).withRootImports unitContexts.foreach(parse(using _)) record("parsedTrees", ast.Trees.ntrees) remaining = unitContexts @@ -123,7 +124,7 @@ class FrontEnd extends Phase { | ${suspendedUnits.toList}%, % |""" val enableXprintSuspensionHint = - if (ctx.settings.XprintSuspension.value) "" + if ctx.settings.XprintSuspension.value then "" else "\n\nCompiling with -Xprint-suspension gives more information." report.error(em"""Cyclic macro dependencies $where |Compilation stopped since no further progress can be made. diff --git a/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala b/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala index 6ac9fa4535a2..6704ffd1157f 100644 --- a/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala +++ b/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala @@ -17,24 +17,32 @@ import Decorators._ object ImportInfo { - type RootRef = ( - () => TermRef, // a lazy reference to the root module to be imported - Boolean // true if this will refer to scala.Predef - ) - - /** The import info for a root import from given symbol `sym` */ - def rootImport(rootRef: RootRef)(using Context): ImportInfo = - val (refFn, isPredef) = rootRef + case class RootRef(refFn: () => TermRef, isPredef: Boolean = false) + + /** The import info for a root import */ + def rootImport(ref: RootRef)(using Context): ImportInfo = var selectors = untpd.ImportSelector(untpd.Ident(nme.WILDCARD)) // import all normal members... :: untpd.ImportSelector(untpd.Ident(nme.EMPTY)) // ... and also all given members :: Nil - if isPredef then // do not import any2stringadd + if ref.isPredef then // do not import any2stringadd selectors = untpd.ImportSelector(untpd.Ident(nme.any2stringadd), untpd.Ident(nme.WILDCARD)) :: selectors - def expr(using Context) = tpd.Ident(refFn()) - def imp(using Context) = tpd.Import(expr, selectors) - ImportInfo(imp.symbol, selectors, None, isRootImport = true) + + def sym(using Context) = + val expr = tpd.Ident(ref.refFn()) // refFn must be called in the context of ImportInfo.sym + tpd.Import(expr, selectors).symbol + + ImportInfo(sym, selectors, None, isRootImport = true) + + extension (c: Context): + def withRootImports(rootRefs: List[RootRef])(using Context): Context = + rootRefs.foldLeft(c)((ctx, ref) => ctx.fresh.setImportInfo(rootImport(ref))) + + def withRootImports: Context = + given Context = c + c.withRootImports(defn.rootImportFns) + } /** Info relating to an import clause @@ -164,7 +172,7 @@ class ImportInfo(symf: Context ?=> Symbol, case Some(symName) => defn.ShadowableImportNames.contains(symName) case None => false myUnimported = - if maybeShadowsRoot && defn.RootImportTypes.exists(_.symbol == sym) then sym + if maybeShadowsRoot && defn.rootImportTypes.exists(_.symbol == sym) then sym else NoSymbol assert(myUnimported != null) myUnimported @@ -193,4 +201,4 @@ class ImportInfo(symf: Context ?=> Symbol, end featureImported def toText(printer: Printer): Text = printer.toText(this) -} \ No newline at end of file +} diff --git a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala index 16e8b9bc5c04..7fa03a78e25d 100644 --- a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala +++ b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala @@ -226,7 +226,7 @@ trait ImportSuggestions: try val roots = suggestionRoots - .filterNot(root => defn.RootImportTypes.exists(_.symbol == root.symbol)) + .filterNot(root => defn.rootImportTypes.exists(_.symbol == root.symbol)) // don't suggest things that are imported by default def extensionImports = pt match diff --git a/compiler/src/dotty/tools/repl/ReplCompiler.scala b/compiler/src/dotty/tools/repl/ReplCompiler.scala index 7ad0a4cd236a..dc5e9b87b715 100644 --- a/compiler/src/dotty/tools/repl/ReplCompiler.scala +++ b/compiler/src/dotty/tools/repl/ReplCompiler.scala @@ -13,7 +13,7 @@ import dotty.tools.dotc.core.StdNames._ import dotty.tools.dotc.core.Symbols._ import dotty.tools.dotc.reporting.Diagnostic import dotty.tools.dotc.transform.{PostTyper, Staging} -import dotty.tools.dotc.typer.ImportInfo +import dotty.tools.dotc.typer.ImportInfo._ import dotty.tools.dotc.util.Spans._ import dotty.tools.dotc.util.{ParsedComment, SourceFile} import dotty.tools.dotc.{CompilationUnit, Compiler, Run} @@ -48,21 +48,19 @@ class ReplCompiler extends Compiler { def importPreviousRun(id: Int)(using Context) = { // we first import the wrapper object id val path = nme.EMPTY_PACKAGE ++ "." ++ objectNames(id) - def importWrapper(c: Context, importGiven: Boolean) = { - val importInfo = ImportInfo.rootImport(() => - requiredModuleRef(path), importGiven)(using c) - c.fresh.setNewScope.setImportInfo(importInfo) - } - val ctx0 = importWrapper(importWrapper(ctx, false), true) + val ctx0 = ctx.fresh + .setNewScope + .withRootImports(RootRef(() => requiredModuleRef(path)) :: Nil) // then its user defined imports val imports = state.imports.getOrElse(id, Nil) - if (imports.isEmpty) ctx0 + if imports.isEmpty then ctx0 else imports.foldLeft(ctx0.fresh.setNewScope)((ctx, imp) => importContext(imp)(using ctx)) } - (1 to state.objectIndex).foldLeft(super.rootContext)((ctx, id) => + val rootCtx = super.rootContext.withRootImports + (1 to state.objectIndex).foldLeft(rootCtx)((ctx, id) => importPreviousRun(id)(using ctx)) } } diff --git a/compiler/src/dotty/tools/repl/ReplFrontEnd.scala b/compiler/src/dotty/tools/repl/ReplFrontEnd.scala index 8e07ccdfe0c3..59df49e853cb 100644 --- a/compiler/src/dotty/tools/repl/ReplFrontEnd.scala +++ b/compiler/src/dotty/tools/repl/ReplFrontEnd.scala @@ -4,6 +4,7 @@ package repl import dotc.typer.FrontEnd import dotc.CompilationUnit import dotc.core.Contexts._ +import dotc.typer.ImportInfo.withRootImports /** A customized `FrontEnd` for the REPL * @@ -17,10 +18,10 @@ private[repl] class REPLFrontEnd extends FrontEnd { override def runOn(units: List[CompilationUnit])(using Context): List[CompilationUnit] = { assert(units.size == 1) // REPl runs one compilation unit at a time - - val unitContext = ctx.fresh.setCompilationUnit(units.head) + val unit = units.head + val unitContext = ctx.fresh.setCompilationUnit(unit).withRootImports enterSyms(using unitContext) typeCheck(using unitContext) - List(unitContext.compilationUnit) + List(unit) } } diff --git a/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala b/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala index f85b38ccc89c..9de1e33d3d6f 100644 --- a/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala +++ b/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala @@ -27,10 +27,9 @@ import dotty.tools.dotc.transform.CookComments class DocCompiler extends Compiler { override def newRun(using Context): Run = { - if (ctx.settings.fromTasty.value) { + if ctx.settings.fromTasty.value then reset() new TASTYRun(this, ctx.addMode(Mode.ReadPositions).addMode(Mode.ReadComments)) - } else super.newRun } diff --git a/doc-tool/test/dotty/tools/dottydoc/DottyDocTest.scala b/doc-tool/test/dotty/tools/dottydoc/DottyDocTest.scala index e2d0b494100c..46fdaa8f8407 100644 --- a/doc-tool/test/dotty/tools/dottydoc/DottyDocTest.scala +++ b/doc-tool/test/dotty/tools/dottydoc/DottyDocTest.scala @@ -3,20 +3,18 @@ package dottydoc import vulpix.TestConfiguration -import dotc.Compiler +import dotc.{Compiler, Run} import dotc.core.Contexts.{ Context, ContextBase, FreshContext } import dotc.core.Comments.{ ContextDoc, ContextDocstrings } import dotc.util.SourceFile import dotc.core.Phases.Phase -import dotty.tools.io.AbstractFile import dotc.typer.FrontEnd -import dottydoc.core.{ DocASTPhase, ContextDottydoc } -import model.Package -import dotty.tools.dottydoc.util.syntax._ -import dotty.tools.io.AbstractFile -import dotc.reporting.{ StoreReporter, MessageRendering } import dotc.interfaces.Diagnostic.ERROR -import io.Directory +import dotc.reporting.{ StoreReporter, MessageRendering } +import util.syntax._ +import io.{AbstractFile, Directory} +import core.{ DocASTPhase, ContextDottydoc } +import model.Package import org.junit.Assert.fail import java.io.{ BufferedWriter, OutputStreamWriter } @@ -115,6 +113,7 @@ trait DottyDocTest extends MessageRendering { ctx.setSetting(ctx.settings.outputDir, AbstractFile.getDirectory(out)) } val dotc = new Compiler + val run = dotc.newRun(using dotcCtx) run.compileSources(sources) assert(!dotcCtx.reporter.hasErrors) diff --git a/tests/run/java-no-scala-import/Config.java b/tests/run/java-no-scala-import/Config.java new file mode 100644 index 000000000000..5fe636f424ee --- /dev/null +++ b/tests/run/java-no-scala-import/Config.java @@ -0,0 +1,25 @@ +public class Config { + long longVal; + Long longObj; + Integer boxed; + + public long getLongVal() { + return longVal; + } + + public void setLongVal(long longVal) { + this.longVal = longVal; + } + + public Long getLongObj() { + return longObj; + } + + public void setLongObj(Long longObj) { + this.longObj = longObj; + } + + public Long longLength(String str) { + return Long.valueOf(str.length()); + } +} diff --git a/tests/run/java-no-scala-import/Test.scala b/tests/run/java-no-scala-import/Test.scala new file mode 100644 index 000000000000..cdc46d2b3e0e --- /dev/null +++ b/tests/run/java-no-scala-import/Test.scala @@ -0,0 +1,6 @@ +object Test extends App { + val c = new Config() + c.setLongObj(10) + println(c.getLongObj) + val l = c.longLength("test") +}