/** * Copyright (c) 2012 by JP Moresmau * This code is made available under the terms of the Eclipse Public License, * version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html */ package net.sf.eclipsefp.haskell.hlint; import java.util.Locale; /** * fixes HLint warning * @author JP Moresmau * */ public class HLintFixer { /** * simple struct * */ public static class HLintFix { /** * the length of text that has to be replaced */ private int length; /** * the value to use has replacement */ private String value=""; /** * have we fully matched the input */ private boolean fullMatch=false; /** * @return the length */ public int getLength() { return length; } /** * @return the value */ public String getValue() { return value; } /** * @return the fullMatch */ public boolean isFullMatch() { return fullMatch; } } public static boolean canFix(Suggestion s){ if (s.getPre().getType().equals(CodeModificationType.TEXT)){ if (s.getPost().getType().equals(CodeModificationType.TEXT)){ String p=((CodeModificationText)s.getPost()).getText().trim(); // we cannot replace automatically when we're just told to combine with another line if (p.length()>0 && p.toLowerCase(Locale.ENGLISH).startsWith("combine with") && Character.isDigit(p.charAt(p.length()-1))){ return false; } } return true; } return false; } /** * fixes the given string * @param doc the document content * @param offset the offset given by the suggestion location * @param s the suggestion given by hlint * @return the fix structure */ public static HLintFix fix(String doc, int offset,Suggestion s){ HLintFix fix=new HLintFix(); if (s.getPre().getType().equals(CodeModificationType.TEXT)){ String txt=((CodeModificationText)s.getPre()).getText(); int offset2=matchIgnoreSpace(doc, offset, txt, 0); fix.fullMatch=offset2>-1; fix.length=offset2-offset; } else { fix.fullMatch=true; } if (s.getPost().getType().equals(CodeModificationType.TEXT)){ fix.value=((CodeModificationText)s.getPost()).getText().trim(); } if (offset>0){ if (Character.isJavaIdentifierPart(doc.charAt(offset-1))){ fix.value=" "+fix.value; } } return fix; } /** * match two strings ignoring spaces * @param doc the first string to match * @param offset the offset to start searching in the first string * @param txt the second string * @param txtIdx the offset to start searching in the second string * @return the index at the end of the match in the first string */ private static int matchIgnoreSpace(String doc,int offset,String txt, int txtIdx){ int txtIdx2=ignoreSpace(txt, txtIdx); if (txtIdx2<txt.length()){ int offset2=ignoreSpace(doc, offset); if (offset2<doc.length()){ while (doc.substring(offset2).startsWith("--")){ int ix=doc.indexOf("\n",offset2); offset2=ignoreSpace(doc, ix); } char c1=doc.charAt(offset2); char c2=txt.charAt(txtIdx2); if (c1==c2){ return matchIgnoreSpace(doc, offset2+1, txt, txtIdx2+1); } else if (c2=='(' || c2==')'){ // hlint sometimes adds extra brackets in the text it tells you to replace return matchIgnoreSpace(doc, offset2, txt, txtIdx2+1); } else { return -1; } } offset=offset2; } return offset; } /** * skip spaces * @param doc the text to skip spaces in * @param offset the offset to start skipping * @return the offset of the first non space character after offset */ private static int ignoreSpace(String doc,int offset){ if (offset<doc.length()){ char c=doc.charAt(offset); while (offset<doc.length() && Character.isWhitespace(c)){ offset++; c=doc.charAt(offset); } } return offset; } }