| Index: dart/sdk/lib/_internal/compiler/implementation/compiler.dart
|
| diff --git a/dart/sdk/lib/_internal/compiler/implementation/compiler.dart b/dart/sdk/lib/_internal/compiler/implementation/compiler.dart
|
| index 7aefe4c95d7e7c2953caddd762a17a3fe1c8ae66..a08b609bb38773ee24f1b027c123dd8621159ac7 100644
|
| --- a/dart/sdk/lib/_internal/compiler/implementation/compiler.dart
|
| +++ b/dart/sdk/lib/_internal/compiler/implementation/compiler.dart
|
| @@ -456,6 +456,12 @@ abstract class Backend {
|
|
|
| // Does this element belong in the output
|
| bool shouldOutput(Element element) => true;
|
| +
|
| + FunctionElement helperForBadMain() => null;
|
| +
|
| + FunctionElement helperForMissingMain() => null;
|
| +
|
| + FunctionElement helperForMainArity() => null;
|
| }
|
|
|
| /// Backend callbacks function specific to the resolution phase.
|
| @@ -1284,53 +1290,75 @@ abstract class Compiler implements DiagnosticListener {
|
| });
|
| }
|
|
|
| - /// Performs the compilation when all libraries have been loaded.
|
| - void compileLoadedLibraries() {
|
| - Element main = null;
|
| - if (mainApp != null) {
|
| - main = mainApp.findExported(MAIN);
|
| - if (main == null) {
|
| - if (!analyzeOnly) {
|
| - // Allow analyze only of libraries with no main.
|
| - reportFatalError(
|
| - mainApp,
|
| - MessageKind.GENERIC,
|
| - {'text': "Could not find '$MAIN'."});
|
| - } else if (!analyzeAll) {
|
| - reportFatalError(mainApp, MessageKind.GENERIC,
|
| - {'text': "Could not find '$MAIN'. "
|
| - "No source will be analyzed. "
|
| - "Use '--analyze-all' to analyze all code in the "
|
| - "library."});
|
| + void computeMain() {
|
| + if (mainApp == null) return;
|
| +
|
| + Element main = mainApp.findExported(MAIN);
|
| + ErroneousElement errorElement = null;
|
| + if (main == null) {
|
| + if (analyzeOnly) {
|
| + if (!analyzeAll) {
|
| + errorElement = new ErroneousElementX(
|
| + MessageKind.CONSIDER_ANALYZE_ALL, {'main': MAIN}, MAIN, mainApp);
|
| }
|
| } else {
|
| - if (main.isErroneous && main.isSynthesized) {
|
| - reportFatalError(main, MessageKind.GENERIC,
|
| - {'text': "Cannot determine which '$MAIN' to use."});
|
| - } else if (!main.isFunction) {
|
| - reportFatalError(main, MessageKind.GENERIC,
|
| - {'text': "'$MAIN' is not a function."});
|
| - }
|
| - mainFunction = main;
|
| - FunctionSignature parameters = mainFunction.computeSignature(this);
|
| - if (parameters.parameterCount > 2) {
|
| - int index = 0;
|
| - parameters.forEachParameter((Element parameter) {
|
| - if (index++ < 2) return;
|
| - reportError(parameter, MessageKind.GENERIC,
|
| - {'text': "'$MAIN' cannot have more than two parameters."});
|
| - });
|
| - }
|
| + // Compilation requires a main method.
|
| + errorElement = new ErroneousElementX(
|
| + MessageKind.MISSING_MAIN, {'main': MAIN}, MAIN, mainApp);
|
| + }
|
| + mainFunction = backend.helperForMissingMain();
|
| + } else if (main.isErroneous && main.isSynthesized) {
|
| + if (main is ErroneousElement) {
|
| + errorElement = main;
|
| + } else {
|
| + internalError(main, 'Problem with $MAIN.');
|
| + }
|
| + mainFunction = backend.helperForBadMain();
|
| + } else if (!main.isFunction) {
|
| + errorElement = new ErroneousElementX(
|
| + MessageKind.MAIN_NOT_A_FUNCTION, {'main': MAIN}, MAIN, main);
|
| + mainFunction = backend.helperForBadMain();
|
| + } else {
|
| + mainFunction = main;
|
| + FunctionSignature parameters = mainFunction.computeSignature(this);
|
| + if (parameters.requiredParameterCount > 2) {
|
| + int index = 0;
|
| + parameters.orderedForEachParameter((Element parameter) {
|
| + if (index++ < 2) return;
|
| + errorElement = new ErroneousElementX(
|
| + MessageKind.MAIN_WITH_EXTRA_PARAMETER, {'main': MAIN}, MAIN,
|
| + parameter);
|
| + mainFunction = backend.helperForMainArity();
|
| + // Don't warn about main not being used:
|
| + enqueuer.resolution.registerStaticUse(main);
|
| + });
|
| + }
|
| + }
|
| + if (mainFunction == null) {
|
| + if (errorElement == null && !analyzeOnly && !analyzeAll) {
|
| + internalError(mainApp, "Problem with '$MAIN'.");
|
| + } else {
|
| + mainFunction = errorElement;
|
| }
|
| + }
|
| + if (errorElement != null && errorElement.isSynthesized) {
|
| + reportWarning(
|
| + errorElement, errorElement.messageKind,
|
| + errorElement.messageArguments);
|
| + }
|
| + }
|
| +
|
| + /// Performs the compilation when all libraries have been loaded.
|
| + void compileLoadedLibraries() {
|
| + computeMain();
|
|
|
| - mirrorUsageAnalyzerTask.analyzeUsage(mainApp);
|
| + mirrorUsageAnalyzerTask.analyzeUsage(mainApp);
|
|
|
| - // In order to see if a library is deferred, we must compute the
|
| - // compile-time constants that are metadata. This means adding
|
| - // something to the resolution queue. So we cannot wait with
|
| - // this until after the resolution queue is processed.
|
| - deferredLoadTask.ensureMetadataResolved(this);
|
| - }
|
| + // In order to see if a library is deferred, we must compute the
|
| + // compile-time constants that are metadata. This means adding
|
| + // something to the resolution queue. So we cannot wait with
|
| + // this until after the resolution queue is processed.
|
| + deferredLoadTask.ensureMetadataResolved(this);
|
|
|
| phase = PHASE_RESOLVING;
|
| if (analyzeAll) {
|
| @@ -1346,7 +1374,7 @@ abstract class Compiler implements DiagnosticListener {
|
| backend.enqueueHelpers(enqueuer.resolution, globalDependencies);
|
| resolveLibraryMetadata();
|
| log('Resolving...');
|
| - processQueue(enqueuer.resolution, main);
|
| + processQueue(enqueuer.resolution, mainFunction);
|
| enqueuer.resolution.logSummary(log);
|
|
|
| if (compilationFailed) return;
|
| @@ -1374,7 +1402,7 @@ abstract class Compiler implements DiagnosticListener {
|
| }
|
| return;
|
| }
|
| - assert(main != null);
|
| + assert(mainFunction != null);
|
| phase = PHASE_DONE_RESOLVING;
|
|
|
| // TODO(ahe): Remove this line. Eventually, enqueuer.resolution
|
| @@ -1384,13 +1412,13 @@ abstract class Compiler implements DiagnosticListener {
|
| // require the information computed in [world.populate].)
|
| backend.onResolutionComplete();
|
|
|
| - deferredLoadTask.onResolutionComplete(main);
|
| + deferredLoadTask.onResolutionComplete(mainFunction);
|
|
|
| log('Building IR...');
|
| irBuilder.buildNodes();
|
|
|
| log('Inferring types...');
|
| - typesTask.onResolutionComplete(main);
|
| + typesTask.onResolutionComplete(mainFunction);
|
|
|
| if(stopAfterTypeInference) return;
|
|
|
| @@ -1399,7 +1427,7 @@ abstract class Compiler implements DiagnosticListener {
|
| // TODO(johnniwinther): Move these to [CodegenEnqueuer].
|
| if (hasIsolateSupport) {
|
| backend.enableIsolateSupport(enqueuer.codegen);
|
| - enqueuer.codegen.registerGetOfStaticFunction(main);
|
| + enqueuer.codegen.registerGetOfStaticFunction(mainFunction);
|
| }
|
| if (enabledNoSuchMethod) {
|
| backend.enableNoSuchMethod(null, enqueuer.codegen);
|
| @@ -1409,7 +1437,7 @@ abstract class Compiler implements DiagnosticListener {
|
| fullyEnqueueLibrary(library, enqueuer.codegen);
|
| });
|
| }
|
| - processQueue(enqueuer.codegen, main);
|
| + processQueue(enqueuer.codegen, mainFunction);
|
| enqueuer.codegen.logSummary(log);
|
|
|
| if (compilationFailed) return;
|
| @@ -1460,7 +1488,7 @@ abstract class Compiler implements DiagnosticListener {
|
|
|
| void processQueue(Enqueuer world, Element main) {
|
| world.nativeEnqueuer.processNativeClasses(libraryLoader.libraries);
|
| - if (main != null) {
|
| + if (main != null && !main.isErroneous) {
|
| FunctionElement mainMethod = main;
|
| if (mainMethod.computeSignature(this).parameterCount != 0) {
|
| // TODO(ngeoffray, floitsch): we should also ensure that the
|
|
|