<commit_before>// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library analysis.server;

import 'dart:async';

import 'package:analysis_server/src/analysis_logger.dart';
import 'package:analysis_server/src/channel.dart';
import 'package:analysis_server/src/protocol.dart';
import 'package:analyzer/src/generated/engine.dart';

/**
 * Instances of the class [AnalysisServer] implement a server that listens on a
 * [CommunicationChannel] for analysis requests and process them.
 */
class AnalysisServer {
  /**
   * The name of the notification of new errors associated with a source.
   */
  static const String ERROR_NOTIFICATION_NAME = 'context.errors';

  /**
   * The name of the parameter whose value is a list of errors.
   */
  static const String ERRORS_PARAM = 'errors';

  /**
   * The name of the parameter whose value is a source.
   */
  static const String SOURCE_PARAM = 'source';

  /**
   * The channel from which requests are received and to which responses should
   * be sent.
   */
  CommunicationChannel channel;

  /**
   * A flag indicating whether the server is running.
   */
  bool running;

  /**
   * A list of the request handlers used to handle the requests sent to this
   * server.
   */
  List<RequestHandler> handlers;

  /**
   * A table mapping context id's to the analysis contexts associated with them.
   */
  final Map<String, AnalysisContext> contextMap = new Map<String, AnalysisContext>();

  /**
   * A list of the analysis contexts for which analysis work needs to be
   * performed.
   */
  final List<AnalysisContext> contextWorkQueue = new List<AnalysisContext>();

  /**
   * Initialize a newly created server to receive requests from and send
   * responses to the given [channel].
   */
  AnalysisServer(CommunicationChannel channel) {
    AnalysisEngine.instance.logger = new AnalysisLogger();
    running = true;
    this.channel = channel;
    this.channel.listen(handleRequest, onError: error, onDone: done);
  }

  /**
   * Add the given [context] to the list of analysis contexts for which analysis
   * work needs to be performed. Ensure that the work will be performed.
   */
  void addContextToWorkQueue(AnalysisContext context) {
    if (!contextWorkQueue.contains(context)) {
      contextWorkQueue.add(context);
      run();
    }
  }

  /**
   * The socket from which requests are being read has been closed.
   */
  void done() {
    running = false;
  }

  /**
   * There was an error related to the socket from which requests are being
   * read.
   */
  void error() {
    running = false;
  }

  /**
   * Handle a [request] that was read from the communication channel.
   */
  void handleRequest(Request request) {
    int count = handlers.length;
    for (int i = 0; i < count; i++) {
      Response response = handlers[i].handleRequest(request);
      if (response != null) {
        channel.sendResponse(response);
        return;
      }
    }
    channel.sendResponse(new Response.unknownRequest(request));
  }

  /**
   * Perform the next available task. If a request was received that has not yet
   * been performed, perform it next. Otherwise, look for some analysis that
   * needs to be done and do that. Otherwise, do nothing.
   */
  void performTask() {
    //
    // Look for a context that has work to be done and then perform one task.
    //
    if (!contextWorkQueue.isEmpty) {
      AnalysisContext context = contextWorkQueue[0];
      AnalysisResult result = context.performAnalysisTask();
      List<ChangeNotice> notices = result.changeNotices;
      if (notices == null) {
        contextWorkQueue.removeAt(0);
      } else { //if (context.analysisOptions.provideErrors) {
        sendNotices(notices);
      }
    }
    //
    // Schedule this method to be run again if there is any more work to be done.
    //
    if (contextWorkQueue.isEmpty) {
      running = false;
    } else {
      Timer.run(() {
        performTask();
      });
    }
  }

  /**
   * Send the information in the given list of notices back to the client.
   */
  void sendNotices(List<ChangeNotice> notices) {
    for (int i = 0; i < notices.length; i++) {
      ChangeNotice notice = notices[i];
      Notification notification = new Notification(ERROR_NOTIFICATION_NAME);
      notification.setParameter(SOURCE_PARAM, notice.source.encoding);
      notification.setParameter(ERRORS_PARAM, notice.errors);
      sendNotification(notification);
    }
  }

  /**
   * Perform the tasks that are waiting for execution until the server is shut
   * down.
   */
  void run() {
    if (!running) {
      running = true;
      Timer.run(() {
        performTask();
      });
    }
  }

  /**
   * Send the given [notification] to the client.
   */
  void sendNotification(Notification notification) {
    channel.sendNotification(notification);
  }
}
<commit_msg>Use Future for error handling. This appears to be the recommended way of doing things because it is safer.<commit_after>// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library analysis.server;

import 'dart:async';

import 'package:analysis_server/src/analysis_logger.dart';
import 'package:analysis_server/src/channel.dart';
import 'package:analysis_server/src/protocol.dart';
import 'package:analyzer/src/generated/engine.dart';

/**
 * Instances of the class [AnalysisServer] implement a server that listens on a
 * [CommunicationChannel] for analysis requests and process them.
 */
class AnalysisServer {
  /**
   * The name of the notification of new errors associated with a source.
   */
  static const String ERROR_NOTIFICATION_NAME = 'context.errors';

  /**
   * The name of the parameter whose value is a list of errors.
   */
  static const String ERRORS_PARAM = 'errors';

  /**
   * The name of the parameter whose value is a source.
   */
  static const String SOURCE_PARAM = 'source';

  /**
   * The channel from which requests are received and to which responses should
   * be sent.
   */
  CommunicationChannel channel;

  /**
   * A flag indicating whether the server is running.
   */
  bool running;

  /**
   * A list of the request handlers used to handle the requests sent to this
   * server.
   */
  List<RequestHandler> handlers;

  /**
   * A table mapping context id's to the analysis contexts associated with them.
   */
  final Map<String, AnalysisContext> contextMap = new Map<String, AnalysisContext>();

  /**
   * A list of the analysis contexts for which analysis work needs to be
   * performed.
   */
  final List<AnalysisContext> contextWorkQueue = new List<AnalysisContext>();

  /**
   * Initialize a newly created server to receive requests from and send
   * responses to the given [channel].
   */
  AnalysisServer(CommunicationChannel channel) {
    AnalysisEngine.instance.logger = new AnalysisLogger();
    running = true;
    this.channel = channel;
    this.channel.listen(handleRequest, onError: error, onDone: done);
  }

  /**
   * Add the given [context] to the list of analysis contexts for which analysis
   * work needs to be performed. Ensure that the work will be performed.
   */
  void addContextToWorkQueue(AnalysisContext context) {
    if (!contextWorkQueue.contains(context)) {
      contextWorkQueue.add(context);
      run();
    }
  }

  /**
   * The socket from which requests are being read has been closed.
   */
  void done() {
    running = false;
  }

  /**
   * There was an error related to the socket from which requests are being
   * read.
   */
  void error() {
    running = false;
  }

  /**
   * Handle a [request] that was read from the communication channel.
   */
  void handleRequest(Request request) {
    int count = handlers.length;
    for (int i = 0; i < count; i++) {
      Response response = handlers[i].handleRequest(request);
      if (response != null) {
        channel.sendResponse(response);
        return;
      }
    }
    channel.sendResponse(new Response.unknownRequest(request));
  }

  /**
   * Perform the next available task. If a request was received that has not yet
   * been performed, perform it next. Otherwise, look for some analysis that
   * needs to be done and do that. Otherwise, do nothing.
   */
  void performTask() {
    //
    // Look for a context that has work to be done and then perform one task.
    //
    if (!contextWorkQueue.isEmpty) {
      AnalysisContext context = contextWorkQueue[0];
      AnalysisResult result = context.performAnalysisTask();
      List<ChangeNotice> notices = result.changeNotices;
      if (notices == null) {
        contextWorkQueue.removeAt(0);
      } else { //if (context.analysisOptions.provideErrors) {
        sendNotices(notices);
      }
    }
    //
    // Schedule this method to be run again if there is any more work to be done.
    //
    if (contextWorkQueue.isEmpty) {
      running = false;
    } else {
      new Future(performTask).catchError((exception, stackTrace) {
        AnalysisEngine.instance.logger.logError3(exception);
      });
    }
  }

  /**
   * Send the information in the given list of notices back to the client.
   */
  void sendNotices(List<ChangeNotice> notices) {
    for (int i = 0; i < notices.length; i++) {
      ChangeNotice notice = notices[i];
      Notification notification = new Notification(ERROR_NOTIFICATION_NAME);
      notification.setParameter(SOURCE_PARAM, notice.source.encoding);
      notification.setParameter(ERRORS_PARAM, notice.errors);
      sendNotification(notification);
    }
  }

  /**
   * Perform the tasks that are waiting for execution until the server is shut
   * down.
   */
  void run() {
    if (!running) {
      running = true;
      Timer.run(() {
        performTask();
      });
    }
  }

  /**
   * Send the given [notification] to the client.
   */
  void sendNotification(Notification notification) {
    channel.sendNotification(notification);
  }
}

{'fraction_non_alphanumeric': 0.09792547438796578, 'fraction_numerical': 0.0016714187395536328, 'mean_word_length': 2.9003067484662575, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2395269', 'n_tokens_mistral': 2841, 'n_tokens_neox': 2751, 'n_words': 1000}