diff --git a/core/modules/field/migration_templates/d7_field_instance.yml b/core/modules/field/migration_templates/d7_field_instance.yml
index e18b273..9fd68dc 100644
--- a/core/modules/field/migration_templates/d7_field_instance.yml
+++ b/core/modules/field/migration_templates/d7_field_instance.yml
@@ -9,6 +9,10 @@ source:
   constants:
     status: true
 process:
+  type:
+    plugin: process_field
+    source: type
+    method: getFieldType
   entity_type: entity_type
   field_name: field_name
   bundle: bundle
diff --git a/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldInstanceTest.php b/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldInstanceTest.php
index ef12ac1..df8ffad 100644
--- a/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldInstanceTest.php
+++ b/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldInstanceTest.php
@@ -85,18 +85,16 @@ protected function createType($id) {
    */
   protected function assertEntity($id, $expected_label, $expected_field_type, $is_required, $expected_translatable) {
     list ($expected_entity_type, $expected_bundle, $expected_name) = explode('.', $id);
-
-    /** @var \Drupal\field\FieldConfigInterface $field */
     $field = FieldConfig::load($id);
-    $this->assertTrue($field instanceof FieldConfigInterface);
-    $this->assertIdentical($expected_label, $field->label());
-    $this->assertIdentical($expected_field_type, $field->getType());
-    $this->assertIdentical($expected_entity_type, $field->getTargetEntityTypeId());
-    $this->assertIdentical($expected_bundle, $field->getTargetBundle());
-    $this->assertIdentical($expected_name, $field->getName());
-    $this->assertEqual($is_required, $field->isRequired());
-    $this->assertIdentical($expected_entity_type . '.' . $expected_name, $field->getFieldStorageDefinition()->id());
-    $this->assertSame($expected_translatable, $field->isTranslatable());
+    $this->assertInstanceOf(FieldConfigInterface::class, $field);
+    $this->assertEquals($expected_label, $field->label());
+    $this->assertEquals($expected_field_type, $field->getType());
+    $this->assertEquals($expected_entity_type, $field->getTargetEntityTypeId());
+    $this->assertEquals($expected_bundle, $field->getTargetBundle());
+    $this->assertEquals($expected_name, $field->getName());
+    $this->assertEquals($is_required, $field->isRequired());
+    $this->assertEquals($expected_entity_type . '.' . $expected_name, $field->getFieldStorageDefinition()->id());
+    $this->assertEquals($expected_translatable, $field->isTranslatable());
   }
 
   /**
@@ -144,7 +142,7 @@ public function testFieldInstances() {
     $this->assertEntity('node.test_content_type.field_integer_list', 'Integer List', 'list_integer', FALSE, FALSE);
     $this->assertEntity('node.test_content_type.field_long_text', 'Long text', 'text_with_summary', FALSE, FALSE);
     $this->assertEntity('node.test_content_type.field_term_reference', 'Term Reference', 'entity_reference', FALSE, FALSE);
-    $this->assertEntity('node.test_content_type.field_text', 'Text', 'text', FALSE, FALSE);
+    $this->assertEntity('node.test_content_type.field_text', 'Text', 'string', FALSE, FALSE);
     $this->assertEntity('comment.comment_node_test_content_type.field_integer', 'Integer', 'integer', FALSE, FALSE);
     $this->assertEntity('user.user.field_file', 'File', 'file', FALSE, FALSE);
 
@@ -154,4 +152,61 @@ public function testFieldInstances() {
     $this->assertLinkFields('node.blog.field_link', DRUPAL_REQUIRED);
   }
 
+  /**
+   * Tests the migration of text field instances with different text processing.
+   */
+  public function testTextFieldInstances() {
+    // All text and text_long field instances using a field base that has only
+    // plain text instances should be migrated to string and string_long fields.
+    // All text_with_summary field instances using a field base that has only
+    // plain text instances should not have been migrated since there's no such
+    // thing as a string_with_summary field.
+    $this->assertEntity('node.page.field_text_plain', 'Text plain', 'string', FALSE, FALSE);
+    $this->assertEntity('node.article.field_text_plain', 'Text plain', 'string', FALSE, TRUE);
+    $this->assertEntity('node.page.field_text_long_plain', 'Text long plain', 'string_long', FALSE, FALSE);
+    $this->assertEntity('node.article.field_text_long_plain', 'Text long plain', 'string_long', FALSE, TRUE);
+    $this->assertNull(FieldConfig::load('node.page.field_text_sum_plain'));
+    $this->assertNull(FieldConfig::load('node.article.field_text_sum_plain'));
+
+    // All text, text_long and text_with_summary field instances using a field
+    // base that has only filtered text instances should be migrated to text,
+    // text_long and text_with_summary fields.
+    $this->assertEntity('node.page.field_text_filtered', 'Text filtered', 'text', FALSE, FALSE);
+    $this->assertEntity('node.article.field_text_filtered', 'Text filtered', 'text', FALSE, TRUE);
+    $this->assertEntity('node.page.field_text_long_filtered', 'Text long filtered', 'text_long', FALSE, FALSE);
+    $this->assertEntity('node.article.field_text_long_filtered', 'Text long filtered', 'text_long', FALSE, TRUE);
+    $this->assertEntity('node.page.field_text_sum_filtered', 'Text summary filtered', 'text_with_summary', FALSE, FALSE);
+    $this->assertEntity('node.article.field_text_sum_filtered', 'Text summary filtered', 'text_with_summary', FALSE, TRUE);
+
+    // All text, text_long and text_with_summary field instances using a field
+    // base that has both plain text and filtered text instances should not have
+    // been migrated.
+    $this->assertNull(FieldConfig::load('node.page.field_text_plain_filtered'));
+    $this->assertNull(FieldConfig::load('node.article.field_text_plain_filtered'));
+    $this->assertNull(FieldConfig::load('node.page.field_text_long_plain_filtered'));
+    $this->assertNull(FieldConfig::load('node.article.field_text_long_plain_filtered'));
+    $this->assertNull(FieldConfig::load('node.page.field_text_sum_plain_filtered'));
+    $this->assertNull(FieldConfig::load('node.article.field_text_sum_plain_filtered'));
+
+    // For each text field instances that were skipped, there should be a log
+    // message with the required steps to fix this.
+    $migration = $this->getMigration('d7_field_instance');
+    $messages = $migration->getIdMap()->getMessageIterator()->fetchAll();
+    $errors = array_map(function($message) {return $message->message;}, $messages);
+    $this->assertCount(8, $errors);
+    sort($errors);
+    $message = 'Can\'t migrate source field field_text_long_plain_filtered configured with both plain text and filtered text processing.';
+    $this->assertEquals($errors[0], $message);
+    $this->assertEquals($errors[1], $message);
+    $message = 'Can\'t migrate source field field_text_plain_filtered configured with both plain text and filtered text processing.';
+    $this->assertEquals($errors[2], $message);
+    $this->assertEquals($errors[3], $message);
+    $message = 'Can\'t migrate source field field_text_sum_plain configured with both plain text processing and text_with_summary.';
+    $this->assertEquals($errors[4], $message);
+    $this->assertEquals($errors[5], $message);
+    $message = 'Can\'t migrate source field field_text_sum_plain_filtered configured with both plain text processing and text_with_summary.';
+    $this->assertEquals($errors[6], $message);
+    $this->assertEquals($errors[7], $message);
+  }
+
 }
diff --git a/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldTest.php b/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldTest.php
index c0af338..828755a 100644
--- a/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldTest.php
+++ b/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldTest.php
@@ -54,14 +54,12 @@ protected function setUp() {
    */
   protected function assertEntity($id, $expected_type, $expected_translatable, $expected_cardinality) {
     list ($expected_entity_type, $expected_name) = explode('.', $id);
-
-    /** @var \Drupal\field\FieldStorageConfigInterface $field */
     $field = FieldStorageConfig::load($id);
-    $this->assertTrue($field instanceof FieldStorageConfigInterface);
-    $this->assertIdentical($expected_name, $field->getName());
-    $this->assertIdentical($expected_type, $field->getType());
-    $this->assertEqual($expected_translatable, $field->isTranslatable());
-    $this->assertIdentical($expected_entity_type, $field->getTargetEntityTypeId());
+    $this->assertInstanceOf(FieldStorageConfigInterface::class, $field);
+    $this->assertEquals($expected_name, $field->getName());
+    $this->assertEquals($expected_type, $field->getType());
+    $this->assertEquals($expected_translatable, $field->isTranslatable());
+    $this->assertEquals($expected_entity_type, $field->getTargetEntityTypeId());
 
     if ($expected_cardinality === 1) {
       $this->assertFalse($field->isMultiple());
@@ -69,7 +67,7 @@ protected function assertEntity($id, $expected_type, $expected_translatable, $ex
     else {
       $this->assertTrue($field->isMultiple());
     }
-    $this->assertIdentical($expected_cardinality, $field->getCardinality());
+    $this->assertEquals($expected_cardinality, $field->getCardinality());
   }
 
   /**
@@ -91,7 +89,7 @@ public function testFields() {
     $this->assertEntity('node.field_tags', 'entity_reference', TRUE, -1);
     $this->assertEntity('node.field_term_reference', 'entity_reference', TRUE, 1);
     $this->assertEntity('node.taxonomy_forums', 'entity_reference', TRUE, 1);
-    $this->assertEntity('node.field_text', 'text', TRUE, 1);
+    $this->assertEntity('node.field_text', 'string', TRUE, 1);
     $this->assertEntity('node.field_text_list', 'list_string', TRUE, 3);
     $this->assertEntity('node.field_boolean', 'boolean', TRUE, 1);
     $this->assertEntity('node.field_email', 'email', TRUE, -1);
@@ -105,24 +103,57 @@ public function testFields() {
     // Assert that the taxonomy term reference fields are referencing the
     // correct entity type.
     $field = FieldStorageConfig::load('node.field_term_reference');
-    $this->assertIdentical('taxonomy_term', $field->getSetting('target_type'));
+    $this->assertEquals('taxonomy_term', $field->getSetting('target_type'));
     $field = FieldStorageConfig::load('node.taxonomy_forums');
-    $this->assertIdentical('taxonomy_term', $field->getSetting('target_type'));
+    $this->assertEquals('taxonomy_term', $field->getSetting('target_type'));
 
     // Assert that the entityreference fields are referencing the correct
     // entity type.
     $field = FieldStorageConfig::load('node.field_node_entityreference');
-    $this->assertIdentical('node', $field->getSetting('target_type'));
+    $this->assertEquals('node', $field->getSetting('target_type'));
     $field = FieldStorageConfig::load('node.field_user_entityreference');
-    $this->assertIdentical('user', $field->getSetting('target_type'));
+    $this->assertEquals('user', $field->getSetting('target_type'));
     $field = FieldStorageConfig::load('node.field_term_entityreference');
-    $this->assertIdentical('taxonomy_term', $field->getSetting('target_type'));
+    $this->assertEquals('taxonomy_term', $field->getSetting('target_type'));
+  }
 
-    // Validate that the source count and processed count match up.
-    /** @var \Drupal\migrate\Plugin\MigrationInterface $migration */
+  /**
+   * Tests the migration of text fields with different text processing.
+   */
+  public function testTextFields() {
+    // All text and text_long field bases that have only plain text instances
+    // should be migrated to string and string_long fields.
+    // All text_with_summary field bases that have only plain text instances
+    // should not have been migrated since there's no such thing as a
+    // string_with_summary field.
+    $this->assertEntity('node.field_text_plain', 'string', TRUE, 1);
+    $this->assertEntity('node.field_text_long_plain', 'string_long', TRUE, 1);
+    $this->assertNull(FieldStorageConfig::load('node.field_text_sum_plain'));
+
+    // All text, text_long and text_with_summary field bases that have only
+    // filtered text instances should be migrated to text, text_long and
+    // text_with_summary fields.
+    $this->assertEntity('node.field_text_filtered', 'text', TRUE, 1);
+    $this->assertEntity('node.field_text_long_filtered', 'text_long', TRUE, 1);
+    $this->assertEntity('node.field_text_sum_filtered', 'text_with_summary', TRUE, 1);
+
+    // All text, text_long and text_with_summary field bases that have both
+    // plain text and filtered text instances should not have been migrated.
+    $this->assertNull(FieldStorageConfig::load('node.field_text_plain_filtered'));
+    $this->assertNull(FieldStorageConfig::load('node.field_text_long_plain_filtered'));
+    $this->assertNull(FieldStorageConfig::load('node.field_text_sum_plain_filtered'));
+
+    // For each text field bases that were skipped, there should be a log
+    // message with the required steps to fix this.
     $migration = $this->getMigration('d7_field');
-    $this->assertSame($migration->getSourcePlugin()
-      ->count(), $migration->getIdMap()->processedCount());
+    $messages = $migration->getIdMap()->getMessageIterator()->fetchAll();
+    $errors = array_map(function($message) {return $message->message;}, $messages);
+    sort($errors);
+    $this->assertCount(4, $errors);
+    $this->assertEquals($errors[0], 'Can\'t migrate source field field_text_long_plain_filtered configured with both plain text and filtered text processing.');
+    $this->assertEquals($errors[1], 'Can\'t migrate source field field_text_plain_filtered configured with both plain text and filtered text processing.');
+    $this->assertEquals($errors[2], 'Can\'t migrate source field field_text_sum_plain configured with both plain text processing and text_with_summary.');
+    $this->assertEquals($errors[3], 'Can\'t migrate source field field_text_sum_plain_filtered configured with both plain text processing and text_with_summary.');
   }
 
 }
diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php
index 248213a..71bc7a5 100644
--- a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php
+++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php
@@ -50,8 +50,8 @@ protected function getEntityCounts() {
       'configurable_language' => 4,
       'contact_form' => 3,
       'editor' => 2,
-      'field_config' => 53,
-      'field_storage_config' => 40,
+      'field_config' => 63,
+      'field_storage_config' => 45,
       'file' => 3,
       'filter_format' => 7,
       'image_style' => 6,
diff --git a/core/modules/text/src/Plugin/migrate/field/d7/TextField.php b/core/modules/text/src/Plugin/migrate/field/d7/TextField.php
index 586f102..53e0938 100644
--- a/core/modules/text/src/Plugin/migrate/field/d7/TextField.php
+++ b/core/modules/text/src/Plugin/migrate/field/d7/TextField.php
@@ -2,7 +2,9 @@
 
 namespace Drupal\text\Plugin\migrate\field\d7;
 
-use Drupal\text\Plugin\migrate\field\d6\TextField as D6TextField;
+use Drupal\migrate\Row;
+use Drupal\migrate\MigrateSkipRowException;
+use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
 
 /**
  * @MigrateField(
@@ -15,4 +17,51 @@
  *   core = {7}
  * )
  */
-class TextField extends D6TextField {}
+class TextField extends FieldPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldType(Row $row) {
+    $type = $row->getSourceProperty('type');
+    $plain_text = FALSE;
+    $filtered_text = FALSE;
+
+    foreach ($row->getSourceProperty('instances') as $instance) {
+      // Check if this field has plain text instances, filtered text instances,
+      // or both.
+      $data = unserialize($instance['data']);
+      switch ($data['settings']['text_processing']) {
+        case '0':
+          $plain_text = TRUE;
+          break;
+        case '1':
+          $filtered_text = TRUE;
+          break;
+      }
+    }
+
+    if (in_array($type, ['text', 'text_long'])) {
+      // If a text or text_long field has only plain text instances, migrate it
+      // to a string or string_long field.
+      if ($plain_text && !$filtered_text) {
+        $type = str_replace(['text', 'text_long'], ['string', 'string_long'], $type);
+      }
+      // If a text or text_long field has both plain text and filtered text
+      // instances, skip the row.
+      elseif ($plain_text && $filtered_text) {
+        $fieldName = $row->getSourceProperty('field_name');
+        throw new MigrateSkipRowException("Can't migrate source field $fieldName configured with both plain text and filtered text processing.");
+      }
+    }
+    elseif ($type == 'text_with_summary' && $plain_text) {
+      // If a text_with_summary field has plain text instances, skip the row
+      // since there's no such thing as a string_with_summary field.
+      $fieldName = $row->getSourceProperty('field_name');
+      throw new MigrateSkipRowException("Can't migrate source field $fieldName configured with both plain text processing and text_with_summary.");
+    }
+
+    return $type;
+  }
+
+}
