| // Copyright (c) 2015, 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. | 
 |  | 
 | import 'package:analyzer/dart/ast/ast.dart'; | 
 | import 'package:analyzer/dart/ast/visitor.dart'; | 
 |  | 
 | import '../analyzer.dart'; | 
 |  | 
 | const _desc = r'Prefer using `///` for doc comments.'; | 
 |  | 
 | const _details = r''' | 
 | From [Effective Dart](https://dart.dev/effective-dart/documentation#do-use--doc-comments-to-document-members-and-types): | 
 |  | 
 | **DO** use `///` for documentation comments. | 
 |  | 
 | Although Dart supports two syntaxes of doc comments (`///` and `/**`), we | 
 | prefer using `///` for doc comments. | 
 |  | 
 | **GOOD:** | 
 | ```dart | 
 | /// Parses a set of option strings. For each option: | 
 | /// | 
 | /// * If it is `null`, then it is ignored. | 
 | /// * If it is a string, then [validate] is called on it. | 
 | /// * If it is any other type, it is *not* validated. | 
 | void parse(List options) { | 
 |   // ... | 
 | } | 
 | ``` | 
 |  | 
 | Within a doc comment, you can use markdown for formatting. | 
 |  | 
 | '''; | 
 |  | 
 | bool isJavaStyle(Comment comment) { | 
 |   var tokens = comment.tokens; | 
 |   if (tokens.isEmpty) { | 
 |     return false; | 
 |   } | 
 |   //Should be only one | 
 |   return comment.tokens.first.lexeme.startsWith('/**'); | 
 | } | 
 |  | 
 | class SlashForDocComments extends LintRule { | 
 |   static const LintCode code = LintCode('slash_for_doc_comments', | 
 |       "Use the end-of-line form ('///') for doc comments.", | 
 |       correctionMessage: "Try rewriting the comment to use '///'.", | 
 |       hasPublishedDocs: true); | 
 |  | 
 |   SlashForDocComments() | 
 |       : super( | 
 |             name: 'slash_for_doc_comments', | 
 |             description: _desc, | 
 |             details: _details, | 
 |             categories: {Category.effectiveDart, Category.style}); | 
 |  | 
 |   @override | 
 |   bool get canUseParsedResult => true; | 
 |  | 
 |   @override | 
 |   LintCode get lintCode => code; | 
 |  | 
 |   @override | 
 |   void registerNodeProcessors( | 
 |       NodeLintRegistry registry, LinterContext context) { | 
 |     var visitor = _Visitor(this); | 
 |     registry.addClassDeclaration(this, visitor); | 
 |     registry.addClassTypeAlias(this, visitor); | 
 |     registry.addCompilationUnit(this, visitor); | 
 |     registry.addConstructorDeclaration(this, visitor); | 
 |     registry.addEnumConstantDeclaration(this, visitor); | 
 |     registry.addEnumDeclaration(this, visitor); | 
 |     registry.addExtensionDeclaration(this, visitor); | 
 |     registry.addFieldDeclaration(this, visitor); | 
 |     registry.addFunctionDeclaration(this, visitor); | 
 |     registry.addFunctionDeclarationStatement(this, visitor); | 
 |     registry.addFunctionTypeAlias(this, visitor); | 
 |     registry.addGenericTypeAlias(this, visitor); | 
 |     registry.addMethodDeclaration(this, visitor); | 
 |     registry.addMixinDeclaration(this, visitor); | 
 |     registry.addTopLevelVariableDeclaration(this, visitor); | 
 |   } | 
 | } | 
 |  | 
 | class _Visitor extends SimpleAstVisitor<void> { | 
 |   final LintRule rule; | 
 |  | 
 |   _Visitor(this.rule); | 
 |  | 
 |   void checkComment(Comment? comment) { | 
 |     if (comment != null && isJavaStyle(comment)) { | 
 |       rule.reportLint(comment); | 
 |     } | 
 |   } | 
 |  | 
 |   @override | 
 |   void visitClassDeclaration(ClassDeclaration node) { | 
 |     checkComment(node.documentationComment); | 
 |   } | 
 |  | 
 |   @override | 
 |   void visitClassTypeAlias(ClassTypeAlias node) { | 
 |     checkComment(node.documentationComment); | 
 |   } | 
 |  | 
 |   @override | 
 |   void visitCompilationUnit(CompilationUnit node) { | 
 |     var directives = node.directives; | 
 |     if (directives.isNotEmpty) { | 
 |       checkComment(directives.first.documentationComment); | 
 |     } | 
 |   } | 
 |  | 
 |   @override | 
 |   void visitConstructorDeclaration(ConstructorDeclaration node) { | 
 |     checkComment(node.documentationComment); | 
 |   } | 
 |  | 
 |   @override | 
 |   void visitEnumConstantDeclaration(EnumConstantDeclaration node) { | 
 |     checkComment(node.documentationComment); | 
 |   } | 
 |  | 
 |   @override | 
 |   void visitEnumDeclaration(EnumDeclaration node) { | 
 |     checkComment(node.documentationComment); | 
 |   } | 
 |  | 
 |   @override | 
 |   void visitExtensionDeclaration(ExtensionDeclaration node) { | 
 |     checkComment(node.documentationComment); | 
 |   } | 
 |  | 
 |   @override | 
 |   void visitFieldDeclaration(FieldDeclaration node) { | 
 |     checkComment(node.documentationComment); | 
 |   } | 
 |  | 
 |   @override | 
 |   void visitFunctionDeclaration(FunctionDeclaration node) { | 
 |     checkComment(node.documentationComment); | 
 |   } | 
 |  | 
 |   @override | 
 |   void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) { | 
 |     var comment = node.beginToken.precedingComments; | 
 |     if (comment != null && comment.lexeme.startsWith('/**')) { | 
 |       rule.reportLintForToken(comment); | 
 |     } | 
 |   } | 
 |  | 
 |   @override | 
 |   void visitFunctionTypeAlias(FunctionTypeAlias node) { | 
 |     checkComment(node.documentationComment); | 
 |   } | 
 |  | 
 |   @override | 
 |   void visitGenericTypeAlias(GenericTypeAlias node) { | 
 |     checkComment(node.documentationComment); | 
 |   } | 
 |  | 
 |   @override | 
 |   void visitMethodDeclaration(MethodDeclaration node) { | 
 |     checkComment(node.documentationComment); | 
 |   } | 
 |  | 
 |   @override | 
 |   void visitMixinDeclaration(MixinDeclaration node) { | 
 |     checkComment(node.documentationComment); | 
 |   } | 
 |  | 
 |   @override | 
 |   void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { | 
 |     checkComment(node.documentationComment); | 
 |   } | 
 | } |