001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2014 Oliver Burn 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018//////////////////////////////////////////////////////////////////////////////// 019package com.puppycrawl.tools.checkstyle.checks; 020 021import com.puppycrawl.tools.checkstyle.api.Check; 022import com.puppycrawl.tools.checkstyle.api.DetailAST; 023import com.puppycrawl.tools.checkstyle.api.TokenTypes; 024import java.io.File; 025 026/** 027 * Checks that the outer type name and the file name match. 028 * @author Oliver Burn 029 * @author maxvetrenko 030 */ 031public class OuterTypeFilenameCheck extends Check 032{ 033 /** indicates whether the first token has been seen in the file. */ 034 private boolean seenFirstToken; 035 036 /** Current file name*/ 037 private String fileName; 038 039 /** If file has public type*/ 040 private boolean hasPublic; 041 042 /** If first type has has same name as file*/ 043 private boolean validFirst; 044 045 /** Outer type with mismatched file name*/ 046 private DetailAST wrongType; 047 048 @Override 049 public int[] getDefaultTokens() 050 { 051 return new int[] { 052 TokenTypes.CLASS_DEF, TokenTypes.INTERFACE_DEF, 053 TokenTypes.ENUM_DEF, TokenTypes.ANNOTATION_DEF, 054 }; 055 } 056 057 @Override 058 public void beginTree(DetailAST ast) 059 { 060 fileName = getFileName(); 061 seenFirstToken = false; 062 validFirst = false; 063 hasPublic = false; 064 wrongType = null; 065 } 066 067 @Override 068 public void visitToken(DetailAST ast) 069 { 070 final String outerTypeName = ast.findFirstToken(TokenTypes.IDENT).getText(); 071 if (!seenFirstToken) { 072 073 if (fileName.equals(outerTypeName)) { 074 validFirst = true; 075 } 076 else { 077 wrongType = ast; 078 } 079 } 080 else { 081 final DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS); 082 if (modifiers.findFirstToken(TokenTypes.LITERAL_PUBLIC) != null 083 && ast.getParent() == null) 084 { 085 hasPublic = true; 086 } 087 } 088 seenFirstToken = true; 089 } 090 091 @Override 092 public void finishTree(DetailAST rootAST) 093 { 094 if (!(validFirst || hasPublic) && wrongType != null) { 095 log(wrongType.getLineNo(), "type.file.mismatch"); 096 } 097 } 098 099 /** 100 * Get source file name. 101 * @return source file name. 102 */ 103 private String getFileName() 104 { 105 String fname = getFileContents().getFilename(); 106 fname = fname.substring(fname.lastIndexOf(File.separatorChar) + 1); 107 fname = fname.replaceAll("\\.[^\\.]*$", ""); 108 return fname; 109 } 110}